Source-Changes-HG archive

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

[src/trunk]: src/sys/ufs Deal with fragment size changes better. For each fr...



details:   https://anonhg.NetBSD.org/src/rev/af07418822c9
branches:  trunk
changeset: 533644:af07418822c9
user:      perseant <perseant%NetBSD.org@localhost>
date:      Sat Jul 06 01:30:11 2002 +0000

description:
Deal with fragment size changes better.  For each fragment that can
exist on an on-disk inode, we keep a record of its size in struct inode,
which is updated when we write the block to disk.  The cleaner routines
thus have ready access to what size is the correct size for this block,
on disk.

Fixed a related bug: if a file with fragments is being cleaned
(fragments being cleaned) at the same time it is being extended beyond
NDADDR blocks, we could write a bogus FINFO record that has a frag in the
middle; when it was cleaned this would give back bogus file data.  Don't
write the indirect blocks in this case, since there is no need.

lfs_fragextend and lfs_truncate no longer require the seglock, but instead
take a shared lock, which the seglock locks exclusively.

diffstat:

 sys/ufs/lfs/lfs.h          |    4 +-
 sys/ufs/lfs/lfs_balloc.c   |   32 ++++-----
 sys/ufs/lfs/lfs_inode.c    |   58 ++++++++++-------
 sys/ufs/lfs/lfs_segment.c  |  147 +++++++++++++++++++++++++++++++-------------
 sys/ufs/lfs/lfs_subr.c     |   14 +++-
 sys/ufs/lfs/lfs_syscalls.c |   54 +++++++++-------
 sys/ufs/lfs/lfs_vfsops.c   |   14 +++-
 sys/ufs/ufs/inode.h        |    6 +-
 8 files changed, 211 insertions(+), 118 deletions(-)

diffs (truncated from 807 to 300 lines):

diff -r 60b9c777f699 -r af07418822c9 sys/ufs/lfs/lfs.h
--- a/sys/ufs/lfs/lfs.h Sat Jul 06 01:00:15 2002 +0000
+++ b/sys/ufs/lfs/lfs.h Sat Jul 06 01:30:11 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lfs.h,v 1.40 2002/06/16 00:13:15 perseant Exp $        */
+/*     $NetBSD: lfs.h,v 1.41 2002/07/06 01:30:11 perseant Exp $        */
 
 /*-
  * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
@@ -460,6 +460,7 @@
        size_t lfs_devbsize;            /* Device block size */
        size_t lfs_devbshift;           /* Device block shift */
        struct lock lfs_freelock;
+       struct lock lfs_fraglock;
        pid_t lfs_rfpid;                /* Process ID of roll-forward agent */
        int       lfs_nadirop;          /* number of active dirop nodes */
        long      lfs_ravail;           /* blocks pre-reserved for writing */
@@ -766,6 +767,7 @@
 #define        SEGM_PROT       0x08            /* don't inactivate at segunlock */
        u_int16_t seg_flags;            /* run-time flags for this segment */
        u_int32_t seg_iocount;          /* number of ios pending */
