|
@@ -62,14 +62,38 @@ noinline void btrfs_set_path_blocking(struct btrfs_path *p)
|
|
|
|
|
|
/*
|
|
|
* reset all the locked nodes in the patch to spinning locks.
|
|
|
+ *
|
|
|
+ * held is used to keep lockdep happy, when lockdep is enabled
|
|
|
+ * we set held to a blocking lock before we go around and
|
|
|
+ * retake all the spinlocks in the path. You can safely use NULL
|
|
|
+ * for held
|
|
|
*/
|
|
|
-noinline void btrfs_clear_path_blocking(struct btrfs_path *p)
|
|
|
+noinline void btrfs_clear_path_blocking(struct btrfs_path *p,
|
|
|
+ struct extent_buffer *held)
|
|
|
{
|
|
|
int i;
|
|
|
- for (i = 0; i < BTRFS_MAX_LEVEL; i++) {
|
|
|
+
|
|
|
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
|
|
|
+ /* lockdep really cares that we take all of these spinlocks
|
|
|
+ * in the right order. If any of the locks in the path are not
|
|
|
+ * currently blocking, it is going to complain. So, make really
|
|
|
+ * really sure by forcing the path to blocking before we clear
|
|
|
+ * the path blocking.
|
|
|
+ */
|
|
|
+ if (held)
|
|
|
+ btrfs_set_lock_blocking(held);
|
|
|
+ btrfs_set_path_blocking(p);
|
|
|
+#endif
|
|
|
+
|
|
|
+ for (i = BTRFS_MAX_LEVEL - 1; i >= 0; i--) {
|
|
|
if (p->nodes[i] && p->locks[i])
|
|
|
btrfs_clear_lock_blocking(p->nodes[i]);
|
|
|
}
|
|
|
+
|
|
|
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
|
|
|
+ if (held)
|
|
|
+ btrfs_clear_lock_blocking(held);
|
|
|
+#endif
|
|
|
}
|
|
|
|
|
|
/* this also releases the path */
|
|
@@ -279,7 +303,7 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
|
|
|
trans->transid, level, &ins);
|
|
|
BUG_ON(ret);
|
|
|
cow = btrfs_init_new_buffer(trans, root, prealloc_dest,
|
|
|
- buf->len);
|
|
|
+ buf->len, level);
|
|
|
} else {
|
|
|
cow = btrfs_alloc_free_block(trans, root, buf->len,
|
|
|
parent_start,
|
|
@@ -1559,7 +1583,7 @@ cow_done:
|
|
|
if (!p->skip_locking)
|
|
|
p->locks[level] = 1;
|
|
|
|
|
|
- btrfs_clear_path_blocking(p);
|
|
|
+ btrfs_clear_path_blocking(p, NULL);
|
|
|
|
|
|
/*
|
|
|
* we have a lock on b and as long as we aren't changing
|
|
@@ -1598,7 +1622,7 @@ cow_done:
|
|
|
|
|
|
btrfs_set_path_blocking(p);
|
|
|
sret = split_node(trans, root, p, level);
|
|
|
- btrfs_clear_path_blocking(p);
|
|
|
+ btrfs_clear_path_blocking(p, NULL);
|
|
|
|
|
|
BUG_ON(sret > 0);
|
|
|
if (sret) {
|
|
@@ -1618,7 +1642,7 @@ cow_done:
|
|
|
|
|
|
btrfs_set_path_blocking(p);
|
|
|
sret = balance_level(trans, root, p, level);
|
|
|
- btrfs_clear_path_blocking(p);
|
|
|
+ btrfs_clear_path_blocking(p, NULL);
|
|
|
|
|
|
if (sret) {
|
|
|
ret = sret;
|
|
@@ -1681,13 +1705,13 @@ cow_done:
|
|
|
if (!p->skip_locking) {
|
|
|
int lret;
|
|
|
|
|
|
- btrfs_clear_path_blocking(p);
|
|
|
+ btrfs_clear_path_blocking(p, NULL);
|
|
|
lret = btrfs_try_spin_lock(b);
|
|
|
|
|
|
if (!lret) {
|
|
|
btrfs_set_path_blocking(p);
|
|
|
btrfs_tree_lock(b);
|
|
|
- btrfs_clear_path_blocking(p);
|
|
|
+ btrfs_clear_path_blocking(p, b);
|
|
|
}
|
|
|
}
|
|
|
} else {
|
|
@@ -1699,7 +1723,7 @@ cow_done:
|
|
|
btrfs_set_path_blocking(p);
|
|
|
sret = split_leaf(trans, root, key,
|
|
|
p, ins_len, ret == 0);
|
|
|
- btrfs_clear_path_blocking(p);
|
|
|
+ btrfs_clear_path_blocking(p, NULL);
|
|
|
|
|
|
BUG_ON(sret > 0);
|
|
|
if (sret) {
|
|
@@ -3919,7 +3943,6 @@ find_next_key:
|
|
|
btrfs_release_path(root, path);
|
|
|
goto again;
|
|
|
} else {
|
|
|
- btrfs_clear_path_blocking(path);
|
|
|
goto out;
|
|
|
}
|
|
|
}
|
|
@@ -3939,7 +3962,7 @@ find_next_key:
|
|
|
path->locks[level - 1] = 1;
|
|
|
path->nodes[level - 1] = cur;
|
|
|
unlock_up(path, level, 1);
|
|
|
- btrfs_clear_path_blocking(path);
|
|
|
+ btrfs_clear_path_blocking(path, NULL);
|
|
|
}
|
|
|
out:
|
|
|
if (ret == 0)
|