All of lore.kernel.org
 help / color / mirror / Atom feed
From: Amery Hung <ameryhung@gmail.com>
To: bpf@vger.kernel.org
Cc: netdev@vger.kernel.org, alexei.starovoitov@gmail.com,
	andrii@kernel.org, daniel@iogearbox.net, tj@kernel.org,
	memxor@gmail.com, martin.lau@kernel.org, ameryhung@gmail.com,
	kernel-team@meta.com
Subject: [PATCH bpf-next v4 3/3] selftests/bpf: Test concurrent task local data key creation
Date: Thu, 15 May 2025 14:16:02 -0700	[thread overview]
Message-ID: <20250515211606.2697271-4-ameryhung@gmail.com> (raw)
In-Reply-To: <20250515211606.2697271-1-ameryhung@gmail.com>

Test thread-safety of tld_create_key(). Since tld_create_key() does
not rely on locks but memory barriers and atomic operations to protect
the shared metadata, the thread-safety of the function is non-trivial.
Make sure concurrent tld_key_create(), both valid and invalid, can not
race and corrupt metatada, which may leads to TLDs not being thread-
specific or duplicate TLDs with the same name.

Signed-off-by: Amery Hung <ameryhung@gmail.com>
---
 .../bpf/prog_tests/test_task_local_data.c     | 91 +++++++++++++++++++
 1 file changed, 91 insertions(+)

diff --git a/tools/testing/selftests/bpf/prog_tests/test_task_local_data.c b/tools/testing/selftests/bpf/prog_tests/test_task_local_data.c
index 738fc1c9d8a4..5743b753a4a1 100644
--- a/tools/testing/selftests/bpf/prog_tests/test_task_local_data.c
+++ b/tools/testing/selftests/bpf/prog_tests/test_task_local_data.c
@@ -156,8 +156,99 @@ static void test_task_local_data_basic(void)
 		pthread_join(thread[i], NULL);
 }
 
+#define TEST_RACE_THREAD_NUM 61
+
+void *test_task_local_data_race_thread(void *arg)
+{
+	char key_name[32];
+	tld_key_t key;
+	int id, fd;
+
+	id = (intptr_t)arg & 0x0000ffff;
+	fd = ((intptr_t)arg & 0xffff0000) >> 16;
+
+	key = tld_create_key(fd, "value_not_exist", PAGE_SIZE + 1);
+	ASSERT_EQ(tld_key_err_or_zero(key), -E2BIG, "tld_create_key");
+
+	/*
+	 * If more than one thread succeed in creating value1 or value2,
+	 * some threads will fail to create thread_<id> later.
+	 */
+	key = tld_create_key(fd, "value1", sizeof(int));
+	if (!tld_key_is_err(key))
+		tld_keys[TEST_RACE_THREAD_NUM] = key;
+	key = tld_create_key(fd, "value2", sizeof(struct test_struct));
+	if (!tld_key_is_err(key))
+		tld_keys[TEST_RACE_THREAD_NUM + 1] = key;
+
+	snprintf(key_name, 32, "thread_%d", id);
+	tld_keys[id] = tld_create_key(fd, key_name, sizeof(int));
+	ASSERT_FALSE(tld_key_is_err(tld_keys[id]), "tld_create_key");
+
+	pthread_exit(NULL);
+}
+
+static void test_task_local_data_race(void)
+{
+	LIBBPF_OPTS(bpf_test_run_opts, opts);
+	pthread_t thread[TEST_RACE_THREAD_NUM];
+	struct test_task_local_data *skel;
+	int fd, i, j, err, *data, arg;
+
+	skel = test_task_local_data__open_and_load();
+	if (!ASSERT_OK_PTR(skel, "skel_open_and_load"))
+		return;
+
+	fd = bpf_map__fd(skel->maps.tld_data_map);
+
+	for (j = 0; j < 100; j++) {
+		reset_tld();
+
+		for (i = 0; i < TEST_RACE_THREAD_NUM; i++) {
+			/*
+			 * Try to make tld_create_key() race with each other. Call
+			 * tld_create_key(), both valid and invalid, from different threads.
+			 */
+			arg = i | fd << 16;
+			err = pthread_create(&thread[i], NULL, test_task_local_data_race_thread,
+					     (void *)(intptr_t)arg);
+			if (!ASSERT_OK(err, "pthread_create"))
+				goto out;
+		}
+
+		/* Wait for all tld_create_key() to return */
+		for (i = 0; i < TEST_RACE_THREAD_NUM; i++)
+			pthread_join(thread[i], NULL);
+
+		/* Run task_init to make sure no invalid TLDs are added */
+		err = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.task_init), &opts);
+		ASSERT_OK(err, "run task_init");
+		ASSERT_OK(opts.retval, "task_init retval");
+
+		/* Write a unique number in the range of [0, TEST_RACE_THREAD_NUM) to each TLD */
+		for (i = 0; i < TEST_RACE_THREAD_NUM; i++) {
+			data = tld_get_data(fd, tld_keys[i]);
+			if (!ASSERT_OK_PTR(data, "tld_get_data"))
+				goto out;
+			*data = i;
+		}
+
+		/* Read TLDs and check the value to see if any address collides with another */
+		for (i = 0; i < TEST_RACE_THREAD_NUM; i++) {
+			data = tld_get_data(fd, tld_keys[i]);
+			if (!ASSERT_OK_PTR(data, "tld_get_data"))
+				goto out;
+			ASSERT_EQ(*data, i, "check TLD");
+		}
+	}
+out:
+	tld_free();
+}
+
 void test_task_local_data(void)
 {
 	if (test__start_subtest("task_local_data_basic"))
 		test_task_local_data_basic();
+	if (test__start_subtest("task_local_data_race"))
+		test_task_local_data_race();
 }
-- 
2.47.1


      parent reply	other threads:[~2025-05-15 21:16 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-05-15 21:15 [PATCH bpf-next v4 0/3] Task local data Amery Hung
2025-05-15 21:16 ` [PATCH bpf-next v4 1/3] selftests/bpf: Introduce task " Amery Hung
2025-05-16 18:57   ` Alexei Starovoitov
2025-05-16 20:41     ` Amery Hung
2025-05-16 22:22       ` Alexei Starovoitov
2025-05-20  7:36         ` Amery Hung
2025-05-20 20:03           ` Alexei Starovoitov
2025-05-19 20:04   ` Tejun Heo
2025-05-20  6:44     ` Amery Hung
2025-05-20 22:57   ` Andrii Nakryiko
2025-05-22 17:27     ` Amery Hung
2025-05-22  8:36   ` Tony Ambardar
2025-05-22 16:49     ` Amery Hung
2025-05-23 10:09       ` Tony Ambardar
2025-05-15 21:16 ` [PATCH bpf-next v4 2/3] selftests/bpf: Test basic task local data operations Amery Hung
2025-05-23 10:18   ` Tony Ambardar
2025-05-15 21:16 ` Amery Hung [this message]

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=20250515211606.2697271-4-ameryhung@gmail.com \
    --to=ameryhung@gmail.com \
    --cc=alexei.starovoitov@gmail.com \
    --cc=andrii@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=kernel-team@meta.com \
    --cc=martin.lau@kernel.org \
    --cc=memxor@gmail.com \
    --cc=netdev@vger.kernel.org \
    --cc=tj@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.