Next3 transactions reserve up to 24 times more credits than Ext3 transactions for the same operation. On mke2fs and tune2fs, if the 'big_journal' feature is set along with the 'has_journal' feature, increase the default journal size by a factor of 24. Signed-off-by: Amir Goldstein <amir73il@xxxxxxxxxxxx> --- lib/ext2fs/ext2_fs.h | 11 ++++++++++ lib/ext2fs/ext2fs.h | 2 + lib/ext2fs/mkjournal.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++ misc/mke2fs.c | 1 + misc/tune2fs.c | 23 +++++++++++++++++++++- misc/util.c | 14 +++++++++++++ 6 files changed, 99 insertions(+), 1 deletions(-) diff --git a/lib/ext2fs/ext2_fs.h b/lib/ext2fs/ext2_fs.h index 35b9ac3..7a1fc58 100644 --- a/lib/ext2fs/ext2_fs.h +++ b/lib/ext2fs/ext2_fs.h @@ -621,6 +621,17 @@ struct ext2_super_block { #define EXT3_JNL_BACKUP_BLOCKS 1 /* + * 'big journal' needs to accomodate extra snapshot COW credits + * default size accomodates maximum possible COW credits + * minimum required size accomodates the avarage COW credits + */ +#define EXT3_DEF_JOURNAL_BLOCKS 32768 +#define NEXT3_AVG_COW_CREDITS 16 +#define NEXT3_MAX_COW_CREDITS 24 +#define NEXT3_MIN_JOURNAL_BLOCKS (EXT3_DEF_JOURNAL_BLOCKS*NEXT3_AVG_COW_CREDITS) +#define NEXT3_DEF_JOURNAL_BLOCKS (EXT3_DEF_JOURNAL_BLOCKS*NEXT3_MAX_COW_CREDITS) + +/* * Feature set definitions */ diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h index c2d9fb9..2af8f1c 100644 --- a/lib/ext2fs/ext2fs.h +++ b/lib/ext2fs/ext2fs.h @@ -1222,6 +1222,8 @@ extern errcode_t ext2fs_add_journal_device(ext2_filsys fs, extern errcode_t ext2fs_add_journal_inode(ext2_filsys fs, blk_t size, int flags); extern int ext2fs_default_journal_size(__u64 blocks); +extern int ext2fs_big_journal_size(__u64 blocks); +extern int ext2fs_check_journal_size(ext2_filsys fs); /* openfs.c */ extern errcode_t ext2fs_open(const char *name, int flags, int superblock, diff --git a/lib/ext2fs/mkjournal.c b/lib/ext2fs/mkjournal.c index 6afbbde..c68cdaa 100644 --- a/lib/ext2fs/mkjournal.c +++ b/lib/ext2fs/mkjournal.c @@ -400,6 +400,54 @@ int ext2fs_default_journal_size(__u64 blocks) return 32768; } +/* + * Big journal is up to 24 times bigger than the default journal + * to accomodate snapshot COW credits in transactions. + * journal size is restricted to 1/32 of the filesystem size + */ +int ext2fs_big_journal_size(__u64 blocks) +{ + int mega_blocks = blocks >> 20; + if (!mega_blocks) + return -1; + + if (mega_blocks < NEXT3_MAX_COW_CREDITS) + /* 32K/1M = 1/32 of filesystem size */ + return 32768*mega_blocks; + + /* 24 times bigger than the default journal */ + return 32768*NEXT3_MAX_COW_CREDITS; +} + +/* + * Find the number of blocks in the journal inode + * and adjust the file system 'big_journal' feature accordingy + */ +int ext2fs_check_journal_size(ext2_filsys fs) +{ + struct ext2_inode j_inode; + int j_blocks; + + if (!(fs->super->s_feature_compat & + EXT3_FEATURE_COMPAT_HAS_JOURNAL) || + !fs->super->s_journal_inum) + return 0; + + if (ext2fs_read_inode(fs, fs->super->s_journal_inum, &j_inode)) + return -1; + + /* read journal inode size */ + j_blocks = j_inode.i_size >> EXT2_BLOCK_SIZE_BITS(fs->super); + + /* fix the 'big_journal' feature */ + if (j_blocks >= NEXT3_MIN_JOURNAL_BLOCKS) + fs->super->s_feature_compat |= NEXT3_FEATURE_COMPAT_BIG_JOURNAL; + else + fs->super->s_feature_compat &= ~NEXT3_FEATURE_COMPAT_BIG_JOURNAL; + + return j_blocks; +} + /* * This function adds a journal device to a filesystem */ @@ -553,6 +601,7 @@ errcode_t ext2fs_add_journal_inode(ext2_filsys fs, blk_t size, int flags) sizeof(fs->super->s_journal_uuid)); fs->super->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL; + ext2fs_check_journal_size(fs); ext2fs_mark_super_dirty(fs); return 0; errout: diff --git a/misc/mke2fs.c b/misc/mke2fs.c index 022c12c..0859d61 100644 --- a/misc/mke2fs.c +++ b/misc/mke2fs.c @@ -781,6 +781,7 @@ static void parse_extended_opts(struct ext2_super_block *param, static __u32 ok_features[3] = { /* Compat */ EXT3_FEATURE_COMPAT_HAS_JOURNAL | + NEXT3_FEATURE_COMPAT_BIG_JOURNAL | EXT2_FEATURE_COMPAT_RESIZE_INODE | EXT2_FEATURE_COMPAT_DIR_INDEX | EXT2_FEATURE_COMPAT_EXT_ATTR, diff --git a/misc/tune2fs.c b/misc/tune2fs.c index 847b3e2..b4733e8 100644 --- a/misc/tune2fs.c +++ b/misc/tune2fs.c @@ -119,6 +119,7 @@ static void usage(void) static __u32 ok_features[3] = { /* Compat */ EXT3_FEATURE_COMPAT_HAS_JOURNAL | + NEXT3_FEATURE_COMPAT_BIG_JOURNAL | EXT2_FEATURE_COMPAT_DIR_INDEX, /* Incompat */ EXT2_FEATURE_INCOMPAT_FILETYPE | @@ -136,6 +137,7 @@ static __u32 ok_features[3] = { static __u32 clear_ok_features[3] = { /* Compat */ EXT3_FEATURE_COMPAT_HAS_JOURNAL | + NEXT3_FEATURE_COMPAT_BIG_JOURNAL | EXT2_FEATURE_COMPAT_RESIZE_INODE | EXT2_FEATURE_COMPAT_DIR_INDEX, /* Incompat */ @@ -403,6 +405,23 @@ static void update_feature_set(ext2_filsys fs, char *features) sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL; } + if (FEATURE_CHANGED(E2P_FEATURE_COMPAT, NEXT3_FEATURE_COMPAT_BIG_JOURNAL)) { + if (sb->s_feature_compat & + EXT3_FEATURE_COMPAT_HAS_JOURNAL) { + /* update 'big_journal' flag according to existing journal size */ + ext2fs_check_journal_size(fs); + if (!FEATURE_CHANGED(E2P_FEATURE_COMPAT, NEXT3_FEATURE_COMPAT_BIG_JOURNAL)) + fputs(_("the filesystem already has a journal.\n" + "Please remove it before changing " + "the big_journal flag.\n"), stderr); + } + else if (sb->s_feature_compat & NEXT3_FEATURE_COMPAT_BIG_JOURNAL) { + /* create 'big_journal' */ + if (!journal_size) + journal_size = -1; + } + } + if (FEATURE_ON(E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_DIR_INDEX)) { if (!sb->s_def_hash_version) sb->s_def_hash_version = EXT2_HASH_HALF_MD4; @@ -1792,8 +1811,10 @@ retry_open: } } - if (l_flag) + if (l_flag) { + ext2fs_check_journal_size(fs); list_super(sb); + } if (stride_set) { sb->s_raid_stride = stride; ext2fs_mark_super_dirty(fs); diff --git a/misc/util.c b/misc/util.c index b8a3cac..8646b8d 100644 --- a/misc/util.c +++ b/misc/util.c @@ -259,6 +259,20 @@ unsigned int figure_journal_size(int size, ext2_filsys fs) return 0; } + if (fs->super->s_feature_compat & NEXT3_FEATURE_COMPAT_BIG_JOURNAL) { + /* big journal requested */ + j_blocks = ext2fs_big_journal_size(fs->super->s_blocks_count); + if (j_blocks < NEXT3_MIN_JOURNAL_BLOCKS) { + fputs(_("\nFilesystem too small for a big journal. "), + stderr); + if (j_blocks < 0) { + fputs(_("Aborting.\n"), stderr); + exit(1); + } + fputs(_("Creating a smaller journal.\n"), stderr); + } + } + if (size > 0) { j_blocks = size * 1024 / (fs->blocksize / 1024); if (j_blocks < 1024 || j_blocks > 10240000) { -- 1.6.6 -- 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