u64 parent_ino;
u64 ino;
u64 gen;
- bool is_orphan;
struct list_head update_refs;
};
u64 ino_gen,
u64 parent_ino,
struct list_head *new_refs,
- struct list_head *deleted_refs,
- const bool is_orphan)
+ struct list_head *deleted_refs)
{
struct rb_node **p = &sctx->pending_dir_moves.rb_node;
struct rb_node *parent = NULL;
pm->parent_ino = parent_ino;
pm->ino = ino;
pm->gen = ino_gen;
- pm->is_orphan = is_orphan;
INIT_LIST_HEAD(&pm->list);
INIT_LIST_HEAD(&pm->update_refs);
RB_CLEAR_NODE(&pm->node);
rmdir_ino = dm->rmdir_ino;
free_waiting_dir_move(sctx, dm);
- if (pm->is_orphan) {
- ret = gen_unique_name(sctx, pm->ino,
- pm->gen, from_path);
- } else {
- ret = get_first_ref(sctx->parent_root, pm->ino,
- &parent_ino, &parent_gen, name);
- if (ret < 0)
- goto out;
- ret = get_cur_path(sctx, parent_ino, parent_gen,
- from_path);
- if (ret < 0)
- goto out;
- ret = fs_path_add_path(from_path, name);
- }
+ ret = get_first_ref(sctx->parent_root, pm->ino,
+ &parent_ino, &parent_gen, name);
+ if (ret < 0)
+ goto out;
+
+ ret = get_cur_path(sctx, parent_ino, parent_gen,
+ from_path);
+ if (ret < 0)
+ goto out;
+ ret = fs_path_add_path(from_path, name);
if (ret < 0)
goto out;
LIST_HEAD(deleted_refs);
ASSERT(ancestor > BTRFS_FIRST_FREE_OBJECTID);
ret = add_pending_dir_move(sctx, pm->ino, pm->gen, ancestor,
- &pm->update_refs, &deleted_refs,
- pm->is_orphan);
+ &pm->update_refs, &deleted_refs);
if (ret < 0)
goto out;
if (rmdir_ino) {
return ret;
}
-/*
- * We might need to delay a directory rename even when no ancestor directory
- * (in the send root) with a higher inode number than ours (sctx->cur_ino) was
- * renamed. This happens when we rename a directory to the old name (the name
- * in the parent root) of some other unrelated directory that got its rename
- * delayed due to some ancestor with higher number that got renamed.
- *
- * Example:
- *
- * Parent snapshot:
- * . (ino 256)
- * |---- a/ (ino 257)
- * | |---- file (ino 260)
- * |
- * |---- b/ (ino 258)
- * |---- c/ (ino 259)
- *
- * Send snapshot:
- * . (ino 256)
- * |---- a/ (ino 258)
- * |---- x/ (ino 259)
- * |---- y/ (ino 257)
- * |----- file (ino 260)
- *
- * Here we can not rename 258 from 'b' to 'a' without the rename of inode 257
- * from 'a' to 'x/y' happening first, which in turn depends on the rename of
- * inode 259 from 'c' to 'x'. So the order of rename commands the send stream
- * must issue is:
- *
- * 1 - rename 259 from 'c' to 'x'
- * 2 - rename 257 from 'a' to 'x/y'
- * 3 - rename 258 from 'b' to 'a'
- *
- * Returns 1 if the rename of sctx->cur_ino needs to be delayed, 0 if it can
- * be done right away and < 0 on error.
- */
-static int wait_for_dest_dir_move(struct send_ctx *sctx,
- struct recorded_ref *parent_ref,
- const bool is_orphan)
-{
- struct btrfs_path *path;
- struct btrfs_key key;
- struct btrfs_key di_key;
- struct btrfs_dir_item *di;
- u64 left_gen;
- u64 right_gen;
- int ret = 0;
-
- if (RB_EMPTY_ROOT(&sctx->waiting_dir_moves))
- return 0;
-
- path = alloc_path_for_send();
- if (!path)
- return -ENOMEM;
-
- key.objectid = parent_ref->dir;
- key.type = BTRFS_DIR_ITEM_KEY;
- key.offset = btrfs_name_hash(parent_ref->name, parent_ref->name_len);
-
- ret = btrfs_search_slot(NULL, sctx->parent_root, &key, path, 0, 0);
- if (ret < 0) {
- goto out;
- } else if (ret > 0) {
- ret = 0;
- goto out;
- }
-
- di = btrfs_match_dir_item_name(sctx->parent_root, path,
- parent_ref->name, parent_ref->name_len);
- if (!di) {
- ret = 0;
- goto out;
- }
- /*
- * di_key.objectid has the number of the inode that has a dentry in the
- * parent directory with the same name that sctx->cur_ino is being
- * renamed to. We need to check if that inode is in the send root as
- * well and if it is currently marked as an inode with a pending rename,
- * if it is, we need to delay the rename of sctx->cur_ino as well, so
- * that it happens after that other inode is renamed.
- */
- btrfs_dir_item_key_to_cpu(path->nodes[0], di, &di_key);
- if (di_key.type != BTRFS_INODE_ITEM_KEY) {
- ret = 0;
- goto out;
- }
-
- ret = get_inode_info(sctx->parent_root, di_key.objectid, NULL,
- &left_gen, NULL, NULL, NULL, NULL);
- if (ret < 0)
- goto out;
- ret = get_inode_info(sctx->send_root, di_key.objectid, NULL,
- &right_gen, NULL, NULL, NULL, NULL);
- if (ret < 0) {
- if (ret == -ENOENT)
- ret = 0;
- goto out;
- }
-
- /* Different inode, no need to delay the rename of sctx->cur_ino */
- if (right_gen != left_gen) {
- ret = 0;
- goto out;
- }
-
- if (is_waiting_for_move(sctx, di_key.objectid)) {
- ret = add_pending_dir_move(sctx,
- sctx->cur_ino,
- sctx->cur_inode_gen,
- di_key.objectid,
- &sctx->new_refs,
- &sctx->deleted_refs,
- is_orphan);
- if (!ret)
- ret = 1;
- }
-out:
- btrfs_free_path(path);
- return ret;
-}
-
static int wait_for_parent_move(struct send_ctx *sctx,
struct recorded_ref *parent_ref)
{
sctx->cur_inode_gen,
ino,
&sctx->new_refs,
- &sctx->deleted_refs,
- false);
+ &sctx->deleted_refs);
if (!ret)
ret = 1;
}
int did_overwrite = 0;
int is_orphan = 0;
u64 last_dir_ino_rm = 0;
- bool can_rename = true;
verbose_printk("btrfs: process_recorded_refs %llu\n", sctx->cur_ino);
}
}
- if (S_ISDIR(sctx->cur_inode_mode) && sctx->parent_root) {
- ret = wait_for_dest_dir_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
* it depending on the inode mode.
*/
- if (is_orphan && can_rename) {
+ if (is_orphan) {
ret = send_rename(sctx, valid_path, cur->full_path);
if (ret < 0)
goto out;
ret = fs_path_copy(valid_path, cur->full_path);
if (ret < 0)
goto out;
- } else if (can_rename) {
+ } else {
if (S_ISDIR(sctx->cur_inode_mode)) {
/*
* Dirs can't be linked, so move it. For moved