summaryrefslogtreecommitdiffstats
path: root/fs/btrfs/transaction.c
diff options
context:
space:
mode:
authorChris Mason <clm@fb.com>2014-05-23 01:18:52 +0200
committerChris Mason <clm@fb.com>2014-06-10 02:20:58 +0200
commita79b7d4b3e8118f265dcb4bdf9a572c392f02708 (patch)
treea7b4792e01ea5a44467f053e1822d4240e70edc6 /fs/btrfs/transaction.c
parentBtrfs: split up __extent_writepage to lower stack usage (diff)
downloadlinux-a79b7d4b3e8118f265dcb4bdf9a572c392f02708.tar.xz
linux-a79b7d4b3e8118f265dcb4bdf9a572c392f02708.zip
Btrfs: async delayed refs
Delayed extent operations are triggered during transaction commits. The goal is to queue up a healthly batch of changes to the extent allocation tree and run through them in bulk. This farms them off to async helper threads. The goal is to have the bulk of the delayed operations being done in the background, but this is also important to limit our stack footprint. Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'fs/btrfs/transaction.c')
-rw-r--r--fs/btrfs/transaction.c19
1 files changed, 16 insertions, 3 deletions
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 3aafbde8b637..1c54e2eb74ab 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -697,6 +697,7 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
unsigned long cur = trans->delayed_ref_updates;
int lock = (trans->type != TRANS_JOIN_NOLOCK);
int err = 0;
+ int must_run_delayed_refs = 0;
if (trans->use_count > 1) {
trans->use_count--;
@@ -711,10 +712,18 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
btrfs_create_pending_block_groups(trans, root);
trans->delayed_ref_updates = 0;
- if (!trans->sync && btrfs_should_throttle_delayed_refs(trans, root)) {
+ if (!trans->sync) {
+ must_run_delayed_refs =
+ btrfs_should_throttle_delayed_refs(trans, root);
cur = max_t(unsigned long, cur, 32);
- trans->delayed_ref_updates = 0;
- btrfs_run_delayed_refs(trans, root, cur);
+
+ /*
+ * don't make the caller wait if they are from a NOLOCK
+ * or ATTACH transaction, it will deadlock with commit
+ */
+ if (must_run_delayed_refs == 1 &&
+ (trans->type & (__TRANS_JOIN_NOLOCK | __TRANS_ATTACH)))
+ must_run_delayed_refs = 2;
}
if (trans->qgroup_reserved) {
@@ -775,6 +784,10 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
assert_qgroups_uptodate(trans);
kmem_cache_free(btrfs_trans_handle_cachep, trans);
+ if (must_run_delayed_refs) {
+ btrfs_async_run_delayed_refs(root, cur,
+ must_run_delayed_refs == 1);
+ }
return err;
}