Commit 4f5427cc authored by Qu Wenruo's avatar Qu Wenruo Committed by David Sterba

btrfs: delayed-inode: Use new qgroup meta rsv for delayed inode and item

Quite similar for delalloc, some modification to delayed-inode and
delayed-item reservation.  Also needs extra parameter for release case
to distinguish normal release and error release.
Signed-off-by: default avatarQu Wenruo <wqu@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 43b18595
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "disk-io.h" #include "disk-io.h"
#include "transaction.h" #include "transaction.h"
#include "ctree.h" #include "ctree.h"
#include "qgroup.h"
#define BTRFS_DELAYED_WRITEBACK 512 #define BTRFS_DELAYED_WRITEBACK 512
#define BTRFS_DELAYED_BACKGROUND 128 #define BTRFS_DELAYED_BACKGROUND 128
...@@ -552,11 +553,12 @@ static struct btrfs_delayed_item *__btrfs_next_delayed_item( ...@@ -552,11 +553,12 @@ static struct btrfs_delayed_item *__btrfs_next_delayed_item(
} }
static int btrfs_delayed_item_reserve_metadata(struct btrfs_trans_handle *trans, static int btrfs_delayed_item_reserve_metadata(struct btrfs_trans_handle *trans,
struct btrfs_fs_info *fs_info, struct btrfs_root *root,
struct btrfs_delayed_item *item) struct btrfs_delayed_item *item)
{ {
struct btrfs_block_rsv *src_rsv; struct btrfs_block_rsv *src_rsv;
struct btrfs_block_rsv *dst_rsv; struct btrfs_block_rsv *dst_rsv;
struct btrfs_fs_info *fs_info = root->fs_info;
u64 num_bytes; u64 num_bytes;
int ret; int ret;
...@@ -578,15 +580,17 @@ static int btrfs_delayed_item_reserve_metadata(struct btrfs_trans_handle *trans, ...@@ -578,15 +580,17 @@ static int btrfs_delayed_item_reserve_metadata(struct btrfs_trans_handle *trans,
return ret; return ret;
} }
static void btrfs_delayed_item_release_metadata(struct btrfs_fs_info *fs_info, static void btrfs_delayed_item_release_metadata(struct btrfs_root *root,
struct btrfs_delayed_item *item) struct btrfs_delayed_item *item)
{ {
struct btrfs_block_rsv *rsv; struct btrfs_block_rsv *rsv;
struct btrfs_fs_info *fs_info = root->fs_info;
if (!item->bytes_reserved) if (!item->bytes_reserved)
return; return;
rsv = &fs_info->delayed_block_rsv; rsv = &fs_info->delayed_block_rsv;
btrfs_qgroup_convert_reserved_meta(root, item->bytes_reserved);
trace_btrfs_space_reservation(fs_info, "delayed_item", trace_btrfs_space_reservation(fs_info, "delayed_item",
item->key.objectid, item->bytes_reserved, item->key.objectid, item->bytes_reserved,
0); 0);
...@@ -611,6 +615,9 @@ static int btrfs_delayed_inode_reserve_metadata( ...@@ -611,6 +615,9 @@ static int btrfs_delayed_inode_reserve_metadata(
num_bytes = btrfs_calc_trans_metadata_size(fs_info, 1); num_bytes = btrfs_calc_trans_metadata_size(fs_info, 1);
ret = btrfs_qgroup_reserve_meta_prealloc(root, num_bytes, true);
if (ret < 0)
return ret;
/* /*
* btrfs_dirty_inode will update the inode under btrfs_join_transaction * btrfs_dirty_inode will update the inode under btrfs_join_transaction
* which doesn't reserve space for speed. This is a problem since we * which doesn't reserve space for speed. This is a problem since we
...@@ -630,8 +637,10 @@ static int btrfs_delayed_inode_reserve_metadata( ...@@ -630,8 +637,10 @@ static int btrfs_delayed_inode_reserve_metadata(
* EAGAIN to make us stop the transaction we have, so return * EAGAIN to make us stop the transaction we have, so return
* ENOSPC instead so that btrfs_dirty_inode knows what to do. * ENOSPC instead so that btrfs_dirty_inode knows what to do.
*/ */
if (ret == -EAGAIN) if (ret == -EAGAIN) {
ret = -ENOSPC; ret = -ENOSPC;
btrfs_qgroup_free_meta_prealloc(root, num_bytes);
}
if (!ret) { if (!ret) {
node->bytes_reserved = num_bytes; node->bytes_reserved = num_bytes;
trace_btrfs_space_reservation(fs_info, trace_btrfs_space_reservation(fs_info,
...@@ -653,7 +662,8 @@ static int btrfs_delayed_inode_reserve_metadata( ...@@ -653,7 +662,8 @@ static int btrfs_delayed_inode_reserve_metadata(
} }
static void btrfs_delayed_inode_release_metadata(struct btrfs_fs_info *fs_info, static void btrfs_delayed_inode_release_metadata(struct btrfs_fs_info *fs_info,
struct btrfs_delayed_node *node) struct btrfs_delayed_node *node,
bool qgroup_free)
{ {
struct btrfs_block_rsv *rsv; struct btrfs_block_rsv *rsv;
...@@ -665,6 +675,12 @@ static void btrfs_delayed_inode_release_metadata(struct btrfs_fs_info *fs_info, ...@@ -665,6 +675,12 @@ static void btrfs_delayed_inode_release_metadata(struct btrfs_fs_info *fs_info,
node->inode_id, node->bytes_reserved, 0); node->inode_id, node->bytes_reserved, 0);
btrfs_block_rsv_release(fs_info, rsv, btrfs_block_rsv_release(fs_info, rsv,
node->bytes_reserved); node->bytes_reserved);
if (qgroup_free)
btrfs_qgroup_free_meta_prealloc(node->root,
node->bytes_reserved);
else
btrfs_qgroup_convert_reserved_meta(node->root,
node->bytes_reserved);
node->bytes_reserved = 0; node->bytes_reserved = 0;
} }
...@@ -766,7 +782,7 @@ static int btrfs_batch_insert_items(struct btrfs_root *root, ...@@ -766,7 +782,7 @@ static int btrfs_batch_insert_items(struct btrfs_root *root,
curr->data_len); curr->data_len);
slot++; slot++;
btrfs_delayed_item_release_metadata(fs_info, curr); btrfs_delayed_item_release_metadata(root, curr);
list_del(&curr->tree_list); list_del(&curr->tree_list);
btrfs_release_delayed_item(curr); btrfs_release_delayed_item(curr);
...@@ -788,7 +804,6 @@ static int btrfs_insert_delayed_item(struct btrfs_trans_handle *trans, ...@@ -788,7 +804,6 @@ static int btrfs_insert_delayed_item(struct btrfs_trans_handle *trans,
struct btrfs_path *path, struct btrfs_path *path,
struct btrfs_delayed_item *delayed_item) struct btrfs_delayed_item *delayed_item)
{ {
struct btrfs_fs_info *fs_info = root->fs_info;
struct extent_buffer *leaf; struct extent_buffer *leaf;
char *ptr; char *ptr;
int ret; int ret;
...@@ -806,7 +821,7 @@ static int btrfs_insert_delayed_item(struct btrfs_trans_handle *trans, ...@@ -806,7 +821,7 @@ static int btrfs_insert_delayed_item(struct btrfs_trans_handle *trans,
delayed_item->data_len); delayed_item->data_len);
btrfs_mark_buffer_dirty(leaf); btrfs_mark_buffer_dirty(leaf);
btrfs_delayed_item_release_metadata(fs_info, delayed_item); btrfs_delayed_item_release_metadata(root, delayed_item);
return 0; return 0;
} }
...@@ -858,7 +873,6 @@ static int btrfs_batch_delete_items(struct btrfs_trans_handle *trans, ...@@ -858,7 +873,6 @@ static int btrfs_batch_delete_items(struct btrfs_trans_handle *trans,
struct btrfs_path *path, struct btrfs_path *path,
struct btrfs_delayed_item *item) struct btrfs_delayed_item *item)
{ {
struct btrfs_fs_info *fs_info = root->fs_info;
struct btrfs_delayed_item *curr, *next; struct btrfs_delayed_item *curr, *next;
struct extent_buffer *leaf; struct extent_buffer *leaf;
struct btrfs_key key; struct btrfs_key key;
...@@ -908,7 +922,7 @@ static int btrfs_batch_delete_items(struct btrfs_trans_handle *trans, ...@@ -908,7 +922,7 @@ static int btrfs_batch_delete_items(struct btrfs_trans_handle *trans,
goto out; goto out;
list_for_each_entry_safe(curr, next, &head, tree_list) { list_for_each_entry_safe(curr, next, &head, tree_list) {
btrfs_delayed_item_release_metadata(fs_info, curr); btrfs_delayed_item_release_metadata(root, curr);
list_del(&curr->tree_list); list_del(&curr->tree_list);
btrfs_release_delayed_item(curr); btrfs_release_delayed_item(curr);
} }
...@@ -1051,7 +1065,7 @@ static int __btrfs_update_delayed_inode(struct btrfs_trans_handle *trans, ...@@ -1051,7 +1065,7 @@ static int __btrfs_update_delayed_inode(struct btrfs_trans_handle *trans,
no_iref: no_iref:
btrfs_release_path(path); btrfs_release_path(path);
err_out: err_out:
btrfs_delayed_inode_release_metadata(fs_info, node); btrfs_delayed_inode_release_metadata(fs_info, node, (ret < 0));
btrfs_release_delayed_inode(node); btrfs_release_delayed_inode(node);
return ret; return ret;
...@@ -1441,7 +1455,7 @@ int btrfs_insert_delayed_dir_index(struct btrfs_trans_handle *trans, ...@@ -1441,7 +1455,7 @@ int btrfs_insert_delayed_dir_index(struct btrfs_trans_handle *trans,
btrfs_set_stack_dir_type(dir_item, type); btrfs_set_stack_dir_type(dir_item, type);
memcpy((char *)(dir_item + 1), name, name_len); memcpy((char *)(dir_item + 1), name, name_len);
ret = btrfs_delayed_item_reserve_metadata(trans, fs_info, delayed_item); ret = btrfs_delayed_item_reserve_metadata(trans, dir->root, delayed_item);
/* /*
* we have reserved enough space when we start a new transaction, * we have reserved enough space when we start a new transaction,
* so reserving metadata failure is impossible * so reserving metadata failure is impossible
...@@ -1478,7 +1492,7 @@ static int btrfs_delete_delayed_insertion_item(struct btrfs_fs_info *fs_info, ...@@ -1478,7 +1492,7 @@ static int btrfs_delete_delayed_insertion_item(struct btrfs_fs_info *fs_info,
return 1; return 1;
} }
btrfs_delayed_item_release_metadata(fs_info, item); btrfs_delayed_item_release_metadata(node->root, item);
btrfs_release_delayed_item(item); btrfs_release_delayed_item(item);
mutex_unlock(&node->mutex); mutex_unlock(&node->mutex);
return 0; return 0;
...@@ -1513,7 +1527,7 @@ int btrfs_delete_delayed_dir_index(struct btrfs_trans_handle *trans, ...@@ -1513,7 +1527,7 @@ int btrfs_delete_delayed_dir_index(struct btrfs_trans_handle *trans,
item->key = item_key; item->key = item_key;
ret = btrfs_delayed_item_reserve_metadata(trans, fs_info, item); ret = btrfs_delayed_item_reserve_metadata(trans, dir->root, item);
/* /*
* we have reserved enough space when we start a new transaction, * we have reserved enough space when we start a new transaction,
* so reserving metadata failure is impossible. * so reserving metadata failure is impossible.
...@@ -1878,7 +1892,7 @@ static void __btrfs_kill_delayed_node(struct btrfs_delayed_node *delayed_node) ...@@ -1878,7 +1892,7 @@ static void __btrfs_kill_delayed_node(struct btrfs_delayed_node *delayed_node)
mutex_lock(&delayed_node->mutex); mutex_lock(&delayed_node->mutex);
curr_item = __btrfs_first_delayed_insertion_item(delayed_node); curr_item = __btrfs_first_delayed_insertion_item(delayed_node);
while (curr_item) { while (curr_item) {
btrfs_delayed_item_release_metadata(fs_info, curr_item); btrfs_delayed_item_release_metadata(root, curr_item);
prev_item = curr_item; prev_item = curr_item;
curr_item = __btrfs_next_delayed_item(prev_item); curr_item = __btrfs_next_delayed_item(prev_item);
btrfs_release_delayed_item(prev_item); btrfs_release_delayed_item(prev_item);
...@@ -1886,7 +1900,7 @@ static void __btrfs_kill_delayed_node(struct btrfs_delayed_node *delayed_node) ...@@ -1886,7 +1900,7 @@ static void __btrfs_kill_delayed_node(struct btrfs_delayed_node *delayed_node)
curr_item = __btrfs_first_delayed_deletion_item(delayed_node); curr_item = __btrfs_first_delayed_deletion_item(delayed_node);
while (curr_item) { while (curr_item) {
btrfs_delayed_item_release_metadata(fs_info, curr_item); btrfs_delayed_item_release_metadata(root, curr_item);
prev_item = curr_item; prev_item = curr_item;
curr_item = __btrfs_next_delayed_item(prev_item); curr_item = __btrfs_next_delayed_item(prev_item);
btrfs_release_delayed_item(prev_item); btrfs_release_delayed_item(prev_item);
...@@ -1896,7 +1910,7 @@ static void __btrfs_kill_delayed_node(struct btrfs_delayed_node *delayed_node) ...@@ -1896,7 +1910,7 @@ static void __btrfs_kill_delayed_node(struct btrfs_delayed_node *delayed_node)
btrfs_release_delayed_iref(delayed_node); btrfs_release_delayed_iref(delayed_node);
if (test_bit(BTRFS_DELAYED_NODE_INODE_DIRTY, &delayed_node->flags)) { if (test_bit(BTRFS_DELAYED_NODE_INODE_DIRTY, &delayed_node->flags)) {
btrfs_delayed_inode_release_metadata(fs_info, delayed_node); btrfs_delayed_inode_release_metadata(fs_info, delayed_node, false);
btrfs_release_delayed_inode(delayed_node); btrfs_release_delayed_inode(delayed_node);
} }
mutex_unlock(&delayed_node->mutex); mutex_unlock(&delayed_node->mutex);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment