aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/send.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-09-12 12:58:51 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-09-12 12:58:51 -0400
commitb7c09ad4014e3678e8cc01fdf663c9f43b272dc6 (patch)
tree1edb073b0a76ce1530cb31c113f9e741e33ece0e /fs/btrfs/send.c
parent1812997720ab90d029548778c55d7315555e1fef (diff)
parentd7396f07358a7c6e22c238d36d1d85f9d652a414 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs
Pull btrfs updates from Chris Mason: "This is against 3.11-rc7, but was pulled and tested against your tree as of yesterday. We do have two small incrementals queued up, but I wanted to get this bunch out the door before I hop on an airplane. This is a fairly large batch of fixes, performance improvements, and cleanups from the usual Btrfs suspects. We've included Stefan Behren's work to index subvolume UUIDs, which is targeted at speeding up send/receive with many subvolumes or snapshots in place. It closes a long standing performance issue that was built in to the disk format. Mark Fasheh's offline dedup work is also here. In this case offline means the FS is mounted and active, but the dedup work is not done inline during file IO. This is a building block where utilities are able to ask the FS to dedup a series of extents. The kernel takes care of verifying the data involved really is the same. Today this involves reading both extents, but we'll continue to evolve the patches" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs: (118 commits) Btrfs: optimize key searches in btrfs_search_slot Btrfs: don't use an async starter for most of our workers Btrfs: only update disk_i_size as we remove extents Btrfs: fix deadlock in uuid scan kthread Btrfs: stop refusing the relocation of chunk 0 Btrfs: fix memory leak of uuid_root in free_fs_info btrfs: reuse kbasename helper btrfs: return btrfs error code for dev excl ops err Btrfs: allow partial ordered extent completion Btrfs: convert all bug_ons in free-space-cache.c Btrfs: add support for asserts Btrfs: adjust the fs_devices->missing count on unmount Btrf: cleanup: don't check for root_refs == 0 twice Btrfs: fix for patch "cleanup: don't check the same thing twice" Btrfs: get rid of one BUG() in write_all_supers() Btrfs: allocate prelim_ref with a slab allocater Btrfs: pass gfp_t to __add_prelim_ref() to avoid always using GFP_ATOMIC Btrfs: fix race conditions in BTRFS_IOC_FS_INFO ioctl Btrfs: fix race between removing a dev and writing sbs Btrfs: remove ourselves from the cluster list under lock ...
Diffstat (limited to 'fs/btrfs/send.c')
-rw-r--r--fs/btrfs/send.c240
1 files changed, 192 insertions, 48 deletions
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c
index 2e14fd89a8b4..e46e0ed74925 100644
--- a/fs/btrfs/send.c
+++ b/fs/btrfs/send.c
@@ -26,6 +26,7 @@
26#include <linux/radix-tree.h> 26#include <linux/radix-tree.h>
27#include <linux/crc32c.h> 27#include <linux/crc32c.h>
28#include <linux/vmalloc.h> 28#include <linux/vmalloc.h>
29#include <linux/string.h>
29 30
30#include "send.h" 31#include "send.h"
31#include "backref.h" 32#include "backref.h"
@@ -54,8 +55,8 @@ struct fs_path {
54 55
55 char *buf; 56 char *buf;
56 int buf_len; 57 int buf_len;
57 int reversed:1; 58 unsigned int reversed:1;
58 int virtual_mem:1; 59 unsigned int virtual_mem:1;
59 char inline_buf[]; 60 char inline_buf[];
60 }; 61 };
61 char pad[PAGE_SIZE]; 62 char pad[PAGE_SIZE];
@@ -1668,6 +1669,7 @@ static int will_overwrite_ref(struct send_ctx *sctx, u64 dir, u64 dir_gen,
1668 u64 *who_ino, u64 *who_gen) 1669 u64 *who_ino, u64 *who_gen)
1669{ 1670{
1670 int ret = 0; 1671 int ret = 0;
1672 u64 gen;
1671 u64 other_inode = 0; 1673 u64 other_inode = 0;
1672 u8 other_type = 0; 1674 u8 other_type = 0;
1673 1675
@@ -1678,6 +1680,24 @@ static int will_overwrite_ref(struct send_ctx *sctx, u64 dir, u64 dir_gen,
1678 if (ret <= 0) 1680 if (ret <= 0)
1679 goto out; 1681 goto out;
1680 1682
1683 /*
1684 * If we have a parent root we need to verify that the parent dir was
1685 * not delted and then re-created, if it was then we have no overwrite
1686 * and we can just unlink this entry.
1687 */
1688 if (sctx->parent_root) {
1689 ret = get_inode_info(sctx->parent_root, dir, NULL, &gen, NULL,
1690 NULL, NULL, NULL);
1691 if (ret < 0 && ret != -ENOENT)
1692 goto out;
1693 if (ret) {
1694 ret = 0;
1695 goto out;
1696 }
1697 if (gen != dir_gen)
1698 goto out;
1699 }
1700
1681 ret = lookup_dir_item_inode(sctx->parent_root, dir, name, name_len, 1701 ret = lookup_dir_item_inode(sctx->parent_root, dir, name, name_len,
1682 &other_inode, &other_type); 1702 &other_inode, &other_type);
1683 if (ret < 0 && ret != -ENOENT) 1703 if (ret < 0 && ret != -ENOENT)
@@ -2519,7 +2539,8 @@ static int did_create_dir(struct send_ctx *sctx, u64 dir)
2519 di = btrfs_item_ptr(eb, slot, struct btrfs_dir_item); 2539 di = btrfs_item_ptr(eb, slot, struct btrfs_dir_item);
2520 btrfs_dir_item_key_to_cpu(eb, di, &di_key); 2540 btrfs_dir_item_key_to_cpu(eb, di, &di_key);
2521 2541
2522 if (di_key.objectid < sctx->send_progress) { 2542 if (di_key.type != BTRFS_ROOT_ITEM_KEY &&
2543 di_key.objectid < sctx->send_progress) {
2523 ret = 1; 2544 ret = 1;
2524 goto out; 2545 goto out;
2525 } 2546 }
@@ -2581,7 +2602,6 @@ static int record_ref(struct list_head *head, u64 dir,
2581 u64 dir_gen, struct fs_path *path) 2602 u64 dir_gen, struct fs_path *path)
2582{ 2603{
2583 struct recorded_ref *ref; 2604 struct recorded_ref *ref;
2584 char *tmp;
2585 2605
2586 ref = kmalloc(sizeof(*ref), GFP_NOFS); 2606 ref = kmalloc(sizeof(*ref), GFP_NOFS);
2587 if (!ref) 2607 if (!ref)
@@ -2591,25 +2611,35 @@ static int record_ref(struct list_head *head, u64 dir,
2591 ref->dir_gen = dir_gen; 2611 ref->dir_gen = dir_gen;
2592 ref->full_path = path; 2612 ref->full_path = path;
2593 2613
2594 tmp = strrchr(ref->full_path->start, '/'); 2614 ref->name = (char *)kbasename(ref->full_path->start);
2595 if (!tmp) { 2615 ref->name_len = ref->full_path->end - ref->name;
2596 ref->name_len = ref->full_path->end - ref->full_path->start; 2616 ref->dir_path = ref->full_path->start;
2597 ref->name = ref->full_path->start; 2617 if (ref->name == ref->full_path->start)
2598 ref->dir_path_len = 0; 2618 ref->dir_path_len = 0;
2599 ref->dir_path = ref->full_path->start; 2619 else
2600 } else {
2601 tmp++;
2602 ref->name_len = ref->full_path->end - tmp;
2603 ref->name = tmp;
2604 ref->dir_path = ref->full_path->start;
2605 ref->dir_path_len = ref->full_path->end - 2620 ref->dir_path_len = ref->full_path->end -
2606 ref->full_path->start - 1 - ref->name_len; 2621 ref->full_path->start - 1 - ref->name_len;
2607 }
2608 2622
2609 list_add_tail(&ref->list, head); 2623 list_add_tail(&ref->list, head);
2610 return 0; 2624 return 0;
2611} 2625}
2612 2626
2627static int dup_ref(struct recorded_ref *ref, struct list_head *list)
2628{
2629 struct recorded_ref *new;
2630
2631 new = kmalloc(sizeof(*ref), GFP_NOFS);
2632 if (!new)
2633 return -ENOMEM;
2634
2635 new->dir = ref->dir;
2636 new->dir_gen = ref->dir_gen;
2637 new->full_path = NULL;
2638 INIT_LIST_HEAD(&new->list);
2639 list_add_tail(&new->list, list);
2640 return 0;
2641}
2642
2613static void __free_recorded_refs(struct list_head *head) 2643static void __free_recorded_refs(struct list_head *head)
2614{ 2644{
2615 struct recorded_ref *cur; 2645 struct recorded_ref *cur;
@@ -2724,9 +2754,7 @@ static int process_recorded_refs(struct send_ctx *sctx)
2724 int ret = 0; 2754 int ret = 0;
2725 struct recorded_ref *cur; 2755 struct recorded_ref *cur;
2726 struct recorded_ref *cur2; 2756 struct recorded_ref *cur2;
2727 struct ulist *check_dirs = NULL; 2757 struct list_head check_dirs;
2728 struct ulist_iterator uit;
2729 struct ulist_node *un;
2730 struct fs_path *valid_path = NULL; 2758 struct fs_path *valid_path = NULL;
2731 u64 ow_inode = 0; 2759 u64 ow_inode = 0;
2732 u64 ow_gen; 2760 u64 ow_gen;
@@ -2740,6 +2768,7 @@ verbose_printk("btrfs: process_recorded_refs %llu\n", sctx->cur_ino);
2740 * which is always '..' 2768 * which is always '..'
2741 */ 2769 */
2742 BUG_ON(sctx->cur_ino <= BTRFS_FIRST_FREE_OBJECTID); 2770 BUG_ON(sctx->cur_ino <= BTRFS_FIRST_FREE_OBJECTID);
2771 INIT_LIST_HEAD(&check_dirs);
2743 2772
2744 valid_path = fs_path_alloc(); 2773 valid_path = fs_path_alloc();
2745 if (!valid_path) { 2774 if (!valid_path) {
@@ -2747,12 +2776,6 @@ verbose_printk("btrfs: process_recorded_refs %llu\n", sctx->cur_ino);
2747 goto out; 2776 goto out;
2748 } 2777 }
2749 2778
2750 check_dirs = ulist_alloc(GFP_NOFS);
2751 if (!check_dirs) {
2752 ret = -ENOMEM;
2753 goto out;
2754 }
2755
2756 /* 2779 /*
2757 * First, check if the first ref of the current inode was overwritten 2780 * First, check if the first ref of the current inode was overwritten
2758 * before. If yes, we know that the current inode was already orphanized 2781 * before. If yes, we know that the current inode was already orphanized
@@ -2889,8 +2912,7 @@ verbose_printk("btrfs: process_recorded_refs %llu\n", sctx->cur_ino);
2889 goto out; 2912 goto out;
2890 } 2913 }
2891 } 2914 }
2892 ret = ulist_add(check_dirs, cur->dir, cur->dir_gen, 2915 ret = dup_ref(cur, &check_dirs);
2893 GFP_NOFS);
2894 if (ret < 0) 2916 if (ret < 0)
2895 goto out; 2917 goto out;
2896 } 2918 }
@@ -2918,8 +2940,7 @@ verbose_printk("btrfs: process_recorded_refs %llu\n", sctx->cur_ino);
2918 } 2940 }
2919 2941
2920 list_for_each_entry(cur, &sctx->deleted_refs, list) { 2942 list_for_each_entry(cur, &sctx->deleted_refs, list) {
2921 ret = ulist_add(check_dirs, cur->dir, cur->dir_gen, 2943 ret = dup_ref(cur, &check_dirs);
2922 GFP_NOFS);
2923 if (ret < 0) 2944 if (ret < 0)
2924 goto out; 2945 goto out;
2925 } 2946 }
@@ -2930,8 +2951,7 @@ verbose_printk("btrfs: process_recorded_refs %llu\n", sctx->cur_ino);
2930 */ 2951 */
2931 cur = list_entry(sctx->deleted_refs.next, struct recorded_ref, 2952 cur = list_entry(sctx->deleted_refs.next, struct recorded_ref,
2932 list); 2953 list);
2933 ret = ulist_add(check_dirs, cur->dir, cur->dir_gen, 2954 ret = dup_ref(cur, &check_dirs);
2934 GFP_NOFS);
2935 if (ret < 0) 2955 if (ret < 0)
2936 goto out; 2956 goto out;
2937 } else if (!S_ISDIR(sctx->cur_inode_mode)) { 2957 } else if (!S_ISDIR(sctx->cur_inode_mode)) {
@@ -2951,12 +2971,10 @@ verbose_printk("btrfs: process_recorded_refs %llu\n", sctx->cur_ino);
2951 if (ret < 0) 2971 if (ret < 0)
2952 goto out; 2972 goto out;
2953 } 2973 }
2954 ret = ulist_add(check_dirs, cur->dir, cur->dir_gen, 2974 ret = dup_ref(cur, &check_dirs);
2955 GFP_NOFS);
2956 if (ret < 0) 2975 if (ret < 0)
2957 goto out; 2976 goto out;
2958 } 2977 }
2959
2960 /* 2978 /*
2961 * If the inode is still orphan, unlink the orphan. This may 2979 * If the inode is still orphan, unlink the orphan. This may
2962 * happen when a previous inode did overwrite the first ref 2980 * happen when a previous inode did overwrite the first ref
@@ -2978,33 +2996,32 @@ verbose_printk("btrfs: process_recorded_refs %llu\n", sctx->cur_ino);
2978 * deletion and if it's finally possible to perform the rmdir now. 2996 * deletion and if it's finally possible to perform the rmdir now.
2979 * We also update the inode stats of the parent dirs here. 2997 * We also update the inode stats of the parent dirs here.
2980 */ 2998 */
2981 ULIST_ITER_INIT(&uit); 2999 list_for_each_entry(cur, &check_dirs, list) {
2982 while ((un = ulist_next(check_dirs, &uit))) {
2983 /* 3000 /*
2984 * In case we had refs into dirs that were not processed yet, 3001 * In case we had refs into dirs that were not processed yet,
2985 * we don't need to do the utime and rmdir logic for these dirs. 3002 * we don't need to do the utime and rmdir logic for these dirs.
2986 * The dir will be processed later. 3003 * The dir will be processed later.
2987 */ 3004 */
2988 if (un->val > sctx->cur_ino) 3005 if (cur->dir > sctx->cur_ino)
2989 continue; 3006 continue;
2990 3007
2991 ret = get_cur_inode_state(sctx, un->val, un->aux); 3008 ret = get_cur_inode_state(sctx, cur->dir, cur->dir_gen);
2992 if (ret < 0) 3009 if (ret < 0)
2993 goto out; 3010 goto out;
2994 3011
2995 if (ret == inode_state_did_create || 3012 if (ret == inode_state_did_create ||
2996 ret == inode_state_no_change) { 3013 ret == inode_state_no_change) {
2997 /* TODO delayed utimes */ 3014 /* TODO delayed utimes */
2998 ret = send_utimes(sctx, un->val, un->aux); 3015 ret = send_utimes(sctx, cur->dir, cur->dir_gen);
2999 if (ret < 0) 3016 if (ret < 0)
3000 goto out; 3017 goto out;
3001 } else if (ret == inode_state_did_delete) { 3018 } else if (ret == inode_state_did_delete) {
3002 ret = can_rmdir(sctx, un->val, sctx->cur_ino); 3019 ret = can_rmdir(sctx, cur->dir, sctx->cur_ino);
3003 if (ret < 0) 3020 if (ret < 0)
3004 goto out; 3021 goto out;
3005 if (ret) { 3022 if (ret) {
3006 ret = get_cur_path(sctx, un->val, un->aux, 3023 ret = get_cur_path(sctx, cur->dir,
3007 valid_path); 3024 cur->dir_gen, valid_path);
3008 if (ret < 0) 3025 if (ret < 0)
3009 goto out; 3026 goto out;
3010 ret = send_rmdir(sctx, valid_path); 3027 ret = send_rmdir(sctx, valid_path);
@@ -3017,8 +3034,8 @@ verbose_printk("btrfs: process_recorded_refs %llu\n", sctx->cur_ino);
3017 ret = 0; 3034 ret = 0;
3018 3035
3019out: 3036out:
3037 __free_recorded_refs(&check_dirs);
3020 free_recorded_refs(sctx); 3038 free_recorded_refs(sctx);
3021 ulist_free(check_dirs);
3022 fs_path_free(valid_path); 3039 fs_path_free(valid_path);
3023 return ret; 3040 return ret;
3024} 3041}
@@ -3119,6 +3136,8 @@ out:
3119 3136
3120struct find_ref_ctx { 3137struct find_ref_ctx {
3121 u64 dir; 3138 u64 dir;
3139 u64 dir_gen;
3140 struct btrfs_root *root;
3122 struct fs_path *name; 3141 struct fs_path *name;
3123 int found_idx; 3142 int found_idx;
3124}; 3143};
@@ -3128,9 +3147,21 @@ static int __find_iref(int num, u64 dir, int index,
3128 void *ctx_) 3147 void *ctx_)
3129{ 3148{
3130 struct find_ref_ctx *ctx = ctx_; 3149 struct find_ref_ctx *ctx = ctx_;
3150 u64 dir_gen;
3151 int ret;
3131 3152
3132 if (dir == ctx->dir && fs_path_len(name) == fs_path_len(ctx->name) && 3153 if (dir == ctx->dir && fs_path_len(name) == fs_path_len(ctx->name) &&
3133 strncmp(name->start, ctx->name->start, fs_path_len(name)) == 0) { 3154 strncmp(name->start, ctx->name->start, fs_path_len(name)) == 0) {
3155 /*
3156 * To avoid doing extra lookups we'll only do this if everything
3157 * else matches.
3158 */
3159 ret = get_inode_info(ctx->root, dir, NULL, &dir_gen, NULL,
3160 NULL, NULL, NULL);
3161 if (ret)
3162 return ret;
3163 if (dir_gen != ctx->dir_gen)
3164 return 0;
3134 ctx->found_idx = num; 3165 ctx->found_idx = num;
3135 return 1; 3166 return 1;
3136 } 3167 }
@@ -3140,14 +3171,16 @@ static int __find_iref(int num, u64 dir, int index,
3140static int find_iref(struct btrfs_root *root, 3171static int find_iref(struct btrfs_root *root,
3141 struct btrfs_path *path, 3172 struct btrfs_path *path,
3142 struct btrfs_key *key, 3173 struct btrfs_key *key,
3143 u64 dir, struct fs_path *name) 3174 u64 dir, u64 dir_gen, struct fs_path *name)
3144{ 3175{
3145 int ret; 3176 int ret;
3146 struct find_ref_ctx ctx; 3177 struct find_ref_ctx ctx;
3147 3178
3148 ctx.dir = dir; 3179 ctx.dir = dir;
3149 ctx.name = name; 3180 ctx.name = name;
3181 ctx.dir_gen = dir_gen;
3150 ctx.found_idx = -1; 3182 ctx.found_idx = -1;
3183 ctx.root = root;
3151 3184
3152 ret = iterate_inode_ref(root, path, key, 0, __find_iref, &ctx); 3185 ret = iterate_inode_ref(root, path, key, 0, __find_iref, &ctx);
3153 if (ret < 0) 3186 if (ret < 0)
@@ -3163,11 +3196,17 @@ static int __record_changed_new_ref(int num, u64 dir, int index,
3163 struct fs_path *name, 3196 struct fs_path *name,
3164 void *ctx) 3197 void *ctx)
3165{ 3198{
3199 u64 dir_gen;
3166 int ret; 3200 int ret;
3167 struct send_ctx *sctx = ctx; 3201 struct send_ctx *sctx = ctx;
3168 3202
3203 ret = get_inode_info(sctx->send_root, dir, NULL, &dir_gen, NULL,
3204 NULL, NULL, NULL);
3205 if (ret)
3206 return ret;
3207
3169 ret = find_iref(sctx->parent_root, sctx->right_path, 3208 ret = find_iref(sctx->parent_root, sctx->right_path,
3170 sctx->cmp_key, dir, name); 3209 sctx->cmp_key, dir, dir_gen, name);
3171 if (ret == -ENOENT) 3210 if (ret == -ENOENT)
3172 ret = __record_new_ref(num, dir, index, name, sctx); 3211 ret = __record_new_ref(num, dir, index, name, sctx);
3173 else if (ret > 0) 3212 else if (ret > 0)
@@ -3180,11 +3219,17 @@ static int __record_changed_deleted_ref(int num, u64 dir, int index,
3180 struct fs_path *name, 3219 struct fs_path *name,
3181 void *ctx) 3220 void *ctx)
3182{ 3221{
3222 u64 dir_gen;
3183 int ret; 3223 int ret;
3184 struct send_ctx *sctx = ctx; 3224 struct send_ctx *sctx = ctx;
3185 3225
3226 ret = get_inode_info(sctx->parent_root, dir, NULL, &dir_gen, NULL,
3227 NULL, NULL, NULL);
3228 if (ret)
3229 return ret;
3230
3186 ret = find_iref(sctx->send_root, sctx->left_path, sctx->cmp_key, 3231 ret = find_iref(sctx->send_root, sctx->left_path, sctx->cmp_key,
3187 dir, name); 3232 dir, dir_gen, name);
3188 if (ret == -ENOENT) 3233 if (ret == -ENOENT)
3189 ret = __record_deleted_ref(num, dir, index, name, sctx); 3234 ret = __record_deleted_ref(num, dir, index, name, sctx);
3190 else if (ret > 0) 3235 else if (ret > 0)
@@ -3869,7 +3914,8 @@ static int is_extent_unchanged(struct send_ctx *sctx,
3869 btrfs_item_key_to_cpu(eb, &found_key, slot); 3914 btrfs_item_key_to_cpu(eb, &found_key, slot);
3870 if (found_key.objectid != key.objectid || 3915 if (found_key.objectid != key.objectid ||
3871 found_key.type != key.type) { 3916 found_key.type != key.type) {
3872 ret = 0; 3917 /* If we're a hole then just pretend nothing changed */
3918 ret = (left_disknr) ? 0 : 1;
3873 goto out; 3919 goto out;
3874 } 3920 }
3875 3921
@@ -3895,7 +3941,8 @@ static int is_extent_unchanged(struct send_ctx *sctx,
3895 * This may only happen on the first iteration. 3941 * This may only happen on the first iteration.
3896 */ 3942 */
3897 if (found_key.offset + right_len <= ekey->offset) { 3943 if (found_key.offset + right_len <= ekey->offset) {
3898 ret = 0; 3944 /* If we're a hole just pretend nothing changed */
3945 ret = (left_disknr) ? 0 : 1;
3899 goto out; 3946 goto out;
3900 } 3947 }
3901 3948
@@ -3960,8 +4007,8 @@ static int process_extent(struct send_ctx *sctx,
3960 struct btrfs_path *path, 4007 struct btrfs_path *path,
3961 struct btrfs_key *key) 4008 struct btrfs_key *key)
3962{ 4009{
3963 int ret = 0;
3964 struct clone_root *found_clone = NULL; 4010 struct clone_root *found_clone = NULL;
4011 int ret = 0;
3965 4012
3966 if (S_ISLNK(sctx->cur_inode_mode)) 4013 if (S_ISLNK(sctx->cur_inode_mode))
3967 return 0; 4014 return 0;
@@ -3974,6 +4021,32 @@ static int process_extent(struct send_ctx *sctx,
3974 ret = 0; 4021 ret = 0;
3975 goto out; 4022 goto out;
3976 } 4023 }
4024 } else {
4025 struct btrfs_file_extent_item *ei;
4026 u8 type;
4027
4028 ei = btrfs_item_ptr(path->nodes[0], path->slots[0],
4029 struct btrfs_file_extent_item);
4030 type = btrfs_file_extent_type(path->nodes[0], ei);
4031 if (type == BTRFS_FILE_EXTENT_PREALLOC ||
4032 type == BTRFS_FILE_EXTENT_REG) {
4033 /*
4034 * The send spec does not have a prealloc command yet,
4035 * so just leave a hole for prealloc'ed extents until
4036 * we have enough commands queued up to justify rev'ing
4037 * the send spec.
4038 */
4039 if (type == BTRFS_FILE_EXTENT_PREALLOC) {
4040 ret = 0;
4041 goto out;
4042 }
4043
4044 /* Have a hole, just skip it. */
4045 if (btrfs_file_extent_disk_bytenr(path->nodes[0], ei) == 0) {
4046 ret = 0;
4047 goto out;
4048 }
4049 }
3977 } 4050 }
3978 4051
3979 ret = find_extent_clone(sctx, path, key->objectid, key->offset, 4052 ret = find_extent_clone(sctx, path, key->objectid, key->offset,
@@ -4361,6 +4434,64 @@ static int changed_extent(struct send_ctx *sctx,
4361 return ret; 4434 return ret;
4362} 4435}
4363 4436
4437static int dir_changed(struct send_ctx *sctx, u64 dir)
4438{
4439 u64 orig_gen, new_gen;
4440 int ret;
4441
4442 ret = get_inode_info(sctx->send_root, dir, NULL, &new_gen, NULL, NULL,
4443 NULL, NULL);
4444 if (ret)
4445 return ret;
4446
4447 ret = get_inode_info(sctx->parent_root, dir, NULL, &orig_gen, NULL,
4448 NULL, NULL, NULL);
4449 if (ret)
4450 return ret;
4451
4452 return (orig_gen != new_gen) ? 1 : 0;
4453}
4454
4455static int compare_refs(struct send_ctx *sctx, struct btrfs_path *path,
4456 struct btrfs_key *key)
4457{
4458 struct btrfs_inode_extref *extref;
4459 struct extent_buffer *leaf;
4460 u64 dirid = 0, last_dirid = 0;
4461 unsigned long ptr;
4462 u32 item_size;
4463 u32 cur_offset = 0;
4464 int ref_name_len;
4465 int ret = 0;
4466
4467 /* Easy case, just check this one dirid */
4468 if (key->type == BTRFS_INODE_REF_KEY) {
4469 dirid = key->offset;
4470
4471 ret = dir_changed(sctx, dirid);
4472 goto out;
4473 }
4474
4475 leaf = path->nodes[0];
4476 item_size = btrfs_item_size_nr(leaf, path->slots[0]);
4477 ptr = btrfs_item_ptr_offset(leaf, path->slots[0]);
4478 while (cur_offset < item_size) {
4479 extref = (struct btrfs_inode_extref *)(ptr +
4480 cur_offset);
4481 dirid = btrfs_inode_extref_parent(leaf, extref);
4482 ref_name_len = btrfs_inode_extref_name_len(leaf, extref);
4483 cur_offset += ref_name_len + sizeof(*extref);
4484 if (dirid == last_dirid)
4485 continue;
4486 ret = dir_changed(sctx, dirid);
4487 if (ret)
4488 break;
4489 last_dirid = dirid;
4490 }
4491out:
4492 return ret;
4493}
4494
4364/* 4495/*
4365 * Updates compare related fields in sctx and simply forwards to the actual 4496 * Updates compare related fields in sctx and simply forwards to the actual
4366 * changed_xxx functions. 4497 * changed_xxx functions.
@@ -4376,6 +4507,19 @@ static int changed_cb(struct btrfs_root *left_root,
4376 int ret = 0; 4507 int ret = 0;
4377 struct send_ctx *sctx = ctx; 4508 struct send_ctx *sctx = ctx;
4378 4509
4510 if (result == BTRFS_COMPARE_TREE_SAME) {
4511 if (key->type != BTRFS_INODE_REF_KEY &&
4512 key->type != BTRFS_INODE_EXTREF_KEY)
4513 return 0;
4514 ret = compare_refs(sctx, left_path, key);
4515 if (!ret)
4516 return 0;
4517 if (ret < 0)
4518 return ret;
4519 result = BTRFS_COMPARE_TREE_CHANGED;
4520 ret = 0;
4521 }
4522
4379 sctx->left_path = left_path; 4523 sctx->left_path = left_path;
4380 sctx->right_path = right_path; 4524 sctx->right_path = right_path;
4381 sctx->cmp_key = key; 4525 sctx->cmp_key = key;