+       int       ndupino;              /* number of duplicate inodes */
 };
 
 struct lfs_cluster {
diff -r 60b9c777f699 -r af07418822c9 sys/ufs/lfs/lfs_balloc.c
--- a/sys/ufs/lfs/lfs_balloc.c  Sat Jul 06 01:00:15 2002 +0000
+++ b/sys/ufs/lfs/lfs_balloc.c  Sat Jul 06 01:30:11 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lfs_balloc.c,v 1.32 2002/05/14 20:03:53 perseant Exp $ */
+/*     $NetBSD: lfs_balloc.c,v 1.33 2002/07/06 01:30:12 perseant Exp $ */
 
 /*-
  * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
@@ -71,7 +71,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: lfs_balloc.c,v 1.32 2002/05/14 20:03:53 perseant Exp $");
+__KERNEL_RCSID(0, "$NetBSD: lfs_balloc.c,v 1.33 2002/07/06 01:30:12 perseant Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_quota.h"
@@ -342,9 +342,7 @@
        long bb;
        int error;
        extern long locked_queue_bytes;
-       struct buf *ibp;
        size_t obufsize;
-       SEGUSE *sup;
 
        ip = VTOI(vp);
        fs = ip->i_lfs;
@@ -356,8 +354,11 @@
         * accounting information while a segment is being written.
         */
     top:
+#ifdef LFS_MALLOC_SEGLOCK
        lfs_seglock(fs, SEGM_PROT);
-
+#else
+       lockmgr(&fs->lfs_fraglock, LK_SHARED, 0);
+#endif
        if (!ISSPACE(fs, bb, cred)) {
                error = ENOSPC;
                goto out;
@@ -378,31 +379,24 @@
         * holding a block busy or while holding the seglock.  In that case,
         * release both and start over after waiting.
         */
+
        if ((*bpp)->b_flags & B_DELWRI) {
                if (!lfs_fits(fs, bb)) {
                        brelse(*bpp);
 #ifdef QUOTA
                        chkdq(ip, -bb, cred, 0);
 #endif
+#ifdef LFS_FRAGSIZE_SEGLOCK
                        lfs_segunlock(fs);
+#else
+                       lockmgr(&fs->lfs_fraglock, LK_RELEASE, 0);
+#endif
                        lfs_availwait(fs, bb);
                        goto top;
                }
                fs->lfs_avail -= bb;
        }
 
-       /*
-        * Fix the allocation for this fragment so that it looks like the
-         * source segment contained a block of the new size.  This overcounts;
-        * but the overcount only lasts until the block in question
-        * is written, so the on-disk live bytes count is always correct.
-        */
-       if ((*bpp)->b_blkno > 0) {
-               LFS_SEGENTRY(sup, fs, dtosn(fs, dbtofsb(fs, (*bpp)->b_blkno)), ibp);
-               sup->su_nbytes += (nsize - osize);
-               LFS_BWRITE_LOG(ibp);
-               ip->i_ffs_blocks += bb;
-       }
        fs->lfs_bfree -= bb;
        ip->i_lfs_effnblks += bb;
        ip->i_flag |= IN_CHANGE | IN_UPDATE;
@@ -421,6 +415,10 @@
        bzero((char *)((*bpp)->b_data) + osize, (u_int)(nsize - osize));
 
     out:
+#ifdef LFS_FRAGSIZE_SEGLOCK
        lfs_segunlock(fs);
+#else
+       lockmgr(&fs->lfs_fraglock, LK_RELEASE, 0);
+#endif
        return (error);
 }
diff -r 60b9c777f699 -r af07418822c9 sys/ufs/lfs/lfs_inode.c
--- a/sys/ufs/lfs/lfs_inode.c   Sat Jul 06 01:00:15 2002 +0000
+++ b/sys/ufs/lfs/lfs_inode.c   Sat Jul 06 01:30:11 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lfs_inode.c,v 1.58 2002/07/02 19:07:03 yamt Exp $      */
+/*     $NetBSD: lfs_inode.c,v 1.59 2002/07/06 01:30:12 perseant Exp $  */
 
 /*-
  * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
@@ -71,7 +71,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: lfs_inode.c,v 1.58 2002/07/02 19:07:03 yamt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: lfs_inode.c,v 1.59 2002/07/06 01:30:12 perseant Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_quota.h"
@@ -124,11 +124,11 @@
 #endif
 
        /*
-        * XXX we used to go from the top down here, presumably with the
-        * idea that the same inode could be written twice in the same
-        * block (which is not supposed to be true).
+        * Read the inode block backwards, since later versions of the
+        * inode will supercede earlier ones.  Though it is unlikely, it is
+        * possible that the same inode will appear in the same inode block.
         */
-       for (ldip = dip; ldip < fin; ++ldip)
+       for (ldip = fin - 1; ldip >= dip; --ldip)
                if (ldip->di_inumber == ino)
                        return (ldip);
 
@@ -218,6 +218,7 @@
  * disk blocks.
  */
 /* VOP_BWRITE 1 + NIADDR + VOP_BALLOC == 2 + 2*NIADDR times */
+
 int
 lfs_truncate(void *v)
 {
@@ -312,18 +313,11 @@
         * truncating.  Otherwise, blocks which are accounted for on the
         * inode *and* which have been created for cleaning can coexist,
         * and cause an overcounting.
-        *
-        * (We don't need to *hold* the seglock, though, because we already
-        * hold the inode lock; draining the seglock is sufficient.)
         */
-#ifdef LFS_AGGRESSIVE_SEGLOCK
+#ifdef LFS_FRAGSIZE_SEGLOCK
        lfs_seglock(fs, SEGM_PROT);
 #else
-       if (ovp != fs->lfs_unlockvp) {
-               while (fs->lfs_seglock) {
-                       tsleep(&fs->lfs_seglock, PRIBIO+1, "lfs_truncate", 0);
-               }
-       }
+       lockmgr(&fs->lfs_fraglock, LK_SHARED, 0);
 #endif
        
        /*
@@ -347,8 +341,10 @@
                error = VOP_BALLOC(ovp, length - 1, 1, ap->a_cred, aflags, &bp);
                if (error) {
                        lfs_reserve(fs, ovp, -btofsb(fs, (2 * NIADDR + 3) << fs->lfs_bshift));
-#ifdef LFS_AGGRESSIVE_SEGLOCK
+#ifdef LFS_FRAGSIZE_SEGLOCK
                        lfs_segunlock(fs);
+#else
+                       lockmgr(&fs->lfs_fraglock, LK_RELEASE, 0);
 #endif
                        return (error);
                }
@@ -430,17 +426,22 @@
         * All whole direct blocks or frags.
         */
        for (i = NDADDR - 1; i > lastblock; i--) {
-               long bsize;
+               long bsize, obsize;
 
                bn = oip->i_ffs_db[i];
                if (bn == 0)
                        continue;
                bsize = blksize(fs, oip, i);
-               if (oip->i_ffs_db[i] > 0)
-                       real_released += btofsb(fs, bsize);
+               if (oip->i_ffs_db[i] > 0) {
+                       /* Check for fragment size changes */
+                       obsize = oip->i_lfs_fragsize[i];
+                       real_released += btofsb(fs, obsize);
+                       oip->i_lfs_fragsize[i] = 0;
+               } else
+                       obsize = 0;
                blocksreleased += btofsb(fs, bsize);
                oip->i_ffs_db[i] = 0;
-               lfs_blkfree(fs, bn, bsize, &lastseg, &bc);
+               lfs_blkfree(fs, bn, obsize, &lastseg, &bc);
        }
        if (lastblock < 0)
                goto done;
@@ -451,23 +452,28 @@
         */
        bn = oip->i_ffs_db[lastblock];
        if (bn != 0) {
-               long oldspace, newspace;
+               long oldspace, newspace, olddspace;
 
                /*
                 * Calculate amount of space we're giving
                 * back as old block size minus new block size.
                 */
                oldspace = blksize(fs, oip, lastblock);
+               olddspace = oip->i_lfs_fragsize[lastblock];
+
                oip->i_ffs_size = length;
                newspace = blksize(fs, oip, lastblock);
                if (newspace == 0)
                        panic("itrunc: newspace");
                if (oldspace - newspace > 0) {
-                       lfs_blkfree(fs, bn, oldspace - newspace, &lastseg, &bc);
-                       if (bn > 0)
-                               real_released += btofsb(fs, oldspace - newspace);
                        blocksreleased += btofsb(fs, oldspace - newspace);
                }
+#if 0
+               if (bn > 0 && olddspace - newspace > 0) {
+                       /* No segment accounting here, just vnode */
+                       real_released += btofsb(fs, olddspace - newspace);
+               }
+#endif
        }
 
 done:
@@ -503,8 +509,10 @@
        (void) chkdq(oip, -blocksreleased, NOCRED, 0);
 #endif
        lfs_reserve(fs, ovp, -btofsb(fs, (2 * NIADDR + 3) << fs->lfs_bshift));
-#ifdef LFS_AGGRESSIVE_SEGLOCK
+#ifdef LFS_FRAGSIZE_SEGLOCK
        lfs_segunlock(fs);
+#else
+       lockmgr(&fs->lfs_fraglock, LK_RELEASE, 0);
 #endif
        return (allerror);
 }
diff -r 60b9c777f699 -r af07418822c9 sys/ufs/lfs/lfs_segment.c
--- a/sys/ufs/lfs/lfs_segment.c Sat Jul 06 01:00:15 2002 +0000
+++ b/sys/ufs/lfs/lfs_segment.c Sat Jul 06 01:30:11 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lfs_segment.c,v 1.79 2002/06/16 00:13:15 perseant Exp $        */
+/*     $NetBSD: lfs_segment.c,v 1.80 2002/07/06 01:30:13 perseant Exp $        */
 
 /*-
  * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
@@ -71,7 +71,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: lfs_segment.c,v 1.79 2002/06/16 00:13:15 perseant Exp $");
+__KERNEL_RCSID(0, "$NetBSD: lfs_segment.c,v 1.80 2002/07/06 01:30:13 perseant Exp $");
 
 #define ivndebug(vp,str) printf("ino %d: %s\n",VTOI(vp)->i_number,(str))
 
@@ -719,9 +719,12 @@
 {
        struct buf *bp;
        struct finfo *fip;
+       struct inode *ip;
        IFILE *ifp;
+       int i, frag;
        
-       
+       ip = VTOI(vp);
+
        if (sp->seg_bytes_left < fs->lfs_bsize ||
            sp->sum_bytes_left < sizeof(struct finfo))
                (void) lfs_writeseg(fs, sp);
@@ -734,7 +737,7 @@
        
        fip = sp->fip;
        fip->fi_nblocks = 0;
-       fip->fi_ino = VTOI(vp)->i_number;
+       fip->fi_ino = ip->i_number;
        LFS_IENTRY(ifp, fs, fip->fi_ino, bp);



Home | Main Index | Thread Index | Old Index