diff options
Diffstat (limited to 'fs/btrfs/backref.c')
| -rw-r--r-- | fs/btrfs/backref.c | 93 |
1 files changed, 55 insertions, 38 deletions
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c index 8bc5e8ccb091..0552a599b28f 100644 --- a/fs/btrfs/backref.c +++ b/fs/btrfs/backref.c | |||
| @@ -119,6 +119,26 @@ struct __prelim_ref { | |||
| 119 | u64 wanted_disk_byte; | 119 | u64 wanted_disk_byte; |
| 120 | }; | 120 | }; |
| 121 | 121 | ||
| 122 | static struct kmem_cache *btrfs_prelim_ref_cache; | ||
| 123 | |||
| 124 | int __init btrfs_prelim_ref_init(void) | ||
| 125 | { | ||
| 126 | btrfs_prelim_ref_cache = kmem_cache_create("btrfs_prelim_ref", | ||
| 127 | sizeof(struct __prelim_ref), | ||
| 128 | 0, | ||
| 129 | SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, | ||
| 130 | NULL); | ||
| 131 | if (!btrfs_prelim_ref_cache) | ||
| 132 | return -ENOMEM; | ||
| 133 | return 0; | ||
| 134 | } | ||
| 135 | |||
| 136 | void btrfs_prelim_ref_exit(void) | ||
| 137 | { | ||
| 138 | if (btrfs_prelim_ref_cache) | ||
| 139 | kmem_cache_destroy(btrfs_prelim_ref_cache); | ||
| 140 | } | ||
| 141 | |||
| 122 | /* | 142 | /* |
| 123 | * the rules for all callers of this function are: | 143 | * the rules for all callers of this function are: |
| 124 | * - obtaining the parent is the goal | 144 | * - obtaining the parent is the goal |
| @@ -160,12 +180,12 @@ struct __prelim_ref { | |||
| 160 | 180 | ||
| 161 | static int __add_prelim_ref(struct list_head *head, u64 root_id, | 181 | static int __add_prelim_ref(struct list_head *head, u64 root_id, |
| 162 | struct btrfs_key *key, int level, | 182 | struct btrfs_key *key, int level, |
| 163 | u64 parent, u64 wanted_disk_byte, int count) | 183 | u64 parent, u64 wanted_disk_byte, int count, |
| 184 | gfp_t gfp_mask) | ||
| 164 | { | 185 | { |
| 165 | struct __prelim_ref *ref; | 186 | struct __prelim_ref *ref; |
| 166 | 187 | ||
| 167 | /* in case we're adding delayed refs, we're holding the refs spinlock */ | 188 | ref = kmem_cache_alloc(btrfs_prelim_ref_cache, gfp_mask); |
| 168 | ref = kmalloc(sizeof(*ref), GFP_ATOMIC); | ||
| 169 | if (!ref) | 189 | if (!ref) |
| 170 | return -ENOMEM; | 190 | return -ENOMEM; |
| 171 | 191 | ||
| @@ -295,10 +315,9 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info, | |||
| 295 | ret = btrfs_search_old_slot(root, &ref->key_for_search, path, time_seq); | 315 | ret = btrfs_search_old_slot(root, &ref->key_for_search, path, time_seq); |
| 296 | pr_debug("search slot in root %llu (level %d, ref count %d) returned " | 316 | pr_debug("search slot in root %llu (level %d, ref count %d) returned " |
| 297 | "%d for key (%llu %u %llu)\n", | 317 | "%d for key (%llu %u %llu)\n", |
| 298 | (unsigned long long)ref->root_id, level, ref->count, ret, | 318 | ref->root_id, level, ref->count, ret, |
| 299 | (unsigned long long)ref->key_for_search.objectid, | 319 | ref->key_for_search.objectid, ref->key_for_search.type, |
| 300 | ref->key_for_search.type, | 320 | ref->key_for_search.offset); |
| 301 | (unsigned long long)ref->key_for_search.offset); | ||
| 302 | if (ret < 0) | 321 | if (ret < 0) |
| 303 | goto out; | 322 | goto out; |
| 304 | 323 | ||
| @@ -365,11 +384,12 @@ static int __resolve_indirect_refs(struct btrfs_fs_info *fs_info, | |||
| 365 | node = ulist_next(parents, &uiter); | 384 | node = ulist_next(parents, &uiter); |
| 366 | ref->parent = node ? node->val : 0; | 385 | ref->parent = node ? node->val : 0; |
| 367 | ref->inode_list = node ? | 386 | ref->inode_list = node ? |
| 368 | (struct extent_inode_elem *)(uintptr_t)node->aux : 0; | 387 | (struct extent_inode_elem *)(uintptr_t)node->aux : NULL; |
| 369 | 388 | ||
| 370 | /* additional parents require new refs being added here */ | 389 | /* additional parents require new refs being added here */ |
| 371 | while ((node = ulist_next(parents, &uiter))) { | 390 | while ((node = ulist_next(parents, &uiter))) { |
| 372 | new_ref = kmalloc(sizeof(*new_ref), GFP_NOFS); | 391 | new_ref = kmem_cache_alloc(btrfs_prelim_ref_cache, |
| 392 | GFP_NOFS); | ||
| 373 | if (!new_ref) { | 393 | if (!new_ref) { |
| 374 | ret = -ENOMEM; | 394 | ret = -ENOMEM; |
| 375 | goto out; | 395 | goto out; |
| @@ -493,7 +513,7 @@ static void __merge_refs(struct list_head *head, int mode) | |||
| 493 | ref1->count += ref2->count; | 513 | ref1->count += ref2->count; |
| 494 | 514 | ||
| 495 | list_del(&ref2->list); | 515 | list_del(&ref2->list); |
| 496 | kfree(ref2); | 516 | kmem_cache_free(btrfs_prelim_ref_cache, ref2); |
| 497 | } | 517 | } |
| 498 | 518 | ||
| 499 | } | 519 | } |
| @@ -548,7 +568,7 @@ static int __add_delayed_refs(struct btrfs_delayed_ref_head *head, u64 seq, | |||
| 548 | ref = btrfs_delayed_node_to_tree_ref(node); | 568 | ref = btrfs_delayed_node_to_tree_ref(node); |
| 549 | ret = __add_prelim_ref(prefs, ref->root, &op_key, | 569 | ret = __add_prelim_ref(prefs, ref->root, &op_key, |
| 550 | ref->level + 1, 0, node->bytenr, | 570 | ref->level + 1, 0, node->bytenr, |
| 551 | node->ref_mod * sgn); | 571 | node->ref_mod * sgn, GFP_ATOMIC); |
| 552 | break; | 572 | break; |
| 553 | } | 573 | } |
| 554 | case BTRFS_SHARED_BLOCK_REF_KEY: { | 574 | case BTRFS_SHARED_BLOCK_REF_KEY: { |
| @@ -558,7 +578,7 @@ static int __add_delayed_refs(struct btrfs_delayed_ref_head *head, u64 seq, | |||
| 558 | ret = __add_prelim_ref(prefs, ref->root, NULL, | 578 | ret = __add_prelim_ref(prefs, ref->root, NULL, |
| 559 | ref->level + 1, ref->parent, | 579 | ref->level + 1, ref->parent, |
| 560 | node->bytenr, | 580 | node->bytenr, |
| 561 | node->ref_mod * sgn); | 581 | node->ref_mod * sgn, GFP_ATOMIC); |
| 562 | break; | 582 | break; |
| 563 | } | 583 | } |
| 564 | case BTRFS_EXTENT_DATA_REF_KEY: { | 584 | case BTRFS_EXTENT_DATA_REF_KEY: { |
| @@ -570,7 +590,7 @@ static int __add_delayed_refs(struct btrfs_delayed_ref_head *head, u64 seq, | |||
| 570 | key.offset = ref->offset; | 590 | key.offset = ref->offset; |
| 571 | ret = __add_prelim_ref(prefs, ref->root, &key, 0, 0, | 591 | ret = __add_prelim_ref(prefs, ref->root, &key, 0, 0, |
| 572 | node->bytenr, | 592 | node->bytenr, |
| 573 | node->ref_mod * sgn); | 593 | node->ref_mod * sgn, GFP_ATOMIC); |
| 574 | break; | 594 | break; |
| 575 | } | 595 | } |
| 576 | case BTRFS_SHARED_DATA_REF_KEY: { | 596 | case BTRFS_SHARED_DATA_REF_KEY: { |
| @@ -583,7 +603,7 @@ static int __add_delayed_refs(struct btrfs_delayed_ref_head *head, u64 seq, | |||
| 583 | key.offset = ref->offset; | 603 | key.offset = ref->offset; |
| 584 | ret = __add_prelim_ref(prefs, ref->root, &key, 0, | 604 | ret = __add_prelim_ref(prefs, ref->root, &key, 0, |
| 585 | ref->parent, node->bytenr, | 605 | ref->parent, node->bytenr, |
| 586 | node->ref_mod * sgn); | 606 | node->ref_mod * sgn, GFP_ATOMIC); |
| 587 | break; | 607 | break; |
| 588 | } | 608 | } |
| 589 | default: | 609 | default: |
| @@ -657,7 +677,7 @@ static int __add_inline_refs(struct btrfs_fs_info *fs_info, | |||
| 657 | case BTRFS_SHARED_BLOCK_REF_KEY: | 677 | case BTRFS_SHARED_BLOCK_REF_KEY: |
| 658 | ret = __add_prelim_ref(prefs, 0, NULL, | 678 | ret = __add_prelim_ref(prefs, 0, NULL, |
| 659 | *info_level + 1, offset, | 679 | *info_level + 1, offset, |
| 660 | bytenr, 1); | 680 | bytenr, 1, GFP_NOFS); |
| 661 | break; | 681 | break; |
| 662 | case BTRFS_SHARED_DATA_REF_KEY: { | 682 | case BTRFS_SHARED_DATA_REF_KEY: { |
| 663 | struct btrfs_shared_data_ref *sdref; | 683 | struct btrfs_shared_data_ref *sdref; |
| @@ -666,13 +686,13 @@ static int __add_inline_refs(struct btrfs_fs_info *fs_info, | |||
| 666 | sdref = (struct btrfs_shared_data_ref *)(iref + 1); | 686 | sdref = (struct btrfs_shared_data_ref *)(iref + 1); |
| 667 | count = btrfs_shared_data_ref_count(leaf, sdref); | 687 | count = btrfs_shared_data_ref_count(leaf, sdref); |
| 668 | ret = __add_prelim_ref(prefs, 0, NULL, 0, offset, | 688 | ret = __add_prelim_ref(prefs, 0, NULL, 0, offset, |
| 669 | bytenr, count); | 689 | bytenr, count, GFP_NOFS); |
| 670 | break; | 690 | break; |
| 671 | } | 691 | } |
| 672 | case BTRFS_TREE_BLOCK_REF_KEY: | 692 | case BTRFS_TREE_BLOCK_REF_KEY: |
| 673 | ret = __add_prelim_ref(prefs, offset, NULL, | 693 | ret = __add_prelim_ref(prefs, offset, NULL, |
| 674 | *info_level + 1, 0, | 694 | *info_level + 1, 0, |
| 675 | bytenr, 1); | 695 | bytenr, 1, GFP_NOFS); |
| 676 | break; | 696 | break; |
| 677 | case BTRFS_EXTENT_DATA_REF_KEY: { | 697 | case BTRFS_EXTENT_DATA_REF_KEY: { |
| 678 | struct btrfs_extent_data_ref *dref; | 698 | struct btrfs_extent_data_ref *dref; |
| @@ -687,7 +707,7 @@ static int __add_inline_refs(struct btrfs_fs_info *fs_info, | |||
| 687 | key.offset = btrfs_extent_data_ref_offset(leaf, dref); | 707 | key.offset = btrfs_extent_data_ref_offset(leaf, dref); |
| 688 | root = btrfs_extent_data_ref_root(leaf, dref); | 708 | root = btrfs_extent_data_ref_root(leaf, dref); |
| 689 | ret = __add_prelim_ref(prefs, root, &key, 0, 0, | 709 | ret = __add_prelim_ref(prefs, root, &key, 0, 0, |
| 690 | bytenr, count); | 710 | bytenr, count, GFP_NOFS); |
| 691 | break; | 711 | break; |
| 692 | } | 712 | } |
| 693 | default: | 713 | default: |
| @@ -738,7 +758,7 @@ static int __add_keyed_refs(struct btrfs_fs_info *fs_info, | |||
| 738 | case BTRFS_SHARED_BLOCK_REF_KEY: | 758 | case BTRFS_SHARED_BLOCK_REF_KEY: |
| 739 | ret = __add_prelim_ref(prefs, 0, NULL, | 759 | ret = __add_prelim_ref(prefs, 0, NULL, |
| 740 | info_level + 1, key.offset, | 760 | info_level + 1, key.offset, |
| 741 | bytenr, 1); | 761 | bytenr, 1, GFP_NOFS); |
| 742 | break; | 762 | break; |
| 743 | case BTRFS_SHARED_DATA_REF_KEY: { | 763 | case BTRFS_SHARED_DATA_REF_KEY: { |
| 744 | struct btrfs_shared_data_ref *sdref; | 764 | struct btrfs_shared_data_ref *sdref; |
| @@ -748,13 +768,13 @@ static int __add_keyed_refs(struct btrfs_fs_info *fs_info, | |||
| 748 | struct btrfs_shared_data_ref); | 768 | struct btrfs_shared_data_ref); |
| 749 | count = btrfs_shared_data_ref_count(leaf, sdref); | 769 | count = btrfs_shared_data_ref_count(leaf, sdref); |
| 750 | ret = __add_prelim_ref(prefs, 0, NULL, 0, key.offset, | 770 | ret = __add_prelim_ref(prefs, 0, NULL, 0, key.offset, |
| 751 | bytenr, count); | 771 | bytenr, count, GFP_NOFS); |
| 752 | break; | 772 | break; |
| 753 | } | 773 | } |
| 754 | case BTRFS_TREE_BLOCK_REF_KEY: | 774 | case BTRFS_TREE_BLOCK_REF_KEY: |
| 755 | ret = __add_prelim_ref(prefs, key.offset, NULL, | 775 | ret = __add_prelim_ref(prefs, key.offset, NULL, |
| 756 | info_level + 1, 0, | 776 | info_level + 1, 0, |
| 757 | bytenr, 1); | 777 | bytenr, 1, GFP_NOFS); |
| 758 | break; | 778 | break; |
| 759 | case BTRFS_EXTENT_DATA_REF_KEY: { | 779 | case BTRFS_EXTENT_DATA_REF_KEY: { |
| 760 | struct btrfs_extent_data_ref *dref; | 780 | struct btrfs_extent_data_ref *dref; |
| @@ -770,7 +790,7 @@ static int __add_keyed_refs(struct btrfs_fs_info *fs_info, | |||
| 770 | key.offset = btrfs_extent_data_ref_offset(leaf, dref); | 790 | key.offset = btrfs_extent_data_ref_offset(leaf, dref); |
| 771 | root = btrfs_extent_data_ref_root(leaf, dref); | 791 | root = btrfs_extent_data_ref_root(leaf, dref); |
| 772 | ret = __add_prelim_ref(prefs, root, &key, 0, 0, | 792 | ret = __add_prelim_ref(prefs, root, &key, 0, 0, |
| 773 | bytenr, count); | 793 | bytenr, count, GFP_NOFS); |
| 774 | break; | 794 | break; |
| 775 | } | 795 | } |
| 776 | default: | 796 | default: |
| @@ -911,7 +931,6 @@ again: | |||
| 911 | 931 | ||
| 912 | while (!list_empty(&prefs)) { | 932 | while (!list_empty(&prefs)) { |
| 913 | ref = list_first_entry(&prefs, struct __prelim_ref, list); | 933 | ref = list_first_entry(&prefs, struct __prelim_ref, list); |
| 914 | list_del(&ref->list); | ||
| 915 | WARN_ON(ref->count < 0); | 934 | WARN_ON(ref->count < 0); |
| 916 | if (ref->count && ref->root_id && ref->parent == 0) { | 935 | if (ref->count && ref->root_id && ref->parent == 0) { |
| 917 | /* no parent == root of tree */ | 936 | /* no parent == root of tree */ |
| @@ -935,8 +954,10 @@ again: | |||
| 935 | } | 954 | } |
| 936 | ret = find_extent_in_eb(eb, bytenr, | 955 | ret = find_extent_in_eb(eb, bytenr, |
| 937 | *extent_item_pos, &eie); | 956 | *extent_item_pos, &eie); |
| 938 | ref->inode_list = eie; | ||
| 939 | free_extent_buffer(eb); | 957 | free_extent_buffer(eb); |
| 958 | if (ret < 0) | ||
| 959 | goto out; | ||
| 960 | ref->inode_list = eie; | ||
| 940 | } | 961 | } |
| 941 | ret = ulist_add_merge(refs, ref->parent, | 962 | ret = ulist_add_merge(refs, ref->parent, |
| 942 | (uintptr_t)ref->inode_list, | 963 | (uintptr_t)ref->inode_list, |
| @@ -954,7 +975,8 @@ again: | |||
| 954 | eie->next = ref->inode_list; | 975 | eie->next = ref->inode_list; |
| 955 | } | 976 | } |
| 956 | } | 977 | } |
| 957 | kfree(ref); | 978 | list_del(&ref->list); |
| 979 | kmem_cache_free(btrfs_prelim_ref_cache, ref); | ||
| 958 | } | 980 | } |
| 959 | 981 | ||
| 960 | out: | 982 | out: |
| @@ -962,13 +984,13 @@ out: | |||
| 962 | while (!list_empty(&prefs)) { | 984 | while (!list_empty(&prefs)) { |
| 963 | ref = list_first_entry(&prefs, struct __prelim_ref, list); | 985 | ref = list_first_entry(&prefs, struct __prelim_ref, list); |
| 964 | list_del(&ref->list); | 986 | list_del(&ref->list); |
| 965 | kfree(ref); | 987 | kmem_cache_free(btrfs_prelim_ref_cache, ref); |
| 966 | } | 988 | } |
| 967 | while (!list_empty(&prefs_delayed)) { | 989 | while (!list_empty(&prefs_delayed)) { |
| 968 | ref = list_first_entry(&prefs_delayed, struct __prelim_ref, | 990 | ref = list_first_entry(&prefs_delayed, struct __prelim_ref, |
| 969 | list); | 991 | list); |
| 970 | list_del(&ref->list); | 992 | list_del(&ref->list); |
| 971 | kfree(ref); | 993 | kmem_cache_free(btrfs_prelim_ref_cache, ref); |
| 972 | } | 994 | } |
| 973 | 995 | ||
| 974 | return ret; | 996 | return ret; |
| @@ -1326,8 +1348,7 @@ int extent_from_logical(struct btrfs_fs_info *fs_info, u64 logical, | |||
| 1326 | found_key->type != BTRFS_METADATA_ITEM_KEY) || | 1348 | found_key->type != BTRFS_METADATA_ITEM_KEY) || |
| 1327 | found_key->objectid > logical || | 1349 | found_key->objectid > logical || |
| 1328 | found_key->objectid + size <= logical) { | 1350 | found_key->objectid + size <= logical) { |
| 1329 | pr_debug("logical %llu is not within any extent\n", | 1351 | pr_debug("logical %llu is not within any extent\n", logical); |
| 1330 | (unsigned long long)logical); | ||
| 1331 | return -ENOENT; | 1352 | return -ENOENT; |
| 1332 | } | 1353 | } |
| 1333 | 1354 | ||
| @@ -1340,11 +1361,8 @@ int extent_from_logical(struct btrfs_fs_info *fs_info, u64 logical, | |||
| 1340 | 1361 | ||
| 1341 | pr_debug("logical %llu is at position %llu within the extent (%llu " | 1362 | pr_debug("logical %llu is at position %llu within the extent (%llu " |
| 1342 | "EXTENT_ITEM %llu) flags %#llx size %u\n", | 1363 | "EXTENT_ITEM %llu) flags %#llx size %u\n", |
| 1343 | (unsigned long long)logical, | 1364 | logical, logical - found_key->objectid, found_key->objectid, |
| 1344 | (unsigned long long)(logical - found_key->objectid), | 1365 | found_key->offset, flags, item_size); |
| 1345 | (unsigned long long)found_key->objectid, | ||
| 1346 | (unsigned long long)found_key->offset, | ||
| 1347 | (unsigned long long)flags, item_size); | ||
| 1348 | 1366 | ||
| 1349 | WARN_ON(!flags_ret); | 1367 | WARN_ON(!flags_ret); |
| 1350 | if (flags_ret) { | 1368 | if (flags_ret) { |
| @@ -1516,7 +1534,7 @@ int iterate_extent_inodes(struct btrfs_fs_info *fs_info, | |||
| 1516 | while (!ret && (root_node = ulist_next(roots, &root_uiter))) { | 1534 | while (!ret && (root_node = ulist_next(roots, &root_uiter))) { |
| 1517 | pr_debug("root %llu references leaf %llu, data list " | 1535 | pr_debug("root %llu references leaf %llu, data list " |
| 1518 | "%#llx\n", root_node->val, ref_node->val, | 1536 | "%#llx\n", root_node->val, ref_node->val, |
| 1519 | (long long)ref_node->aux); | 1537 | ref_node->aux); |
| 1520 | ret = iterate_leaf_refs((struct extent_inode_elem *) | 1538 | ret = iterate_leaf_refs((struct extent_inode_elem *) |
| 1521 | (uintptr_t)ref_node->aux, | 1539 | (uintptr_t)ref_node->aux, |
| 1522 | root_node->val, | 1540 | root_node->val, |
| @@ -1608,9 +1626,8 @@ static int iterate_inode_refs(u64 inum, struct btrfs_root *fs_root, | |||
| 1608 | name_len = btrfs_inode_ref_name_len(eb, iref); | 1626 | name_len = btrfs_inode_ref_name_len(eb, iref); |
| 1609 | /* path must be released before calling iterate()! */ | 1627 | /* path must be released before calling iterate()! */ |
| 1610 | pr_debug("following ref at offset %u for inode %llu in " | 1628 | pr_debug("following ref at offset %u for inode %llu in " |
| 1611 | "tree %llu\n", cur, | 1629 | "tree %llu\n", cur, found_key.objectid, |
| 1612 | (unsigned long long)found_key.objectid, | 1630 | fs_root->objectid); |
| 1613 | (unsigned long long)fs_root->objectid); | ||
| 1614 | ret = iterate(parent, name_len, | 1631 | ret = iterate(parent, name_len, |
| 1615 | (unsigned long)(iref + 1), eb, ctx); | 1632 | (unsigned long)(iref + 1), eb, ctx); |
| 1616 | if (ret) | 1633 | if (ret) |
