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 --- mm/filemap.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) --- a/mm/filemap.c +++ b/mm/filemap.c @@ -2498,7 +2498,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 @@ -2516,10 +2516,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);