aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLiu Bo2018-01-25 12:02:51 -0600
committerGreg Kroah-Hartman2018-02-22 08:45:00 -0600
commit145832a93f28fb80d6cb22b5cd84df5a6e63f47b (patch)
tree6329e148506e3ed91b626dfc1547c9763b7921fc
parentefba91a4c3f465e1b7f10b2454d6406eb217a17e (diff)
downloadkernel-omap-145832a93f28fb80d6cb22b5cd84df5a6e63f47b.tar.gz
kernel-omap-145832a93f28fb80d6cb22b5cd84df5a6e63f47b.tar.xz
kernel-omap-145832a93f28fb80d6cb22b5cd84df5a6e63f47b.zip
Btrfs: fix crash due to not cleaning up tree log block's dirty bits
commit 1846430c24d66e85cc58286b3319c82cd54debb2 upstream. 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> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-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 ee7832e2d39d..61a37fdff73c 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -2445,6 +2445,9 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans,
2445 next); 2445 next);
2446 btrfs_wait_tree_block_writeback(next); 2446 btrfs_wait_tree_block_writeback(next);
2447 btrfs_tree_unlock(next); 2447 btrfs_tree_unlock(next);
2448 } else {
2449 if (test_and_clear_bit(EXTENT_BUFFER_DIRTY, &next->bflags))
2450 clear_extent_buffer_dirty(next);
2448 } 2451 }
2449 2452
2450 WARN_ON(root_owner != 2453 WARN_ON(root_owner !=
@@ -2524,6 +2527,9 @@ static noinline int walk_up_log_tree(struct btrfs_trans_handle *trans,
2524 next); 2527 next);
2525 btrfs_wait_tree_block_writeback(next); 2528 btrfs_wait_tree_block_writeback(next);
2526 btrfs_tree_unlock(next); 2529 btrfs_tree_unlock(next);
2530 } else {
2531 if (test_and_clear_bit(EXTENT_BUFFER_DIRTY, &next->bflags))
2532 clear_extent_buffer_dirty(next);
2527 } 2533 }
2528 2534
2529 WARN_ON(root_owner != BTRFS_TREE_LOG_OBJECTID); 2535 WARN_ON(root_owner != BTRFS_TREE_LOG_OBJECTID);
@@ -2600,6 +2606,9 @@ static int walk_log_tree(struct btrfs_trans_handle *trans,
2600 clean_tree_block(trans, log->fs_info, next); 2606 clean_tree_block(trans, log->fs_info, next);
2601 btrfs_wait_tree_block_writeback(next); 2607 btrfs_wait_tree_block_writeback(next);
2602 btrfs_tree_unlock(next); 2608 btrfs_tree_unlock(next);
2609 } else {
2610 if (test_and_clear_bit(EXTENT_BUFFER_DIRTY, &next->bflags))
2611 clear_extent_buffer_dirty(next);
2603 } 2612 }
2604 2613
2605 WARN_ON(log->root_key.objectid != 2614 WARN_ON(log->root_key.objectid !=