From: Mykyta Yatsenko <mykyta.yatsenko5@gmail.com>
To: bpf@vger.kernel.org, ast@kernel.org, andrii@kernel.org,
daniel@iogearbox.net, kafai@meta.com, kernel-team@meta.com,
eddyz87@gmail.com, memxor@gmail.com,
herbert@gondor.apana.org.au
Cc: Mykyta Yatsenko <yatsenko@meta.com>
Subject: [PATCH bpf-next v4 01/11] rhashtable: Add rhashtable_next_key() API
Date: Wed, 13 May 2026 15:36:04 -0700 [thread overview]
Message-ID: <20260513-rhash-v4-1-dd3d541ccb0b@meta.com> (raw)
In-Reply-To: <20260513-rhash-v4-0-dd3d541ccb0b@meta.com>
From: Mykyta Yatsenko <yatsenko@meta.com>
Introduce a simpler iteration mechanism for rhashtable that lets
the caller continue from an arbitrary position by supplying the
previous key, without the per-iterator state of the
rhashtable_walk_* API.
void *rhashtable_next_key(struct rhashtable *ht,
const void *prev_key,
const struct rhashtable_params params);
Caller holds RCU; passes NULL prev_key for the first element or
the previously returned key to advance. Walks tbl->future_tbl
chain so in-flight rehashes are observed.
Best-effort semantics: an element being migrated may transiently
appear in both source and destination tables and be observed
twice. Concurrent inserts and shrinks may be skipped. Termination
of a full iteration is not guaranteed under continuous adversarial
rehash; callers must bound their loop externally. If prev_key is
not present in any in-flight table, returns ERR_PTR(-ENOENT).
Signed-off-by: Mykyta Yatsenko <yatsenko@meta.com>
---
include/linux/rhashtable.h | 85 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 85 insertions(+)
diff --git a/include/linux/rhashtable.h b/include/linux/rhashtable.h
index ef5230cece36..edf4d4c5102e 100644
--- a/include/linux/rhashtable.h
+++ b/include/linux/rhashtable.h
@@ -650,6 +650,91 @@ static __always_inline struct rhash_head *__rhashtable_lookup(
return NULL;
}
+/* Internal: scan one element forward from prev_key's position.
+ * Returns first rhash_head whose bucket >= prev_key's bucket and
+ * (if within prev_key's bucket) appears after prev_key in chain.
+ * Returns first element if prev_key is NULL or ERR_PTR(-ENOENT) if prev_key
+ * is not found.
+ */
+static __always_inline struct rhash_head *__rhashtable_next_in_table(
+ struct rhashtable *ht, struct bucket_table *tbl,
+ const void *prev_key, const struct rhashtable_params params)
+ __must_hold_shared(RCU)
+{
+ struct rhashtable_compare_arg arg = { .ht = ht, .key = prev_key };
+ struct rhash_head *he;
+ unsigned int b = 0;
+ bool found = false;
+
+ if (prev_key) {
+ b = rht_key_hashfn(ht, tbl, prev_key, params);
+ rht_for_each_rcu(he, tbl, b) {
+ if (found)
+ return he;
+ if (params.obj_cmpfn ?
+ !params.obj_cmpfn(&arg, rht_obj(ht, he)) :
+ !rhashtable_compare(&arg, rht_obj(ht, he)))
+ found = true;
+ }
+ if (!found)
+ return ERR_PTR(-ENOENT);
+ b++;
+ }
+
+ for (; b < tbl->size; b++)
+ rht_for_each_rcu(he, tbl, b)
+ return he;
+ return NULL;
+}
+
+/**
+ * rhashtable_next_key - return next element after a given key
+ * @ht: hash table
+ * @prev_key: pointer to previous key, or NULL for the first element
+ * @params: hash table parameters
+ *
+ * Returns the next element in best-effort iteration order, walking the
+ * @tbl chain (including any future_tbl in flight). Caller must hold RCU.
+ *
+ * Pass @prev_key == NULL to obtain the first element. To iterate, set
+ * @prev_key to the key of the previously returned element on each call,
+ * and stop when NULL is returned.
+ *
+ * Best-effort semantics:
+ * - Across the tbl->future_tbl chain, an element being migrated may
+ * transiently appear in both tables and be observed twice.
+ * - Concurrent inserts may or may not be observed.
+ * - Termination of a full iteration loop is NOT guaranteed under
+ * adversarial continuous rehash; callers MUST tolerate skips and
+ * repeats and SHOULD bound their loop externally.
+ * - If prev_key was concurrently deleted and is not present in any
+ * in-flight table, returns ERR_PTR(-ENOENT).
+ *
+ * Returns entry of the next element, or NULL when iteration is exhausted
+ * or ERR_PTR(-ENOENT) if prev_key is not found.
+ */
+static inline void *rhashtable_next_key(
+ struct rhashtable *ht, const void *prev_key,
+ const struct rhashtable_params params)
+ __must_hold_shared(RCU)
+{
+ struct bucket_table *tbl;
+ struct rhash_head *he;
+
+ tbl = rht_dereference_rcu(ht->tbl, ht);
+ do {
+ he = __rhashtable_next_in_table(ht, tbl, prev_key, params);
+ if (!IS_ERR_OR_NULL(he))
+ return rht_obj(ht, he);
+ if (!he)
+ prev_key = NULL;
+ /* Ensure we see any new future_tbl attached during a rehash. */
+ smp_rmb();
+ tbl = rht_dereference_rcu(tbl->future_tbl, ht);
+ } while (tbl);
+ return he; /* NULL or -ENOENT */
+}
+
/**
* rhashtable_lookup - search hash table
* @ht: hash table
--
2.53.0-Meta
next prev parent reply other threads:[~2026-05-13 22:37 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-13 22:36 [PATCH bpf-next v4 00/11] bpf: Introduce resizable hash map Mykyta Yatsenko
2026-05-13 22:36 ` Mykyta Yatsenko [this message]
2026-05-13 23:21 ` [PATCH bpf-next v4 01/11] rhashtable: Add rhashtable_next_key() API bot+bpf-ci
2026-05-13 22:36 ` [PATCH bpf-next v4 02/11] rhashtable: Add selftest for rhashtable_next_key() Mykyta Yatsenko
2026-05-13 22:36 ` [PATCH bpf-next v4 03/11] bpf: Implement resizable hashmap basic functions Mykyta Yatsenko
2026-05-13 23:21 ` bot+bpf-ci
2026-05-13 22:36 ` [PATCH bpf-next v4 04/11] bpf: Implement iteration ops for resizable hashtab Mykyta Yatsenko
2026-05-13 22:36 ` [PATCH bpf-next v4 05/11] bpf: Allow special fields in " Mykyta Yatsenko
2026-05-13 23:21 ` bot+bpf-ci
2026-05-13 22:36 ` [PATCH bpf-next v4 06/11] bpf: Optimize word-sized keys for resizable hashtable Mykyta Yatsenko
2026-05-13 22:36 ` [PATCH bpf-next v4 07/11] libbpf: Support " Mykyta Yatsenko
2026-05-13 22:36 ` [PATCH bpf-next v4 08/11] selftests/bpf: Add basic tests for resizable hash map Mykyta Yatsenko
2026-05-13 22:36 ` [PATCH bpf-next v4 09/11] selftests/bpf: Add BPF iterator " Mykyta Yatsenko
2026-05-13 22:36 ` [PATCH bpf-next v4 10/11] bpftool: Add rhash map documentation Mykyta Yatsenko
2026-05-13 22:36 ` [PATCH bpf-next v4 11/11] selftests/bpf: Add resizable hashmap to benchmarks Mykyta Yatsenko
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=20260513-rhash-v4-1-dd3d541ccb0b@meta.com \
--to=mykyta.yatsenko5@gmail.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=eddyz87@gmail.com \
--cc=herbert@gondor.apana.org.au \
--cc=kafai@meta.com \
--cc=kernel-team@meta.com \
--cc=memxor@gmail.com \
--cc=yatsenko@meta.com \
/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