diff options
author | Theodore Ts'o <tytso@mit.edu> | 2008-10-09 23:53:47 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2008-10-09 23:53:47 -0400 |
commit | 240799cdf22bd789ea6852653c3b879d35ad0a6c (patch) | |
tree | e696b60cc103f23838b5c14d8d397f692abffbc3 /fs/ext4/super.c | |
parent | 37515facd001942221d68171c81c1f46d54ffdd0 (diff) |
ext4: Use readahead when reading an inode from the inode table
With modern hard drives, reading 64k takes roughly the same time as
reading a 4k block. So request readahead for adjacent inode table
blocks to reduce the time it takes when iterating over directories
(especially when doing this in htree sort order) in a cold cache case.
With this patch, the time it takes to run "git status" on a kernel
tree after flushing the caches via "echo 3 > /proc/sys/vm/drop_caches"
is reduced by 21%.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/super.c')
-rw-r--r-- | fs/ext4/super.c | 27 |
1 files changed, 25 insertions, 2 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 9f5468fb06da..6583aee5177f 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -515,8 +515,10 @@ static void ext4_put_super(struct super_block *sb) | |||
515 | mark_buffer_dirty(sbi->s_sbh); | 515 | mark_buffer_dirty(sbi->s_sbh); |
516 | ext4_commit_super(sb, es, 1); | 516 | ext4_commit_super(sb, es, 1); |
517 | } | 517 | } |
518 | if (sbi->s_proc) | 518 | if (sbi->s_proc) { |
519 | remove_proc_entry("inode_readahead_blks", sbi->s_proc); | ||
519 | remove_proc_entry(sb->s_id, ext4_proc_root); | 520 | remove_proc_entry(sb->s_id, ext4_proc_root); |
521 | } | ||
520 | 522 | ||
521 | for (i = 0; i < sbi->s_gdb_count; i++) | 523 | for (i = 0; i < sbi->s_gdb_count; i++) |
522 | brelse(sbi->s_group_desc[i]); | 524 | brelse(sbi->s_group_desc[i]); |
@@ -779,6 +781,10 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
779 | else if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA) | 781 | else if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA) |
780 | seq_puts(seq, ",data=writeback"); | 782 | seq_puts(seq, ",data=writeback"); |
781 | 783 | ||
784 | if (sbi->s_inode_readahead_blks != EXT4_DEF_INODE_READAHEAD_BLKS) | ||
785 | seq_printf(seq, ",inode_readahead_blks=%u", | ||
786 | sbi->s_inode_readahead_blks); | ||
787 | |||
782 | ext4_show_quota_options(seq, sb); | 788 | ext4_show_quota_options(seq, sb); |
783 | return 0; | 789 | return 0; |
784 | } | 790 | } |
@@ -913,6 +919,7 @@ enum { | |||
913 | Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota, | 919 | Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota, |
914 | Opt_grpquota, Opt_extents, Opt_noextents, Opt_i_version, | 920 | Opt_grpquota, Opt_extents, Opt_noextents, Opt_i_version, |
915 | Opt_mballoc, Opt_nomballoc, Opt_stripe, Opt_delalloc, Opt_nodelalloc, | 921 | Opt_mballoc, Opt_nomballoc, Opt_stripe, Opt_delalloc, Opt_nodelalloc, |
922 | Opt_inode_readahead_blks | ||
916 | }; | 923 | }; |
917 | 924 | ||
918 | static match_table_t tokens = { | 925 | static match_table_t tokens = { |
@@ -973,6 +980,7 @@ static match_table_t tokens = { | |||
973 | {Opt_resize, "resize"}, | 980 | {Opt_resize, "resize"}, |
974 | {Opt_delalloc, "delalloc"}, | 981 | {Opt_delalloc, "delalloc"}, |
975 | {Opt_nodelalloc, "nodelalloc"}, | 982 | {Opt_nodelalloc, "nodelalloc"}, |
983 | {Opt_inode_readahead_blks, "inode_readahead_blks=%u"}, | ||
976 | {Opt_err, NULL}, | 984 | {Opt_err, NULL}, |
977 | }; | 985 | }; |
978 | 986 | ||
@@ -1381,6 +1389,13 @@ set_qf_format: | |||
1381 | case Opt_delalloc: | 1389 | case Opt_delalloc: |
1382 | set_opt(sbi->s_mount_opt, DELALLOC); | 1390 | set_opt(sbi->s_mount_opt, DELALLOC); |
1383 | break; | 1391 | break; |
1392 | case Opt_inode_readahead_blks: | ||
1393 | if (match_int(&args[0], &option)) | ||
1394 | return 0; | ||
1395 | if (option < 0 || option > (1 << 30)) | ||
1396 | return 0; | ||
1397 | sbi->s_inode_readahead_blks = option; | ||
1398 | break; | ||
1384 | default: | 1399 | default: |
1385 | printk(KERN_ERR | 1400 | printk(KERN_ERR |
1386 | "EXT4-fs: Unrecognized mount option \"%s\" " | 1401 | "EXT4-fs: Unrecognized mount option \"%s\" " |
@@ -1938,6 +1953,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
1938 | sbi->s_mount_opt = 0; | 1953 | sbi->s_mount_opt = 0; |
1939 | sbi->s_resuid = EXT4_DEF_RESUID; | 1954 | sbi->s_resuid = EXT4_DEF_RESUID; |
1940 | sbi->s_resgid = EXT4_DEF_RESGID; | 1955 | sbi->s_resgid = EXT4_DEF_RESGID; |
1956 | sbi->s_inode_readahead_blks = EXT4_DEF_INODE_READAHEAD_BLKS; | ||
1941 | sbi->s_sb_block = sb_block; | 1957 | sbi->s_sb_block = sb_block; |
1942 | 1958 | ||
1943 | unlock_kernel(); | 1959 | unlock_kernel(); |
@@ -2234,6 +2250,11 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
2234 | if (ext4_proc_root) | 2250 | if (ext4_proc_root) |
2235 | sbi->s_proc = proc_mkdir(sb->s_id, ext4_proc_root); | 2251 | sbi->s_proc = proc_mkdir(sb->s_id, ext4_proc_root); |
2236 | 2252 | ||
2253 | if (sbi->s_proc) | ||
2254 | proc_create_data("inode_readahead_blks", 0644, sbi->s_proc, | ||
2255 | &ext4_ui_proc_fops, | ||
2256 | &sbi->s_inode_readahead_blks); | ||
2257 | |||
2237 | bgl_lock_init(&sbi->s_blockgroup_lock); | 2258 | bgl_lock_init(&sbi->s_blockgroup_lock); |
2238 | 2259 | ||
2239 | for (i = 0; i < db_count; i++) { | 2260 | for (i = 0; i < db_count; i++) { |
@@ -2513,8 +2534,10 @@ failed_mount2: | |||
2513 | brelse(sbi->s_group_desc[i]); | 2534 | brelse(sbi->s_group_desc[i]); |
2514 | kfree(sbi->s_group_desc); | 2535 | kfree(sbi->s_group_desc); |
2515 | failed_mount: | 2536 | failed_mount: |
2516 | if (sbi->s_proc) | 2537 | if (sbi->s_proc) { |
2538 | remove_proc_entry("inode_readahead_blks", sbi->s_proc); | ||
2517 | remove_proc_entry(sb->s_id, ext4_proc_root); | 2539 | remove_proc_entry(sb->s_id, ext4_proc_root); |
2540 | } | ||
2518 | #ifdef CONFIG_QUOTA | 2541 | #ifdef CONFIG_QUOTA |
2519 | for (i = 0; i < MAXQUOTAS; i++) | 2542 | for (i = 0; i < MAXQUOTAS; i++) |
2520 | kfree(sbi->s_qf_names[i]); | 2543 | kfree(sbi->s_qf_names[i]); |