only delete space used by inode, on inode deletion; required
[unix-history] / usr / src / sys / ufs / lfs / lfs_inode.c
index ac0dd7b..e3e28c9 100644 (file)
@@ -4,7 +4,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)lfs_inode.c 7.53 (Berkeley) %G%
+ *     @(#)lfs_inode.c 7.56 (Berkeley) %G%
  */
 
 #include <sys/param.h>
  */
 
 #include <sys/param.h>
@@ -34,25 +34,6 @@ lfs_init()
        return (ufs_init());
 }
 
        return (ufs_init());
 }
 
-static daddr_t
-lfs_itod(fs, ino)
-       struct lfs *fs;
-       ino_t ino;
-{
-       BUF *bp;
-       IFILE *ifp;
-       daddr_t iaddr;
-
-       /* Translate an inode number to a disk address. */
-       if (ino == LFS_IFILE_INUM)
-               return (fs->lfs_idaddr);
-
-       LFS_IENTRY(ifp, fs, ino, bp);
-       iaddr = ifp->if_daddr;
-       brelse(bp);
-       return (iaddr);
-}
-
 /*
  * Look up an LFS dinode number to find its incore vnode.  If not already
  * in core, read it in from the specified device.  Return the inode locked.
 /*
  * Look up an LFS dinode number to find its incore vnode.  If not already
  * in core, read it in from the specified device.  Return the inode locked.
@@ -67,8 +48,10 @@ lfs_vget(mntp, ino, vpp)
        register struct lfs *fs;
        register struct inode *ip;
        struct buf *bp;
        register struct lfs *fs;
        register struct inode *ip;
        struct buf *bp;
+       struct ifile *ifp;
        struct vnode *vp;
        struct ufsmount *ump;
        struct vnode *vp;
        struct ufsmount *ump;
+       daddr_t daddr;
        dev_t dev;
        int error;
 
        dev_t dev;
        int error;
 
@@ -80,11 +63,24 @@ lfs_vget(mntp, ino, vpp)
        if ((*vpp = ufs_ihashget(dev, ino)) != NULL)
                return (0);
 
        if ((*vpp = ufs_ihashget(dev, ino)) != NULL)
                return (0);
 
+       /* Translate the inode number to a disk address. */
+       fs = ump->um_lfs;
+       if (ino == LFS_IFILE_INUM)
+               daddr = fs->lfs_idaddr;
+       else {
+               LFS_IENTRY(ifp, fs, ino, bp);
+               daddr = ifp->if_daddr;
+               brelse(bp);
+               if (daddr == LFS_UNUSED_DADDR)
+                       return (ENOENT);
+       }
+
        /* Allocate new vnode/inode. */
        if (error = lfs_vcreate(mntp, ino, &vp)) {
                *vpp = NULL;
                return (error);
        }
        /* Allocate new vnode/inode. */
        if (error = lfs_vcreate(mntp, ino, &vp)) {
                *vpp = NULL;
                return (error);
        }
+
        /*
         * Put it onto its hash chain and lock it so that other requests for
         * this inode will block if they arrive while we are sleeping waiting
        /*
         * Put it onto its hash chain and lock it so that other requests for
         * this inode will block if they arrive while we are sleeping waiting
@@ -94,10 +90,17 @@ lfs_vget(mntp, ino, vpp)
        ip = VTOI(vp);
        ufs_ihashins(ip);
 
        ip = VTOI(vp);
        ufs_ihashins(ip);
 
+       /*
+        * XXX
+        * This may not need to be here, logically it should go down with
+        * the i_devvp initialization.
+        * Ask Kirk.
+        */
+       ip->i_lfs = ump->um_lfs;
+
        /* Read in the disk contents for the inode, copy into the inode. */
        /* Read in the disk contents for the inode, copy into the inode. */
