X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/a97f919882371a325f80c115ea1dc86f0aa9a70c..82161bc863f8bfc002a6ffd03a59c3548161874f:/usr/src/sys/ufs/lfs/lfs_inode.c diff --git a/usr/src/sys/ufs/lfs/lfs_inode.c b/usr/src/sys/ufs/lfs/lfs_inode.c index 341d30bbb1..bf589b073f 100644 --- a/usr/src/sys/ufs/lfs/lfs_inode.c +++ b/usr/src/sys/ufs/lfs/lfs_inode.c @@ -14,23 +14,22 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * @(#)lfs_inode.c 7.19 (Berkeley) %G% + * @(#)lfs_inode.c 7.32 (Berkeley) %G% */ #include "param.h" #include "systm.h" #include "mount.h" #include "user.h" +#include "proc.h" #include "file.h" #include "buf.h" #include "cmap.h" #include "vnode.h" +#include "../ufs/quota.h" #include "../ufs/inode.h" #include "../ufs/fs.h" #include "../ufs/ufsmount.h" -#ifdef QUOTA -#include "../ufs/quota.h" -#endif #include "kernel.h" #include "malloc.h" @@ -46,6 +45,8 @@ union ihead { struct inode *ih_chain[2]; } ihead[INOHSZ]; +int prtactive; /* 1 => print out reclaim of active vnodes */ + /* * Initialize hash links for inodes. */ @@ -62,6 +63,9 @@ ufs_init() ih->ih_head[0] = ih; ih->ih_head[1] = ih; } +#ifdef QUOTA + dqinit(); +#endif /* QUOTA */ } /* @@ -88,8 +92,8 @@ iget(xp, ino, ipp) struct vnode *nvp; struct buf *bp; struct dinode *dp; - union ihead *ih; - int error; + union ihead *ih; + int i, error; ih = &ihead[INOHASH(dev, ino)]; loop: @@ -117,10 +121,11 @@ loop: ip->i_vnode = nvp; ip->i_flag = 0; ip->i_devvp = 0; - ip->i_lastr = 0; ip->i_mode = 0; + ip->i_diroff = 0; #ifdef QUOTA - ip->i_dquot = NODQUOT; + for (i = 0; i < MAXQUOTAS; i++) + ip->i_dquot[i] = NODQUOT; #endif /* * Put it onto its hash chain and lock it so that other requests for @@ -137,6 +142,14 @@ loop: */ if (error = bread(VFSTOUFS(mntp)->um_devvp, fsbtodb(fs, itod(fs, ino)), (int)fs->fs_bsize, NOCRED, &bp)) { + /* + * The inode does not contain anything useful, so it would + * be misleading to leave it on its hash chain. + * Iput() will take care of putting it back on the free list. + */ + remque(ip); + ip->i_forw = ip; + ip->i_back = ip; /* * Unlock and discard unneeded inode. */ @@ -154,17 +167,25 @@ loop: */ vp = ITOV(ip); vp->v_type = IFTOVT(ip->i_mode); + if (vp->v_type == VFIFO) { +#ifdef FIFO + extern struct vnodeops fifo_inodeops; + vp->v_op = &fifo_inodeops; +#else + iput(ip); + *ipp = 0; + return (EOPNOTSUPP); +#endif /* FIFO */ + } if (vp->v_type == VCHR || vp->v_type == VBLK) { - vp->v_rdev = ip->i_rdev; vp->v_op = &spec_inodeops; - if (nvp = checkalias(vp, mntp)) { + if (nvp = checkalias(vp, ip->i_rdev, mntp)) { /* * Reinitialize aliased inode. */ vp = nvp; iq = VTOI(vp); iq->i_vnode = vp; - iq->i_lastr = 0; iq->i_flag = 0; ILOCK(iq); iq->i_din = ip->i_din; @@ -187,10 +208,6 @@ loop: ip->i_fs = fs; ip->i_devvp = VFSTOUFS(mntp)->um_devvp; VREF(ip->i_devvp); -#ifdef QUOTA - if (ip->i_mode != 0) - ip->i_dquot = inoquota(ip); -#endif /* * Set up a generation number for this inode if it does not * already have one. This should only happen on old filesystems. @@ -199,7 +216,7 @@ loop: if (++nextgennumber < (u_long)time.tv_sec) nextgennumber = time.tv_sec; ip->i_gen = nextgennumber; - if ((vp->v_mount->m_flag & M_RDONLY) == 0) + if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0) ip->i_flag |= IMOD; } *ipp = ip; @@ -229,29 +246,27 @@ ufs_inactive(vp) register struct inode *ip = VTOI(vp); int mode, error = 0; - if (vp->v_count != 0) - printf("ufs_inactive: pushing active ino %d dev 0x%x\n", - ip->i_number, ip->i_dev); + if (prtactive && vp->v_usecount != 0) + vprint("ufs_inactive: pushing active", vp); /* * Get rid of inodes related to stale file handles. */ if (ip->i_mode == 0) { - vgone(vp); + if ((vp->v_flag & VXLOCK) == 0) + vgone(vp); return (0); } ILOCK(ip); - if (ip->i_nlink <= 0 && (vp->v_mount->m_flag & M_RDONLY) == 0) { - error = itrunc(ip, (u_long)0); + if (ip->i_nlink <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { +#ifdef QUOTA + if (!getinoquota(ip)) + (void) chkiq(ip, -1, NOCRED, 0); +#endif + error = itrunc(ip, (u_long)0, 0); mode = ip->i_mode; ip->i_mode = 0; - ip->i_rdev = 0; ip->i_flag |= IUPD|ICHG; ifree(ip, ip->i_number, mode); -#ifdef QUOTA - (void) chkiq(ip->i_dev, ip, ip->i_uid, 0); - dqrele(ip->i_dquot); - ip->i_dquot = NODQUOT; -#endif } IUPDAT(ip, &time, &time, 0); IUNLOCK(ip); @@ -260,7 +275,7 @@ ufs_inactive(vp) * If we are done with the inode, reclaim it * so that it can be reused immediately. */ - if (vp->v_count == 0 && ip->i_mode == 0) + if (vp->v_usecount == 0 && ip->i_mode == 0) vgone(vp); return (error); } @@ -272,10 +287,10 @@ ufs_reclaim(vp) register struct vnode *vp; { register struct inode *ip = VTOI(vp); + int i; - if (vp->v_count != 0) - printf("ufs_reclaim: pushing active ino %d dev 0x%x\n", - ip->i_number, ip->i_dev); + if (prtactive && vp->v_usecount != 0) + vprint("ufs_reclaim: pushing active", vp); /* * Remove the inode from its hash chain. */ @@ -291,8 +306,12 @@ ufs_reclaim(vp) ip->i_devvp = 0; } #ifdef QUOTA - dqrele(ip->i_dquot); - ip->i_dquot = NODQUOT; + for (i = 0; i < MAXQUOTAS; i++) { + if (ip->i_dquot[i] != NODQUOT) { + dqrele(vp, ip->i_dquot[i]); + ip->i_dquot[i] = NODQUOT; + } + } #endif ip->i_flag = 0; return (0); @@ -317,7 +336,7 @@ iupdat(ip, ta, tm, waitfor) fs = ip->i_fs; if ((ip->i_flag & (IUPD|IACC|ICHG|IMOD)) == 0) return (0); - if (vp->v_mount->m_flag & M_RDONLY) + if (vp->v_mount->mnt_flag & MNT_RDONLY) return (0); error = bread(ip->i_devvp, fsbtodb(fs, itod(fs, ip->i_number)), (int)fs->fs_bsize, NOCRED, &bp); @@ -351,9 +370,10 @@ iupdat(ip, ta, tm, waitfor) * * NB: triple indirect blocks are untested. */ -itrunc(oip, length) +itrunc(oip, length, flags) register struct inode *oip; u_long length; + int flags; { register daddr_t lastblock; daddr_t bn, lbn, lastiblock[NIADDR]; @@ -363,7 +383,7 @@ itrunc(oip, length) int offset, osize, size, level; long count, nblocks, blocksreleased = 0; register int i; - int error, allerror = 0; + int aflags, error, allerror; struct inode tip; if (oip->i_size <= length) { @@ -396,23 +416,26 @@ itrunc(oip, length) oip->i_size = length; } else { lbn = lblkno(fs, length); - error = balloc(oip, lbn, offset, &bn, B_CLRBUF); - if (error) + aflags = B_CLRBUF; + if (flags & IO_SYNC) + aflags |= B_SYNC; +#ifdef QUOTA + if (error = getinoquota(oip)) + return (error); +#endif + if (error = balloc(oip, lbn, offset, &bp, aflags)) return (error); - if ((long)bn < 0) - panic("itrunc: hole"); oip->i_size = length; size = blksize(fs, oip, lbn); + bn = bp->b_blkno; count = howmany(size, CLBYTES); munhash(oip->i_devvp, bn + i * CLBYTES / DEV_BSIZE); - error = bread(oip->i_devvp, bn, size, NOCRED, &bp); - if (error) { - oip->i_size = osize; - brelse(bp); - return (error); - } bzero(bp->b_un.b_addr + offset, (unsigned)(size - offset)); - bdwrite(bp); + brealloc(bp, size); + if (flags & IO_SYNC) + bwrite(bp); + else + bdwrite(bp); } /* * Update file and block pointers @@ -432,7 +455,8 @@ itrunc(oip, length) for (i = NDADDR - 1; i > lastblock; i--) oip->i_db[i] = 0; oip->i_flag |= ICHG|IUPD; - allerror = syncip(oip); + vinvalbuf(ITOV(oip), (length > 0)); + allerror = iupdat(oip, &time, &time, MNT_WAIT); /* * Indirect blocks first. @@ -515,7 +539,8 @@ done: oip->i_blocks = 0; oip->i_flag |= ICHG; #ifdef QUOTA - (void) chkdq(oip, -blocksreleased, 0); + if (!getinoquota(oip)) + (void) chkdq(oip, -blocksreleased, NOCRED, 0); #endif return (allerror); } @@ -578,6 +603,8 @@ indirtrunc(ip, bn, lastbn, level, countp) bcopy((caddr_t)bap, (caddr_t)copy, (u_int)fs->fs_bsize); bzero((caddr_t)&bap[last + 1], (u_int)(NINDIR(fs) - (last + 1)) * sizeof (daddr_t)); + if (last == -1) + bp->b_flags |= B_INVAL; error = bwrite(bp); if (error) allerror = error; @@ -628,8 +655,14 @@ ilock(ip) while (ip->i_flag & ILOCKED) { ip->i_flag |= IWANT; + if (ip->i_spare0 == u.u_procp->p_pid) + panic("locking against myself"); + ip->i_spare1 = u.u_procp->p_pid; (void) sleep((caddr_t)ip, PINOD); } + ip->i_spare1 = 0; + ip->i_spare0 = u.u_procp->p_pid; + u.u_spare[0]++; ip->i_flag |= ILOCKED; } @@ -641,52 +674,12 @@ iunlock(ip) { if ((ip->i_flag & ILOCKED) == 0) - printf("unlocking unlocked inode %d on dev 0x%x\n", - ip->i_number, ip->i_dev); + vprint("iunlock: unlocked inode", ITOV(ip)); + ip->i_spare0 = 0; + u.u_spare[0]--; ip->i_flag &= ~ILOCKED; if (ip->i_flag&IWANT) { ip->i_flag &= ~IWANT; wakeup((caddr_t)ip); } } - -/* - * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC. - * The mode is shifted to select the owner/group/other fields. The - * super user is granted all permissions. - * - * NB: Called from vnode op table. It seems this could all be done - * using vattr's but... - */ -iaccess(ip, mode, cred) - register struct inode *ip; - register int mode; - struct ucred *cred; -{ - register gid_t *gp; - int i; - - /* - * If you're the super-user, you always get access. - */ - if (cred->cr_uid == 0) - return (0); - /* - * Access check is based on only one of owner, group, public. - * If not owner, then check group. If not a member of the - * group, then check public access. - */ - if (cred->cr_uid != ip->i_uid) { - mode >>= 3; - gp = cred->cr_groups; - for (i = 0; i < cred->cr_ngroups; i++, gp++) - if (ip->i_gid == *gp) - goto found; - mode >>= 3; -found: - ; - } - if ((ip->i_mode & mode) != 0) - return (0); - return (EACCES); -}