Skip site navigation (1)Skip section navigation (2)
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>