summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2006-05-08 20:17:26 -0400
committerTheodore Ts'o <tytso@mit.edu>2006-05-08 20:17:26 -0400
commitf5fa20078bfc05b554294fe9c5505375d7913e8c (patch)
treef51fd572f2a76eaab495e7559ba40dee09067dd2
parent49c6b4e9472f53c252126f1c9a5a6e9629967d1f (diff)
downloade2fsprogs-f5fa20078bfc05b554294fe9c5505375d7913e8c.tar.gz
Add support for EXT2_FEATURE_COMPAT_LAZY_BG
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>
-rw-r--r--debugfs/ChangeLog5
-rw-r--r--debugfs/debugfs.c25
-rw-r--r--e2fsck/ChangeLog8
-rw-r--r--e2fsck/pass5.c73
-rw-r--r--lib/e2p/ChangeLog4
-rw-r--r--lib/e2p/feature.c2
-rw-r--r--lib/ext2fs/ChangeLog26
-rw-r--r--lib/ext2fs/ext2_fs.h6
-rw-r--r--lib/ext2fs/ext2fs.h2
-rw-r--r--lib/ext2fs/inode.c11
-rw-r--r--lib/ext2fs/rw_bitmaps.c29
-rw-r--r--lib/ext2fs/swapfs.c1
-rw-r--r--misc/ChangeLog11
-rw-r--r--misc/dumpe2fs.c33
-rw-r--r--misc/mke2fs.c55
15 files changed, 266 insertions, 25 deletions
diff --git a/debugfs/ChangeLog b/debugfs/ChangeLog
index a9fb8a4d..0425d227 100644
--- a/debugfs/ChangeLog
+++ b/debugfs/ChangeLog
@@ -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
diff --git a/debugfs/debugfs.c b/debugfs/debugfs.c
index 12ef00c2..25d52d75 100644
--- a/debugfs/debugfs.c
+++ b/debugfs/debugfs.c
@@ -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:
diff --git a/e2fsck/ChangeLog b/e2fsck/ChangeLog
index 3b408fab..545dafcc 100644
--- a/e2fsck/ChangeLog
+++ b/e2fsck/ChangeLog
@@ -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.
diff --git a/e2fsck/pass5.c b/e2fsck/pass5.c
index e708fa41..eb3ebf02 100644
--- a/e2fsck/pass5.c
+++ b/e2fsck/pass5.c
@@ -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)
diff --git a/lib/e2p/ChangeLog b/lib/e2p/ChangeLog
index 358e108c..641e7d8d 100644
--- a/lib/e2p/ChangeLog
+++ b/lib/e2p/ChangeLog
@@ -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
diff --git a/lib/e2p/feature.c b/lib/e2p/feature.c
index 50f1ef3d..e8f6729d 100644
--- a/lib/e2p/feature.c
+++ b/lib/e2p/feature.c
@@ -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,
diff --git a/lib/ext2fs/ChangeLog b/lib/ext2fs/ChangeLog
index 7da3fe2e..512ef3f7 100644
--- a/lib/ext2fs/ChangeLog
+++ b/lib/ext2fs/ChangeLog
@@ -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,
diff --git a/lib/ext2fs/ext2_fs.h b/lib/ext2fs/ext2_fs.h
index e427addf..1cfbc358 100644
--- a/lib/ext2fs/ext2_fs.h
+++ b/lib/ext2fs/ext2_fs.h
@@ -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
diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
index c3d04289..8618fe26 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -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 */
diff --git a/lib/ext2fs/inode.c b/lib/ext2fs/inode.c
index 222568eb..8d528b44 100644
--- a/lib/ext2fs/inode.c
+++ b/lib/ext2fs/inode.c
@@ -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;
diff --git a/lib/ext2fs/rw_bitmaps.c b/lib/ext2fs/rw_bitmaps.c
index 7ab0a4db..cb470b8e 100644
--- a/lib/ext2fs/rw_bitmaps.c
+++ b/lib/ext2fs/rw_bitmaps.c
@@ -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;
}
}
diff --git a/lib/ext2fs/swapfs.c b/lib/ext2fs/swapfs.c
index 90817012..a4c66980 100644
--- a/lib/ext2fs/swapfs.c
+++ b/lib/ext2fs/swapfs.c
@@ -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)
diff --git a/misc/ChangeLog b/misc/ChangeLog
index 605928a9..0cb03895 100644
--- a/misc/ChangeLog
+++ b/misc/ChangeLog
@@ -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
diff --git a/misc/dumpe2fs.c b/misc/dumpe2fs.c
index 2e42cb3d..58c9869b 100644
--- a/misc/dumpe2fs.c
+++ b/misc/dumpe2fs.c
@@ -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 "),
diff --git a/misc/mke2fs.c b/misc/mke2fs.c
index 6fd55400..9f23ea5d 100644
--- a/misc/mke2fs.c
+++ b/misc/mke2fs.c
@@ -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);