Btrfs: don't treat top/root directory inode as deleted/reused
authorAlexander Block <ablock84@googlemail.com>
Wed, 1 Aug 2012 12:48:59 +0000 (14:48 +0200)
committerChris Mason <chris.mason@fusionio.com>
Mon, 1 Oct 2012 19:19:00 +0000 (15:19 -0400)
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>
fs/btrfs/send.c

index a4011a9148fdd09d0bda8a719fca91b3c4335df0..d17d75ebc482cf1f0a6d0b2ffda500ad0dfedce8 100644 (file)
@@ -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;
        }