Whamcloud - gitweb
Add support for EXT2_FEATURE_COMPAT_LAZY_BG
authorTheodore Ts'o <tytso@mit.edu>
Tue, 9 May 2006 00:17:26 +0000 (20:17 -0400)
committerTheodore Ts'o <tytso@mit.edu>
Tue, 9 May 2006 00:17:26 +0000 (20:17 -0400)
This feature is initially intended for testing purposes; it allows an
ext2/ext3 developer to create very large filesystems using sparse files
where most of the block groups are not initialized and so do not require
much disk space.  Eventually it could be used as a way of speeding up
mke2fs and e2fsck for large filesystem, but that would be best done by
adding an RO_COMPAT extension to the filesystem to allow the inode table
to be lazily initialized on a per-block basis, instead of being entirely initialized
or entirely unused on a per-blockgroup basis.

Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
15 files changed:
debugfs/ChangeLog
debugfs/debugfs.c
e2fsck/ChangeLog
e2fsck/pass5.c
lib/e2p/ChangeLog
lib/e2p/feature.c
lib/ext2fs/ChangeLog
lib/ext2fs/ext2_fs.h
lib/ext2fs/ext2fs.h
lib/ext2fs/inode.c
lib/ext2fs/rw_bitmaps.c
lib/ext2fs/swapfs.c
misc/ChangeLog
misc/dumpe2fs.c
misc/mke2fs.c

index a9fb8a4..0425d22 100644 (file)
@@ -1,3 +1,8 @@
+2006-05-08  Theodore Tso  <tytso@mit.edu>
+
+       * debugfs.c (do_show_super_stats): Print out the block group flags
+               if they are set.
+
 2006-04-27  Theodore Ts'o  <tytso@mit.edu>
 
        * htree.c (do_htree_dump, do_dx_hash), ls.c (do_list_dir): Add
index 12ef00c..25d52d7 100644 (file)
@@ -266,13 +266,26 @@ static void print_features(struct ext2_super_block * s, FILE *f)
        fputs("\n", f);
 }
 
