mke2fs: Disentangle lazy_bg from uninit_bg's lazy inode table initialization

Instead of using -O lazy_bg,uninit_bg as the way of requesting that
the inode table be lazy unitialized, use the parameter
lazy_itable_init, which can either be set via mke2fs's -E option, or
via /etc/mke2fs.conf.

Also fix some random problems in mke2fs's man page, including
documenting the extent feature, which had been missing.

Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
diff --git a/misc/mke2fs.8.in b/misc/mke2fs.8.in
index e12b42e..1e9a203 100644
--- a/misc/mke2fs.8.in
+++ b/misc/mke2fs.8.in
@@ -189,7 +189,7 @@
 filesystem blocks. This is the number of blocks read or written to disk
 before moving to next disk. This mostly affects placement of filesystem
 metadata like bitmaps at
-.BR mke2fs (2)
+.B mke2fs
 time to avoid placing them on a single disk, which can hurt the performanace.
 It may also be used by block allocator.
 .TP
@@ -205,6 +205,15 @@
 Reserve enough space so that the block group descriptor table can grow
 to support a filesystem that has max-online-resize blocks.
 .TP
+.B lazy_itable_init= \fI<0 to disable, 1 to enable>
+If enabled and the uninit_bg feature is enabled, the inode table will
+not fully initialized by 
+.BR mke2fs .
+This speeds up filesystem
+initialization noitceably, but it requires the kernel to finish
+initializing the filesystem in the background when the filesystem is
+first mounted.
+.TP
 .B test_fs
 Set a flag in the filesystem superblock indicating that it may be
 mounted using experimental kernel code, such as the ext4dev filesystem.
@@ -449,11 +458,20 @@
 @JDEV@must be created with the same
 @JDEV@block size as the filesystems that will be using it.
 .TP
+.B extent
+Instead of using the indirect block scheme for storing the location of
+data blocks in an inode, use extents instead.  This is a much more
+efficient encoding which speeds up filesystem access, especially for
+large files.
+.TP
 .B uninit_bg
-Create a filesystem without initializing all of the groups.  This speeds
-up filesystem creation time noticably, and can also reduce
+Create a filesystem without initializing all of the block groups.  This 
+feature also enables checksums and highest-inode-used statistics in each
+blockgroup.  This feature can
+speed up filesystem creation time noticably (if lazy_itable_init is
+enabled), and can also reduce
 .BR e2fsck time
-dramatically.  This feature is only supported by the ext4 filesystem in
+dramatically.  It is only supported by the ext4 filesystem in
 recent Linux kernels.
 .TP
 .B resize_inode
@@ -523,7 +541,7 @@
 .B mke2fs
 will pick a single default usage type based on the size of the filesystem to
 be created.  If the filesystem size is less than or equal to 3 megabytes,
-.BR mke2fs (8)
+.B mke2fs
 will use the filesystem type
 .IR floppy .
 If the filesystem size is greater than 3 but less than or equal to
diff --git a/misc/mke2fs.c b/misc/mke2fs.c
index a58b116..9940d3f 100644
--- a/misc/mke2fs.c
+++ b/misc/mke2fs.c
@@ -77,6 +77,7 @@
 int	noaction;
 int	journal_size;
 int	journal_flags;
+int	lazy_itable_init;
 char	*bad_blocks_filename;
 __u32	fs_stride;
 
@@ -399,14 +400,13 @@
 	return 0;
 }	
 
