X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/1344ae311f84e842a8832a49f8784d7471213d21..f35a939fd354a3bf8784e0d791928a27ebbc1273:/usr/src/sys/ufs/lfs/lfs_alloc.c diff --git a/usr/src/sys/ufs/lfs/lfs_alloc.c b/usr/src/sys/ufs/lfs/lfs_alloc.c index 73aaddcc9d..817637f17d 100644 --- a/usr/src/sys/ufs/lfs/lfs_alloc.c +++ b/usr/src/sys/ufs/lfs/lfs_alloc.c @@ -4,7 +4,7 @@ * * %sccs.include.redist.c% * - * @(#)lfs_alloc.c 7.37 (Berkeley) %G% + * @(#)lfs_alloc.c 7.50 (Berkeley) %G% */ #include @@ -13,6 +13,9 @@ #include #include #include +#include + +#include #include #include @@ -26,58 +29,87 @@ extern u_long nextgennumber; /* Allocate a new inode. */ /* ARGSUSED */ int -lfs_valloc(pvp, notused, cred, vpp) - VNODE *pvp, **vpp; - int notused; - UCRED *cred; +lfs_valloc(ap) + struct vop_valloc_args /* { + struct vnode *a_pvp; + int a_mode; + struct ucred *a_cred; + struct vnode **a_vpp; + } */ *ap; { struct lfs *fs; - BUF *bp; - IFILE *ifp; - INODE *ip; - VNODE *vp; + struct buf *bp; + struct ifile *ifp; + struct inode *ip; + struct vnode *vp; + daddr_t blkno; ino_t new_ino; + u_long i, max; int error; #ifdef VERBOSE printf("lfs_valloc\n"); #endif /* Get the head of the freelist. */ - fs = VTOI(pvp)->i_lfs; + fs = VTOI(ap->a_pvp)->i_lfs; new_ino = fs->lfs_free; - if (new_ino == LFS_UNUSED_INUM) { - /* - * XXX - * Currently, no more inodes are allocated if the ifile fills - * up. The ifile should be extended instead. - */ - uprintf("\n%s: no inodes left\n", fs->lfs_fsmnt); - log(LOG_ERR, "uid %d on %s: out of inodes\n", - cred->cr_uid, fs->lfs_fsmnt); - return (ENOSPC); - } #ifdef ALLOCPRINT printf("lfs_ialloc: allocate inode %d\n", new_ino); #endif /* - * Remove the inode from the free list and write the free list - * back. + * Remove the inode from the free list and write the new start + * of the free list into the superblock. */ LFS_IENTRY(ifp, fs, new_ino, bp); if (ifp->if_daddr != LFS_UNUSED_DADDR) panic("lfs_ialloc: inuse inode on the free list"); fs->lfs_free = ifp->if_nextfree; - ifp->if_st_atime = time.tv_sec; - LFS_IWRITE(fs, bp); + brelse(bp); + + /* Extend IFILE so that the next lfs_valloc will succeed. */ + if (fs->lfs_free == LFS_UNUSED_INUM) { + vp = fs->lfs_ivnode; + ip = VTOI(vp); + blkno = lblkno(fs, ip->i_size); + bp = getblk(vp, blkno, fs->lfs_bsize); + if (!bp) { + uprintf("\n%s: no inodes left\n", fs->lfs_fsmnt); + log(LOG_ERR, "uid %d on %s: out of inodes\n", + ap->a_cred->cr_uid, fs->lfs_fsmnt); + return (ENOSPC); + } + i = (blkno - fs->lfs_segtabsz - fs->lfs_cleansz) * + fs->lfs_ifpb; + fs->lfs_free = i; + max = i + fs->lfs_ifpb; + for (ifp = (struct ifile *)bp->b_un.b_words; i < max; ++ifp) { + ifp->if_version = 1; + ifp->if_daddr = LFS_UNUSED_DADDR; + ifp->if_nextfree = ++i; + } + ifp--; + ifp->if_nextfree = LFS_UNUSED_INUM; + + ip->i_blocks += btodb(fs->lfs_bsize); + fs->lfs_bfree -= btodb(fs->lfs_bsize); + ip->i_size += fs->lfs_bsize; + vnode_pager_setsize(vp, (u_long)ip->i_size); + vnode_pager_uncache(vp); + LFS_UBWRITE(bp); + } /* Create a vnode to associate with the inode. */ - if (error = lfs_vcreate(pvp->v_mount, new_ino, &vp)) + if (error = lfs_vcreate(ap->a_pvp->v_mount, new_ino, &vp)) return (error); - *vpp = vp; + *ap->a_vpp = vp; + vp->v_flag |= VDIROP; ip = VTOI(vp); VREF(ip->i_devvp); + /* Zero out the direct and indirect block addresses. */ + bzero(ip->i_db, (NDADDR + NIADDR) * sizeof(daddr_t)); + /* Set a new generation number for this inode. */ if (++nextgennumber < (u_long)time.tv_sec) nextgennumber = time.tv_sec; @@ -95,58 +127,67 @@ lfs_valloc(pvp, notused, cred, vpp) /* Create a new vnode/inode pair and initialize what fields we can. */ int lfs_vcreate(mp, ino, vpp) - MOUNT *mp; + struct mount *mp; ino_t ino; - VNODE **vpp; + struct vnode **vpp; { - extern struct vnodeops lfs_vnodeops; - INODE *ip; - UFSMOUNT *ump; + extern int (**lfs_vnodeop_p)(); + struct inode *ip; + struct ufsmount *ump; int error, i; #ifdef VERBOSE printf("lfs_vcreate: ino %d\n", ino); #endif /* Create the vnode. */ - if (error = getnewvnode(VT_LFS, mp, &lfs_vnodeops, vpp)) + if (error = getnewvnode(VT_LFS, mp, lfs_vnodeop_p, vpp)) { + *vpp = NULL; return (error); + } /* Get a pointer to the private mount structure. */ ump = VFSTOUFS(mp); /* Initialize the inode. */ - ip = VTOI(*vpp); + MALLOC(ip, struct inode *, sizeof(struct inode), M_LFSNODE, M_WAITOK); + (*vpp)->v_data = ip; ip->i_vnode = *vpp; + ip->i_devvp = ump->um_devvp; ip->i_flag = 0; - ip->i_mode = 0; - ip->i_diroff = 0; - ip->i_lockf = 0; ip->i_dev = ump->um_dev; ip->i_number = ip->i_din.di_inum = ino; ip->i_lfs = ump->um_lfs; - ip->i_devvp = ump->um_devvp; #ifdef QUOTA for (i = 0; i < MAXQUOTAS; i++) ip->i_dquot[i] = NODQUOT; #endif + ip->i_lockf = 0; + ip->i_diroff = 0; + ip->i_mode = 0; + ip->i_size = 0; + ip->i_blocks = 0; return (0); } /* Free an inode. */ /* ARGUSED */ -void -lfs_vfree(vp, notused1, notused2) - VNODE *vp; - ino_t notused1; - int notused2; +int +lfs_vfree(ap) + struct vop_vfree_args /* { + struct vnode *a_pvp; + ino_t a_ino; + int a_mode; + } */ *ap; { - BUF *bp; - IFILE *ifp; - INODE *ip; + SEGUSE *sup; + struct buf *bp; + struct ifile *ifp; + struct inode *ip; struct lfs *fs; + daddr_t old_iaddr; ino_t ino; - ip = VTOI(vp); + ip = VTOI(ap->a_pvp); #ifdef VERBOSE printf("lfs_vfree: free %d\n", ip->i_number); #endif @@ -159,13 +200,26 @@ lfs_vfree(vp, notused1, notused2) * and link it into the free chain. */ LFS_IENTRY(ifp, fs, ino, bp); + old_iaddr = ifp->if_daddr; ifp->if_daddr = LFS_UNUSED_DADDR; ++ifp->if_version; ifp->if_nextfree = fs->lfs_free; fs->lfs_free = ino; - LFS_IWRITE(fs, bp); + LFS_UBWRITE(bp); + + if (old_iaddr != LFS_UNUSED_DADDR) { + LFS_SEGENTRY(sup, fs, datosn(fs, old_iaddr), bp); +#ifdef DIAGNOSTIC + if (sup->su_nbytes < sizeof(struct dinode)) + panic("lfs_vfree: negative byte count (segment %d)\n", + datosn(fs, old_iaddr)); +#endif + sup->su_nbytes -= sizeof(struct dinode); + LFS_UBWRITE(bp); + } /* Set superblock modified bit and decrement file count. */ fs->lfs_fmod = 1; --fs->lfs_nfiles; + return (0); }