From: Stefan Roesch <[email protected]>
To: <[email protected]>, <[email protected]>,
<[email protected]>
Cc: <[email protected]>, <[email protected]>, <[email protected]>,
<[email protected]>
Subject: [PATCH v2 02/12] btrfs: implement a nowait option for tree searches
Date: Wed, 7 Sep 2022 17:26:06 -0700 [thread overview]
Message-ID: <[email protected]> (raw)
In-Reply-To: <[email protected]>
From: Josef Bacik <[email protected]>
For NOWAIT IOCB's we'll need a way to tell search to not wait on locks
or anything. Accomplish this by adding a path->nowait flag that will
use trylocks and skip reading of metadata, returning -EWOULDBLOCK in
either of these cases. For now we only need this for reads, so only the
read side is handled. Add an ASSERT() to catch anybody trying to use
this for writes so they know they'll have to implement the write side.
Signed-off-by: Josef Bacik <[email protected]>
Signed-off-by: Stefan Roesch <[email protected]>
---
fs/btrfs/ctree.c | 39 ++++++++++++++++++++++++++++++++++++---
fs/btrfs/ctree.h | 1 +
fs/btrfs/locking.c | 23 +++++++++++++++++++++++
fs/btrfs/locking.h | 1 +
4 files changed, 61 insertions(+), 3 deletions(-)
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index ebfa35fe1c38..71b238364939 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -1447,6 +1447,11 @@ read_block_for_search(struct btrfs_root *root, struct btrfs_path *p,
return 0;
}
+ if (p->nowait) {
+ free_extent_buffer(tmp);
+ return -EAGAIN;
+ }
+
if (unlock_up)
btrfs_unlock_up_safe(p, level + 1);
@@ -1467,6 +1472,8 @@ read_block_for_search(struct btrfs_root *root, struct btrfs_path *p,
ret = -EAGAIN;
goto out;
+ } else if (p->nowait) {
+ return -EAGAIN;
}
if (unlock_up) {
@@ -1634,7 +1641,13 @@ static struct extent_buffer *btrfs_search_slot_get_root(struct btrfs_root *root,
* We don't know the level of the root node until we actually
* have it read locked
*/
- b = btrfs_read_lock_root_node(root);
+ if (p->nowait) {
+ b = btrfs_try_read_lock_root_node(root);
+ if (IS_ERR(b))
+ return b;
+ } else {
+ b = btrfs_read_lock_root_node(root);
+ }
level = btrfs_header_level(b);
if (level > write_lock_level)
goto out;
@@ -1910,6 +1923,13 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root *root,
WARN_ON(p->nodes[0] != NULL);
BUG_ON(!cow && ins_len);
+ /*
+ * For now only allow nowait for read only operations. There's no
+ * strict reason why we can't, we just only need it for reads so I'm
+ * only implementing it for reads right now.
+ */
+ ASSERT(!p->nowait || !cow);
+
if (ins_len < 0) {
lowest_unlock = 2;
@@ -1936,7 +1956,12 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root *root,
if (p->need_commit_sem) {
ASSERT(p->search_commit_root);
- down_read(&fs_info->commit_root_sem);
+ if (p->nowait) {
+ if (!down_read_trylock(&fs_info->commit_root_sem))
+ return -EAGAIN;
+ } else {
+ down_read(&fs_info->commit_root_sem);
+ }
}
again:
@@ -2082,7 +2107,15 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root *root,
btrfs_tree_lock(b);
p->locks[level] = BTRFS_WRITE_LOCK;
} else {
- btrfs_tree_read_lock(b);
+ if (p->nowait) {
+ if (!btrfs_try_tree_read_lock(b)) {
+ free_extent_buffer(b);
+ ret = -EAGAIN;
+ goto done;
+ }
+ } else {
+ btrfs_tree_read_lock(b);
+ }
p->locks[level] = BTRFS_READ_LOCK;
}
p->nodes[level] = b;
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 9ef162dbd4bc..d6d05450198d 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -443,6 +443,7 @@ struct btrfs_path {
* header (ie. sizeof(struct btrfs_item) is not included).
*/
unsigned int search_for_extension:1;
+ unsigned int nowait:1;
};
#define BTRFS_MAX_EXTENT_ITEM_SIZE(r) ((BTRFS_LEAF_DATA_SIZE(r->fs_info) >> 4) - \
sizeof(struct btrfs_item))
diff --git a/fs/btrfs/locking.c b/fs/btrfs/locking.c
index 9063072b399b..d6c88922d3e2 100644
--- a/fs/btrfs/locking.c
+++ b/fs/btrfs/locking.c
@@ -285,6 +285,29 @@ struct extent_buffer *btrfs_read_lock_root_node(struct btrfs_root *root)
return eb;
}
+/*
+ * Loop around taking references on and locking the root node of the tree in
+ * nowait mode until we end up with a lock on the root node or returning to
+ * avoid blocking.
+ *
+ * Return: root extent buffer with read lock held or -EWOULDBLOCK.
+ */
+struct extent_buffer *btrfs_try_read_lock_root_node(struct btrfs_root *root)
+{
+ struct extent_buffer *eb;
+
+ while (1) {
+ eb = btrfs_root_node(root);
+ if (!btrfs_try_tree_read_lock(eb))
+ return ERR_PTR(-EAGAIN);
+ if (eb == root->node)
+ break;
+ btrfs_tree_read_unlock(eb);
+ free_extent_buffer(eb);
+ }
+ return eb;
+}
+
/*
* DREW locks
* ==========
diff --git a/fs/btrfs/locking.h b/fs/btrfs/locking.h
index ab268be09bb5..490c7a79e995 100644
--- a/fs/btrfs/locking.h
+++ b/fs/btrfs/locking.h
@@ -94,6 +94,7 @@ int btrfs_try_tree_read_lock(struct extent_buffer *eb);
int btrfs_try_tree_write_lock(struct extent_buffer *eb);
struct extent_buffer *btrfs_lock_root_node(struct btrfs_root *root);
struct extent_buffer *btrfs_read_lock_root_node(struct btrfs_root *root);
+struct extent_buffer *btrfs_try_read_lock_root_node(struct btrfs_root *root);
#ifdef CONFIG_BTRFS_DEBUG
static inline void btrfs_assert_tree_write_locked(struct extent_buffer *eb)
--
2.30.2
next prev parent reply other threads:[~2022-09-08 0:26 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-09-08 0:26 [PATCH v2 00/12] io-uring/btrfs: support async buffered writes Stefan Roesch
2022-09-08 0:26 ` [PATCH v2 01/12] mm: export balance_dirty_pages_ratelimited_flags() Stefan Roesch
2022-09-08 10:18 ` Filipe Manana
2022-09-08 0:26 ` Stefan Roesch [this message]
2022-09-08 13:19 ` [PATCH v2 02/12] btrfs: implement a nowait option for tree searches Josef Bacik
2022-09-08 18:05 ` Stefan Roesch
2022-09-08 0:26 ` [PATCH v2 03/12] btrfs: make can_nocow_extent nowait compatible Stefan Roesch
2022-09-08 0:26 ` [PATCH v2 04/12] btrfs: add the ability to use NO_FLUSH for data reservations Stefan Roesch
2022-09-08 0:26 ` [PATCH v2 05/12] btrfs: add btrfs_try_lock_ordered_range Stefan Roesch
2022-09-08 10:18 ` Filipe Manana
2022-09-08 18:12 ` Stefan Roesch
2022-09-08 0:26 ` [PATCH v2 06/12] btrfs: make btrfs_check_nocow_lock nowait compatible Stefan Roesch
2022-09-08 10:18 ` Filipe Manana
2022-09-08 18:23 ` Stefan Roesch
2022-09-08 0:26 ` [PATCH v2 07/12] btrfs: make prepare_pages " Stefan Roesch
2022-09-08 10:17 ` Filipe Manana
2022-09-08 18:33 ` Stefan Roesch
2022-09-08 0:26 ` [PATCH v2 08/12] btrfs: make lock_and_cleanup_extent_if_need " Stefan Roesch
2022-09-08 10:17 ` Filipe Manana
2022-09-08 18:38 ` Stefan Roesch
2022-09-08 0:26 ` [PATCH v2 09/12] btrfs: btrfs: plumb NOWAIT through the write path Stefan Roesch
2022-09-08 10:16 ` Filipe Manana
2022-09-08 18:44 ` Stefan Roesch
2022-09-08 0:26 ` [PATCH v2 10/12] btrfs: make balance_dirty_pages nowait compatible Stefan Roesch
2022-09-08 10:16 ` Filipe Manana
2022-09-08 18:48 ` Stefan Roesch
2022-09-08 0:26 ` [PATCH v2 11/12] btrfs: add assert to search functions Stefan Roesch
2022-09-08 10:15 ` Filipe Manana
2022-09-08 19:10 ` Stefan Roesch
2022-09-08 0:26 ` [PATCH v2 12/12] btrfs: enable nowait async buffered writes Stefan Roesch
2022-09-08 10:14 ` Filipe Manana
2022-09-08 19:14 ` Stefan Roesch
2022-09-08 10:14 ` [PATCH v2 00/12] io-uring/btrfs: support " Filipe Manana
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 \
[email protected] \
[email protected] \
[email protected] \
[email protected] \
[email protected] \
[email protected] \
[email protected] \
[email protected] \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox