Commit c992ec94f24c3e7135d6c23860615f269f0b1d87

Authored by Filipe Manana
Committed by Chris Mason
1 parent b46ab97bcd

Btrfs: send, account for orphan directories when building path strings

If we have directories with a pending move/rename operation, we must take into
account any orphan directories that got created before executing the pending
move/rename. Those orphan directories are directories with an inode number higher
then the current send progress and that don't exist in the parent snapshot, they
are created before current progress reaches their inode number, with a generated
name of the form oN-M-I and at the root of the filesystem tree, and later when
progress matches their inode number, moved/renamed to their final location.

Reproducer:

          $ mkfs.btrfs -f /dev/sdd
          $ mount /dev/sdd /mnt

          $ mkdir -p /mnt/a/b/c/d
          $ mkdir /mnt/a/b/e
          $ mv /mnt/a/b/c /mnt/a/b/e/CC
          $ mkdir /mnt/a/b/e/CC/d/f
	  $ mkdir /mnt/a/g

          $ btrfs subvolume snapshot -r /mnt /mnt/snap1
          $ btrfs send /mnt/snap1 -f /tmp/base.send

          $ mkdir /mnt/a/g/h
	  $ mv /mnt/a/b/e /mnt/a/g/h/EE
          $ mv /mnt/a/g/h/EE/CC/d /mnt/a/g/h/EE/DD

          $ btrfs subvolume snapshot -r /mnt /mnt/snap2
          $ btrfs send -p /mnt/snap1 /mnt/snap2 -f /tmp/incremental.send

The second receive command failed with the following error:

    ERROR: rename a/b/e/CC/d -> o264-7-0/EE/DD failed. No such file or directory

A test case for xfstests follows soon.

Signed-off-by: Filipe David Borba Manana <fdmanana@gmail.com>
Signed-off-by: Chris Mason <clm@fb.com>

Showing 1 changed file with 9 additions and 24 deletions Side-by-side Diff

... ... @@ -3055,32 +3055,17 @@
3055 3055 if (ret < 0)
3056 3056 goto out;
3057 3057  
3058   - if (parent_ino == sctx->cur_ino) {
3059   - /* child only renamed, not moved */
3060   - ASSERT(parent_gen == sctx->cur_inode_gen);
3061   - ret = get_cur_path(sctx, sctx->cur_ino, sctx->cur_inode_gen,
3062   - from_path);
3063   - if (ret < 0)
3064   - goto out;
3065   - ret = fs_path_add_path(from_path, name);
3066   - if (ret < 0)
3067   - goto out;
3068   - } else {
3069   - /* child moved and maybe renamed too */
3070   - sctx->send_progress = pm->ino;
3071   - ret = get_cur_path(sctx, pm->ino, pm->gen, from_path);
3072   - if (ret < 0)
3073   - goto out;
3074   - }
  3058 + ret = get_cur_path(sctx, parent_ino, parent_gen,
  3059 + from_path);
  3060 + if (ret < 0)
  3061 + goto out;
  3062 + ret = fs_path_add_path(from_path, name);
  3063 + if (ret < 0)
  3064 + goto out;
3075 3065  
3076   - fs_path_free(name);
  3066 + fs_path_reset(name);
  3067 + to_path = name;
3077 3068 name = NULL;
3078   -
3079   - to_path = fs_path_alloc();
3080   - if (!to_path) {
3081   - ret = -ENOMEM;
3082   - goto out;
3083   - }
3084 3069  
3085 3070 sctx->send_progress = sctx->cur_ino + 1;
3086 3071 ret = get_cur_path(sctx, pm->ino, pm->gen, to_path);