Commit b51c26f7 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] fix failure to write ext2 indirects under load

This patch fixes a filesystem corrupting bug, present in 2.5.41 through
2.5.44.  It can cause ext2 indirect blocks to not be written out.  A
fsck will fix it up.

Under heavy memory pressure a PF_MEMALLOC task attemtps to write out a
blockdev page whose buffers are already under writeback and which were
dirtied while under writeback.

The writepage call returns -EAGAIN but because the caller is
PF_MEMALLOC, the page was not being marked dirty again.

The page sits on mapping->clean_pages for ever and it not written out.

The fix is to mark that page dirty again for all callers, regardless of
PF_MEMALLOC state.
parent 61fa45e0
...@@ -595,6 +595,10 @@ mpage_writepages(struct address_space *mapping, ...@@ -595,6 +595,10 @@ mpage_writepages(struct address_space *mapping,
test_clear_page_dirty(page)) { test_clear_page_dirty(page)) {
if (writepage) { if (writepage) {
ret = (*writepage)(page); ret = (*writepage)(page);
if (ret == -EAGAIN) {
__set_page_dirty_nobuffers(page);
ret = 0;
}
} else { } else {
bio = mpage_writepage(bio, page, get_block, bio = mpage_writepage(bio, page, get_block,
&last_block_in_bio, &ret); &last_block_in_bio, &ret);
...@@ -605,10 +609,6 @@ mpage_writepages(struct address_space *mapping, ...@@ -605,10 +609,6 @@ mpage_writepages(struct address_space *mapping,
pagevec_deactivate_inactive(&pvec); pagevec_deactivate_inactive(&pvec);
page = NULL; page = NULL;
} }
if (ret == -EAGAIN && page) {
__set_page_dirty_nobuffers(page);
ret = 0;
}
if (ret || (--(wbc->nr_to_write) <= 0)) if (ret || (--(wbc->nr_to_write) <= 0))
done = 1; done = 1;
if (wbc->nonblocking && bdi_write_congested(bdi)) { if (wbc->nonblocking && bdi_write_congested(bdi)) {
......
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