From c046ac7f2e4c53e20cf1e909bbe511f91074b396 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sun, 20 Oct 2002 00:38:57 -0400 Subject: [PATCH] Add support for the meta_blockgroup filesystem format. --- e2fsck/pass1.c | 32 +++++++++++++---- lib/e2p/ChangeLog | 5 +++ lib/e2p/feature.c | 2 ++ lib/e2p/ls.c | 3 ++ lib/ext2fs/ChangeLog | 7 ++++ lib/ext2fs/closefs.c | 96 +++++++++++++++++++++++++++++++++++-------------- lib/ext2fs/ext2_fs.h | 6 ++-- lib/ext2fs/ext2fs.h | 4 +++ lib/ext2fs/initialize.c | 34 +++++++++++++++--- lib/ext2fs/openfs.c | 29 +++++++++++---- lib/ext2fs/swapfs.c | 1 + misc/ChangeLog | 6 ++++ misc/dumpe2fs.c | 28 +++++++++++++-- misc/e2image.c | 2 +- misc/mke2fs.c | 9 ++++- 15 files changed, 213 insertions(+), 51 deletions(-) diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c index 9849645..c685581 100644 --- a/e2fsck/pass1.c +++ b/e2fsck/pass1.c @@ -1793,7 +1793,7 @@ static void mark_table_blocks(e2fsck_t ctx) { ext2_filsys fs = ctx->fs; blk_t block, b; - int i,j; + int i, j, has_super, meta_bg, meta_bg_size; struct problem_context pctx; clear_problem_context(&pctx); @@ -1802,21 +1802,39 @@ static void mark_table_blocks(e2fsck_t ctx) for (i = 0; i < fs->group_desc_count; i++) { pctx.group = i; - if (ext2fs_bg_has_super(fs, i)) { + has_super = ext2fs_bg_has_super(fs, i); + if (has_super) /* * Mark this group's copy of the superblock */ ext2fs_mark_block_bitmap(ctx->block_found_map, block); - /* - * Mark this group's copy of the descriptors - */ - for (j = 0; j < fs->desc_blocks; j++) { - ext2fs_mark_block_bitmap(ctx->block_found_map, + meta_bg_size = (fs->blocksize / + sizeof (struct ext2_group_desc)); + meta_bg = i / meta_bg_size; + if (!(fs->super->s_feature_incompat & + EXT2_FEATURE_INCOMPAT_META_BG) || + (meta_bg < fs->super->s_first_meta_bg)) { + if (has_super) { + /* + * Mark this group's copy of the descriptors + */ + for (j = 0; j < fs->desc_blocks; j++) { + ext2fs_mark_block_bitmap(ctx->block_found_map, block + j + 1); + } } + } else { + if (has_super) + has_super = 1; + if (((i % meta_bg_size) == 0) || + ((i % meta_bg_size) == 1) || + ((i % meta_bg_size) == (meta_bg_size-1))) + ext2fs_mark_block_bitmap(ctx->block_found_map, + block + has_super); } + /* * Mark the blocks used for the inode table */ diff --git a/lib/e2p/ChangeLog b/lib/e2p/ChangeLog index ba6c7f9..f3a9b70 100644 --- a/lib/e2p/ChangeLog +++ b/lib/e2p/ChangeLog @@ -1,3 +1,8 @@ +2002-10-20 Theodore Ts'o + + * feature.c, ls.c (list_super2): Add support for the + meta_blockgroup filesystem format. + 2002-10-15 * ls.c (print_mntopts, list_super2): Print any default mount diff --git a/lib/e2p/feature.c b/lib/e2p/feature.c index 2586727..83cf6f9 100644 --- a/lib/e2p/feature.c +++ b/lib/e2p/feature.c @@ -49,6 +49,8 @@ static struct feature feature_list[] = { "needs_recovery" }, { E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_JOURNAL_DEV, "journal_dev" }, + { E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_META_BG, + "meta_bg" }, { 0, 0, 0 }, }; diff --git a/lib/e2p/ls.c b/lib/e2p/ls.c index c18e0ff..cab3ae1 100644 --- a/lib/e2p/ls.c +++ b/lib/e2p/ls.c @@ -202,6 +202,9 @@ void list_super2(struct ext2_super_block * sb, FILE *f) fprintf(f, "Inodes per group: %u\n", sb->s_inodes_per_group); fprintf(f, "Inode blocks per group: %u\n", inode_blocks_per_group); tm = sb->s_mtime; + if (sb->s_first_meta_bg) + fprintf(f, "First meta block group: %u\n", + sb->s_first_meta_bg); fprintf(f, "Last mount time: %s", ctime(&tm)); tm = sb->s_wtime; fprintf(f, "Last write time: %s", ctime(&tm)); diff --git a/lib/ext2fs/ChangeLog b/lib/ext2fs/ChangeLog index a12a608..7d085e1 100644 --- a/lib/ext2fs/ChangeLog +++ b/lib/ext2fs/ChangeLog @@ -1,3 +1,10 @@ +2002-10-20 Theodore Ts'o + + * closefs.c (ext2fs_flush, write_bgdesc), ext2_fs.h, ext2fs.h, + openfs.c (ext2fs_descriptor_block_loc, ext2fs_open), initialize.c + (ext2fs_initialize), swapfs.c (ext2fs_swap_super): Add support for + the meta_blockgroup filesystem format. + 2002-10-15 * ext2_fs.h: Add new field in superblock for default mount options. diff --git a/lib/ext2fs/closefs.c b/lib/ext2fs/closefs.c index f52c343..dcf244b 100644 --- a/lib/ext2fs/closefs.c +++ b/lib/ext2fs/closefs.c @@ -113,9 +113,71 @@ void ext2fs_update_dynamic_rev(ext2_filsys fs) /* other fields should be left alone */ } +/* + * This writes out the block group descriptors the original, + * old-fashioned way. + */ +static errcode_t write_bgdesc(ext2_filsys fs, dgrp_t group, blk_t group_block, + struct ext2_group_desc *group_shadow) +{ + errcode_t retval; + char *group_ptr = (char *) group_shadow; + int j; + int has_super = ext2fs_bg_has_super(fs, group); + dgrp_t meta_bg_size, meta_bg; + blk_t blk; + + meta_bg_size = (fs->blocksize / sizeof (struct ext2_group_desc)); + meta_bg = group / meta_bg_size; + if (!(fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) || + (meta_bg < fs->super->s_first_meta_bg)) { + if (!has_super) + return 0; + for (j=0; j < fs->desc_blocks; j++) { + retval = io_channel_write_blk(fs->io, + group_block+1+j, 1, + group_ptr); + if (retval) + return retval; + group_ptr += fs->blocksize; + } + } else { + if (has_super) + group_block++; + if (((group % meta_bg_size) == 0) || + ((group % meta_bg_size) == 1) || + ((group % meta_bg_size) == (meta_bg_size-1))) { + return io_channel_write_blk(fs->io, group_block, + 1, group_ptr + (meta_bg*fs->blocksize)); + } + } + return 0; +} + + +static errcode_t write_backup_super(ext2_filsys fs, dgrp_t group, + blk_t group_block, + struct ext2_super_block *super_shadow) +{ + dgrp_t sgrp = group; + + if (sgrp > ((1 << 16) - 1)) + sgrp = (1 << 16) - 1; +#ifdef EXT2FS_ENABLE_SWAPFS + if (fs->flags & EXT2_FLAG_SWAP_BYTES) + super_shadow->s_block_group_nr = ext2fs_swab16(sgrp); + else +#endif + fs->super->s_block_group_nr = sgrp; + + return io_channel_write_blk(fs->io, group_block, -SUPERBLOCK_SIZE, + super_shadow); +} + + errcode_t ext2fs_flush(ext2_filsys fs) { - dgrp_t i,j,maxgroup,sgrp; + dgrp_t i,j,maxgroup; blk_t group_block; errcode_t retval; char *group_ptr; @@ -204,36 +266,16 @@ errcode_t ext2fs_flush(ext2_filsys fs) maxgroup = (fs->flags & EXT2_FLAG_MASTER_SB_ONLY) ? 1 : fs->group_desc_count; for (i = 0; i < maxgroup; i++) { - if (!ext2fs_bg_has_super(fs, i)) - goto next_group; - - sgrp = i; - if (sgrp > ((1 << 16) - 1)) - sgrp = (1 << 16) - 1; -#ifdef EXT2FS_ENABLE_SWAPFS - if (fs->flags & EXT2_FLAG_SWAP_BYTES) - super_shadow->s_block_group_nr = ext2fs_swab16(sgrp); - else -#endif - fs->super->s_block_group_nr = sgrp; - - if (i !=0 ) { - retval = io_channel_write_blk(fs->io, group_block, - -SUPERBLOCK_SIZE, - super_shadow); + if (i && ext2fs_bg_has_super(fs, i)) { + retval = write_backup_super(fs, i, group_block, + super_shadow); if (retval) goto errout; } - if (fs->flags & EXT2_FLAG_SUPER_ONLY) - goto next_group; - group_ptr = (char *) group_shadow; - for (j=0; j < fs->desc_blocks; j++) { - retval = io_channel_write_blk(fs->io, - group_block+1+j, 1, - group_ptr); - if (retval) + if (!(fs->flags & EXT2_FLAG_SUPER_ONLY)) { + if ((retval = write_bgdesc(fs, i, group_block, + group_shadow))) goto errout; - group_ptr += fs->blocksize; } next_group: group_block += EXT2_BLOCKS_PER_GROUP(fs->super); diff --git a/lib/ext2fs/ext2_fs.h b/lib/ext2fs/ext2_fs.h index 56fabbf..2b11261 100644 --- a/lib/ext2fs/ext2_fs.h +++ b/lib/ext2fs/ext2_fs.h @@ -439,7 +439,8 @@ struct ext2_super_block { __u8 s_reserved_char_pad; __u16 s_reserved_word_pad; __u32 s_default_mount_opts; - __u32 s_reserved[191]; /* Padding to the end of the block */ + __u32 s_first_meta_bg; /* First metablock group */ + __u32 s_reserved[190]; /* Padding to the end of the block */ }; /* @@ -488,9 +489,10 @@ struct ext2_super_block { #define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002 #define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */ #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */ +#define EXT2_FEATURE_INCOMPAT_META_BG 0x0010 #define EXT2_FEATURE_COMPAT_SUPP 0 -#define EXT2_FEATURE_INCOMPAT_SUPP EXT2_FEATURE_INCOMPAT_FILETYPE +#define EXT2_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE) #define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \ EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \ EXT2_FEATURE_RO_COMPAT_BTREE_DIR) diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h index 6f5bc47..992fc74 100644 --- a/lib/ext2fs/ext2fs.h +++ b/lib/ext2fs/ext2fs.h @@ -432,10 +432,12 @@ typedef struct ext2_icount *ext2_icount_t; #define EXT2_LIB_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE|\ EXT2_FEATURE_INCOMPAT_COMPRESSION|\ EXT3_FEATURE_INCOMPAT_JOURNAL_DEV|\ + EXT2_FEATURE_INCOMPAT_META_BG|\ EXT3_FEATURE_INCOMPAT_RECOVER) #else #define EXT2_LIB_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE|\ EXT3_FEATURE_INCOMPAT_JOURNAL_DEV|\ + EXT2_FEATURE_INCOMPAT_META_BG|\ EXT3_FEATURE_INCOMPAT_RECOVER) #endif #define EXT2_LIB_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER|\ @@ -808,6 +810,8 @@ extern errcode_t ext2fs_add_journal_inode(ext2_filsys fs, blk_t size, extern errcode_t ext2fs_open(const char *name, int flags, int superblock, int block_size, io_manager manager, ext2_filsys *ret_fs); +extern blk_t ext2fs_descriptor_block_loc(ext2_filsys fs, blk_t group_block, + dgrp_t i); /* get_pathname.c */ extern errcode_t ext2fs_get_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino, diff --git a/lib/ext2fs/initialize.c b/lib/ext2fs/initialize.c index f132416..d9be945 100644 --- a/lib/ext2fs/initialize.c +++ b/lib/ext2fs/initialize.c @@ -67,6 +67,7 @@ errcode_t ext2fs_initialize(const char *name, int flags, int i, j; blk_t numblocks; char *buf; + int meta_bg_size, meta_bg, has_super; if (!param || !param->s_blocks_count) return EXT2_ET_INVALID_ARGUMENT; @@ -113,6 +114,7 @@ errcode_t ext2fs_initialize(const char *name, int flags, set_field(s_feature_compat, 0); set_field(s_feature_incompat, 0); set_field(s_feature_ro_compat, 0); + set_field(s_first_meta_bg, 0); if (super->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP) return EXT2_ET_UNSUPP_FEATURE; if (super->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) @@ -301,11 +303,35 @@ retry: } else numblocks = fs->super->s_blocks_per_group; - if (ext2fs_bg_has_super(fs, i)) { - for (j=0; j < fs->desc_blocks+1; j++) + has_super = ext2fs_bg_has_super(fs, i); + + if (has_super) { + ext2fs_mark_block_bitmap(fs->block_map, group_block); + numblocks--; + } + meta_bg_size = (fs->blocksize / + sizeof (struct ext2_group_desc)); + meta_bg = i / meta_bg_size; + + if (!(fs->super->s_feature_incompat & + EXT2_FEATURE_INCOMPAT_META_BG) || + (meta_bg < fs->super->s_first_meta_bg)) { + if (has_super) { + for (j=0; j < fs->desc_blocks; j++) + ext2fs_mark_block_bitmap(fs->block_map, + group_block + j + 1); + numblocks -= fs->desc_blocks; + } + } else { + if (has_super) + has_super = 1; + if (((i % meta_bg_size) == 0) || + ((i % meta_bg_size) == 1) || + ((i % meta_bg_size) == (meta_bg_size-1))) { ext2fs_mark_block_bitmap(fs->block_map, - group_block + j); - numblocks -= 1 + fs->desc_blocks; + group_block + has_super); + numblocks--; + } } numblocks -= 2 + fs->inode_blocks_per_group; diff --git a/lib/ext2fs/openfs.c b/lib/ext2fs/openfs.c index d9021d6..4dcae98 100644 --- a/lib/ext2fs/openfs.c +++ b/lib/ext2fs/openfs.c @@ -24,9 +24,27 @@ #endif #include "ext2_fs.h" + + #include "ext2fs.h" #include "e2image.h" +blk_t ext2fs_descriptor_block_loc(ext2_filsys fs, blk_t group_block, dgrp_t i) +{ + int bg; + int has_super = 0; + + if (!(fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) || + (i < fs->super->s_first_meta_bg)) + return (group_block + i + 1); + + bg = (fs->blocksize / sizeof (struct ext2_group_desc)) * i; + if (ext2fs_bg_has_super(fs, bg)) + has_super = 1; + return (fs->super->s_first_data_block + has_super + + (bg * fs->super->s_blocks_per_group)); +} + /* * Note: if superblock is non-zero, block-size must also be non-zero. * Superblock and block_size can be zero to use the default size. @@ -44,7 +62,7 @@ errcode_t ext2fs_open(const char *name, int flags, int superblock, ext2_filsys fs; errcode_t retval; int i, j, groups_per_block, blocks_per_group; - blk_t group_block; + blk_t group_block, blk; char *dest; struct ext2_group_desc *gdp; @@ -214,18 +232,17 @@ errcode_t ext2fs_open(const char *name, int flags, int superblock, if (retval) goto cleanup; if (!group_block) - group_block = fs->super->s_first_data_block + 1; + group_block = fs->super->s_first_data_block; dest = (char *) fs->group_desc; + groups_per_block = fs->blocksize / sizeof(struct ext2_group_desc); for (i=0 ; i < fs->desc_blocks; i++) { - retval = io_channel_read_blk(fs->io, group_block, 1, dest); + blk = ext2fs_descriptor_block_loc(fs, group_block, i); + retval = io_channel_read_blk(fs->io, blk, 1, dest); if (retval) goto cleanup; - group_block++; #ifdef EXT2FS_ENABLE_SWAPFS if (fs->flags & EXT2_FLAG_SWAP_BYTES) { gdp = (struct ext2_group_desc *) dest; - groups_per_block = fs->blocksize / - sizeof(struct ext2_group_desc); for (j=0; j < groups_per_block; j++) ext2fs_swap_group_desc(gdp++); } diff --git a/lib/ext2fs/swapfs.c b/lib/ext2fs/swapfs.c index 14165cb..e375c63 100644 --- a/lib/ext2fs/swapfs.c +++ b/lib/ext2fs/swapfs.c @@ -57,6 +57,7 @@ void ext2fs_swap_super(struct ext2_super_block * sb) sb->s_journal_inum = ext2fs_swab32(sb->s_journal_inum); sb->s_journal_dev = ext2fs_swab32(sb->s_journal_dev); sb->s_last_orphan = ext2fs_swab32(sb->s_last_orphan); + sb->s_first_meta_bg = ext2fs_swab32(sb->s_first_meta_bg); for (i=0; i < 4; i++) sb->s_hash_seed[i] = ext2fs_swab32(sb->s_hash_seed[i]); } diff --git a/misc/ChangeLog b/misc/ChangeLog index 038cb71..63f1d98 100644 --- a/misc/ChangeLog +++ b/misc/ChangeLog @@ -1,3 +1,9 @@ +2002-10-20 Theodore Ts'o + + * dumpe2fs.c (list_desc), mke2fs.c (PRS), e2image.c + (mark_table_blocks): Add support for the meta_blockgroup + filesystem format. + 2002-10-15 * tune2fs.8.in, tune2fs.c (update_mntopts, main): Add new option diff --git a/misc/dumpe2fs.c b/misc/dumpe2fs.c index 14931b0..b4c63a7 100644 --- a/misc/dumpe2fs.c +++ b/misc/dumpe2fs.c @@ -90,6 +90,7 @@ static void list_desc (ext2_filsys fs) char * inode_bitmap = fs->inode_map->bitmap; int inode_blocks_per_group; int group_desc_blocks; + int meta_bg, meta_bg_size, has_super; inode_blocks_per_group = ((fs->super->s_inodes_per_group * EXT2_INODE_SIZE(fs->super)) + @@ -111,14 +112,35 @@ static void list_desc (ext2_filsys fs) printf (_("Group %lu: (Blocks "), i); printf(range_format, group_blk, next_blk - 1); fputs(")\n", stdout); - if (ext2fs_bg_has_super (fs, i)) { - printf (_(" %s Superblock at "), + has_super = ext2fs_bg_has_super(fs, i); + if (has_super) { + printf (_(" %s superblock at "), i == 0 ? _("Primary") : _("Backup")); printf(num_format, group_blk); - printf(_(", Group Descriptors at ")); + } + meta_bg_size = (fs->blocksize / + sizeof (struct ext2_group_desc)); + meta_bg = i / meta_bg_size; + if (!(fs->super->s_feature_incompat & + EXT2_FEATURE_INCOMPAT_META_BG) || + (meta_bg < fs->super->s_first_meta_bg)) { + fputc(has_super ? ',' : ' ', stdout); + printf(_(" Group descriptors at ")); printf(range_format, group_blk+1, group_blk + group_desc_blocks); fputc('\n', stdout); + } else { + if (has_super) + has_super = 1; + if (((i % meta_bg_size) == 0) || + ((i % meta_bg_size) == 1) || + ((i % meta_bg_size) == (meta_bg_size-1))) { + fputc(has_super ? ',' : ' ', stdout); + printf(_(" Group descriptor at ")); + printf(num_format, group_blk + has_super); + fputc('\n', stdout); + } else if (has_super) + fputc('\n', stdout); } fputs(_(" Block bitmap at "), stdout); printf(num_format, fs->group_desc[i].bg_block_bitmap); diff --git a/misc/e2image.c b/misc/e2image.c index 1996311..34b1e2c 100644 --- a/misc/e2image.c +++ b/misc/e2image.c @@ -240,7 +240,7 @@ static void mark_table_blocks(ext2_filsys fs) */ for (j = 0; j < fs->desc_blocks; j++) { ext2fs_mark_block_bitmap(meta_block_map, - block + j + 1); + ext2fs_descriptor_block_loc(fs, block, j)); } for (i = 0; i < fs->group_desc_count; i++) { diff --git a/misc/mke2fs.c b/misc/mke2fs.c index c37eecc..1c83d9f 100644 --- a/misc/mke2fs.c +++ b/misc/mke2fs.c @@ -780,7 +780,8 @@ static __u32 ok_features[3] = { EXT3_FEATURE_COMPAT_HAS_JOURNAL | EXT2_FEATURE_COMPAT_DIR_INDEX, /* Compat */ EXT2_FEATURE_INCOMPAT_FILETYPE| /* Incompat */ - EXT3_FEATURE_INCOMPAT_JOURNAL_DEV, + EXT3_FEATURE_INCOMPAT_JOURNAL_DEV| + EXT2_FEATURE_INCOMPAT_META_BG, EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER /* R/O compat */ }; @@ -1164,6 +1165,12 @@ static void PRS(int argc, char *argv[]) !journal_size) journal_size = -1; + /* Set first meta blockgroup via an environment variable */ + /* (this is mostly for debugging purposes) */ + if ((param.s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) && + ((tmp = getenv("MKE2FS_FIRST_META_BG")))) + param.s_first_meta_bg = atoi(tmp); + set_fs_defaults(fs_type, ¶m, blocksize, &inode_ratio); if (param.s_blocks_per_group) { -- 1.8.3.1