diff options
author | Liu Bo <bo.li.liu@oracle.com> | 2014-09-23 10:22:33 -0400 |
---|---|---|
committer | Chris Mason <clm@fb.com> | 2014-10-03 19:14:58 -0400 |
commit | 8146502820231da924ca22d147cdcf733ac9a057 (patch) | |
tree | a4ff285ca64394aea238a249ac9bf41fbc7fbe11 /fs/btrfs/extent_io.c | |
parent | 55e3bd2e0c2e1cfb43429b962e61415e0526bc01 (diff) |
Btrfs: fix crash of btrfs_release_extent_buffer_page
This is actually inspired by Filipe's patch. When write_one_eb() fails on
submit_extent_page(), it'll give up writing this eb and mark it with
EXTENT_BUFFER_IOERR. So if it's not the last page that encounter the failure,
there are some left pages which remain DIRTY, and if a later COW on this eb
happens, ie. eb is COWed and freed, it'd run into BUG_ON in
btrfs_release_extent_buffer_page() for the DIRTY page, ie. BUG_ON(PageDirty(page));
This adds the missing clear_page_dirty_for_io() for the rest pages of eb.
Signed-off-by: Liu Bo <bo.li.liu@oracle.com>
Reviewed-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'fs/btrfs/extent_io.c')
-rw-r--r-- | fs/btrfs/extent_io.c | 1 |
1 files changed, 1 insertions, 0 deletions
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 828aded0f8aa..4267a054b9c1 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
@@ -3677,6 +3677,7 @@ static noinline_for_stack int write_one_eb(struct extent_buffer *eb, | |||
3677 | if (unlikely(ret)) { | 3677 | if (unlikely(ret)) { |
3678 | for (; i < num_pages; i++) { | 3678 | for (; i < num_pages; i++) { |
3679 | struct page *p = extent_buffer_page(eb, i); | 3679 | struct page *p = extent_buffer_page(eb, i); |
3680 | clear_page_dirty_for_io(p); | ||
3680 | unlock_page(p); | 3681 | unlock_page(p); |
3681 | } | 3682 | } |
3682 | } | 3683 | } |