aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/super.c
diff options
context:
space:
mode:
authorJiaying Zhang <jiayingz@google.com>2010-03-04 16:14:02 -0500
committerTheodore Ts'o <tytso@mit.edu>2010-03-04 16:14:02 -0500
commit744692dc059845b2a3022119871846e74d4f6e11 (patch)
treeed246651aebcb8dae57de8c58dc20983064ee017 /fs/ext4/super.c
parentc7064ef13b2181a489836349f9baf87df0dab28f (diff)
ext4: use ext4_get_block_write in buffer write
Allocate uninitialized extent before ext4 buffer write and convert the extent to initialized after io completes. The purpose is to make sure an extent can only be marked initialized after it has been written with new data so we can safely drop the i_mutex lock in ext4 DIO read without exposing stale data. This helps to improve multi-thread DIO read performance on high-speed disks. Skip the nobh and data=journal mount cases to make things simple for now. Signed-off-by: Jiaying Zhang <jiayingz@google.com> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/super.c')
-rw-r--r--fs/ext4/super.c37
1 files changed, 33 insertions, 4 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index dc7a97e79e3b..5e8f9077b0fc 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -709,6 +709,7 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
709 ei->i_reserved_quota = 0; 709 ei->i_reserved_quota = 0;
710#endif 710#endif
711 INIT_LIST_HEAD(&ei->i_completed_io_list); 711 INIT_LIST_HEAD(&ei->i_completed_io_list);
712 spin_lock_init(&ei->i_completed_io_lock);
712 ei->cur_aio_dio = NULL; 713 ei->cur_aio_dio = NULL;
713 ei->i_sync_tid = 0; 714 ei->i_sync_tid = 0;
714 ei->i_datasync_tid = 0; 715 ei->i_datasync_tid = 0;
@@ -926,6 +927,9 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs)
926 if (test_opt(sb, NOLOAD)) 927 if (test_opt(sb, NOLOAD))
927 seq_puts(seq, ",norecovery"); 928 seq_puts(seq, ",norecovery");
928 929
930 if (test_opt(sb, DIOREAD_NOLOCK))
931 seq_puts(seq, ",dioread_nolock");
932
929 ext4_show_quota_options(seq, sb); 933 ext4_show_quota_options(seq, sb);
930 934
931 return 0; 935 return 0;
@@ -1109,6 +1113,7 @@ enum {
1109 Opt_stripe, Opt_delalloc, Opt_nodelalloc, 1113 Opt_stripe, Opt_delalloc, Opt_nodelalloc,
1110 Opt_block_validity, Opt_noblock_validity, 1114 Opt_block_validity, Opt_noblock_validity,
1111 Opt_inode_readahead_blks, Opt_journal_ioprio, 1115 Opt_inode_readahead_blks, Opt_journal_ioprio,
1116 Opt_dioread_nolock, Opt_dioread_lock,
1112 Opt_discard, Opt_nodiscard, 1117 Opt_discard, Opt_nodiscard,
1113}; 1118};
1114 1119
@@ -1176,6 +1181,8 @@ static const match_table_t tokens = {
1176 {Opt_auto_da_alloc, "auto_da_alloc=%u"}, 1181 {Opt_auto_da_alloc, "auto_da_alloc=%u"},
1177 {Opt_auto_da_alloc, "auto_da_alloc"}, 1182 {Opt_auto_da_alloc, "auto_da_alloc"},
1178 {Opt_noauto_da_alloc, "noauto_da_alloc"}, 1183 {Opt_noauto_da_alloc, "noauto_da_alloc"},
1184 {Opt_dioread_nolock, "dioread_nolock"},
1185 {Opt_dioread_lock, "dioread_lock"},
1179 {Opt_discard, "discard"}, 1186 {Opt_discard, "discard"},
1180 {Opt_nodiscard, "nodiscard"}, 1187 {Opt_nodiscard, "nodiscard"},
1181 {Opt_err, NULL}, 1188 {Opt_err, NULL},
@@ -1640,6 +1647,12 @@ set_qf_format:
1640 case Opt_nodiscard: 1647 case Opt_nodiscard:
1641 clear_opt(sbi->s_mount_opt, DISCARD); 1648 clear_opt(sbi->s_mount_opt, DISCARD);
1642 break; 1649 break;
1650 case Opt_dioread_nolock:
1651 set_opt(sbi->s_mount_opt, DIOREAD_NOLOCK);
1652 break;
1653 case Opt_dioread_lock:
1654 clear_opt(sbi->s_mount_opt, DIOREAD_NOLOCK);
1655 break;
1643 default: 1656 default:
1644 ext4_msg(sb, KERN_ERR, 1657 ext4_msg(sb, KERN_ERR,
1645 "Unrecognized mount option \"%s\" " 1658 "Unrecognized mount option \"%s\" "
@@ -2795,7 +2808,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
2795 EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER)) { 2808 EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER)) {
2796 ext4_msg(sb, KERN_ERR, "required journal recovery " 2809 ext4_msg(sb, KERN_ERR, "required journal recovery "
2797 "suppressed and not mounted read-only"); 2810 "suppressed and not mounted read-only");
2798 goto failed_mount4; 2811 goto failed_mount_wq;
2799 } else { 2812 } else {
2800 clear_opt(sbi->s_mount_opt, DATA_FLAGS); 2813 clear_opt(sbi->s_mount_opt, DATA_FLAGS);
2801 set_opt(sbi->s_mount_opt, WRITEBACK_DATA); 2814 set_opt(sbi->s_mount_opt, WRITEBACK_DATA);
@@ -2808,7 +2821,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
2808 !jbd2_journal_set_features(EXT4_SB(sb)->s_journal, 0, 0, 2821 !jbd2_journal_set_features(EXT4_SB(sb)->s_journal, 0, 0,
2809 JBD2_FEATURE_INCOMPAT_64BIT)) { 2822 JBD2_FEATURE_INCOMPAT_64BIT)) {
2810 ext4_msg(sb, KERN_ERR, "Failed to set 64-bit journal feature"); 2823 ext4_msg(sb, KERN_ERR, "Failed to set 64-bit journal feature");
2811 goto failed_mount4; 2824 goto failed_mount_wq;
2812 } 2825 }
2813 2826
2814 if (test_opt(sb, JOURNAL_ASYNC_COMMIT)) { 2827 if (test_opt(sb, JOURNAL_ASYNC_COMMIT)) {
@@ -2847,7 +2860,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
2847 (sbi->s_journal, 0, 0, JBD2_FEATURE_INCOMPAT_REVOKE)) { 2860 (sbi->s_journal, 0, 0, JBD2_FEATURE_INCOMPAT_REVOKE)) {
2848 ext4_msg(sb, KERN_ERR, "Journal does not support " 2861 ext4_msg(sb, KERN_ERR, "Journal does not support "
2849 "requested data journaling mode"); 2862 "requested data journaling mode");
2850 goto failed_mount4; 2863 goto failed_mount_wq;
2851 } 2864 }
2852 default: 2865 default:
2853 break; 2866 break;
@@ -2855,13 +2868,17 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
2855 set_task_ioprio(sbi->s_journal->j_task, journal_ioprio); 2868 set_task_ioprio(sbi->s_journal->j_task, journal_ioprio);
2856 2869
2857no_journal: 2870no_journal:
2858
2859 if (test_opt(sb, NOBH)) { 2871 if (test_opt(sb, NOBH)) {
2860 if (!(test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA)) { 2872 if (!(test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA)) {
2861 ext4_msg(sb, KERN_WARNING, "Ignoring nobh option - " 2873 ext4_msg(sb, KERN_WARNING, "Ignoring nobh option - "
2862 "its supported only with writeback mode"); 2874 "its supported only with writeback mode");
2863 clear_opt(sbi->s_mount_opt, NOBH); 2875 clear_opt(sbi->s_mount_opt, NOBH);
2864 } 2876 }
2877 if (test_opt(sb, DIOREAD_NOLOCK)) {
2878 ext4_msg(sb, KERN_WARNING, "dioread_nolock option is "
2879 "not supported with nobh mode");
2880 goto failed_mount_wq;
2881 }
2865 } 2882 }
2866 EXT4_SB(sb)->dio_unwritten_wq = create_workqueue("ext4-dio-unwritten"); 2883 EXT4_SB(sb)->dio_unwritten_wq = create_workqueue("ext4-dio-unwritten");
2867 if (!EXT4_SB(sb)->dio_unwritten_wq) { 2884 if (!EXT4_SB(sb)->dio_unwritten_wq) {
@@ -2926,6 +2943,18 @@ no_journal:
2926 "requested data journaling mode"); 2943 "requested data journaling mode");
2927 clear_opt(sbi->s_mount_opt, DELALLOC); 2944 clear_opt(sbi->s_mount_opt, DELALLOC);
2928 } 2945 }
2946 if (test_opt(sb, DIOREAD_NOLOCK)) {
2947 if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) {
2948 ext4_msg(sb, KERN_WARNING, "Ignoring dioread_nolock "
2949 "option - requested data journaling mode");
2950 clear_opt(sbi->s_mount_opt, DIOREAD_NOLOCK);
2951 }
2952 if (sb->s_blocksize < PAGE_SIZE) {
2953 ext4_msg(sb, KERN_WARNING, "Ignoring dioread_nolock "
2954 "option - block size is too small");
2955 clear_opt(sbi->s_mount_opt, DIOREAD_NOLOCK);
2956 }
2957 }
2929 2958
2930 err = ext4_setup_system_zone(sb); 2959 err = ext4_setup_system_zone(sb);
2931 if (err) { 2960 if (err) {