send.c (ef8c029fa793423439e67ef0416b220d3fa3321a) | send.c (96b5bd777118bb673b458b41bbefc7f0f31d65c9) |
---|---|
1/* 2 * Copyright (C) 2012 Alexander Block. All rights reserved. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public 6 * License v2 as published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it will be useful, --- 731 unchanged lines hidden (view full) --- 740 return ret; 741} 742 743typedef int (*iterate_inode_ref_t)(int num, u64 dir, int index, 744 struct fs_path *p, 745 void *ctx); 746 747/* | 1/* 2 * Copyright (C) 2012 Alexander Block. All rights reserved. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public 6 * License v2 as published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it will be useful, --- 731 unchanged lines hidden (view full) --- 740 return ret; 741} 742 743typedef int (*iterate_inode_ref_t)(int num, u64 dir, int index, 744 struct fs_path *p, 745 void *ctx); 746 747/* |
748 * Helper function to iterate the entries in ONE btrfs_inode_ref. | 748 * Helper function to iterate the entries in ONE btrfs_inode_ref or 749 * btrfs_inode_extref. |
749 * The iterate callback may return a non zero value to stop iteration. This can 750 * be a negative value for error codes or 1 to simply stop it. 751 * | 750 * The iterate callback may return a non zero value to stop iteration. This can 751 * be a negative value for error codes or 1 to simply stop it. 752 * |
752 * path must point to the INODE_REF when called. | 753 * path must point to the INODE_REF or INODE_EXTREF when called. |
753 */ 754static int iterate_inode_ref(struct send_ctx *sctx, 755 struct btrfs_root *root, struct btrfs_path *path, 756 struct btrfs_key *found_key, int resolve, 757 iterate_inode_ref_t iterate, void *ctx) 758{ | 754 */ 755static int iterate_inode_ref(struct send_ctx *sctx, 756 struct btrfs_root *root, struct btrfs_path *path, 757 struct btrfs_key *found_key, int resolve, 758 iterate_inode_ref_t iterate, void *ctx) 759{ |
759 struct extent_buffer *eb; | 760 struct extent_buffer *eb = path->nodes[0]; |
760 struct btrfs_item *item; 761 struct btrfs_inode_ref *iref; | 761 struct btrfs_item *item; 762 struct btrfs_inode_ref *iref; |
763 struct btrfs_inode_extref *extref; |
|
762 struct btrfs_path *tmp_path; 763 struct fs_path *p; | 764 struct btrfs_path *tmp_path; 765 struct fs_path *p; |
764 u32 cur; 765 u32 len; | 766 u32 cur = 0; |
766 u32 total; | 767 u32 total; |
767 int slot; | 768 int slot = path->slots[0]; |
768 u32 name_len; 769 char *start; 770 int ret = 0; | 769 u32 name_len; 770 char *start; 771 int ret = 0; |
771 int num; | 772 int num = 0; |
772 int index; | 773 int index; |
774 u64 dir; 775 unsigned long name_off; 776 unsigned long elem_size; 777 unsigned long ptr; |
|
773 774 p = fs_path_alloc_reversed(sctx); 775 if (!p) 776 return -ENOMEM; 777 778 tmp_path = alloc_path_for_send(); 779 if (!tmp_path) { 780 fs_path_free(sctx, p); 781 return -ENOMEM; 782 } 783 | 778 779 p = fs_path_alloc_reversed(sctx); 780 if (!p) 781 return -ENOMEM; 782 783 tmp_path = alloc_path_for_send(); 784 if (!tmp_path) { 785 fs_path_free(sctx, p); 786 return -ENOMEM; 787 } 788 |
784 eb = path->nodes[0]; 785 slot = path->slots[0]; 786 item = btrfs_item_nr(eb, slot); 787 iref = btrfs_item_ptr(eb, slot, struct btrfs_inode_ref); 788 cur = 0; 789 len = 0; 790 total = btrfs_item_size(eb, item); | |
791 | 789 |
792 num = 0; | 790 if (found_key->type == BTRFS_INODE_REF_KEY) { 791 ptr = (unsigned long)btrfs_item_ptr(eb, slot, 792 struct btrfs_inode_ref); 793 item = btrfs_item_nr(eb, slot); 794 total = btrfs_item_size(eb, item); 795 elem_size = sizeof(*iref); 796 } else { 797 ptr = btrfs_item_ptr_offset(eb, slot); 798 total = btrfs_item_size_nr(eb, slot); 799 elem_size = sizeof(*extref); 800 } 801 |
793 while (cur < total) { 794 fs_path_reset(p); 795 | 802 while (cur < total) { 803 fs_path_reset(p); 804 |
796 name_len = btrfs_inode_ref_name_len(eb, iref); 797 index = btrfs_inode_ref_index(eb, iref); | 805 if (found_key->type == BTRFS_INODE_REF_KEY) { 806 iref = (struct btrfs_inode_ref *)(ptr + cur); 807 name_len = btrfs_inode_ref_name_len(eb, iref); 808 name_off = (unsigned long)(iref + 1); 809 index = btrfs_inode_ref_index(eb, iref); 810 dir = found_key->offset; 811 } else { 812 extref = (struct btrfs_inode_extref *)(ptr + cur); 813 name_len = btrfs_inode_extref_name_len(eb, extref); 814 name_off = (unsigned long)&extref->name; 815 index = btrfs_inode_extref_index(eb, extref); 816 dir = btrfs_inode_extref_parent(eb, extref); 817 } 818 |
798 if (resolve) { | 819 if (resolve) { |
799 start = btrfs_iref_to_path(root, tmp_path, iref, eb, 800 found_key->offset, p->buf, 801 p->buf_len); | 820 start = btrfs_ref_to_path(root, tmp_path, name_len, 821 name_off, eb, dir, 822 p->buf, p->buf_len); |
802 if (IS_ERR(start)) { 803 ret = PTR_ERR(start); 804 goto out; 805 } 806 if (start < p->buf) { 807 /* overflow , try again with larger buffer */ 808 ret = fs_path_ensure_buf(p, 809 p->buf_len + p->buf - start); 810 if (ret < 0) 811 goto out; | 823 if (IS_ERR(start)) { 824 ret = PTR_ERR(start); 825 goto out; 826 } 827 if (start < p->buf) { 828 /* overflow , try again with larger buffer */ 829 ret = fs_path_ensure_buf(p, 830 p->buf_len + p->buf - start); 831 if (ret < 0) 832 goto out; |
812 start = btrfs_iref_to_path(root, tmp_path, iref, 813 eb, found_key->offset, p->buf, 814 p->buf_len); | 833 start = btrfs_ref_to_path(root, tmp_path, 834 name_len, name_off, 835 eb, dir, 836 p->buf, p->buf_len); |
815 if (IS_ERR(start)) { 816 ret = PTR_ERR(start); 817 goto out; 818 } 819 BUG_ON(start < p->buf); 820 } 821 p->start = start; 822 } else { | 837 if (IS_ERR(start)) { 838 ret = PTR_ERR(start); 839 goto out; 840 } 841 BUG_ON(start < p->buf); 842 } 843 p->start = start; 844 } else { |
823 ret = fs_path_add_from_extent_buffer(p, eb, 824 (unsigned long)(iref + 1), name_len); | 845 ret = fs_path_add_from_extent_buffer(p, eb, name_off, 846 name_len); |
825 if (ret < 0) 826 goto out; 827 } 828 | 847 if (ret < 0) 848 goto out; 849 } 850 |
829 830 len = sizeof(*iref) + name_len; 831 iref = (struct btrfs_inode_ref *)((char *)iref + len); 832 cur += len; 833 834 ret = iterate(num, found_key->offset, index, p, ctx); | 851 cur += elem_size + name_len; 852 ret = iterate(num, dir, index, p, ctx); |
835 if (ret) 836 goto out; | 853 if (ret) 854 goto out; |
837 | |
838 num++; 839 } 840 841out: 842 btrfs_free_path(tmp_path); 843 fs_path_free(sctx, p); 844 return ret; 845} --- 147 unchanged lines hidden (view full) --- 993 if (ret < 0) 994 goto out; 995 if (ret) { 996 ret = 1; 997 goto out; 998 } 999 btrfs_item_key_to_cpu(p->nodes[0], &found_key, p->slots[0]); 1000 if (found_key.objectid != ino || | 855 num++; 856 } 857 858out: 859 btrfs_free_path(tmp_path); 860 fs_path_free(sctx, p); 861 return ret; 862} --- 147 unchanged lines hidden (view full) --- 1010 if (ret < 0) 1011 goto out; 1012 if (ret) { 1013 ret = 1; 1014 goto out; 1015 } 1016 btrfs_item_key_to_cpu(p->nodes[0], &found_key, p->slots[0]); 1017 if (found_key.objectid != ino || |
1001 found_key.type != BTRFS_INODE_REF_KEY) { | 1018 (found_key.type != BTRFS_INODE_REF_KEY && 1019 found_key.type != BTRFS_INODE_EXTREF_KEY)) { |
1002 ret = -ENOENT; 1003 goto out; 1004 } 1005 1006 ret = iterate_inode_ref(sctx, root, p, &found_key, 1, 1007 __copy_first_ref, path); 1008 if (ret < 0) 1009 goto out; --- 536 unchanged lines hidden (view full) --- 1546static int get_first_ref(struct send_ctx *sctx, 1547 struct btrfs_root *root, u64 ino, 1548 u64 *dir, u64 *dir_gen, struct fs_path *name) 1549{ 1550 int ret; 1551 struct btrfs_key key; 1552 struct btrfs_key found_key; 1553 struct btrfs_path *path; | 1020 ret = -ENOENT; 1021 goto out; 1022 } 1023 1024 ret = iterate_inode_ref(sctx, root, p, &found_key, 1, 1025 __copy_first_ref, path); 1026 if (ret < 0) 1027 goto out; --- 536 unchanged lines hidden (view full) --- 1564static int get_first_ref(struct send_ctx *sctx, 1565 struct btrfs_root *root, u64 ino, 1566 u64 *dir, u64 *dir_gen, struct fs_path *name) 1567{ 1568 int ret; 1569 struct btrfs_key key; 1570 struct btrfs_key found_key; 1571 struct btrfs_path *path; |
1554 struct btrfs_inode_ref *iref; | |
1555 int len; | 1572 int len; |
1573 u64 parent_dir; |
|
1556 1557 path = alloc_path_for_send(); 1558 if (!path) 1559 return -ENOMEM; 1560 1561 key.objectid = ino; 1562 key.type = BTRFS_INODE_REF_KEY; 1563 key.offset = 0; 1564 1565 ret = btrfs_search_slot_for_read(root, &key, path, 1, 0); 1566 if (ret < 0) 1567 goto out; 1568 if (!ret) 1569 btrfs_item_key_to_cpu(path->nodes[0], &found_key, 1570 path->slots[0]); | 1574 1575 path = alloc_path_for_send(); 1576 if (!path) 1577 return -ENOMEM; 1578 1579 key.objectid = ino; 1580 key.type = BTRFS_INODE_REF_KEY; 1581 key.offset = 0; 1582 1583 ret = btrfs_search_slot_for_read(root, &key, path, 1, 0); 1584 if (ret < 0) 1585 goto out; 1586 if (!ret) 1587 btrfs_item_key_to_cpu(path->nodes[0], &found_key, 1588 path->slots[0]); |
1571 if (ret || found_key.objectid != key.objectid || 1572 found_key.type != key.type) { | 1589 if (ret || found_key.objectid != ino || 1590 (found_key.type != BTRFS_INODE_REF_KEY && 1591 found_key.type != BTRFS_INODE_EXTREF_KEY)) { |
1573 ret = -ENOENT; 1574 goto out; 1575 } 1576 | 1592 ret = -ENOENT; 1593 goto out; 1594 } 1595 |
1577 iref = btrfs_item_ptr(path->nodes[0], path->slots[0], 1578 struct btrfs_inode_ref); 1579 len = btrfs_inode_ref_name_len(path->nodes[0], iref); 1580 ret = fs_path_add_from_extent_buffer(name, path->nodes[0], 1581 (unsigned long)(iref + 1), len); | 1596 if (key.type == BTRFS_INODE_REF_KEY) { 1597 struct btrfs_inode_ref *iref; 1598 iref = btrfs_item_ptr(path->nodes[0], path->slots[0], 1599 struct btrfs_inode_ref); 1600 len = btrfs_inode_ref_name_len(path->nodes[0], iref); 1601 ret = fs_path_add_from_extent_buffer(name, path->nodes[0], 1602 (unsigned long)(iref + 1), 1603 len); 1604 parent_dir = found_key.offset; 1605 } else { 1606 struct btrfs_inode_extref *extref; 1607 extref = btrfs_item_ptr(path->nodes[0], path->slots[0], 1608 struct btrfs_inode_extref); 1609 len = btrfs_inode_extref_name_len(path->nodes[0], extref); 1610 ret = fs_path_add_from_extent_buffer(name, path->nodes[0], 1611 (unsigned long)&extref->name, len); 1612 parent_dir = btrfs_inode_extref_parent(path->nodes[0], extref); 1613 } |
1582 if (ret < 0) 1583 goto out; 1584 btrfs_release_path(path); 1585 | 1614 if (ret < 0) 1615 goto out; 1616 btrfs_release_path(path); 1617 |
1586 ret = get_inode_info(root, found_key.offset, NULL, dir_gen, NULL, NULL, | 1618 ret = get_inode_info(root, parent_dir, NULL, dir_gen, NULL, NULL, |
1587 NULL, NULL); 1588 if (ret < 0) 1589 goto out; 1590 | 1619 NULL, NULL); 1620 if (ret < 0) 1621 goto out; 1622 |
1591 *dir = found_key.offset; | 1623 *dir = parent_dir; |
1592 1593out: 1594 btrfs_free_path(path); 1595 return ret; 1596} 1597 1598static int is_first_ref(struct send_ctx *sctx, 1599 struct btrfs_root *root, --- 1621 unchanged lines hidden (view full) --- 3221 if (ret) 3222 break; 3223 3224 eb = path->nodes[0]; 3225 slot = path->slots[0]; 3226 btrfs_item_key_to_cpu(eb, &found_key, slot); 3227 3228 if (found_key.objectid != key.objectid || | 1624 1625out: 1626 btrfs_free_path(path); 1627 return ret; 1628} 1629 1630static int is_first_ref(struct send_ctx *sctx, 1631 struct btrfs_root *root, --- 1621 unchanged lines hidden (view full) --- 3253 if (ret) 3254 break; 3255 3256 eb = path->nodes[0]; 3257 slot = path->slots[0]; 3258 btrfs_item_key_to_cpu(eb, &found_key, slot); 3259 3260 if (found_key.objectid != key.objectid || |
3229 found_key.type != key.type) | 3261 (found_key.type != BTRFS_INODE_REF_KEY && 3262 found_key.type != BTRFS_INODE_EXTREF_KEY)) |
3230 break; 3231 3232 ret = iterate_inode_ref(sctx, root, path, &found_key, 0, cb, 3233 sctx); 3234 btrfs_release_path(path); 3235 if (ret < 0) 3236 goto out; 3237 --- 744 unchanged lines hidden (view full) --- 3982 3983static int process_recorded_refs_if_needed(struct send_ctx *sctx, int at_end) 3984{ 3985 int ret = 0; 3986 3987 if (sctx->cur_ino == 0) 3988 goto out; 3989 if (!at_end && sctx->cur_ino == sctx->cmp_key->objectid && | 3263 break; 3264 3265 ret = iterate_inode_ref(sctx, root, path, &found_key, 0, cb, 3266 sctx); 3267 btrfs_release_path(path); 3268 if (ret < 0) 3269 goto out; 3270 --- 744 unchanged lines hidden (view full) --- 4015 4016static int process_recorded_refs_if_needed(struct send_ctx *sctx, int at_end) 4017{ 4018 int ret = 0; 4019 4020 if (sctx->cur_ino == 0) 4021 goto out; 4022 if (!at_end && sctx->cur_ino == sctx->cmp_key->objectid && |
3990 sctx->cmp_key->type <= BTRFS_INODE_REF_KEY) | 4023 sctx->cmp_key->type <= BTRFS_INODE_EXTREF_KEY) |
3991 goto out; 3992 if (list_empty(&sctx->new_refs) && list_empty(&sctx->deleted_refs)) 3993 goto out; 3994 3995 ret = process_recorded_refs(sctx); 3996 if (ret < 0) 3997 goto out; 3998 --- 331 unchanged lines hidden (view full) --- 4330 4331 /* Ignore non-FS objects */ 4332 if (key->objectid == BTRFS_FREE_INO_OBJECTID || 4333 key->objectid == BTRFS_FREE_SPACE_OBJECTID) 4334 goto out; 4335 4336 if (key->type == BTRFS_INODE_ITEM_KEY) 4337 ret = changed_inode(sctx, result); | 4024 goto out; 4025 if (list_empty(&sctx->new_refs) && list_empty(&sctx->deleted_refs)) 4026 goto out; 4027 4028 ret = process_recorded_refs(sctx); 4029 if (ret < 0) 4030 goto out; 4031 --- 331 unchanged lines hidden (view full) --- 4363 4364 /* Ignore non-FS objects */ 4365 if (key->objectid == BTRFS_FREE_INO_OBJECTID || 4366 key->objectid == BTRFS_FREE_SPACE_OBJECTID) 4367 goto out; 4368 4369 if (key->type == BTRFS_INODE_ITEM_KEY) 4370 ret = changed_inode(sctx, result); |
4338 else if (key->type == BTRFS_INODE_REF_KEY) | 4371 else if (key->type == BTRFS_INODE_REF_KEY || 4372 key->type == BTRFS_INODE_EXTREF_KEY) |
4339 ret = changed_ref(sctx, result); 4340 else if (key->type == BTRFS_XATTR_ITEM_KEY) 4341 ret = changed_xattr(sctx, result); 4342 else if (key->type == BTRFS_EXTENT_DATA_KEY) 4343 ret = changed_extent(sctx, result); 4344 4345out: 4346 return ret; --- 313 unchanged lines hidden --- | 4373 ret = changed_ref(sctx, result); 4374 else if (key->type == BTRFS_XATTR_ITEM_KEY) 4375 ret = changed_xattr(sctx, result); 4376 else if (key->type == BTRFS_EXTENT_DATA_KEY) 4377 ret = changed_extent(sctx, result); 4378 4379out: 4380 return ret; --- 313 unchanged lines hidden --- |