diff options
author | Jan Schmidt <list.btrfs@jan-o-sch.net> | 2012-10-15 04:30:45 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@fusionio.com> | 2012-10-25 15:45:16 -0400 |
commit | 96b5bd777118bb673b458b41bbefc7f0f31d65c9 (patch) | |
tree | bcb941e48650405cf61d7f152da9c102a5a07975 /fs | |
parent | 84167d190569eedcdb24bf2499bdda437e442962 (diff) |
Btrfs: extended inode refs support for send mechanism
This adds support for the new extended inode refs to btrfs send.
Signed-off-by: Jan Schmidt <list.btrfs@jan-o-sch.net>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/backref.c | 22 | ||||
-rw-r--r-- | fs/btrfs/backref.h | 4 | ||||
-rw-r--r-- | fs/btrfs/send.c | 126 |
3 files changed, 94 insertions, 58 deletions
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c index 2bcbea3f6308..b8b69266393a 100644 --- a/fs/btrfs/backref.c +++ b/fs/btrfs/backref.c | |||
@@ -1177,11 +1177,10 @@ int btrfs_find_one_extref(struct btrfs_root *root, u64 inode_objectid, | |||
1177 | return ret; | 1177 | return ret; |
1178 | } | 1178 | } |
1179 | 1179 | ||
1180 | static char *ref_to_path(struct btrfs_root *fs_root, | 1180 | char *btrfs_ref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path, |
1181 | struct btrfs_path *path, | 1181 | u32 name_len, unsigned long name_off, |
1182 | u32 name_len, unsigned long name_off, | 1182 | struct extent_buffer *eb_in, u64 parent, |
1183 | struct extent_buffer *eb_in, u64 parent, | 1183 | char *dest, u32 size) |
1184 | char *dest, u32 size) | ||
1185 | { | 1184 | { |
1186 | int slot; | 1185 | int slot; |
1187 | u64 next_inum; | 1186 | u64 next_inum; |
@@ -1266,10 +1265,10 @@ char *btrfs_iref_to_path(struct btrfs_root *fs_root, | |||
1266 | struct extent_buffer *eb_in, u64 parent, | 1265 | struct extent_buffer *eb_in, u64 parent, |
1267 | char *dest, u32 size) | 1266 | char *dest, u32 size) |
1268 | { | 1267 | { |
1269 | return ref_to_path(fs_root, path, | 1268 | return btrfs_ref_to_path(fs_root, path, |
1270 | btrfs_inode_ref_name_len(eb_in, iref), | 1269 | btrfs_inode_ref_name_len(eb_in, iref), |
1271 | (unsigned long)(iref + 1), | 1270 | (unsigned long)(iref + 1), |
1272 | eb_in, parent, dest, size); | 1271 | eb_in, parent, dest, size); |
1273 | } | 1272 | } |
1274 | 1273 | ||
1275 | /* | 1274 | /* |
@@ -1715,9 +1714,8 @@ static int inode_to_path(u64 inum, u32 name_len, unsigned long name_off, | |||
1715 | ipath->fspath->bytes_left - s_ptr : 0; | 1714 | ipath->fspath->bytes_left - s_ptr : 0; |
1716 | 1715 | ||
1717 | fspath_min = (char *)ipath->fspath->val + (i + 1) * s_ptr; | 1716 | fspath_min = (char *)ipath->fspath->val + (i + 1) * s_ptr; |
1718 | fspath = ref_to_path(ipath->fs_root, ipath->btrfs_path, name_len, | 1717 | fspath = btrfs_ref_to_path(ipath->fs_root, ipath->btrfs_path, name_len, |
1719 | name_off, eb, inum, fspath_min, | 1718 | name_off, eb, inum, fspath_min, bytes_left); |
1720 | bytes_left); | ||
1721 | if (IS_ERR(fspath)) | 1719 | if (IS_ERR(fspath)) |
1722 | return PTR_ERR(fspath); | 1720 | return PTR_ERR(fspath); |
1723 | 1721 | ||
diff --git a/fs/btrfs/backref.h b/fs/btrfs/backref.h index e75533043a5f..d61feca79455 100644 --- a/fs/btrfs/backref.h +++ b/fs/btrfs/backref.h | |||
@@ -62,6 +62,10 @@ int btrfs_find_all_roots(struct btrfs_trans_handle *trans, | |||
62 | char *btrfs_iref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path, | 62 | char *btrfs_iref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path, |
63 | struct btrfs_inode_ref *iref, struct extent_buffer *eb, | 63 | struct btrfs_inode_ref *iref, struct extent_buffer *eb, |
64 | u64 parent, char *dest, u32 size); | 64 | u64 parent, char *dest, u32 size); |
65 | char *btrfs_ref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path, | ||
66 | u32 name_len, unsigned long name_off, | ||
67 | struct extent_buffer *eb_in, u64 parent, | ||
68 | char *dest, u32 size); | ||
65 | 69 | ||
66 | struct btrfs_data_container *init_data_container(u32 total_bytes); | 70 | struct btrfs_data_container *init_data_container(u32 total_bytes); |
67 | struct inode_fs_paths *init_ipath(s32 total_bytes, struct btrfs_root *fs_root, | 71 | struct inode_fs_paths *init_ipath(s32 total_bytes, struct btrfs_root *fs_root, |
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c index c7beb543a4a8..4f20c49edd58 100644 --- a/fs/btrfs/send.c +++ b/fs/btrfs/send.c | |||
@@ -745,31 +745,36 @@ typedef int (*iterate_inode_ref_t)(int num, u64 dir, int index, | |||
745 | void *ctx); | 745 | void *ctx); |
746 | 746 | ||
747 | /* | 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 | * 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 | * be a negative value for error codes or 1 to simply stop it. |
751 | * | 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 | */ | 754 | */ |
754 | static int iterate_inode_ref(struct send_ctx *sctx, | 755 | static int iterate_inode_ref(struct send_ctx *sctx, |
755 | struct btrfs_root *root, struct btrfs_path *path, | 756 | struct btrfs_root *root, struct btrfs_path *path, |
756 | struct btrfs_key *found_key, int resolve, | 757 | struct btrfs_key *found_key, int resolve, |
757 | iterate_inode_ref_t iterate, void *ctx) | 758 | iterate_inode_ref_t iterate, void *ctx) |
758 | { | 759 | { |
759 | struct extent_buffer *eb; | 760 | struct extent_buffer *eb = path->nodes[0]; |
760 | struct btrfs_item *item; | 761 | struct btrfs_item *item; |
761 | struct btrfs_inode_ref *iref; | 762 | struct btrfs_inode_ref *iref; |
763 | struct btrfs_inode_extref *extref; | ||
762 | struct btrfs_path *tmp_path; | 764 | struct btrfs_path *tmp_path; |
763 | struct fs_path *p; | 765 | struct fs_path *p; |
764 | u32 cur; | 766 | u32 cur = 0; |
765 | u32 len; | ||
766 | u32 total; | 767 | u32 total; |
767 | int slot; | 768 | int slot = path->slots[0]; |
768 | u32 name_len; | 769 | u32 name_len; |
769 | char *start; | 770 | char *start; |
770 | int ret = 0; | 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 | 778 | ||
774 | p = fs_path_alloc_reversed(sctx); | 779 | p = fs_path_alloc_reversed(sctx); |
775 | if (!p) | 780 | if (!p) |
@@ -781,24 +786,40 @@ static int iterate_inode_ref(struct send_ctx *sctx, | |||
781 | return -ENOMEM; | 786 | return -ENOMEM; |
782 | } | 787 | } |
783 | 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) { | 802 | while (cur < total) { |
794 | fs_path_reset(p); | 803 | fs_path_reset(p); |
795 | 804 | ||
796 | name_len = btrfs_inode_ref_name_len(eb, iref); | 805 | if (found_key->type == BTRFS_INODE_REF_KEY) { |
797 | index = btrfs_inode_ref_index(eb, iref); | 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, | 820 | start = btrfs_ref_to_path(root, tmp_path, name_len, |
800 | found_key->offset, p->buf, | 821 | name_off, eb, dir, |
801 | p->buf_len); | 822 | p->buf, p->buf_len); |
802 | if (IS_ERR(start)) { | 823 | if (IS_ERR(start)) { |
803 | ret = PTR_ERR(start); | 824 | ret = PTR_ERR(start); |
804 | goto out; | 825 | goto out; |
@@ -809,9 +830,10 @@ static int iterate_inode_ref(struct send_ctx *sctx, | |||
809 | p->buf_len + p->buf - start); | 830 | p->buf_len + p->buf - start); |
810 | if (ret < 0) | 831 | if (ret < 0) |
811 | goto out; | 832 | goto out; |
812 | start = btrfs_iref_to_path(root, tmp_path, iref, | 833 | start = btrfs_ref_to_path(root, tmp_path, |
813 | eb, found_key->offset, p->buf, | 834 | name_len, name_off, |
814 | p->buf_len); | 835 | eb, dir, |
836 | p->buf, p->buf_len); | ||
815 | if (IS_ERR(start)) { | 837 | if (IS_ERR(start)) { |
816 | ret = PTR_ERR(start); | 838 | ret = PTR_ERR(start); |
817 | goto out; | 839 | goto out; |
@@ -820,21 +842,16 @@ static int iterate_inode_ref(struct send_ctx *sctx, | |||
820 | } | 842 | } |
821 | p->start = start; | 843 | p->start = start; |
822 | } else { | 844 | } else { |
823 | ret = fs_path_add_from_extent_buffer(p, eb, | 845 | ret = fs_path_add_from_extent_buffer(p, eb, name_off, |
824 | (unsigned long)(iref + 1), name_len); | 846 | name_len); |
825 | if (ret < 0) | 847 | if (ret < 0) |
826 | goto out; | 848 | goto out; |
827 | } | 849 | } |
828 | 850 | ||
829 | 851 | cur += elem_size + name_len; | |
830 | len = sizeof(*iref) + name_len; | 852 | ret = iterate(num, dir, index, p, ctx); |
831 | iref = (struct btrfs_inode_ref *)((char *)iref + len); | ||
832 | cur += len; | ||
833 | |||
834 | ret = iterate(num, found_key->offset, index, p, ctx); | ||
835 | if (ret) | 853 | if (ret) |
836 | goto out; | 854 | goto out; |
837 | |||
838 | num++; | 855 | num++; |
839 | } | 856 | } |
840 | 857 | ||
@@ -998,7 +1015,8 @@ static int get_inode_path(struct send_ctx *sctx, struct btrfs_root *root, | |||
998 | } | 1015 | } |
999 | btrfs_item_key_to_cpu(p->nodes[0], &found_key, p->slots[0]); | 1016 | btrfs_item_key_to_cpu(p->nodes[0], &found_key, p->slots[0]); |
1000 | if (found_key.objectid != ino || | 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; | 1020 | ret = -ENOENT; |
1003 | goto out; | 1021 | goto out; |
1004 | } | 1022 | } |
@@ -1551,8 +1569,8 @@ static int get_first_ref(struct send_ctx *sctx, | |||
1551 | struct btrfs_key key; | 1569 | struct btrfs_key key; |
1552 | struct btrfs_key found_key; | 1570 | struct btrfs_key found_key; |
1553 | struct btrfs_path *path; | 1571 | struct btrfs_path *path; |
1554 | struct btrfs_inode_ref *iref; | ||
1555 | int len; | 1572 | int len; |
1573 | u64 parent_dir; | ||
1556 | 1574 | ||
1557 | path = alloc_path_for_send(); | 1575 | path = alloc_path_for_send(); |
1558 | if (!path) | 1576 | if (!path) |
@@ -1568,27 +1586,41 @@ static int get_first_ref(struct send_ctx *sctx, | |||
1568 | if (!ret) | 1586 | if (!ret) |
1569 | btrfs_item_key_to_cpu(path->nodes[0], &found_key, | 1587 | btrfs_item_key_to_cpu(path->nodes[0], &found_key, |
1570 | path->slots[0]); | 1588 | path->slots[0]); |
1571 | if (ret || found_key.objectid != key.objectid || | 1589 | if (ret || found_key.objectid != ino || |
1572 | found_key.type != key.type) { | 1590 | (found_key.type != BTRFS_INODE_REF_KEY && |
1591 | found_key.type != BTRFS_INODE_EXTREF_KEY)) { | ||
1573 | ret = -ENOENT; | 1592 | ret = -ENOENT; |
1574 | goto out; | 1593 | goto out; |
1575 | } | 1594 | } |
1576 | 1595 | ||
1577 | iref = btrfs_item_ptr(path->nodes[0], path->slots[0], | 1596 | if (key.type == BTRFS_INODE_REF_KEY) { |
1578 | struct btrfs_inode_ref); | 1597 | struct btrfs_inode_ref *iref; |
1579 | len = btrfs_inode_ref_name_len(path->nodes[0], iref); | 1598 | iref = btrfs_item_ptr(path->nodes[0], path->slots[0], |
1580 | ret = fs_path_add_from_extent_buffer(name, path->nodes[0], | 1599 | struct btrfs_inode_ref); |
1581 | (unsigned long)(iref + 1), len); | 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) | 1614 | if (ret < 0) |
1583 | goto out; | 1615 | goto out; |
1584 | btrfs_release_path(path); | 1616 | btrfs_release_path(path); |
1585 | 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); | 1619 | NULL, NULL); |
1588 | if (ret < 0) | 1620 | if (ret < 0) |
1589 | goto out; | 1621 | goto out; |
1590 | 1622 | ||
1591 | *dir = found_key.offset; | 1623 | *dir = parent_dir; |
1592 | 1624 | ||
1593 | out: | 1625 | out: |
1594 | btrfs_free_path(path); | 1626 | btrfs_free_path(path); |
@@ -3226,7 +3258,8 @@ static int process_all_refs(struct send_ctx *sctx, | |||
3226 | btrfs_item_key_to_cpu(eb, &found_key, slot); | 3258 | btrfs_item_key_to_cpu(eb, &found_key, slot); |
3227 | 3259 | ||
3228 | if (found_key.objectid != key.objectid || | 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; | 3263 | break; |
3231 | 3264 | ||
3232 | ret = iterate_inode_ref(sctx, root, path, &found_key, 0, cb, | 3265 | ret = iterate_inode_ref(sctx, root, path, &found_key, 0, cb, |
@@ -3987,7 +4020,7 @@ static int process_recorded_refs_if_needed(struct send_ctx *sctx, int at_end) | |||
3987 | if (sctx->cur_ino == 0) | 4020 | if (sctx->cur_ino == 0) |
3988 | goto out; | 4021 | goto out; |
3989 | if (!at_end && sctx->cur_ino == sctx->cmp_key->objectid && | 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; | 4024 | goto out; |
3992 | if (list_empty(&sctx->new_refs) && list_empty(&sctx->deleted_refs)) | 4025 | if (list_empty(&sctx->new_refs) && list_empty(&sctx->deleted_refs)) |
3993 | goto out; | 4026 | goto out; |
@@ -4335,7 +4368,8 @@ static int changed_cb(struct btrfs_root *left_root, | |||
4335 | 4368 | ||
4336 | if (key->type == BTRFS_INODE_ITEM_KEY) | 4369 | if (key->type == BTRFS_INODE_ITEM_KEY) |
4337 | ret = changed_inode(sctx, result); | 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); | 4373 | ret = changed_ref(sctx, result); |
4340 | else if (key->type == BTRFS_XATTR_ITEM_KEY) | 4374 | else if (key->type == BTRFS_XATTR_ITEM_KEY) |
4341 | ret = changed_xattr(sctx, result); | 4375 | ret = changed_xattr(sctx, result); |