[PATCH 4.4 20/33] Btrfs: fix crash due to not cleaning up tree log blocks dirty bits

From: Greg Kroah-Hartman
Date: Wed Feb 21 2018 - 07:51:25 EST


4.4-stable review patch. If anyone has any objections, please let me know.

------------------

From: Liu Bo <bo.li.liu@xxxxxxxxxx>

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@xxxxxxxxxxxxxxx> v3.12+
Fixes: 681ae50917df ("Btrfs: cleanup reserved space when freeing tree log on error")
Signed-off-by: Liu Bo <bo.li.liu@xxxxxxxxxx>
Reviewed-by: Josef Bacik <jbacik@xxxxxx>
Signed-off-by: David Sterba <dsterba@xxxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>

---
fs/btrfs/tree-log.c | 9 +++++++++
1 file changed, 9 insertions(+)

--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -2445,6 +2445,9 @@ static noinline int walk_down_log_tree(s
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 !=
@@ -2524,6 +2527,9 @@ static noinline int walk_up_log_tree(str
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);
@@ -2600,6 +2606,9 @@ static int walk_log_tree(struct btrfs_tr
clean_tree_block(trans, log->fs_info, 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 !=