ext3: enable cache flush in ext3_sync_file
PATCH 1/1 ext3: enable cache flush in ext3_sync_file
We need to flush the write cache unconditionally in ->fsync, otherwise writes into already allocated blocks can get lost. Writes into fully allocated files are very common when using disk images for virtualization, and without this fix can easily lose data after an fdatasync, which is the typical implementation for a cache flush on the virtual drive.
fs/ext3/fsync.c +3 -0
@@ -23,6 +23,7 @@*/ #include <linux/time.h> +#include <linux/blkdev.h> #include <linux/fs.h> #include <linux/sched.h> #include <linux/writeback.h>
@@ -87,5 +88,7 @@ int ext3_sync_file(struct file * file, s ret =sync_inode (inode, &wbc); } out: +if (test_opt (inode->i_sb,BARRIER )) +blkdev_issue_flush (inode->i_sb->s_bdev,NULL );return ret; }
Quoted 9 lines · Christoph Hellwig
We need to flush the write cache unconditionally in ->fsync, otherwise writes into already allocated blocks can get lost. Writes into fully allocated files are very common when using disk images for virtualization, and without this fix can easily lose data after an fdatasync, which is the typical implementation for a cache flush on the virtual drive.
Signed-off-by Christoph Hellwig <[email protected]>
Given that I tried to do the same thing 1.5 years ago (though not quite correctly) ...
Quoted 25 lines
Index:
linux-2.6/fs/ext3/fsync.c
===================================================================fs/ext3/fsync.c +3
-1@@ -23,6 +23,7 @@*/ #include <linux/time.h> +#include <linux/blkdev.h> #include <linux/fs.h> #include <linux/sched.h> #include <linux/writeback.h> @@ -87,5 +88,7 @@ int ext3_sync_file(struct file * file, s ret =sync_inode (inode, &wbc); } out: +if (test_opt (inode->i_sb,BARRIER )) +blkdev_issue_flush (inode->i_sb->s_bdev,NULL );return ret; } --To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 9 lines
Quoted 8 lines · Christoph Hellwig
We need to flush the write cache unconditionally in ->fsync, otherwise writes into already allocated blocks can get lost. Writes into fully allocated files are very common when using disk images for virtualization, and without this fix can easily lose data after an fdatasync, which is the typical implementation for a cache flush on the virtual drive.
Quoted 6 lines
Quoted 1 line
Signed-off-by Christoph Hellwig <[email protected]>Given that I tried to do the same thing 1.5 years ago (though not quite correctly) ...
Acked-by Eric Sandeen <[email protected]>
But would the patch below be better? When we force a transaction
commit we don't have to flush caches again. Or am I missing something?
Honza
Signature · 2 lines
Jan Kara <[email protected]> SuSE CR Labs
Quoted 1 line
From
4412c3d5cc04849d959e9083d3bdf0b4a058e947Mon Sep 17 00:00:00 2001
From: Jan Kara <[email protected]>
Date: Tue, 8 Sep 2009 14:59:42 +0200
Subject: [PATCH] ext3: Flush disk caches on fsync when needed
In case we fsync() a file and inode is not dirty, we don't force a transaction to disk and hence don't flush disk caches. Thus file data could be just in disk caches and not on persistent storage. Fix the problem by flushing disk caches if we didn't force a transaction commit.
--- fs/ext3/fsync.c | 12 +++++++++++- 1 files changed, 11 insertions(+), 1 deletions(-)
fs/ext3/fsync.c +11 -1
@@ -23,6 +23,7 @@*/ #include <linux/time.h> +#include <linux/blkdev.h> #include <linux/fs.h> #include <linux/sched.h> #include <linux/writeback.h>
@@ -73,7 +74,7 @@ int ext3_sync_file(struct file * file, struct dentry *dentry, int datasync) }if (datasync && !(inode->i_state &I_DIRTY_DATASYNC )) - goto out; + goto flush;/* * The VFS has written the file data. If the inode is unaltered
@@ -85,7 +86,16 @@ int ext3_sync_file(struct file * file, struct dentry *dentry, int datasync) .nr_to_write = 0, /* sys_fsync did this */ }; ret =sync_inode (inode, &wbc); + goto out; } +flush: +/* +* In case we didn't commit a transaction, we have to flush +* disk caches manually so that data really is on persistent +* storage +*/ +if (test_opt (inode->i_sb,BARRIER )) +blkdev_issue_flush (inode->i_sb->s_bdev,NULL ); out:return ret; }
Signature · 1 line
1.6.0.2
Quoted 3 lines · Jan Kara
Quoted 1 line
Acked-by Eric Sandeen <[email protected]>But would the patch below be better? When we force a transaction
commit we don't have to flush caches again. Or am I missing something?
If you know that you really did issue a barrier for sure you don't have to flush the cache again. I don't know extN enough to easily figure out how, but if this patch ensures that it's good. Same scheme should also apply to ext4.