diff options
author | Miao Xie <miaox@cn.fujitsu.com> | 2013-02-28 05:05:36 -0500 |
---|---|---|
committer | Josef Bacik <jbacik@fusionio.com> | 2013-02-28 13:33:55 -0500 |
commit | c58aaad2ac46f8dbce9ab7f7a7a3726e332a56ee (patch) | |
tree | 6597760ea9f3c39f22f3ebada06b27ee59b8ea34 | |
parent | d5c1207017cd8387b4d3224dd7ab6cf5cd7f1c9a (diff) |
Btrfs: fix wrong reserved space when deleting a snapshot/subvolume
When deleting a snapshot/subvolume, we need remove root ref/backref,
dir entries and update the dir inode, so we must reserve free space
for those operations.
Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
Signed-off-by: Josef Bacik <jbacik@fusionio.com>
-rw-r--r-- | fs/btrfs/ioctl.c | 21 |
1 files changed, 19 insertions, 2 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 56d92549389c..b908960c9746 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -2064,6 +2064,8 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file, | |||
2064 | struct btrfs_root *dest = NULL; | 2064 | struct btrfs_root *dest = NULL; |
2065 | struct btrfs_ioctl_vol_args *vol_args; | 2065 | struct btrfs_ioctl_vol_args *vol_args; |
2066 | struct btrfs_trans_handle *trans; | 2066 | struct btrfs_trans_handle *trans; |
2067 | struct btrfs_block_rsv block_rsv; | ||
2068 | u64 qgroup_reserved; | ||
2067 | int namelen; | 2069 | int namelen; |
2068 | int ret; | 2070 | int ret; |
2069 | int err = 0; | 2071 | int err = 0; |
@@ -2153,12 +2155,23 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file, | |||
2153 | if (err) | 2155 | if (err) |
2154 | goto out_up_write; | 2156 | goto out_up_write; |
2155 | 2157 | ||
2158 | btrfs_init_block_rsv(&block_rsv, BTRFS_BLOCK_RSV_TEMP); | ||
2159 | /* | ||
2160 | * One for dir inode, two for dir entries, two for root | ||
2161 | * ref/backref. | ||
2162 | */ | ||
2163 | err = btrfs_subvolume_reserve_metadata(root, &block_rsv, | ||
2164 | 5, &qgroup_reserved); | ||
2165 | if (err) | ||
2166 | goto out_up_write; | ||
2167 | |||
2156 | trans = btrfs_start_transaction(root, 0); | 2168 | trans = btrfs_start_transaction(root, 0); |
2157 | if (IS_ERR(trans)) { | 2169 | if (IS_ERR(trans)) { |
2158 | err = PTR_ERR(trans); | 2170 | err = PTR_ERR(trans); |
2159 | goto out_up_write; | 2171 | goto out_release; |
2160 | } | 2172 | } |
2161 | trans->block_rsv = &root->fs_info->global_block_rsv; | 2173 | trans->block_rsv = &block_rsv; |
2174 | trans->bytes_reserved = block_rsv.size; | ||
2162 | 2175 | ||
2163 | ret = btrfs_unlink_subvol(trans, root, dir, | 2176 | ret = btrfs_unlink_subvol(trans, root, dir, |
2164 | dest->root_key.objectid, | 2177 | dest->root_key.objectid, |
@@ -2188,10 +2201,14 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file, | |||
2188 | } | 2201 | } |
2189 | } | 2202 | } |
2190 | out_end_trans: | 2203 | out_end_trans: |
2204 | trans->block_rsv = NULL; | ||
2205 | trans->bytes_reserved = 0; | ||
2191 | ret = btrfs_end_transaction(trans, root); | 2206 | ret = btrfs_end_transaction(trans, root); |
2192 | if (ret && !err) | 2207 | if (ret && !err) |
2193 | err = ret; | 2208 | err = ret; |
2194 | inode->i_flags |= S_DEAD; | 2209 | inode->i_flags |= S_DEAD; |
2210 | out_release: | ||
2211 | btrfs_subvolume_release_metadata(root, &block_rsv, qgroup_reserved); | ||
2195 | out_up_write: | 2212 | out_up_write: |
2196 | up_write(&root->fs_info->subvol_sem); | 2213 | up_write(&root->fs_info->subvol_sem); |
2197 | out_unlock: | 2214 | out_unlock: |