Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/ufs/lfs If LFS_DO_ROLLFORWARD is defined, roll forward f...



details:   https://anonhg.NetBSD.org/src/rev/42f68dc81cc3
branches:  trunk
changeset: 499688:42f68dc81cc3
user:      perseant <perseant%NetBSD.org@localhost>
date:      Mon Nov 27 03:33:57 2000 +0000

description:
If LFS_DO_ROLLFORWARD is defined, roll forward from the older checkpoint
on mount, through the newer checkpoint and on through any newer
partial-segments that may have been written but not checkpointed because
of an intervening crash.

LFS_DO_ROLLFORWARD is not defined by default.

diffstat:

 sys/ufs/lfs/lfs_alloc.c    |  245 ++++++++++++++++----
 sys/ufs/lfs/lfs_bio.c      |   17 +-
 sys/ufs/lfs/lfs_inode.c    |   15 +-
 sys/ufs/lfs/lfs_segment.c  |   33 +-
 sys/ufs/lfs/lfs_syscalls.c |   15 +-
 sys/ufs/lfs/lfs_vfsops.c   |  538 ++++++++++++++++++++++++++++++++++++++++++++-
 6 files changed, 775 insertions(+), 88 deletions(-)

diffs (truncated from 1165 to 300 lines):

diff -r c89db04a0307 -r 42f68dc81cc3 sys/ufs/lfs/lfs_alloc.c
--- a/sys/ufs/lfs/lfs_alloc.c   Mon Nov 27 02:37:14 2000 +0000
+++ b/sys/ufs/lfs/lfs_alloc.c   Mon Nov 27 03:33:57 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lfs_alloc.c,v 1.43 2000/09/09 04:49:54 perseant Exp $  */
+/*     $NetBSD: lfs_alloc.c,v 1.44 2000/11/27 03:33:57 perseant Exp $  */
 
 /*-
  * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
@@ -95,6 +95,166 @@
 extern int lfs_dirvcount;
 extern struct lock ufs_hashlock;
 
+static int extend_ifile(struct lfs *, struct ucred *);
+static int lfs_ialloc(struct lfs *, struct vnode *, ino_t, int, struct vnode **);
+
+/*
+ * Allocate a particular inode with a particular version number, freeing
+ * any previous versions of this inode that may have gone before.
+ * Used by the roll-forward code.
+ *
+ * XXX this function does not have appropriate locking to be used on a live fs;
+ * XXX but something similar could probably be used for an "undelete" call.
+ */
+int
+lfs_rf_valloc(struct lfs *fs, ino_t ino, int version, struct proc *p,
+             struct vnode **vpp)
+{
+       IFILE *ifp;
+       struct buf *bp;
+       struct vnode *vp;
+       struct inode *ip;
+       ino_t tino, oldnext;
+       int error;
+
+       /*
+        * First, just try a vget. If the version number is the one we want,
+        * we don't have to do anything else.  If the version number is wrong,
+        * take appropriate action.
+        */
+       error = VFS_VGET(fs->lfs_ivnode->v_mount, ino, &vp);
+       if (error == 0) {
+               /* printf("lfs_rf_valloc[1]: ino %d vp %p\n", ino, vp); */
+
+               *vpp = vp;
+               ip = VTOI(vp);
+               if (ip->i_ffs_gen == version)
+                       return 0;
+               else if (ip->i_ffs_gen < version) {
+                       VOP_TRUNCATE(vp, (off_t)0, 0, NOCRED, p);
+                       ip->i_ffs_gen = version;
+                       LFS_SET_UINO(ip, IN_CHANGE | IN_MODIFIED | IN_UPDATE);
+                       return 0;
+               } else {
+                       /* printf("ino %d: asked for version %d but got %d\n",
+                              ino, version, ip->i_ffs_gen); */
+                       vput(vp);
+                       *vpp = NULLVP;
+                       return EEXIST;
+               }
+       }
+
+       /*
+        * The inode is not in use.  Find it on the free list.
+        */
+       /* If the Ifile is too short to contain this inum, extend it */
+       while (VTOI(fs->lfs_ivnode)->i_ffs_size <=
+              dbtob(fsbtodb(fs, ino / fs->lfs_ifpb + fs->lfs_cleansz +
+                            fs->lfs_segtabsz))) {
+               extend_ifile(fs, NOCRED);
+       }
+
+       LFS_IENTRY(ifp, fs, ino, bp);
+       oldnext = ifp->if_nextfree;
+       ifp->if_version = version;
+       brelse(bp);
+
+       if (ino == fs->lfs_free) {
+               fs->lfs_free = oldnext;
+       } else {
+               tino = fs->lfs_free;
+               while(1) {
+                       LFS_IENTRY(ifp, fs, tino, bp);
+                       if (ifp->if_nextfree == ino ||
+                           ifp->if_nextfree == LFS_UNUSED_INUM)
+                               break;
+                       tino = ifp->if_nextfree;
+                       brelse(bp);
+               }
+               if (ifp->if_nextfree == LFS_UNUSED_INUM) {
+                       brelse(bp);
+                       return ENOENT;
+               }
+               ifp->if_nextfree = oldnext;
+               VOP_BWRITE(bp);
+       }
+
+       error = lfs_ialloc(fs, fs->lfs_ivnode, ino, version, &vp);
+       if (error == 0) {
+               /*
+                * Make it VREG so we can put blocks on it.  We will change
+                * this later if it turns out to be some other kind of file.
+                */
+               ip = VTOI(vp);
+               ip->i_ffs_mode = IFREG;
+               ip->i_ffs_nlink = 1;
+               ip->i_ffs_effnlink = 1;
+               ufs_vinit(vp->v_mount, lfs_specop_p, lfs_fifoop_p, &vp);
+               ip = VTOI(vp);
+
+               /* printf("lfs_rf_valloc: ino %d vp %p\n", ino, vp); */
+
+               /* The dirop-nature of this vnode is past */
+               (void)lfs_vunref(vp);
+               --lfs_dirvcount;
+               vp->v_flag &= ~VDIROP;
+               --fs->lfs_nadirop;
+               ip->i_flag &= ~IN_ADIROP;
+       }
+       *vpp = vp;
+       return error;
+}
+
+static int
+extend_ifile(struct lfs *fs, struct ucred *cred)
+{
+       struct vnode *vp;
+       struct inode *ip;
+       IFILE *ifp;
+       struct buf *bp;
+       int error;
+       ufs_daddr_t i, blkno, max;
+       ino_t oldlast;
+
+       vp = fs->lfs_ivnode;
+       (void)lfs_vref(vp);
+       vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+       ip = VTOI(vp);
+       blkno = lblkno(fs, ip->i_ffs_size);
+       if ((error = VOP_BALLOC(vp, ip->i_ffs_size, fs->lfs_bsize, cred, 0,
+                               &bp)) != 0) {
+               VOP_UNLOCK(vp, 0);
+               lfs_vunref(vp);
+               return (error);
+       }
+       ip->i_ffs_size += fs->lfs_bsize;
+       uvm_vnp_setsize(vp, ip->i_ffs_size);
+       (void)uvm_vnp_uncache(vp);
+       VOP_UNLOCK(vp, 0);
+       
+       i = (blkno - fs->lfs_segtabsz - fs->lfs_cleansz) *
+               fs->lfs_ifpb;
+       oldlast = fs->lfs_free;
+       fs->lfs_free = i;
+#ifdef DIAGNOSTIC
+       if(fs->lfs_free == LFS_UNUSED_INUM)
+               panic("inode 0 allocated [2]");
+#endif /* DIAGNOSTIC */
+       max = i + fs->lfs_ifpb;
+       /* printf("extend ifile for ino %d--%d\n", i, max); */
+       for (ifp = (struct ifile *)bp->b_data; i < max; ++ifp) {
+               ifp->if_version = 1;
+               ifp->if_daddr = LFS_UNUSED_DADDR;
+               ifp->if_nextfree = ++i;
+       }
+       ifp--;
+       ifp->if_nextfree = oldlast;
+       (void) VOP_BWRITE(bp); /* Ifile */
+       lfs_vunref(vp);
+
+       return 0;
+}
+
 /* Allocate a new inode. */
 /* ARGSUSED */
 /* VOP_BWRITE 2i times */
