Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 1 Feb 2011 18:21:45 +0000 (UTC)
From:      John Baldwin <jhb@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r218175 - head/sys/fs/ext2fs
Message-ID:  <201102011821.p11ILjda080918@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jhb
Date: Tue Feb  1 18:21:45 2011
New Revision: 218175
URL: http://svn.freebsd.org/changeset/base/218175

Log:
  - Set the next_alloc fields for an i-node after allocating a new block
    so that future allocations start with most recently allocated block
    rather than the beginning of the filesystem.
  - Fix ext2_alloccg() to properly scan for 8 block chunks that are not
    aligned on 8-bit boundaries.  Previously this was causing new blocks
    to be allocated in a highly fragmented fashion (block 0 of a file at
    lbn N, block 1 at lbn N + 8, block 2 at lbn N + 16, etc.).
  - Cosmetic tweaks to the currently-disabled fancy realloc sysctls.
  
  PR:		kern/153584
  Discussed with:	bde
  Tested by:	Pedro F. Giffuni  giffunip at yahoo, Zheng Liu (lz)

Modified:
  head/sys/fs/ext2fs/ext2_alloc.c

Modified: head/sys/fs/ext2fs/ext2_alloc.c
==============================================================================
--- head/sys/fs/ext2fs/ext2_alloc.c	Tue Feb  1 17:42:57 2011	(r218174)
+++ head/sys/fs/ext2fs/ext2_alloc.c	Tue Feb  1 18:21:45 2011	(r218175)
@@ -59,6 +59,10 @@ static u_long	ext2_hashalloc(struct inod
 						int));
 static daddr_t	ext2_nodealloccg(struct inode *, int, daddr_t, int);
 static daddr_t  ext2_mapsearch(struct m_ext2fs *, char *, daddr_t);
+#ifdef FANCY_REALLOC
+static int	ext2_reallocblks(struct vop_reallocblks_args *);
+#endif
+
 /*
  * Allocate a block in the file system.
  *
@@ -108,13 +112,17 @@ ext2_alloc(ip, lbn, bpref, size, cred, b
 		goto nospace;
 	if (bpref >= fs->e2fs->e2fs_bcount)
 		bpref = 0;
-	 if (bpref == 0)
+	if (bpref == 0)
                 cg = ino_to_cg(fs, ip->i_number);
         else
                 cg = dtog(fs, bpref);
         bno = (daddr_t)ext2_hashalloc(ip, cg, bpref, fs->e2fs_bsize,
                                                  ext2_alloccg);
         if (bno > 0) {
+		/* set next_alloc fields as done in block_getblk */
+		ip->i_next_alloc_block = lbn;
+		ip->i_next_alloc_goal = bno;
+
                 ip->i_blocks += btodb(fs->e2fs_bsize);
                 ip->i_flag |= IN_CHANGE | IN_UPDATE;
                 *bnp = bno;
@@ -143,13 +151,14 @@ nospace:
  */
 
 #ifdef FANCY_REALLOC
-#include <sys/sysctl.h>
+SYSCTL_NODE(_vfs, OID_AUTO, ext2fs, CTLFLAG_RW, 0, "EXT2FS filesystem");
+
 static int doasyncfree = 1;
-static int doreallocblks = 1;
+SYSCTL_INT(_vfs_ext2fs, OID_AUTO, doasyncfree, CTLFLAG_RW, &doasyncfree, 0,
+    "Use asychronous writes to update block pointers when freeing blocks");
 
-#ifdef	OPT_DEBUG
-SYSCTL_INT(_debug, 14, doasyncfree, CTLFLAG_RW, &doasyncfree, 0, "");
-#endif	/* OPT_DEBUG */
+static int doreallocblks = 1;
+SYSCTL_INT(_vfs_ext2fs, OID_AUTO, doreallocblks, CTLFLAG_RW, &doreallocblks, 0, "");
 #endif
 
 int
@@ -624,7 +633,8 @@ ext2_alloccg(struct inode *ip, int cg, d
 	struct m_ext2fs *fs;
 	struct buf *bp;
 	struct ext2mount *ump;
-	int error, bno, start, end, loc;
+	daddr_t bno, runstart, runlen;
+	int bit, loc, end, error, start;
 	char *bbp;
 	/* XXX ondisk32 */
 	fs = ip->i_e2fs;
@@ -665,18 +675,52 @@ ext2_alloccg(struct inode *ip, int cg, d
 	else
 		start = 0;
 	end = howmany(fs->e2fs->e2fs_fpg, NBBY) - start;
+retry:
+	runlen = 0;
+	runstart = 0;
 	for (loc = start; loc < end; loc++) {
-		if (bbp[loc] == 0) {
-			bno = loc * NBBY;
-			goto gotit;
+		if (bbp[loc] == (char)0xff) {
+			runlen = 0;
+			continue;
 		}
-	}
-	for (loc = 0; loc < start; loc++) {
-		if (bbp[loc] == 0) {
-			bno = loc * NBBY;
+
+		/* Start of a run, find the number of high clear bits. */
+		if (runlen == 0) {
+			bit = fls(bbp[loc]);
+			runlen = NBBY - bit;
+			runstart = loc * NBBY + bit;
+		} else if (bbp[loc] == 0) {
+			/* Continue a run. */
+			runlen += NBBY;
+		} else {
+			/*
+			 * Finish the current run.  If it isn't long
+			 * enough, start a new one.
+			 */
+			bit = ffs(bbp[loc]) - 1;
+			runlen += bit;
+			if (runlen >= 8) {
+				bno = runstart;
+				goto gotit;
+			}
+
+			/* Run was too short, start a new one. */
+			bit = fls(bbp[loc]);
+			runlen = NBBY - bit;
+			runstart = loc * NBBY + bit;
+		}
+
+		/* If the current run is long enough, use it. */
+		if (runlen >= 8) {
+			bno = runstart;
 			goto gotit;
 		}
 	}
+	if (start != 0) {
+		end = start;
+		start = 0;
+		goto retry;
+	}
 
 	bno = ext2_mapsearch(fs, bbp, bpref);
 	if (bno < 0){



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