From 6220b6715f4900bbcfa04ef3b81ccf48b2d21825 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sat, 4 Jun 2011 16:36:19 -0400 Subject: libext2fs: require cluster size == block_size when opening a !bigalloc fs In ext2fs_open() check to make sure the cluster size superblock field is the same as the block size field when the bigalloc feature is not set. This is necessary since we will start introducing calculations based on the cluster size field. Signed-off-by: "Theodore Ts'o" --- lib/ext2fs/openfs.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'lib/ext2fs') diff --git a/lib/ext2fs/openfs.c b/lib/ext2fs/openfs.c index a20b923a..f87c1717 100644 --- a/lib/ext2fs/openfs.c +++ b/lib/ext2fs/openfs.c @@ -239,6 +239,12 @@ errcode_t ext2fs_open2(const char *name, const char *io_options, retval = EXT2_ET_CORRUPT_SUPERBLOCK; goto cleanup; } + if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super, + EXT4_FEATURE_RO_COMPAT_BIGALLOC) && + (fs->super->s_log_block_size != fs->super->s_log_cluster_size)) { + retval = EXT2_ET_CORRUPT_SUPERBLOCK; + goto cleanup; + } fs->blocksize = EXT2_BLOCK_SIZE(fs->super); if (EXT2_INODE_SIZE(fs->super) < EXT2_GOOD_OLD_INODE_SIZE) { retval = EXT2_ET_CORRUPT_SUPERBLOCK; -- cgit v1.2.3 From ae9e37cd114385764864518057ff854b3f335440 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sat, 4 Jun 2011 16:40:26 -0400 Subject: libext2fs: change EXT2_MAX_BLOCKS_PER_GROUP() to be cluster size aware Change the EXT2_MAX_BLOCKS_PER_GROUP so that it takes the cluster size into account. This way we can open bigalloc file systems without ext2fs_open() thinking that they are corrupt. Signed-off-by: "Theodore Ts'o" --- lib/ext2fs/ext2_fs.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'lib/ext2fs') diff --git a/lib/ext2fs/ext2_fs.h b/lib/ext2fs/ext2_fs.h index a6c70de5..2d960910 100644 --- a/lib/ext2fs/ext2_fs.h +++ b/lib/ext2fs/ext2_fs.h @@ -225,9 +225,13 @@ struct ext2_dx_countlimit { #define EXT2_BLOCKS_PER_GROUP(s) (EXT2_SB(s)->s_blocks_per_group) #define EXT2_INODES_PER_GROUP(s) (EXT2_SB(s)->s_inodes_per_group) +#define EXT2_CLUSTERS_PER_GROUP(s) (EXT2_SB(s)->s_clusters_per_group) #define EXT2_INODES_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s)/EXT2_INODE_SIZE(s)) /* limits imposed by 16-bit value gd_free_{blocks,inode}_count */ -#define EXT2_MAX_BLOCKS_PER_GROUP(s) ((1 << 16) - 8) +#define EXT2_MAX_BLOCKS_PER_GROUP(s) (((1 << 16) - 8) * \ + (EXT2_CLUSTER_SIZE(s) / \ + EXT2_BLOCK_SIZE(s))) +#define EXT2_MAX_CLUSTERS_PER_GROUP(s) ((1 << 16) - 8) #define EXT2_MAX_INODES_PER_GROUP(s) ((1 << 16) - EXT2_INODES_PER_BLOCK(s)) #ifdef __KERNEL__ #define EXT2_DESC_PER_BLOCK(s) (EXT2_SB(s)->s_desc_per_block) -- cgit v1.2.3 From 1da5ef707904cf99300a0fb36b9ae3b29dbc8bde Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sat, 4 Jun 2011 10:20:47 -0400 Subject: libext2fs: change fs->clustersize to fs->cluster_ratio_bits The log2 of the ratio of cluster size to block size is far more useful than just storing the cluster size. So make this change, and then define basic utility macros: EXT2FS_CLUSTER_RATIO(), EXT2FS_CLUSTER_MASK(), EXT2FS_B2C(), EXT2FS_C2B(), and EXT2FS_NUM_B2C(). Signed-off-by: "Theodore Ts'o" --- lib/ext2fs/ext2fs.h | 13 ++++++++++++- lib/ext2fs/initialize.c | 3 ++- lib/ext2fs/openfs.c | 8 +++++++- misc/mke2fs.c | 5 +++-- 4 files changed, 24 insertions(+), 5 deletions(-) (limited to 'lib/ext2fs') diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h index 516eb1af..5379422b 100644 --- a/lib/ext2fs/ext2fs.h +++ b/lib/ext2fs/ext2fs.h @@ -195,7 +195,7 @@ struct struct_ext2_filsys { char * device_name; struct ext2_super_block * super; unsigned int blocksize; - int clustersize; + int cluster_ratio_bits; dgrp_t group_desc_count; unsigned long desc_blocks; struct ext2_group_desc * group_desc; @@ -547,6 +547,17 @@ typedef struct ext2_icount *ext2_icount_t; #define EXT2_LIB_SOFTSUPP_INCOMPAT (0) #define EXT2_LIB_SOFTSUPP_RO_COMPAT (EXT4_FEATURE_RO_COMPAT_BIGALLOC) + +/* Translate a block number to a cluster number */ +#define EXT2FS_CLUSTER_RATIO(fs) (1 << (fs)->cluster_ratio_bits) +#define EXT2FS_CLUSTER_MASK(fs) (EXT2FS_CLUSTER_RATIO(fs) - 1) +#define EXT2FS_B2C(fs, blk) ((blk) >> (fs)->cluster_ratio_bits) +/* Translate a cluster number to a block number */ +#define EXT2FS_C2B(fs, cluster) ((cluster) << (fs)->cluster_ratio_bits) +/* Translate # of blks to # of clusters */ +#define EXT2FS_NUM_B2C(fs, blks) (((blks) + EXT2FS_CLUSTER_MASK(fs)) >> \ + (fs)->cluster_ratio_bits) + /* * function prototypes */ diff --git a/lib/ext2fs/initialize.c b/lib/ext2fs/initialize.c index c109d08e..b9d45aef 100644 --- a/lib/ext2fs/initialize.c +++ b/lib/ext2fs/initialize.c @@ -178,7 +178,8 @@ errcode_t ext2fs_initialize(const char *name, int flags, super->s_creator_os = CREATOR_OS; fs->blocksize = EXT2_BLOCK_SIZE(super); - fs->clustersize = EXT2_CLUSTER_SIZE(super); + fs->cluster_ratio_bits = super->s_log_cluster_size - + super->s_log_block_size; /* default: (fs->blocksize*8) blocks/group, up to 2^16 (GDT limit) */ set_field(s_blocks_per_group, fs->blocksize * 8); diff --git a/lib/ext2fs/openfs.c b/lib/ext2fs/openfs.c index f87c1717..a598ca04 100644 --- a/lib/ext2fs/openfs.c +++ b/lib/ext2fs/openfs.c @@ -250,7 +250,13 @@ errcode_t ext2fs_open2(const char *name, const char *io_options, retval = EXT2_ET_CORRUPT_SUPERBLOCK; goto cleanup; } - fs->clustersize = EXT2_CLUSTER_SIZE(fs->super); + fs->cluster_ratio_bits = fs->super->s_log_cluster_size - + fs->super->s_log_block_size; + if (EXT2_BLOCKS_PER_GROUP(fs->super) != + EXT2_CLUSTERS_PER_GROUP(fs->super) << fs->cluster_ratio_bits) { + retval = EXT2_ET_CORRUPT_SUPERBLOCK; + goto cleanup; + } fs->inode_blocks_per_group = ((EXT2_INODES_PER_GROUP(fs->super) * EXT2_INODE_SIZE(fs->super) + EXT2_BLOCK_SIZE(fs->super) - 1) / diff --git a/misc/mke2fs.c b/misc/mke2fs.c index 9f28901a..c46df6ce 100644 --- a/misc/mke2fs.c +++ b/misc/mke2fs.c @@ -619,9 +619,10 @@ static void show_stats(ext2_filsys fs) if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super, EXT4_FEATURE_RO_COMPAT_BIGALLOC)) printf(_("Cluster size=%u (log=%u)\n"), - fs->clustersize, s->s_log_cluster_size); + fs->blocksize << fs->cluster_ratio_bits, + s->s_log_cluster_size); else - printf(_("Fragment size=%u (log=%u)\n"), fs->clustersize, + printf(_("Fragment size=%u (log=%u)\n"), EXT2_CLUSTER_SIZE(s), s->s_log_cluster_size); printf(_("Stride=%u blocks, Stripe width=%u blocks\n"), s->s_raid_stride, s->s_raid_stripe_width); -- cgit v1.2.3 From b92fbed77875b447f930fdcb5ae660c16b2ec0db Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sat, 4 Jun 2011 20:05:22 -0400 Subject: libext2fs: Teach block bitmap read, write, and allocation funcs about clusters Signed-off-by: "Theodore Ts'o" --- lib/ext2fs/bitmaps.c | 2 +- lib/ext2fs/rw_bitmaps.c | 17 +++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) (limited to 'lib/ext2fs') diff --git a/lib/ext2fs/bitmaps.c b/lib/ext2fs/bitmaps.c index 649c524f..6f758f06 100644 --- a/lib/ext2fs/bitmaps.c +++ b/lib/ext2fs/bitmaps.c @@ -79,7 +79,7 @@ errcode_t ext2fs_allocate_block_bitmap(ext2_filsys fs, start = fs->super->s_first_data_block; end = fs->super->s_blocks_count-1; - real_end = (EXT2_BLOCKS_PER_GROUP(fs->super) + real_end = (EXT2_CLUSTERS_PER_GROUP(fs->super) * fs->group_desc_count)-1 + start; return (ext2fs_make_generic_bitmap(EXT2_ET_MAGIC_BLOCK_BITMAP, fs, diff --git a/lib/ext2fs/rw_bitmaps.c b/lib/ext2fs/rw_bitmaps.c index 4e77a8f1..48f06e06 100644 --- a/lib/ext2fs/rw_bitmaps.c +++ b/lib/ext2fs/rw_bitmaps.c @@ -37,7 +37,7 @@ static errcode_t write_bitmaps(ext2_filsys fs, int do_inode, int do_block) char *block_buf, *inode_buf; int csum_flag = 0; blk_t blk; - blk_t blk_itr = fs->super->s_first_data_block; + blk_t blk_itr = EXT2FS_B2C(fs, fs->super->s_first_data_block); ext2_ino_t ino_itr = 1; EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); @@ -51,7 +51,7 @@ static errcode_t write_bitmaps(ext2_filsys fs, int do_inode, int do_block) inode_nbytes = block_nbytes = 0; if (do_block) { - block_nbytes = EXT2_BLOCKS_PER_GROUP(fs->super) / 8; + block_nbytes = EXT2_CLUSTERS_PER_GROUP(fs->super) / 8; retval = ext2fs_get_memalign(fs->blocksize, fs->blocksize, &block_buf); if (retval) @@ -83,9 +83,10 @@ static errcode_t write_bitmaps(ext2_filsys fs, int do_inode, int do_block) if (i == fs->group_desc_count - 1) { /* Force bitmap padding for the last group */ - nbits = ((fs->super->s_blocks_count - - fs->super->s_first_data_block) - % EXT2_BLOCKS_PER_GROUP(fs->super)); + nbits = EXT2FS_NUM_B2C(fs, + ((fs->super->s_blocks_count + - fs->super->s_first_data_block) + % EXT2_BLOCKS_PER_GROUP(fs->super))); if (nbits) for (j = nbits; j < fs->blocksize * 8; j++) ext2fs_set_bit(j, block_buf); @@ -141,13 +142,13 @@ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block) char *block_bitmap = 0, *inode_bitmap = 0; char *buf; errcode_t retval; - int block_nbytes = EXT2_BLOCKS_PER_GROUP(fs->super) / 8; + int block_nbytes = EXT2_CLUSTERS_PER_GROUP(fs->super) / 8; int inode_nbytes = EXT2_INODES_PER_GROUP(fs->super) / 8; int csum_flag = 0; int do_image = fs->flags & EXT2_FLAG_IMAGE_FILE; unsigned int cnt; blk_t blk; - blk_t blk_itr = fs->super->s_first_data_block; + blk_t blk_itr = EXT2FS_B2C(fs, fs->super->s_first_data_block); blk_t blk_cnt; ext2_ino_t ino_itr = 1; ext2_ino_t ino_cnt; @@ -219,7 +220,7 @@ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block) } blk = (fs->image_header->offset_blockmap / fs->blocksize); - blk_cnt = EXT2_BLOCKS_PER_GROUP(fs->super) * + blk_cnt = EXT2_CLUSTERS_PER_GROUP(fs->super) * fs->group_desc_count; while (block_nbytes > 0) { retval = io_channel_read_blk(fs->image_io, blk++, -- cgit v1.2.3