PERFORCE change 181353 for review

Zheng Liu lz at FreeBSD.org
Fri Jul 23 07:59:33 UTC 2010


http://p4web.freebsd.org/@@181353?ac=10

Change 181353 by lz at gnehzuil-freebsd on 2010/07/23 07:59:03

	       Add flex group data structure and add a function to initialize it.
	
	       * FLEX_BG feature don't be required in read-only mode. However, I add a
	         data structure and a function into ext2fs.
	
	       * Now ext2fs can read ext4 file system, which is with some features:
	               + HAS_JOURNAL (NOT support this feature. It just can read data when file system
	                              with this feature.)
	               + FILETYPE
	               + SPARSE_SUPER
	               + HUGE_FILE
	               + EXTENTS (NOW it just can read data from ext4 extents.)
	               + DIR_NLINK
	               + UNINIT_BG (IT don't be required in read-only mode.)
	               + FLEX_BG (IT dont't be required in read-only mode.)

Affected files ...

.. //depot/projects/soc2010/ext4fs/src/sys/fs/ext2fs/ext2_vfsops.c#8 edit
.. //depot/projects/soc2010/ext4fs/src/sys/fs/ext2fs/ext2fs.h#4 edit

Differences ...

==== //depot/projects/soc2010/ext4fs/src/sys/fs/ext2fs/ext2_vfsops.c#8 (text+ko) ====

@@ -51,6 +51,9 @@
 #include <sys/malloc.h>
 #include <sys/stat.h>
 #include <sys/mutex.h>
+#include <sys/types.h>
+
+#include <machine/atomic.h>
 
 #include <geom/geom.h>
 #include <geom/geom_vfs.h>
@@ -94,6 +97,8 @@
 		    int ronly);
 static int	compute_sb_data(struct vnode * devvp,
 		    struct ext2fs * es, struct m_ext2fs * fs);
+static int      ext4_init_fg(struct m_ext2fs *);
+static int      find_most_set_bit(int64_t n);
 
 static const char *ext2_opts[] = { "from", "export", "acls", "noexec",
     "noatime", "union", "suiddir", "multilabel", "nosymfollow",
@@ -349,6 +354,7 @@
 	fs->e2fs_ipb = fs->e2fs_bsize / EXT2_INODE_SIZE(fs);
 	fs->e2fs_itpg = fs->e2fs_ipg /fs->e2fs_ipb;
 	fs->e2fs_descpb = fs->e2fs_bsize / sizeof (struct ext2_gd);
+        fs->e2fs_descpbbits = find_most_set_bit(fs->e2fs_descpb);
 	/* s_resuid / s_resgid ? */
 	fs->e2fs_gcount = (((int64_t)(es->e2fs_bcount_hi) << 32 | es->e2fs_bcount_lo)
             - es->e2fs_first_dblock + EXT2_BLOCKS_PER_GROUP(fs) - 1) /
@@ -384,6 +390,10 @@
 		brelse(bp);
 		bp = NULL;
 	}
+
+        /* initialize flex groups */
+        ext4_init_fg(fs);
+
 	fs->e2fs_total_dir = 0;
 	for (i=0; i < fs->e2fs_gcount; i++){
 		fs->e2fs_total_dir += (fs->e2fs_gd[i].ext2bgd_ndirs_lo);
@@ -398,6 +408,71 @@
 }
 
 /*
+ * Initialize flex groups data structure.
+ */
+static int
+ext4_init_fg(struct m_ext2fs *fs)
+{
+        struct ext2fs *es = fs->e2fs;
+        int i, gpf = 0;
+        unsigned int fgcount, fg;
+        long nifree, nbfree, ndirs;
+
+        fs->e2fs_log_gpf = es->e2fs_log_gpf;
+        gpf = 1 << fs->e2fs_log_gpf;
+
+        if (gpf < 2) {
+                fs->e2fs_log_gpf = 0;
+                return (0);
+        }
+
+        fgcount = ((fs->e2fs_gcount + gpf - 1) +
+            ((es->e2fs_reserved_ngdb + 1) << fs->e2fs_descpbbits)) / gpf;
+
+        fs->e2fs_fg = malloc(fgcount * sizeof(struct ext4_flex_groups),
+            M_EXT2MNT, M_WAITOK | M_ZERO);
+
+        for (i = 0; i < fs->e2fs_gcount; i++) {
+                nifree = 0;
+                nbfree = 0;
+                ndirs = 0;
+                fg = i >> fs->e2fs_log_gpf;
+
+                /* XXX: need to support 64 bits. */
+                nifree = fs->e2fs_gd[i].ext2bgd_nifree_lo;
+                nbfree = fs->e2fs_gd[i].ext2bgd_nbfree_lo;
+                ndirs = fs->e2fs_gd[i].ext2bgd_ndirs_lo;
+
+                atomic_add_long(&fs->e2fs_fg[fg].e2fg_nifree, nifree);
+                atomic_add_long(&fs->e2fs_fg[fg].e2fg_nbfree, nbfree);
+                atomic_add_long(&fs->e2fs_fg[fg].e2fg_ndirs, ndirs);
+        }
+
+        return (0);
+}
+
+/*
+ * Find most significant set bit.
+ *
+ * TODO: Maybe it need to rewrite by assembly language for
+ * improving the performance.
+ */
+static int
+find_most_set_bit(int64_t n)
+{
+        int64_t num, i;
+        unsigned int pos, res = 0;
+
+        for (num = 1; num <= n; num++) {
+                for (i = (num >> 1), pos = 0; i != 0; pos++)
+                        i >>= 1;
+                res = pos;
+        }
+
+        return res;
+}
+
+/*
  * Reload all incore data for a filesystem (used after running fsck on
  * the root filesystem and finding things to fix). The filesystem must
  * be mounted read-only.
@@ -688,6 +763,7 @@
 	PICKUP_GIANT();
 	vrele(ump->um_devvp);
 	mtx_destroy(&fs->e2fs_rsv_lock);
+        free(fs->e2fs_fg, M_EXT2MNT);
 	free(fs->e2fs_gd, M_EXT2MNT);
 	free(fs->e2fs_contigdirs, M_EXT2MNT);
 	free(fs->e2fs, M_EXT2MNT);

==== //depot/projects/soc2010/ext4fs/src/sys/fs/ext2fs/ext2fs.h#4 (text+ko) ====

@@ -40,6 +40,7 @@
 #include <sys/types.h>
 #include <sys/lock.h>
 #include <fs/ext2fs/ext2_rsv_win.h>
+#include <machine/atomic.h>
 
 /*
  * Special inode numbers
@@ -92,6 +93,15 @@
  */
 #define MAXMNTLEN 512
 
+/* ext4 flex block group data structure */
+struct ext4_flex_groups {
+        long e2fg_nifree;
+        long e2fg_nbfree;
+        long e2fg_ndirs;
+};
+
+#define EXT4_FLEX_ALLOC_DIR_SIZE 4
+
 /*
  * Super block for an ext2fs file system.
  */
@@ -203,10 +213,14 @@
 	uint8_t	*e2fs_contigdirs;
 	char e2fs_wasvalid;       /* valid at mount time */
 	off_t e2fs_maxfilesize;
-	struct ext2_gd *e2fs_gd; /* Group Descriptors */
+	struct ext2_gd *e2fs_gd;  /* Group Descriptors */
 
 	struct mtx e2fs_rsv_lock;               /* Protect reservation window RB tree */
 	struct ext2_rsv_win_tree e2fs_rsv_tree; /* Reservation window index */
+
+        u_int8_t e2fs_log_gpf;    /* FLEX_BG group size */
+        int      e2fs_descpbbits;
+        struct ext4_flex_groups *e2fs_fg;
 };
 
 /*


More information about the p4-projects mailing list