diff options
author | Wang Shilong <wangsl.fnst@cn.fujitsu.com> | 2014-01-07 04:25:19 -0500 |
---|---|---|
committer | Chris Mason <clm@fb.com> | 2014-01-28 16:20:21 -0500 |
commit | 18f687d538449373c37cbe52b03f5f3d42b7c7ed (patch) | |
tree | da340e3522b0e22516af99a7f3cb44d96cfdd6cf /fs/btrfs/transaction.c | |
parent | 896c14f97f700aec6565154f2451605d7c5ce3ed (diff) |
Btrfs: fix protection between send and root deletion
We should gurantee that parent and clone roots can not be destroyed
during send, for this we have two ideas.
1.by holding @subvol_sem, this might be a nightmare, because it will
block all subvolumes deletion for a long time.
2.Miao pointed out we can reuse @send_in_progress, that mean we will
skip snapshot deletion if root sending is in progress.
Here we adopt the second approach since it won't block other subvolumes
deletion for a long time.
Besides in btrfs_clean_one_deleted_snapshot(), we only check first root
, if this root is involved in send, we return directly rather than
continue to check.There are several reasons about it:
1.this case happen seldomly.
2.after sending,cleaner thread can continue to drop that root.
3.make code simple
Cc: David Sterba <dsterba@suse.cz>
Signed-off-by: Wang Shilong <wangsl.fnst@cn.fujitsu.com>
Reviewed-by: Miao Xie <miaox@cn.fujitsu.com>
Signed-off-by: Josef Bacik <jbacik@fb.com>
Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'fs/btrfs/transaction.c')
-rw-r--r-- | fs/btrfs/transaction.c | 13 |
1 files changed, 13 insertions, 0 deletions
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index e5fe801659ba..da2ac4c6d78b 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -1972,6 +1972,19 @@ int btrfs_clean_one_deleted_snapshot(struct btrfs_root *root) | |||
1972 | } | 1972 | } |
1973 | root = list_first_entry(&fs_info->dead_roots, | 1973 | root = list_first_entry(&fs_info->dead_roots, |
1974 | struct btrfs_root, root_list); | 1974 | struct btrfs_root, root_list); |
1975 | /* | ||
1976 | * Make sure root is not involved in send, | ||
1977 | * if we fail with first root, we return | ||
1978 | * directly rather than continue. | ||
1979 | */ | ||
1980 | spin_lock(&root->root_item_lock); | ||
1981 | if (root->send_in_progress) { | ||
1982 | spin_unlock(&fs_info->trans_lock); | ||
1983 | spin_unlock(&root->root_item_lock); | ||
1984 | return 0; | ||
1985 | } | ||
1986 | spin_unlock(&root->root_item_lock); | ||
1987 | |||
1975 | list_del_init(&root->root_list); | 1988 | list_del_init(&root->root_list); |
1976 | spin_unlock(&fs_info->trans_lock); | 1989 | spin_unlock(&fs_info->trans_lock); |
1977 | 1990 | ||