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>