Commit bf0da8c1 authored by Chris Mason's avatar Chris Mason

Btrfs: ClearPageError during writepage and clean_tree_block

Failure testing was tripping up over stale PageError bits in
metadata pages.  If we have an io error on a block, and later on
end up reusing it, nobody ever clears PageError on those pages.

During commit, we'll find PageError and think we had trouble writing
the block, which will lead to aborts and other problems.

This changes clean_tree_block and the btrfs writepage code to
clear the PageError bit.  In both cases we're either completely
done with the page or the page has good stuff and the error bit
is no longer valid.
Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent 663350ac
...@@ -2334,6 +2334,9 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc, ...@@ -2334,6 +2334,9 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc,
trace___extent_writepage(page, inode, wbc); trace___extent_writepage(page, inode, wbc);
WARN_ON(!PageLocked(page)); WARN_ON(!PageLocked(page));
ClearPageError(page);
pg_offset = i_size & (PAGE_CACHE_SIZE - 1); pg_offset = i_size & (PAGE_CACHE_SIZE - 1);
if (page->index > end_index || if (page->index > end_index ||
(page->index == end_index && !pg_offset)) { (page->index == end_index && !pg_offset)) {
...@@ -3402,6 +3405,7 @@ int clear_extent_buffer_dirty(struct extent_io_tree *tree, ...@@ -3402,6 +3405,7 @@ int clear_extent_buffer_dirty(struct extent_io_tree *tree,
PAGECACHE_TAG_DIRTY); PAGECACHE_TAG_DIRTY);
} }
spin_unlock_irq(&page->mapping->tree_lock); spin_unlock_irq(&page->mapping->tree_lock);
ClearPageError(page);
unlock_page(page); unlock_page(page);
} }
return 0; return 0;
......
...@@ -634,7 +634,12 @@ int btrfs_write_and_wait_marked_extents(struct btrfs_root *root, ...@@ -634,7 +634,12 @@ int btrfs_write_and_wait_marked_extents(struct btrfs_root *root,
ret = btrfs_write_marked_extents(root, dirty_pages, mark); ret = btrfs_write_marked_extents(root, dirty_pages, mark);
ret2 = btrfs_wait_marked_extents(root, dirty_pages, mark); ret2 = btrfs_wait_marked_extents(root, dirty_pages, mark);
return ret || ret2;
if (ret)
return ret;
if (ret2)
return ret2;
return 0;
} }
int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans, int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans,
......
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