+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
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) {
}
gdp = ¤t_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"
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:
+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.
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;
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,
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.
had_problem++;
do_counts:
- if (!bitmap) {
+ if (!bitmap && !skip_group) {
group_free++;
free_blocks++;
}
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)
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,
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;
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) ||
dir_array[group] = dirs_count;
group ++;
inodes = 0;
+ skip_group = 0;
group_free = 0;
dirs_count = 0;
if (ctx->progress)
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)
+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
"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,
+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,
__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
*
#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
#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
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 */
}
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;
}
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;
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) {
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) {
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) {
if (retval)
return EXT2_ET_INODE_BITMAP_WRITE;
}
+ skip_this_inode_bitmap:
inode_bitmap += inode_nbytes;
}
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;
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);
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);
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;
}
}
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)
+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
}
}
+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;
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 "),
dgrp_t i;
int num;
struct progress_struct progress;
+ int lazy_flag = 0;
if (quiet)
memset(&progress, 0, sizeof(progress));
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)
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;
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,
_("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);