-/* ffs_inode.c 3.1 %H% */
+/* ffs_inode.c 4.9 82/02/27 */
#include "../h/param.h"
#include "../h/systm.h"
ihinit()
{
register int i;
+ register struct inode *ip = inode;
ifreel = 0;
- for (i = 0; i < NINODE - 1; i++)
- inode[i].i_hlink = i+1;
- inode[NINODE - 1].i_hlink = -1;
+ for (i = 0; i < ninode-1; i++, ip++)
+ ip->i_hlink = i+1;
+ ip->i_hlink = -1;
for (i = 0; i < INOHSZ; i++)
inohash[i] = -1;
}
*/
struct inode *
ifind(dev, ino)
-dev_t dev;
-ino_t ino;
+ dev_t dev;
+ ino_t ino;
{
register struct inode *ip;
* In all cases, a pointer to a locked
* inode structure is returned.
*
- * printf warning: no inodes -- if the inode
- * structure is full
* panic: no imt -- if the mounted file
* system is not in the mount table.
* "cannot happen"
*/
struct inode *
iget(dev, ino)
-dev_t dev;
-ino_t ino;
+ dev_t dev;
+ ino_t ino;
{
register struct inode *ip;
register struct mount *mp;
slot = INOHASH(dev, ino);
ip = &inode[inohash[slot]];
while (ip != &inode[-1]) {
- if(ino == ip->i_number && dev == ip->i_dev) {
- if((ip->i_flag&ILOCK) != 0) {
+ if (ino == ip->i_number && dev == ip->i_dev) {
+ if ((ip->i_flag&ILOCK) != 0) {
ip->i_flag |= IWANT;
sleep((caddr_t)ip, PINOD);
goto loop;
}
- if((ip->i_flag&IMOUNT) != 0) {
+ if ((ip->i_flag&IMOUNT) != 0) {
for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
- if(mp->m_inodp == ip) {
+ if (mp->m_inodp == ip) {
dev = mp->m_dev;
ino = ROOTINO;
goto loop;
}
ip = &inode[ip->i_hlink];
}
- if(ifreel < 0) {
- printf("Inode table overflow\n");
+ if (ifreel < 0) {
+ tablefull("inode");
u.u_error = ENFILE;
return(NULL);
}
/*
* Check I/O errors
*/
- if((bp->b_flags&B_ERROR) != 0) {
+ if ((bp->b_flags&B_ERROR) != 0) {
brelse(bp);
iput(ip);
return(NULL);
}
iexpand(ip, dp)
-register struct inode *ip;
-register struct dinode *dp;
+ register struct inode *ip;
+ register struct dinode *dp;
{
register char *p1, *p2;
register int i;
* truncate and deallocate the file.
*/
iput(ip)
-register struct inode *ip;
+ register struct inode *ip;
{
register int i, x;
register struct inode *jp;
- if(ip->i_count == 1) {
+ if (ip->i_count == 1) {
ip->i_flag |= ILOCK;
- if(ip->i_nlink <= 0) {
+ if (ip->i_nlink <= 0) {
itrunc(ip);
ip->i_mode = 0;
ip->i_flag |= IUPD|ICHG;
ifree(ip->i_dev, ip->i_number);
}
- iupdat(ip, &time, &time);
- prele(ip);
+ IUPDAT(ip, &time, &time, 0);
+ irele(ip);
i = INOHASH(ip->i_dev, ip->i_number);
x = ip - inode;
if (inohash[i] == x) {
ip->i_flag = 0;
ip->i_number = 0;
} else
- prele(ip);
+ irele(ip);
ip->i_count--;
}
* an inode structure.
* If any is on, update the inode
* with the current time.
+ * If waitfor is given, then must insure
+ * i/o order so wait for write to complete.
*/
-iupdat(ip, ta, tm)
-register struct inode *ip;
-time_t *ta, *tm;
+iupdat(ip, ta, tm, waitfor)
+ register struct inode *ip;
+ time_t *ta, *tm;
+ int waitfor;
{
register struct buf *bp;
struct dinode *dp;
register char *p1, *p2;
register int i;
- if((ip->i_flag&(IUPD|IACC|ICHG)) != 0) {
- if(getfs(ip->i_dev)->s_ronly)
+ if ((ip->i_flag&(IUPD|IACC|ICHG)) != 0) {
+ if (getfs(ip->i_dev)->s_ronly)
return;
bp = bread(ip->i_dev, itod(ip->i_number));
if (bp->b_flags & B_ERROR) {
*p1++ = *p2++;
*p1++ = *p2++;
*p1++ = *p2++;
- if(*p2++ != 0 && (ip->i_mode&IFMT)!=IFMPC
- && (ip->i_mode&IFMT)!=IFMPB)
+ if (*p2++ != 0)
printf("iaddress > 2^24\n");
}
- if(ip->i_flag&IACC)
+ if (ip->i_flag&IACC)
dp->di_atime = *ta;
- if(ip->i_flag&IUPD)
+ if (ip->i_flag&IUPD)
dp->di_mtime = *tm;
- if(ip->i_flag&ICHG)
+ if (ip->i_flag&ICHG)
dp->di_ctime = time;
ip->i_flag &= ~(IUPD|IACC|ICHG);
- bdwrite(bp);
+ if (waitfor)
+ bwrite(bp);
+ else
+ bdwrite(bp);
}
}
* than FIFO.
*/
itrunc(ip)
-register struct inode *ip;
+ register struct inode *ip;
{
register i;
dev_t dev;
daddr_t bn;
+ struct inode itmp;
- if (ip->i_vfdcnt)
- panic("itrunc");
i = ip->i_mode & IFMT;
- if (i!=IFREG && i!=IFDIR)
+ if (i!=IFREG && i!=IFDIR && i!=IFLNK)
return;
+
+ /*
+ * Clean inode on disk before freeing blocks
+ * to insure no duplicates if system crashes.
+ */
+ itmp = *ip;
+ itmp.i_size = 0;
+ for (i = 0; i < NADDR; i++)
+ itmp.i_un.i_addr[i] = 0;
+ itmp.i_flag |= ICHG|IUPD;
+ iupdat(&itmp, &time, &time, 1);
+ ip->i_flag &= ~(IUPD|IACC|ICHG);
+
+ /*
+ * Now return blocks to free list... if machine
+ * crashes, they will be harmless MISSING blocks.
+ */
dev = ip->i_dev;
for(i=NADDR-1; i>=0; i--) {
bn = ip->i_un.i_addr[i];
- if(bn == (daddr_t)0)
+ if (bn == (daddr_t)0)
continue;
ip->i_un.i_addr[i] = (daddr_t)0;
switch(i) {
}
}
ip->i_size = 0;
- ip->i_flag |= ICHG|IUPD;
+ /*
+ * Inode was written and flags updated above.
+ * No need to modify flags here.
+ */
}
tloop(dev, bn, f1, f2)
bp = NULL;
for(i=NINDIR-1; i>=0; i--) {
- if(bp == NULL) {
+ if (bp == NULL) {
bp = bread(dev, bn);
if (bp->b_flags & B_ERROR) {
brelse(bp);
bap = bp->b_un.b_daddr;
}
nb = bap[i];
- if(nb == (daddr_t)0)
+ if (nb == (daddr_t)0)
continue;
- if(f1) {
+ if (f1) {
brelse(bp);
bp = NULL;
tloop(dev, nb, f2, 0);
} else
free(dev, nb);
}
- if(bp != NULL)
+ if (bp != NULL)
brelse(bp);
free(dev, bn);
}
register struct inode *ip;
ip = ialloc(u.u_pdir->i_dev);
- if(ip == NULL) {
+ if (ip == NULL) {
iput(u.u_pdir);
return(NULL);
}
ip->i_flag |= IACC|IUPD|ICHG;
- if((mode&IFMT) == 0)
+ if ((mode&IFMT) == 0)
mode |= IFREG;
ip->i_mode = mode & ~u.u_cmask;
ip->i_nlink = 1;
ip->i_uid = u.u_uid;
- ip->i_gid = u.u_gid;
+ ip->i_gid = u.u_pdir->i_gid;
+
+ /*
+ * Make sure inode goes to disk before directory entry.
+ */
+ iupdat(ip, &time, &time, 1);
+
wdir(ip);
return(ip);
}
* to a call to namei.
*/
wdir(ip)
-struct inode *ip;
+ struct inode *ip;
{
u.u_dent.d_ino = ip->i_number;
writei(u.u_pdir);
iput(u.u_pdir);
}
+
+#ifdef ilock
+#undef ilock
+#endif
+#ifdef irele
+#undef irele
+#endif
+/*
+ * Lock an inode. If its already locked, set the WANT bit and sleep.
+ */
+ilock(ip)
+ register struct inode *ip;
+{
+
+ while (ip->i_flag&ILOCK) {
+ ip->i_flag |= IWANT;
+ sleep((caddr_t)ip, PINOD);
+ }
+ ip->i_flag |= ILOCK;
+}
+
+/*
+ * Unlock an inode. If WANT bit is on, wakeup.
+ */
+irele(ip)
+ register struct inode *ip;
+{
+
+ ip->i_flag &= ~ILOCK;
+ if (ip->i_flag&IWANT) {
+ ip->i_flag &= ~IWANT;
+ wakeup((caddr_t)ip);
+ }
+}