]>
Commit | Line | Data |
---|---|---|
2cb7cef9 BS |
1 | From: Chris Mason <mason@suse.com> |
2 | Subject: ext2 should force the FS readonly for metadata write errors | |
3 | References: 65718 | |
4 | ||
5 | During fsync we should check for write errors to the block device in order to make | |
6 | sure all metadata writes have been properly written to the disk. Without this check | |
7 | writes that happen through the normal async mechanisms might hit errors without | |
8 | reporting them back to the application. | |
9 | ||
10 | Acked-by: Jeff Mahoney <jeffm@suse.com> | |
11 | ||
12 | --- | |
13 | fs/ext2/fsync.c | 17 +++++++++++++++++ | |
14 | 1 file changed, 17 insertions(+) | |
15 | ||
16 | --- a/fs/ext2/fsync.c | |
17 | +++ b/fs/ext2/fsync.c | |
18 | @@ -24,6 +24,7 @@ | |
19 | ||
20 | #include "ext2.h" | |
21 | #include <linux/buffer_head.h> /* for sync_mapping_buffers() */ | |
22 | +#include <linux/pagemap.h> | |
23 | ||
24 | ||
25 | /* | |
26 | @@ -34,10 +35,26 @@ | |
27 | int ext2_sync_file(struct file *file, struct dentry *dentry, int datasync) | |
28 | { | |
29 | struct inode *inode = dentry->d_inode; | |
30 | + struct super_block *sb = inode->i_sb; | |
31 | int err; | |
32 | int ret; | |
33 | ||
34 | ret = sync_mapping_buffers(inode->i_mapping); | |
35 | + | |
36 | + /* it might make more sense to ext2_error on -EIO from | |
37 | + * sync_mapping_buffers as well, but those errors are isolated to just | |
38 | + * this file. We can safely return -EIO to fsync and let the app know | |
39 | + * they have a problem. | |
40 | + * | |
41 | + * AS_EIO indicates a failure to write a metadata page, but we have no | |
42 | + * way of knowing which one. It's best to force readonly and let fsck | |
43 | + * figure it all out. | |
44 | + */ | |
45 | + if (test_and_clear_bit(AS_EIO, &sb->s_bdev->bd_inode->i_mapping->flags)) { | |
46 | + ext2_error(sb, "ext2_sync_file", "metadata io error"); | |
47 | + if (!ret) | |
48 | + ret = -EIO; | |
49 | + } | |
50 | if (!(inode->i_state & I_DIRTY)) | |
51 | return ret; | |
52 | if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) |