Btrfs: fix wrong reserved space in qgroup during snap/subv creation
There are two problems in the space reservation of the snapshot/ subvolume creation. - don't reserve the space for the root item insertion - the space which is reserved in the qgroup is different with the free space reservation. we need reserve free space for 7 items, but in qgroup reservation, we need reserve space only for 3 items. So we implement new metadata reservation functions for the snapshot/subvolume creation. Signed-off-by: Miao Xie <miaox@cn.fujitsu.com> Signed-off-by: Josef Bacik <jbacik@fusionio.com>
This commit is contained in:
@@ -4560,19 +4560,60 @@ void btrfs_orphan_release_metadata(struct inode *inode)
|
||||
btrfs_block_rsv_release(root, root->orphan_block_rsv, num_bytes);
|
||||
}
|
||||
|
||||
int btrfs_snap_reserve_metadata(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_pending_snapshot *pending)
|
||||
/*
|
||||
* btrfs_subvolume_reserve_metadata() - reserve space for subvolume operation
|
||||
* root: the root of the parent directory
|
||||
* rsv: block reservation
|
||||
* items: the number of items that we need do reservation
|
||||
* qgroup_reserved: used to return the reserved size in qgroup
|
||||
*
|
||||
* This function is used to reserve the space for snapshot/subvolume
|
||||
* creation and deletion. Those operations are different with the
|
||||
* common file/directory operations, they change two fs/file trees
|
||||
* and root tree, the number of items that the qgroup reserves is
|
||||
* different with the free space reservation. So we can not use
|
||||
* the space reseravtion mechanism in start_transaction().
|
||||
*/
|
||||
int btrfs_subvolume_reserve_metadata(struct btrfs_root *root,
|
||||
struct btrfs_block_rsv *rsv,
|
||||
int items,
|
||||
u64 *qgroup_reserved)
|
||||
{
|
||||
struct btrfs_root *root = pending->root;
|
||||
struct btrfs_block_rsv *src_rsv = get_block_rsv(trans, root);
|
||||
struct btrfs_block_rsv *dst_rsv = &pending->block_rsv;
|
||||
/*
|
||||
* two for root back/forward refs, two for directory entries,
|
||||
* one for root of the snapshot and one for parent inode.
|
||||
*/
|
||||
u64 num_bytes = btrfs_calc_trans_metadata_size(root, 6);
|
||||
dst_rsv->space_info = src_rsv->space_info;
|
||||
return block_rsv_migrate_bytes(src_rsv, dst_rsv, num_bytes);
|
||||
u64 num_bytes;
|
||||
int ret;
|
||||
|
||||
if (root->fs_info->quota_enabled) {
|
||||
/* One for parent inode, two for dir entries */
|
||||
num_bytes = 3 * root->leafsize;
|
||||
ret = btrfs_qgroup_reserve(root, num_bytes);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
num_bytes = 0;
|
||||
}
|
||||
|
||||
*qgroup_reserved = num_bytes;
|
||||
|
||||
num_bytes = btrfs_calc_trans_metadata_size(root, items);
|
||||
rsv->space_info = __find_space_info(root->fs_info,
|
||||
BTRFS_BLOCK_GROUP_METADATA);
|
||||
ret = btrfs_block_rsv_add(root, rsv, num_bytes,
|
||||
BTRFS_RESERVE_FLUSH_ALL);
|
||||
if (ret) {
|
||||
if (*qgroup_reserved)
|
||||
btrfs_qgroup_free(root, *qgroup_reserved);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void btrfs_subvolume_release_metadata(struct btrfs_root *root,
|
||||
struct btrfs_block_rsv *rsv,
|
||||
u64 qgroup_reserved)
|
||||
{
|
||||
btrfs_block_rsv_release(root, rsv, (u64)-1);
|
||||
if (qgroup_reserved)
|
||||
btrfs_qgroup_free(root, qgroup_reserved);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user