Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 4 Jul 2011 22:08:04 +0000 (UTC)
From:      Jeff Roberson <jeff@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r223772 - head/sys/ufs/ffs
Message-ID:  <201107042208.p64M84I8036302@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201107042208.p64M84I8036302>