aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/backref.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/backref.c')
-rw-r--r--fs/btrfs/backref.c120
1 files changed, 70 insertions, 50 deletions
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
index 290e347b6db3..8bc5e8ccb091 100644
--- a/fs/btrfs/backref.c
+++ b/fs/btrfs/backref.c
@@ -36,16 +36,23 @@ static int check_extent_in_eb(struct btrfs_key *key, struct extent_buffer *eb,
36 u64 extent_item_pos, 36 u64 extent_item_pos,
37 struct extent_inode_elem **eie) 37 struct extent_inode_elem **eie)
38{ 38{
39 u64 data_offset; 39 u64 offset = 0;
40 u64 data_len;
41 struct extent_inode_elem *e; 40 struct extent_inode_elem *e;
42 41
43 data_offset = btrfs_file_extent_offset(eb, fi); 42 if (!btrfs_file_extent_compression(eb, fi) &&
44 data_len = btrfs_file_extent_num_bytes(eb, fi); 43 !btrfs_file_extent_encryption(eb, fi) &&
44 !btrfs_file_extent_other_encoding(eb, fi)) {
45 u64 data_offset;
46 u64 data_len;
45 47
46 if (extent_item_pos < data_offset || 48 data_offset = btrfs_file_extent_offset(eb, fi);
47 extent_item_pos >= data_offset + data_len) 49 data_len = btrfs_file_extent_num_bytes(eb, fi);
48 return 1; 50
51 if (extent_item_pos < data_offset ||
52 extent_item_pos >= data_offset + data_len)
53 return 1;
54 offset = extent_item_pos - data_offset;
55 }
49 56
50 e = kmalloc(sizeof(*e), GFP_NOFS); 57 e = kmalloc(sizeof(*e), GFP_NOFS);
51 if (!e) 58 if (!e)
@@ -53,7 +60,7 @@ static int check_extent_in_eb(struct btrfs_key *key, struct extent_buffer *eb,
53 60
54 e->next = *eie; 61 e->next = *eie;
55 e->inum = key->objectid; 62 e->inum = key->objectid;
56 e->offset = key->offset + (extent_item_pos - data_offset); 63 e->offset = key->offset + offset;
57 *eie = e; 64 *eie = e;
58 65
59 return 0; 66 return 0;
@@ -189,7 +196,7 @@ static int add_all_parents(struct btrfs_root *root, struct btrfs_path *path,
189 struct extent_buffer *eb; 196 struct extent_buffer *eb;
190 struct btrfs_key key; 197 struct btrfs_key key;
191 struct btrfs_file_extent_item *fi; 198 struct btrfs_file_extent_item *fi;
192 struct extent_inode_elem *eie = NULL; 199 struct extent_inode_elem *eie = NULL, *old = NULL;
193 u64 disk_byte; 200 u64 disk_byte;
194 201
195 if (level != 0) { 202 if (level != 0) {
@@ -223,6 +230,7 @@ static int add_all_parents(struct btrfs_root *root, struct btrfs_path *path,
223 230
224 if (disk_byte == wanted_disk_byte) { 231 if (disk_byte == wanted_disk_byte) {
225 eie = NULL; 232 eie = NULL;
233 old = NULL;
226 if (extent_item_pos) { 234 if (extent_item_pos) {
227 ret = check_extent_in_eb(&key, eb, fi, 235 ret = check_extent_in_eb(&key, eb, fi,
228 *extent_item_pos, 236 *extent_item_pos,
@@ -230,18 +238,20 @@ static int add_all_parents(struct btrfs_root *root, struct btrfs_path *path,
230 if (ret < 0) 238 if (ret < 0)
231 break; 239 break;
232 } 240 }
233 if (!ret) { 241 if (ret > 0)
234 ret = ulist_add(parents, eb->start, 242 goto next;
235 (uintptr_t)eie, GFP_NOFS); 243 ret = ulist_add_merge(parents, eb->start,
236 if (ret < 0) 244 (uintptr_t)eie,
237 break; 245 (u64 *)&old, GFP_NOFS);
238 if (!extent_item_pos) { 246 if (ret < 0)
239 ret = btrfs_next_old_leaf(root, path, 247 break;
240 time_seq); 248 if (!ret && extent_item_pos) {
241 continue; 249 while (old->next)
242 } 250 old = old->next;
251 old->next = eie;
243 } 252 }
244 } 253 }
254next:
245 ret = btrfs_next_old_item(root, path, time_seq); 255 ret = btrfs_next_old_item(root, path, time_seq);
246 } 256 }
247 257
@@ -255,13 +265,11 @@ static int add_all_parents(struct btrfs_root *root, struct btrfs_path *path,
255 * to a logical address 265 * to a logical address
256 */ 266 */
257static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info, 267static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info,
258 int search_commit_root, 268 struct btrfs_path *path, u64 time_seq,
259 u64 time_seq, 269 struct __prelim_ref *ref,
260 struct __prelim_ref *ref, 270 struct ulist *parents,
261 struct ulist *parents, 271 const u64 *extent_item_pos)
262 const u64 *extent_item_pos)
263{ 272{
264 struct btrfs_path *path;
265 struct btrfs_root *root; 273 struct btrfs_root *root;
266 struct btrfs_key root_key; 274 struct btrfs_key root_key;
267 struct extent_buffer *eb; 275 struct extent_buffer *eb;
@@ -269,11 +277,6 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info,
269 int root_level; 277 int root_level;
270 int level = ref->level; 278 int level = ref->level;
271 279
272 path = btrfs_alloc_path();
273 if (!path)
274 return -ENOMEM;
275 path->search_commit_root = !!search_commit_root;
276
277 root_key.objectid = ref->root_id; 280 root_key.objectid = ref->root_id;
278 root_key.type = BTRFS_ROOT_ITEM_KEY; 281 root_key.type = BTRFS_ROOT_ITEM_KEY;
279 root_key.offset = (u64)-1; 282 root_key.offset = (u64)-1;
@@ -314,7 +317,8 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info,
314 time_seq, ref->wanted_disk_byte, 317 time_seq, ref->wanted_disk_byte,
315 extent_item_pos); 318 extent_item_pos);
316out: 319out:
317 btrfs_free_path(path); 320 path->lowest_level = 0;
321 btrfs_release_path(path);
318 return ret; 322 return ret;
319} 323}
320 324
@@ -322,7 +326,7 @@ out:
322 * resolve all indirect backrefs from the list 326 * resolve all indirect backrefs from the list
323 */ 327 */
324static int __resolve_indirect_refs(struct btrfs_fs_info *fs_info, 328static int __resolve_indirect_refs(struct btrfs_fs_info *fs_info,
325 int search_commit_root, u64 time_seq, 329 struct btrfs_path *path, u64 time_seq,
326 struct list_head *head, 330 struct list_head *head,
327 const u64 *extent_item_pos) 331 const u64 *extent_item_pos)
328{ 332{
@@ -349,9 +353,8 @@ static int __resolve_indirect_refs(struct btrfs_fs_info *fs_info,
349 continue; 353 continue;
350 if (ref->count == 0) 354 if (ref->count == 0)
351 continue; 355 continue;
352 err = __resolve_indirect_ref(fs_info, search_commit_root, 356 err = __resolve_indirect_ref(fs_info, path, time_seq, ref,
353 time_seq, ref, parents, 357 parents, extent_item_pos);
354 extent_item_pos);
355 if (err == -ENOMEM) 358 if (err == -ENOMEM)
356 goto out; 359 goto out;
357 if (err) 360 if (err)
@@ -604,6 +607,7 @@ static int __add_inline_refs(struct btrfs_fs_info *fs_info,
604 int slot; 607 int slot;
605 struct extent_buffer *leaf; 608 struct extent_buffer *leaf;
606 struct btrfs_key key; 609 struct btrfs_key key;
610 struct btrfs_key found_key;
607 unsigned long ptr; 611 unsigned long ptr;
608 unsigned long end; 612 unsigned long end;
609 struct btrfs_extent_item *ei; 613 struct btrfs_extent_item *ei;
@@ -621,17 +625,21 @@ static int __add_inline_refs(struct btrfs_fs_info *fs_info,
621 625
622 ei = btrfs_item_ptr(leaf, slot, struct btrfs_extent_item); 626 ei = btrfs_item_ptr(leaf, slot, struct btrfs_extent_item);
623 flags = btrfs_extent_flags(leaf, ei); 627 flags = btrfs_extent_flags(leaf, ei);
628 btrfs_item_key_to_cpu(leaf, &found_key, slot);
624 629
625 ptr = (unsigned long)(ei + 1); 630 ptr = (unsigned long)(ei + 1);
626 end = (unsigned long)ei + item_size; 631 end = (unsigned long)ei + item_size;
627 632
628 if (flags & BTRFS_EXTENT_FLAG_TREE_BLOCK) { 633 if (found_key.type == BTRFS_EXTENT_ITEM_KEY &&
634 flags & BTRFS_EXTENT_FLAG_TREE_BLOCK) {
629 struct btrfs_tree_block_info *info; 635 struct btrfs_tree_block_info *info;
630 636
631 info = (struct btrfs_tree_block_info *)ptr; 637 info = (struct btrfs_tree_block_info *)ptr;
632 *info_level = btrfs_tree_block_level(leaf, info); 638 *info_level = btrfs_tree_block_level(leaf, info);
633 ptr += sizeof(struct btrfs_tree_block_info); 639 ptr += sizeof(struct btrfs_tree_block_info);
634 BUG_ON(ptr > end); 640 BUG_ON(ptr > end);
641 } else if (found_key.type == BTRFS_METADATA_ITEM_KEY) {
642 *info_level = found_key.offset;
635 } else { 643 } else {
636 BUG_ON(!(flags & BTRFS_EXTENT_FLAG_DATA)); 644 BUG_ON(!(flags & BTRFS_EXTENT_FLAG_DATA));
637 } 645 }
@@ -795,7 +803,6 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans,
795 struct btrfs_delayed_ref_head *head; 803 struct btrfs_delayed_ref_head *head;
796 int info_level = 0; 804 int info_level = 0;
797 int ret; 805 int ret;
798 int search_commit_root = (trans == BTRFS_BACKREF_SEARCH_COMMIT_ROOT);
799 struct list_head prefs_delayed; 806 struct list_head prefs_delayed;
800 struct list_head prefs; 807 struct list_head prefs;
801 struct __prelim_ref *ref; 808 struct __prelim_ref *ref;
@@ -804,13 +811,17 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans,
804 INIT_LIST_HEAD(&prefs_delayed); 811 INIT_LIST_HEAD(&prefs_delayed);
805 812
806 key.objectid = bytenr; 813 key.objectid = bytenr;
807 key.type = BTRFS_EXTENT_ITEM_KEY;
808 key.offset = (u64)-1; 814 key.offset = (u64)-1;
815 if (btrfs_fs_incompat(fs_info, SKINNY_METADATA))
816 key.type = BTRFS_METADATA_ITEM_KEY;
817 else
818 key.type = BTRFS_EXTENT_ITEM_KEY;
809 819
810 path = btrfs_alloc_path(); 820 path = btrfs_alloc_path();
811 if (!path) 821 if (!path)
812 return -ENOMEM; 822 return -ENOMEM;
813 path->search_commit_root = !!search_commit_root; 823 if (!trans)
824 path->search_commit_root = 1;
814 825
815 /* 826 /*
816 * grab both a lock on the path and a lock on the delayed ref head. 827 * grab both a lock on the path and a lock on the delayed ref head.
@@ -825,7 +836,7 @@ again:
825 goto out; 836 goto out;
826 BUG_ON(ret == 0); 837 BUG_ON(ret == 0);
827 838
828 if (trans != BTRFS_BACKREF_SEARCH_COMMIT_ROOT) { 839 if (trans) {
829 /* 840 /*
830 * look if there are updates for this ref queued and lock the 841 * look if there are updates for this ref queued and lock the
831 * head 842 * head
@@ -869,7 +880,8 @@ again:
869 slot = path->slots[0]; 880 slot = path->slots[0];
870 btrfs_item_key_to_cpu(leaf, &key, slot); 881 btrfs_item_key_to_cpu(leaf, &key, slot);
871 if (key.objectid == bytenr && 882 if (key.objectid == bytenr &&
872 key.type == BTRFS_EXTENT_ITEM_KEY) { 883 (key.type == BTRFS_EXTENT_ITEM_KEY ||
884 key.type == BTRFS_METADATA_ITEM_KEY)) {
873 ret = __add_inline_refs(fs_info, path, bytenr, 885 ret = __add_inline_refs(fs_info, path, bytenr,
874 &info_level, &prefs); 886 &info_level, &prefs);
875 if (ret) 887 if (ret)
@@ -890,8 +902,8 @@ again:
890 902
891 __merge_refs(&prefs, 1); 903 __merge_refs(&prefs, 1);
892 904
893 ret = __resolve_indirect_refs(fs_info, search_commit_root, time_seq, 905 ret = __resolve_indirect_refs(fs_info, path, time_seq, &prefs,
894 &prefs, extent_item_pos); 906 extent_item_pos);
895 if (ret) 907 if (ret)
896 goto out; 908 goto out;
897 909
@@ -1283,12 +1295,16 @@ int extent_from_logical(struct btrfs_fs_info *fs_info, u64 logical,
1283{ 1295{
1284 int ret; 1296 int ret;
1285 u64 flags; 1297 u64 flags;
1298 u64 size = 0;
1286 u32 item_size; 1299 u32 item_size;
1287 struct extent_buffer *eb; 1300 struct extent_buffer *eb;
1288 struct btrfs_extent_item *ei; 1301 struct btrfs_extent_item *ei;
1289 struct btrfs_key key; 1302 struct btrfs_key key;
1290 1303
1291 key.type = BTRFS_EXTENT_ITEM_KEY; 1304 if (btrfs_fs_incompat(fs_info, SKINNY_METADATA))
1305 key.type = BTRFS_METADATA_ITEM_KEY;
1306 else
1307 key.type = BTRFS_EXTENT_ITEM_KEY;
1292 key.objectid = logical; 1308 key.objectid = logical;
1293 key.offset = (u64)-1; 1309 key.offset = (u64)-1;
1294 1310
@@ -1301,9 +1317,15 @@ int extent_from_logical(struct btrfs_fs_info *fs_info, u64 logical,
1301 return ret; 1317 return ret;
1302 1318
1303 btrfs_item_key_to_cpu(path->nodes[0], found_key, path->slots[0]); 1319 btrfs_item_key_to_cpu(path->nodes[0], found_key, path->slots[0]);
1304 if (found_key->type != BTRFS_EXTENT_ITEM_KEY || 1320 if (found_key->type == BTRFS_METADATA_ITEM_KEY)
1321 size = fs_info->extent_root->leafsize;
1322 else if (found_key->type == BTRFS_EXTENT_ITEM_KEY)
1323 size = found_key->offset;
1324
1325 if ((found_key->type != BTRFS_EXTENT_ITEM_KEY &&
1326 found_key->type != BTRFS_METADATA_ITEM_KEY) ||
1305 found_key->objectid > logical || 1327 found_key->objectid > logical ||
1306 found_key->objectid + found_key->offset <= logical) { 1328 found_key->objectid + size <= logical) {
1307 pr_debug("logical %llu is not within any extent\n", 1329 pr_debug("logical %llu is not within any extent\n",
1308 (unsigned long long)logical); 1330 (unsigned long long)logical);
1309 return -ENOENT; 1331 return -ENOENT;
@@ -1459,7 +1481,7 @@ int iterate_extent_inodes(struct btrfs_fs_info *fs_info,
1459 iterate_extent_inodes_t *iterate, void *ctx) 1481 iterate_extent_inodes_t *iterate, void *ctx)
1460{ 1482{
1461 int ret; 1483 int ret;
1462 struct btrfs_trans_handle *trans; 1484 struct btrfs_trans_handle *trans = NULL;
1463 struct ulist *refs = NULL; 1485 struct ulist *refs = NULL;
1464 struct ulist *roots = NULL; 1486 struct ulist *roots = NULL;
1465 struct ulist_node *ref_node = NULL; 1487 struct ulist_node *ref_node = NULL;
@@ -1471,9 +1493,7 @@ int iterate_extent_inodes(struct btrfs_fs_info *fs_info,
1471 pr_debug("resolving all inodes for extent %llu\n", 1493 pr_debug("resolving all inodes for extent %llu\n",
1472 extent_item_objectid); 1494 extent_item_objectid);
1473 1495
1474 if (search_commit_root) { 1496 if (!search_commit_root) {
1475 trans = BTRFS_BACKREF_SEARCH_COMMIT_ROOT;
1476 } else {
1477 trans = btrfs_join_transaction(fs_info->extent_root); 1497 trans = btrfs_join_transaction(fs_info->extent_root);
1478 if (IS_ERR(trans)) 1498 if (IS_ERR(trans))
1479 return PTR_ERR(trans); 1499 return PTR_ERR(trans);