diff options
| -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: |
