Message ID | 20220607102421.170419-1-nborisov@suse.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | btrfs-progs: convert: Properly work with large ext4 filesystems | expand |
On Tue, Jun 07, 2022 at 01:24:21PM +0300, Nikolay Borisov wrote: > On large (blockcount > 32bit) filesystems reading directly > super_block->s_blocks_count is not sufficient as the block count is held > in 2 separate 32 bit variables. Instead always use the provided > ext2fs_blocks_count to read the value. This can result in assertion > failure, when the block count is only held in the high 32 bits, in this > case s_block_counts would be zero, which would result in > btrfs_convert_context::block_count/total_bytes to also be 0 and hit an > assertion failure: > > convert/main.c:1162: do_convert: Assertion `cctx.total_bytes != 0` failed, value 0 > btrfs-convert(+0xffb0)[0x557defdabfb0] > btrfs-convert(main+0x6c5)[0x557defdaa125] > /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xea)[0x7f66e1f8bd0a] > btrfs-convert(_start+0x2a)[0x557defdab52a] > Aborted > > What's worse it can also result in btrfs-conver mistakenly thinking that > a filesystem is smaller than it actually is (ignoring the top 32 bits). > > Link: https://lore.kernel.org/linux-btrfs/023b5ca9-0610-231b-fc4e-a72fe1377a5a@jansson.tech/ > Signed-off-by: Nikolay Borisov <nborisov@suse.com> Added to devel, thanks.
diff --git a/convert/main.c b/convert/main.c index 73f919d25255..92ebb1acd181 100644 --- a/convert/main.c +++ b/convert/main.c @@ -1134,7 +1134,6 @@ static int do_convert(const char *devname, u32 convert_flags, u32 nodesize, int ret; int fd = -1; u32 blocksize; - u64 total_bytes; struct btrfs_root *root; struct btrfs_root *image_root; struct btrfs_convert_context cctx; @@ -1161,7 +1160,6 @@ static int do_convert(const char *devname, u32 convert_flags, u32 nodesize, ASSERT(cctx.total_bytes != 0); blocksize = cctx.blocksize; - total_bytes = (u64)blocksize * (u64)cctx.block_count; if (blocksize < 4096) { error("block size is too small: %u < 4096", blocksize); goto fail; @@ -1223,7 +1221,7 @@ static int do_convert(const char *devname, u32 convert_flags, u32 nodesize, mkfs_cfg.csum_type = csum_type; mkfs_cfg.label = cctx.label; - mkfs_cfg.num_bytes = total_bytes; + mkfs_cfg.num_bytes = cctx.total_bytes; mkfs_cfg.nodesize = nodesize; mkfs_cfg.sectorsize = blocksize; mkfs_cfg.stripesize = blocksize; diff --git a/convert/source-ext2.c b/convert/source-ext2.c index 9fad4c50e244..610db16b81aa 100644 --- a/convert/source-ext2.c +++ b/convert/source-ext2.c @@ -92,8 +92,8 @@ static int ext2_open_fs(struct btrfs_convert_context *cctx, const char *name) cctx->fs_data = ext2_fs; cctx->blocksize = ext2_fs->blocksize; - cctx->block_count = ext2_fs->super->s_blocks_count; - cctx->total_bytes = (u64)ext2_fs->super->s_blocks_count * ext2_fs->blocksize; + cctx->block_count = ext2fs_blocks_count(ext2_fs->super); + cctx->total_bytes = cctx->block_count * cctx->blocksize; cctx->label = strndup((char *)ext2_fs->super->s_volume_name, 16); cctx->first_data_block = ext2_fs->super->s_first_data_block; cctx->inodes_count = ext2_fs->super->s_inodes_count;
On large (blockcount > 32bit) filesystems reading directly super_block->s_blocks_count is not sufficient as the block count is held in 2 separate 32 bit variables. Instead always use the provided ext2fs_blocks_count to read the value. This can result in assertion failure, when the block count is only held in the high 32 bits, in this case s_block_counts would be zero, which would result in btrfs_convert_context::block_count/total_bytes to also be 0 and hit an assertion failure: convert/main.c:1162: do_convert: Assertion `cctx.total_bytes != 0` failed, value 0 btrfs-convert(+0xffb0)[0x557defdabfb0] btrfs-convert(main+0x6c5)[0x557defdaa125] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xea)[0x7f66e1f8bd0a] btrfs-convert(_start+0x2a)[0x557defdab52a] Aborted What's worse it can also result in btrfs-conver mistakenly thinking that a filesystem is smaller than it actually is (ignoring the top 32 bits). Link: https://lore.kernel.org/linux-btrfs/023b5ca9-0610-231b-fc4e-a72fe1377a5a@jansson.tech/ Signed-off-by: Nikolay Borisov <nborisov@suse.com> --- convert/main.c | 4 +--- convert/source-ext2.c | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) -- 2.17.1