Btrfs: send, fix infinite loop due to directory rename dependencies
[sfrench/cifs-2.6.git] / fs / btrfs / send.c
index ba8950bfd9c714627b59ff41f4aa4e5e8ffef653..5be83b5a1b43121234c6d0edda9e1c0566f30132 100644 (file)
@@ -1186,9 +1186,9 @@ static int __clone_root_cmp_bsearch(const void *key, const void *elt)
        u64 root = (u64)(uintptr_t)key;
        struct clone_root *cr = (struct clone_root *)elt;
 
-       if (root < cr->root->objectid)
+       if (root < cr->root->root_key.objectid)
                return -1;
-       if (root > cr->root->objectid)
+       if (root > cr->root->root_key.objectid)
                return 1;
        return 0;
 }
@@ -1198,9 +1198,9 @@ static int __clone_root_cmp_sort(const void *e1, const void *e2)
        struct clone_root *cr1 = (struct clone_root *)e1;
        struct clone_root *cr2 = (struct clone_root *)e2;
 
-       if (cr1->root->objectid < cr2->root->objectid)
+       if (cr1->root->root_key.objectid < cr2->root->root_key.objectid)
                return -1;
-       if (cr1->root->objectid > cr2->root->objectid)
+       if (cr1->root->root_key.objectid > cr2->root->root_key.objectid)
                return 1;
        return 0;
 }
@@ -1693,12 +1693,8 @@ static int lookup_dir_item_inode(struct btrfs_root *root,
 
        di = btrfs_lookup_dir_item(NULL, root, path,
                        dir, name, name_len, 0);
-       if (!di) {
-               ret = -ENOENT;
-               goto out;
-       }
-       if (IS_ERR(di)) {
-               ret = PTR_ERR(di);
+       if (IS_ERR_OR_NULL(di)) {
+               ret = di ? PTR_ERR(di) : -ENOENT;
                goto out;
        }
        btrfs_dir_item_key_to_cpu(path->nodes[0], di, &key);
@@ -2346,7 +2342,7 @@ static int send_subvol_begin(struct send_ctx *sctx)
                return -ENOMEM;
        }
 
-       key.objectid = send_root->objectid;
+       key.objectid = send_root->root_key.objectid;
        key.type = BTRFS_ROOT_BACKREF_KEY;
        key.offset = 0;
 
@@ -2362,7 +2358,7 @@ static int send_subvol_begin(struct send_ctx *sctx)
        leaf = path->nodes[0];
        btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
        if (key.type != BTRFS_ROOT_BACKREF_KEY ||
-           key.objectid != send_root->objectid) {
+           key.objectid != send_root->root_key.objectid) {
                ret = -ENOENT;
                goto out;
        }
@@ -3344,7 +3340,8 @@ static void free_pending_move(struct send_ctx *sctx, struct pending_dir_move *m)
        kfree(m);
 }
 
-static void tail_append_pending_moves(struct pending_dir_move *moves,
+static void tail_append_pending_moves(struct send_ctx *sctx,
+                                     struct pending_dir_move *moves,
                                      struct list_head *stack)
 {
        if (list_empty(&moves->list)) {
@@ -3355,6 +3352,10 @@ static void tail_append_pending_moves(struct pending_dir_move *moves,
                list_add_tail(&moves->list, stack);
                list_splice_tail(&list, stack);
        }
+       if (!RB_EMPTY_NODE(&moves->node)) {
+               rb_erase(&moves->node, &sctx->pending_dir_moves);
+               RB_CLEAR_NODE(&moves->node);
+       }
 }
 
 static int apply_children_dir_moves(struct send_ctx *sctx)
@@ -3369,7 +3370,7 @@ static int apply_children_dir_moves(struct send_ctx *sctx)
                return 0;
 
        INIT_LIST_HEAD(&stack);
-       tail_append_pending_moves(pm, &stack);
+       tail_append_pending_moves(sctx, pm, &stack);
 
        while (!list_empty(&stack)) {
                pm = list_first_entry(&stack, struct pending_dir_move, list);
@@ -3380,7 +3381,7 @@ static int apply_children_dir_moves(struct send_ctx *sctx)
                        goto out;
                pm = get_pending_dir_moves(sctx, parent_ino);
                if (pm)
-                       tail_append_pending_moves(pm, &stack);
+                       tail_append_pending_moves(sctx, pm, &stack);
        }
        return 0;
 
@@ -4907,8 +4908,8 @@ static int send_clone(struct send_ctx *sctx,
 
        btrfs_debug(sctx->send_root->fs_info,
                    "send_clone offset=%llu, len=%d, clone_root=%llu, clone_inode=%llu, clone_offset=%llu",
-                   offset, len, clone_root->root->objectid, clone_root->ino,
-                   clone_root->offset);
+                   offset, len, clone_root->root->root_key.objectid,
+                   clone_root->ino, clone_root->offset);
 
        p = fs_path_alloc();
        if (!p)