From nobody Thu Apr 16 22:33:13 2026 Received: from mail-pj1-f49.google.com (mail-pj1-f49.google.com [209.85.216.49]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E95D93115AF for ; Wed, 25 Feb 2026 09:27:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.49 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772011652; cv=none; b=ez/YHsDLoGwCOfTKX6zJMAP4i9s9TM7RKauE/7uk81ECB/kPAM3XbJtRgthxxQi9Hoa9pYapZz7mnHtUtF105sjwSPtA9CHpq1JV3psiFwpV92kv/bGbcL+86ff5KXYeReCLAlDu8Vp66neQJSylCYAqzNldgniURAF53zsLjkI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772011652; c=relaxed/simple; bh=9WB8MCPTdtXhtrp5FTp0FnfzfHPnxg3d6osMwaa3AW4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=fGfSC94X7DSHgk535T/wYmzT6jyrm4AN3U46KZF83vyOsz122Z9dTe1YvAAo9mYeXS49CJATx0MXCmfqejvKv/yUA7ct3LKuGK/rPMET3tt4l2ODUKAr8VQQFCbP5qxF/f931BFTf2dJaUI08xGK8oXyNkL6ag1kcKGy73vsQjc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=UwoFCEUT; arc=none smtp.client-ip=209.85.216.49 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="UwoFCEUT" Received: by mail-pj1-f49.google.com with SMTP id 98e67ed59e1d1-354c67da885so5505840a91.3 for ; Wed, 25 Feb 2026 01:27:30 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772011650; x=1772616450; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=6NeUYBW+BF+U6wXLlBa7cECXJg2bRaRM2pqIkQAOKAU=; b=UwoFCEUTnkgdf638aAgYj0wGVUH/h90Um6uscbF5tNBHOgGsL+gEwpQkoGrrebFQ8P wYf1jyouqPK0r8P2G4xQ0gNMTS1HycUPK6HtuM6Q4Bpa7IQMFWYkUjws/lxNQXjj1bw9 f/qf9GZoNhNgOepVdajoNEco41w5C7+V0SRU21a1UbUjpUbQfXkVOVm3c9mRTJXcJK8P DaCr6hahU599hHX+dY7dw4WlzyL/zETogPUQDOOyxqr8F5j+qDDi2XYYwC75Kj8Qy0b+ hNvvirDV4Ns85znILCCOYDjd6Icq8TTXT9goViO5KfYjkxb10mcpfbO4P68ZyIgdtGDP aFqQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772011650; x=1772616450; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=6NeUYBW+BF+U6wXLlBa7cECXJg2bRaRM2pqIkQAOKAU=; b=LMxWuo7Fb3cBOuMJ/gdBukBiNcebXfkSIDUvUe9OnJPPuAum1XFQ7nJ4znZVldZ3yb Kwrlnv54JUzU/Nd6UZ+xoFQLzRQbcA1atSn+2z1EgcKGG4iU0oeuT+BH55L9+XSg+rfl E30PkF1G0s/k8wgkoINNe1JeECMJUt3BNtmn8QIBMf9rh2LNy3ftKgpaWsnDdmb76WJx df8eBwo39tf/LUz2tRc1Exc6puTaBoGz5hbI8DEqXQU7K95P90ahRu23fE82RzxcNQFU RaFG4dW6aAAeTjPJEYycQ6lpQZ/h/6rXBlv7JC1OciUOm+sQT8f7NqnFv4gZKWhWSszO DVdg== X-Forwarded-Encrypted: i=1; AJvYcCW6GkSbCW/EO3HuUkQgRI7LEn+sbK3yShSdEXsiekTb2RHB8ZQPbLl2iB0BH9jfgouo3BDcEZjZ6NU8M28=@vger.kernel.org X-Gm-Message-State: AOJu0Yys7Wnd5o6hQv7D08azVDNtZ8bi6ZjxkiME2ApFbZCZkbfQowbJ aE1HaMs3DWoXM6ZTKbV/htS+MUaUPhG5Vi9WCjO0BR6KPs4SusE62Tmc X-Gm-Gg: ATEYQzyywoncGva2euY6bfjiSx0fPdH6AmnbLi8UJ8qIJaVAqGCgAHVMRC4P41XVhut DXscaSEYEeNPcpDpWmh+EP29/KB2Ek5gOCD+MWbNR+JsEWeSi831MokWY5d1R31YUKr+XvZCvJ5 tbCaDycgmQNt2ugBzwXAdxMXVKxkYx5QW+pQ2BpH8gf9Vt3UzMXGKhb56AqoIvcmojH+vsbWpGA vk+5RWO/ytpTKgvBSpEeKDPwvWF+/GP9/QCswidv/BWmDXUkNwg+CdiECZ2JeO4lGDzLasrKgXi lTjfqYwVRmFLcQgcjDCxdOyxs+Ju4hkTj5m5t1LjzQvzorbFBGKSzpOTLcLP835SWjPNhohyMC1 IosXGTVNbnSZwlnFQtFFn9ZSE40lJGXqovpNpGVTSG5q2b7dlA1mdzN9pjyg5LKJPEQZGl7lwMn wLKP0Y7cn6b0GcyshJj205JsO+3XBUSsYgXwxP4tv4HEMjUhursWJZnwY3X1A9dlV9 X-Received: by 2002:a17:90a:d448:b0:356:8719:f516 with SMTP id 98e67ed59e1d1-3590f1b0583mr1886400a91.24.1772011650208; Wed, 25 Feb 2026 01:27:30 -0800 (PST) Received: from localhost.localdomain ([113.218.252.140]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-35912f5f29fsm837901a91.1.2026.02.25.01.27.18 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Wed, 25 Feb 2026 01:27:29 -0800 (PST) From: Chengkaitao To: martin.lau@linux.dev, ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org, eddyz87@gmail.com, song@kernel.org, yonghong.song@linux.dev, john.fastabend@gmail.com, kpsingh@kernel.org, sdf@fomichev.me, haoluo@google.com, jolsa@kernel.org, shuah@kernel.org, chengkaitao@kylinos.cn, leon.hwang@linux.dev, linux-kselftest@vger.kernel.org Cc: bpf@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 1/6] bpf: Introduce the bpf_list_del kfunc. Date: Wed, 25 Feb 2026 17:26:46 +0800 Message-ID: <20260225092651.94689-2-pilgrimtao@gmail.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20260225092651.94689-1-pilgrimtao@gmail.com> References: <20260225092651.94689-1-pilgrimtao@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Kaitao Cheng If a user holds ownership of a node in the middle of a list, they can directly remove it from the list without strictly adhering to deletion rules from the head or tail. When a kfunc has only one bpf_list_node parameter, supplement the initialization of the corresponding btf_field. This is typically paired with bpf_refcount. After calling bpf_list_del, it is generally necessary to drop the reference to the list node twice to prevent reference count leaks. Signed-off-by: Kaitao Cheng --- kernel/bpf/btf.c | 33 +++++++++++++++++++++++++++++---- kernel/bpf/helpers.c | 17 +++++++++++++++++ kernel/bpf/verifier.c | 9 ++++++++- 3 files changed, 54 insertions(+), 5 deletions(-) diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c index 4872d2a6c42d..8a977c793d56 100644 --- a/kernel/bpf/btf.c +++ b/kernel/bpf/btf.c @@ -3785,7 +3785,6 @@ static int btf_find_field_one(const struct btf *btf, case BPF_RES_SPIN_LOCK: case BPF_TIMER: case BPF_WORKQUEUE: - case BPF_LIST_NODE: case BPF_RB_NODE: case BPF_REFCOUNT: case BPF_TASK_WORK: @@ -3794,6 +3793,27 @@ static int btf_find_field_one(const struct btf *btf, if (ret < 0) return ret; break; + case BPF_LIST_NODE: + ret =3D btf_find_struct(btf, var_type, off, sz, field_type, + info_cnt ? &info[0] : &tmp); + if (ret < 0) + return ret; + /* graph_root for verifier: container type and node member name */ + if (info_cnt && var_idx >=3D 0 && (u32)var_idx < btf_type_vlen(var)) { + u32 id; + const struct btf_member *member; + + for (id =3D 1; id < btf_nr_types(btf); id++) { + if (btf_type_by_id(btf, id) =3D=3D var) { + info[0].graph_root.value_btf_id =3D id; + member =3D btf_type_member(var) + var_idx; + info[0].graph_root.node_name =3D + __btf_name_by_offset(btf, member->name_off); + break; + } + } + } + break; case BPF_KPTR_UNREF: case BPF_KPTR_REF: case BPF_KPTR_PERCPU: @@ -4138,6 +4158,7 @@ struct btf_record *btf_parse_fields(const struct btf = *btf, const struct btf_type if (ret < 0) goto end; break; + case BPF_LIST_NODE: case BPF_LIST_HEAD: ret =3D btf_parse_list_head(btf, &rec->fields[i], &info_arr[i]); if (ret < 0) @@ -4148,7 +4169,6 @@ struct btf_record *btf_parse_fields(const struct btf = *btf, const struct btf_type if (ret < 0) goto end; break; - case BPF_LIST_NODE: case BPF_RB_NODE: break; default: @@ -4192,20 +4212,25 @@ int btf_check_and_fixup_fields(const struct btf *bt= f, struct btf_record *rec) int i; =20 /* There are three types that signify ownership of some other type: - * kptr_ref, bpf_list_head, bpf_rb_root. + * kptr_ref, bpf_list_head/node, bpf_rb_root. * kptr_ref only supports storing kernel types, which can't store * references to program allocated local types. * * Hence we only need to ensure that bpf_{list_head,rb_root} ownership * does not form cycles. */ - if (IS_ERR_OR_NULL(rec) || !(rec->field_mask & (BPF_GRAPH_ROOT | BPF_UPTR= ))) + if (IS_ERR_OR_NULL(rec) || !(rec->field_mask & + (BPF_GRAPH_ROOT | BPF_GRAPH_NODE | BPF_UPTR))) return 0; + for (i =3D 0; i < rec->cnt; i++) { struct btf_struct_meta *meta; const struct btf_type *t; u32 btf_id; =20 + if (rec->fields[i].type & BPF_GRAPH_NODE) + rec->fields[i].graph_root.value_rec =3D rec; + if (rec->fields[i].type =3D=3D BPF_UPTR) { /* The uptr only supports pinning one page and cannot * point to a kernel struct diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c index 6eb6c82ed2ee..577af62a9f7a 100644 --- a/kernel/bpf/helpers.c +++ b/kernel/bpf/helpers.c @@ -2459,6 +2459,22 @@ __bpf_kfunc struct bpf_list_node *bpf_list_pop_back(= struct bpf_list_head *head) return __bpf_list_del(head, true); } =20 +__bpf_kfunc struct bpf_list_node *bpf_list_del(struct bpf_list_node *node) +{ + struct bpf_list_node_kern *knode =3D (struct bpf_list_node_kern *)node; + + if (unlikely(!knode)) + return NULL; + + if (WARN_ON_ONCE(!READ_ONCE(knode->owner))) + return NULL; + + list_del_init(&knode->list_head); + WRITE_ONCE(knode->owner, NULL); + + return node; +} + __bpf_kfunc struct bpf_list_node *bpf_list_front(struct bpf_list_head *hea= d) { struct list_head *h =3D (struct list_head *)head; @@ -4545,6 +4561,7 @@ BTF_ID_FLAGS(func, bpf_list_push_front_impl) BTF_ID_FLAGS(func, bpf_list_push_back_impl) BTF_ID_FLAGS(func, bpf_list_pop_front, KF_ACQUIRE | KF_RET_NULL) BTF_ID_FLAGS(func, bpf_list_pop_back, KF_ACQUIRE | KF_RET_NULL) +BTF_ID_FLAGS(func, bpf_list_del, KF_ACQUIRE | KF_RET_NULL) BTF_ID_FLAGS(func, bpf_list_front, KF_RET_NULL) BTF_ID_FLAGS(func, bpf_list_back, KF_RET_NULL) BTF_ID_FLAGS(func, bpf_task_acquire, KF_ACQUIRE | KF_RCU | KF_RET_NULL) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index a3390190c26e..1e9857177a7a 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -12431,6 +12431,7 @@ enum special_kfunc_type { KF_bpf_list_push_back_impl, KF_bpf_list_pop_front, KF_bpf_list_pop_back, + KF_bpf_list_del, KF_bpf_list_front, KF_bpf_list_back, KF_bpf_cast_to_kern_ctx, @@ -12491,6 +12492,7 @@ BTF_ID(func, bpf_list_push_front_impl) BTF_ID(func, bpf_list_push_back_impl) BTF_ID(func, bpf_list_pop_front) BTF_ID(func, bpf_list_pop_back) +BTF_ID(func, bpf_list_del) BTF_ID(func, bpf_list_front) BTF_ID(func, bpf_list_back) BTF_ID(func, bpf_cast_to_kern_ctx) @@ -12966,6 +12968,7 @@ static bool is_bpf_list_api_kfunc(u32 btf_id) btf_id =3D=3D special_kfunc_list[KF_bpf_list_push_back_impl] || btf_id =3D=3D special_kfunc_list[KF_bpf_list_pop_front] || btf_id =3D=3D special_kfunc_list[KF_bpf_list_pop_back] || + btf_id =3D=3D special_kfunc_list[KF_bpf_list_del] || btf_id =3D=3D special_kfunc_list[KF_bpf_list_front] || btf_id =3D=3D special_kfunc_list[KF_bpf_list_back]; } @@ -13088,7 +13091,8 @@ static bool check_kfunc_is_graph_node_api(struct bp= f_verifier_env *env, switch (node_field_type) { case BPF_LIST_NODE: ret =3D (kfunc_btf_id =3D=3D special_kfunc_list[KF_bpf_list_push_front_i= mpl] || - kfunc_btf_id =3D=3D special_kfunc_list[KF_bpf_list_push_back_impl= ]); + kfunc_btf_id =3D=3D special_kfunc_list[KF_bpf_list_push_back_impl= ] || + kfunc_btf_id =3D=3D special_kfunc_list[KF_bpf_list_del]); break; case BPF_RB_NODE: ret =3D (kfunc_btf_id =3D=3D special_kfunc_list[KF_bpf_rbtree_remove] || @@ -13211,6 +13215,9 @@ __process_kf_arg_ptr_to_graph_node(struct bpf_verif= ier_env *env, return -EINVAL; } =20 + if (!*node_field) + *node_field =3D field; + field =3D *node_field; =20 et =3D btf_type_by_id(field->graph_root.btf, field->graph_root.value_btf_= id); --=20 2.50.1 (Apple Git-155) From nobody Thu Apr 16 22:33:13 2026 Received: from mail-pj1-f53.google.com (mail-pj1-f53.google.com [209.85.216.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E78F4311C2A for ; Wed, 25 Feb 2026 09:27:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772011666; cv=none; b=Wiy0q7tOVSHzO8Ule4/8raLptcqnQU5JlmXuCKWjpjm+Y3nJqdvK3D5OrhD+A41VFtlIHGGDqc+OOXwAzBJ+zfxwR87VjBL62Z9XhTJ3t6cLuLZM63CUnNvYBp+9hcbKIgdyM/H+5Mg9AAof54bVpvJuiL9VJZlQUBExABzF/AE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772011666; c=relaxed/simple; bh=ntnkQefVl45lQLEojls73Rs/Y+YFDH/AmymklrtPohE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=lrme/2m2IPIL/aj3IWY+EL9yYJ1i49kYg2BtJKTH9TTXsEf82vtr98XiQbByc6r9eIGNuefduYObw4yvxofS9cxM8qfj+HM4HxYd5kdSPOLL6IET2ippbTKffpR0s3M1MGBPqjuEeU1GtfibrOtLPUR6BdZO/IKOirXSvHg0+FY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=b076u3PR; arc=none smtp.client-ip=209.85.216.53 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="b076u3PR" Received: by mail-pj1-f53.google.com with SMTP id 98e67ed59e1d1-358ed67cd4bso355857a91.0 for ; Wed, 25 Feb 2026 01:27:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772011663; x=1772616463; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=edeAv+lo1yi2ZetRpzlKqTFXrWjKU1IM+ewr9/GQxlk=; b=b076u3PRUo9NH4yBxsw0ocdQFubUZl9GwZfd5pywQn48+YjpU3vMoXmZrdsi5GbXxi 9YPfZo0BoAbVrHAqwOzi4apQtJg2+jWopn2XaUWsGuyqwRpsOhLCSiuHZ3MrF5Gjq5E7 +ZKKf5uFUrYxvT6Hp5lo9ozzoLWDsHx992gQ0SPYXbN1XKC9AUdQZynRT3jax/h8vtvK /UcOP7+L5PikaAMwGO+ST0KyNUcRIyxf7j/o4kJ1Binv3kV84hXNFu2v8I6G/m06Xunm zAo/vw5pYqYTWx8YofVYvkNkf+cnhASVFY5ew/e+FejCXdPxupe68QrxEZS/ZUadUdOG Cu6A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772011663; x=1772616463; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=edeAv+lo1yi2ZetRpzlKqTFXrWjKU1IM+ewr9/GQxlk=; b=ZAtRIiGW4yT2adFAmKXWPjmaNvj9U8aTvlzXX7f3kpDDkd9b049n0ytCvOM8Z8TEj2 PJ64lgubCyTXGb0/e11ovgyUdwso0X9AU6vwRee+hQ7y985xKDwALcAhJEx/aZT2vWZX 2+XMTvE59fIje/weW5SM1dPdG3x9LHcjtE4nDxQhN6evyp0meyngPw6Y8xAzfuGz7YjJ 0E6f2nmVa5g/osTUxA5ECJ+iXT2SrheXhL+IUF/yu4dafPYaj9ld1TTZvcGxynnza2ie QZTwBQ+ZcCLQHXlr9a6d6KS1Yz7txH0d8bPCrJNxHKYqXQGDq38oQ1Wll93LeU5Jp0SK g7CQ== X-Forwarded-Encrypted: i=1; AJvYcCWGmErTGBs1rnpSEV4U/H7n6jE+TCCasE4jUu1RKKqbJKTyULd9uAVnqHBr24MxJRzrMUKm2iE/C47tcJU=@vger.kernel.org X-Gm-Message-State: AOJu0YycTKdR8p7VO3oIVigosVdfQLMnxpTfwLo/bf7zjAOC58XmIYvO y/P4SaGSnc1lpz679BxeMYP10vG39fFqI28OX7B9RGOxN6eda4//2ka4 X-Gm-Gg: ATEYQzzSXyU6nk0dtnDtdK+w4VdYHN0eyH+oxAJgqGdpiS9bEPSiUwbV0h2iqZga0nB 9+i4nto4awhM3jG0TcmgNeM9JGT9XH32GhvisiSwTbJnWfzTnwNIYMPmlOCczyH5GzJfxecHZ5z 4TwurIKu+/lqnT8VIi1BRoepmPseW3yRVPalZ/uyEJf+7PJ14PZWvv6aIm9eNuIHCLbiVjsPK61 CzIM0kpFUeE0rZpfAJ+cxU1FStfMqzP2K/tcTitU2KBT8X/cuWyUhlt0IrWkSIRKyKKo55Yn4WQ VjaRBZBMPZhcub1drq0YCfKClqIG27c48KbVItqI1lP8LaF/fnQrHws8gTxehfGWzXhUfZQ2vFg 3AuVbtaC9yQ7SFe5lYSpmXLyutO0sTKNJhLhHHDNTrk/lXjSAW0+T9kYzN3EdNZUsyPxgj2viZ1 ebvu1XpmPZgSrtatB6Cv3GNwULF5rRRvceEz6I/VNXm2TcduQled8Quw== X-Received: by 2002:a17:90b:5787:b0:34c:7212:7a67 with SMTP id 98e67ed59e1d1-3590382bfabmr2213562a91.12.1772011663325; Wed, 25 Feb 2026 01:27:43 -0800 (PST) Received: from localhost.localdomain ([113.218.252.140]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-35912f5f29fsm837901a91.1.2026.02.25.01.27.30 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Wed, 25 Feb 2026 01:27:43 -0800 (PST) From: Chengkaitao To: martin.lau@linux.dev, ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org, eddyz87@gmail.com, song@kernel.org, yonghong.song@linux.dev, john.fastabend@gmail.com, kpsingh@kernel.org, sdf@fomichev.me, haoluo@google.com, jolsa@kernel.org, shuah@kernel.org, chengkaitao@kylinos.cn, leon.hwang@linux.dev, linux-kselftest@vger.kernel.org Cc: bpf@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 2/6] selftests/bpf: Add test cases for bpf_list_del Date: Wed, 25 Feb 2026 17:26:47 +0800 Message-ID: <20260225092651.94689-3-pilgrimtao@gmail.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20260225092651.94689-1-pilgrimtao@gmail.com> References: <20260225092651.94689-1-pilgrimtao@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Kaitao Cheng Add a node to both an rbtree and a list, retrieve the node from the rbtree, use the obtained node pointer to remove it from the list, and finally free the node. Signed-off-by: Kaitao Cheng --- .../testing/selftests/bpf/bpf_experimental.h | 10 +++++ .../selftests/bpf/progs/refcounted_kptr.c | 41 +++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/tools/testing/selftests/bpf/bpf_experimental.h b/tools/testing= /selftests/bpf/bpf_experimental.h index 4b7210c318dd..c7c950e10501 100644 --- a/tools/testing/selftests/bpf/bpf_experimental.h +++ b/tools/testing/selftests/bpf/bpf_experimental.h @@ -99,6 +99,16 @@ extern struct bpf_list_node *bpf_list_pop_front(struct b= pf_list_head *head) __ks */ extern struct bpf_list_node *bpf_list_pop_back(struct bpf_list_head *head)= __ksym; =20 +/* Description + * Remove 'node' from the BPF linked list with head 'head'. + * The node must be in the list. Caller receives ownership of the + * removed node and must release it with bpf_obj_drop. + * Returns + * Pointer to the removed bpf_list_node, or NULL if 'node' is NULL + * or not in the list. + */ +extern struct bpf_list_node *bpf_list_del(struct bpf_list_node *node) __ks= ym; + /* Description * Remove 'node' from rbtree with root 'root' * Returns diff --git a/tools/testing/selftests/bpf/progs/refcounted_kptr.c b/tools/te= sting/selftests/bpf/progs/refcounted_kptr.c index 1aca85d86aeb..86f7f5f8e4c8 100644 --- a/tools/testing/selftests/bpf/progs/refcounted_kptr.c +++ b/tools/testing/selftests/bpf/progs/refcounted_kptr.c @@ -367,6 +367,47 @@ long insert_rbtree_and_stash__del_tree_##rem_tree(void= *ctx) \ INSERT_STASH_READ(true, "insert_stash_read: remove from tree"); INSERT_STASH_READ(false, "insert_stash_read: don't remove from tree"); =20 +/* Insert node_data into both rbtree and list, remove from tree, then remo= ve + * from list via bpf_list_del using the node obtained from the tree. + */ +SEC("tc") +__description("test_bpf_list_del: remove an arbitrary node from the list") +__success __retval(0) +long test_bpf_list_del(void *ctx) +{ + long err; + struct bpf_rb_node *rb; + struct bpf_list_node *l; + struct node_data *n; + + err =3D __insert_in_tree_and_list(&head, &root, &lock); + if (err) + return err; + + bpf_spin_lock(&lock); + rb =3D bpf_rbtree_first(&root); + if (!rb) { + bpf_spin_unlock(&lock); + return -4; + } + + rb =3D bpf_rbtree_remove(&root, rb); + bpf_spin_unlock(&lock); + if (!rb) + return -5; + n =3D container_of(rb, struct node_data, r); + + bpf_spin_lock(&lock); + l =3D bpf_list_del(&n->l); + bpf_spin_unlock(&lock); + bpf_obj_drop(n); + if (!l) + return -6; + + bpf_obj_drop(container_of(l, struct node_data, l)); + return 0; +} + SEC("tc") __success long rbtree_refcounted_node_ref_escapes(void *ctx) --=20 2.50.1 (Apple Git-155) From nobody Thu Apr 16 22:33:13 2026 Received: from mail-pj1-f48.google.com (mail-pj1-f48.google.com [209.85.216.48]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8EB6938E104 for ; Wed, 25 Feb 2026 09:27:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.48 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772011680; cv=none; b=c5t5ovWtbhuESWj7CnG32yF/yzERrFTPhJ/V2TPVTadD6xcZFGNushI4Pr78qjeUaBVBZkjhW1x3O/d46mRZrYJYru5PJuAkfj8jYyiw7Zw3iD2H3NqFEotIZmk4BYI6PZml4S7eYJls2PNrYS8dzmTnUsnwDXGTpT+J6bLbRKE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772011680; c=relaxed/simple; bh=yXrH5rL6UTGlagvJh99nORU7wnrKGwIaVSCupkBW4K0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=F5E0C00JplGYfVkJF7h8gmA8sS5JoHo0hNwGfMNsQsOTMdd+pN9RleEHjFwUtoKQDj/Or5HxHCp4GQqSwXcLh6p/sz3QyWR3Cg3wWYRcb7kj66cCxSgDm6L8T4Jfa4HKOn2UxgdxK3dSBNkFzZj0Hj4qd0qBy/q7l7/HoZoMcKI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=BeGkM6Hu; arc=none smtp.client-ip=209.85.216.48 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="BeGkM6Hu" Received: by mail-pj1-f48.google.com with SMTP id 98e67ed59e1d1-354c825dc77so2947018a91.0 for ; Wed, 25 Feb 2026 01:27:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772011679; x=1772616479; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=9G/55UcWAx4kclxigcvG1vbLWUkcp/GEASDckWLnDsY=; b=BeGkM6HukGM5Vn0Vnp7LThhZOflsimtLtj41kE8v7QyswSORFFDrsFHdk24Nd9ZgHs TLYwmsRbvi9v85E+7iFtNDRXFtTOXaMQDkXGMc6/rB2D3nzB+eCHvsNIc20rPuyVFGMv BVtZsLkq1GZVzEzuf2dgMNU2aLAXrLS7oyyis+s2fSJrr/sTSkPn+qI/RkvRw8fhNSfW ruPdpGIfuvm/P3MwAu0Nc4pp0CsR4d4k/D+c9brNavpNjCOMf+n9YJq+k35qtC4oRRBu tfXEe1TJ6mLtPByoxYyQZN4FoqLDSqooQkf5l/IkkHrlYaTTwIZ4e0CdA/bWSfVTWqGO eEfw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772011679; x=1772616479; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=9G/55UcWAx4kclxigcvG1vbLWUkcp/GEASDckWLnDsY=; b=PC9Ho5PVd16kwotIu2YGsryskrO+ZZVaB+O7m6J3s4pwfccohVgvXF0r1WdmYcUzbs 7wkNF6GbcZg0UF9kHJUs2HAwVn8LJnUXoJM4S1o2FkN5nzFx04/2hcYGwAtPuqvpu9Ul BIdXOZORCJDSCfS/5xrgncGiW5jiZRPSHHPS9T+LnMVw75gMBaHQ+nzZiB0CeQp4gL1X L92LSCpzOt/BgDSNIu8bnxNaVSK3hKSgv3SRuTz+tZhqONZXuWEh9x96LBoxoFPeFfVR Do5ZxY2N+WmJpBCZQbwk921DkEGsPr7ntvQyefR31KST4sRhEvLgaSEN4NW2cVISE8dz RVGA== X-Forwarded-Encrypted: i=1; AJvYcCXP/1pG6dwbh/m16/Ehat6yw2hw2DUCYk5YZmabjW8SgDCJTLQZuXlmxGewTBvsaK5qeIIx5TV1CxqOEPI=@vger.kernel.org X-Gm-Message-State: AOJu0YyAVtm1qROjh1DsLmXtcJpRtrNI9FPos+WQg/mBaCOWDYjxYFYo Hst/cvmLeDkFO0NK+hmn4pVI9pg/GocjYDykttLsHt5iZPntDYOUx7gP X-Gm-Gg: ATEYQzxHwVTVVEgKMvuj2CPExgyiogXSaJEoHJhHrWwjv7f68EJv5eJMJWIe7ErJsSW zmZZbHbLuJyWKcFIUoOtiEREny5ara7On76Uf02CbeanwAnNsxx1b+J/6OJ1eNGgnLHDJ1kz30t TyrJDxCLpj6gNY3Om1nh2qWC4phI61yfbAAoQ2G0KBzNDcvIZutG9Jngefr7pAs5N8O9a8GEFA+ JI9ANXDX0uSDK8ckRe4JkC31W0HdboqEMODuajl9oT0hfA9f/UxwcR9x+lj+8DwsQPrkQm3UFgz qyv55JSt6iyC7klUFt13lHODBdXF2n71OXJdQ4GMJntKEoQvrfjT3AfyhTmusZoJ8aq0Ex/o27j josmuxwlAZ3q1mTXkXWENGobmD3O8Jh4e4tHWxphFbevtbkwxZItJx2akbOG4zijjonaVQ7RFkG ns0O9O9aU+NsdQhn1LXanTt7VuhHKyYE5Z0jQgga1AaaCvQHP2+Co9NA== X-Received: by 2002:a17:90b:2e0f:b0:32e:3829:a71c with SMTP id 98e67ed59e1d1-358ae8b23damr14852741a91.16.1772011678742; Wed, 25 Feb 2026 01:27:58 -0800 (PST) Received: from localhost.localdomain ([113.218.252.140]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-35912f5f29fsm837901a91.1.2026.02.25.01.27.43 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Wed, 25 Feb 2026 01:27:58 -0800 (PST) From: Chengkaitao To: martin.lau@linux.dev, ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org, eddyz87@gmail.com, song@kernel.org, yonghong.song@linux.dev, john.fastabend@gmail.com, kpsingh@kernel.org, sdf@fomichev.me, haoluo@google.com, jolsa@kernel.org, shuah@kernel.org, chengkaitao@kylinos.cn, leon.hwang@linux.dev, linux-kselftest@vger.kernel.org Cc: bpf@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 3/6] bpf: add bpf_list_add_impl to insert node after a given list node Date: Wed, 25 Feb 2026 17:26:48 +0800 Message-ID: <20260225092651.94689-4-pilgrimtao@gmail.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20260225092651.94689-1-pilgrimtao@gmail.com> References: <20260225092651.94689-1-pilgrimtao@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Kaitao Cheng Add a new kfunc bpf_list_add_impl(prev, node, meta, off) that inserts 'node' after 'prev' in the BPF linked list. Both must be in the same list; 'prev' must already be in the list. The new node must be an owning reference (e.g. from bpf_obj_new); the kfunc consumes that reference and the node becomes non-owning once inserted. Returns 0 on success, -EINVAL if prev is not in a list or node is already in a list (or duplicate insertion). On failure, the kernel drops the passed-in node. Signed-off-by: Kaitao Cheng --- kernel/bpf/helpers.c | 34 ++++++++++++++++++++++++++++++++++ kernel/bpf/verifier.c | 10 ++++++++-- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c index 577af62a9f7a..d212962d4ed6 100644 --- a/kernel/bpf/helpers.c +++ b/kernel/bpf/helpers.c @@ -2495,6 +2495,39 @@ __bpf_kfunc struct bpf_list_node *bpf_list_back(stru= ct bpf_list_head *head) return (struct bpf_list_node *)h->prev; } =20 +static int __bpf_list_add_after(struct bpf_list_node_kern *prev, + struct bpf_list_node_kern *node, + struct btf_record *rec, u64 off) +{ + struct bpf_list_head *head; + struct list_head *n =3D &node->list_head, *p =3D &prev->list_head; + + head =3D READ_ONCE(prev->owner); + if (unlikely(!head)) + goto fail; + + if (cmpxchg(&node->owner, NULL, BPF_PTR_POISON)) + goto fail; + + list_add(n, p); + WRITE_ONCE(node->owner, head); + return 0; + +fail: + __bpf_obj_drop_impl((void *)n - off, rec, false); + return -EINVAL; +} + +__bpf_kfunc int bpf_list_add_impl(struct bpf_list_node *prev, + struct bpf_list_node *node, + void *meta__ign, u64 off) +{ + struct bpf_list_node_kern *n =3D (void *)node, *p =3D (void *)prev; + struct btf_struct_meta *meta =3D meta__ign; + + return __bpf_list_add_after(p, n, meta ? meta->record : NULL, off); +} + __bpf_kfunc struct bpf_rb_node *bpf_rbtree_remove(struct bpf_rb_root *root, struct bpf_rb_node *node) { @@ -4564,6 +4597,7 @@ BTF_ID_FLAGS(func, bpf_list_pop_back, KF_ACQUIRE | KF= _RET_NULL) BTF_ID_FLAGS(func, bpf_list_del, KF_ACQUIRE | KF_RET_NULL) BTF_ID_FLAGS(func, bpf_list_front, KF_RET_NULL) BTF_ID_FLAGS(func, bpf_list_back, KF_RET_NULL) +BTF_ID_FLAGS(func, bpf_list_add_impl) BTF_ID_FLAGS(func, bpf_task_acquire, KF_ACQUIRE | KF_RCU | KF_RET_NULL) BTF_ID_FLAGS(func, bpf_task_release, KF_RELEASE) BTF_ID_FLAGS(func, bpf_rbtree_remove, KF_ACQUIRE | KF_RET_NULL) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 1e9857177a7a..923deb73683b 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -12434,6 +12434,7 @@ enum special_kfunc_type { KF_bpf_list_del, KF_bpf_list_front, KF_bpf_list_back, + KF_bpf_list_add_impl, KF_bpf_cast_to_kern_ctx, KF_bpf_rdonly_cast, KF_bpf_rcu_read_lock, @@ -12495,6 +12496,7 @@ BTF_ID(func, bpf_list_pop_back) BTF_ID(func, bpf_list_del) BTF_ID(func, bpf_list_front) BTF_ID(func, bpf_list_back) +BTF_ID(func, bpf_list_add_impl) BTF_ID(func, bpf_cast_to_kern_ctx) BTF_ID(func, bpf_rdonly_cast) BTF_ID(func, bpf_rcu_read_lock) @@ -12970,7 +12972,8 @@ static bool is_bpf_list_api_kfunc(u32 btf_id) btf_id =3D=3D special_kfunc_list[KF_bpf_list_pop_back] || btf_id =3D=3D special_kfunc_list[KF_bpf_list_del] || btf_id =3D=3D special_kfunc_list[KF_bpf_list_front] || - btf_id =3D=3D special_kfunc_list[KF_bpf_list_back]; + btf_id =3D=3D special_kfunc_list[KF_bpf_list_back] || + btf_id =3D=3D special_kfunc_list[KF_bpf_list_add_impl]; } =20 static bool is_bpf_rbtree_api_kfunc(u32 btf_id) @@ -13092,7 +13095,8 @@ static bool check_kfunc_is_graph_node_api(struct bp= f_verifier_env *env, case BPF_LIST_NODE: ret =3D (kfunc_btf_id =3D=3D special_kfunc_list[KF_bpf_list_push_front_i= mpl] || kfunc_btf_id =3D=3D special_kfunc_list[KF_bpf_list_push_back_impl= ] || - kfunc_btf_id =3D=3D special_kfunc_list[KF_bpf_list_del]); + kfunc_btf_id =3D=3D special_kfunc_list[KF_bpf_list_del] || + kfunc_btf_id =3D=3D special_kfunc_list[KF_bpf_list_add_impl]); break; case BPF_RB_NODE: ret =3D (kfunc_btf_id =3D=3D special_kfunc_list[KF_bpf_rbtree_remove] || @@ -14237,6 +14241,7 @@ static int check_kfunc_call(struct bpf_verifier_env= *env, struct bpf_insn *insn, =20 if (meta.func_id =3D=3D special_kfunc_list[KF_bpf_list_push_front_impl] || meta.func_id =3D=3D special_kfunc_list[KF_bpf_list_push_back_impl] || + meta.func_id =3D=3D special_kfunc_list[KF_bpf_list_add_impl] || meta.func_id =3D=3D special_kfunc_list[KF_bpf_rbtree_add_impl]) { release_ref_obj_id =3D regs[BPF_REG_2].ref_obj_id; insn_aux->insert_off =3D regs[BPF_REG_2].off; @@ -23203,6 +23208,7 @@ static int fixup_kfunc_call(struct bpf_verifier_env= *env, struct bpf_insn *insn, *cnt =3D 3; } else if (desc->func_id =3D=3D special_kfunc_list[KF_bpf_list_push_back_= impl] || desc->func_id =3D=3D special_kfunc_list[KF_bpf_list_push_front_impl] = || + desc->func_id =3D=3D special_kfunc_list[KF_bpf_list_add_impl] || desc->func_id =3D=3D special_kfunc_list[KF_bpf_rbtree_add_impl]) { struct btf_struct_meta *kptr_struct_meta =3D env->insn_aux_data[insn_idx= ].kptr_struct_meta; int struct_meta_reg =3D BPF_REG_3; --=20 2.50.1 (Apple Git-155) From nobody Thu Apr 16 22:33:13 2026 Received: from mail-pj1-f48.google.com (mail-pj1-f48.google.com [209.85.216.48]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C876B2DFA4A for ; Wed, 25 Feb 2026 09:28:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.48 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772011695; cv=none; b=Hpj/4iXmQonIio92IRoTU1nT+PohbckCcgoAy7vBa24wb1CBKASk54RZED/glxh9o6ECN0iHmX7gho2ojWmncnB5dPMAXbxgybr2iUOKXWgKy/0otKlKu/osH/kvrlEuaU2IQIsCUmfPL9LO9tTmmW0cNJcdew/yB8YPrY4qHvk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772011695; c=relaxed/simple; bh=TUkrUM5RCj94MKh5jKoSSPGDxsIxViCDTq4/BrGFtiE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=G9s+8vIZUeL3QMsfEt/SqHRXO0Hs87hp4cVmKh3qDFAJkLjw5jrQvYsOWmSRDwHzF/AqXCJza0PDgF7RJK/mA0i+lRTo0sM4nmXNnME9PHgPPzJGVTdx6jiGyZaXRNQ/Glhtg3VXQj9tgxrYQcb9gTV3tzVXNLyMCnh4dwBiMPI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=DJZ6UwZT; arc=none smtp.client-ip=209.85.216.48 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="DJZ6UwZT" Received: by mail-pj1-f48.google.com with SMTP id 98e67ed59e1d1-354c67da885so5506537a91.3 for ; Wed, 25 Feb 2026 01:28:14 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772011694; x=1772616494; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=DGuc+6wfePsL6aB6sAwQhLsZz/tjnZCJ1WumwwWFEEU=; b=DJZ6UwZTyMr0W95Lb1AuEzuqv9N/ofOUmirFuomUadNy69TSoZ4MdslSzSX+UJsc12 I2KR1hjsVkrW3mrPbt7eBdm5yE5Spyj5QnTvqVIoxt/Lh4HA1kTBsfxjl3OjvPe93qE3 BDfD71rTDtaf+0nl3lJYji7Ta07jaXXgr935EwJOIks7jmi9fkVXhYSOKk+gaVSZxwar lYJ9sgMgFjEoXJqlydV0go1S+c0eyhYAOfUV4Y70tOLCyjZeprvFFPdXaEFX3UwW2DAy 8rRHYaLyYWKlek9433FyakUkV+UlUylVcnOCeCaoASRwUjczfLND2JeUJhcrUOP2vcuq A65A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772011694; x=1772616494; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=DGuc+6wfePsL6aB6sAwQhLsZz/tjnZCJ1WumwwWFEEU=; b=OZB2Bo6sdSqUmfifhy8gmgFP7t9sIHwPbpw7NnApD+SMIs3ywx3M9O6q/ofhspvZ1I JbpZUcqWgLhvpldW2nyvF7KzL/Arpk0s7bJ3/wmNvdvaao+m8EE3EmJUf9qki5WHQOYl yrPfcLXhlCdPFm4YUnNwQHfE6irn5eu/urOcbbnbilvDTZU3dcgsGlCr5rHYts5wz6jP qBksyEf8qV2oFWsaNuD7UrS6p6fzY2Jkp6a8ItBDDteia1m5dbw2cGAXFC++tlYk7M8y 9aRscHyzQefY7HzS5tNoiPRnl4FVeo0SFqlA3PER4y2ZLmnA9EYZCqCwFko+pjeffHvb 3VkA== X-Forwarded-Encrypted: i=1; AJvYcCW4mxPmZwPHvgTezYSv7ggcRPSTfs5UZ3epSi8hM19ucSrXPW4id2Sc3/fsz3BHU+BJ5PFc0f50LqJe6/E=@vger.kernel.org X-Gm-Message-State: AOJu0Ywm+hEtNQQXBQ04AfXwIixDvjdKVIMo50VribFzMXd1/TDWyaNG pk+kXirVLFNa+BpSSBUeo6qihF6aHDebUCz7VW0HtXbFGiJrElrz5WDT X-Gm-Gg: ATEYQzxNMOW4x3czZFG8Uwwyvv0x81LcCNgh3sfxhfMsPngRaabdp+O52B9K8ttNomw F5VUMnLIK7mfIEpOZEgOdCWfM21LVf1d0sZtLywdEyF1jGFhaTBtMvuxYgEaQ+ij78pgF4v56ke 7TRwIrCfnJpa1v5BCrQtoHYlThBT4s1PJKQfLWKueEKZiCXHsQGqL+39JATbwMsafk1INKy04qe Rbfn0+cccCg2tth6NLG4AUlc612wB0KE+heIBqCIwmsDP9teVp4uhS0GpRqpx2cbAutZYBWbjoC UkD9H3DcYfYMPyvTdtFsA+8uGE/eRQ0R3OVN4tkmIA8hq3kFHaCgyhPs54otmsEpM6P+R06GV9r xGlvR4VmBKK1bDvgjF8A9lujIoPsvijVI1/DyJWBAA3PvoljbZJ7daEZK5FEtcj3P2ckB5v7h0u Fnt49GuK0+w4brXygSlkHSsomsB4mrh/0B/+Fp/Xu7VfguWWd7AUVavw== X-Received: by 2002:a17:90b:2250:b0:354:a546:5edd with SMTP id 98e67ed59e1d1-3590f060ffcmr1820592a91.11.1772011694049; Wed, 25 Feb 2026 01:28:14 -0800 (PST) Received: from localhost.localdomain ([113.218.252.140]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-35912f5f29fsm837901a91.1.2026.02.25.01.27.59 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Wed, 25 Feb 2026 01:28:13 -0800 (PST) From: Chengkaitao To: martin.lau@linux.dev, ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org, eddyz87@gmail.com, song@kernel.org, yonghong.song@linux.dev, john.fastabend@gmail.com, kpsingh@kernel.org, sdf@fomichev.me, haoluo@google.com, jolsa@kernel.org, shuah@kernel.org, chengkaitao@kylinos.cn, leon.hwang@linux.dev, linux-kselftest@vger.kernel.org Cc: bpf@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 4/6] selftests/bpf: Add test case for bpf_list_add_impl Date: Wed, 25 Feb 2026 17:26:49 +0800 Message-ID: <20260225092651.94689-5-pilgrimtao@gmail.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20260225092651.94689-1-pilgrimtao@gmail.com> References: <20260225092651.94689-1-pilgrimtao@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Kaitao Cheng Extend refcounted_kptr test (test_list_add_del) to exercise bpf_list_add: add a second node after the first, then bpf_list_del both nodes. Signed-off-by: Kaitao Cheng --- .../testing/selftests/bpf/bpf_experimental.h | 13 +++++ .../selftests/bpf/progs/refcounted_kptr.c | 51 +++++++++++++++---- 2 files changed, 53 insertions(+), 11 deletions(-) diff --git a/tools/testing/selftests/bpf/bpf_experimental.h b/tools/testing= /selftests/bpf/bpf_experimental.h index c7c950e10501..dc3919deab89 100644 --- a/tools/testing/selftests/bpf/bpf_experimental.h +++ b/tools/testing/selftests/bpf/bpf_experimental.h @@ -109,6 +109,19 @@ extern struct bpf_list_node *bpf_list_pop_back(struct = bpf_list_head *head) __ksy */ extern struct bpf_list_node *bpf_list_del(struct bpf_list_node *node) __ks= ym; =20 +/* Description + * Insert 'node' after 'prev' in the BPF linked list. Both must be in the + * same list; 'prev' must be in the list. The 'meta' and 'off' parameters + * are rewritten by the verifier, no need for BPF programs to set them. + * Returns + * 0 on success, -EINVAL if prev is not in a list or node is already in a = list. + */ +extern int bpf_list_add_impl(struct bpf_list_node *prev, struct bpf_list_n= ode *node, + void *meta, __u64 off) __ksym; + +/* Convenience macro to wrap over bpf_list_add_impl */ +#define bpf_list_add(prev, node) bpf_list_add_impl(prev, node, NULL, 0) + /* Description * Remove 'node' from rbtree with root 'root' * Returns diff --git a/tools/testing/selftests/bpf/progs/refcounted_kptr.c b/tools/te= sting/selftests/bpf/progs/refcounted_kptr.c index 86f7f5f8e4c8..a3d5995d4302 100644 --- a/tools/testing/selftests/bpf/progs/refcounted_kptr.c +++ b/tools/testing/selftests/bpf/progs/refcounted_kptr.c @@ -367,18 +367,19 @@ long insert_rbtree_and_stash__del_tree_##rem_tree(voi= d *ctx) \ INSERT_STASH_READ(true, "insert_stash_read: remove from tree"); INSERT_STASH_READ(false, "insert_stash_read: don't remove from tree"); =20 -/* Insert node_data into both rbtree and list, remove from tree, then remo= ve - * from list via bpf_list_del using the node obtained from the tree. +/* Insert one node in tree and list, remove it from tree, add a second + * node after it in list with bpf_list_add, then remove both nodes from + * list via bpf_list_del. */ SEC("tc") -__description("test_bpf_list_del: remove an arbitrary node from the list") +__description("test_list_add_del: test bpf_list_add/del") __success __retval(0) -long test_bpf_list_del(void *ctx) +long test_list_add_del(void *ctx) { - long err; + long err =3D 0; struct bpf_rb_node *rb; - struct bpf_list_node *l; - struct node_data *n; + struct bpf_list_node *l, *l_1; + struct node_data *n, *n_1, *m_1; =20 err =3D __insert_in_tree_and_list(&head, &root, &lock); if (err) @@ -397,15 +398,43 @@ long test_bpf_list_del(void *ctx) return -5; n =3D container_of(rb, struct node_data, r); =20 + n_1 =3D bpf_obj_new(typeof(*n_1)); + if (!n_1) { + bpf_obj_drop(n); + return -1; + } + m_1 =3D bpf_refcount_acquire(n_1); + if (!m_1) { + bpf_obj_drop(n); + bpf_obj_drop(n_1); + return -1; + } + bpf_spin_lock(&lock); + if (bpf_list_add(&n->l, &n_1->l)) { + bpf_spin_unlock(&lock); + bpf_obj_drop(n); + bpf_obj_drop(m_1); + return -8; + } + l =3D bpf_list_del(&n->l); + l_1 =3D bpf_list_del(&m_1->l); bpf_spin_unlock(&lock); bpf_obj_drop(n); - if (!l) - return -6; + bpf_obj_drop(m_1); =20 - bpf_obj_drop(container_of(l, struct node_data, l)); - return 0; + if (l) + bpf_obj_drop(container_of(l, struct node_data, l)); + else + err =3D -6; + + if (l_1) + bpf_obj_drop(container_of(l_1, struct node_data, l)); + else + err =3D -6; + + return err; } =20 SEC("tc") --=20 2.50.1 (Apple Git-155) From nobody Thu Apr 16 22:33:13 2026 Received: from mail-pj1-f54.google.com (mail-pj1-f54.google.com [209.85.216.54]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 99F7321A453 for ; Wed, 25 Feb 2026 09:28:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.54 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772011714; cv=none; b=jLOJkUBwmONdTA+bR+NJW+lCcrPdeCwWuEOwbNy9gdGIqf363U1xLDkes2hHumtyMULJhONb+bwH6sqhDybH1aJ6D0ebEF5KzKALO7Evy8hw/vRu7V3eX8gUom0gHtJLV8JLTl5As6fFotoB1Z4SyjLD5vB4adnG+KagTiF1alM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772011714; c=relaxed/simple; bh=MtGZ1s9d0Ohu8LVtS1x+dMK9rylCalqlFA6D7V3l7Ro=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=rzb3sY+oBGWpOJCOJCzfokBgrhu/PkQAB5Oq1dWdozXWzSlmTzlDOKg7ed9SbXl+RZREUVlsF5alPbd/a4tLkKujNRL5wVJH2Wooh1tSY324b+9B7Y3IihJVjkTBmkxtFEgLBZ1UStUAY0QtoCu+iMBaKCnLZvM0P1Jn19xqNrc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=IJ7vnRzM; arc=none smtp.client-ip=209.85.216.54 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="IJ7vnRzM" Received: by mail-pj1-f54.google.com with SMTP id 98e67ed59e1d1-3591cc98871so41258a91.3 for ; Wed, 25 Feb 2026 01:28:33 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772011713; x=1772616513; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=jcNjMPltPtLcCQ8lC4dQD+ECjUO8JYcdiEXegBoi6yA=; b=IJ7vnRzMWIosw+fn1X84Dv/FciYW0nbnyW6ij8AoUaJqLsFPG92mHyaYBSrkG6hd5w vNOxXanELbPPw1DqtHSirSc5LItDmpwXd2m0ukyx/LH8z4SW+Jdu1OzCTv0vvHzXQVZu btsSavK2hE10aN/jVxxMbk+S/gKqlooLnmRKcIufkn9C1tID7xJIGUDsGMBzd/BQUuLd jR7jYuV9Axjg2eZG9Gv3/3CRGrHCSZs6qzxEN82tcQr5ZKtziw2L0cohj3Cumu1dQSH+ ADnYk+OgN11OVhZVOMrT2wVkfrOV3OeA/wZgkQu8qgbTRWOH0q5DR6eDiAqKhg+75ymW h5mQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772011713; x=1772616513; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=jcNjMPltPtLcCQ8lC4dQD+ECjUO8JYcdiEXegBoi6yA=; b=v1XaRXQVLjwzCYpWF/J8Op1e9RPcuT6L66BsndVnUpUKYA+eVgNGQtky+aHlgDiPcX a2n90bsZArSbsmXtDGlaJvKPagtHHXTnslKJQCwiul6rPavkJvBal3z7NphbjAnam/Fo ZiEiE3tJohbbab3XtgtDOMv/zPPf3aMb2ChU51onLyrQiR+8o8apvtXp2U/Kd3EuycGA POcTNXHa/PXtIqXtIUncm+b4bxkvelZhSdjnwEHixdveKxAbIvBV78YaVm7wQpXXF0BL lYhwYyAoiWMNNVIpWF95Vo6m/Sn8DTBCe94N2ZlpUDBWHh9NGjVvezPMohkPZHNIkFz2 uxhA== X-Forwarded-Encrypted: i=1; AJvYcCWFV3tBmcxQekH0r9XN45pmH/OZ7qCI2owQY7woORgCHSW4IiJTXrwi70GFRI0+2rrgLFNFDS905BHJtQg=@vger.kernel.org X-Gm-Message-State: AOJu0Ywvzj29h8Wq6BhFelkDd9658qROUCFwrQzK1bclrx7PuYpCz+nZ 0RWTtoFaOEZT+5P/sHu3YB5W0SPUzzxBj3OTGTra/M5h3Onax0MVTmIf X-Gm-Gg: ATEYQzyewiZo97Fug3TZfUDnSthO6tjIvqQJ+9MU7YGAqdY1KvMG7eodTXJrlSoXVsW B9qEIRHX4YtdtRUMnMDcxcpWobPHPE4JUYEEeQpC1wo9h7KfSpYVgMUdcySjTrygZoLTD64ZoUr /SMovJLf4Mpoz8IoKDXmCS8zkmNzAdJvi4yCl1BH0yjSqab+yxJ2yh0J9i+5TXSxRroaKDC51Y1 UHDX2+Fz5etE8c+EAjR3eMyGtPre1dzK6WODewtbED5H45V7NV+ubT8fLNrvoaasB1CM7lftkcS KDmI9dv0fsC0A5dFRoiiK8vkuTh1RGTq7dWM48iLwHlbPVgNItNtLBzZRwlk3xZ0UcPMl2B/2wp iCiNXpdMLky5XOAZTBxt9FRHBIfo98ALDPpNcRa3G+2BMVW0oBZCYBbjADnlyT5OvjjEt6ptwAA jBpCDN8IcPlrmCUVf8u2SjuXcZaMSOEj0rMFxuo3cyoHwj5mBFs/dWqXzhkGNaaUhG X-Received: by 2002:a17:90b:4c4f:b0:358:e7bc:429 with SMTP id 98e67ed59e1d1-358e7bc080bmr4543609a91.0.1772011712956; Wed, 25 Feb 2026 01:28:32 -0800 (PST) Received: from localhost.localdomain ([113.218.252.140]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-35912f5f29fsm837901a91.1.2026.02.25.01.28.14 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Wed, 25 Feb 2026 01:28:32 -0800 (PST) From: Chengkaitao To: martin.lau@linux.dev, ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org, eddyz87@gmail.com, song@kernel.org, yonghong.song@linux.dev, john.fastabend@gmail.com, kpsingh@kernel.org, sdf@fomichev.me, haoluo@google.com, jolsa@kernel.org, shuah@kernel.org, chengkaitao@kylinos.cn, leon.hwang@linux.dev, linux-kselftest@vger.kernel.org Cc: bpf@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 5/6] bpf: add bpf_list_is_first/last/empty kfuncs Date: Wed, 25 Feb 2026 17:26:50 +0800 Message-ID: <20260225092651.94689-6-pilgrimtao@gmail.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20260225092651.94689-1-pilgrimtao@gmail.com> References: <20260225092651.94689-1-pilgrimtao@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Kaitao Cheng Add three kfuncs for BPF linked list queries: - bpf_list_is_first(head, node): true if node is the first in the list. - bpf_list_is_last(head, node): true if node is the last in the list. - bpf_list_empty(head): true if the list has no entries. In previous versions, to implement the above functionality, it was necessary to first call bpf_list_pop_front/back to retrieve the first or last node before checking whether the passed-in node was the first or last one. After the check, the node had to be pushed back into the list using bpf_list_push_front/back, which was very inefficient. Now, with the bpf_list_is_first/last/empty kfuncs, we can directly check whether a node is the first, last, or whether the list is empty, without having to first retrieve the node. Signed-off-by: Kaitao Cheng --- kernel/bpf/helpers.c | 41 +++++++++++++++++++++++++++++++++++++++++ kernel/bpf/verifier.c | 15 +++++++++++++-- 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c index d212962d4ed6..ada14eca58ab 100644 --- a/kernel/bpf/helpers.c +++ b/kernel/bpf/helpers.c @@ -2528,6 +2528,44 @@ __bpf_kfunc int bpf_list_add_impl(struct bpf_list_no= de *prev, return __bpf_list_add_after(p, n, meta ? meta->record : NULL, off); } =20 +__bpf_kfunc bool bpf_list_is_first(struct bpf_list_head *head, struct bpf_= list_node *node) +{ + struct list_head *h =3D (struct list_head *)head; + struct bpf_list_node_kern *n =3D (struct bpf_list_node_kern *)node; + + if (unlikely(!h->next) || list_empty(h)) + return false; + + if (READ_ONCE(n->owner) !=3D head) + return false; + + return h->next =3D=3D &n->list_head; +} + +__bpf_kfunc bool bpf_list_is_last(struct bpf_list_head *head, struct bpf_l= ist_node *node) +{ + struct list_head *h =3D (struct list_head *)head; + struct bpf_list_node_kern *n =3D (struct bpf_list_node_kern *)node; + + if (unlikely(!h->next) || list_empty(h)) + return false; + + if (READ_ONCE(n->owner) !=3D head) + return false; + + return h->prev =3D=3D &n->list_head; +} + +__bpf_kfunc bool bpf_list_empty(struct bpf_list_head *head) +{ + struct list_head *h =3D (struct list_head *)head; + + if (unlikely(!h->next)) + return true; + + return list_empty(h); +} + __bpf_kfunc struct bpf_rb_node *bpf_rbtree_remove(struct bpf_rb_root *root, struct bpf_rb_node *node) { @@ -4598,6 +4636,9 @@ BTF_ID_FLAGS(func, bpf_list_del, KF_ACQUIRE | KF_RET_= NULL) BTF_ID_FLAGS(func, bpf_list_front, KF_RET_NULL) BTF_ID_FLAGS(func, bpf_list_back, KF_RET_NULL) BTF_ID_FLAGS(func, bpf_list_add_impl) +BTF_ID_FLAGS(func, bpf_list_is_first) +BTF_ID_FLAGS(func, bpf_list_is_last) +BTF_ID_FLAGS(func, bpf_list_empty) BTF_ID_FLAGS(func, bpf_task_acquire, KF_ACQUIRE | KF_RCU | KF_RET_NULL) BTF_ID_FLAGS(func, bpf_task_release, KF_RELEASE) BTF_ID_FLAGS(func, bpf_rbtree_remove, KF_ACQUIRE | KF_RET_NULL) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 923deb73683b..149eac5f70e3 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -12435,6 +12435,9 @@ enum special_kfunc_type { KF_bpf_list_front, KF_bpf_list_back, KF_bpf_list_add_impl, + KF_bpf_list_is_first, + KF_bpf_list_is_last, + KF_bpf_list_empty, KF_bpf_cast_to_kern_ctx, KF_bpf_rdonly_cast, KF_bpf_rcu_read_lock, @@ -12497,6 +12500,9 @@ BTF_ID(func, bpf_list_del) BTF_ID(func, bpf_list_front) BTF_ID(func, bpf_list_back) BTF_ID(func, bpf_list_add_impl) +BTF_ID(func, bpf_list_is_first) +BTF_ID(func, bpf_list_is_last) +BTF_ID(func, bpf_list_empty) BTF_ID(func, bpf_cast_to_kern_ctx) BTF_ID(func, bpf_rdonly_cast) BTF_ID(func, bpf_rcu_read_lock) @@ -12973,7 +12979,10 @@ static bool is_bpf_list_api_kfunc(u32 btf_id) btf_id =3D=3D special_kfunc_list[KF_bpf_list_del] || btf_id =3D=3D special_kfunc_list[KF_bpf_list_front] || btf_id =3D=3D special_kfunc_list[KF_bpf_list_back] || - btf_id =3D=3D special_kfunc_list[KF_bpf_list_add_impl]; + btf_id =3D=3D special_kfunc_list[KF_bpf_list_add_impl] || + btf_id =3D=3D special_kfunc_list[KF_bpf_list_is_first] || + btf_id =3D=3D special_kfunc_list[KF_bpf_list_is_last] || + btf_id =3D=3D special_kfunc_list[KF_bpf_list_empty]; } =20 static bool is_bpf_rbtree_api_kfunc(u32 btf_id) @@ -13096,7 +13105,9 @@ static bool check_kfunc_is_graph_node_api(struct bp= f_verifier_env *env, ret =3D (kfunc_btf_id =3D=3D special_kfunc_list[KF_bpf_list_push_front_i= mpl] || kfunc_btf_id =3D=3D special_kfunc_list[KF_bpf_list_push_back_impl= ] || kfunc_btf_id =3D=3D special_kfunc_list[KF_bpf_list_del] || - kfunc_btf_id =3D=3D special_kfunc_list[KF_bpf_list_add_impl]); + kfunc_btf_id =3D=3D special_kfunc_list[KF_bpf_list_add_impl] || + kfunc_btf_id =3D=3D special_kfunc_list[KF_bpf_list_is_first] || + kfunc_btf_id =3D=3D special_kfunc_list[KF_bpf_list_is_last]); break; case BPF_RB_NODE: ret =3D (kfunc_btf_id =3D=3D special_kfunc_list[KF_bpf_rbtree_remove] || --=20 2.50.1 (Apple Git-155) From nobody Thu Apr 16 22:33:13 2026 Received: from mail-pj1-f52.google.com (mail-pj1-f52.google.com [209.85.216.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 20F0A38E5CE for ; Wed, 25 Feb 2026 09:28:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772011728; cv=none; b=tRjH8eyv1XEP3Pp9mmxuQstt9df7KimvYgevq4D3yyl9TOTbpsbHYzvAbFUSeZziiVr4S1TCGqsZ0C3VytBKVCkrxuLVuH4k/0wbrHR07XQ04ZOEVUlRXAWwrqnu1y9i3EXRKE02PQYtKjVLzJzbtHvAkunA1BimjG5gWW6JE18= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772011728; c=relaxed/simple; bh=I8o4y5mNT6NBUdK1Hz51XMHixYT0zeMuuzrQvMT/nDI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=V8aOj4hK6tHocvLIilgzKRjrGqYyjzQ+HCacmnDaLfDnhD67CEyhMi0YHqfmtE+6VKE9KL91Y2w2clF7rUrYNA/CrS8e3PwMLk183ZffTHCNcSHN/fkBGQ/GpefNnz1zqqmqUxmbWZzEnA25WhdFW4k9Lt4j8ZN9P6Rovz8Wj0o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=PPPhBcFd; arc=none smtp.client-ip=209.85.216.52 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="PPPhBcFd" Received: by mail-pj1-f52.google.com with SMTP id 98e67ed59e1d1-354c67da885so5506891a91.3 for ; Wed, 25 Feb 2026 01:28:46 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772011726; x=1772616526; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=UV/LTk2gfEB8ll8anEm9MRkQrafSl1LusFUtX+b2yMA=; b=PPPhBcFdonPI+yS9Aklf/86qn5UGvTzo7dQBIxaJq3i8l7bsC98kmDkYW3dsUzVJB+ hT8jCjGEzlnjd0Sfka6RFH+DZZDmvF4CJbqM9PrMMHD3QEWi/6RoqWIMz0hZEaUtTjM+ N4BwjnVUK19bmi/F5/BRILCdszkgbyNwQP4XZMiDctIfxfGY3+0Pj9+krQU1W9lrKbRJ tO4skn+CBxbt5ojt4LViEQDTBMfrAm8E7ZCNZZoD8r6EAjx9QKOW43eDyhmegI90dHGI EenWzgXm1la6qhqa+6LznLEv2XTybllxlW/JgGztmdi9/zT0FfWVWQ3yHlNd5IXxPjWi UJ0w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772011726; x=1772616526; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=UV/LTk2gfEB8ll8anEm9MRkQrafSl1LusFUtX+b2yMA=; b=bjnZ1R+nVIPEY4mZTOunZLpzBSgBLXWCAcUD632rgtNTJzA/lxJK5cepGg790FQBm4 X9DCGvd8vFs0xq4u+7KP2wL61+HeGnu4voDc9dcrHc8sVJE124o0trdFx9EMfUwXzEQq Bp2B4o+1LHi9wIP6LdDOxg+PqMMLkyE0VsCoGGKSh7/p0FGwfd+nQaJpM2IzGS/5ehM6 xAkCdzlKgoShTudfOmswmyZtZaiRFfijmVaVnF34X83WCr9uazZEsoktxIY7foF7BCRJ CJfzyrDqqkDq6kMreXYhTRv3PRJcP+wmT3UUf8eC+lkNaFOPmcAqXTwqfRzIa3/I3jzj OomQ== X-Forwarded-Encrypted: i=1; AJvYcCURy3G+XV6YTyfwBkn63+aSnABnyW5HiYxPlDqHatrq0EZoaYYYYyrofe2Zd0lQ0jhggRZpd/IFfDfI95M=@vger.kernel.org X-Gm-Message-State: AOJu0Yw8l1IYtqvnAXZxS//l9Uj5x2ntc+nKdOun0cysxX8AYaU5HRGG 8INGddooUydPjq88HjIcQDngAfuzyBXmbRtwwq/3tGJTLAGQBvoP58K4 X-Gm-Gg: ATEYQzxNRF3FNxlQ13ArHd3gb3D5kZUbWSW53CJuzLsd1JVANACHwWWmqKXI4L8jfuV 4DPvMuv5u1fxseOYOPfZy82eV4o6BzfeF0HGg0Ln5nOPgP3ZJSQTAxTMM5zOdf8fBkazyAAcKY2 Jmmfuxhzw3GI0PJw9IYg+1agBWh9AMJaQW9ZKx/eBDF808Fpde3jZxWvU9D/VXJOPelo332heC5 EObhRtwb6HAkvJYX5/APk2WlQhKB3x8EpAOqFKq7L/C8RJnDl3h4clNirjOsSQE13M++zTeRJ8F fsgqFgUTCjOlwtssPzvIa3Fo6NkCdDEGy2rmjJWnwJV7zGnzLdYFTb1n9dHodEDTq2XObLMwudn c3F/aFptVdJu6+CsuqTXvZDJq+OnDc4TK46IKBmezJ9OsA29wf6pbIoP5PRiUuqyGWTGZP7HKcf pPwElDx8xzFWF0hSU7H2sR1qRLG/uAlcJRX+D1s90ZKAQ09YQadpZSHlUwCkIxZBgC X-Received: by 2002:a17:90b:2681:b0:356:72f3:acaf with SMTP id 98e67ed59e1d1-3590f2552b5mr1428352a91.32.1772011726439; Wed, 25 Feb 2026 01:28:46 -0800 (PST) Received: from localhost.localdomain ([113.218.252.140]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-35912f5f29fsm837901a91.1.2026.02.25.01.28.33 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Wed, 25 Feb 2026 01:28:46 -0800 (PST) From: Chengkaitao To: martin.lau@linux.dev, ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org, eddyz87@gmail.com, song@kernel.org, yonghong.song@linux.dev, john.fastabend@gmail.com, kpsingh@kernel.org, sdf@fomichev.me, haoluo@google.com, jolsa@kernel.org, shuah@kernel.org, chengkaitao@kylinos.cn, leon.hwang@linux.dev, linux-kselftest@vger.kernel.org Cc: bpf@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 6/6] selftests/bpf: Add test cases for bpf_list_is_first/is_last/empty Date: Wed, 25 Feb 2026 17:26:51 +0800 Message-ID: <20260225092651.94689-7-pilgrimtao@gmail.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20260225092651.94689-1-pilgrimtao@gmail.com> References: <20260225092651.94689-1-pilgrimtao@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Kaitao Cheng Rename test_list_add_del to list_add_del_and_check and extend it to cover the new kfuncs: assert list non-empty after insert, assert is_first(n) and is_last(m_1) after bpf_list_add, and assert list empty after removing both nodes. Signed-off-by: Kaitao Cheng --- .../testing/selftests/bpf/bpf_experimental.h | 15 +++++++++++ .../selftests/bpf/progs/refcounted_kptr.c | 27 +++++++++++++++---- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/tools/testing/selftests/bpf/bpf_experimental.h b/tools/testing= /selftests/bpf/bpf_experimental.h index dc3919deab89..fc73a276c268 100644 --- a/tools/testing/selftests/bpf/bpf_experimental.h +++ b/tools/testing/selftests/bpf/bpf_experimental.h @@ -122,6 +122,21 @@ extern int bpf_list_add_impl(struct bpf_list_node *pre= v, struct bpf_list_node *n /* Convenience macro to wrap over bpf_list_add_impl */ #define bpf_list_add(prev, node) bpf_list_add_impl(prev, node, NULL, 0) =20 +/* Description + * Return true if 'node' is the first node in the list with head 'head'. + */ +extern bool bpf_list_is_first(struct bpf_list_head *head, struct bpf_list_= node *node) __ksym; + +/* Description + * Return true if 'node' is the last node in the list with head 'head'. + */ +extern bool bpf_list_is_last(struct bpf_list_head *head, struct bpf_list_n= ode *node) __ksym; + +/* Description + * Return true if the list with head 'head' has no entries. + */ +extern bool bpf_list_empty(struct bpf_list_head *head) __ksym; + /* Description * Remove 'node' from rbtree with root 'root' * Returns diff --git a/tools/testing/selftests/bpf/progs/refcounted_kptr.c b/tools/te= sting/selftests/bpf/progs/refcounted_kptr.c index a3d5995d4302..aa4ee68c8baf 100644 --- a/tools/testing/selftests/bpf/progs/refcounted_kptr.c +++ b/tools/testing/selftests/bpf/progs/refcounted_kptr.c @@ -367,14 +367,14 @@ long insert_rbtree_and_stash__del_tree_##rem_tree(voi= d *ctx) \ INSERT_STASH_READ(true, "insert_stash_read: remove from tree"); INSERT_STASH_READ(false, "insert_stash_read: don't remove from tree"); =20 -/* Insert one node in tree and list, remove it from tree, add a second - * node after it in list with bpf_list_add, then remove both nodes from - * list via bpf_list_del. +/* Insert one node in tree and list, remove it from tree, add a second node + * after it with bpf_list_add, check bpf_list_is_first/is_last/empty, then + * remove both nodes from list via bpf_list_del. */ SEC("tc") -__description("test_list_add_del: test bpf_list_add/del") +__description("list_add_del_and_check: test bpf_list_add/del/is_first/is_l= ast/empty") __success __retval(0) -long test_list_add_del(void *ctx) +long list_add_del_and_check(void *ctx) { long err =3D 0; struct bpf_rb_node *rb; @@ -386,6 +386,11 @@ long test_list_add_del(void *ctx) return err; =20 bpf_spin_lock(&lock); + if (bpf_list_empty(&head)) { + bpf_spin_unlock(&lock); + return -7; + } + rb =3D bpf_rbtree_first(&root); if (!rb) { bpf_spin_unlock(&lock); @@ -418,6 +423,14 @@ long test_list_add_del(void *ctx) return -8; } =20 + if (!bpf_list_is_first(&head, &n->l) || + !bpf_list_is_last(&head, &m_1->l)) { + bpf_spin_unlock(&lock); + bpf_obj_drop(n); + bpf_obj_drop(m_1); + return -9; + } + l =3D bpf_list_del(&n->l); l_1 =3D bpf_list_del(&m_1->l); bpf_spin_unlock(&lock); @@ -434,6 +447,10 @@ long test_list_add_del(void *ctx) else err =3D -6; =20 + bpf_spin_lock(&lock); + if (!bpf_list_empty(&head)) + err =3D -7; + bpf_spin_unlock(&lock); return err; } =20 --=20 2.50.1 (Apple Git-155)