aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLiu Bo <bo.li.liu@oracle.com>2018-01-25 13:02:51 -0500
committerDavid Sterba <dsterba@suse.com>2018-02-02 10:24:24 -0500
commit1846430c24d66e85cc58286b3319c82cd54debb2 (patch)
treea6bd680f201d90cc007254cb988093b41b936f8c
parente89166990f11c3f21e1649d760dd35f9e410321c (diff)
Btrfs: fix crash due to not cleaning up tree log block's dirty bits
In cases that the whole fs flips into readonly status due to failures in critical sections, then log tree's blocks are still dirty, and this leads to a crash during umount time, the crash is about use-after-free, umount -> close_ctree -> stop workers -> iput(btree_inode) -> iput_final -> write_inode_now -> ... -> queue job on stop'd workers cc: <stable@vger.kernel.org> v3.12+ Fixes: 681ae50917df ("Btrfs: cleanup reserved space when freeing tree log on error") Signed-off-by: Liu Bo <bo.li.liu@oracle.com> Reviewed-by: Josef Bacik <jbacik@fb.com> Signed-off-by: David Sterba <dsterba@suse.com>
-rw-r--r--fs/btrfs/tree-log.c9
1 files changed, 9 insertions, 0 deletions
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index ee1aaed1330e..1920c2149f88 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -2471,6 +2471,9 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans,
2471 clean_tree_block(fs_info, next); 2471 clean_tree_block(fs_info, next);
2472 btrfs_wait_tree_block_writeback(next); 2472 btrfs_wait_tree_block_writeback(next);
2473 btrfs_tree_unlock(next); 2473 btrfs_tree_unlock(next);
2474 } else {
2475 if (test_and_clear_bit(EXTENT_BUFFER_DIRTY, &next->bflags))
2476 clear_extent_buffer_dirty(next);
2474 } 2477 }
2475 2478
2476 WARN_ON(root_owner != 2479 WARN_ON(root_owner !=
@@ -2551,6 +2554,9 @@ static noinline int walk_up_log_tree(struct btrfs_trans_handle *trans,
2551 clean_tree_block(fs_info, next); 2554 clean_tree_block(fs_info, next);
2552 btrfs_wait_tree_block_writeback(next); 2555 btrfs_wait_tree_block_writeback(next);
2553 btrfs_tree_unlock(next); 2556 btrfs_tree_unlock(next);
2557 } else {
2558 if (test_and_clear_bit(EXTENT_BUFFER_DIRTY, &next->bflags))
2559 clear_extent_buffer_dirty(next);
2554 } 2560 }
2555 2561
2556 WARN_ON(root_owner != BTRFS_TREE_LOG_OBJECTID); 2562 WARN_ON(root_owner != BTRFS_TREE_LOG_OBJECTID);
@@ -2629,6 +2635,9 @@ static int walk_log_tree(struct btrfs_trans_handle *trans,
2629 clean_tree_block(fs_info, next); 2635 clean_tree_block(fs_info, next);
2630 btrfs_wait_tree_block_writeback(next); 2636 btrfs_wait_tree_block_writeback(next);
2631 btrfs_tree_unlock(next); 2637 btrfs_tree_unlock(next);
2638 } else {
2639 if (test_and_clear_bit(EXTENT_BUFFER_DIRTY, &next->bflags))
2640 clear_extent_buffer_dirty(next);
2632 } 2641 }
2633 2642
2634 WARN_ON(log->root_key.objectid != 2643 WARN_ON(log->root_key.objectid !=