aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ctree.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/ctree.c')
-rw-r--r--fs/btrfs/ctree.c61
1 files changed, 38 insertions, 23 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 551177c0011a..42491d728e99 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -38,19 +38,12 @@ static int balance_node_right(struct btrfs_trans_handle *trans,
38static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root, 38static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,
39 struct btrfs_path *path, int level, int slot); 39 struct btrfs_path *path, int level, int slot);
40 40
41inline void btrfs_init_path(struct btrfs_path *p)
42{
43 memset(p, 0, sizeof(*p));
44}
45
46struct btrfs_path *btrfs_alloc_path(void) 41struct btrfs_path *btrfs_alloc_path(void)
47{ 42{
48 struct btrfs_path *path; 43 struct btrfs_path *path;
49 path = kmem_cache_alloc(btrfs_path_cachep, GFP_NOFS); 44 path = kmem_cache_zalloc(btrfs_path_cachep, GFP_NOFS);
50 if (path) { 45 if (path)
51 btrfs_init_path(path);
52 path->reada = 1; 46 path->reada = 1;
53 }
54 return path; 47 return path;
55} 48}
56 49
@@ -69,14 +62,38 @@ noinline void btrfs_set_path_blocking(struct btrfs_path *p)
69 62
70/* 63/*
71 * 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
72 */ 70 */
73noinline void btrfs_clear_path_blocking(struct btrfs_path *p) 71noinline void btrfs_clear_path_blocking(struct btrfs_path *p,
72 struct extent_buffer *held)
74{ 73{
75 int i; 74 int i;
76 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--) {
77 if (p->nodes[i] && p->locks[i]) 89 if (p->nodes[i] && p->locks[i])
78 btrfs_clear_lock_blocking(p->nodes[i]); 90 btrfs_clear_lock_blocking(p->nodes[i]);
79 } 91 }
92
93#ifdef CONFIG_DEBUG_LOCK_ALLOC
94 if (held)
95 btrfs_clear_lock_blocking(held);
96#endif
80} 97}
81 98
82/* this also releases the path */ 99/* this also releases the path */
@@ -286,7 +303,7 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
286 trans->transid, level, &ins); 303 trans->transid, level, &ins);
287 BUG_ON(ret); 304 BUG_ON(ret);
288 cow = btrfs_init_new_buffer(trans, root, prealloc_dest, 305 cow = btrfs_init_new_buffer(trans, root, prealloc_dest,
289 buf->len); 306 buf->len, level);
290 } else { 307 } else {
291 cow = btrfs_alloc_free_block(trans, root, buf->len, 308 cow = btrfs_alloc_free_block(trans, root, buf->len,
292 parent_start, 309 parent_start,
@@ -917,9 +934,9 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
917 934
918 /* promote the child to a root */ 935 /* promote the child to a root */
919 child = read_node_slot(root, mid, 0); 936 child = read_node_slot(root, mid, 0);
937 BUG_ON(!child);
920 btrfs_tree_lock(child); 938 btrfs_tree_lock(child);
921 btrfs_set_lock_blocking(child); 939 btrfs_set_lock_blocking(child);
922 BUG_ON(!child);
923 ret = btrfs_cow_block(trans, root, child, mid, 0, &child, 0); 940 ret = btrfs_cow_block(trans, root, child, mid, 0, &child, 0);
924 BUG_ON(ret); 941 BUG_ON(ret);
925 942
@@ -1530,8 +1547,7 @@ again:
1530 * for higher level blocks, try not to allocate blocks 1547 * for higher level blocks, try not to allocate blocks
1531 * with the block and the parent locks held. 1548 * with the block and the parent locks held.
1532 */ 1549 */
1533 if (level > 0 && !prealloc_block.objectid && 1550 if (level > 0 && !prealloc_block.objectid) {
1534 btrfs_path_lock_waiting(p, level)) {
1535 u32 size = b->len; 1551 u32 size = b->len;
1536 u64 hint = b->start; 1552 u64 hint = b->start;
1537 1553
@@ -1567,7 +1583,7 @@ cow_done:
1567 if (!p->skip_locking) 1583 if (!p->skip_locking)
1568 p->locks[level] = 1; 1584 p->locks[level] = 1;
1569 1585
1570 btrfs_clear_path_blocking(p); 1586 btrfs_clear_path_blocking(p, NULL);
1571 1587
1572 /* 1588 /*
1573 * 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
@@ -1606,7 +1622,7 @@ cow_done:
1606 1622
1607 btrfs_set_path_blocking(p); 1623 btrfs_set_path_blocking(p);
1608 sret = split_node(trans, root, p, level); 1624 sret = split_node(trans, root, p, level);
1609 btrfs_clear_path_blocking(p); 1625 btrfs_clear_path_blocking(p, NULL);
1610 1626
1611 BUG_ON(sret > 0); 1627 BUG_ON(sret > 0);
1612 if (sret) { 1628 if (sret) {
@@ -1626,7 +1642,7 @@ cow_done:
1626 1642
1627 btrfs_set_path_blocking(p); 1643 btrfs_set_path_blocking(p);
1628 sret = balance_level(trans, root, p, level); 1644 sret = balance_level(trans, root, p, level);
1629 btrfs_clear_path_blocking(p); 1645 btrfs_clear_path_blocking(p, NULL);
1630 1646
1631 if (sret) { 1647 if (sret) {
1632 ret = sret; 1648 ret = sret;
@@ -1689,13 +1705,13 @@ cow_done:
1689 if (!p->skip_locking) { 1705 if (!p->skip_locking) {
1690 int lret; 1706 int lret;
1691 1707
1692 btrfs_clear_path_blocking(p); 1708 btrfs_clear_path_blocking(p, NULL);
1693 lret = btrfs_try_spin_lock(b); 1709 lret = btrfs_try_spin_lock(b);
1694 1710
1695 if (!lret) { 1711 if (!lret) {
1696 btrfs_set_path_blocking(p); 1712 btrfs_set_path_blocking(p);
1697 btrfs_tree_lock(b); 1713 btrfs_tree_lock(b);
1698 btrfs_clear_path_blocking(p); 1714 btrfs_clear_path_blocking(p, b);
1699 } 1715 }
1700 } 1716 }
1701 } else { 1717 } else {
@@ -1707,7 +1723,7 @@ cow_done:
1707 btrfs_set_path_blocking(p); 1723 btrfs_set_path_blocking(p);
1708 sret = split_leaf(trans, root, key, 1724 sret = split_leaf(trans, root, key,
1709 p, ins_len, ret == 0); 1725 p, ins_len, ret == 0);
1710 btrfs_clear_path_blocking(p); 1726 btrfs_clear_path_blocking(p, NULL);
1711 1727
1712 BUG_ON(sret > 0); 1728 BUG_ON(sret > 0);
1713 if (sret) { 1729 if (sret) {
@@ -3927,7 +3943,6 @@ find_next_key:
3927 btrfs_release_path(root, path); 3943 btrfs_release_path(root, path);
3928 goto again; 3944 goto again;
3929 } else { 3945 } else {
3930 btrfs_clear_path_blocking(path);
3931 goto out; 3946 goto out;
3932 } 3947 }
3933 } 3948 }
@@ -3947,7 +3962,7 @@ find_next_key:
3947 path->locks[level - 1] = 1; 3962 path->locks[level - 1] = 1;
3948 path->nodes[level - 1] = cur; 3963 path->nodes[level - 1] = cur;
3949 unlock_up(path, level, 1); 3964 unlock_up(path, level, 1);
3950 btrfs_clear_path_blocking(path); 3965 btrfs_clear_path_blocking(path, NULL);
3951 } 3966 }
3952out: 3967out:
3953 if (ret == 0) 3968 if (ret == 0)