Commit 0e64a39d authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] Fix the __block_write_full_page() error path.

Fix the ENOSPC recovery code in __block_write_full_page()

- Don't write out clean buffers.

- Set PG_writeback before submitting the IO.  Otherwise the completion
  handler will go BUG when it sees a non-PageWriteback page.  If the IO
  is very fast, or synchronous.
parent d98b1feb
...@@ -1784,6 +1784,7 @@ static int __block_write_full_page(struct inode *inode, ...@@ -1784,6 +1784,7 @@ static int __block_write_full_page(struct inode *inode,
if (err == 0) if (err == 0)
return ret; return ret;
return err; return err;
recover: recover:
/* /*
* ENOSPC, or some other error. We may already have added some * ENOSPC, or some other error. We may already have added some
...@@ -1795,7 +1796,8 @@ static int __block_write_full_page(struct inode *inode, ...@@ -1795,7 +1796,8 @@ static int __block_write_full_page(struct inode *inode,
bh = head; bh = head;
/* Recovery: lock and submit the mapped buffers */ /* Recovery: lock and submit the mapped buffers */
do { do {
if (buffer_mapped(bh)) { get_bh(bh);
if (buffer_mapped(bh) && buffer_dirty(bh)) {
lock_buffer(bh); lock_buffer(bh);
mark_buffer_async_write(bh); mark_buffer_async_write(bh);
} else { } else {
...@@ -1805,21 +1807,21 @@ static int __block_write_full_page(struct inode *inode, ...@@ -1805,21 +1807,21 @@ static int __block_write_full_page(struct inode *inode,
*/ */
clear_buffer_dirty(bh); clear_buffer_dirty(bh);
} }
bh = bh->b_this_page; } while ((bh = bh->b_this_page) != head);
} while (bh != head); SetPageError(page);
BUG_ON(PageWriteback(page));
SetPageWriteback(page);
unlock_page(page);
do { do {
struct buffer_head *next = bh->b_this_page; struct buffer_head *next = bh->b_this_page;
if (buffer_async_write(bh)) { if (buffer_async_write(bh)) {
set_buffer_uptodate(bh);
clear_buffer_dirty(bh); clear_buffer_dirty(bh);
submit_bh(WRITE, bh); submit_bh(WRITE, bh);
nr_underway++; nr_underway++;
} }
put_bh(bh);
bh = next; bh = next;
} while (bh != head); } while (bh != head);
BUG_ON(PageWriteback(page));
SetPageWriteback(page);
unlock_page(page);
goto done; goto done;
} }
......
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