diff options
Diffstat (limited to 'fs/btrfs/backref.c')
-rw-r--r-- | fs/btrfs/backref.c | 568 |
1 files changed, 388 insertions, 180 deletions
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c index bcec06750232..7301cdb4b2cb 100644 --- a/fs/btrfs/backref.c +++ b/fs/btrfs/backref.c | |||
@@ -24,22 +24,135 @@ | |||
24 | #include "delayed-ref.h" | 24 | #include "delayed-ref.h" |
25 | #include "locking.h" | 25 | #include "locking.h" |
26 | 26 | ||
27 | struct extent_inode_elem { | ||
28 | u64 inum; | ||
29 | u64 offset; | ||
30 | struct extent_inode_elem *next; | ||
31 | }; | ||
32 | |||
33 | static int check_extent_in_eb(struct btrfs_key *key, struct extent_buffer *eb, | ||
34 | struct btrfs_file_extent_item *fi, | ||
35 | u64 extent_item_pos, | ||
36 | struct extent_inode_elem **eie) | ||
37 | { | ||
38 | u64 data_offset; | ||
39 | u64 data_len; | ||
40 | struct extent_inode_elem *e; | ||
41 | |||
42 | data_offset = btrfs_file_extent_offset(eb, fi); | ||
43 | data_len = btrfs_file_extent_num_bytes(eb, fi); | ||
44 | |||
45 | if (extent_item_pos < data_offset || | ||
46 | extent_item_pos >= data_offset + data_len) | ||
47 | return 1; | ||
48 | |||
49 | e = kmalloc(sizeof(*e), GFP_NOFS); | ||
50 | if (!e) | ||
51 | return -ENOMEM; | ||
52 | |||
53 | e->next = *eie; | ||
54 | e->inum = key->objectid; | ||
55 | e->offset = key->offset + (extent_item_pos - data_offset); | ||
56 | *eie = e; | ||
57 | |||
58 | return 0; | ||
59 | } | ||
60 | |||
61 | static int find_extent_in_eb(struct extent_buffer *eb, u64 wanted_disk_byte, | ||
62 | u64 extent_item_pos, | ||
63 | struct extent_inode_elem **eie) | ||
64 | { | ||
65 | u64 disk_byte; | ||
66 | struct btrfs_key key; | ||
67 | struct btrfs_file_extent_item *fi; | ||
68 | int slot; | ||
69 | int nritems; | ||
70 | int extent_type; | ||
71 | int ret; | ||
72 | |||
73 | /* | ||
74 | * from the shared data ref, we only have the leaf but we need | ||
75 | * the key. thus, we must look into all items and see that we | ||
76 | * find one (some) with a reference to our extent item. | ||
77 | */ | ||
78 | nritems = btrfs_header_nritems(eb); | ||
79 | for (slot = 0; slot < nritems; ++slot) { | ||
80 | btrfs_item_key_to_cpu(eb, &key, slot); | ||
81 | if (key.type != BTRFS_EXTENT_DATA_KEY) | ||
82 | continue; | ||
83 | fi = btrfs_item_ptr(eb, slot, struct btrfs_file_extent_item); | ||
84 | extent_type = btrfs_file_extent_type(eb, fi); | ||
85 | if (extent_type == BTRFS_FILE_EXTENT_INLINE) | ||
86 | continue; | ||
87 | /* don't skip BTRFS_FILE_EXTENT_PREALLOC, we can handle that */ | ||
88 | disk_byte = btrfs_file_extent_disk_bytenr(eb, fi); | ||
89 | if (disk_byte != wanted_disk_byte) | ||
90 | continue; | ||
91 | |||
92 | ret = check_extent_in_eb(&key, eb, fi, extent_item_pos, eie); | ||
93 | if (ret < 0) | ||
94 | return ret; | ||
95 | } | ||
96 | |||
97 | return 0; | ||
98 | } | ||
99 | |||
27 | /* | 100 | /* |
28 | * this structure records all encountered refs on the way up to the root | 101 | * this structure records all encountered refs on the way up to the root |
29 | */ | 102 | */ |
30 | struct __prelim_ref { | 103 | struct __prelim_ref { |
31 | struct list_head list; | 104 | struct list_head list; |
32 | u64 root_id; | 105 | u64 root_id; |
33 | struct btrfs_key key; | 106 | struct btrfs_key key_for_search; |
34 | int level; | 107 | int level; |
35 | int count; | 108 | int count; |
109 | struct extent_inode_elem *inode_list; | ||
36 | u64 parent; | 110 | u64 parent; |
37 | u64 wanted_disk_byte; | 111 | u64 wanted_disk_byte; |
38 | }; | 112 | }; |
39 | 113 | ||
114 | /* | ||
115 | * the rules for all callers of this function are: | ||
116 | * - obtaining the parent is the goal | ||
117 | * - if you add a key, you must know that it is a correct key | ||
118 | * - if you cannot add the parent or a correct key, then we will look into the | ||
119 | * block later to set a correct key | ||
120 | * | ||
121 | * delayed refs | ||
122 | * ============ | ||
123 | * backref type | shared | indirect | shared | indirect | ||
124 | * information | tree | tree | data | data | ||
125 | * --------------------+--------+----------+--------+---------- | ||
126 | * parent logical | y | - | - | - | ||
127 | * key to resolve | - | y | y | y | ||
128 | * tree block logical | - | - | - | - | ||
129 | * root for resolving | y | y | y | y | ||
130 | * | ||
131 | * - column 1: we've the parent -> done | ||
132 | * - column 2, 3, 4: we use the key to find the parent | ||
133 | * | ||
134 | * on disk refs (inline or keyed) | ||
135 | * ============================== | ||
136 | * backref type | shared | indirect | shared | indirect | ||
137 | * information | tree | tree | data | data | ||
138 | * --------------------+--------+----------+--------+---------- | ||
139 | * parent logical | y | - | y | - | ||
140 | * key to resolve | - | - | - | y | ||
141 | * tree block logical | y | y | y | y | ||
142 | * root for resolving | - | y | y | y | ||
143 | * | ||
144 | * - column 1, 3: we've the parent -> done | ||
145 | * - column 2: we take the first key from the block to find the parent | ||
146 | * (see __add_missing_keys) | ||
147 | * - column 4: we use the key to find the parent | ||
148 | * | ||
149 | * additional information that's available but not required to find the parent | ||
150 | * block might help in merging entries to gain some speed. | ||
151 | */ | ||
152 | |||
40 | static int __add_prelim_ref(struct list_head *head, u64 root_id, | 153 | static int __add_prelim_ref(struct list_head *head, u64 root_id, |
41 | struct btrfs_key *key, int level, u64 parent, | 154 | struct btrfs_key *key, int level, |
42 | u64 wanted_disk_byte, int count) | 155 | u64 parent, u64 wanted_disk_byte, int count) |
43 | { | 156 | { |
44 | struct __prelim_ref *ref; | 157 | struct __prelim_ref *ref; |
45 | 158 | ||
@@ -50,10 +163,11 @@ static int __add_prelim_ref(struct list_head *head, u64 root_id, | |||
50 | 163 | ||
51 | ref->root_id = root_id; | 164 | ref->root_id = root_id; |
52 | if (key) | 165 | if (key) |
53 | ref->key = *key; | 166 | ref->key_for_search = *key; |
54 | else | 167 | else |
55 | memset(&ref->key, 0, sizeof(ref->key)); | 168 | memset(&ref->key_for_search, 0, sizeof(ref->key_for_search)); |
56 | 169 | ||
170 | ref->inode_list = NULL; | ||
57 | ref->level = level; | 171 | ref->level = level; |
58 | ref->count = count; | 172 | ref->count = count; |
59 | ref->parent = parent; | 173 | ref->parent = parent; |
@@ -64,52 +178,75 @@ static int __add_prelim_ref(struct list_head *head, u64 root_id, | |||
64 | } | 178 | } |
65 | 179 | ||
66 | static int add_all_parents(struct btrfs_root *root, struct btrfs_path *path, | 180 | static int add_all_parents(struct btrfs_root *root, struct btrfs_path *path, |
67 | struct ulist *parents, | 181 | struct ulist *parents, int level, |
68 | struct extent_buffer *eb, int level, | 182 | struct btrfs_key *key_for_search, u64 time_seq, |
69 | u64 wanted_objectid, u64 wanted_disk_byte) | 183 | u64 wanted_disk_byte, |
184 | const u64 *extent_item_pos) | ||
70 | { | 185 | { |
71 | int ret; | 186 | int ret = 0; |
72 | int slot; | 187 | int slot; |
73 | struct btrfs_file_extent_item *fi; | 188 | struct extent_buffer *eb; |
74 | struct btrfs_key key; | 189 | struct btrfs_key key; |
190 | struct btrfs_file_extent_item *fi; | ||
191 | struct extent_inode_elem *eie = NULL; | ||
75 | u64 disk_byte; | 192 | u64 disk_byte; |
76 | 193 | ||
77 | add_parent: | 194 | if (level != 0) { |
78 | ret = ulist_add(parents, eb->start, 0, GFP_NOFS); | 195 | eb = path->nodes[level]; |
79 | if (ret < 0) | 196 | ret = ulist_add(parents, eb->start, 0, GFP_NOFS); |
80 | return ret; | 197 | if (ret < 0) |
81 | 198 | return ret; | |
82 | if (level != 0) | ||
83 | return 0; | 199 | return 0; |
200 | } | ||
84 | 201 | ||
85 | /* | 202 | /* |
86 | * if the current leaf is full with EXTENT_DATA items, we must | 203 | * We normally enter this function with the path already pointing to |
87 | * check the next one if that holds a reference as well. | 204 | * the first item to check. But sometimes, we may enter it with |
88 | * ref->count cannot be used to skip this check. | 205 | * slot==nritems. In that case, go to the next leaf before we continue. |
89 | * repeat this until we don't find any additional EXTENT_DATA items. | ||
90 | */ | 206 | */ |
91 | while (1) { | 207 | if (path->slots[0] >= btrfs_header_nritems(path->nodes[0])) |
92 | ret = btrfs_next_leaf(root, path); | 208 | ret = btrfs_next_old_leaf(root, path, time_seq); |
93 | if (ret < 0) | ||
94 | return ret; | ||
95 | if (ret) | ||
96 | return 0; | ||
97 | 209 | ||
210 | while (!ret) { | ||
98 | eb = path->nodes[0]; | 211 | eb = path->nodes[0]; |
99 | for (slot = 0; slot < btrfs_header_nritems(eb); ++slot) { | 212 | slot = path->slots[0]; |
100 | btrfs_item_key_to_cpu(eb, &key, slot); | 213 | |
101 | if (key.objectid != wanted_objectid || | 214 | btrfs_item_key_to_cpu(eb, &key, slot); |
102 | key.type != BTRFS_EXTENT_DATA_KEY) | 215 | |
103 | return 0; | 216 | if (key.objectid != key_for_search->objectid || |
104 | fi = btrfs_item_ptr(eb, slot, | 217 | key.type != BTRFS_EXTENT_DATA_KEY) |
105 | struct btrfs_file_extent_item); | 218 | break; |
106 | disk_byte = btrfs_file_extent_disk_bytenr(eb, fi); | 219 | |
107 | if (disk_byte == wanted_disk_byte) | 220 | fi = btrfs_item_ptr(eb, slot, struct btrfs_file_extent_item); |
108 | goto add_parent; | 221 | disk_byte = btrfs_file_extent_disk_bytenr(eb, fi); |
222 | |||
223 | if (disk_byte == wanted_disk_byte) { | ||
224 | eie = NULL; | ||
225 | if (extent_item_pos) { | ||
226 | ret = check_extent_in_eb(&key, eb, fi, | ||
227 | *extent_item_pos, | ||
228 | &eie); | ||
229 | if (ret < 0) | ||
230 | break; | ||
231 | } | ||
232 | if (!ret) { | ||
233 | ret = ulist_add(parents, eb->start, | ||
234 | (unsigned long)eie, GFP_NOFS); | ||
235 | if (ret < 0) | ||
236 | break; | ||
237 | if (!extent_item_pos) { | ||
238 | ret = btrfs_next_old_leaf(root, path, | ||
239 | time_seq); | ||
240 | continue; | ||
241 | } | ||
242 | } | ||
109 | } | 243 | } |
244 | ret = btrfs_next_old_item(root, path, time_seq); | ||
110 | } | 245 | } |
111 | 246 | ||
112 | return 0; | 247 | if (ret > 0) |
248 | ret = 0; | ||
249 | return ret; | ||
113 | } | 250 | } |
114 | 251 | ||
115 | /* | 252 | /* |
@@ -118,13 +255,14 @@ add_parent: | |||
118 | */ | 255 | */ |
119 | static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info, | 256 | static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info, |
120 | int search_commit_root, | 257 | int search_commit_root, |
258 | u64 time_seq, | ||
121 | struct __prelim_ref *ref, | 259 | struct __prelim_ref *ref, |
122 | struct ulist *parents) | 260 | struct ulist *parents, |
261 | const u64 *extent_item_pos) | ||
123 | { | 262 | { |
124 | struct btrfs_path *path; | 263 | struct btrfs_path *path; |
125 | struct btrfs_root *root; | 264 | struct btrfs_root *root; |
126 | struct btrfs_key root_key; | 265 | struct btrfs_key root_key; |
127 | struct btrfs_key key = {0}; | ||
128 | struct extent_buffer *eb; | 266 | struct extent_buffer *eb; |
129 | int ret = 0; | 267 | int ret = 0; |
130 | int root_level; | 268 | int root_level; |
@@ -152,12 +290,13 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info, | |||
152 | goto out; | 290 | goto out; |
153 | 291 | ||
154 | path->lowest_level = level; | 292 | path->lowest_level = level; |
155 | ret = btrfs_search_slot(NULL, root, &ref->key, path, 0, 0); | 293 | ret = btrfs_search_old_slot(root, &ref->key_for_search, path, time_seq); |
156 | pr_debug("search slot in root %llu (level %d, ref count %d) returned " | 294 | pr_debug("search slot in root %llu (level %d, ref count %d) returned " |
157 | "%d for key (%llu %u %llu)\n", | 295 | "%d for key (%llu %u %llu)\n", |
158 | (unsigned long long)ref->root_id, level, ref->count, ret, | 296 | (unsigned long long)ref->root_id, level, ref->count, ret, |
159 | (unsigned long long)ref->key.objectid, ref->key.type, | 297 | (unsigned long long)ref->key_for_search.objectid, |
160 | (unsigned long long)ref->key.offset); | 298 | ref->key_for_search.type, |
299 | (unsigned long long)ref->key_for_search.offset); | ||
161 | if (ret < 0) | 300 | if (ret < 0) |
162 | goto out; | 301 | goto out; |
163 | 302 | ||
@@ -168,20 +307,9 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info, | |||
168 | goto out; | 307 | goto out; |
169 | } | 308 | } |
170 | 309 | ||
171 | if (level == 0) { | 310 | ret = add_all_parents(root, path, parents, level, &ref->key_for_search, |
172 | if (ret == 1 && path->slots[0] >= btrfs_header_nritems(eb)) { | 311 | time_seq, ref->wanted_disk_byte, |
173 | ret = btrfs_next_leaf(root, path); | 312 | extent_item_pos); |
174 | if (ret) | ||
175 | goto out; | ||
176 | eb = path->nodes[0]; | ||
177 | } | ||
178 | |||
179 | btrfs_item_key_to_cpu(eb, &key, path->slots[0]); | ||
180 | } | ||
181 | |||
182 | /* the last two parameters will only be used for level == 0 */ | ||
183 | ret = add_all_parents(root, path, parents, eb, level, key.objectid, | ||
184 | ref->wanted_disk_byte); | ||
185 | out: | 313 | out: |
186 | btrfs_free_path(path); | 314 | btrfs_free_path(path); |
187 | return ret; | 315 | return ret; |
@@ -191,8 +319,9 @@ out: | |||
191 | * resolve all indirect backrefs from the list | 319 | * resolve all indirect backrefs from the list |
192 | */ | 320 | */ |
193 | static int __resolve_indirect_refs(struct btrfs_fs_info *fs_info, | 321 | static int __resolve_indirect_refs(struct btrfs_fs_info *fs_info, |
194 | int search_commit_root, | 322 | int search_commit_root, u64 time_seq, |
195 | struct list_head *head) | 323 | struct list_head *head, |
324 | const u64 *extent_item_pos) | ||
196 | { | 325 | { |
197 | int err; | 326 | int err; |
198 | int ret = 0; | 327 | int ret = 0; |
@@ -201,6 +330,7 @@ static int __resolve_indirect_refs(struct btrfs_fs_info *fs_info, | |||
201 | struct __prelim_ref *new_ref; | 330 | struct __prelim_ref *new_ref; |
202 | struct ulist *parents; | 331 | struct ulist *parents; |
203 | struct ulist_node *node; | 332 | struct ulist_node *node; |
333 | struct ulist_iterator uiter; | ||
204 | 334 | ||
205 | parents = ulist_alloc(GFP_NOFS); | 335 | parents = ulist_alloc(GFP_NOFS); |
206 | if (!parents) | 336 | if (!parents) |
@@ -217,7 +347,8 @@ static int __resolve_indirect_refs(struct btrfs_fs_info *fs_info, | |||
217 | if (ref->count == 0) | 347 | if (ref->count == 0) |
218 | continue; | 348 | continue; |
219 | err = __resolve_indirect_ref(fs_info, search_commit_root, | 349 | err = __resolve_indirect_ref(fs_info, search_commit_root, |
220 | ref, parents); | 350 | time_seq, ref, parents, |
351 | extent_item_pos); | ||
221 | if (err) { | 352 | if (err) { |
222 | if (ret == 0) | 353 | if (ret == 0) |
223 | ret = err; | 354 | ret = err; |
@@ -225,11 +356,14 @@ static int __resolve_indirect_refs(struct btrfs_fs_info *fs_info, | |||
225 | } | 356 | } |
226 | 357 | ||
227 | /* we put the first parent into the ref at hand */ | 358 | /* we put the first parent into the ref at hand */ |
228 | node = ulist_next(parents, NULL); | 359 | ULIST_ITER_INIT(&uiter); |
360 | node = ulist_next(parents, &uiter); | ||
229 | ref->parent = node ? node->val : 0; | 361 | ref->parent = node ? node->val : 0; |
362 | ref->inode_list = | ||
363 | node ? (struct extent_inode_elem *)node->aux : 0; | ||
230 | 364 | ||
231 | /* additional parents require new refs being added here */ | 365 | /* additional parents require new refs being added here */ |
232 | while ((node = ulist_next(parents, node))) { | 366 | while ((node = ulist_next(parents, &uiter))) { |
233 | new_ref = kmalloc(sizeof(*new_ref), GFP_NOFS); | 367 | new_ref = kmalloc(sizeof(*new_ref), GFP_NOFS); |
234 | if (!new_ref) { | 368 | if (!new_ref) { |
235 | ret = -ENOMEM; | 369 | ret = -ENOMEM; |
@@ -237,6 +371,8 @@ static int __resolve_indirect_refs(struct btrfs_fs_info *fs_info, | |||
237 | } | 371 | } |
238 | memcpy(new_ref, ref, sizeof(*ref)); | 372 | memcpy(new_ref, ref, sizeof(*ref)); |
239 | new_ref->parent = node->val; | 373 | new_ref->parent = node->val; |
374 | new_ref->inode_list = | ||
375 | (struct extent_inode_elem *)node->aux; | ||
240 | list_add(&new_ref->list, &ref->list); | 376 | list_add(&new_ref->list, &ref->list); |
241 | } | 377 | } |
242 | ulist_reinit(parents); | 378 | ulist_reinit(parents); |
@@ -246,10 +382,65 @@ static int __resolve_indirect_refs(struct btrfs_fs_info *fs_info, | |||
246 | return ret; | 382 | return ret; |
247 | } | 383 | } |
248 | 384 | ||
385 | static inline int ref_for_same_block(struct __prelim_ref *ref1, | ||
386 | struct __prelim_ref *ref2) | ||
387 | { | ||
388 | if (ref1->level != ref2->level) | ||
389 | return 0; | ||
390 | if (ref1->root_id != ref2->root_id) | ||
391 | return 0; | ||
392 | if (ref1->key_for_search.type != ref2->key_for_search.type) | ||
393 | return 0; | ||
394 | if (ref1->key_for_search.objectid != ref2->key_for_search.objectid) | ||
395 | return 0; | ||
396 | if (ref1->key_for_search.offset != ref2->key_for_search.offset) | ||
397 | return 0; | ||
398 | if (ref1->parent != ref2->parent) | ||
399 | return 0; | ||
400 | |||
401 | return 1; | ||
402 | } | ||
403 | |||
404 | /* | ||
405 | * read tree blocks and add keys where required. | ||
406 | */ | ||
407 | static int __add_missing_keys(struct btrfs_fs_info *fs_info, | ||
408 | struct list_head *head) | ||
409 | { | ||
410 | struct list_head *pos; | ||
411 | struct extent_buffer *eb; | ||
412 | |||
413 | list_for_each(pos, head) { | ||
414 | struct __prelim_ref *ref; | ||
415 | ref = list_entry(pos, struct __prelim_ref, list); | ||
416 | |||
417 | if (ref->parent) | ||
418 | continue; | ||
419 | if (ref->key_for_search.type) | ||
420 | continue; | ||
421 | BUG_ON(!ref->wanted_disk_byte); | ||
422 | eb = read_tree_block(fs_info->tree_root, ref->wanted_disk_byte, | ||
423 | fs_info->tree_root->leafsize, 0); | ||
424 | BUG_ON(!eb); | ||
425 | btrfs_tree_read_lock(eb); | ||
426 | if (btrfs_header_level(eb) == 0) | ||
427 | btrfs_item_key_to_cpu(eb, &ref->key_for_search, 0); | ||
428 | else | ||
429 | btrfs_node_key_to_cpu(eb, &ref->key_for_search, 0); | ||
430 | btrfs_tree_read_unlock(eb); | ||
431 | free_extent_buffer(eb); | ||
432 | } | ||
433 | return 0; | ||
434 | } | ||
435 | |||
249 | /* | 436 | /* |
250 | * merge two lists of backrefs and adjust counts accordingly | 437 | * merge two lists of backrefs and adjust counts accordingly |
251 | * | 438 | * |
252 | * mode = 1: merge identical keys, if key is set | 439 | * mode = 1: merge identical keys, if key is set |
440 | * FIXME: if we add more keys in __add_prelim_ref, we can merge more here. | ||
441 | * additionally, we could even add a key range for the blocks we | ||
442 | * looked into to merge even more (-> replace unresolved refs by those | ||
443 | * having a parent). | ||
253 | * mode = 2: merge identical parents | 444 | * mode = 2: merge identical parents |
254 | */ | 445 | */ |
255 | static int __merge_refs(struct list_head *head, int mode) | 446 | static int __merge_refs(struct list_head *head, int mode) |
@@ -263,20 +454,21 @@ static int __merge_refs(struct list_head *head, int mode) | |||
263 | 454 | ||
264 | ref1 = list_entry(pos1, struct __prelim_ref, list); | 455 | ref1 = list_entry(pos1, struct __prelim_ref, list); |
265 | 456 | ||
266 | if (mode == 1 && ref1->key.type == 0) | ||
267 | continue; | ||
268 | for (pos2 = pos1->next, n2 = pos2->next; pos2 != head; | 457 | for (pos2 = pos1->next, n2 = pos2->next; pos2 != head; |
269 | pos2 = n2, n2 = pos2->next) { | 458 | pos2 = n2, n2 = pos2->next) { |
270 | struct __prelim_ref *ref2; | 459 | struct __prelim_ref *ref2; |
460 | struct __prelim_ref *xchg; | ||
271 | 461 | ||
272 | ref2 = list_entry(pos2, struct __prelim_ref, list); | 462 | ref2 = list_entry(pos2, struct __prelim_ref, list); |
273 | 463 | ||
274 | if (mode == 1) { | 464 | if (mode == 1) { |
275 | if (memcmp(&ref1->key, &ref2->key, | 465 | if (!ref_for_same_block(ref1, ref2)) |
276 | sizeof(ref1->key)) || | ||
277 | ref1->level != ref2->level || | ||
278 | ref1->root_id != ref2->root_id) | ||
279 | continue; | 466 | continue; |
467 | if (!ref1->parent && ref2->parent) { | ||
468 | xchg = ref1; | ||
469 | ref1 = ref2; | ||
470 | ref2 = xchg; | ||
471 | } | ||
280 | ref1->count += ref2->count; | 472 | ref1->count += ref2->count; |
281 | } else { | 473 | } else { |
282 | if (ref1->parent != ref2->parent) | 474 | if (ref1->parent != ref2->parent) |
@@ -296,16 +488,17 @@ static int __merge_refs(struct list_head *head, int mode) | |||
296 | * smaller or equal that seq to the list | 488 | * smaller or equal that seq to the list |
297 | */ | 489 | */ |
298 | static int __add_delayed_refs(struct btrfs_delayed_ref_head *head, u64 seq, | 490 | static int __add_delayed_refs(struct btrfs_delayed_ref_head *head, u64 seq, |
299 | struct btrfs_key *info_key, | ||
300 | struct list_head *prefs) | 491 | struct list_head *prefs) |
301 | { | 492 | { |
302 | struct btrfs_delayed_extent_op *extent_op = head->extent_op; | 493 | struct btrfs_delayed_extent_op *extent_op = head->extent_op; |
303 | struct rb_node *n = &head->node.rb_node; | 494 | struct rb_node *n = &head->node.rb_node; |
495 | struct btrfs_key key; | ||
496 | struct btrfs_key op_key = {0}; | ||
304 | int sgn; | 497 | int sgn; |
305 | int ret = 0; | 498 | int ret = 0; |
306 | 499 | ||
307 | if (extent_op && extent_op->update_key) | 500 | if (extent_op && extent_op->update_key) |
308 | btrfs_disk_key_to_cpu(info_key, &extent_op->key); | 501 | btrfs_disk_key_to_cpu(&op_key, &extent_op->key); |
309 | 502 | ||
310 | while ((n = rb_prev(n))) { | 503 | while ((n = rb_prev(n))) { |
311 | struct btrfs_delayed_ref_node *node; | 504 | struct btrfs_delayed_ref_node *node; |
@@ -337,7 +530,7 @@ static int __add_delayed_refs(struct btrfs_delayed_ref_head *head, u64 seq, | |||
337 | struct btrfs_delayed_tree_ref *ref; | 530 | struct btrfs_delayed_tree_ref *ref; |
338 | 531 | ||
339 | ref = btrfs_delayed_node_to_tree_ref(node); | 532 | ref = btrfs_delayed_node_to_tree_ref(node); |
340 | ret = __add_prelim_ref(prefs, ref->root, info_key, | 533 | ret = __add_prelim_ref(prefs, ref->root, &op_key, |
341 | ref->level + 1, 0, node->bytenr, | 534 | ref->level + 1, 0, node->bytenr, |
342 | node->ref_mod * sgn); | 535 | node->ref_mod * sgn); |
343 | break; | 536 | break; |
@@ -346,7 +539,7 @@ static int __add_delayed_refs(struct btrfs_delayed_ref_head *head, u64 seq, | |||
346 | struct btrfs_delayed_tree_ref *ref; | 539 | struct btrfs_delayed_tree_ref *ref; |
347 | 540 | ||
348 | ref = btrfs_delayed_node_to_tree_ref(node); | 541 | ref = btrfs_delayed_node_to_tree_ref(node); |
349 | ret = __add_prelim_ref(prefs, ref->root, info_key, | 542 | ret = __add_prelim_ref(prefs, ref->root, NULL, |
350 | ref->level + 1, ref->parent, | 543 | ref->level + 1, ref->parent, |
351 | node->bytenr, | 544 | node->bytenr, |
352 | node->ref_mod * sgn); | 545 | node->ref_mod * sgn); |
@@ -354,8 +547,6 @@ static int __add_delayed_refs(struct btrfs_delayed_ref_head *head, u64 seq, | |||
354 | } | 547 | } |
355 | case BTRFS_EXTENT_DATA_REF_KEY: { | 548 | case BTRFS_EXTENT_DATA_REF_KEY: { |
356 | struct btrfs_delayed_data_ref *ref; | 549 | struct btrfs_delayed_data_ref *ref; |
357 | struct btrfs_key key; | ||
358 | |||
359 | ref = btrfs_delayed_node_to_data_ref(node); | 550 | ref = btrfs_delayed_node_to_data_ref(node); |
360 | 551 | ||
361 | key.objectid = ref->objectid; | 552 | key.objectid = ref->objectid; |
@@ -368,7 +559,6 @@ static int __add_delayed_refs(struct btrfs_delayed_ref_head *head, u64 seq, | |||
368 | } | 559 | } |
369 | case BTRFS_SHARED_DATA_REF_KEY: { | 560 | case BTRFS_SHARED_DATA_REF_KEY: { |
370 | struct btrfs_delayed_data_ref *ref; | 561 | struct btrfs_delayed_data_ref *ref; |
371 | struct btrfs_key key; | ||
372 | 562 | ||
373 | ref = btrfs_delayed_node_to_data_ref(node); | 563 | ref = btrfs_delayed_node_to_data_ref(node); |
374 | 564 | ||
@@ -394,8 +584,7 @@ static int __add_delayed_refs(struct btrfs_delayed_ref_head *head, u64 seq, | |||
394 | */ | 584 | */ |
395 | static int __add_inline_refs(struct btrfs_fs_info *fs_info, | 585 | static int __add_inline_refs(struct btrfs_fs_info *fs_info, |
396 | struct btrfs_path *path, u64 bytenr, | 586 | struct btrfs_path *path, u64 bytenr, |
397 | struct btrfs_key *info_key, int *info_level, | 587 | int *info_level, struct list_head *prefs) |
398 | struct list_head *prefs) | ||
399 | { | 588 | { |
400 | int ret = 0; | 589 | int ret = 0; |
401 | int slot; | 590 | int slot; |
@@ -411,7 +600,7 @@ static int __add_inline_refs(struct btrfs_fs_info *fs_info, | |||
411 | * enumerate all inline refs | 600 | * enumerate all inline refs |
412 | */ | 601 | */ |
413 | leaf = path->nodes[0]; | 602 | leaf = path->nodes[0]; |
414 | slot = path->slots[0] - 1; | 603 | slot = path->slots[0]; |
415 | 604 | ||
416 | item_size = btrfs_item_size_nr(leaf, slot); | 605 | item_size = btrfs_item_size_nr(leaf, slot); |
417 | BUG_ON(item_size < sizeof(*ei)); | 606 | BUG_ON(item_size < sizeof(*ei)); |
@@ -424,12 +613,9 @@ static int __add_inline_refs(struct btrfs_fs_info *fs_info, | |||
424 | 613 | ||
425 | if (flags & BTRFS_EXTENT_FLAG_TREE_BLOCK) { | 614 | if (flags & BTRFS_EXTENT_FLAG_TREE_BLOCK) { |
426 | struct btrfs_tree_block_info *info; | 615 | struct btrfs_tree_block_info *info; |
427 | struct btrfs_disk_key disk_key; | ||
428 | 616 | ||
429 | info = (struct btrfs_tree_block_info *)ptr; | 617 | info = (struct btrfs_tree_block_info *)ptr; |
430 | *info_level = btrfs_tree_block_level(leaf, info); | 618 | *info_level = btrfs_tree_block_level(leaf, info); |
431 | btrfs_tree_block_key(leaf, info, &disk_key); | ||
432 | btrfs_disk_key_to_cpu(info_key, &disk_key); | ||
433 | ptr += sizeof(struct btrfs_tree_block_info); | 619 | ptr += sizeof(struct btrfs_tree_block_info); |
434 | BUG_ON(ptr > end); | 620 | BUG_ON(ptr > end); |
435 | } else { | 621 | } else { |
@@ -447,7 +633,7 @@ static int __add_inline_refs(struct btrfs_fs_info *fs_info, | |||
447 | 633 | ||
448 | switch (type) { | 634 | switch (type) { |
449 | case BTRFS_SHARED_BLOCK_REF_KEY: | 635 | case BTRFS_SHARED_BLOCK_REF_KEY: |
450 | ret = __add_prelim_ref(prefs, 0, info_key, | 636 | ret = __add_prelim_ref(prefs, 0, NULL, |
451 | *info_level + 1, offset, | 637 | *info_level + 1, offset, |
452 | bytenr, 1); | 638 | bytenr, 1); |
453 | break; | 639 | break; |
@@ -462,8 +648,9 @@ static int __add_inline_refs(struct btrfs_fs_info *fs_info, | |||
462 | break; | 648 | break; |
463 | } | 649 | } |
464 | case BTRFS_TREE_BLOCK_REF_KEY: | 650 | case BTRFS_TREE_BLOCK_REF_KEY: |
465 | ret = __add_prelim_ref(prefs, offset, info_key, | 651 | ret = __add_prelim_ref(prefs, offset, NULL, |
466 | *info_level + 1, 0, bytenr, 1); | 652 | *info_level + 1, 0, |
653 | bytenr, 1); | ||
467 | break; | 654 | break; |
468 | case BTRFS_EXTENT_DATA_REF_KEY: { | 655 | case BTRFS_EXTENT_DATA_REF_KEY: { |
469 | struct btrfs_extent_data_ref *dref; | 656 | struct btrfs_extent_data_ref *dref; |
@@ -477,8 +664,8 @@ static int __add_inline_refs(struct btrfs_fs_info *fs_info, | |||
477 | key.type = BTRFS_EXTENT_DATA_KEY; | 664 | key.type = BTRFS_EXTENT_DATA_KEY; |
478 | key.offset = btrfs_extent_data_ref_offset(leaf, dref); | 665 | key.offset = btrfs_extent_data_ref_offset(leaf, dref); |
479 | root = btrfs_extent_data_ref_root(leaf, dref); | 666 | root = btrfs_extent_data_ref_root(leaf, dref); |
480 | ret = __add_prelim_ref(prefs, root, &key, 0, 0, bytenr, | 667 | ret = __add_prelim_ref(prefs, root, &key, 0, 0, |
481 | count); | 668 | bytenr, count); |
482 | break; | 669 | break; |
483 | } | 670 | } |
484 | default: | 671 | default: |
@@ -496,8 +683,7 @@ static int __add_inline_refs(struct btrfs_fs_info *fs_info, | |||
496 | */ | 683 | */ |
497 | static int __add_keyed_refs(struct btrfs_fs_info *fs_info, | 684 | static int __add_keyed_refs(struct btrfs_fs_info *fs_info, |
498 | struct btrfs_path *path, u64 bytenr, | 685 | struct btrfs_path *path, u64 bytenr, |
499 | struct btrfs_key *info_key, int info_level, | 686 | int info_level, struct list_head *prefs) |
500 | struct list_head *prefs) | ||
501 | { | 687 | { |
502 | struct btrfs_root *extent_root = fs_info->extent_root; | 688 | struct btrfs_root *extent_root = fs_info->extent_root; |
503 | int ret; | 689 | int ret; |
@@ -527,7 +713,7 @@ static int __add_keyed_refs(struct btrfs_fs_info *fs_info, | |||
527 | 713 | ||
528 | switch (key.type) { | 714 | switch (key.type) { |
529 | case BTRFS_SHARED_BLOCK_REF_KEY: | 715 | case BTRFS_SHARED_BLOCK_REF_KEY: |
530 | ret = __add_prelim_ref(prefs, 0, info_key, | 716 | ret = __add_prelim_ref(prefs, 0, NULL, |
531 | info_level + 1, key.offset, | 717 | info_level + 1, key.offset, |
532 | bytenr, 1); | 718 | bytenr, 1); |
533 | break; | 719 | break; |
@@ -543,8 +729,9 @@ static int __add_keyed_refs(struct btrfs_fs_info *fs_info, | |||
543 | break; | 729 | break; |
544 | } | 730 | } |
545 | case BTRFS_TREE_BLOCK_REF_KEY: | 731 | case BTRFS_TREE_BLOCK_REF_KEY: |
546 | ret = __add_prelim_ref(prefs, key.offset, info_key, | 732 | ret = __add_prelim_ref(prefs, key.offset, NULL, |
547 | info_level + 1, 0, bytenr, 1); | 733 | info_level + 1, 0, |
734 | bytenr, 1); | ||
548 | break; | 735 | break; |
549 | case BTRFS_EXTENT_DATA_REF_KEY: { | 736 | case BTRFS_EXTENT_DATA_REF_KEY: { |
550 | struct btrfs_extent_data_ref *dref; | 737 | struct btrfs_extent_data_ref *dref; |
@@ -560,7 +747,7 @@ static int __add_keyed_refs(struct btrfs_fs_info *fs_info, | |||
560 | key.offset = btrfs_extent_data_ref_offset(leaf, dref); | 747 | key.offset = btrfs_extent_data_ref_offset(leaf, dref); |
561 | root = btrfs_extent_data_ref_root(leaf, dref); | 748 | root = btrfs_extent_data_ref_root(leaf, dref); |
562 | ret = __add_prelim_ref(prefs, root, &key, 0, 0, | 749 | ret = __add_prelim_ref(prefs, root, &key, 0, 0, |
563 | bytenr, count); | 750 | bytenr, count); |
564 | break; | 751 | break; |
565 | } | 752 | } |
566 | default: | 753 | default: |
@@ -582,11 +769,12 @@ static int __add_keyed_refs(struct btrfs_fs_info *fs_info, | |||
582 | */ | 769 | */ |
583 | static int find_parent_nodes(struct btrfs_trans_handle *trans, | 770 | static int find_parent_nodes(struct btrfs_trans_handle *trans, |
584 | struct btrfs_fs_info *fs_info, u64 bytenr, | 771 | struct btrfs_fs_info *fs_info, u64 bytenr, |
585 | u64 seq, struct ulist *refs, struct ulist *roots) | 772 | u64 delayed_ref_seq, u64 time_seq, |
773 | struct ulist *refs, struct ulist *roots, | ||
774 | const u64 *extent_item_pos) | ||
586 | { | 775 | { |
587 | struct btrfs_key key; | 776 | struct btrfs_key key; |
588 | struct btrfs_path *path; | 777 | struct btrfs_path *path; |
589 | struct btrfs_key info_key = { 0 }; | ||
590 | struct btrfs_delayed_ref_root *delayed_refs = NULL; | 778 | struct btrfs_delayed_ref_root *delayed_refs = NULL; |
591 | struct btrfs_delayed_ref_head *head; | 779 | struct btrfs_delayed_ref_head *head; |
592 | int info_level = 0; | 780 | int info_level = 0; |
@@ -645,7 +833,7 @@ again: | |||
645 | btrfs_put_delayed_ref(&head->node); | 833 | btrfs_put_delayed_ref(&head->node); |
646 | goto again; | 834 | goto again; |
647 | } | 835 | } |
648 | ret = __add_delayed_refs(head, seq, &info_key, | 836 | ret = __add_delayed_refs(head, delayed_ref_seq, |
649 | &prefs_delayed); | 837 | &prefs_delayed); |
650 | if (ret) { | 838 | if (ret) { |
651 | spin_unlock(&delayed_refs->lock); | 839 | spin_unlock(&delayed_refs->lock); |
@@ -659,16 +847,17 @@ again: | |||
659 | struct extent_buffer *leaf; | 847 | struct extent_buffer *leaf; |
660 | int slot; | 848 | int slot; |
661 | 849 | ||
850 | path->slots[0]--; | ||
662 | leaf = path->nodes[0]; | 851 | leaf = path->nodes[0]; |
663 | slot = path->slots[0] - 1; | 852 | slot = path->slots[0]; |
664 | btrfs_item_key_to_cpu(leaf, &key, slot); | 853 | btrfs_item_key_to_cpu(leaf, &key, slot); |
665 | if (key.objectid == bytenr && | 854 | if (key.objectid == bytenr && |
666 | key.type == BTRFS_EXTENT_ITEM_KEY) { | 855 | key.type == BTRFS_EXTENT_ITEM_KEY) { |
667 | ret = __add_inline_refs(fs_info, path, bytenr, | 856 | ret = __add_inline_refs(fs_info, path, bytenr, |
668 | &info_key, &info_level, &prefs); | 857 | &info_level, &prefs); |
669 | if (ret) | 858 | if (ret) |
670 | goto out; | 859 | goto out; |
671 | ret = __add_keyed_refs(fs_info, path, bytenr, &info_key, | 860 | ret = __add_keyed_refs(fs_info, path, bytenr, |
672 | info_level, &prefs); | 861 | info_level, &prefs); |
673 | if (ret) | 862 | if (ret) |
674 | goto out; | 863 | goto out; |
@@ -676,21 +865,18 @@ again: | |||
676 | } | 865 | } |
677 | btrfs_release_path(path); | 866 | btrfs_release_path(path); |
678 | 867 | ||
679 | /* | ||
680 | * when adding the delayed refs above, the info_key might not have | ||
681 | * been known yet. Go over the list and replace the missing keys | ||
682 | */ | ||
683 | list_for_each_entry(ref, &prefs_delayed, list) { | ||
684 | if ((ref->key.offset | ref->key.type | ref->key.objectid) == 0) | ||
685 | memcpy(&ref->key, &info_key, sizeof(ref->key)); | ||
686 | } | ||
687 | list_splice_init(&prefs_delayed, &prefs); | 868 | list_splice_init(&prefs_delayed, &prefs); |
688 | 869 | ||
870 | ret = __add_missing_keys(fs_info, &prefs); | ||
871 | if (ret) | ||
872 | goto out; | ||
873 | |||
689 | ret = __merge_refs(&prefs, 1); | 874 | ret = __merge_refs(&prefs, 1); |
690 | if (ret) | 875 | if (ret) |
691 | goto out; | 876 | goto out; |
692 | 877 | ||
693 | ret = __resolve_indirect_refs(fs_info, search_commit_root, &prefs); | 878 | ret = __resolve_indirect_refs(fs_info, search_commit_root, time_seq, |
879 | &prefs, extent_item_pos); | ||
694 | if (ret) | 880 | if (ret) |
695 | goto out; | 881 | goto out; |
696 | 882 | ||
@@ -709,7 +895,33 @@ again: | |||
709 | BUG_ON(ret < 0); | 895 | BUG_ON(ret < 0); |
710 | } | 896 | } |
711 | if (ref->count && ref->parent) { | 897 | if (ref->count && ref->parent) { |
712 | ret = ulist_add(refs, ref->parent, 0, GFP_NOFS); | 898 | struct extent_inode_elem *eie = NULL; |
899 | if (extent_item_pos && !ref->inode_list) { | ||
900 | u32 bsz; | ||
901 | struct extent_buffer *eb; | ||
902 | bsz = btrfs_level_size(fs_info->extent_root, | ||
903 | info_level); | ||
904 | eb = read_tree_block(fs_info->extent_root, | ||
905 | ref->parent, bsz, 0); | ||
906 | BUG_ON(!eb); | ||
907 | ret = find_extent_in_eb(eb, bytenr, | ||
908 | *extent_item_pos, &eie); | ||
909 | ref->inode_list = eie; | ||
910 | free_extent_buffer(eb); | ||
911 | } | ||
912 | ret = ulist_add_merge(refs, ref->parent, | ||
913 | (unsigned long)ref->inode_list, | ||
914 | (unsigned long *)&eie, GFP_NOFS); | ||
915 | if (!ret && extent_item_pos) { | ||
916 | /* | ||
917 | * we've recorded that parent, so we must extend | ||
918 | * its inode list here | ||
919 | */ | ||
920 | BUG_ON(!eie); | ||
921 | while (eie->next) | ||
922 | eie = eie->next; | ||
923 | eie->next = ref->inode_list; | ||
924 | } | ||
713 | BUG_ON(ret < 0); | 925 | BUG_ON(ret < 0); |
714 | } | 926 | } |
715 | kfree(ref); | 927 | kfree(ref); |
@@ -734,6 +946,28 @@ out: | |||
734 | return ret; | 946 | return ret; |
735 | } | 947 | } |
736 | 948 | ||
949 | static void free_leaf_list(struct ulist *blocks) | ||
950 | { | ||
951 | struct ulist_node *node = NULL; | ||
952 | struct extent_inode_elem *eie; | ||
953 | struct extent_inode_elem *eie_next; | ||
954 | struct ulist_iterator uiter; | ||
955 | |||
956 | ULIST_ITER_INIT(&uiter); | ||
957 | while ((node = ulist_next(blocks, &uiter))) { | ||
958 | if (!node->aux) | ||
959 | continue; | ||
960 | eie = (struct extent_inode_elem *)node->aux; | ||
961 | for (; eie; eie = eie_next) { | ||
962 | eie_next = eie->next; | ||
963 | kfree(eie); | ||
964 | } | ||
965 | node->aux = 0; | ||
966 | } | ||
967 | |||
968 | ulist_free(blocks); | ||
969 | } | ||
970 | |||
737 | /* | 971 | /* |
738 | * Finds all leafs with a reference to the specified combination of bytenr and | 972 | * Finds all leafs with a reference to the specified combination of bytenr and |
739 | * offset. key_list_head will point to a list of corresponding keys (caller must | 973 | * offset. key_list_head will point to a list of corresponding keys (caller must |
@@ -744,7 +978,9 @@ out: | |||
744 | */ | 978 | */ |
745 | static int btrfs_find_all_leafs(struct btrfs_trans_handle *trans, | 979 | static int btrfs_find_all_leafs(struct btrfs_trans_handle *trans, |
746 | struct btrfs_fs_info *fs_info, u64 bytenr, | 980 | struct btrfs_fs_info *fs_info, u64 bytenr, |
747 | u64 num_bytes, u64 seq, struct ulist **leafs) | 981 | u64 delayed_ref_seq, u64 time_seq, |
982 | struct ulist **leafs, | ||
983 | const u64 *extent_item_pos) | ||
748 | { | 984 | { |
749 | struct ulist *tmp; | 985 | struct ulist *tmp; |
750 | int ret; | 986 | int ret; |
@@ -758,11 +994,12 @@ static int btrfs_find_all_leafs(struct btrfs_trans_handle *trans, | |||
758 | return -ENOMEM; | 994 | return -ENOMEM; |
759 | } | 995 | } |
760 | 996 | ||
761 | ret = find_parent_nodes(trans, fs_info, bytenr, seq, *leafs, tmp); | 997 | ret = find_parent_nodes(trans, fs_info, bytenr, delayed_ref_seq, |
998 | time_seq, *leafs, tmp, extent_item_pos); | ||
762 | ulist_free(tmp); | 999 | ulist_free(tmp); |
763 | 1000 | ||
764 | if (ret < 0 && ret != -ENOENT) { | 1001 | if (ret < 0 && ret != -ENOENT) { |
765 | ulist_free(*leafs); | 1002 | free_leaf_list(*leafs); |
766 | return ret; | 1003 | return ret; |
767 | } | 1004 | } |
768 | 1005 | ||
@@ -784,10 +1021,12 @@ static int btrfs_find_all_leafs(struct btrfs_trans_handle *trans, | |||
784 | */ | 1021 | */ |
785 | int btrfs_find_all_roots(struct btrfs_trans_handle *trans, | 1022 | int btrfs_find_all_roots(struct btrfs_trans_handle *trans, |
786 | struct btrfs_fs_info *fs_info, u64 bytenr, | 1023 | struct btrfs_fs_info *fs_info, u64 bytenr, |
787 | u64 num_bytes, u64 seq, struct ulist **roots) | 1024 | u64 delayed_ref_seq, u64 time_seq, |
1025 | struct ulist **roots) | ||
788 | { | 1026 | { |
789 | struct ulist *tmp; | 1027 | struct ulist *tmp; |
790 | struct ulist_node *node = NULL; | 1028 | struct ulist_node *node = NULL; |
1029 | struct ulist_iterator uiter; | ||
791 | int ret; | 1030 | int ret; |
792 | 1031 | ||
793 | tmp = ulist_alloc(GFP_NOFS); | 1032 | tmp = ulist_alloc(GFP_NOFS); |
@@ -799,15 +1038,16 @@ int btrfs_find_all_roots(struct btrfs_trans_handle *trans, | |||
799 | return -ENOMEM; | 1038 | return -ENOMEM; |
800 | } | 1039 | } |
801 | 1040 | ||
1041 | ULIST_ITER_INIT(&uiter); | ||
802 | while (1) { | 1042 | while (1) { |
803 | ret = find_parent_nodes(trans, fs_info, bytenr, seq, | 1043 | ret = find_parent_nodes(trans, fs_info, bytenr, delayed_ref_seq, |
804 | tmp, *roots); | 1044 | time_seq, tmp, *roots, NULL); |
805 | if (ret < 0 && ret != -ENOENT) { | 1045 | if (ret < 0 && ret != -ENOENT) { |
806 | ulist_free(tmp); | 1046 | ulist_free(tmp); |
807 | ulist_free(*roots); | 1047 | ulist_free(*roots); |
808 | return ret; | 1048 | return ret; |
809 | } | 1049 | } |
810 | node = ulist_next(tmp, node); | 1050 | node = ulist_next(tmp, &uiter); |
811 | if (!node) | 1051 | if (!node) |
812 | break; | 1052 | break; |
813 | bytenr = node->val; | 1053 | bytenr = node->val; |
@@ -1093,67 +1333,25 @@ int tree_backref_for_extent(unsigned long *ptr, struct extent_buffer *eb, | |||
1093 | return 0; | 1333 | return 0; |
1094 | } | 1334 | } |
1095 | 1335 | ||
1096 | static int iterate_leaf_refs(struct btrfs_fs_info *fs_info, u64 logical, | 1336 | static int iterate_leaf_refs(struct extent_inode_elem *inode_list, |
1097 | u64 orig_extent_item_objectid, | 1337 | u64 root, u64 extent_item_objectid, |
1098 | u64 extent_item_pos, u64 root, | ||
1099 | iterate_extent_inodes_t *iterate, void *ctx) | 1338 | iterate_extent_inodes_t *iterate, void *ctx) |
1100 | { | 1339 | { |
1101 | u64 disk_byte; | 1340 | struct extent_inode_elem *eie; |
1102 | struct btrfs_key key; | ||
1103 | struct btrfs_file_extent_item *fi; | ||
1104 | struct extent_buffer *eb; | ||
1105 | int slot; | ||
1106 | int nritems; | ||
1107 | int ret = 0; | 1341 | int ret = 0; |
1108 | int extent_type; | ||
1109 | u64 data_offset; | ||
1110 | u64 data_len; | ||
1111 | |||
1112 | eb = read_tree_block(fs_info->tree_root, logical, | ||
1113 | fs_info->tree_root->leafsize, 0); | ||
1114 | if (!eb) | ||
1115 | return -EIO; | ||
1116 | |||
1117 | /* | ||
1118 | * from the shared data ref, we only have the leaf but we need | ||
1119 | * the key. thus, we must look into all items and see that we | ||
1120 | * find one (some) with a reference to our extent item. | ||
1121 | */ | ||
1122 | nritems = btrfs_header_nritems(eb); | ||
1123 | for (slot = 0; slot < nritems; ++slot) { | ||
1124 | btrfs_item_key_to_cpu(eb, &key, slot); | ||
1125 | if (key.type != BTRFS_EXTENT_DATA_KEY) | ||
1126 | continue; | ||
1127 | fi = btrfs_item_ptr(eb, slot, struct btrfs_file_extent_item); | ||
1128 | extent_type = btrfs_file_extent_type(eb, fi); | ||
1129 | if (extent_type == BTRFS_FILE_EXTENT_INLINE) | ||
1130 | continue; | ||
1131 | /* don't skip BTRFS_FILE_EXTENT_PREALLOC, we can handle that */ | ||
1132 | disk_byte = btrfs_file_extent_disk_bytenr(eb, fi); | ||
1133 | if (disk_byte != orig_extent_item_objectid) | ||
1134 | continue; | ||
1135 | |||
1136 | data_offset = btrfs_file_extent_offset(eb, fi); | ||
1137 | data_len = btrfs_file_extent_num_bytes(eb, fi); | ||
1138 | |||
1139 | if (extent_item_pos < data_offset || | ||
1140 | extent_item_pos >= data_offset + data_len) | ||
1141 | continue; | ||
1142 | 1342 | ||
1343 | for (eie = inode_list; eie; eie = eie->next) { | ||
1143 | pr_debug("ref for %llu resolved, key (%llu EXTEND_DATA %llu), " | 1344 | pr_debug("ref for %llu resolved, key (%llu EXTEND_DATA %llu), " |
1144 | "root %llu\n", orig_extent_item_objectid, | 1345 | "root %llu\n", extent_item_objectid, |
1145 | key.objectid, key.offset, root); | 1346 | eie->inum, eie->offset, root); |
1146 | ret = iterate(key.objectid, | 1347 | ret = iterate(eie->inum, eie->offset, root, ctx); |
1147 | key.offset + (extent_item_pos - data_offset), | ||
1148 | root, ctx); | ||
1149 | if (ret) { | 1348 | if (ret) { |
1150 | pr_debug("stopping iteration because ret=%d\n", ret); | 1349 | pr_debug("stopping iteration for %llu due to ret=%d\n", |
1350 | extent_item_objectid, ret); | ||
1151 | break; | 1351 | break; |
1152 | } | 1352 | } |
1153 | } | 1353 | } |
1154 | 1354 | ||
1155 | free_extent_buffer(eb); | ||
1156 | |||
1157 | return ret; | 1355 | return ret; |
1158 | } | 1356 | } |
1159 | 1357 | ||
@@ -1175,7 +1373,10 @@ int iterate_extent_inodes(struct btrfs_fs_info *fs_info, | |||
1175 | struct ulist *roots = NULL; | 1373 | struct ulist *roots = NULL; |
1176 | struct ulist_node *ref_node = NULL; | 1374 | struct ulist_node *ref_node = NULL; |
1177 | struct ulist_node *root_node = NULL; | 1375 | struct ulist_node *root_node = NULL; |
1178 | struct seq_list seq_elem; | 1376 | struct seq_list seq_elem = {}; |
1377 | struct seq_list tree_mod_seq_elem = {}; | ||
1378 | struct ulist_iterator ref_uiter; | ||
1379 | struct ulist_iterator root_uiter; | ||
1179 | struct btrfs_delayed_ref_root *delayed_refs = NULL; | 1380 | struct btrfs_delayed_ref_root *delayed_refs = NULL; |
1180 | 1381 | ||
1181 | pr_debug("resolving all inodes for extent %llu\n", | 1382 | pr_debug("resolving all inodes for extent %llu\n", |
@@ -1192,34 +1393,41 @@ int iterate_extent_inodes(struct btrfs_fs_info *fs_info, | |||
1192 | spin_lock(&delayed_refs->lock); | 1393 | spin_lock(&delayed_refs->lock); |
1193 | btrfs_get_delayed_seq(delayed_refs, &seq_elem); | 1394 | btrfs_get_delayed_seq(delayed_refs, &seq_elem); |
1194 | spin_unlock(&delayed_refs->lock); | 1395 | spin_unlock(&delayed_refs->lock); |
1396 | btrfs_get_tree_mod_seq(fs_info, &tree_mod_seq_elem); | ||
1195 | } | 1397 | } |
1196 | 1398 | ||
1197 | ret = btrfs_find_all_leafs(trans, fs_info, extent_item_objectid, | 1399 | ret = btrfs_find_all_leafs(trans, fs_info, extent_item_objectid, |
1198 | extent_item_pos, seq_elem.seq, | 1400 | seq_elem.seq, tree_mod_seq_elem.seq, &refs, |
1199 | &refs); | 1401 | &extent_item_pos); |
1200 | |||
1201 | if (ret) | 1402 | if (ret) |
1202 | goto out; | 1403 | goto out; |
1203 | 1404 | ||
1204 | while (!ret && (ref_node = ulist_next(refs, ref_node))) { | 1405 | ULIST_ITER_INIT(&ref_uiter); |
1205 | ret = btrfs_find_all_roots(trans, fs_info, ref_node->val, -1, | 1406 | while (!ret && (ref_node = ulist_next(refs, &ref_uiter))) { |
1206 | seq_elem.seq, &roots); | 1407 | ret = btrfs_find_all_roots(trans, fs_info, ref_node->val, |
1408 | seq_elem.seq, | ||
1409 | tree_mod_seq_elem.seq, &roots); | ||
1207 | if (ret) | 1410 | if (ret) |
1208 | break; | 1411 | break; |
1209 | while (!ret && (root_node = ulist_next(roots, root_node))) { | 1412 | ULIST_ITER_INIT(&root_uiter); |
1210 | pr_debug("root %llu references leaf %llu\n", | 1413 | while (!ret && (root_node = ulist_next(roots, &root_uiter))) { |
1211 | root_node->val, ref_node->val); | 1414 | pr_debug("root %llu references leaf %llu, data list " |
1212 | ret = iterate_leaf_refs(fs_info, ref_node->val, | 1415 | "%#lx\n", root_node->val, ref_node->val, |
1213 | extent_item_objectid, | 1416 | ref_node->aux); |
1214 | extent_item_pos, root_node->val, | 1417 | ret = iterate_leaf_refs( |
1215 | iterate, ctx); | 1418 | (struct extent_inode_elem *)ref_node->aux, |
1419 | root_node->val, extent_item_objectid, | ||
1420 | iterate, ctx); | ||
1216 | } | 1421 | } |
1422 | ulist_free(roots); | ||
1423 | roots = NULL; | ||
1217 | } | 1424 | } |
1218 | 1425 | ||
1219 | ulist_free(refs); | 1426 | free_leaf_list(refs); |
1220 | ulist_free(roots); | 1427 | ulist_free(roots); |
1221 | out: | 1428 | out: |
1222 | if (!search_commit_root) { | 1429 | if (!search_commit_root) { |
1430 | btrfs_put_tree_mod_seq(fs_info, &tree_mod_seq_elem); | ||
1223 | btrfs_put_delayed_seq(delayed_refs, &seq_elem); | 1431 | btrfs_put_delayed_seq(delayed_refs, &seq_elem); |
1224 | btrfs_end_transaction(trans, fs_info->extent_root); | 1432 | btrfs_end_transaction(trans, fs_info->extent_root); |
1225 | } | 1433 | } |