X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/a3a9487d7c80fac9d6da8d126b0c7f36eb233a2b..943685687a914f34bb028d07fefeff4a802b6d5b:/usr/src/sys/ufs/ffs/ffs_inode.c diff --git a/usr/src/sys/ufs/ffs/ffs_inode.c b/usr/src/sys/ufs/ffs/ffs_inode.c index a7a6b80dc0..2620c48abd 100644 --- a/usr/src/sys/ufs/ffs/ffs_inode.c +++ b/usr/src/sys/ufs/ffs/ffs_inode.c @@ -1,20 +1,20 @@ -/* ffs_inode.c 4.33 83/02/10 */ - -#include "../h/param.h" -#include "../h/systm.h" -#include "../h/mount.h" -#include "../h/dir.h" -#include "../h/user.h" -#include "../h/inode.h" -#include "../h/fs.h" -#include "../h/conf.h" -#include "../h/buf.h" +/* ffs_inode.c 6.11 84/08/29 */ + +#include "param.h" +#include "systm.h" +#include "mount.h" +#include "dir.h" +#include "user.h" +#include "inode.h" +#include "fs.h" +#include "conf.h" +#include "buf.h" #ifdef QUOTA -#include "../h/quota.h" +#include "quota.h" #endif -#include "../h/kernel.h" +#include "kernel.h" -#define INOHSZ 63 +#define INOHSZ 512 #if ((INOHSZ&(INOHSZ-1)) == 0) #define INOHASH(dev,ino) (((dev)+(ino))&(INOHSZ-1)) #else @@ -108,12 +108,18 @@ iget(dev, fs, ino) register struct dinode *dp; register struct inode *iq; + loop: - if (getfs(dev) != fs) - panic("iget: bad fs"); ih = &ihead[INOHASH(dev, ino)]; for (ip = ih->ih_chain[0]; ip != (struct inode *)ih; ip = ip->i_forw) if (ino == ip->i_number && dev == ip->i_dev) { + /* + * Following is essentially an inline expanded + * copy of igrab(), expanded inline for speed, + * and so that the test for a mounted on inode + * can be deferred until after we are sure that + * the inode isn't busy. + */ if ((ip->i_flag&ILOCKED) != 0) { ip->i_flag |= IWANT; sleep((caddr_t)ip, PINOD); @@ -148,6 +154,8 @@ loop: u.u_error = ENFILE; return(NULL); } + if (ip->i_count) + panic("free inode isn't"); if (iq = ip->i_freef) iq->i_freeb = &ifreeh; ifreeh = iq; @@ -162,15 +170,16 @@ loop: */ remque(ip); insque(ip, ih); -#ifdef QUOTA - dqrele(ip->i_dquot); -#endif ip->i_dev = dev; ip->i_fs = fs; ip->i_number = ino; + cacheinval(ip); ip->i_flag = ILOCKED; ip->i_count++; ip->i_lastr = 0; +#ifdef QUOTA + dqrele(ip->i_dquot); +#endif bp = bread(dev, fsbtodb(fs, itod(fs, ino)), (int)fs->fs_bsize); /* * Check I/O errors @@ -211,6 +220,36 @@ loop: return (ip); } +/* + * Convert a pointer to an inode into a reference to an inode. + * + * This is basically the internal piece of iget (after the + * inode pointer is located) but without the test for mounted + * filesystems. It is caller's responsibility to check that + * the inode pointer is valid. + */ +igrab(ip) + register struct inode *ip; +{ + while ((ip->i_flag&ILOCKED) != 0) { + ip->i_flag |= IWANT; + sleep((caddr_t)ip, PINOD); + } + if (ip->i_count == 0) { /* ino on free list */ + register struct inode *iq; + + if (iq = ip->i_freef) + iq->i_freeb = ip->i_freeb; + else + ifreet = ip->i_freeb; + *ip->i_freeb = iq; + ip->i_freef = NULL; + ip->i_freeb = NULL; + } + ip->i_count++; + ip->i_flag |= ILOCKED; +} + /* * Decrement reference count of * an inode structure. @@ -224,7 +263,7 @@ iput(ip) if ((ip->i_flag & ILOCKED) == 0) panic("iput"); - iunlock(ip); + IUNLOCK(ip); irele(ip); } @@ -243,13 +282,13 @@ irele(ip) ip->i_flag |= IUPD|ICHG; ifree(ip, ip->i_number, mode); #ifdef QUOTA - (void)chkiq(ip->i_dev, ip, ip->i_uid, 0); + (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); + IUNLOCK(ip); ip->i_flag = 0; /* * Put the inode on the end of the free list. @@ -270,7 +309,8 @@ irele(ip) } ip->i_freef = NULL; ifreet = &ip->i_freef; - } + } else if (!(ip->i_flag & ILOCKED)) + ITIMES(ip, &time, &time); ip->i_count--; } @@ -292,7 +332,7 @@ iupdat(ip, ta, tm, waitfor) register struct fs *fp; fp = ip->i_fs; - if ((ip->i_flag & (IUPD|IACC|ICHG)) != 0) { + if ((ip->i_flag & (IUPD|IACC|ICHG|IMOD)) != 0) { if (fp->fs_ronly) return; bp = bread(ip->i_dev, fsbtodb(fp, itod(fp, ip->i_number)), @@ -307,7 +347,7 @@ iupdat(ip, ta, tm, waitfor) ip->i_mtime = tm->tv_sec; if (ip->i_flag&ICHG) ip->i_ctime = time.tv_sec; - ip->i_flag &= ~(IUPD|IACC|ICHG); + ip->i_flag &= ~(IUPD|IACC|ICHG|IMOD); dp = bp->b_un.b_dino + itoo(fp, ip->i_number); dp->di_ic = ip->i_ic; if (waitfor) @@ -338,14 +378,15 @@ itrunc(oip, length) register struct fs *fs; register struct inode *ip; struct inode tip; - int level; -#ifdef QUOTA long blocksreleased = 0, nblocks; long indirtrunc(); -#endif + int level; - if (oip->i_size <= length) + if (oip->i_size <= length) { + oip->i_flag |= ICHG|IUPD; + iupdat(oip, &time, &time, 1); return; + } /* * Calculate index into inode's block list of * last direct and indirect blocks (if any) @@ -357,9 +398,7 @@ itrunc(oip, length) lastiblock[SINGLE] = lastblock - NDADDR; lastiblock[DOUBLE] = lastiblock[SINGLE] - NINDIR(fs); lastiblock[TRIPLE] = lastiblock[DOUBLE] - NINDIR(fs) * NINDIR(fs); -#ifdef QUOTA - nblocks = fs->fs_bsize / DEV_BSIZE; -#endif + nblocks = btodb(fs->fs_bsize); /* * Update size of file and block pointers * on disk before we start freeing blocks. @@ -388,16 +427,12 @@ itrunc(oip, length) for (level = TRIPLE; level >= SINGLE; level--) { bn = ip->i_ib[level]; if (bn != 0) { -#ifdef QUOTA blocksreleased += -#endif - indirtrunc(ip, bn, lastiblock[level], level); + indirtrunc(ip, bn, lastiblock[level], level); if (lastiblock[level] < 0) { ip->i_ib[level] = 0; free(ip, bn, (off_t)fs->fs_bsize); -#ifdef QUOTA blocksreleased += nblocks; -#endif } } if (lastiblock[level] >= 0) @@ -416,9 +451,7 @@ itrunc(oip, length) ip->i_db[i] = 0; size = (off_t)blksize(fs, ip, i); free(ip, bn, size); -#ifdef QUOTA - blocksreleased += size / DEV_BSIZE; -#endif + blocksreleased += btodb(size); } if (lastblock < 0) goto done; @@ -448,9 +481,7 @@ itrunc(oip, length) */ bn += numfrags(fs, newspace); free(ip, bn, oldspace - newspace); -#ifdef QUOTA - blocksreleased += (oldspace - newspace) / DEV_BSIZE; -#endif + blocksreleased += btodb(oldspace - newspace); } } done: @@ -462,8 +493,12 @@ done: if (ip->i_db[i] != oip->i_db[i]) panic("itrunc2"); /* END PARANOIA */ + oip->i_blocks -= blocksreleased; + if (oip->i_blocks < 0) /* sanity */ + oip->i_blocks = 0; + oip->i_flag |= ICHG; #ifdef QUOTA - (void) chkdq(ip, -blocksreleased, 0); + (void) chkdq(oip, -blocksreleased, 0); #endif } @@ -477,9 +512,7 @@ done: * * NB: triple indirect blocks are untested. */ -#ifdef QUOTA long -#endif indirtrunc(ip, bn, lastbn, level) register struct inode *ip; daddr_t bn, lastbn; @@ -491,9 +524,7 @@ indirtrunc(ip, bn, lastbn, level) register struct fs *fs = ip->i_fs; daddr_t nb, last; long factor; -#ifdef QUOTA int blocksreleased = 0, nblocks; -#endif /* * Calculate index in current block of last @@ -506,9 +537,7 @@ indirtrunc(ip, bn, lastbn, level) last = lastbn; if (lastbn > 0) last /= factor; -#ifdef QUOTA - nblocks = fs->fs_bsize / DEV_BSIZE; -#endif + nblocks = btodb(fs->fs_bsize); /* * Get buffer of block pointers, zero those * entries corresponding to blocks to be free'd, @@ -519,9 +548,7 @@ indirtrunc(ip, bn, lastbn, level) if (bp->b_flags&B_ERROR) { brelse(copy); brelse(bp); -#ifdef QUOTA return (0); -#endif } bap = bp->b_un.b_daddr; bcopy((caddr_t)bap, (caddr_t)copy->b_un.b_daddr, (u_int)fs->fs_bsize); @@ -538,14 +565,10 @@ indirtrunc(ip, bn, lastbn, level) if (nb == 0) continue; if (level > SINGLE) -#ifdef QUOTA blocksreleased += -#endif - indirtrunc(ip, nb, (daddr_t)-1, level - 1); + indirtrunc(ip, nb, (daddr_t)-1, level - 1); free(ip, nb, (int)fs->fs_bsize); -#ifdef QUOTA blocksreleased += nblocks; -#endif } /* @@ -555,15 +578,10 @@ indirtrunc(ip, bn, lastbn, level) last = lastbn % factor; nb = bap[i]; if (nb != 0) -#ifdef QUOTA - blocksreleased += -#endif - indirtrunc(ip, nb, last, level - 1); + blocksreleased += indirtrunc(ip, nb, last, level - 1); } brelse(bp); -#ifdef QUOTA return (blocksreleased); -#endif } /*