From 8b0210841a74d541a157fdbae520c6b36f24fb84 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Tue, 22 Oct 2019 18:42:25 -0400 Subject: [PATCH] Teach ext2fs_open2() to honor the EXT2_FLAG_SUPER_ONLY flag Opening the file system with EXT2_FLAG_SUPER_ONLY will leave fs->group_desc to be NULL and modify "dumpe2fs -h" and tune2fs when it is emulating e2label to use this flag. This speeds up "dumpe2fs -h" and "e2label" when operating on very large file systems. To allow other libext2fs functions to work without too many surprises, ext2fs_group_desc() will read in the block group descriptors on demand. This allows "dumpe2fs -h" to be able to read the journal inode, for example. Signed-off-by: Theodore Ts'o Cray-bug-id: LUS-5777 --- lib/ext2fs/blknum.c | 39 ++++++++++++++++++++++++++++++++++++--- lib/ext2fs/openfs.c | 4 +++- misc/dumpe2fs.c | 2 ++ misc/tune2fs.c | 2 +- 4 files changed, 42 insertions(+), 5 deletions(-) diff --git a/lib/ext2fs/blknum.c b/lib/ext2fs/blknum.c index ec77a06..7c3c6b5 100644 --- a/lib/ext2fs/blknum.c +++ b/lib/ext2fs/blknum.c @@ -201,9 +201,42 @@ struct ext2_group_desc *ext2fs_group_desc(ext2_filsys fs, struct opaque_ext2_group_desc *gdp, dgrp_t group) { - int desc_size = EXT2_DESC_SIZE(fs->super) & ~7; - - return (struct ext2_group_desc *)((char *)gdp + group * desc_size); + struct ext2_group_desc *ret_gdp; + errcode_t retval; + static char *buf = 0; + static int bufsize = 0; + blk64_t blk; + int desc_size = EXT2_DESC_SIZE(fs->super) & ~7; + int desc_per_blk = EXT2_DESC_PER_BLOCK(fs->super); + + if (group > fs->group_desc_count) + return NULL; + if (gdp) + return (struct ext2_group_desc *)((char *)gdp + + group * desc_size); + /* + * If fs->group_desc wasn't read in when the file system was + * opened, then read it on demand here. + */ + if (bufsize < fs->blocksize) + ext2fs_free_mem(&buf); + if (!buf) { + retval = ext2fs_get_mem(fs->blocksize, &buf); + if (retval) + return NULL; + bufsize = fs->blocksize; + } + blk = ext2fs_descriptor_block_loc2(fs, fs->super->s_first_data_block, + group / desc_per_blk); + retval = io_channel_read_blk(fs->io, blk, 1, buf); + if (retval) + return NULL; + ret_gdp = (struct ext2_group_desc *) + (buf + ((group % desc_per_blk) * desc_size)); +#ifdef WORDS_BIGENDIAN + ext2fs_swap_group_desc2(fs, ret_gdp); +#endif + return ret_gdp; } /* Do the same but as an ext4 group desc for internal use here */ diff --git a/lib/ext2fs/openfs.c b/lib/ext2fs/openfs.c index 51b54a4..ec2d6cb 100644 --- a/lib/ext2fs/openfs.c +++ b/lib/ext2fs/openfs.c @@ -393,6 +393,8 @@ errcode_t ext2fs_open2(const char *name, const char *io_options, } fs->desc_blocks = ext2fs_div_ceil(fs->group_desc_count, EXT2_DESC_PER_BLOCK(fs->super)); + if (flags & EXT2_FLAG_SUPER_ONLY) + goto skip_read_bg; retval = ext2fs_get_array(fs->desc_blocks, fs->blocksize, &fs->group_desc); if (retval) @@ -479,7 +481,7 @@ errcode_t ext2fs_open2(const char *name, const char *io_options, if (fs->flags & EXT2_FLAG_RW) ext2fs_mark_super_dirty(fs); } - +skip_read_bg: if (ext2fs_has_feature_mmp(fs->super) && !(flags & EXT2_FLAG_SKIP_MMP) && (flags & (EXT2_FLAG_RW | EXT2_FLAG_EXCLUSIVE))) { diff --git a/misc/dumpe2fs.c b/misc/dumpe2fs.c index 72f323e..045e9d8 100644 --- a/misc/dumpe2fs.c +++ b/misc/dumpe2fs.c @@ -670,6 +670,8 @@ int main (int argc, char ** argv) flags |= EXT2_FLAG_FORCE; if (image_dump) flags |= EXT2_FLAG_IMAGE_FILE; + if (header_only) + flags |= EXT2_FLAG_SUPER_ONLY; try_open_again: if (use_superblock && !use_blocksize) { for (use_blocksize = EXT2_MIN_BLOCK_SIZE; diff --git a/misc/tune2fs.c b/misc/tune2fs.c index 39cf858..fbd2059 100644 --- a/misc/tune2fs.c +++ b/misc/tune2fs.c @@ -1708,7 +1708,7 @@ static void parse_e2label_options(int argc, char ** argv) argv[1]); exit(1); } - open_flag = EXT2_FLAG_JOURNAL_DEV_OK; + open_flag = EXT2_FLAG_JOURNAL_DEV_OK | EXT2_FLAG_SUPER_ONLY; if (argc == 3) { open_flag |= EXT2_FLAG_RW; L_flag = 1; -- 1.8.3.1