-/* 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
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);
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;
*/
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
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.
if ((ip->i_flag & ILOCKED) == 0)
panic("iput");
- iunlock(ip);
+ IUNLOCK(ip);
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.
}
ip->i_freef = NULL;
ifreet = &ip->i_freef;
- }
+ } else if (!(ip->i_flag & ILOCKED))
+ ITIMES(ip, &time, &time);
ip->i_count--;
}
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)),
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)
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)
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.
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)
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;
*/
bn += numfrags(fs, newspace);
free(ip, bn, oldspace - newspace);
-#ifdef QUOTA
- blocksreleased += (oldspace - newspace) / DEV_BSIZE;
-#endif
+ blocksreleased += btodb(oldspace - newspace);
}
}
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
}
*
* NB: triple indirect blocks are untested.
*/
-#ifdef QUOTA
long
-#endif
indirtrunc(ip, bn, lastbn, level)
register struct inode *ip;
daddr_t bn, lastbn;
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
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,
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);
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
}
/*
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
}
/*