aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/ctree.c45
-rw-r--r--fs/btrfs/ctree.h10
-rw-r--r--fs/btrfs/disk-io.c46
-rw-r--r--fs/btrfs/disk-io.h10
-rw-r--r--fs/btrfs/extent-tree.c7
-rw-r--r--fs/btrfs/locking.c11
-rw-r--r--fs/btrfs/volumes.c2
7 files changed, 99 insertions, 32 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index c8f4c540cc2..42491d728e9 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 */
66noinline void btrfs_clear_path_blocking(struct btrfs_path *p) 71noinline 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 }
3944out: 3967out:
3945 if (ret == 0) 3968 if (ret == 0)
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 3f7a8058df2..766b31ae318 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -43,11 +43,7 @@ struct btrfs_ordered_sum;
43 43
44#define BTRFS_ACL_NOT_CACHED ((void *)-1) 44#define BTRFS_ACL_NOT_CACHED ((void *)-1)
45 45
46#ifdef CONFIG_LOCKDEP 46#define BTRFS_MAX_LEVEL 8
47# define BTRFS_MAX_LEVEL 7
48#else
49# define BTRFS_MAX_LEVEL 8
50#endif
51 47
52/* holds pointers to all of the tree roots */ 48/* holds pointers to all of the tree roots */
53#define BTRFS_ROOT_TREE_OBJECTID 1ULL 49#define BTRFS_ROOT_TREE_OBJECTID 1ULL
@@ -1715,7 +1711,8 @@ struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
1715 u64 empty_size); 1711 u64 empty_size);
1716struct extent_buffer *btrfs_init_new_buffer(struct btrfs_trans_handle *trans, 1712struct extent_buffer *btrfs_init_new_buffer(struct btrfs_trans_handle *trans,
1717 struct btrfs_root *root, 1713 struct btrfs_root *root,
1718 u64 bytenr, u32 blocksize); 1714 u64 bytenr, u32 blocksize,
1715 int level);
1719int btrfs_alloc_extent(struct btrfs_trans_handle *trans, 1716int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
1720 struct btrfs_root *root, 1717 struct btrfs_root *root,
1721 u64 num_bytes, u64 parent, u64 min_bytes, 1718 u64 num_bytes, u64 parent, u64 min_bytes,
@@ -1835,7 +1832,6 @@ void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p);
1835struct btrfs_path *btrfs_alloc_path(void); 1832struct btrfs_path *btrfs_alloc_path(void);
1836void btrfs_free_path(struct btrfs_path *p); 1833void btrfs_free_path(struct btrfs_path *p);
1837void btrfs_set_path_blocking(struct btrfs_path *p); 1834void btrfs_set_path_blocking(struct btrfs_path *p);
1838void btrfs_clear_path_blocking(struct btrfs_path *p);
1839void btrfs_unlock_up_safe(struct btrfs_path *p, int level); 1835void btrfs_unlock_up_safe(struct btrfs_path *p, int level);
1840 1836
1841int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root, 1837int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root,
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 5aebddd7119..adda739a021 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -75,6 +75,40 @@ struct async_submit_bio {
75 struct btrfs_work work; 75 struct btrfs_work work;
76}; 76};
77 77
78/* These are used to set the lockdep class on the extent buffer locks.
79 * The class is set by the readpage_end_io_hook after the buffer has
80 * passed csum validation but before the pages are unlocked.
81 *
82 * The lockdep class is also set by btrfs_init_new_buffer on freshly
83 * allocated blocks.
84 *
85 * The class is based on the level in the tree block, which allows lockdep
86 * to know that lower nodes nest inside the locks of higher nodes.
87 *
88 * We also add a check to make sure the highest level of the tree is
89 * the same as our lockdep setup here. If BTRFS_MAX_LEVEL changes, this
90 * code needs update as well.
91 */
92#ifdef CONFIG_DEBUG_LOCK_ALLOC
93# if BTRFS_MAX_LEVEL != 8
94# error
95# endif
96static struct lock_class_key btrfs_eb_class[BTRFS_MAX_LEVEL + 1];
97static const char *btrfs_eb_name[BTRFS_MAX_LEVEL + 1] = {
98 /* leaf */
99 "btrfs-extent-00",
100 "btrfs-extent-01",
101 "btrfs-extent-02",
102 "btrfs-extent-03",
103 "btrfs-extent-04",
104 "btrfs-extent-05",
105 "btrfs-extent-06",
106 "btrfs-extent-07",
107 /* highest possible level */
108 "btrfs-extent-08",
109};
110#endif
111
78/* 112/*
79 * extents on the btree inode are pretty simple, there's one extent 113 * extents on the btree inode are pretty simple, there's one extent
80 * that covers the entire device 114 * that covers the entire device
@@ -347,6 +381,15 @@ static int check_tree_block_fsid(struct btrfs_root *root,
347 return ret; 381 return ret;
348} 382}
349 383
384#ifdef CONFIG_DEBUG_LOCK_ALLOC
385void btrfs_set_buffer_lockdep_class(struct extent_buffer *eb, int level)
386{
387 lockdep_set_class_and_name(&eb->lock,
388 &btrfs_eb_class[level],
389 btrfs_eb_name[level]);
390}
391#endif
392
350static int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end, 393static int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end,
351 struct extent_state *state) 394 struct extent_state *state)
352{ 395{
@@ -392,6 +435,8 @@ static int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end,
392 } 435 }
393 found_level = btrfs_header_level(eb); 436 found_level = btrfs_header_level(eb);
394 437
438 btrfs_set_buffer_lockdep_class(eb, found_level);
439
395 ret = csum_tree_block(root, eb, 1); 440 ret = csum_tree_block(root, eb, 1);
396 if (ret) 441 if (ret)
397 ret = -EIO; 442 ret = -EIO;
@@ -1777,7 +1822,6 @@ struct btrfs_root *open_ctree(struct super_block *sb,
1777 ret = find_and_setup_root(tree_root, fs_info, 1822 ret = find_and_setup_root(tree_root, fs_info,
1778 BTRFS_DEV_TREE_OBJECTID, dev_root); 1823 BTRFS_DEV_TREE_OBJECTID, dev_root);
1779 dev_root->track_dirty = 1; 1824 dev_root->track_dirty = 1;
1780
1781 if (ret) 1825 if (ret)
1782 goto fail_extent_root; 1826 goto fail_extent_root;
1783 1827
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h
index 494a56eb298..95029db227b 100644
--- a/fs/btrfs/disk-io.h
+++ b/fs/btrfs/disk-io.h
@@ -101,4 +101,14 @@ int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans,
101int btrfs_add_log_tree(struct btrfs_trans_handle *trans, 101int btrfs_add_log_tree(struct btrfs_trans_handle *trans,
102 struct btrfs_root *root); 102 struct btrfs_root *root);
103int btree_lock_page_hook(struct page *page); 103int btree_lock_page_hook(struct page *page);
104
105
106#ifdef CONFIG_DEBUG_LOCK_ALLOC
107void btrfs_set_buffer_lockdep_class(struct extent_buffer *eb, int level);
108#else
109static inline void btrfs_set_buffer_lockdep_class(struct extent_buffer *eb,
110 int level)
111{
112}
113#endif
104#endif 114#endif
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index c59e12036e2..cd86bffbdc9 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -3416,7 +3416,8 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
3416 3416
3417struct extent_buffer *btrfs_init_new_buffer(struct btrfs_trans_handle *trans, 3417struct extent_buffer *btrfs_init_new_buffer(struct btrfs_trans_handle *trans,
3418 struct btrfs_root *root, 3418 struct btrfs_root *root,
3419 u64 bytenr, u32 blocksize) 3419 u64 bytenr, u32 blocksize,
3420 int level)
3420{ 3421{
3421 struct extent_buffer *buf; 3422 struct extent_buffer *buf;
3422 3423
@@ -3424,6 +3425,7 @@ struct extent_buffer *btrfs_init_new_buffer(struct btrfs_trans_handle *trans,
3424 if (!buf) 3425 if (!buf)
3425 return ERR_PTR(-ENOMEM); 3426 return ERR_PTR(-ENOMEM);
3426 btrfs_set_header_generation(buf, trans->transid); 3427 btrfs_set_header_generation(buf, trans->transid);
3428 btrfs_set_buffer_lockdep_class(buf, level);
3427 btrfs_tree_lock(buf); 3429 btrfs_tree_lock(buf);
3428 clean_tree_block(trans, root, buf); 3430 clean_tree_block(trans, root, buf);
3429 3431
@@ -3467,7 +3469,8 @@ struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
3467 return ERR_PTR(ret); 3469 return ERR_PTR(ret);
3468 } 3470 }
3469 3471
3470 buf = btrfs_init_new_buffer(trans, root, ins.objectid, blocksize); 3472 buf = btrfs_init_new_buffer(trans, root, ins.objectid,
3473 blocksize, level);
3471 return buf; 3474 return buf;
3472} 3475}
3473 3476
diff --git a/fs/btrfs/locking.c b/fs/btrfs/locking.c
index 9ebe9385129..85506c4a3af 100644
--- a/fs/btrfs/locking.c
+++ b/fs/btrfs/locking.c
@@ -25,21 +25,10 @@
25#include "extent_io.h" 25#include "extent_io.h"
26#include "locking.h" 26#include "locking.h"
27 27
28/*
29 * btrfs_header_level() isn't free, so don't call it when lockdep isn't
30 * on
31 */
32#ifdef CONFIG_DEBUG_LOCK_ALLOC
33static inline void spin_nested(struct extent_buffer *eb)
34{
35 spin_lock_nested(&eb->lock, BTRFS_MAX_LEVEL - btrfs_header_level(eb));
36}
37#else
38static inline void spin_nested(struct extent_buffer *eb) 28static inline void spin_nested(struct extent_buffer *eb)
39{ 29{
40 spin_lock(&eb->lock); 30 spin_lock(&eb->lock);
41} 31}
42#endif
43 32
44/* 33/*
45 * Setting a lock to blocking will drop the spinlock and set the 34 * Setting a lock to blocking will drop the spinlock and set the
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index c793b6f50d8..1316139bf9e 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -3102,6 +3102,8 @@ int btrfs_read_sys_array(struct btrfs_root *root)
3102 if (!sb) 3102 if (!sb)
3103 return -ENOMEM; 3103 return -ENOMEM;
3104 btrfs_set_buffer_uptodate(sb); 3104 btrfs_set_buffer_uptodate(sb);
3105 btrfs_set_buffer_lockdep_class(sb, 0);
3106
3105 write_extent_buffer(sb, super_copy, 0, BTRFS_SUPER_INFO_SIZE); 3107 write_extent_buffer(sb, super_copy, 0, BTRFS_SUPER_INFO_SIZE);
3106 array_size = btrfs_super_sys_array_size(super_copy); 3108 array_size = btrfs_super_sys_array_size(super_copy);
3107 3109