Commit f1ca7e98 authored by Josef Bacik's avatar Josef Bacik

Btrfs: hold the tree mod lock in __tree_mod_log_rewind

We need to hold the tree mod log lock in __tree_mod_log_rewind since we walk
forward in the tree mod entries, otherwise we'll end up with random entries and
trip the BUG_ON() at the front of __tree_mod_log_rewind.  This fixes the panics
people were seeing when running

find /whatever -type f -exec btrfs fi defrag {} \;

Thansk,

Cc: stable@vger.kernel.org
Signed-off-by: default avatarJosef Bacik <jbacik@fusionio.com>
parent 261c84b6
...@@ -1161,8 +1161,8 @@ __tree_mod_log_oldest_root(struct btrfs_fs_info *fs_info, ...@@ -1161,8 +1161,8 @@ __tree_mod_log_oldest_root(struct btrfs_fs_info *fs_info,
* time_seq). * time_seq).
*/ */
static void static void
__tree_mod_log_rewind(struct extent_buffer *eb, u64 time_seq, __tree_mod_log_rewind(struct btrfs_fs_info *fs_info, struct extent_buffer *eb,
struct tree_mod_elem *first_tm) u64 time_seq, struct tree_mod_elem *first_tm)
{ {
u32 n; u32 n;
struct rb_node *next; struct rb_node *next;
...@@ -1172,6 +1172,7 @@ __tree_mod_log_rewind(struct extent_buffer *eb, u64 time_seq, ...@@ -1172,6 +1172,7 @@ __tree_mod_log_rewind(struct extent_buffer *eb, u64 time_seq,
unsigned long p_size = sizeof(struct btrfs_key_ptr); unsigned long p_size = sizeof(struct btrfs_key_ptr);
n = btrfs_header_nritems(eb); n = btrfs_header_nritems(eb);
tree_mod_log_read_lock(fs_info);
while (tm && tm->seq >= time_seq) { while (tm && tm->seq >= time_seq) {
/* /*
* all the operations are recorded with the operator used for * all the operations are recorded with the operator used for
...@@ -1226,6 +1227,7 @@ __tree_mod_log_rewind(struct extent_buffer *eb, u64 time_seq, ...@@ -1226,6 +1227,7 @@ __tree_mod_log_rewind(struct extent_buffer *eb, u64 time_seq,
if (tm->index != first_tm->index) if (tm->index != first_tm->index)
break; break;
} }
tree_mod_log_read_unlock(fs_info);
btrfs_set_header_nritems(eb, n); btrfs_set_header_nritems(eb, n);
} }
...@@ -1274,7 +1276,7 @@ tree_mod_log_rewind(struct btrfs_fs_info *fs_info, struct extent_buffer *eb, ...@@ -1274,7 +1276,7 @@ tree_mod_log_rewind(struct btrfs_fs_info *fs_info, struct extent_buffer *eb,
extent_buffer_get(eb_rewin); extent_buffer_get(eb_rewin);
btrfs_tree_read_lock(eb_rewin); btrfs_tree_read_lock(eb_rewin);
__tree_mod_log_rewind(eb_rewin, time_seq, tm); __tree_mod_log_rewind(fs_info, eb_rewin, time_seq, tm);
WARN_ON(btrfs_header_nritems(eb_rewin) > WARN_ON(btrfs_header_nritems(eb_rewin) >
BTRFS_NODEPTRS_PER_BLOCK(fs_info->tree_root)); BTRFS_NODEPTRS_PER_BLOCK(fs_info->tree_root));
...@@ -1350,7 +1352,7 @@ get_old_root(struct btrfs_root *root, u64 time_seq) ...@@ -1350,7 +1352,7 @@ get_old_root(struct btrfs_root *root, u64 time_seq)
btrfs_set_header_generation(eb, old_generation); btrfs_set_header_generation(eb, old_generation);
} }
if (tm) if (tm)
__tree_mod_log_rewind(eb, time_seq, tm); __tree_mod_log_rewind(root->fs_info, eb, time_seq, tm);
else else
WARN_ON(btrfs_header_level(eb) != 0); WARN_ON(btrfs_header_level(eb) != 0);
WARN_ON(btrfs_header_nritems(eb) > BTRFS_NODEPTRS_PER_BLOCK(root)); WARN_ON(btrfs_header_nritems(eb) > BTRFS_NODEPTRS_PER_BLOCK(root));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment