All of lore.kernel.org
 help / color / mirror / Atom feed
From: Josef Bacik <josef@toxicpanda.com>
To: linux-btrfs@vger.kernel.org, kernel-team@fb.com
Subject: [PATCH 02/25] btrfs: rework async transaction committing
Date: Fri,  5 Nov 2021 16:45:28 -0400	[thread overview]
Message-ID: <5a181fb41c864ca518a35defc2547abef30afb18.1636144971.git.josef@toxicpanda.com> (raw)
In-Reply-To: <cover.1636144971.git.josef@toxicpanda.com>

Currently we do this awful thing where we get another ref on a trans
handle, async off that handle and commit the transaction from that work.
Because we do this we have to mess with current->journal_info and the
freeze counting stuff.

We already have an async thing to kick for the transaction commit, the
transaction kthread.  Replace this work struct with a flag on the
fs_info to tell the kthread to go ahead and commit even if it's before
our timeout.  Then we can drastically simplify the async transaction
commit path.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 fs/btrfs/ctree.h       |  3 ++
 fs/btrfs/disk-io.c     |  3 +-
 fs/btrfs/ioctl.c       |  7 +----
 fs/btrfs/transaction.c | 64 ++++++++----------------------------------
 fs/btrfs/transaction.h |  2 +-
 5 files changed, 18 insertions(+), 61 deletions(-)

diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index ce48ff69c77f..fb49162311b9 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -595,6 +595,9 @@ enum {
 	/* Indicate whether there are any tree modification log users */
 	BTRFS_FS_TREE_MOD_LOG_USERS,
 
+	/* Indicate that we want the transaction kthread to commit right now. */
+	BTRFS_FS_COMMIT_TRANS,
+
 #if BITS_PER_LONG == 32
 	/* Indicate if we have error/warn message printed on 32bit systems */
 	BTRFS_FS_32BIT_ERROR,
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 8d36950800f4..4c4357724ed0 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -1926,7 +1926,8 @@ static int transaction_kthread(void *arg)
 		}
 
 		delta = ktime_get_seconds() - cur->start_time;
-		if (cur->state < TRANS_STATE_COMMIT_START &&
+		if (!test_and_clear_bit(BTRFS_FS_COMMIT_TRANS, &fs_info->flags) &&
+		    cur->state < TRANS_STATE_COMMIT_START &&
 		    delta < fs_info->commit_interval) {
 			spin_unlock(&fs_info->trans_lock);
 			delay -= msecs_to_jiffies((delta - 1) * 1000);
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index c474f7e24163..44372f1e61ac 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -3622,7 +3622,6 @@ static noinline long btrfs_ioctl_start_sync(struct btrfs_root *root,
 {
 	struct btrfs_trans_handle *trans;
 	u64 transid;
-	int ret;
 
 	trans = btrfs_attach_transaction_barrier(root);
 	if (IS_ERR(trans)) {
@@ -3634,11 +3633,7 @@ static noinline long btrfs_ioctl_start_sync(struct btrfs_root *root,
 		goto out;
 	}
 	transid = trans->transid;
-	ret = btrfs_commit_transaction_async(trans);
-	if (ret) {
-		btrfs_end_transaction(trans);
-		return ret;
-	}
+	btrfs_commit_transaction_async(trans);
 out:
 	if (argp)
 		if (copy_to_user(argp, &transid, sizeof(transid)))
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index b958e0fdfe10..befe04019271 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -1861,50 +1861,14 @@ int btrfs_transaction_blocked(struct btrfs_fs_info *info)
 	return ret;
 }
 
-/*
- * commit transactions asynchronously. once btrfs_commit_transaction_async
- * returns, any subsequent transaction will not be allowed to join.
- */
-struct btrfs_async_commit {
-	struct btrfs_trans_handle *newtrans;
-	struct work_struct work;
-};
-
-static void do_async_commit(struct work_struct *work)
-{
-	struct btrfs_async_commit *ac =
-		container_of(work, struct btrfs_async_commit, work);
-
-	/*
-	 * We've got freeze protection passed with the transaction.
-	 * Tell lockdep about it.
-	 */
-	if (ac->newtrans->type & __TRANS_FREEZABLE)
-		__sb_writers_acquired(ac->newtrans->fs_info->sb, SB_FREEZE_FS);
-
-	current->journal_info = ac->newtrans;
-
-	btrfs_commit_transaction(ac->newtrans);
-	kfree(ac);
-}
-
-int btrfs_commit_transaction_async(struct btrfs_trans_handle *trans)
+void btrfs_commit_transaction_async(struct btrfs_trans_handle *trans)
 {
 	struct btrfs_fs_info *fs_info = trans->fs_info;
-	struct btrfs_async_commit *ac;
 	struct btrfs_transaction *cur_trans;
 
-	ac = kmalloc(sizeof(*ac), GFP_NOFS);
-	if (!ac)
-		return -ENOMEM;
-
-	INIT_WORK(&ac->work, do_async_commit);
-	ac->newtrans = btrfs_join_transaction(trans->root);
-	if (IS_ERR(ac->newtrans)) {
-		int err = PTR_ERR(ac->newtrans);
-		kfree(ac);
-		return err;
-	}
+	/* Kick the transaction kthread. */
+	set_bit(BTRFS_FS_COMMIT_TRANS, &fs_info->flags);
+	wake_up_process(fs_info->transaction_kthread);
 
 	/* take transaction reference */
 	cur_trans = trans->transaction;
@@ -1912,14 +1876,6 @@ int btrfs_commit_transaction_async(struct btrfs_trans_handle *trans)
 
 	btrfs_end_transaction(trans);
 
-	/*
-	 * Tell lockdep we've released the freeze rwsem, since the
-	 * async commit thread will be the one to unlock it.
-	 */
-	if (ac->newtrans->type & __TRANS_FREEZABLE)
-		__sb_writers_release(fs_info->sb, SB_FREEZE_FS);
-
-	schedule_work(&ac->work);
 	/*
 	 * Wait for the current transaction commit to start and block
 	 * subsequent transaction joins
@@ -1927,14 +1883,9 @@ int btrfs_commit_transaction_async(struct btrfs_trans_handle *trans)
 	wait_event(fs_info->transaction_blocked_wait,
 		   cur_trans->state >= TRANS_STATE_COMMIT_START ||
 		   TRANS_ABORTED(cur_trans));
-	if (current->journal_info == trans)
-		current->journal_info = NULL;
-
 	btrfs_put_transaction(cur_trans);
-	return 0;
 }
 
-
 static void cleanup_transaction(struct btrfs_trans_handle *trans, int err)
 {
 	struct btrfs_fs_info *fs_info = trans->fs_info;
@@ -2200,6 +2151,13 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans)
 	wait_event(cur_trans->writer_wait,
 		   atomic_read(&cur_trans->num_writers) == 1);
 
+	/*
+	 * We've started the commit, clear the flag in case we were triggered to
+	 * do an async commit but somebody else started before the transaction
+	 * kthread could do the work.
+	 */
+	clear_bit(BTRFS_FS_COMMIT_TRANS, &fs_info->flags);
+
 	if (TRANS_ABORTED(cur_trans)) {
 		ret = cur_trans->aborted;
 		goto scrub_continue;
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h
index ba45065f9451..e4b9b251a29e 100644
--- a/fs/btrfs/transaction.h
+++ b/fs/btrfs/transaction.h
@@ -217,7 +217,7 @@ void btrfs_add_dead_root(struct btrfs_root *root);
 int btrfs_defrag_root(struct btrfs_root *root);
 int btrfs_clean_one_deleted_snapshot(struct btrfs_root *root);
 int btrfs_commit_transaction(struct btrfs_trans_handle *trans);
-int btrfs_commit_transaction_async(struct btrfs_trans_handle *trans);
+void btrfs_commit_transaction_async(struct btrfs_trans_handle *trans);
 int btrfs_end_transaction_throttle(struct btrfs_trans_handle *trans);
 bool btrfs_should_end_transaction(struct btrfs_trans_handle *trans);
 void btrfs_throttle(struct btrfs_fs_info *fs_info);
-- 
2.26.3


  parent reply	other threads:[~2021-11-05 20:46 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-11-05 20:45 [PATCH 00/25] btrfs: extent tree v2 prep work for global roots Josef Bacik
2021-11-05 20:45 ` [PATCH 01/25] btrfs: kill BTRFS_FS_BARRIER Josef Bacik
2021-11-18 11:50   ` David Sterba
2021-11-05 20:45 ` Josef Bacik [this message]
2021-11-18 12:12   ` [PATCH 02/25] btrfs: rework async transaction committing David Sterba
2021-11-23 17:19     ` David Sterba
2021-11-05 20:45 ` [PATCH 03/25] btrfs: pass fs_info to trace_btrfs_transaction_commit Josef Bacik
2021-11-05 20:45 ` [PATCH 04/25] btrfs: remove trans_handle->root Josef Bacik
2021-11-05 20:45 ` [PATCH 05/25] btrfs: pass the root to add_keyed_refs Josef Bacik
2021-11-05 20:45 ` [PATCH 06/25] btrfs: move comment in find_parent_nodes() Josef Bacik
2021-11-05 20:45 ` [PATCH 07/25] btrfs: remove SANITY_TESTS check form find_parent_nodes Josef Bacik
2021-11-05 20:45 ` [PATCH 08/25] btrfs: remove BUG_ON() in find_parent_nodes() Josef Bacik
2021-11-23 20:53   ` Nikolay Borisov
2021-11-23 21:35     ` Josef Bacik
2021-11-05 20:45 ` [PATCH 09/25] btrfs: remove BUG_ON(!eie) in find_parent_nodes Josef Bacik
2021-11-05 20:45 ` [PATCH 10/25] btrfs: add a btrfs_block_group_root() helper Josef Bacik
2021-11-05 20:45 ` [PATCH 11/25] btrfs: make remove_extent_backref pass the root Josef Bacik
2021-11-05 20:45 ` [PATCH 12/25] btrfs: use chunk_root in find_free_extent_update_loop Josef Bacik
2021-11-25 10:11   ` Nikolay Borisov
2021-11-05 20:45 ` [PATCH 13/25] btrfs: do not special case the extent root for switch commit roots Josef Bacik
2021-11-05 20:45 ` [PATCH 14/25] btrfs: remove unnecessary extent root check in btrfs_defrag_leaves Josef Bacik
2021-11-05 20:45 ` [PATCH 15/25] btrfs: don't use the extent root in btrfs_chunk_alloc_add_chunk_item Josef Bacik
2021-11-05 20:45 ` [PATCH 16/25] btrfs: don't use extent_root in iterate_extent_inodes Josef Bacik
2021-11-05 20:45 ` [PATCH 17/25] btrfs: don't use the extent_root in flush_space Josef Bacik
2021-11-05 20:45 ` [PATCH 18/25] btrfs: init root block_rsv at init root time Josef Bacik
2021-11-05 20:45 ` [PATCH 19/25] btrfs: stop accessing ->extent_root directly Josef Bacik
2021-11-05 20:45 ` [PATCH 20/25] btrfs: fix csum assert to check objectid of the root Josef Bacik
2021-11-05 20:45 ` [PATCH 21/25] btrfs: set BTRFS_FS_STATE_NO_CSUMS if we fail to load the csum root Josef Bacik
2021-11-25 15:05   ` Nikolay Borisov
2021-11-05 20:45 ` [PATCH 22/25] btrfs: stop accessing ->csum_root directly Josef Bacik
2021-11-05 20:45 ` [PATCH 23/25] btrfs: stop accessing ->free_space_root directly Josef Bacik
2021-11-05 20:45 ` [PATCH 24/25] btrfs: remove useless WARN_ON in record_root_in_trans Josef Bacik
2021-11-05 20:45 ` [PATCH 25/25] btrfs: track the csum, extent, and free space trees in a rb tree Josef Bacik
2021-11-18 12:22   ` David Sterba

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=5a181fb41c864ca518a35defc2547abef30afb18.1636144971.git.josef@toxicpanda.com \
    --to=josef@toxicpanda.com \
    --cc=kernel-team@fb.com \
    --cc=linux-btrfs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.