50 lines
1.5 KiB
Plaintext
50 lines
1.5 KiB
Plaintext
|
From: mason@suse.de
|
||
|
Subject: make sure O_SYNC writes properly return -EIO
|
||
|
References: bnc#58622
|
||
|
|
||
|
Make sure to honor the error status of synchronous writeback during
|
||
|
O_SYNC writes
|
||
|
|
||
|
Acked-by: Jeff Mahoney <jeffm@suse.com>
|
||
|
|
||
|
---
|
||
|
mm/filemap.c | 17 +++++++++++++++--
|
||
|
1 file changed, 15 insertions(+), 2 deletions(-)
|
||
|
|
||
|
--- a/mm/filemap.c
|
||
|
+++ b/mm/filemap.c
|
||
|
@@ -2325,7 +2325,7 @@ generic_file_buffered_write(struct kiocb
|
||
|
|
||
|
if (likely(status >= 0)) {
|
||
|
written += status;
|
||
|
- *ppos = pos + status;
|
||
|
+ pos += status;
|
||
|
|
||
|
/*
|
||
|
* For now, when the user asks for O_SYNC, we'll actually give
|
||
|
@@ -2343,10 +2343,23 @@ generic_file_buffered_write(struct kiocb
|
||
|
* to buffered writes (block instantiation inside i_size). So we sync
|
||
|
* the file data here, to try to honour O_DIRECT expectations.
|
||
|
*/
|
||
|
- if (unlikely(file->f_flags & O_DIRECT) && written)
|
||
|
+ if (unlikely(file->f_flags & O_DIRECT) && status >= 0 && written)
|
||
|
status = filemap_write_and_wait_range(mapping,
|
||
|
pos, pos + written - 1);
|
||
|
|
||
|
+ /*
|
||
|
+ * We must let know userspace if something hasn't been written
|
||
|
+ * correctly. If we got an I/O error it means we got an hardware
|
||
|
+ * failure, anything can be happening to the on-disk data,
|
||
|
+ * letting know userspace that a bit of data might have been
|
||
|
+ * written correctly on disk is a very low priority, compared
|
||
|
+ * to letting know userspace that some data has _not_ been
|
||
|
+ * written at all.
|
||
|
+ */
|
||
|
+ if (unlikely(status == -EIO))
|
||
|
+ return status;
|
||
|
+ *ppos = pos;
|
||
|
+
|
||
|
return written ? written : status;
|
||
|
}
|
||
|
EXPORT_SYMBOL(generic_file_buffered_write);
|