Author: jeff
Date: Mon Jul  4 22:08:04 2011
New Revision: 223772
URL: http://svn.freebsd.org/changeset/base/223772

Log:
   - Speed up pendingblock processing again.  Having too much delay between
     ffs_blkfree() and the pending adjustment causes all kinds of
     space related problems.

Modified:
  head/sys/ufs/ffs/ffs_softdep.c
  head/sys/ufs/ffs/softdep.h

Modified: head/sys/ufs/ffs/ffs_softdep.c
==============================================================================
--- head/sys/ufs/ffs/ffs_softdep.c      Mon Jul  4 21:04:25 2011        
(r223771)
+++ head/sys/ufs/ffs/ffs_softdep.c      Mon Jul  4 22:08:04 2011        
(r223772)
@@ -880,6 +880,7 @@ static      inline void setup_freeext(struct 
 static inline void setup_freeindir(struct freeblks *, struct inode *, int,
            ufs_lbn_t, int);
 static inline struct freeblks *newfreeblks(struct mount *, struct inode *);
+static void freeblks_free(struct ufsmount *, struct freeblks *, int);
 static void indir_trunc(struct freework *, ufs2_daddr_t, ufs_lbn_t);
 ufs2_daddr_t blkcount(struct fs *, ufs2_daddr_t, off_t);
 static int trunc_check_buf(struct buf *, int *, ufs_lbn_t, int, int);
@@ -5751,7 +5752,6 @@ newfreeblks(mp, ip)
        freeblks->fb_modrev = DIP(ip, i_modrev);
        freeblks->fb_devvp = ip->i_devvp;
        freeblks->fb_chkcnt = 0;
-       freeblks->fb_freecnt = 0;
        freeblks->fb_len = 0;
 
        return (freeblks);
@@ -6199,7 +6199,7 @@ softdep_journal_freeblocks(ip, cred, len
        quotaref(vp, freeblks->fb_quota);
        (void) chkdq(ip, -datablocks, NOCRED, 0);
 #endif
-       freeblks->fb_chkcnt = datablocks;
+       freeblks->fb_chkcnt = -datablocks;
        UFS_LOCK(ip->i_ump);
        fs->fs_pendingblocks += datablocks;
        UFS_UNLOCK(ip->i_ump);
@@ -6429,7 +6429,7 @@ softdep_setup_freeblocks(ip, length, fla
        quotaref(vp, freeblks->fb_quota);
        (void) chkdq(ip, -datablocks, NOCRED, 0);
 #endif
-       freeblks->fb_chkcnt = datablocks;
+       freeblks->fb_chkcnt = -datablocks;
        UFS_LOCK(ip->i_ump);
        fs->fs_pendingblocks += datablocks;
        UFS_UNLOCK(ip->i_ump);
@@ -7284,8 +7284,8 @@ freework_freeblock(freework)
                freeblks->fb_cgwait++;
                WORKLIST_INSERT(&wkhd, &freework->fw_list);
        }
-       freeblks->fb_freecnt += btodb(bsize);
        FREE_LOCK(&lk);
+       freeblks_free(ump, freeblks, btodb(bsize));
        ffs_blkfree(ump, fs, freeblks->fb_devvp, freework->fw_blkno, bsize,
            freeblks->fb_inum, freeblks->fb_vtype, &wkhd);
        ACQUIRE_LOCK(&lk);
@@ -7459,6 +7459,33 @@ handle_workitem_freeblocks(freeblks, fla
 }
 
 /*
+ * Handle completion of block free via truncate.  This allows fs_pending
+ * to track the actual free block count more closely than if we only updated
+ * it at the end.  We must be careful to handle cases where the block count
+ * on free was incorrect.
+ */
+static void
+freeblks_free(ump, freeblks, blocks)
+       struct ufsmount *ump;
+       struct freeblks *freeblks;
+       int blocks;
+{
+       struct fs *fs;
+       ufs2_daddr_t remain;
+
+       UFS_LOCK(ump);
+       remain = -freeblks->fb_chkcnt;
+       freeblks->fb_chkcnt += blocks;
+       if (remain > 0) {
+               if (remain < blocks)
+                       blocks = remain;
+               fs = ump->um_fs;
+               fs->fs_pendingblocks -= blocks;
+       }
+       UFS_UNLOCK(ump);
+}
+
+/*
  * Once all of the freework workitems are complete we can retire the
  * freeblocks dependency and any journal work awaiting completion.  This
  * can not be called until all other dependencies are stable on disk.
@@ -7478,7 +7505,7 @@ handle_complete_freeblocks(freeblks, fla
        ump = VFSTOUFS(freeblks->fb_list.wk_mp);
        fs = ump->um_fs;
        flags = LK_EXCLUSIVE | flags;
-       spare = freeblks->fb_freecnt - freeblks->fb_chkcnt;
+       spare = freeblks->fb_chkcnt;
 
        /*
         * If we did not release the expected number of blocks we may have
@@ -7501,9 +7528,9 @@ handle_complete_freeblocks(freeblks, fla
                }
                vput(vp);
        }
-       if (freeblks->fb_chkcnt) {
+       if (spare < 0) {
                UFS_LOCK(ump);
-               fs->fs_pendingblocks -= freeblks->fb_chkcnt;
+               fs->fs_pendingblocks += spare;
                UFS_UNLOCK(ump);
        }
 #ifdef QUOTA
@@ -7559,7 +7586,7 @@ indir_trunc(freework, dbn, lbn)
        ufs2_daddr_t nb, nnb, *bap2 = 0;
        ufs_lbn_t lbnadd, nlbn;
        int i, nblocks, ufs1fmt;
-       int fs_pendingblocks;
+       int freedblocks;
        int goingaway;
        int freedeps;
        int needj;
@@ -7701,16 +7728,18 @@ indir_trunc(freework, dbn, lbn)
                bp->b_flags |= B_INVAL | B_NOCACHE;
                brelse(bp);
        }
-       fs_pendingblocks = 0;
+       freedblocks = 0;
        if (level == 0)
-               fs_pendingblocks = (nblocks * cnt);
+               freedblocks = (nblocks * cnt);
+       if (needj == 0)
+               freedblocks += nblocks;
+       freeblks_free(ump, freeblks, freedblocks);
        /*
         * If we are journaling set up the ref counts and offset so this
         * indirect can be completed when its children are free.
         */
        if (needj) {
                ACQUIRE_LOCK(&lk);
-               freeblks->fb_freecnt += fs_pendingblocks;
                freework->fw_off = i;
                freework->fw_ref += freedeps;
                freework->fw_ref -= NINDIR(fs) + 1;
@@ -7724,12 +7753,10 @@ indir_trunc(freework, dbn, lbn)
        /*
         * If we're not journaling we can free the indirect now.
         */
-       fs_pendingblocks += nblocks;
        dbn = dbtofsb(fs, dbn);
        ffs_blkfree(ump, fs, freeblks->fb_devvp, dbn, fs->fs_bsize,
            freeblks->fb_inum, freeblks->fb_vtype, NULL);
        /* Non SUJ softdep does single-threaded truncations. */
-       freeblks->fb_freecnt += fs_pendingblocks;
        if (freework->fw_blkno == dbn) {
                freework->fw_state |= ALLCOMPLETE;
                ACQUIRE_LOCK(&lk);

Modified: head/sys/ufs/ffs/softdep.h
==============================================================================
--- head/sys/ufs/ffs/softdep.h  Mon Jul  4 21:04:25 2011        (r223771)
+++ head/sys/ufs/ffs/softdep.h  Mon Jul  4 22:08:04 2011        (r223772)
@@ -536,8 +536,7 @@ struct freeblks {
 #endif
        uint64_t fb_modrev;             /* Inode revision at start of trunc. */
        off_t   fb_len;                 /* Length we're truncating to. */
-       ufs2_daddr_t fb_chkcnt;         /* Expected blks released. */
-       ufs2_daddr_t fb_freecnt;        /* Actual blocks released. */
+       ufs2_daddr_t fb_chkcnt;         /* Blocks released. */
        ino_t   fb_inum;                /* inode owner of blocks */
        enum    vtype fb_vtype;         /* inode owner's file type */
        uid_t   fb_uid;                 /* uid of previous owner of blocks */
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to