[The following is perhaps not quite kosher in the details (e.g. should the function names be changed?), but I think it's correct in principle.] The block number comparison in ext2fs_block_alloc_stats2() is invalid for 64-bit filesystems: it compares the block number to the low 32-bits of the blocks_count in the superblock. That caused the journal file for a 32TiB filesystem to be malformed and the resulting filesystem could not be mounted. I found three static functions in lib/e2p/ls.c that do the right thing wrt 64-bit compatibility, one of which can be used in the context above; moved them to the common header file lib/ext2fs.ext2_fs.h, and changed ext2fs_block_alloc_stats2() to use one of these, e2p_blocks_count(), to calculate the correct blocks count. With this change, the journal looks sane and the filesystem could be mounted. --- lib/e2p/ls.c | 21 --------------------- lib/ext2fs/alloc_stats.c | 2 +- lib/ext2fs/ext2_fs.h | 25 +++++++++++++++++++++++++ 3 files changed, 26 insertions(+), 22 deletions(-) diff --git a/lib/e2p/ls.c b/lib/e2p/ls.c index 77463ca..e6a819f 100644 --- a/lib/e2p/ls.c +++ b/lib/e2p/ls.c @@ -164,27 +164,6 @@ static void print_super_flags(struct ext2_super_block * s, FILE *f) fputs("(none)\n", f); } -static __u64 e2p_blocks_count(struct ext2_super_block *super) -{ - return super->s_blocks_count | - (super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT ? - (__u64) super->s_blocks_count_hi << 32 : 0); -} - -static __u64 e2p_r_blocks_count(struct ext2_super_block *super) -{ - return super->s_r_blocks_count | - (super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT ? - (__u64) super->s_r_blocks_count_hi << 32 : 0); -} - -static __u64 e2p_free_blocks_count(struct ext2_super_block *super) -{ - return super->s_free_blocks_count | - (super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT ? - (__u64) super->s_free_blocks_hi << 32 : 0); -} - #ifndef EXT2_INODE_SIZE #define EXT2_INODE_SIZE(s) sizeof(struct ext2_inode) #endif diff --git a/lib/ext2fs/alloc_stats.c b/lib/ext2fs/alloc_stats.c index 7895aee..44142f4 100644 --- a/lib/ext2fs/alloc_stats.c +++ b/lib/ext2fs/alloc_stats.c @@ -65,7 +65,7 @@ void ext2fs_block_alloc_stats2(ext2_filsys fs, blk64_t blk, int inuse) int group = ext2fs_group_of_blk2(fs, blk); #ifndef OMIT_COM_ERR - if (blk >= fs->super->s_blocks_count) { + if (blk >= e2p_blocks_count(fs->super)) { com_err("ext2fs_block_alloc_stats2", 0, "Illegal block number: %lu", blk); return; diff --git a/lib/ext2fs/ext2_fs.h b/lib/ext2fs/ext2_fs.h index 46f4ae0..a256b5e 100644 --- a/lib/ext2fs/ext2_fs.h +++ b/lib/ext2fs/ext2_fs.h @@ -585,6 +585,7 @@ struct ext2_super_block { __u32 s_reserved[162]; /* Padding to the end of the block */ }; + /* * Codes for operating systems */ @@ -750,4 +751,28 @@ struct mmp_struct { */ #define EXT2_MMP_DEF_INTERVAL 5 +/* + * Inlines used in lib/e2p/ls.c and lib/ext2fs/alloc_stats.c + */ +static __u64 e2p_blocks_count(struct ext2_super_block *super) +{ + return super->s_blocks_count | + (super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT ? + (__u64) super->s_blocks_count_hi << 32 : 0); +} + +static __u64 e2p_r_blocks_count(struct ext2_super_block *super) +{ + return super->s_r_blocks_count | + (super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT ? + (__u64) super->s_r_blocks_count_hi << 32 : 0); +} + +static __u64 e2p_free_blocks_count(struct ext2_super_block *super) +{ + return super->s_free_blocks_count | + (super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT ? + (__u64) super->s_free_blocks_hi << 32 : 0); +} + #endif /* _LINUX_EXT2_FS_H */ -- 1.6.0.3 -- To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html