-       ip->i_lfs = fs = ump->um_lfs;
-       if (error = bread(ump->um_devvp, lfs_itod(fs, ino),
-           (int)fs->lfs_bsize, NOCRED, &bp)) {
+       if (error =
+           bread(ump->um_devvp, daddr, (int)fs->lfs_bsize, NOCRED, &bp)) {
                /*
                 * The inode does not contain anything useful, so it
                 * would be misleading to leave it on its hash chain.
                /*
                 * The inode does not contain anything useful, so it
                 * would be misleading to leave it on its hash chain.
@@ -160,23 +163,18 @@ lfs_update(vp, ta, tm, waitfor)
                ip->i_ctime = time.tv_sec;
        ip->i_flag &= ~(IUPD|IACC|ICHG|IMOD);
 
                ip->i_ctime = time.tv_sec;
        ip->i_flag &= ~(IUPD|IACC|ICHG|IMOD);
 
-       /*
-        * XXX
-        * I'm not real sure what to do here; once we have fsync and partial
-        * segments working in the LFS context, this must be fixed to be
-        * correct.  The contents of the inode have to be pushed back to
-        * stable storage.
-        */
-       return (0);
+       /* Push back the vnode and any dirty blocks it may have. */
+       return (waitfor ? lfs_vflush(vp) : 0);
 }
 
 /* Update segment usage information when removing a block. */
 }
 
 /* Update segment usage information when removing a block. */
-#define UPDATE_SEGUSE { \
-       LFS_SEGENTRY(sup, fs, lastseg, bp); \
-       sup->su_nbytes -= fs->lfs_bsize * num; \
-       LFS_UBWRITE(bp); \
-       blocksreleased += num; \
-}
+#define UPDATE_SEGUSE \
+       if (lastseg != -1) { \
+               LFS_SEGENTRY(sup, fs, lastseg, sup_bp); \
+               sup->su_nbytes -= fs->lfs_bsize * num; \
+               LFS_UBWRITE(sup_bp); \
+               blocksreleased += num; \
+       }
 
 #define SEGDEC { \
        if (daddr != UNASSIGNED) { \
 
 #define SEGDEC { \
        if (daddr != UNASSIGNED) { \
@@ -203,7 +201,8 @@ lfs_truncate(vp, length, flags)
        register INDIR *ap;
        register int i;
        register daddr_t *daddrp;
        register INDIR *ap;
        register int i;
        register daddr_t *daddrp;
-       struct buf *bp;
+       struct buf *bp, *sup_bp;
+       struct ifile *ifp;
        struct inode *ip;
        struct lfs *fs;
        INDIR a[NIADDR + 2], a_end[NIADDR + 2];
        struct inode *ip;
        struct lfs *fs;
        INDIR a[NIADDR + 2], a_end[NIADDR + 2];
@@ -217,18 +216,28 @@ lfs_truncate(vp, length, flags)
        printf("lfs_truncate\n");
 #endif
        vnode_pager_setsize(vp, length);
        printf("lfs_truncate\n");
 #endif
        vnode_pager_setsize(vp, length);
+
        ip = VTOI(vp);
        ip = VTOI(vp);
+       fs = ip->i_lfs;
+
+       /* If truncating the file to 0, update the version number. */
+       if (length == 0) {
+               LFS_IENTRY(ifp, fs, ip->i_number, bp);
+               ++ifp->if_version;
+               LFS_UBWRITE(bp);
+       }
+
        /* If length is larger than the file, just update the times. */
        if (ip->i_size <= length) {
                ip->i_flag |= ICHG|IUPD;
                return (lfs_update(vp, &time, &time, 1));
        }
        /* If length is larger than the file, just update the times. */
        if (ip->i_size <= length) {
                ip->i_flag |= ICHG|IUPD;
                return (lfs_update(vp, &time, &time, 1));
        }
+
        /*
         * Calculate index into inode's block list of last direct and indirect
         * blocks (if any) which we want to keep.  Lastblock is 0 when the
         * file is truncated to 0.
         */
        /*
         * Calculate index into inode's block list of last direct and indirect
         * blocks (if any) which we want to keep.  Lastblock is 0 when the
         * file is truncated to 0.
         */
-       fs = ip->i_lfs;
        lastblock = lblkno(fs, length + fs->lfs_bsize - 1);
        olastblock = lblkno(fs, ip->i_size + fs->lfs_bsize - 1) - 1;
 
        lastblock = lblkno(fs, length + fs->lfs_bsize - 1);
        olastblock = lblkno(fs, ip->i_size + fs->lfs_bsize - 1) - 1;
 
@@ -330,9 +339,7 @@ lfs_truncate(vp, length, flags)
                        }
                }
        }
                        }
                }
        }
-       if (lastseg != -1)
-               UPDATE_SEGUSE;
-
+       UPDATE_SEGUSE;
        ip->i_blocks -= blocksreleased;
        /* 
         * XXX
        ip->i_blocks -= blocksreleased;
        /* 
         * XXX