Commit 31b9655f authored by Josef Bacik's avatar Josef Bacik Committed by Chris Mason

Btrfs: track transid for delayed ref flushing

Using the offwakecputime bpf script I noticed most of our time was spent waiting
on the delayed ref throttling.  This is what is supposed to happen, but
sometimes the transaction can commit and then we're waiting for throttling that
doesn't matter anymore.  So change this stuff to be a little smarter by tracking
the transid we were in when we initiated the throttling.  If the transaction we
get is different then we can just bail out.  This resulted in a 50% speedup in
my fs_mark test, and reduced the amount of time spent throttling by 60 seconds
over the entire run (which is about 30 minutes).  Thanks,
Signed-off-by: default avatarJosef Bacik <jbacik@fb.com>
Signed-off-by: default avatarChris Mason <clm@fb.com>
parent de18c165
...@@ -2518,7 +2518,7 @@ void btrfs_put_block_group(struct btrfs_block_group_cache *cache); ...@@ -2518,7 +2518,7 @@ void btrfs_put_block_group(struct btrfs_block_group_cache *cache);
int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans, int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
struct btrfs_root *root, unsigned long count); struct btrfs_root *root, unsigned long count);
int btrfs_async_run_delayed_refs(struct btrfs_root *root, int btrfs_async_run_delayed_refs(struct btrfs_root *root,
unsigned long count, int wait); unsigned long count, u64 transid, int wait);
int btrfs_lookup_data_extent(struct btrfs_root *root, u64 start, u64 len); int btrfs_lookup_data_extent(struct btrfs_root *root, u64 start, u64 len);
int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans, int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans,
struct btrfs_root *root, u64 bytenr, struct btrfs_root *root, u64 bytenr,
......
...@@ -2835,6 +2835,7 @@ int btrfs_should_throttle_delayed_refs(struct btrfs_trans_handle *trans, ...@@ -2835,6 +2835,7 @@ int btrfs_should_throttle_delayed_refs(struct btrfs_trans_handle *trans,
struct async_delayed_refs { struct async_delayed_refs {
struct btrfs_root *root; struct btrfs_root *root;
u64 transid;
int count; int count;
int error; int error;
int sync; int sync;
...@@ -2850,9 +2851,16 @@ static void delayed_ref_async_start(struct btrfs_work *work) ...@@ -2850,9 +2851,16 @@ static void delayed_ref_async_start(struct btrfs_work *work)
async = container_of(work, struct async_delayed_refs, work); async = container_of(work, struct async_delayed_refs, work);
trans = btrfs_join_transaction(async->root); trans = btrfs_attach_transaction(async->root);
if (IS_ERR(trans)) { if (IS_ERR(trans)) {
async->error = PTR_ERR(trans); if (PTR_ERR(trans) != -ENOENT)
async->error = PTR_ERR(trans);
goto done;
}
/* Don't bother flushing if we got into a different transaction */
if (trans->transid != async->transid) {
btrfs_end_transaction(trans, async->root);
goto done; goto done;
} }
...@@ -2876,7 +2884,7 @@ static void delayed_ref_async_start(struct btrfs_work *work) ...@@ -2876,7 +2884,7 @@ static void delayed_ref_async_start(struct btrfs_work *work)
} }
int btrfs_async_run_delayed_refs(struct btrfs_root *root, int btrfs_async_run_delayed_refs(struct btrfs_root *root,
unsigned long count, int wait) unsigned long count, u64 transid, int wait)
{ {
struct async_delayed_refs *async; struct async_delayed_refs *async;
int ret; int ret;
...@@ -2888,6 +2896,7 @@ int btrfs_async_run_delayed_refs(struct btrfs_root *root, ...@@ -2888,6 +2896,7 @@ int btrfs_async_run_delayed_refs(struct btrfs_root *root,
async->root = root->fs_info->tree_root; async->root = root->fs_info->tree_root;
async->count = count; async->count = count;
async->error = 0; async->error = 0;
async->transid = transid;
if (wait) if (wait)
async->sync = 1; async->sync = 1;
else else
......
...@@ -4558,6 +4558,7 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans, ...@@ -4558,6 +4558,7 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
BUG_ON(ret); BUG_ON(ret);
if (btrfs_should_throttle_delayed_refs(trans, root)) if (btrfs_should_throttle_delayed_refs(trans, root))
btrfs_async_run_delayed_refs(root, btrfs_async_run_delayed_refs(root,
trans->transid,
trans->delayed_ref_updates * 2, 0); trans->delayed_ref_updates * 2, 0);
if (be_nice) { if (be_nice) {
if (truncate_space_check(trans, root, if (truncate_space_check(trans, root,
......
...@@ -818,6 +818,7 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans, ...@@ -818,6 +818,7 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
{ {
struct btrfs_transaction *cur_trans = trans->transaction; struct btrfs_transaction *cur_trans = trans->transaction;
struct btrfs_fs_info *info = root->fs_info; struct btrfs_fs_info *info = root->fs_info;
u64 transid = trans->transid;
unsigned long cur = trans->delayed_ref_updates; unsigned long cur = trans->delayed_ref_updates;
int lock = (trans->type != TRANS_JOIN_NOLOCK); int lock = (trans->type != TRANS_JOIN_NOLOCK);
int err = 0; int err = 0;
...@@ -905,7 +906,7 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans, ...@@ -905,7 +906,7 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
kmem_cache_free(btrfs_trans_handle_cachep, trans); kmem_cache_free(btrfs_trans_handle_cachep, trans);
if (must_run_delayed_refs) { if (must_run_delayed_refs) {
btrfs_async_run_delayed_refs(root, cur, btrfs_async_run_delayed_refs(root, cur, transid,
must_run_delayed_refs == 1); must_run_delayed_refs == 1);
} }
return err; return err;
......
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