aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/super.c
diff options
context:
space:
mode:
authorMingming Cao <cmm@us.ibm.com>2009-09-28 15:48:41 -0400
committerTheodore Ts'o <tytso@mit.edu>2009-09-28 15:48:41 -0400
commit4c0425ff68b1b87b802ffeda7b6a46ff7da7241c (patch)
treea8718f5f4574af8e15fd876b24f4aec88d62451b /fs/ext4/super.c
parent0031462b5b392f90d17f1d75abb795883c44e969 (diff)
ext4: Use end_io callback to avoid direct I/O fallback to buffered I/O
Currently the DIO VFS code passes create = 0 when writing to the middle of file. It does this to avoid block allocation for holes, so as not to expose stale data out when there is a parallel buffered read (which does not hold the i_mutex lock). Direct I/O writes into holes falls back to buffered IO for this reason. Since preallocated extents are treated as holes when doing a get_block() look up (buffer is not mapped), direct IO over fallocate also falls back to buffered IO. Thus ext4 actually silently falls back to buffered IO in above two cases, which is undesirable. To fix this, this patch creates unitialized extents when a direct I/O write into holes in sparse files, and registering an end_io callback which converts the uninitialized extent to an initialized extent after the I/O is completed. Singed-Off-By: Mingming Cao <cmm@us.ibm.com> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/super.c')
-rw-r--r--fs/ext4/super.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 16817737ba52..1a03ea98fdd1 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -580,6 +580,9 @@ static void ext4_put_super(struct super_block *sb)
580 struct ext4_super_block *es = sbi->s_es; 580 struct ext4_super_block *es = sbi->s_es;
581 int i, err; 581 int i, err;
582 582
583 flush_workqueue(sbi->dio_unwritten_wq);
584 destroy_workqueue(sbi->dio_unwritten_wq);
585
583 lock_super(sb); 586 lock_super(sb);
584 lock_kernel(); 587 lock_kernel();
585 if (sb->s_dirt) 588 if (sb->s_dirt)
@@ -2801,6 +2804,12 @@ no_journal:
2801 clear_opt(sbi->s_mount_opt, NOBH); 2804 clear_opt(sbi->s_mount_opt, NOBH);
2802 } 2805 }
2803 } 2806 }
2807 EXT4_SB(sb)->dio_unwritten_wq = create_workqueue("ext4-dio-unwritten");
2808 if (!EXT4_SB(sb)->dio_unwritten_wq) {
2809 printk(KERN_ERR "EXT4-fs: failed to create DIO workqueue\n");
2810 goto failed_mount_wq;
2811 }
2812
2804 /* 2813 /*
2805 * The jbd2_journal_load will have done any necessary log recovery, 2814 * The jbd2_journal_load will have done any necessary log recovery,
2806 * so we can safely mount the rest of the filesystem now. 2815 * so we can safely mount the rest of the filesystem now.
@@ -2913,6 +2922,8 @@ cantfind_ext4:
2913 2922
2914failed_mount4: 2923failed_mount4:
2915 ext4_msg(sb, KERN_ERR, "mount failed"); 2924 ext4_msg(sb, KERN_ERR, "mount failed");
2925 destroy_workqueue(EXT4_SB(sb)->dio_unwritten_wq);
2926failed_mount_wq:
2916 ext4_release_system_zone(sb); 2927 ext4_release_system_zone(sb);
2917 if (sbi->s_journal) { 2928 if (sbi->s_journal) {
2918 jbd2_journal_destroy(sbi->s_journal); 2929 jbd2_journal_destroy(sbi->s_journal);