All of lore.kernel.org
 help / color / mirror / Atom feed
From: Yonghong Song <yonghong.song@linux.dev>
To: Leon Hwang <leon.hwang@linux.dev>, bpf@vger.kernel.org
Cc: ast@kernel.org, andrii@kernel.org, daniel@iogearbox.net,
	martin.lau@linux.dev, eddyz87@gmail.com, song@kernel.org,
	john.fastabend@gmail.com, kpsingh@kernel.org, sdf@fomichev.me,
	haoluo@google.com, jolsa@kernel.org, memxor@gmail.com,
	ameryhung@gmail.com, linux-kernel@vger.kernel.org,
	kernel-patches-bot@fb.com
Subject: Re: [PATCH bpf-next v6 2/2] selftests/bpf: Add test to verify freeing the special fields when update [lru_,]percpu_hash maps
Date: Thu, 6 Nov 2025 18:00:17 -0800	[thread overview]
Message-ID: <9f662e2c-7370-4f99-bdec-bc123495e1c5@linux.dev> (raw)
In-Reply-To: <20251105151407.12723-3-leon.hwang@linux.dev>



On 11/5/25 7:14 AM, Leon Hwang wrote:
> Add test to verify that updating [lru_,]percpu_hash maps decrements
> refcount when BPF_KPTR_REF objects are involved.
>
> The tests perform the following steps:
>
> 1. Call update_elem() to insert an initial value.
> 2. Use bpf_refcount_acquire() to increment the refcount.
> 3. Store the node pointer in the map value.
> 4. Add the node to a linked list.
> 5. Probe-read the refcount and verify it is *2*.
> 6. Call update_elem() again to trigger refcount decrement.
> 7. Probe-read the refcount and verify it is *1*.
>
> Signed-off-by: Leon Hwang <leon.hwang@linux.dev>

LGTM with a few nits below.

Acked-by: Yonghong Song <yonghong.song@linux.dev>

> ---
>   .../bpf/prog_tests/refcounted_kptr.c          | 57 ++++++++++++++++++
>   .../selftests/bpf/progs/refcounted_kptr.c     | 60 +++++++++++++++++++
>   2 files changed, 117 insertions(+)
>
> diff --git a/tools/testing/selftests/bpf/prog_tests/refcounted_kptr.c b/tools/testing/selftests/bpf/prog_tests/refcounted_kptr.c
> index d6bd5e16e6372..086f679fa3f61 100644
> --- a/tools/testing/selftests/bpf/prog_tests/refcounted_kptr.c
> +++ b/tools/testing/selftests/bpf/prog_tests/refcounted_kptr.c
> @@ -44,3 +44,60 @@ void test_refcounted_kptr_wrong_owner(void)
>   	ASSERT_OK(opts.retval, "rbtree_wrong_owner_remove_fail_a2 retval");
>   	refcounted_kptr__destroy(skel);
>   }
> +
> +void test_percpu_hash_refcounted_kptr_refcount_leak(void)
> +{
> +	struct refcounted_kptr *skel;
> +	int cpu_nr, fd, err, key = 0;
> +	struct bpf_map *map;
> +	size_t values_sz;
> +	u64 *values;
> +	LIBBPF_OPTS(bpf_test_run_opts, opts,
> +		    .data_in = &pkt_v4,
> +		    .data_size_in = sizeof(pkt_v4),
> +		    .repeat = 1,
> +	);
> +
> +	cpu_nr = libbpf_num_possible_cpus();
> +	if (!ASSERT_GT(cpu_nr, 0, "libbpf_num_possible_cpus"))
> +		return;
> +
> +	values = calloc(cpu_nr, sizeof(u64));
> +	if (!ASSERT_OK_PTR(values, "calloc values"))
> +		return;
> +
> +	skel = refcounted_kptr__open_and_load();
> +	if (!ASSERT_OK_PTR(skel, "refcounted_kptr__open_and_load")) {
> +		free(values);
> +		return;
> +	}
> +
> +	values_sz = cpu_nr * sizeof(u64);
> +	memset(values, 0, values_sz);
> +
> +	map = skel->maps.percpu_hash;
> +	err = bpf_map__update_elem(map, &key, sizeof(key), values, values_sz, 0);
> +	if (!ASSERT_OK(err, "bpf_map__update_elem"))
> +		goto out;
> +
> +	fd = bpf_program__fd(skel->progs.percpu_hash_refcount_leak);
> +	err = bpf_prog_test_run_opts(fd, &opts);
> +	if (!ASSERT_OK(err, "bpf_prog_test_run_opts"))
> +		goto out;
> +	if (!ASSERT_EQ(opts.retval, 2, "opts.retval"))
> +		goto out;
> +
> +	err = bpf_map__update_elem(map, &key, sizeof(key), values, values_sz, 0);
> +	if (!ASSERT_OK(err, "bpf_map__update_elem"))
> +		goto out;
> +
> +	fd = bpf_program__fd(skel->progs.check_percpu_hash_refcount);
> +	err = bpf_prog_test_run_opts(fd, &opts);
> +	ASSERT_OK(err, "bpf_prog_test_run_opts");
> +	ASSERT_EQ(opts.retval, 1, "opts.retval");
> +
> +out:
> +	refcounted_kptr__destroy(skel);
> +	free(values);
> +}
> +

Empty line here.

> diff --git a/tools/testing/selftests/bpf/progs/refcounted_kptr.c b/tools/testing/selftests/bpf/progs/refcounted_kptr.c
> index 893a4fdb4b6e9..1aca85d86aebc 100644
> --- a/tools/testing/selftests/bpf/progs/refcounted_kptr.c
> +++ b/tools/testing/selftests/bpf/progs/refcounted_kptr.c
> @@ -568,4 +568,64 @@ int BPF_PROG(rbtree_sleepable_rcu_no_explicit_rcu_lock,
>   	return 0;
>   }
>   
> +private(kptr_ref) u64 ref;
> +
> +static int probe_read_refcount(void)
> +{
> +	u32 refcount;
> +
> +	bpf_probe_read_kernel(&refcount, sizeof(refcount), (void *) ref);
> +	return refcount;
> +}
> +
> +static int __insert_in_list(struct bpf_list_head *head, struct bpf_spin_lock *lock,
> +			    struct node_data __kptr **node)
> +{
> +	struct node_data *node_new, *node_ref, *node_old;
> +
> +	node_new = bpf_obj_new(typeof(*node_new));
> +	if (!node_new)
> +		return -1;
> +
> +	node_ref = bpf_refcount_acquire(node_new);
> +	node_old = bpf_kptr_xchg(node, node_new);

Change the above to node_old = bpf_kptr_xchg(node, node_node_ref); might 
be better for reasoning although node_ref/node_new are the same.

> +	if (node_old) {
> +		bpf_obj_drop(node_old);
> +		bpf_obj_drop(node_ref);
> +		return -2;
> +	}
> +
> +	bpf_spin_lock(lock);
> +	bpf_list_push_front(head, &node_ref->l);
> +	ref = (u64)(void *) &node_ref->ref;
> +	bpf_spin_unlock(lock);
> +	return probe_read_refcount();
> +}
> +
> +struct {
> +	__uint(type, BPF_MAP_TYPE_PERCPU_HASH);
> +	__type(key, int);
> +	__type(value, struct map_value);
> +	__uint(max_entries, 1);
> +} percpu_hash SEC(".maps");
> +
> +SEC("tc")
> +int percpu_hash_refcount_leak(void *ctx)
> +{
> +	struct map_value *v;
> +	int key = 0;
> +
> +	v = bpf_map_lookup_elem(&percpu_hash, &key);
> +	if (!v)
> +		return 0;
> +
> +	return __insert_in_list(&head, &lock, &v->node);
> +}
> +
> +SEC("tc")
> +int check_percpu_hash_refcount(void *ctx)
> +{
> +	return probe_read_refcount();
> +}
> +
>   char _license[] SEC("license") = "GPL";


  reply	other threads:[~2025-11-07  2:00 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-11-05 15:14 [PATCH bpf-next v6 0/2] bpf: Free special fields when update [lru_,]percpu_hash maps Leon Hwang
2025-11-05 15:14 ` [PATCH bpf-next v6 1/2] " Leon Hwang
2025-11-07  1:56   ` Yonghong Song
2025-11-05 15:14 ` [PATCH bpf-next v6 2/2] selftests/bpf: Add test to verify freeing the " Leon Hwang
2025-11-07  2:00   ` Yonghong Song [this message]
2025-11-11 13:38     ` Leon Hwang
2025-11-11 13:52       ` Leon Hwang
2025-11-11 21:58         ` Yonghong Song
2025-11-13 13:16           ` Leon Hwang
2025-11-13 17:30 ` [PATCH bpf-next v6 0/2] bpf: Free " patchwork-bot+netdevbpf

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=9f662e2c-7370-4f99-bdec-bc123495e1c5@linux.dev \
    --to=yonghong.song@linux.dev \
    --cc=ameryhung@gmail.com \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=eddyz87@gmail.com \
    --cc=haoluo@google.com \
    --cc=john.fastabend@gmail.com \
    --cc=jolsa@kernel.org \
    --cc=kernel-patches-bot@fb.com \
    --cc=kpsingh@kernel.org \
    --cc=leon.hwang@linux.dev \
    --cc=linux-kernel@vger.kernel.org \
    --cc=martin.lau@linux.dev \
    --cc=memxor@gmail.com \
    --cc=sdf@fomichev.me \
    --cc=song@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.