From 7dca4c88f166561031011ed27287818eaa343486 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Tue, 23 Dec 2008 19:10:43 -0500 Subject: [PATCH] e2fsck: When repacking directories, leave slack space for more efficiency If the directory is packed with no slack space, as soon as any new directory entries are added, leaf nodes end up getting split and directory ends up getting very inefficient. Signed-off-by: "Theodore Ts'o" --- e2fsck/e2fsck.c | 1 + e2fsck/e2fsck.conf.5.in | 20 ++++++++++++++++---- e2fsck/e2fsck.h | 1 + e2fsck/rehash.c | 22 ++++++++++++++++++---- tests/f_h_badnode/expect.1 | 2 +- tests/f_h_badnode/expect.2 | 2 +- tests/f_h_badroot/expect.1 | 2 +- tests/f_h_badroot/expect.2 | 2 +- tests/f_h_reindex/expect.1 | 2 +- tests/f_h_reindex/expect.2 | 2 +- 10 files changed, 42 insertions(+), 14 deletions(-) diff --git a/e2fsck/e2fsck.c b/e2fsck/e2fsck.c index 9f862ffa..26f7b5e5 100644 --- a/e2fsck/e2fsck.c +++ b/e2fsck/e2fsck.c @@ -32,6 +32,7 @@ errcode_t e2fsck_allocate_context(e2fsck_t *ret) context->process_inode_size = 256; context->ext_attr_ver = 2; context->blocks_per_page = 1; + context->htree_slack_percentage = 255; time_env = getenv("E2FSCK_TIME"); if (time_env) diff --git a/e2fsck/e2fsck.conf.5.in b/e2fsck/e2fsck.conf.5.in index c66a7698..6638a394 100644 --- a/e2fsck/e2fsck.conf.5.in +++ b/e2fsck/e2fsck.conf.5.in @@ -100,6 +100,13 @@ buggy distributions do not correct this before running e2fsck. If this option is set to a boolean value of true, we attempt to work around this situation by allowing the superblock last write time, last mount time, and last check time to be in the future by up to 24 hours. +.TP +.I clear_test_fs_flag +This boolean relation controls whether or not +.BR e2fsck (8) +will offer to clear +the test_fs flag if the ext4 filesystem is available on the system. It +defaults to true. .TP .I defer_check_on_battery This boolean relation controls whether or not the interval between @@ -107,10 +114,15 @@ filesystem checks (either based on time or number of mounts) should be doubled if the system is running on battery. It defaults to true. .TP -.I clear_test_fs_flag -This boolean relation controls whether or not e2fsck will offer to clear -the test_fs flag if the ext4 filesystem is available on the system. It -defaults to true. +.I indexed_dir_slack_percentage +When +.BR e2fsck (8) +repacks a indexed directory, reserve the specified percentage of +empty space in each leaf nodes so that a few new entries can +be added to the directory without splitting leaf nodes, so that +the average fill ratio of directories can be maintained at a +higher, more efficient level. This relation defaults to 20 +percent. .SH THE [problems] STANZA Each tag in the .I [problems] diff --git a/e2fsck/e2fsck.h b/e2fsck/e2fsck.h index 9b916155..a159f2a9 100644 --- a/e2fsck/e2fsck.h +++ b/e2fsck/e2fsck.h @@ -289,6 +289,7 @@ struct e2fsck_struct { */ int process_inode_size; int inode_buffer_blocks; + unsigned int htree_slack_percentage; /* * ext3 journal support diff --git a/e2fsck/rehash.c b/e2fsck/rehash.c index 6c24bdd4..51c29930 100644 --- a/e2fsck/rehash.c +++ b/e2fsck/rehash.c @@ -397,17 +397,27 @@ static int duplicate_search_and_fix(e2fsck_t ctx, ext2_filsys fs, } -static errcode_t copy_dir_entries(ext2_filsys fs, +static errcode_t copy_dir_entries(e2fsck_t ctx, struct fill_dir_struct *fd, struct out_dir *outdir) { + ext2_filsys fs = ctx->fs; errcode_t retval; char *block_start; struct hash_entry *ent; struct ext2_dir_entry *dirent; int i, rec_len, left; ext2_dirhash_t prev_hash; - int offset; + int offset, slack; + + if (ctx->htree_slack_percentage == 255) { + profile_get_uint(ctx->profile, "options", + "indexed_dir_slack_percentage", + 0, 20, + &ctx->htree_slack_percentage); + if (ctx->htree_slack_percentage > 100) + ctx->htree_slack_percentage = 20; + } outdir->max = 0; retval = alloc_size_dir(fs, outdir, @@ -422,6 +432,10 @@ static errcode_t copy_dir_entries(ext2_filsys fs, return retval; dirent = (struct ext2_dir_entry *) block_start; left = fs->blocksize; + slack = fd->compress ? 12 : + (fs->blocksize * ctx->htree_slack_percentage)/100; + if (slack < 12) + slack = 12; for (i=0; i < fd->num_array; i++) { ent = fd->harray + i; if (ent->dir->inode == 0) @@ -449,7 +463,7 @@ static errcode_t copy_dir_entries(ext2_filsys fs, memcpy(dirent->name, ent->dir->name, dirent->name_len & 0xFF); offset += rec_len; left -= rec_len; - if (left < 12) { + if (left < slack) { dirent->rec_len += left; offset += left; left = 0; @@ -750,7 +764,7 @@ resort: * Copy the directory entries. In a htree directory these * will become the leaf nodes. */ - retval = copy_dir_entries(fs, &fd, &outdir); + retval = copy_dir_entries(ctx, &fd, &outdir); if (retval) goto errout; diff --git a/tests/f_h_badnode/expect.1 b/tests/f_h_badnode/expect.1 index 44d4a7c5..5aa3cda1 100644 --- a/tests/f_h_badnode/expect.1 +++ b/tests/f_h_badnode/expect.1 @@ -14,5 +14,5 @@ Pass 4: Checking reference counts Pass 5: Checking group summary information test_filesys: ***** FILE SYSTEM WAS MODIFIED ***** -test_filesys: 47730/100192 files (0.0% non-contiguous), 13377/31745 blocks +test_filesys: 47730/100192 files (0.0% non-contiguous), 13551/31745 blocks Exit status is 1 diff --git a/tests/f_h_badnode/expect.2 b/tests/f_h_badnode/expect.2 index 8a219978..b9dadb73 100644 --- a/tests/f_h_badnode/expect.2 +++ b/tests/f_h_badnode/expect.2 @@ -3,5 +3,5 @@ Pass 2: Checking directory structure Pass 3: Checking directory connectivity Pass 4: Checking reference counts Pass 5: Checking group summary information -test_filesys: 47730/100192 files (0.0% non-contiguous), 13377/31745 blocks +test_filesys: 47730/100192 files (0.0% non-contiguous), 13551/31745 blocks Exit status is 0 diff --git a/tests/f_h_badroot/expect.1 b/tests/f_h_badroot/expect.1 index 261000da..037942db 100644 --- a/tests/f_h_badroot/expect.1 +++ b/tests/f_h_badroot/expect.1 @@ -36,5 +36,5 @@ Pass 4: Checking reference counts Pass 5: Checking group summary information test_filesys: ***** FILE SYSTEM WAS MODIFIED ***** -test_filesys: 1921/100080 files (0.0% non-contiguous), 13642/15361 blocks +test_filesys: 1921/100080 files (0.0% non-contiguous), 13646/15361 blocks Exit status is 1 diff --git a/tests/f_h_badroot/expect.2 b/tests/f_h_badroot/expect.2 index 28f1d2aa..d5772c1e 100644 --- a/tests/f_h_badroot/expect.2 +++ b/tests/f_h_badroot/expect.2 @@ -3,5 +3,5 @@ Pass 2: Checking directory structure Pass 3: Checking directory connectivity Pass 4: Checking reference counts Pass 5: Checking group summary information -test_filesys: 1921/100080 files (0.0% non-contiguous), 13642/15361 blocks +test_filesys: 1921/100080 files (0.0% non-contiguous), 13646/15361 blocks Exit status is 0 diff --git a/tests/f_h_reindex/expect.1 b/tests/f_h_reindex/expect.1 index 45118935..a2324d76 100755 --- a/tests/f_h_reindex/expect.1 +++ b/tests/f_h_reindex/expect.1 @@ -954,5 +954,5 @@ Pass 4: Checking reference counts Pass 5: Checking group summary information test_filesys: ***** FILE SYSTEM WAS MODIFIED ***** -test_filesys: 30514/32000 files (0.0% non-contiguous), 5558/8000 blocks +test_filesys: 30514/32000 files (0.0% non-contiguous), 5669/8000 blocks Exit status is 1 diff --git a/tests/f_h_reindex/expect.2 b/tests/f_h_reindex/expect.2 index 99de4cfc..7f785afa 100644 --- a/tests/f_h_reindex/expect.2 +++ b/tests/f_h_reindex/expect.2 @@ -3,5 +3,5 @@ Pass 2: Checking directory structure Pass 3: Checking directory connectivity Pass 4: Checking reference counts Pass 5: Checking group summary information -test_filesys: 30514/32000 files (0.0% non-contiguous), 5558/8000 blocks +test_filesys: 30514/32000 files (0.0% non-contiguous), 5669/8000 blocks Exit status is 0