plock/prele here now
[unix-history] / usr / src / sys / ufs / lfs / lfs_inode.c
index 871987d..18d152b 100644 (file)
@@ -1,4 +1,4 @@
-/*     lfs_inode.c     3.3     %G%     */
+/*     lfs_inode.c     4.5     81/04/28        */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
@@ -24,11 +24,12 @@ short       ifreel;
 ihinit()
 {
        register int i;
 ihinit()
 {
        register int i;
+       register struct inode *ip = inode;
 
        ifreel = 0;
 
        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;
 }
        for (i = 0; i < INOHSZ; i++)
                inohash[i] = -1;
 }
@@ -63,8 +64,6 @@ ino_t ino;
  * In all cases, a pointer to a locked
  * inode structure is returned.
  *
  * 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"
  * panic: no imt -- if the mounted file
  *     system is not in the mount table.
  *     "cannot happen"
@@ -106,7 +105,7 @@ loop:
                ip = &inode[ip->i_hlink];
        }
        if(ifreel < 0) {
                ip = &inode[ip->i_hlink];
        }
        if(ifreel < 0) {
-               printf("Inode table overflow\n");
+               tablefull("inode");
                u.u_error = ENFILE;
                return(NULL);
        }
                u.u_error = ENFILE;
                return(NULL);
        }
@@ -178,7 +177,7 @@ register struct inode *ip;
                        ip->i_flag |= IUPD|ICHG;
                        ifree(ip->i_dev, ip->i_number);
                }
                        ip->i_flag |= IUPD|ICHG;
                        ifree(ip->i_dev, ip->i_number);
                }
-               IUPDAT(ip, &time, &time);
+               IUPDAT(ip, &time, &time, 0);
                prele(ip);
                i = INOHASH(ip->i_dev, ip->i_number);
                x = ip - inode;
                prele(ip);
                i = INOHASH(ip->i_dev, ip->i_number);
                x = ip - inode;
@@ -208,10 +207,13 @@ done:
  * an inode structure.
  * If any is on, update the inode
  * with the current time.
  * 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)
+iupdat(ip, ta, tm, waitfor)
 register struct inode *ip;
 time_t *ta, *tm;
 register struct inode *ip;
 time_t *ta, *tm;
+int waitfor;
 {
        register struct buf *bp;
        struct dinode *dp;
 {
        register struct buf *bp;
        struct dinode *dp;
@@ -250,7 +252,10 @@ time_t *ta, *tm;
                if(ip->i_flag&ICHG)
                        dp->di_ctime = time;
                ip->i_flag &= ~(IUPD|IACC|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);
        }
 }
 
        }
 }
 
@@ -269,12 +274,30 @@ register struct inode *ip;
        register i;
        dev_t dev;
        daddr_t bn;
        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)
                return;
 
        if (ip->i_vfdcnt)
                panic("itrunc");
        i = ip->i_mode & IFMT;
        if (i!=IFREG && i!=IFDIR)
                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];
        dev = ip->i_dev;
        for(i=NADDR-1; i>=0; i--) {
                bn = ip->i_un.i_addr[i];
@@ -300,7 +323,10 @@ register struct inode *ip;
                }
        }
        ip->i_size = 0;
                }
        }
        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)
 }
 
 tloop(dev, bn, f1, f2)
@@ -357,6 +383,12 @@ maknode(mode)
        ip->i_nlink = 1;
        ip->i_uid = u.u_uid;
        ip->i_gid = u.u_gid;
        ip->i_nlink = 1;
        ip->i_uid = u.u_uid;
        ip->i_gid = u.u_gid;
+
+       /*
+        * Make sure inode goes to disk before directory entry.
+        */
+       iupdat(ip, &time, &time, 1);
+
        wdir(ip);
        return(ip);
 }
        wdir(ip);
        return(ip);
 }
@@ -378,3 +410,41 @@ struct inode *ip;
        writei(u.u_pdir);
        iput(u.u_pdir);
 }
        writei(u.u_pdir);
        iput(u.u_pdir);
 }
+
+#ifdef plock
+#undef plock
+#endif
+#ifdef prele
+#undef prele
+#endif
+/*
+ * Lock an inode (should be called ilock).
+ * If its already locked,
+ * set the WANT bit and sleep.
+ */
+plock(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.
+ */
+prele(ip)
+register struct inode *ip;
+{
+
+       ip->i_flag &= ~ILOCK;
+       if(ip->i_flag&IWANT) {
+               ip->i_flag &= ~IWANT;
+               wakeup((caddr_t)ip);
+       }
+}