btrfs: fix tree mod log mishandling of reallocated nodes
[sfrench/cifs-2.6.git] / fs / btrfs / extent-tree.c
index cd2d36580f1ac169fa0724ba2db732f03bfcfe5d..2801c991814f573e33977c17eb32205852eb2192 100644 (file)
@@ -3295,21 +3295,22 @@ void btrfs_free_tree_block(struct btrfs_trans_handle *trans,
                }
 
                /*
-                * If this is a leaf and there are tree mod log users, we may
-                * have recorded mod log operations that point to this leaf.
-                * So we must make sure no one reuses this leaf's extent before
-                * mod log operations are applied to a node, otherwise after
-                * rewinding a node using the mod log operations we get an
-                * inconsistent btree, as the leaf's extent may now be used as
-                * a node or leaf for another different btree.
+                * If there are tree mod log users we may have recorded mod log
+                * operations for this node.  If we re-allocate this node we
+                * could replay operations on this node that happened when it
+                * existed in a completely different root.  For example if it
+                * was part of root A, then was reallocated to root B, and we
+                * are doing a btrfs_old_search_slot(root b), we could replay
+                * operations that happened when the block was part of root A,
+                * giving us an inconsistent view of the btree.
+                *
                 * We are safe from races here because at this point no other
                 * node or root points to this extent buffer, so if after this
-                * check a new tree mod log user joins, it will not be able to
-                * find a node pointing to this leaf and record operations that
-                * point to this leaf.
+                * check a new tree mod log user joins we will not have an
+                * existing log of operations on this node that we have to
+                * contend with.
                 */
-               if (btrfs_header_level(buf) == 0 &&
-                   test_bit(BTRFS_FS_TREE_MOD_LOG_USERS, &fs_info->flags))
+               if (test_bit(BTRFS_FS_TREE_MOD_LOG_USERS, &fs_info->flags))
                        must_pin = true;
 
                if (must_pin || btrfs_is_zoned(fs_info)) {