]>
Commit | Line | Data |
---|---|---|
00e5a55c BS |
1 | From: mason@suse.de |
2 | Subject: make sure O_SYNC writes properly return -EIO | |
3 | References: bnc#58622 | |
4 | ||
5 | Make sure to honor the error status of synchronous writeback during | |
6 | O_SYNC writes | |
7 | ||
8 | Acked-by: Jeff Mahoney <jeffm@suse.com> | |
9 | ||
10 | --- | |
11 | mm/filemap.c | 17 +++++++++++++++-- | |
12 | 1 file changed, 15 insertions(+), 2 deletions(-) | |
13 | ||
14 | --- a/mm/filemap.c | |
15 | +++ b/mm/filemap.c | |
16 | @@ -2497,7 +2497,7 @@ generic_file_buffered_write(struct kiocb | |
17 | ||
18 | if (likely(status >= 0)) { | |
19 | written += status; | |
20 | - *ppos = pos + status; | |
21 | + pos += status; | |
22 | ||
23 | /* | |
24 | * For now, when the user asks for O_SYNC, we'll actually give | |
25 | @@ -2515,10 +2515,23 @@ generic_file_buffered_write(struct kiocb | |
26 | * to buffered writes (block instantiation inside i_size). So we sync | |
27 | * the file data here, to try to honour O_DIRECT expectations. | |
28 | */ | |
29 | - if (unlikely(file->f_flags & O_DIRECT) && written) | |
30 | + if (unlikely(file->f_flags & O_DIRECT) && status >= 0 && written) | |
31 | status = filemap_write_and_wait_range(mapping, | |
32 | pos, pos + written - 1); | |
33 | ||
34 | + /* | |
35 | + * We must let know userspace if something hasn't been written | |
36 | + * correctly. If we got an I/O error it means we got an hardware | |
37 | + * failure, anything can be happening to the on-disk data, | |
38 | + * letting know userspace that a bit of data might have been | |
39 | + * written correctly on disk is a very low priority, compared | |
40 | + * to letting know userspace that some data has _not_ been | |
41 | + * written at all. | |
42 | + */ | |
43 | + if (unlikely(status == -EIO)) | |
44 | + return status; | |
45 | + *ppos = pos; | |
46 | + | |
47 | return written ? written : status; | |
48 | } | |
49 | EXPORT_SYMBOL(generic_file_buffered_write); |