diff options
Diffstat (limited to 'fs/btrfs/ctree.c')
-rw-r--r-- | fs/btrfs/ctree.c | 45 |
1 files changed, 34 insertions, 11 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index c8f4c540cc2c..42491d728e99 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -62,14 +62,38 @@ noinline void btrfs_set_path_blocking(struct btrfs_path *p) | |||
62 | 62 | ||
63 | /* | 63 | /* |
64 | * reset all the locked nodes in the patch to spinning locks. | 64 | * reset all the locked nodes in the patch to spinning locks. |
65 | * | ||
66 | * held is used to keep lockdep happy, when lockdep is enabled | ||
67 | * we set held to a blocking lock before we go around and | ||
68 | * retake all the spinlocks in the path. You can safely use NULL | ||
69 | * for held | ||
65 | */ | 70 | */ |
66 | noinline void btrfs_clear_path_blocking(struct btrfs_path *p) | 71 | noinline void btrfs_clear_path_blocking(struct btrfs_path *p, |
72 | struct extent_buffer *held) | ||
67 | { | 73 | { |
68 | int i; | 74 | int i; |
69 | for (i = 0; i < BTRFS_MAX_LEVEL; i++) { | 75 | |
76 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
77 | /* lockdep really cares that we take all of these spinlocks | ||
78 | * in the right order. If any of the locks in the path are not | ||
79 | * currently blocking, it is going to complain. So, make really | ||
80 | * really sure by forcing the path to blocking before we clear | ||
81 | * the path blocking. | ||
82 | */ | ||
83 | if (held) | ||
84 | btrfs_set_lock_blocking(held); | ||
85 | btrfs_set_path_blocking(p); | ||
86 | #endif | ||
87 | |||
88 | for (i = BTRFS_MAX_LEVEL - 1; i >= 0; i--) { | ||
70 | if (p->nodes[i] && p->locks[i]) | 89 | if (p->nodes[i] && p->locks[i]) |
71 | btrfs_clear_lock_blocking(p->nodes[i]); | 90 | btrfs_clear_lock_blocking(p->nodes[i]); |
72 | } | 91 | } |
92 | |||
93 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
94 | if (held) | ||
95 | btrfs_clear_lock_blocking(held); | ||
96 | #endif | ||
73 | } | 97 | } |
74 | 98 | ||
75 | /* this also releases the path */ | 99 | /* this also releases the path */ |
@@ -279,7 +303,7 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans, | |||
279 | trans->transid, level, &ins); | 303 | trans->transid, level, &ins); |
280 | BUG_ON(ret); | 304 | BUG_ON(ret); |
281 | cow = btrfs_init_new_buffer(trans, root, prealloc_dest, | 305 | cow = btrfs_init_new_buffer(trans, root, prealloc_dest, |
282 | buf->len); | 306 | buf->len, level); |
283 | } else { | 307 | } else { |
284 | cow = btrfs_alloc_free_block(trans, root, buf->len, | 308 | cow = btrfs_alloc_free_block(trans, root, buf->len, |
285 | parent_start, | 309 | parent_start, |
@@ -1559,7 +1583,7 @@ cow_done: | |||
1559 | if (!p->skip_locking) | 1583 | if (!p->skip_locking) |
1560 | p->locks[level] = 1; | 1584 | p->locks[level] = 1; |
1561 | 1585 | ||
1562 | btrfs_clear_path_blocking(p); | 1586 | btrfs_clear_path_blocking(p, NULL); |
1563 | 1587 | ||
1564 | /* | 1588 | /* |
1565 | * we have a lock on b and as long as we aren't changing | 1589 | * we have a lock on b and as long as we aren't changing |
@@ -1598,7 +1622,7 @@ cow_done: | |||
1598 | 1622 | ||
1599 | btrfs_set_path_blocking(p); | 1623 | btrfs_set_path_blocking(p); |
1600 | sret = split_node(trans, root, p, level); | 1624 | sret = split_node(trans, root, p, level); |
1601 | btrfs_clear_path_blocking(p); | 1625 | btrfs_clear_path_blocking(p, NULL); |
1602 | 1626 | ||
1603 | BUG_ON(sret > 0); | 1627 | BUG_ON(sret > 0); |
1604 | if (sret) { | 1628 | if (sret) { |
@@ -1618,7 +1642,7 @@ cow_done: | |||
1618 | 1642 | ||
1619 | btrfs_set_path_blocking(p); | 1643 | btrfs_set_path_blocking(p); |
1620 | sret = balance_level(trans, root, p, level); | 1644 | sret = balance_level(trans, root, p, level); |
1621 | btrfs_clear_path_blocking(p); | 1645 | btrfs_clear_path_blocking(p, NULL); |
1622 | 1646 | ||
1623 | if (sret) { | 1647 | if (sret) { |
1624 | ret = sret; | 1648 | ret = sret; |
@@ -1681,13 +1705,13 @@ cow_done: | |||
1681 | if (!p->skip_locking) { | 1705 | if (!p->skip_locking) { |
1682 | int lret; | 1706 | int lret; |
1683 | 1707 | ||
1684 | btrfs_clear_path_blocking(p); | 1708 | btrfs_clear_path_blocking(p, NULL); |
1685 | lret = btrfs_try_spin_lock(b); | 1709 | lret = btrfs_try_spin_lock(b); |
1686 | 1710 | ||
1687 | if (!lret) { | 1711 | if (!lret) { |
1688 | btrfs_set_path_blocking(p); | 1712 | btrfs_set_path_blocking(p); |
1689 | btrfs_tree_lock(b); | 1713 | btrfs_tree_lock(b); |
1690 | btrfs_clear_path_blocking(p); | 1714 | btrfs_clear_path_blocking(p, b); |
1691 | } | 1715 | } |
1692 | } | 1716 | } |
1693 | } else { | 1717 | } else { |
@@ -1699,7 +1723,7 @@ cow_done: | |||
1699 | btrfs_set_path_blocking(p); | 1723 | btrfs_set_path_blocking(p); |
1700 | sret = split_leaf(trans, root, key, | 1724 | sret = split_leaf(trans, root, key, |
1701 | p, ins_len, ret == 0); | 1725 | p, ins_len, ret == 0); |
1702 | btrfs_clear_path_blocking(p); | 1726 | btrfs_clear_path_blocking(p, NULL); |
1703 | 1727 | ||
1704 | BUG_ON(sret > 0); | 1728 | BUG_ON(sret > 0); |
1705 | if (sret) { | 1729 | if (sret) { |
@@ -3919,7 +3943,6 @@ find_next_key: | |||
3919 | btrfs_release_path(root, path); | 3943 | btrfs_release_path(root, path); |
3920 | goto again; | 3944 | goto again; |
3921 | } else { | 3945 | } else { |
3922 | btrfs_clear_path_blocking(path); | ||
3923 | goto out; | 3946 | goto out; |
3924 | } | 3947 | } |
3925 | } | 3948 | } |
@@ -3939,7 +3962,7 @@ find_next_key: | |||
3939 | path->locks[level - 1] = 1; | 3962 | path->locks[level - 1] = 1; |
3940 | path->nodes[level - 1] = cur; | 3963 | path->nodes[level - 1] = cur; |
3941 | unlock_up(path, level, 1); | 3964 | unlock_up(path, level, 1); |
3942 | btrfs_clear_path_blocking(path); | 3965 | btrfs_clear_path_blocking(path, NULL); |
3943 | } | 3966 | } |
3944 | out: | 3967 | out: |
3945 | if (ret == 0) | 3968 | if (ret == 0) |