@@ -111,14 +271,9 @@
        struct lfs *fs;
        struct buf *bp;
        struct ifile *ifp;
-       struct inode *ip;
-       struct vnode *vp;
-       ufs_daddr_t blkno;
        ino_t new_ino;
-       u_long i, max;
        int error;
        int new_gen;
-       extern int lfs_dirvcount;
 
        fs = VTOI(ap->a_pvp)->i_lfs;
        if (fs->lfs_ronly)
@@ -132,7 +287,7 @@
         * written to disk.
         *
         * XXX this sucks.  We should instead encode the head of the free
-        * list into the CLEANERINFO block of the Ifile.
+        * list into the CLEANERINFO block of the Ifile. [XXX v2]
         */
        lfs_seglock(fs, SEGM_PROT);
 
@@ -147,7 +302,7 @@
        }
 #endif /* DIAGNOSTIC */
 #ifdef ALLOCPRINT
-       printf("lfs_ialloc: allocate inode %d\n", new_ino);
+       printf("lfs_valloc: allocate inode %d\n", new_ino);
 #endif
        
        /*
@@ -156,52 +311,18 @@
         */
        LFS_IENTRY(ifp, fs, new_ino, bp);
        if (ifp->if_daddr != LFS_UNUSED_DADDR)
-               panic("lfs_ialloc: inuse inode %d on the free list", new_ino);
+               panic("lfs_valloc: inuse inode %d on the free list", new_ino);
        fs->lfs_free = ifp->if_nextfree;
        new_gen = ifp->if_version; /* version was updated by vfree */
