Date: Sat, 12 Mar 2011 10:09:17 GMT From: Zheng Liu <lz@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 189918 for review Message-ID: <201103121009.p2CA9HfM008771@skunkworks.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@189918?ac=10 Change 189918 by lz@freebsd-dev on 2011/03/12 10:08:22 Add cluster summary information in memory. Affected files ... .. //depot/projects/soc2010/extfs/src/sys/fs/ext2fs/ext2_alloc.c#39 edit .. //depot/projects/soc2010/extfs/src/sys/fs/ext2fs/ext2_extern.h#4 edit .. //depot/projects/soc2010/extfs/src/sys/fs/ext2fs/ext2_subr.c#3 edit .. //depot/projects/soc2010/extfs/src/sys/fs/ext2fs/ext2_vfsops.c#12 edit .. //depot/projects/soc2010/extfs/src/sys/fs/ext2fs/ext2fs.h#8 edit Differences ... ==== //depot/projects/soc2010/extfs/src/sys/fs/ext2fs/ext2_alloc.c#39 (text+ko) ==== @@ -678,7 +678,7 @@ */ #ifdef FANCY_REALLOC -static int doasyncfree = 0; +static int doasyncfree = 1; SYSCTL_INT(_vfs_ext2fs, OID_AUTO, doasyncfree, CTLFLAG_RW, &doasyncfree, 0, "Use asychronous writes to update block pointers when freeing blocks"); @@ -1291,6 +1291,7 @@ #endif setbit(bbp, bno); EXT2_LOCK(ump); + ext2_clusteracct(fs, bbp, cg, bno, -1); fs->e2fs->e2fs_fbcount--; fs->e2fs_gd[cg].ext2bgd_nbfree--; fs->e2fs_fmod = 1; @@ -1309,6 +1310,7 @@ char *bbp; int error, i, bit, loc, end, start; daddr_t bno = 0, runstart, runlen; + int32_t *lp; fs = ip->i_e2fs; ump = ip->i_ump; @@ -1326,11 +1328,32 @@ bbp = (char *)bp->b_data; bp->b_xflags |= BX_BKGRDWRITE; + EXT2_LOCK(ump); /* - * TODO: check to see if a cluster of the needed size is - * available in this cg. + * Check to see if a cluster of the needed size (or bigger) is + * available in this cylinder group. */ + lp = &fs->e2fs_clustersum[cg].cs_sum[len]; + for (i = len; i <= fs->e2fs_contigsumsize; i++) + if (*lp++ > 0) + break; + if (i > fs->e2fs_contigsumsize) { + /* + * Update the cluster summary information to reflect + * the true maximum sized cluster so that future cluster + * allocation requests can avoid reading the bitmap only + * to find no clusters. + */ + lp = &fs->e2fs_clustersum[cg].cs_sum[len - 1]; + for (i = len - 1; i > 0; i--) + if (*lp-- > 0) + break; + fs->e2fs_maxcluster[cg] = i; + goto fail; + } + EXT2_UNLOCK(ump); + /* Search the cluster map to find a big enough cluster like ffs. */ if (bpref) start = dtogd(fs, bpref) / NBBY; else @@ -1393,18 +1416,20 @@ EXT2_LOCK(ump); for (i = 0; i < len; i += fs->e2fs_fpb) { setbit(bbp, bno + i); + ext2_clusteracct(fs, bbp, cg, bno + i, -1); fs->e2fs->e2fs_fbcount--; fs->e2fs_gd[cg].ext2bgd_nbfree--; - fs->e2fs_fmod = 1; } + fs->e2fs_fmod = 1; EXT2_UNLOCK(ump); bdwrite(bp); return (phy_blk(cg, fs) + bno); fail_lock: + EXT2_LOCK(ump); +fail: brelse(bp); - EXT2_LOCK(ump); return (0); } #endif /* FANCY_REALLOC */ @@ -1531,6 +1556,7 @@ } clrbit(bbp, bno); EXT2_LOCK(ump); + ext2_clusteracct(fs, bbp, cg, bno, 1); fs->e2fs->e2fs_fbcount++; fs->e2fs_gd[cg].ext2bgd_nbfree++; fs->e2fs_fmod = 1; ==== //depot/projects/soc2010/extfs/src/sys/fs/ext2fs/ext2_extern.h#4 (text+ko) ==== @@ -55,6 +55,7 @@ int32_t ext2_blkpref(struct inode *, int32_t, int, int32_t *, int32_t); int ext2_bmap(struct vop_bmap_args *); int ext2_bmaparray(struct vnode *, int32_t, int32_t *, int *, int *); +void ext2_clusteracct(struct m_ext2fs *, char *, int, daddr_t, int); void ext2_dirbad(struct inode *ip, doff_t offset, char *how); void ext2_ei2i(struct ext2fs_dinode *, struct inode *); int ext2_getlbns(struct vnode *, int32_t, struct indir *, int *); ==== //depot/projects/soc2010/extfs/src/sys/fs/ext2fs/ext2_subr.c#3 (text+ko) ==== @@ -120,3 +120,120 @@ } } #endif /* KDB */ + +/* + * Update the cluster map because of an allocation or free like ffs. + * + * cnt == 1 means free; cnt == -1 means allocating. + */ +void +ext2_clusteracct(struct m_ext2fs *fs, char *bbp, int cg, daddr_t bno, int cnt) +{ + int32_t *sump = fs->e2fs_clustersum[cg].cs_sum; + int32_t *lp; + int i, forw, back, start, end, map = 0, bit, loc; + int fpgn = howmany(fs->e2fs->e2fs_fpg, NBBY); + + /* Initialize the cluster summary array. */ + if (fs->e2fs_clustersum[cg].cs_init == 0) { + int run = 0; + + end = fpgn; + bit = 1; + loc = 0; + map = bbp[loc++]; + + for (i = 0; i < fs->e2fs->e2fs_fpg && loc < end; i++) { + if ((map & bit) == 0) + run++; + else if (run != 0) { + if (run > fs->e2fs_contigsumsize) + run = fs->e2fs_contigsumsize; + sump[run]++; + run = 0; + } + if ((i & (NBBY - 1)) != (NBBY - 1)) + bit <<= 1; + else { + map = bbp[loc++]; + bit = 1; + } + } + if (run != 0) { + if (run > fs->e2fs_contigsumsize) + run = fs->e2fs_contigsumsize; + sump[run]++; + } + fs->e2fs_clustersum[cg].cs_init = 1; + } + + if (fs->e2fs_contigsumsize <= 0) + return; + + /* Find the size of the cluster going forward. */ + start = bno + 1; + loc = start / NBBY; + end = start + fs->e2fs_contigsumsize; + if (end > fs->e2fs->e2fs_fpg) + end = fs->e2fs->e2fs_fpg; + if (loc < fpgn) + map = bbp[loc++]; + bit = 1 << (start % NBBY); + for (i = start; i < end; i++) { + if ((map & bit) != 0) + break; + if ((i & (NBBY - 1)) != (NBBY - 1)) { + bit <<= 1; + } else { + /* + * XXX: off-by-one. + * when loc == howmany(fs->e2fs->e2fs_fpg, NBBY), + * bbp[loc++] will cause kernel crash. + */ + if (loc < fpgn) + map = bbp[loc++]; + bit = 1; + } + } + forw = i - start; + + /* Find the size of the cluster going backward. */ + start = bno - 1; + loc = start / NBBY; + end = start - fs->e2fs_contigsumsize; + if (end < 0) + end = -1; + map = bbp[loc--]; + bit = 1 << (start % NBBY); + for (i = start; i > end; i--) { + if ((map & bit) != 0) + break; + if ((i & (NBBY - 1)) != 0) { + bit >>= 1; + } else { + map = bbp[loc--]; + bit = 1 << (NBBY - 1); + } + } + back = start - i; + + /* + * Account for old cluster and the possibly new forward and + * back clusters. + */ + i = back + forw + 1; + if (i > fs->e2fs_contigsumsize) + i = fs->e2fs_contigsumsize; + sump[i] += cnt; + if (back > 0) + sump[back] -= cnt; + if (forw > 0) + sump[forw] -= cnt; + + /* Update cluster summary information. */ + lp = &sump[fs->e2fs_contigsumsize]; + for (i = fs->e2fs_contigsumsize; i > 0; i--) + if (*lp-- > 0) + break; + fs->e2fs_maxcluster[cg] = i; +} ==== //depot/projects/soc2010/extfs/src/sys/fs/ext2fs/ext2_vfsops.c#12 (text+ko) ==== @@ -455,6 +455,10 @@ return (error); } + /* + * FIXME: It seems that we don't need to do something + * for reallocblk. + */ if (fs->e2fs_contigsumsize > 0) { lp = fs->e2fs_maxcluster; for (i = 0; i < fs->e2fs_gcount; i++) @@ -525,6 +529,7 @@ int ronly; int i, size; int32_t *lp; + struct csum *sump; ronly = vfs_flagopt(mp->mnt_optnew, "ro", NULL, 0); /* XXX: use VOP_ACESS to check FS perms */ @@ -614,13 +619,19 @@ MIN(ump->um_e2fs->e2fs_maxcontig, EXT2_MAXCONTIG); else ump->um_e2fs->e2fs_contigsumsize = 0; - ump->um_e2fs->e2fs_maxcluster = NULL; if (ump->um_e2fs->e2fs_contigsumsize > 0) { size = ump->um_e2fs->e2fs_gcount * sizeof(int32_t); ump->um_e2fs->e2fs_maxcluster = malloc(size, M_EXT2MNT, M_WAITOK); + size = ump->um_e2fs->e2fs_gcount * sizeof(struct csum); + ump->um_e2fs->e2fs_clustersum = malloc(size, M_EXT2MNT, M_WAITOK); lp = ump->um_e2fs->e2fs_maxcluster; - for (i = 0; i < ump->um_e2fs->e2fs_gcount; i++) + sump = ump->um_e2fs->e2fs_clustersum; + for (i = 0; i < ump->um_e2fs->e2fs_gcount; i++, sump++) { *lp++ = ump->um_e2fs->e2fs_contigsumsize; + sump->cs_init = 0; + sump->cs_sum = malloc((ump->um_e2fs->e2fs_contigsumsize + 1) * + sizeof(int32_t), M_EXT2MNT, M_WAITOK | M_ZERO); + } } brelse(bp); @@ -698,6 +709,8 @@ struct ext2mount *ump; struct m_ext2fs *fs; int error, flags, ronly; + struct csum *sump; + int i; flags = 0; if (mntflags & MNT_FORCE) { @@ -722,6 +735,10 @@ g_topology_unlock(); PICKUP_GIANT(); vrele(ump->um_devvp); + sump = fs->e2fs_clustersum; + for (i = 0; i < fs->e2fs_gcount; i++, sump++) + free(sump->cs_sum, M_EXT2MNT); + free(fs->e2fs_clustersum, M_EXT2MNT); free(fs->e2fs_maxcluster, M_EXT2MNT); free(fs->e2fs_rsv_tree, M_EXT2MNT); mtx_destroy(&fs->e2fs_rsv_lock); ==== //depot/projects/soc2010/extfs/src/sys/fs/ext2fs/ext2fs.h#8 (text+ko) ==== @@ -156,6 +156,7 @@ int32_t e2fs_maxcontig; /* max number of contiguous blks */ int32_t e2fs_contigsumsize; /* size of cluster summary array */ int32_t *e2fs_maxcluster; /* max cluster in each cyl group */ + struct csum *e2fs_clustersum;/* cluster summary in each cly group */ }; /* @@ -258,6 +259,13 @@ u_int32_t reserved2[3]; }; +/* cluster summary information */ + +struct csum { + int8_t cs_init; /* cluster summary has been initialized */ + int32_t *cs_sum; /* cluster summary array */ +}; + /* EXT2FS metadatas are stored in little-endian byte order. These macros * helps reading these metadatas */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201103121009.p2CA9HfM008771>