-static void write_inode_tables(ext2_filsys fs)
+static void write_inode_tables(ext2_filsys fs, int lazy_flag)
 {
 	errcode_t	retval;
 	blk_t		blk;
 	dgrp_t		i;
 	int		num;
 	struct progress_struct progress;
-	int		lazy_flag = 0;
 
 	if (quiet)
 		memset(&progress, 0, sizeof(progress));
@@ -886,6 +886,13 @@
 			}
 		} else if (!strcmp(token, "test_fs")) {
 			param->s_flags |= EXT2_FLAGS_TEST_FILESYS;
+		} else if (!strcmp(token, "lazy_itable_init")) {
+			if (!arg) {
+				r_usage++;
+				badopt = token;
+				continue;
+			}
+			lazy_itable_init = strtoul(arg, &p, 0);
 		} else {
 			r_usage++;
 			badopt = token;
@@ -899,8 +906,9 @@
 			"Valid extended options are:\n"
 			"\tstride=<RAID per-disk data chunk in blocks>\n"
 			"\tstripe-width=<RAID stride * data disks in blocks>\n"
-			"\tresize=<resize maximum size in blocks>\n\n"
-			"\ttest_fs\n"),
+			"\tresize=<resize maximum size in blocks>\n"
+			"\tlazy_itable_init=<0 to disable, 1 to enable>\n"
+			"\ttest_fs\n\n"),
 			badopt ? badopt : "");
 		free(buf);
 		exit(1);
@@ -1120,6 +1128,16 @@
 	return ret;
 }
 
+static int get_bool_from_profile(char **fs_types, const char *opt, int def_val)
+{
+	int ret;
+	char **cpp;
+
+	profile_get_boolean(profile, "defaults", opt, 0, def_val, &ret);
+	for (cpp = fs_types; *cpp; cpp++)
+		profile_get_boolean(profile, "fs_types", *cpp, opt, ret, &ret);
+	return ret;
+}
 
 extern const char *mke2fs_default_profile;
 static const char *default_files[] = { "<default>", 0 };
@@ -1645,6 +1663,9 @@
 		int_log2(blocksize >> EXT2_MIN_BLOCK_LOG_SIZE);
 
 	blocksize = EXT2_BLOCK_SIZE(&fs_param);
+
+	lazy_itable_init = get_bool_from_profile(fs_types, 
+						 "lazy_itable_init", 0);
 	
 	if (extended_opts)
 		parse_extended_opts(&fs_param, extended_opts);
@@ -1660,6 +1681,17 @@
 		exit(1);
 	}
 
+	if (EXT2_HAS_RO_COMPAT_FEATURE(&fs_param,
+				       EXT4_FEATURE_RO_COMPAT_GDT_CSUM) &&
+	    EXT2_HAS_COMPAT_FEATURE(&fs_param, EXT2_FEATURE_COMPAT_LAZY_BG)) {
+		com_err(program_name, 0,
+			_("lazy_bg and uninit_bg can not be enabled "
+			  "at the same time;\n\t"
+			  "use -E lazy_itable_init=1 to defer zeroing the "
+			  "inode table."));
+		exit(1);
+	}
+
 	if (fs_param.s_blocks_per_group) {
 		if (fs_param.s_blocks_per_group < 256 ||
 		    fs_param.s_blocks_per_group > 8 * (unsigned) blocksize) {
@@ -1886,7 +1918,7 @@
 				ret_blk);
 		}
 		setup_lazy_bg(fs);
-		write_inode_tables(fs);
+		write_inode_tables(fs, lazy_itable_init);
 		create_root_dir(fs);
 		create_lost_and_found(fs);
 		reserve_inodes(fs);
diff --git a/misc/mke2fs.conf.5.in b/misc/mke2fs.conf.5.in
index 1fc16e7..6734bf3 100644
--- a/misc/mke2fs.conf.5.in
+++ b/misc/mke2fs.conf.5.in
@@ -282,6 +282,18 @@
 This relation specifies the default blocksize if the user does not
 specify a blocksize on the command line.
 .TP
+.I lazy_itable_init
+This relation is a boolean which specifies whether the inode table should 
+be lazily initialized.  It only has meaning if the uninit_bg feature is
+enabled.  If lazy_itable_init is true and the uninit_bg feature is
+enabled,  the inode table will
+not fully initialized by 
+.BR mke2fs (8).
+This speeds up filesystem
+initialization noitceably, but it requires the kernel to finish
+initializing the filesystem in the background when the filesystem is
+first mounted.
+.TP
 .I inode_ratio
 This relation specifies the default inode ratio if the user does not
 specify one on the command line.