-#ifdef LFS_DEBUG_NEXTFREE
-       ifp->if_nextfree = 0;
-       (void) VOP_BWRITE(bp); /* Ifile */
-#else
        brelse(bp);
-#endif
 
        /* Extend IFILE so that the next lfs_valloc will succeed. */
        if (fs->lfs_free == LFS_UNUSED_INUM) {
-               vp = fs->lfs_ivnode;
-               (void)lfs_vref(vp);
-               vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
-               ip = VTOI(vp);
-               blkno = lblkno(fs, ip->i_ffs_size);
-               if ((error = VOP_BALLOC(vp, ip->i_ffs_size, fs->lfs_bsize,
-                                       ap->a_cred, 0, &bp)) != 0) {
-                       VOP_UNLOCK(vp, 0);
+               if ((error = extend_ifile(fs, ap->a_cred)) != 0) {
+                       fs->lfs_free = new_ino;
                        lfs_segunlock(fs);
-                       fs->lfs_free = new_ino;
-                       return (error);
+                       return error;
                }
-               ip->i_ffs_size += fs->lfs_bsize;
-               uvm_vnp_setsize(vp, ip->i_ffs_size);
-               (void)uvm_vnp_uncache(vp);
-               VOP_UNLOCK(vp, 0);
-
-               i = (blkno - fs->lfs_segtabsz - fs->lfs_cleansz) *
-                       fs->lfs_ifpb;
-               fs->lfs_free = i;
-#ifdef DIAGNOSTIC
-               if(fs->lfs_free == LFS_UNUSED_INUM)
-                       panic("inode 0 allocated [2]");
-#endif /* DIAGNOSTIC */
-               max = i + fs->lfs_ifpb;
-               for (ifp = (struct ifile *)bp->b_data; i < max; ++ifp) {
-                       ifp->if_version = 1;
-                       ifp->if_daddr = LFS_UNUSED_DADDR;
-                       ifp->if_nextfree = ++i;
-               }
-               ifp--;
-               ifp->if_nextfree = LFS_UNUSED_INUM;
-               (void) VOP_BWRITE(bp); /* Ifile */
-               lfs_vunref(vp);
        }
 #ifdef DIAGNOSTIC
        if(fs->lfs_free == LFS_UNUSED_INUM)
@@ -210,13 +331,27 @@
        
        lfs_segunlock(fs);
 
-       if ((error = getnewvnode(VT_LFS, ap->a_pvp->v_mount,
-           lfs_vnodeop_p, &vp)) != 0)
+       return lfs_ialloc(fs, ap->a_pvp, new_ino, new_gen, ap->a_vpp);
+}
+
+static int
+lfs_ialloc(struct lfs *fs, struct vnode *pvp, ino_t new_ino, int new_gen,
+          struct vnode **vpp)
+{
+       struct inode *ip;
+       struct vnode *vp;
+       IFILE *ifp;
+       struct buf *bp;
+       int error;
+
+       error = getnewvnode(VT_LFS, pvp->v_mount, lfs_vnodeop_p, &vp);
+       /* printf("lfs_ialloc: ino %d vp %p error %d\n", new_ino, vp, error);*/
+       if (error)
                goto errout;
 
        lockmgr(&ufs_hashlock, LK_EXCLUSIVE, 0);
        /* Create an inode to associate with the vnode. */
-       lfs_vcreate(ap->a_pvp->v_mount, new_ino, vp);
+       lfs_vcreate(pvp->v_mount, new_ino, vp);
        
        ip = VTOI(vp);
        /* Zero out the direct and indirect block addresses. */
@@ -224,19 +359,22 @@
        ip->i_din.ffs_din.di_inumber = new_ino;
        



Home | Main Index | Thread Index | Old Index