diff options
-rw-r--r-- | fs/btrfs/ctree.c | 45 | ||||
-rw-r--r-- | fs/btrfs/ctree.h | 10 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 46 | ||||
-rw-r--r-- | fs/btrfs/disk-io.h | 10 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 7 | ||||
-rw-r--r-- | fs/btrfs/locking.c | 11 | ||||
-rw-r--r-- | fs/btrfs/volumes.c | 2 |
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 | */ |
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) |
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); |
1716 | struct extent_buffer *btrfs_init_new_buffer(struct btrfs_trans_handle *trans, | 1712 | struct 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); | ||
1719 | int btrfs_alloc_extent(struct btrfs_trans_handle *trans, | 1716 | int 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); | |||
1835 | struct btrfs_path *btrfs_alloc_path(void); | 1832 | struct btrfs_path *btrfs_alloc_path(void); |
1836 | void btrfs_free_path(struct btrfs_path *p); | 1833 | void btrfs_free_path(struct btrfs_path *p); |
1837 | void btrfs_set_path_blocking(struct btrfs_path *p); | 1834 | void btrfs_set_path_blocking(struct btrfs_path *p); |
1838 | void btrfs_clear_path_blocking(struct btrfs_path *p); | ||
1839 | void btrfs_unlock_up_safe(struct btrfs_path *p, int level); | 1835 | void btrfs_unlock_up_safe(struct btrfs_path *p, int level); |
1840 | 1836 | ||
1841 | int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 1837 | int 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 | ||
96 | static struct lock_class_key btrfs_eb_class[BTRFS_MAX_LEVEL + 1]; | ||
97 | static 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 | ||
385 | void 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 | |||
350 | static int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end, | 393 | static 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, | |||
101 | int btrfs_add_log_tree(struct btrfs_trans_handle *trans, | 101 | int btrfs_add_log_tree(struct btrfs_trans_handle *trans, |
102 | struct btrfs_root *root); | 102 | struct btrfs_root *root); |
103 | int btree_lock_page_hook(struct page *page); | 103 | int btree_lock_page_hook(struct page *page); |
104 | |||
105 | |||
106 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
107 | void btrfs_set_buffer_lockdep_class(struct extent_buffer *eb, int level); | ||
108 | #else | ||
109 | static 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 | ||
3417 | struct extent_buffer *btrfs_init_new_buffer(struct btrfs_trans_handle *trans, | 3417 | struct 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 | ||
33 | static 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 | ||
38 | static inline void spin_nested(struct extent_buffer *eb) | 28 | static 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 | ||