summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Block <ablock84@googlemail.com>2012-08-01 14:48:59 +0200
committerChris Mason <chris.mason@fusionio.com>2012-10-01 15:19:00 -0400
commit6d85ed05e16e7ff747025c8374f23d7d81c98540 (patch)
treed1c045d6cbc6f7ed4a4e92714664728d57b55fb6
parent2981e225f7048b36470383bf5622c42139bd96f7 (diff)
Btrfs: don't treat top/root directory inode as deleted/reused
We can't do the deleted/reused logic for top/root inodes as it would create a stream that tries to delete and recreate the root dir. Reported-by: Alex Lyakas <alex.bolshoy.btrfs@gmail.com> Signed-off-by: Alexander Block <ablock84@googlemail.com>
-rw-r--r--fs/btrfs/send.c21
1 files changed, 20 insertions, 1 deletions
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c
index a4011a9148fd..d17d75ebc482 100644
--- a/fs/btrfs/send.c
+++ b/fs/btrfs/send.c
@@ -2627,6 +2627,12 @@ static int can_rmdir(struct send_ctx *sctx, u64 dir, u64 send_progress)
struct btrfs_key loc;
struct btrfs_dir_item *di;
+ /*
+ * Don't try to rmdir the top/root subvolume dir.
+ */
+ if (dir == BTRFS_FIRST_FREE_OBJECTID)
+ return 0;
+
path = alloc_path_for_send();
if (!path)
return -ENOMEM;
@@ -2687,6 +2693,12 @@ static int process_recorded_refs(struct send_ctx *sctx)
verbose_printk("btrfs: process_recorded_refs %llu\n", sctx->cur_ino);
+ /*
+ * This should never happen as the root dir always has the same ref
+ * which is always '..'
+ */
+ BUG_ON(sctx->cur_ino <= BTRFS_FIRST_FREE_OBJECTID);
+
valid_path = fs_path_alloc(sctx);
if (!valid_path) {
ret = -ENOMEM;
@@ -4094,7 +4106,14 @@ static int changed_inode(struct send_ctx *sctx,
right_gen = btrfs_inode_generation(sctx->right_path->nodes[0],
right_ii);
- if (left_gen != right_gen)
+
+ /*
+ * The cur_ino = root dir case is special here. We can't treat
+ * the inode as deleted+reused because it would generate a
+ * stream that tries to delete/mkdir the root dir.
+ */
+ if (left_gen != right_gen &&
+ sctx->cur_ino != BTRFS_FIRST_FREE_OBJECTID)
sctx->cur_inode_new_gen = 1;
}