+static void print_bg_opts(struct ext2_group_desc *gdp, int mask,
+                         const char *str, int *first, FILE *f)
+{
+       if (gdp->bg_flags & mask) {
+               if (*first) {
+                       fputs("           [", f);
+                       *first = 0;
+               } else
+                       fputs(", ", f);
+               fputs(str, f);
+       }
+}
+
 void do_show_super_stats(int argc, char *argv[])
 {
        dgrp_t  i;
        FILE    *out;
        struct ext2_group_desc *gdp;
        int     c, header_only = 0;
-       int     numdirs = 0;
+       int     numdirs = 0, first;
 
        reset_getopt();
        while ((c = getopt (argc, argv, "h")) != EOF) {
@@ -302,7 +315,7 @@ void do_show_super_stats(int argc, char *argv[])
        }
        
        gdp = &current_fs->group_desc[0];
-       for (i = 0; i < current_fs->group_desc_count; i++, gdp++)
+       for (i = 0; i < current_fs->group_desc_count; i++, gdp++) {
                fprintf(out, " Group %2d: block bitmap at %u, "
                        "inode bitmap at %u, "
                        "inode table at %u\n"
@@ -318,6 +331,14 @@ void do_show_super_stats(int argc, char *argv[])
                        gdp->bg_used_dirs_count,
                        gdp->bg_used_dirs_count != 1 ? "directories"
                                : "directory");
+               first = 1;
+               print_bg_opts(gdp, EXT2_BG_INODE_UNINIT, "Inode not init",
+                             &first, out);
+               print_bg_opts(gdp, EXT2_BG_BLOCK_UNINIT, "Block not init",
+                             &first, out);
+               if (!first)
+                       fputs("]\n", out);
+       }
        close_pager(out);
        return;
 print_usage:
index 3b408fa..545dafc 100644 (file)
@@ -1,3 +1,11 @@
+2006-05-08  Theodore Tso  <tytso@mit.edu>
+
+       * pass5.c (check_block_bitmaps, check_inode_bitmaps): Add support
+               for the lazy_bg feature; if the block group does not have
+               an initialized block or inode bitmaps/table, emulate what
+               the allocation bitmap would look like if no blocks or
+               inodes have been allocated.
+
 2006-03-27  Theodore Ts'o  <tytso@mit.edu>
 
        * e2fsck.8.in: Add badblocks(8) to the See Also section.
index e708fa4..eb3ebf0 100644 (file)
@@ -111,7 +111,7 @@ static void print_bitmap_problem(e2fsck_t ctx, int problem,
 static void check_block_bitmaps(e2fsck_t ctx)
 {
        ext2_filsys fs = ctx->fs;
-       blk_t   i;
+       blk_t   i, super;
        int     *free_array;
        int     group = 0;
        unsigned int    blocks = 0;
@@ -121,6 +121,8 @@ static void check_block_bitmaps(e2fsck_t ctx)
        struct problem_context  pctx;
        int     problem, save_problem, fixit, had_problem;
        errcode_t       retval;
+       int             lazy_bg = 0;
+       int             skip_group = 0;
        
        clear_problem_context(&pctx);
        free_array = (int *) e2fsck_allocate_memory(ctx,
@@ -156,19 +158,45 @@ static void check_block_bitmaps(e2fsck_t ctx)
                return;
        }
                       
+       if (EXT2_HAS_COMPAT_FEATURE(fs->super, 
+                                   EXT2_FEATURE_COMPAT_LAZY_BG))
+               lazy_bg++;
+
 redo_counts:
        had_problem = 0;
        save_problem = 0;
        pctx.blk = pctx.blk2 = NO_BLK;
+       if (lazy_bg && (fs->group_desc[group].bg_flags &
+                       EXT2_BG_BLOCK_UNINIT))
+               skip_group++;
+       super = fs->super->s_first_data_block;
        for (i = fs->super->s_first_data_block;
             i < fs->super->s_blocks_count;
             i++) {
                actual = ext2fs_fast_test_block_bitmap(ctx->block_found_map, i);
-               bitmap = ext2fs_fast_test_block_bitmap(fs->block_map, i);
+
+               if (skip_group) {
+                       if ((i >= super) &&
+                           (i <= super + fs->desc_blocks) &&
+                           ext2fs_bg_has_super(fs, group))
+                               bitmap = 1;
+                       else if (i == fs->group_desc[group].bg_block_bitmap)
+                               bitmap = 1;
+                       else if (i == fs->group_desc[group].bg_inode_bitmap)
+                               bitmap = 1;
+                       else if (i >= fs->group_desc[group].bg_inode_table &&
+                                (i < fs->group_desc[group].bg_inode_table
+                                 + fs->inode_blocks_per_group))
+                               bitmap = 1;
+                       else
+                               bitmap = 0;
+                       actual = (actual != 0);
+               } else
+                       bitmap = ext2fs_fast_test_block_bitmap(fs->block_map, i);
                
                if (actual == bitmap)
                        goto do_counts;
-               
+
                if (!actual && bitmap) {
                        /*
                         * Block not used, but marked in use in the bitmap.
@@ -197,7 +225,7 @@ redo_counts:
                had_problem++;
                
        do_counts:
-               if (!bitmap) {
+               if (!bitmap && !skip_group) {
                        group_free++;
                        free_blocks++;
                }
@@ -208,10 +236,17 @@ redo_counts:
                        group ++;
                        blocks = 0;
                        group_free = 0;
+                       skip_group = 0;
+                       super += fs->super->s_blocks_per_group;
                        if (ctx->progress)
                                if ((ctx->progress)(ctx, 5, group,
                                                    fs->group_desc_count*2))
                                        return;
+                       if (lazy_bg &&
+                           (i != fs->super->s_blocks_count-1) &&
+                           (fs->group_desc[group].bg_flags &
+                            EXT2_BG_BLOCK_UNINIT))
+                               skip_group++;
                }
        }
        if (pctx.blk != NO_BLK)
@@ -286,6 +321,8 @@ static void check_inode_bitmaps(e2fsck_t ctx)
        errcode_t       retval;
        struct problem_context  pctx;
        int             problem, save_problem, fixit, had_problem;
+       int             lazy_bg = 0;
+       int             skip_group = 0;
        
        clear_problem_context(&pctx);
        free_array = (int *) e2fsck_allocate_memory(ctx,
@@ -321,14 +358,24 @@ static void check_inode_bitmaps(e2fsck_t ctx)
                return;
        }
 
+       if (EXT2_HAS_COMPAT_FEATURE(fs->super, 
+                                   EXT2_FEATURE_COMPAT_LAZY_BG))
+               lazy_bg++;
+
 redo_counts:
        had_problem = 0;
        save_problem = 0;
        pctx.ino = pctx.ino2 = 0;
+       if (lazy_bg && (fs->group_desc[group].bg_flags &
+                       EXT2_BG_INODE_UNINIT))
+               skip_group++;
+
        for (i = 1; i <= fs->super->s_inodes_count; i++) {
                actual = ext2fs_fast_test_inode_bitmap(ctx->inode_used_map, i);
-               bitmap = ext2fs_fast_test_inode_bitmap(fs->inode_map, i);
-               
+               if (skip_group) 
+                       bitmap = 0;
+               else
+                       bitmap = ext2fs_fast_test_inode_bitmap(fs->inode_map, i);
                if (actual == bitmap)
                        goto do_counts;
                
@@ -360,12 +407,12 @@ redo_counts:
                had_problem++;
                
 do_counts:
-               if (!bitmap) {
-                       group_free++;
-                       free_inodes++;
-               } else {
+               if (bitmap) {
                        if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, i))
                                dirs_count++;
+               } else if (!skip_group) {
+                       group_free++;
+                       free_inodes++;
                }
                inodes++;
                if ((inodes == fs->super->s_inodes_per_group) ||
@@ -374,6 +421,7 @@ do_counts:
                        dir_array[group] = dirs_count;
                        group ++;
                        inodes = 0;
+                       skip_group = 0;
                        group_free = 0;
                        dirs_count = 0;
                        if (ctx->progress)
@@ -381,6 +429,11 @@ do_counts:
                                            group + fs->group_desc_count,
                                            fs->group_desc_count*2))
                                        return;
+                       if (lazy_bg &&
+                           (i != fs->super->s_inodes_count) &&
+                           (fs->group_desc[group].bg_flags &
+                            EXT2_BG_INODE_UNINIT))
+                               skip_group++;
                }
        }
        if (pctx.ino)
index 358e108..641e7d8 100644 (file)
@@ -1,3 +1,7 @@
+2006-05-08  Theodore Tso  <tytso@mit.edu>
+
+       * feature.c: Add support for EXT2_FEATURE_COMPAT_LAZY_BG feature.
+
 2006-04-18  Theodore Ts'o  <tytso@mit.edu>
 
        * uuid.c (e2p_is_null_uuid): Fix really stupid bug which could
index 50f1ef3..e8f6729 100644 (file)
@@ -35,6 +35,8 @@ static struct feature feature_list[] = {
                        "dir_index" },
        {       E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_RESIZE_INODE,
                        "resize_inode" },
+       {       E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_LAZY_BG,
+                       "lazy_bg" },
        {       E2P_FEATURE_RO_INCOMPAT, EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER,
                        "sparse_super" },
        {       E2P_FEATURE_RO_INCOMPAT, EXT2_FEATURE_RO_COMPAT_LARGE_FILE,
index 7da3fe2..512ef3f 100644 (file)
@@ -1,3 +1,29 @@
+2006-05-08  Theodore Tso  <tytso@mit.edu>
+
+       * rw_bitmaps.c (write_bitmaps, read_bitmaps): Added support for
+               lazy blockgroups.  If a block group has flags indicating
+               that its block or inode data structures have not been
+               initialized, skip reading or writing that portion of the
+               bitmap.
+
+       * inode.c (ext2fs_open_inode_scan, ext2fs_read_inode_full): When
+               scanning a filesystem with lazy blockgroups, skip
+               uninitialized portions of the inode table when iterating
+               over the block group.
+
+       * swapfs.c (ext2fs_swap_group_desc): Byte swap the bg_flags field.
+
+       * ext2fs.h: Define the a new internal flag, EXT2_SF_DO_LAZY, so
+               that the inode interator knows compat_lazy_bg feature is
+               enabled.  Declare that this version of e2fsprogs supports
+               the EXT2_FEATURE_COMPAY_LAZY_BG feature.
+
+       * ext2_fs.h (struct ext2_group_desc): Use the bg_pad field for
+               bg_flags, and define the flags EXT2_BG_INODE_UNINIT and
+               EXT2_BG_BLOCK_UNINIT.  These flags are only honored if
+               EXT2_FEATURE_COMPAT_LAZY_BG feature is enabled (also
+               added).
+
 2006-04-23  Theodore Ts'o  <tytso@mit.edu>
 
        * rw_bitmaps.c (write_bitmaps, ext2fs_write_inode_bitmap,
index e427add..1cfbc35 100644 (file)
@@ -143,10 +143,13 @@ struct ext2_group_desc
        __u16   bg_free_blocks_count;   /* Free blocks count */
        __u16   bg_free_inodes_count;   /* Free inodes count */
        __u16   bg_used_dirs_count;     /* Directories count */
-       __u16   bg_pad;
+       __u16   bg_flags;
        __u32   bg_reserved[3];
 };
 
+#define EXT2_BG_INODE_UNINIT   0x0001 /* Inode table/bitmap not initialized */
+#define EXT2_BG_BLOCK_UNINIT   0x0002 /* Block bitmap not initialized */
+
 /*
  * Data structures used by the directory indexing feature
  *
@@ -568,6 +571,7 @@ struct ext2_super_block {
 #define EXT2_FEATURE_COMPAT_EXT_ATTR           0x0008
 #define EXT2_FEATURE_COMPAT_RESIZE_INODE       0x0010
 #define EXT2_FEATURE_COMPAT_DIR_INDEX          0x0020
+#define EXT2_FEATURE_COMPAT_LAZY_BG            0x0040
 
 #define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER    0x0001
 #define EXT2_FEATURE_RO_COMPAT_LARGE_FILE      0x0002
index c3d0428..8618fe2 100644 (file)
@@ -341,6 +341,7 @@ typedef struct ext2_struct_inode_scan *ext2_inode_scan;
 #define EXT2_SF_BAD_INODE_BLK  0x0002
 #define EXT2_SF_BAD_EXTRA_BYTES        0x0004
 #define EXT2_SF_SKIP_MISSING_ITABLE    0x0008
+#define EXT2_SF_DO_LAZY                0x0010
 
 /*
  * ext2fs_check_if_mounted flags
@@ -437,6 +438,7 @@ typedef struct ext2_icount *ext2_icount_t;
                                         EXT3_FEATURE_COMPAT_HAS_JOURNAL|\
                                         EXT2_FEATURE_COMPAT_RESIZE_INODE|\
                                         EXT2_FEATURE_COMPAT_DIR_INDEX|\
+                                        EXT2_FEATURE_COMPAT_LAZY_BG|\
                                         EXT2_FEATURE_COMPAT_EXT_ATTR)
 
 /* This #ifdef is temporary until compression is fully supported */
index 222568e..8d528b4 100644 (file)
@@ -164,6 +164,9 @@ errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks,
        }
        if (scan->fs->badblocks && scan->fs->badblocks->num)
                scan->scan_flags |= EXT2_SF_CHK_BADBLOCKS;
+       if (EXT2_HAS_COMPAT_FEATURE(fs->super, 
+                                   EXT2_FEATURE_COMPAT_LAZY_BG))
+               scan->scan_flags |= EXT2_SF_DO_LAZY;
        *ret_scan = scan;
        return 0;
 }
@@ -407,9 +410,13 @@ errcode_t ext2fs_get_next_inode_full(ext2_inode_scan scan, ext2_ino_t *ino,
                        return retval;
        }
        /*
-        * This is done outside the above if statement so that the
-        * check can be done for block group #0.
+        * These checks are done outside the above if statement so 
+        * they can be done for block group #0.
         */
+       if ((scan->scan_flags & EXT2_SF_DO_LAZY) &&
+           (scan->fs->group_desc[scan->current_group].bg_flags &
+            EXT2_BG_INODE_UNINIT))
+               goto force_new_group;
        if (scan->current_block == 0) {
                if (scan->scan_flags & EXT2_SF_SKIP_MISSING_ITABLE) {
                        goto force_new_group;
index 7ab0a4d..cb470b8 100644 (file)
@@ -60,12 +60,16 @@ static errcode_t write_bitmaps(ext2_filsys fs, int do_inode, int do_block)
        errcode_t       retval;
        char            *block_bitmap, *inode_bitmap;
        char            *block_buf, *inode_buf;
+       int             lazy_flag = 0;
        blk_t           blk;
 
        EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
 
        if (!(fs->flags & EXT2_FLAG_RW))
                return EXT2_ET_RO_FILSYS;
+       if (EXT2_HAS_COMPAT_FEATURE(fs->super, 
+                                   EXT2_FEATURE_COMPAT_LAZY_BG))
+               lazy_flag = 1;
        inode_nbytes = block_nbytes = 0;
        block_bitmap = inode_bitmap = 0;
        if (do_block) {
@@ -89,6 +93,10 @@ static errcode_t write_bitmaps(ext2_filsys fs, int do_inode, int do_block)
        for (i = 0; i < fs->group_desc_count; i++) {
                if (!block_bitmap || !do_block)
                        goto skip_block_bitmap;
+
+               if (lazy_flag && fs->group_desc[i].bg_flags &
+                   EXT2_BG_BLOCK_UNINIT) 
+                       goto skip_this_block_bitmap;
  
                memcpy(block_buf, block_bitmap, block_nbytes);
                if (i == fs->group_desc_count - 1) {
@@ -113,12 +121,17 @@ static errcode_t write_bitmaps(ext2_filsys fs, int do_inode, int do_block)
                        if (retval)
                                return EXT2_ET_BLOCK_BITMAP_WRITE;
                }
+       skip_this_block_bitmap:
                block_bitmap += block_nbytes;
        skip_block_bitmap:
 
                if (!inode_bitmap || !do_inode)
                        continue;
 
+               if (lazy_flag && fs->group_desc[i].bg_flags &
+                   EXT2_BG_INODE_UNINIT) 
+                       goto skip_this_inode_bitmap;
                memcpy(inode_buf, inode_bitmap, inode_nbytes);
                blk = fs->group_desc[i].bg_inode_bitmap;
                if (blk) {
@@ -133,6 +146,7 @@ static errcode_t write_bitmaps(ext2_filsys fs, int do_inode, int do_block)
                        if (retval)
                                return EXT2_ET_INODE_BITMAP_WRITE;
                }
+       skip_this_inode_bitmap:
                inode_bitmap += inode_nbytes;
 
        }
@@ -155,12 +169,17 @@ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block)
        errcode_t retval;
        int block_nbytes = (int) EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
        int inode_nbytes = (int) EXT2_INODES_PER_GROUP(fs->super) / 8;
+       int lazy_flag = 0;
        blk_t   blk;
 
        EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
 
        fs->write_bitmaps = ext2fs_write_bitmaps;
 
+       if (EXT2_HAS_COMPAT_FEATURE(fs->super, 
+                                   EXT2_FEATURE_COMPAT_LAZY_BG))
+               lazy_flag = 1;
+
        retval = ext2fs_get_mem(strlen(fs->device_name) + 80, &buf);
        if (retval)
                return retval;
@@ -209,6 +228,9 @@ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block)
        for (i = 0; i < fs->group_desc_count; i++) {
                if (block_bitmap) {
                        blk = fs->group_desc[i].bg_block_bitmap;
+                       if (lazy_flag && fs->group_desc[i].bg_flags &
+                           EXT2_BG_BLOCK_UNINIT)
+                               blk = 0;
                        if (blk) {
                                retval = io_channel_read_blk(fs->io, blk,
                                             -block_nbytes, block_bitmap);
@@ -222,11 +244,14 @@ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block)
                                        ext2fs_swap_bitmap(fs, block_bitmap, block_nbytes);
 #endif
                        } else
-                               memset(block_bitmap, 0, block_nbytes);
+                               memset(block_bitmap, 0xff, block_nbytes);
                        block_bitmap += block_nbytes;
                }
                if (inode_bitmap) {
                        blk = fs->group_desc[i].bg_inode_bitmap;
+                       if (lazy_flag && fs->group_desc[i].bg_flags &
+                           EXT2_BG_INODE_UNINIT)
+                               blk = 0;
                        if (blk) {
                                retval = io_channel_read_blk(fs->io, blk,
                                             -inode_nbytes, inode_bitmap);
@@ -240,7 +265,7 @@ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block)
                                        ext2fs_swap_bitmap(fs, inode_bitmap, inode_nbytes);
 #endif
                        } else
-                               memset(inode_bitmap, 0, inode_nbytes);
+                               memset(inode_bitmap, 0xff, inode_nbytes);
                        inode_bitmap += inode_nbytes;
                }
        }
index 9081701..a4c6698 100644 (file)
@@ -78,6 +78,7 @@ void ext2fs_swap_group_desc(struct ext2_group_desc *gdp)
        gdp->bg_free_blocks_count = ext2fs_swab16(gdp->bg_free_blocks_count);
        gdp->bg_free_inodes_count = ext2fs_swab16(gdp->bg_free_inodes_count);
        gdp->bg_used_dirs_count = ext2fs_swab16(gdp->bg_used_dirs_count);
+       gdp->bg_flags = ext2fs_swab16(gdp->bg_flags);
 }
 
 void ext2fs_swap_ext_attr(char *to, char *from, int bufsize, int has_header)
