PERFORCE change 189918 for review
Zheng Liu
lz at FreeBSD.org
Sat Mar 12 10:09:18 UTC 2011
http://p4web.freebsd.org/@@189918?ac=10
Change 189918 by lz at 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
*/
More information about the p4-projects
mailing list