aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/disk-io.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/disk-io.c')
-rw-r--r--fs/btrfs/disk-io.c116
1 files changed, 78 insertions, 38 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index b231ae13b269..07b3ac662e19 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -100,38 +100,83 @@ struct async_submit_bio {
100 struct btrfs_work work; 100 struct btrfs_work work;
101}; 101};
102 102
103/* These are used to set the lockdep class on the extent buffer locks. 103/*
104 * The class is set by the readpage_end_io_hook after the buffer has 104 * Lockdep class keys for extent_buffer->lock's in this root. For a given
105 * passed csum validation but before the pages are unlocked. 105 * eb, the lockdep key is determined by the btrfs_root it belongs to and
106 * the level the eb occupies in the tree.
107 *
108 * Different roots are used for different purposes and may nest inside each
109 * other and they require separate keysets. As lockdep keys should be
110 * static, assign keysets according to the purpose of the root as indicated
111 * by btrfs_root->objectid. This ensures that all special purpose roots
112 * have separate keysets.
106 * 113 *
107 * The lockdep class is also set by btrfs_init_new_buffer on freshly 114 * Lock-nesting across peer nodes is always done with the immediate parent
108 * allocated blocks. 115 * node locked thus preventing deadlock. As lockdep doesn't know this, use
116 * subclass to avoid triggering lockdep warning in such cases.
109 * 117 *
110 * The class is based on the level in the tree block, which allows lockdep 118 * The key is set by the readpage_end_io_hook after the buffer has passed
111 * to know that lower nodes nest inside the locks of higher nodes. 119 * csum validation but before the pages are unlocked. It is also set by
120 * btrfs_init_new_buffer on freshly allocated blocks.
112 * 121 *
113 * We also add a check to make sure the highest level of the tree is 122 * We also add a check to make sure the highest level of the tree is the
114 * the same as our lockdep setup here. If BTRFS_MAX_LEVEL changes, this 123 * same as our lockdep setup here. If BTRFS_MAX_LEVEL changes, this code
115 * code needs update as well. 124 * needs update as well.
116 */ 125 */
117#ifdef CONFIG_DEBUG_LOCK_ALLOC 126#ifdef CONFIG_DEBUG_LOCK_ALLOC
118# if BTRFS_MAX_LEVEL != 8 127# if BTRFS_MAX_LEVEL != 8
119# error 128# error
120# endif 129# endif
121static struct lock_class_key btrfs_eb_class[BTRFS_MAX_LEVEL + 1]; 130
122static const char *btrfs_eb_name[BTRFS_MAX_LEVEL + 1] = { 131static struct btrfs_lockdep_keyset {
123 /* leaf */ 132 u64 id; /* root objectid */
124 "btrfs-extent-00", 133 const char *name_stem; /* lock name stem */
125 "btrfs-extent-01", 134 char names[BTRFS_MAX_LEVEL + 1][20];
126 "btrfs-extent-02", 135 struct lock_class_key keys[BTRFS_MAX_LEVEL + 1];
127 "btrfs-extent-03", 136} btrfs_lockdep_keysets[] = {
128 "btrfs-extent-04", 137 { .id = BTRFS_ROOT_TREE_OBJECTID, .name_stem = "root" },
129 "btrfs-extent-05", 138 { .id = BTRFS_EXTENT_TREE_OBJECTID, .name_stem = "extent" },
130 "btrfs-extent-06", 139 { .id = BTRFS_CHUNK_TREE_OBJECTID, .name_stem = "chunk" },
131 "btrfs-extent-07", 140 { .id = BTRFS_DEV_TREE_OBJECTID, .name_stem = "dev" },
132 /* highest possible level */ 141 { .id = BTRFS_FS_TREE_OBJECTID, .name_stem = "fs" },
133 "btrfs-extent-08", 142 { .id = BTRFS_CSUM_TREE_OBJECTID, .name_stem = "csum" },
143 { .id = BTRFS_ORPHAN_OBJECTID, .name_stem = "orphan" },
144 { .id = BTRFS_TREE_LOG_OBJECTID, .name_stem = "log" },
145 { .id = BTRFS_TREE_RELOC_OBJECTID, .name_stem = "treloc" },
146 { .id = BTRFS_DATA_RELOC_TREE_OBJECTID, .name_stem = "dreloc" },
147 { .id = 0, .name_stem = "tree" },
134}; 148};
149
150void __init btrfs_init_lockdep(void)
151{
152 int i, j;
153
154 /* initialize lockdep class names */
155 for (i = 0; i < ARRAY_SIZE(btrfs_lockdep_keysets); i++) {
156 struct btrfs_lockdep_keyset *ks = &btrfs_lockdep_keysets[i];
157
158 for (j = 0; j < ARRAY_SIZE(ks->names); j++)
159 snprintf(ks->names[j], sizeof(ks->names[j]),
160 "btrfs-%s-%02d", ks->name_stem, j);
161 }
162}
163
164void btrfs_set_buffer_lockdep_class(u64 objectid, struct extent_buffer *eb,
165 int level)
166{
167 struct btrfs_lockdep_keyset *ks;
168
169 BUG_ON(level >= ARRAY_SIZE(ks->keys));
170
171 /* find the matching keyset, id 0 is the default entry */
172 for (ks = btrfs_lockdep_keysets; ks->id; ks++)
173 if (ks->id == objectid)
174 break;
175
176 lockdep_set_class_and_name(&eb->lock,
177 &ks->keys[level], ks->names[level]);
178}
179
135#endif 180#endif
136 181
137/* 182/*
@@ -217,7 +262,6 @@ static int csum_tree_block(struct btrfs_root *root, struct extent_buffer *buf,
217 unsigned long len; 262 unsigned long len;
218 unsigned long cur_len; 263 unsigned long cur_len;
219 unsigned long offset = BTRFS_CSUM_SIZE; 264 unsigned long offset = BTRFS_CSUM_SIZE;
220 char *map_token = NULL;
221 char *kaddr; 265 char *kaddr;
222 unsigned long map_start; 266 unsigned long map_start;
223 unsigned long map_len; 267 unsigned long map_len;
@@ -228,8 +272,7 @@ static int csum_tree_block(struct btrfs_root *root, struct extent_buffer *buf,
228 len = buf->len - offset; 272 len = buf->len - offset;
229 while (len > 0) { 273 while (len > 0) {
230 err = map_private_extent_buffer(buf, offset, 32, 274 err = map_private_extent_buffer(buf, offset, 32,
231 &map_token, &kaddr, 275 &kaddr, &map_start, &map_len);
232 &map_start, &map_len, KM_USER0);
233 if (err) 276 if (err)
234 return 1; 277 return 1;
235 cur_len = min(len, map_len - (offset - map_start)); 278 cur_len = min(len, map_len - (offset - map_start));
@@ -237,7 +280,6 @@ static int csum_tree_block(struct btrfs_root *root, struct extent_buffer *buf,
237 crc, cur_len); 280 crc, cur_len);
238 len -= cur_len; 281 len -= cur_len;
239 offset += cur_len; 282 offset += cur_len;
240 unmap_extent_buffer(buf, map_token, KM_USER0);
241 } 283 }
242 if (csum_size > sizeof(inline_result)) { 284 if (csum_size > sizeof(inline_result)) {
243 result = kzalloc(csum_size * sizeof(char), GFP_NOFS); 285 result = kzalloc(csum_size * sizeof(char), GFP_NOFS);
@@ -494,15 +536,6 @@ static noinline int check_leaf(struct btrfs_root *root,
494 return 0; 536 return 0;
495} 537}
496 538
497#ifdef CONFIG_DEBUG_LOCK_ALLOC
498void btrfs_set_buffer_lockdep_class(struct extent_buffer *eb, int level)
499{
500 lockdep_set_class_and_name(&eb->lock,
501 &btrfs_eb_class[level],
502 btrfs_eb_name[level]);
503}
504#endif
505
506static int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end, 539static int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end,
507 struct extent_state *state) 540 struct extent_state *state)
508{ 541{
@@ -553,7 +586,8 @@ static int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end,
553 } 586 }
554 found_level = btrfs_header_level(eb); 587 found_level = btrfs_header_level(eb);
555 588
556 btrfs_set_buffer_lockdep_class(eb, found_level); 589 btrfs_set_buffer_lockdep_class(btrfs_header_owner(eb),
590 eb, found_level);
557 591
558 ret = csum_tree_block(root, eb, 1); 592 ret = csum_tree_block(root, eb, 1);
559 if (ret) { 593 if (ret) {
@@ -1598,7 +1632,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
1598 goto fail_bdi; 1632 goto fail_bdi;
1599 } 1633 }
1600 1634
1601 fs_info->btree_inode->i_mapping->flags &= ~__GFP_FS; 1635 mapping_set_gfp_mask(fs_info->btree_inode->i_mapping, GFP_NOFS);
1602 1636
1603 INIT_RADIX_TREE(&fs_info->fs_roots_radix, GFP_ATOMIC); 1637 INIT_RADIX_TREE(&fs_info->fs_roots_radix, GFP_ATOMIC);
1604 INIT_LIST_HEAD(&fs_info->trans_list); 1638 INIT_LIST_HEAD(&fs_info->trans_list);
@@ -1802,6 +1836,9 @@ struct btrfs_root *open_ctree(struct super_block *sb,
1802 fs_info->thread_pool_size), 1836 fs_info->thread_pool_size),
1803 &fs_info->generic_worker); 1837 &fs_info->generic_worker);
1804 1838
1839 btrfs_init_workers(&fs_info->caching_workers, "cache",
1840 2, &fs_info->generic_worker);
1841
1805 /* a higher idle thresh on the submit workers makes it much more 1842 /* a higher idle thresh on the submit workers makes it much more
1806 * likely that bios will be send down in a sane order to the 1843 * likely that bios will be send down in a sane order to the
1807 * devices 1844 * devices
@@ -1855,6 +1892,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
1855 btrfs_start_workers(&fs_info->endio_write_workers, 1); 1892 btrfs_start_workers(&fs_info->endio_write_workers, 1);
1856 btrfs_start_workers(&fs_info->endio_freespace_worker, 1); 1893 btrfs_start_workers(&fs_info->endio_freespace_worker, 1);
1857 btrfs_start_workers(&fs_info->delayed_workers, 1); 1894 btrfs_start_workers(&fs_info->delayed_workers, 1);
1895 btrfs_start_workers(&fs_info->caching_workers, 1);
1858 1896
1859 fs_info->bdi.ra_pages *= btrfs_super_num_devices(disk_super); 1897 fs_info->bdi.ra_pages *= btrfs_super_num_devices(disk_super);
1860 fs_info->bdi.ra_pages = max(fs_info->bdi.ra_pages, 1898 fs_info->bdi.ra_pages = max(fs_info->bdi.ra_pages,
@@ -2112,6 +2150,7 @@ fail_sb_buffer:
2112 btrfs_stop_workers(&fs_info->endio_freespace_worker); 2150 btrfs_stop_workers(&fs_info->endio_freespace_worker);
2113 btrfs_stop_workers(&fs_info->submit_workers); 2151 btrfs_stop_workers(&fs_info->submit_workers);
2114 btrfs_stop_workers(&fs_info->delayed_workers); 2152 btrfs_stop_workers(&fs_info->delayed_workers);
2153 btrfs_stop_workers(&fs_info->caching_workers);
2115fail_alloc: 2154fail_alloc:
2116 kfree(fs_info->delayed_root); 2155 kfree(fs_info->delayed_root);
2117fail_iput: 2156fail_iput:
@@ -2577,6 +2616,7 @@ int close_ctree(struct btrfs_root *root)
2577 btrfs_stop_workers(&fs_info->endio_freespace_worker); 2616 btrfs_stop_workers(&fs_info->endio_freespace_worker);
2578 btrfs_stop_workers(&fs_info->submit_workers); 2617 btrfs_stop_workers(&fs_info->submit_workers);
2579 btrfs_stop_workers(&fs_info->delayed_workers); 2618 btrfs_stop_workers(&fs_info->delayed_workers);
2619 btrfs_stop_workers(&fs_info->caching_workers);
2580 2620
2581 btrfs_close_devices(fs_info->fs_devices); 2621 btrfs_close_devices(fs_info->fs_devices);
2582 btrfs_mapping_tree_free(&fs_info->mapping_tree); 2622 btrfs_mapping_tree_free(&fs_info->mapping_tree);