|
@@ -2156,6 +2156,7 @@ int write_cache_pages(struct address_space *mapping,
|
|
|
{
|
|
{
|
|
|
int ret = 0;
|
|
int ret = 0;
|
|
|
int done = 0;
|
|
int done = 0;
|
|
|
|
|
+ int error;
|
|
|
struct pagevec pvec;
|
|
struct pagevec pvec;
|
|
|
int nr_pages;
|
|
int nr_pages;
|
|
|
pgoff_t uninitialized_var(writeback_index);
|
|
pgoff_t uninitialized_var(writeback_index);
|
|
@@ -2236,25 +2237,31 @@ continue_unlock:
|
|
|
goto continue_unlock;
|
|
goto continue_unlock;
|
|
|
|
|
|
|
|
trace_wbc_writepage(wbc, inode_to_bdi(mapping->host));
|
|
trace_wbc_writepage(wbc, inode_to_bdi(mapping->host));
|
|
|
- ret = (*writepage)(page, wbc, data);
|
|
|
|
|
- if (unlikely(ret)) {
|
|
|
|
|
- if (ret == AOP_WRITEPAGE_ACTIVATE) {
|
|
|
|
|
|
|
+ error = (*writepage)(page, wbc, data);
|
|
|
|
|
+ if (unlikely(error)) {
|
|
|
|
|
+ /*
|
|
|
|
|
+ * Handle errors according to the type of
|
|
|
|
|
+ * writeback. There's no need to continue for
|
|
|
|
|
+ * background writeback. Just push done_index
|
|
|
|
|
+ * past this page so media errors won't choke
|
|
|
|
|
+ * writeout for the entire file. For integrity
|
|
|
|
|
+ * writeback, we must process the entire dirty
|
|
|
|
|
+ * set regardless of errors because the fs may
|
|
|
|
|
+ * still have state to clear for each page. In
|
|
|
|
|
+ * that case we continue processing and return
|
|
|
|
|
+ * the first error.
|
|
|
|
|
+ */
|
|
|
|
|
+ if (error == AOP_WRITEPAGE_ACTIVATE) {
|
|
|
unlock_page(page);
|
|
unlock_page(page);
|
|
|
- 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).
|
|
|
|
|
- */
|
|
|
|
|
|
|
+ error = 0;
|
|
|
|
|
+ } else if (wbc->sync_mode != WB_SYNC_ALL) {
|
|
|
|
|
+ ret = error;
|
|
|
done_index = page->index + 1;
|
|
done_index = page->index + 1;
|
|
|
done = 1;
|
|
done = 1;
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
|
|
+ if (!ret)
|
|
|
|
|
+ ret = error;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
/*
|