Messages in this thread Patch in this message | | | From | Greg Kroah-Hartman <> | Subject | [PATCH 3.18 14/58] Btrfs: fix crash due to not cleaning up tree log blocks dirty bits | Date | Fri, 23 Feb 2018 19:26:13 +0100 |
| |
3.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Liu Bo <bo.li.liu@oracle.com>
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>
--- fs/btrfs/tree-log.c | 9 +++++++++ 1 file changed, 9 insertions(+)
--- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -2201,6 +2201,9 @@ static noinline int walk_down_log_tree(s clean_tree_block(trans, root, next); btrfs_wait_tree_block_writeback(next); btrfs_tree_unlock(next); + } else { + if (test_and_clear_bit(EXTENT_BUFFER_DIRTY, &next->bflags)) + clear_extent_buffer_dirty(next); } WARN_ON(root_owner != @@ -2279,6 +2282,9 @@ static noinline int walk_up_log_tree(str clean_tree_block(trans, root, next); btrfs_wait_tree_block_writeback(next); btrfs_tree_unlock(next); + } else { + if (test_and_clear_bit(EXTENT_BUFFER_DIRTY, &next->bflags)) + clear_extent_buffer_dirty(next); } WARN_ON(root_owner != BTRFS_TREE_LOG_OBJECTID); @@ -2355,6 +2361,9 @@ static int walk_log_tree(struct btrfs_tr clean_tree_block(trans, log, next); btrfs_wait_tree_block_writeback(next); btrfs_tree_unlock(next); + } else { + if (test_and_clear_bit(EXTENT_BUFFER_DIRTY, &next->bflags)) + clear_extent_buffer_dirty(next); } WARN_ON(log->root_key.objectid !=
| |