btrfs: divide btrfs_update_reserved_bytes() into two functions
This patch divides btrfs_update_reserved_bytes() into btrfs_add_reserved_bytes() and btrfs_free_reserved_bytes(), and next patch will extend btrfs_add_reserved_bytes()to fix some false ENOSPC error, please see later patch for detailed info. Signed-off-by: Wang Xiaoguang <wangxg.fnst@cn.fujitsu.com> Reviewed-by: Josef Bacik <jbacik@fb.com> Signed-off-by: David Sterba <dsterba@suse.com> Signed-off-by: Chris Mason <clm@fb.com>
This commit is contained in:
parent
dcb40c196f
commit
4824f1f412
|
@ -104,9 +104,10 @@ static int find_next_key(struct btrfs_path *path, int level,
|
||||||
struct btrfs_key *key);
|
struct btrfs_key *key);
|
||||||
static void dump_space_info(struct btrfs_space_info *info, u64 bytes,
|
static void dump_space_info(struct btrfs_space_info *info, u64 bytes,
|
||||||
int dump_block_groups);
|
int dump_block_groups);
|
||||||
static int btrfs_update_reserved_bytes(struct btrfs_block_group_cache *cache,
|
static int btrfs_add_reserved_bytes(struct btrfs_block_group_cache *cache,
|
||||||
u64 num_bytes, int reserve,
|
u64 num_bytes, int reserve, int delalloc);
|
||||||
int delalloc);
|
static int btrfs_free_reserved_bytes(struct btrfs_block_group_cache *cache,
|
||||||
|
u64 num_bytes, int delalloc);
|
||||||
static int block_rsv_use_bytes(struct btrfs_block_rsv *block_rsv,
|
static int block_rsv_use_bytes(struct btrfs_block_rsv *block_rsv,
|
||||||
u64 num_bytes);
|
u64 num_bytes);
|
||||||
int btrfs_pin_extent(struct btrfs_root *root,
|
int btrfs_pin_extent(struct btrfs_root *root,
|
||||||
|
@ -6497,19 +6498,14 @@ void btrfs_wait_block_group_reservations(struct btrfs_block_group_cache *bg)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* btrfs_update_reserved_bytes - update the block_group and space info counters
|
* btrfs_add_reserved_bytes - update the block_group and space info counters
|
||||||
* @cache: The cache we are manipulating
|
* @cache: The cache we are manipulating
|
||||||
* @num_bytes: The number of bytes in question
|
* @num_bytes: The number of bytes in question
|
||||||
* @reserve: One of the reservation enums
|
* @reserve: One of the reservation enums
|
||||||
* @delalloc: The blocks are allocated for the delalloc write
|
* @delalloc: The blocks are allocated for the delalloc write
|
||||||
*
|
*
|
||||||
* This is called by the allocator when it reserves space, or by somebody who is
|
* This is called by the allocator when it reserves space. Metadata
|
||||||
* freeing space that was never actually used on disk. For example if you
|
* reservations should be called with RESERVE_ALLOC so we do the proper
|
||||||
* reserve some space for a new leaf in transaction A and before transaction A
|
|
||||||
* commits you free that leaf, you call this with reserve set to 0 in order to
|
|
||||||
* clear the reservation.
|
|
||||||
*
|
|
||||||
* Metadata reservations should be called with RESERVE_ALLOC so we do the proper
|
|
||||||
* ENOSPC accounting. For data we handle the reservation through clearing the
|
* ENOSPC accounting. For data we handle the reservation through clearing the
|
||||||
* delalloc bits in the io_tree. We have to do this since we could end up
|
* delalloc bits in the io_tree. We have to do this since we could end up
|
||||||
* allocating less disk space for the amount of data we have reserved in the
|
* allocating less disk space for the amount of data we have reserved in the
|
||||||
|
@ -6519,44 +6515,65 @@ void btrfs_wait_block_group_reservations(struct btrfs_block_group_cache *bg)
|
||||||
* make the reservation and return -EAGAIN, otherwise this function always
|
* make the reservation and return -EAGAIN, otherwise this function always
|
||||||
* succeeds.
|
* succeeds.
|
||||||
*/
|
*/
|
||||||
static int btrfs_update_reserved_bytes(struct btrfs_block_group_cache *cache,
|
static int btrfs_add_reserved_bytes(struct btrfs_block_group_cache *cache,
|
||||||
u64 num_bytes, int reserve, int delalloc)
|
u64 num_bytes, int reserve, int delalloc)
|
||||||
{
|
{
|
||||||
struct btrfs_space_info *space_info = cache->space_info;
|
struct btrfs_space_info *space_info = cache->space_info;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
spin_lock(&space_info->lock);
|
spin_lock(&space_info->lock);
|
||||||
spin_lock(&cache->lock);
|
spin_lock(&cache->lock);
|
||||||
if (reserve != RESERVE_FREE) {
|
if (cache->ro) {
|
||||||
if (cache->ro) {
|
ret = -EAGAIN;
|
||||||
ret = -EAGAIN;
|
|
||||||
} else {
|
|
||||||
cache->reserved += num_bytes;
|
|
||||||
space_info->bytes_reserved += num_bytes;
|
|
||||||
if (reserve == RESERVE_ALLOC) {
|
|
||||||
trace_btrfs_space_reservation(cache->fs_info,
|
|
||||||
"space_info", space_info->flags,
|
|
||||||
num_bytes, 0);
|
|
||||||
space_info->bytes_may_use -= num_bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (delalloc)
|
|
||||||
cache->delalloc_bytes += num_bytes;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (cache->ro)
|
cache->reserved += num_bytes;
|
||||||
space_info->bytes_readonly += num_bytes;
|
space_info->bytes_reserved += num_bytes;
|
||||||
cache->reserved -= num_bytes;
|
if (reserve == RESERVE_ALLOC) {
|
||||||
space_info->bytes_reserved -= num_bytes;
|
trace_btrfs_space_reservation(cache->fs_info,
|
||||||
|
"space_info", space_info->flags,
|
||||||
|
num_bytes, 0);
|
||||||
|
space_info->bytes_may_use -= num_bytes;
|
||||||
|
}
|
||||||
|
|
||||||
if (delalloc)
|
if (delalloc)
|
||||||
cache->delalloc_bytes -= num_bytes;
|
cache->delalloc_bytes += num_bytes;
|
||||||
}
|
}
|
||||||
spin_unlock(&cache->lock);
|
spin_unlock(&cache->lock);
|
||||||
spin_unlock(&space_info->lock);
|
spin_unlock(&space_info->lock);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* btrfs_free_reserved_bytes - update the block_group and space info counters
|
||||||
|
* @cache: The cache we are manipulating
|
||||||
|
* @num_bytes: The number of bytes in question
|
||||||
|
* @delalloc: The blocks are allocated for the delalloc write
|
||||||
|
*
|
||||||
|
* This is called by somebody who is freeing space that was never actually used
|
||||||
|
* on disk. For example if you reserve some space for a new leaf in transaction
|
||||||
|
* A and before transaction A commits you free that leaf, you call this with
|
||||||
|
* reserve set to 0 in order to clear the reservation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int btrfs_free_reserved_bytes(struct btrfs_block_group_cache *cache,
|
||||||
|
u64 num_bytes, int delalloc)
|
||||||
|
{
|
||||||
|
struct btrfs_space_info *space_info = cache->space_info;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
spin_lock(&space_info->lock);
|
||||||
|
spin_lock(&cache->lock);
|
||||||
|
if (cache->ro)
|
||||||
|
space_info->bytes_readonly += num_bytes;
|
||||||
|
cache->reserved -= num_bytes;
|
||||||
|
space_info->bytes_reserved -= num_bytes;
|
||||||
|
|
||||||
|
if (delalloc)
|
||||||
|
cache->delalloc_bytes -= num_bytes;
|
||||||
|
spin_unlock(&cache->lock);
|
||||||
|
spin_unlock(&space_info->lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
void btrfs_prepare_extent_commit(struct btrfs_trans_handle *trans,
|
void btrfs_prepare_extent_commit(struct btrfs_trans_handle *trans,
|
||||||
struct btrfs_root *root)
|
struct btrfs_root *root)
|
||||||
{
|
{
|
||||||
|
@ -7191,7 +7208,7 @@ void btrfs_free_tree_block(struct btrfs_trans_handle *trans,
|
||||||
WARN_ON(test_bit(EXTENT_BUFFER_DIRTY, &buf->bflags));
|
WARN_ON(test_bit(EXTENT_BUFFER_DIRTY, &buf->bflags));
|
||||||
|
|
||||||
btrfs_add_free_space(cache, buf->start, buf->len);
|
btrfs_add_free_space(cache, buf->start, buf->len);
|
||||||
btrfs_update_reserved_bytes(cache, buf->len, RESERVE_FREE, 0);
|
btrfs_free_reserved_bytes(cache, buf->len, 0);
|
||||||
btrfs_put_block_group(cache);
|
btrfs_put_block_group(cache);
|
||||||
trace_btrfs_reserved_extent_free(root, buf->start, buf->len);
|
trace_btrfs_reserved_extent_free(root, buf->start, buf->len);
|
||||||
pin = 0;
|
pin = 0;
|
||||||
|
@ -7763,8 +7780,8 @@ static noinline int find_free_extent(struct btrfs_root *orig_root,
|
||||||
search_start - offset);
|
search_start - offset);
|
||||||
BUG_ON(offset > search_start);
|
BUG_ON(offset > search_start);
|
||||||
|
|
||||||
ret = btrfs_update_reserved_bytes(block_group, num_bytes,
|
ret = btrfs_add_reserved_bytes(block_group, num_bytes,
|
||||||
alloc_type, delalloc);
|
alloc_type, delalloc);
|
||||||
if (ret == -EAGAIN) {
|
if (ret == -EAGAIN) {
|
||||||
btrfs_add_free_space(block_group, offset, num_bytes);
|
btrfs_add_free_space(block_group, offset, num_bytes);
|
||||||
goto loop;
|
goto loop;
|
||||||
|
@ -7995,7 +8012,7 @@ static int __btrfs_free_reserved_extent(struct btrfs_root *root,
|
||||||
if (btrfs_test_opt(root->fs_info, DISCARD))
|
if (btrfs_test_opt(root->fs_info, DISCARD))
|
||||||
ret = btrfs_discard_extent(root, start, len, NULL);
|
ret = btrfs_discard_extent(root, start, len, NULL);
|
||||||
btrfs_add_free_space(cache, start, len);
|
btrfs_add_free_space(cache, start, len);
|
||||||
btrfs_update_reserved_bytes(cache, len, RESERVE_FREE, delalloc);
|
btrfs_free_reserved_bytes(cache, len, delalloc);
|
||||||
trace_btrfs_reserved_extent_free(root, start, len);
|
trace_btrfs_reserved_extent_free(root, start, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8223,8 +8240,8 @@ int btrfs_alloc_logged_file_extent(struct btrfs_trans_handle *trans,
|
||||||
if (!block_group)
|
if (!block_group)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
ret = btrfs_update_reserved_bytes(block_group, ins->offset,
|
ret = btrfs_add_reserved_bytes(block_group, ins->offset,
|
||||||
RESERVE_ALLOC_NO_ACCOUNT, 0);
|
RESERVE_ALLOC_NO_ACCOUNT, 0);
|
||||||
BUG_ON(ret); /* logic error */
|
BUG_ON(ret); /* logic error */
|
||||||
ret = alloc_reserved_file_extent(trans, root, 0, root_objectid,
|
ret = alloc_reserved_file_extent(trans, root, 0, root_objectid,
|
||||||
0, owner, offset, ins, 1);
|
0, owner, offset, ins, 1);
|
||||||
|
|
Loading…
Reference in New Issue