summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMykyta Yatsenko <yatsenko@meta.com>2026-06-05 14:41:19 +0300
committerAlexei Starovoitov <ast@kernel.org>2026-06-05 18:00:07 +0300
commite673eee0f49ea41bf1af7aab08682ef98876c792 (patch)
treed0f1315d2a7af1e4f6d3faea464bb52cf5882b74
parent8f4fa9f89b72845fa8ac956bff2e1d2ba5722f2e (diff)
downloadlinux-e673eee0f49ea41bf1af7aab08682ef98876c792.tar.xz
rhashtable: Add selftest for rhashtable_next_key()
Insert n elements, then verify: - NULL prev_key walks from the beginning, visiting all n - non-existing prev_key returns ERR_PTR(-ENOENT) Signed-off-by: Mykyta Yatsenko <yatsenko@meta.com> Acked-by: Herbert Xu <herbert@gondor.apana.org.au> Link: https://lore.kernel.org/r/20260605-rhash-v7-2-5b8e05f8630d@meta.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
-rw-r--r--lib/test_rhashtable.c75
1 files changed, 75 insertions, 0 deletions
diff --git a/lib/test_rhashtable.c b/lib/test_rhashtable.c
index 0b33559a910b..b767a38a74f9 100644
--- a/lib/test_rhashtable.c
+++ b/lib/test_rhashtable.c
@@ -679,6 +679,78 @@ out:
return err;
}
+static int __init test_rhashtable_next_key(void)
+{
+ struct rhashtable_params params = test_rht_params;
+ struct test_obj_val key_missing = { .id = 99999, .tid = 0 };
+ struct test_obj_val *prev_key = NULL;
+ struct rhashtable ht;
+ struct test_obj *objs, *cur;
+ int i, count = 0, err;
+ int visited_keys[8] = { 0 };
+ const int n = ARRAY_SIZE(visited_keys);
+
+ params.nelem_hint = n;
+
+ err = rhashtable_init(&ht, &params);
+ if (err)
+ return err;
+
+ objs = kcalloc(n, sizeof(*objs), GFP_KERNEL);
+ if (!objs) {
+ rhashtable_destroy(&ht);
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < n; i++) {
+ objs[i].value.id = i;
+ err = rhashtable_insert_fast(&ht, &objs[i].node, params);
+ if (err)
+ goto out;
+ }
+
+ rcu_read_lock();
+
+ /* NULL prev_key: walk from the beginning, expect all n elements. */
+ while ((cur = rhashtable_next_key(&ht, prev_key))) {
+ if (IS_ERR(cur)) {
+ err = -EINVAL;
+ goto unlock;
+ }
+ count++;
+ prev_key = &cur->value;
+ visited_keys[cur->value.id] = 1;
+ if (count > n)
+ break;
+ }
+
+ if (count != n) {
+ err = -EINVAL;
+ goto unlock;
+ }
+
+ for (i = 0; i < n; i++) {
+ if (!visited_keys[i]) {
+ err = -EINVAL;
+ goto unlock;
+ }
+ }
+
+ /* Non-existing prev_key: must return ERR_PTR(-ENOENT). */
+ cur = rhashtable_next_key(&ht, &key_missing);
+ if (!IS_ERR(cur) || PTR_ERR(cur) != -ENOENT)
+ err = -EINVAL;
+
+unlock:
+ rcu_read_unlock();
+out:
+ for (i = 0; i < n; i++)
+ rhashtable_remove_fast(&ht, &objs[i].node, params);
+ kfree(objs);
+ rhashtable_destroy(&ht);
+ return err;
+}
+
static int __init test_rht_init(void)
{
unsigned int entries;
@@ -738,6 +810,9 @@ static int __init test_rht_init(void)
test_insert_duplicates_run();
+ pr_info("Testing rhashtable_next_key: %s\n",
+ test_rhashtable_next_key() == 0 ? "pass" : "FAIL");
+
if (!tcount)
return 0;