* after this directory is moved, we can try to rmdir the ino rmdir_ino.
         */
        u64 rmdir_ino;
+       bool orphanized;
 };
 
 struct orphan_dir_info {
                goto out;
        }
 
-       /* we know that it is or will be overwritten. check this now */
-       if (ow_inode < sctx->send_progress)
+       /*
+        * We know that it is or will be overwritten. Check this now.
+        * The current inode being processed might have been the one that caused
+        * inode 'ino' to be orphanized, therefore ow_inode can actually be the
+        * same as sctx->send_progress.
+        */
+       if (ow_inode <= sctx->send_progress)
                ret = 1;
        else
                ret = 0;
        fs_path_reset(dest);
 
        while (!stop && ino != BTRFS_FIRST_FREE_OBJECTID) {
+               struct waiting_dir_move *wdm;
+
                fs_path_reset(name);
 
                if (is_waiting_for_rm(sctx, ino)) {
                        break;
                }
 
-               if (is_waiting_for_move(sctx, ino)) {
+               wdm = get_waiting_dir_move(sctx, ino);
+               if (wdm && wdm->orphanized) {
+                       ret = gen_unique_name(sctx, ino, gen, name);
+                       stop = 1;
+               } else if (wdm) {
                        ret = get_first_ref(sctx->parent_root, ino,
                                            &parent_inode, &parent_gen, name);
                } else {
        return entry != NULL;
 }
 
-static int add_waiting_dir_move(struct send_ctx *sctx, u64 ino)
+static int add_waiting_dir_move(struct send_ctx *sctx, u64 ino, bool orphanized)
 {
        struct rb_node **p = &sctx->waiting_dir_moves.rb_node;
        struct rb_node *parent = NULL;
                return -ENOMEM;
        dm->ino = ino;
        dm->rmdir_ino = 0;
+       dm->orphanized = orphanized;
 
        while (*p) {
                parent = *p;
                        goto out;
        }
 
-       ret = add_waiting_dir_move(sctx, pm->ino);
+       ret = add_waiting_dir_move(sctx, pm->ino, is_orphan);
        if (ret)
                goto out;
 
 }
 
 static int wait_for_parent_move(struct send_ctx *sctx,
-                               struct recorded_ref *parent_ref)
+                               struct recorded_ref *parent_ref,
+                               const bool is_orphan)
 {
        int ret = 0;
        u64 ino = parent_ref->dir;
                                           ino,
                                           &sctx->new_refs,
                                           &sctx->deleted_refs,
-                                          false);
+                                          is_orphan);
                if (!ret)
                        ret = 1;
        }
                        }
                }
 
+               if (S_ISDIR(sctx->cur_inode_mode) && sctx->parent_root &&
+                   can_rename) {
+                       ret = wait_for_parent_move(sctx, cur, is_orphan);
+                       if (ret < 0)
+                               goto out;
+                       if (ret == 1) {
+                               can_rename = false;
+                               *pending_move = 1;
+                       }
+               }
+
                /*
                 * link/move the ref to the new place. If we have an orphan
                 * inode, move it and update valid_path. If not, link or move
                                 * dirs, we always have one new and one deleted
                                 * ref. The deleted ref is ignored later.
                                 */
-                               ret = wait_for_parent_move(sctx, cur);
-                               if (ret < 0)
-                                       goto out;
-                               if (ret) {
-                                       *pending_move = 1;
-                               } else {
-                                       ret = send_rename(sctx, valid_path,
-                                                         cur->full_path);
-                                       if (!ret)
-                                               ret = fs_path_copy(valid_path,
-                                                              cur->full_path);
-                               }
+                               ret = send_rename(sctx, valid_path,
+                                                 cur->full_path);
+                               if (!ret)
+                                       ret = fs_path_copy(valid_path,
+                                                          cur->full_path);
                                if (ret < 0)
                                        goto out;
                        } else {