index 605928a..0cb0389 100644 (file)
@@ -1,3 +1,14 @@
+2006-05-08  Theodore Tso  <tytso@mit.edu>
+
+       * mke2fs.c (write_inode_tables, setup_lazy_bg, main): Add support
+               for the COMPAT_LAZY_BG feature.  This is currently
+               intended for debugging purposes only, as a way to create
+               very large filesystems stored on sparse files for testing
+               purposes.
+
+       * dumpe2fs.c (list_desc): Print out the block group flags if they
+               are set.
+
 2006-04-22  Theodore Ts'o  <tytso@mit.edu>
 
        * filefrag.c: Make filefrag 32-bit clean, so that it works on 
index 2e42cb3..58c9869 100644 (file)
@@ -96,6 +96,36 @@ static void print_free (unsigned long group, char * bitmap,
                }
 }
 
+static void print_bg_opt(int bg_flags, int mask,
+                         const char *str, int *first)
+{
+       if (bg_flags & mask) {
+               if (*first) {
+                       fputs(" [", stdout);
+                       *first = 0;
+               } else
+                       fputs(", ", stdout);
+               fputs(str, stdout);
+       }
+}
+static void print_bg_opts(ext2_filsys fs, dgrp_t i)
+{
+       int first = 1, bg_flags;
+
+       if (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_LAZY_BG)
+               bg_flags = fs->group_desc[i].bg_flags;
+       else
+               bg_flags = 0;
+
+       print_bg_opt(bg_flags, EXT2_BG_INODE_UNINIT, "Inode not init",
+                    &first);
+       print_bg_opt(bg_flags, EXT2_BG_BLOCK_UNINIT, "Block not init",
+                    &first);
+       if (!first)
+               fputc(']', stdout);
+       fputc('\n', stdout);
+}
+
 static void list_desc (ext2_filsys fs)
 {
        unsigned long i;
@@ -130,7 +160,8 @@ static void list_desc (ext2_filsys fs)
                        next_blk = fs->super->s_blocks_count;
                printf (_("Group %lu: (Blocks "), i);
                print_range(group_blk, next_blk - 1);
-               fputs(")\n", stdout);
+               fputs(")", stdout);
+               print_bg_opts(fs, i);
                has_super = ((i==0) || super_blk);
                if (has_super) {
                        printf (_("  %s superblock at "),
index 6fd5540..9f23ea5 100644 (file)
@@ -403,6 +403,7 @@ static void write_inode_tables(ext2_filsys fs)
        dgrp_t          i;
        int             num;
        struct progress_struct progress;
+       int             lazy_flag = 0;
 
        if (quiet)
                memset(&progress, 0, sizeof(progress));
@@ -410,18 +411,25 @@ static void write_inode_tables(ext2_filsys fs)
                progress_init(&progress, _("Writing inode tables: "),
                              fs->group_desc_count);
 
+       if (EXT2_HAS_COMPAT_FEATURE(fs->super, 
+                                   EXT2_FEATURE_COMPAT_LAZY_BG))
+               lazy_flag = 1;
+
        for (i = 0; i < fs->group_desc_count; i++) {
                progress_update(&progress, i);
                
                blk = fs->group_desc[i].bg_inode_table;
                num = fs->inode_blocks_per_group;
 
-               retval = zero_blocks(fs, blk, num, 0, &blk, &num);
-               if (retval) {
-                       fprintf(stderr, _("\nCould not write %d blocks "
-                               "in inode table starting at %u: %s\n"),
-                               num, blk, error_message(retval));
-                       exit(1);
+               if (!(lazy_flag &&
+                     (fs->group_desc[i].bg_flags & EXT2_BG_INODE_UNINIT))) {
+                       retval = zero_blocks(fs, blk, num, 0, &blk, &num);
+                       if (retval) {
+                               fprintf(stderr, _("\nCould not write %d "
+                               "blocks in inode table starting at %u: %s\n"),
+                                       num, blk, error_message(retval));
+                               exit(1);
+                       }
                }
                if (sync_kludge) {
                        if (sync_kludge == 1)
@@ -434,6 +442,37 @@ static void write_inode_tables(ext2_filsys fs)
        progress_close(&progress);
 }
 
+static void setup_lazy_bg(ext2_filsys fs)
+{
+       dgrp_t i;
+       int blks;
+       struct ext2_super_block *sb = fs->super;
+       struct ext2_group_desc *bg = fs->group_desc;
+
+       if (EXT2_HAS_COMPAT_FEATURE(fs->super, 
+                                   EXT2_FEATURE_COMPAT_LAZY_BG)) {
+               for (i = 0; i < fs->group_desc_count; i++, bg++) {
+                       if ((i == 0) ||
+                           (i == fs->group_desc_count-1))
+                               continue;
+                       if (bg->bg_free_inodes_count ==
+                           sb->s_inodes_per_group) {
+                               bg->bg_free_inodes_count = 0;
+                               bg->bg_flags |= EXT2_BG_INODE_UNINIT;
+                               sb->s_free_inodes_count -= 
+                                       sb->s_inodes_per_group;
+                       }
+                       blks = ext2fs_super_and_bgd_loc(fs, i, 0, 0, 0, 0);
+                       if (bg->bg_free_blocks_count == blks) {
+                               bg->bg_free_blocks_count = 0;
+                               bg->bg_flags |= EXT2_BG_BLOCK_UNINIT;
+                               sb->s_free_blocks_count -= blks;
+                       }
+               }
+       }
+}
+
+
 static void create_root_dir(ext2_filsys fs)
 {
        errcode_t       retval;
@@ -814,7 +853,8 @@ static void parse_extended_opts(struct ext2_super_block *param,
 static __u32 ok_features[3] = {
        EXT3_FEATURE_COMPAT_HAS_JOURNAL |
                EXT2_FEATURE_COMPAT_RESIZE_INODE |
-               EXT2_FEATURE_COMPAT_DIR_INDEX,  /* Compat */
+               EXT2_FEATURE_COMPAT_DIR_INDEX |
+               EXT2_FEATURE_COMPAT_LAZY_BG,    /* Compat */
        EXT2_FEATURE_INCOMPAT_FILETYPE|         /* Incompat */
                EXT3_FEATURE_INCOMPAT_JOURNAL_DEV|
                EXT2_FEATURE_INCOMPAT_META_BG,
@@ -1557,6 +1597,7 @@ int main (int argc, char *argv[])
                                _("while zeroing block %u at end of filesystem"),
                                ret_blk);
                }
+               setup_lazy_bg(fs);
                write_inode_tables(fs);
                create_root_dir(fs);
                create_lost_and_found(fs);