Commit 00266770 authored by Nick Piggin's avatar Nick Piggin Committed by Linus Torvalds

mm: write_cache_pages writepage error fix

In write_cache_pages, if ret signals a real error, but we still have some
pages left in the pagevec, done would be set to 1, but the remaining pages
would continue to be processed and ret will be overwritten in the process.

It could easily be overwritten with success, and thus success will be
returned even if there is an error.  Thus the caller is told all writes
succeeded, wheras in reality some did not.

Fix this by bailing immediately if there is an error, and retaining the
first error code.

This is a data integrity bug.
Signed-off-by: default avatarNick Piggin <npiggin@suse.de>
Cc: Chris Mason <chris.mason@oracle.com>
Cc: Dave Chinner <david@fromorbit.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent bd19e012
...@@ -944,12 +944,26 @@ int write_cache_pages(struct address_space *mapping, ...@@ -944,12 +944,26 @@ int write_cache_pages(struct address_space *mapping,
} }
ret = (*writepage)(page, wbc, data); ret = (*writepage)(page, wbc, data);
if (unlikely(ret)) {
if (unlikely(ret == AOP_WRITEPAGE_ACTIVATE)) { if (ret == AOP_WRITEPAGE_ACTIVATE) {
unlock_page(page); unlock_page(page);
ret = 0; ret = 0;
} else {
/*
* done_index is set past this page,
* so media errors will not choke
* background writeout for the entire
* file. This has consequences for
* range_cyclic semantics (ie. it may
* not be suitable for data integrity
* writeout).
*/
done = 1;
break;
} }
if (ret || (--nr_to_write <= 0)) }
if (--nr_to_write <= 0)
done = 1; done = 1;
if (wbc->nonblocking && bdi_write_congested(bdi)) { if (wbc->nonblocking && bdi_write_congested(bdi)) {
wbc->encountered_congestion = 1; wbc->encountered_congestion = 1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment