diff options
author | Alexander Block <ablock84@googlemail.com> | 2012-08-01 08:48:59 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@fusionio.com> | 2012-10-01 15:19:00 -0400 |
commit | 6d85ed05e16e7ff747025c8374f23d7d81c98540 (patch) | |
tree | d1c045d6cbc6f7ed4a4e92714664728d57b55fb6 /fs/btrfs/send.c | |
parent | 2981e225f7048b36470383bf5622c42139bd96f7 (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>
Diffstat (limited to 'fs/btrfs/send.c')
-rw-r--r-- | fs/btrfs/send.c | 21 |
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) | |||
2627 | struct btrfs_key loc; | 2627 | struct btrfs_key loc; |
2628 | struct btrfs_dir_item *di; | 2628 | struct btrfs_dir_item *di; |
2629 | 2629 | ||
2630 | /* | ||
2631 | * Don't try to rmdir the top/root subvolume dir. | ||
2632 | */ | ||
2633 | if (dir == BTRFS_FIRST_FREE_OBJECTID) | ||
2634 | return 0; | ||
2635 | |||
2630 | path = alloc_path_for_send(); | 2636 | path = alloc_path_for_send(); |
2631 | if (!path) | 2637 | if (!path) |
2632 | return -ENOMEM; | 2638 | return -ENOMEM; |
@@ -2687,6 +2693,12 @@ static int process_recorded_refs(struct send_ctx *sctx) | |||
2687 | 2693 | ||
2688 | verbose_printk("btrfs: process_recorded_refs %llu\n", sctx->cur_ino); | 2694 | verbose_printk("btrfs: process_recorded_refs %llu\n", sctx->cur_ino); |
2689 | 2695 | ||
2696 | /* | ||
2697 | * This should never happen as the root dir always has the same ref | ||
2698 | * which is always '..' | ||
2699 | */ | ||
2700 | BUG_ON(sctx->cur_ino <= BTRFS_FIRST_FREE_OBJECTID); | ||
2701 | |||
2690 | valid_path = fs_path_alloc(sctx); | 2702 | valid_path = fs_path_alloc(sctx); |
2691 | if (!valid_path) { | 2703 | if (!valid_path) { |
2692 | ret = -ENOMEM; | 2704 | ret = -ENOMEM; |
@@ -4094,7 +4106,14 @@ static int changed_inode(struct send_ctx *sctx, | |||
4094 | 4106 | ||
4095 | right_gen = btrfs_inode_generation(sctx->right_path->nodes[0], | 4107 | right_gen = btrfs_inode_generation(sctx->right_path->nodes[0], |
4096 | right_ii); | 4108 | right_ii); |
4097 | if (left_gen != right_gen) | 4109 | |
4110 | /* | ||
4111 | * The cur_ino = root dir case is special here. We can't treat | ||
4112 | * the inode as deleted+reused because it would generate a | ||
4113 | * stream that tries to delete/mkdir the root dir. | ||
4114 | */ | ||
4115 | if (left_gen != right_gen && | ||
4116 | sctx->cur_ino != BTRFS_FIRST_FREE_OBJECTID) | ||
4098 | sctx->cur_inode_new_gen = 1; | 4117 | sctx->cur_inode_new_gen = 1; |
4099 | } | 4118 | } |
4100 | 4119 | ||