From nobody Sun Feb 8 05:42:14 2026 Received: from mail-dl1-f73.google.com (mail-dl1-f73.google.com [74.125.82.73]) (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 24D523346B9 for ; Thu, 8 Jan 2026 22:56:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767913007; cv=none; b=qFI3ZHKM+yPtrChsgA4gGuh6oaFkB7o8QeIYUE7SdUvP82vXfIatVX7gfDQAS5eK03IPTU+/etcigbKoB4YSXWOPtk/L7f0saHoi0td+ScvaI7AER6ElYqsxcxI7pf6cgcdag0W/w19ts+jAL+0ZaGv654a/hH41KBf7Xz/IRZA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767913007; c=relaxed/simple; bh=O6ot7CPctdPFw6WHudhxbDM8ZE4E8EaTJG3EnZslIx8=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=s9PJnWQ/mj4LXFjzfIAwNjp7qFel+N0TF55gzySncLRbdEiLL5tO1wxWJ1c9gCIFKA7oYhHkpeuSW30N0MZUWc1tpQc7riXktRSafqHBML+TMbGBfQrCCtze9qcd+2X6vuQvy1JAXwuzDiKUvl+IwCDed1o0cW15xdrRWQ4cjXA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--wusamuel.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=rEWcm3Fz; arc=none smtp.client-ip=74.125.82.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--wusamuel.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="rEWcm3Fz" Received: by mail-dl1-f73.google.com with SMTP id a92af1059eb24-1219f27037fso14336819c88.1 for ; Thu, 08 Jan 2026 14:56:46 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1767913005; x=1768517805; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=dJJFhVKyiKKoV+I6tkl9SP4apjw+O1s0pu7zT4uXhoI=; b=rEWcm3FzBG6Quo3FVczNQFeX1M/PpmRajo9yqRGjOQOAtrr6/2wig65ycv293oDUE0 N4jrSbe9T7kAzh+kl1aSApqqrZO8bprMvnPYxHocYFtWPbgbBuMEIaKwX19iuvVT77XS Rc4iyrl4g+XjNgzQlFrD1sCb22649XBilp/En8r3Iin02qAeqBm8gZUtsj8q8S47fPf2 G2CuDsDxQIJgSr+YDYmiEwyH3DsLoqf5w4hevb707LQ8fPEaXvsp9KE/3h5C1Ao9Q5td ceJI1ykbvcj8Nu0utoEyBKp7RAiJP2bL1XxUBLuU/M7u0pww6iUeiphZAjaulAiHGD6u Qaug== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1767913005; x=1768517805; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=dJJFhVKyiKKoV+I6tkl9SP4apjw+O1s0pu7zT4uXhoI=; b=d63t/yfBrgjo33tttpvC5qHqYxqUDYQ/diNIYx9sitGZDxNMpMpDZ7zG43f5MQdARY r0wrlN2F95hQnwX6Tqj8lTqSRK6nWBUtpIge/vAxuqpqaiURH+k/Jt8ejOwbjW5nirCn auB0wXafPphcWgV6THnQA7G2BygUSANcXbOeoYcgc0tvutBFHcStT6ZxVSY2JrhFXZ/b Jznb3I7QsiGqYa4zGpuVJo3TYUkpKa6CFe1C7d1+aWGCWsXSY7uXfyGZ+U4FkTbCo4z7 yZox+36YpJOIDLmPwdFkOmRyuh/Lt08m96toChtumCRymCHcRiLp2iRQTVYFcPhYFi6y P6Tg== X-Forwarded-Encrypted: i=1; AJvYcCW9LtR0Cc5qBauJ+BEUSi1JLDVPw+HOSmhGQOBHmeP8Oy7VPOWiS3yN6xte3idv4cOgt8uZ1UMdRqB0oZU=@vger.kernel.org X-Gm-Message-State: AOJu0YwTPbb/Xv1VJlyAeh1VchB6Y+rvQ+3He1F/+4S96cd1oSMYNNP2 huA8jxGrZybi9UN6qYCuwxVz1y4Qfz26uCcMNIivH57POp2Ra7/KCHkLb4T5VhunNl1hdeHr8EA 8O4v+fZ1ikqlPVQ== X-Google-Smtp-Source: AGHT+IH3CAgfHxDvv2J1GeCokRZ2S0eL3vzB4naD0DGXvhIrgl0bXBb/VDYWZsHKr5BZFHhvYXCyyWn/7qi9tQ== X-Received: from dlbbs14.prod.google.com ([2002:a05:7022:90e:b0:11b:b756:3e9b]) (user=wusamuel job=prod-delivery.src-stubby-dispatcher) by 2002:a05:7022:aa9:b0:11b:9386:7ecc with SMTP id a92af1059eb24-121f8b5f7a4mr7253173c88.41.1767913005229; Thu, 08 Jan 2026 14:56:45 -0800 (PST) Date: Thu, 8 Jan 2026 14:55:18 -0800 In-Reply-To: <20260108225523.3268383-1-wusamuel@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260108225523.3268383-1-wusamuel@google.com> X-Mailer: git-send-email 2.52.0.457.g6b5491de43-goog Message-ID: <20260108225523.3268383-2-wusamuel@google.com> Subject: [PATCH bpf-next v2 1/4] bpf: Add wakeup_source iterator From: Samuel Wu To: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Shuah Khan Cc: Samuel Wu , kernel-team@android.com, linux-kernel@vger.kernel.org, bpf@vger.kernel.org, linux-kselftest@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add a BPF iterator for traversing through wakeup_sources. Setup iterators to traverse through a SRCUs of wakeup_sources. This is a more elegant and efficient traversal than going through the options today, such as at /sys/class/wakeup, or through debugfs. Signed-off-by: Samuel Wu --- kernel/bpf/Makefile | 3 + kernel/bpf/wakeup_source_iter.c | 103 ++++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+) create mode 100644 kernel/bpf/wakeup_source_iter.c diff --git a/kernel/bpf/Makefile b/kernel/bpf/Makefile index 79cf22860a99..1259373298e1 100644 --- a/kernel/bpf/Makefile +++ b/kernel/bpf/Makefile @@ -66,6 +66,9 @@ obj-$(CONFIG_BPF_SYSCALL) +=3D kmem_cache_iter.o ifeq ($(CONFIG_DMA_SHARED_BUFFER),y) obj-$(CONFIG_BPF_SYSCALL) +=3D dmabuf_iter.o endif +ifeq ($(CONFIG_PM_SLEEP),y) +obj-$(CONFIG_BPF_SYSCALL) +=3D wakeup_source_iter.o +endif =20 CFLAGS_REMOVE_percpu_freelist.o =3D $(CC_FLAGS_FTRACE) CFLAGS_REMOVE_bpf_lru_list.o =3D $(CC_FLAGS_FTRACE) diff --git a/kernel/bpf/wakeup_source_iter.c b/kernel/bpf/wakeup_source_ite= r.c new file mode 100644 index 000000000000..ab83d212a1f9 --- /dev/null +++ b/kernel/bpf/wakeup_source_iter.c @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright (c) 2026 Google LLC */ +#include +#include +#include +#include +#include + +struct bpf_iter__wakeup_source { + __bpf_md_ptr(struct bpf_iter_meta *, meta); + __bpf_md_ptr(struct wakeup_source *, wakeup_source); +}; + +static void *wakeup_source_iter_seq_start(struct seq_file *seq, loff_t *po= s) +{ + int *srcuidx =3D seq->private; + struct wakeup_source *ws; + loff_t i; + + *srcuidx =3D wakeup_sources_read_lock(); + + ws =3D wakeup_sources_walk_start(); + for (i =3D 0; ws && i < *pos; i++) + ws =3D wakeup_sources_walk_next(ws); + + return ws; +} + +static void *wakeup_source_iter_seq_next(struct seq_file *seq, void *v, lo= ff_t *pos) +{ + struct wakeup_source *ws =3D v; + + ++*pos; + + return wakeup_sources_walk_next(ws); +} + +static void wakeup_source_iter_seq_stop(struct seq_file *seq, void *v) +{ + int *srcuidx =3D seq->private; + + if (*srcuidx >=3D 0) + wakeup_sources_read_unlock(*srcuidx); + *srcuidx =3D -1; +} + +static int __wakeup_source_seq_show(struct seq_file *seq, void *v, bool in= _stop) +{ + struct bpf_iter_meta meta =3D { + .seq =3D seq, + }; + struct bpf_iter__wakeup_source ctx =3D { + .meta =3D &meta, + .wakeup_source =3D v, + }; + struct bpf_prog *prog =3D bpf_iter_get_info(&meta, in_stop); + + if (prog) + return bpf_iter_run_prog(prog, &ctx); + + return 0; +} + +static int wakeup_source_iter_seq_show(struct seq_file *seq, void *v) +{ + return __wakeup_source_seq_show(seq, v, false); +} + +static const struct seq_operations wakeup_source_iter_seq_ops =3D { + .start =3D wakeup_source_iter_seq_start, + .next =3D wakeup_source_iter_seq_next, + .stop =3D wakeup_source_iter_seq_stop, + .show =3D wakeup_source_iter_seq_show, +}; + +static const struct bpf_iter_seq_info wakeup_source_iter_seq_info =3D { + .seq_ops =3D &wakeup_source_iter_seq_ops, + .seq_priv_size =3D sizeof(int), +}; + +static struct bpf_iter_reg bpf_wakeup_source_reg_info =3D { + .target =3D "wakeup_source", + .ctx_arg_info_size =3D 1, + .ctx_arg_info =3D { + { + offsetof(struct bpf_iter__wakeup_source, wakeup_source), + PTR_TO_BTF_ID_OR_NULL + }, + }, + .seq_info =3D &wakeup_source_iter_seq_info, +}; + +DEFINE_BPF_ITER_FUNC(wakeup_source, struct bpf_iter_meta *meta, + struct wakeup_source *wakeup_source) +BTF_ID_LIST_SINGLE(bpf_wakeup_source_btf_id, struct, wakeup_source) + +static int __init wakeup_source_iter_init(void) +{ + bpf_wakeup_source_reg_info.ctx_arg_info[0].btf_id =3D bpf_wakeup_source_b= tf_id[0]; + return bpf_iter_reg_target(&bpf_wakeup_source_reg_info); +} + +late_initcall(wakeup_source_iter_init); --=20 2.52.0.457.g6b5491de43-goog From nobody Sun Feb 8 05:42:14 2026 Received: from mail-dl1-f74.google.com (mail-dl1-f74.google.com [74.125.82.74]) (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 DAB9D328B47 for ; Thu, 8 Jan 2026 22:56:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767913012; cv=none; b=CVE0x+iv9Tjtakx7NJhcwzKNbiZBqUn9x89dg1DazmNbqL1BfUokLfKd8LUf6LiDFIHU7TFXT16T2mxolW5vOjBYBMud+ecUVgSBT6OPFr2otPxSV+G0lZGkQ1oRno5ustq4iVsaW9M0DDXQT9su6lSxk1BbK9AaJAwIWJYkylE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767913012; c=relaxed/simple; bh=kuVmwolLprvgFQC5gK2CvP6uE4+/Xs3CDYIOcSnFIuI=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=ZKu8ezKKBPMsutYzLwWdPJyTeWn9QO8VqTgmJVrs7fzCXLKF2AWiQUW2Er5dTtAgj8kwKvYbXJbATvp9O4ebSp/GAr6pf3nQRXJ6s4XvKX9/r1Sy7TBbCcsZ4o1vx1D1MJGFPxgvDx1i1/Ws7QxqL4PCH+DcGI1TgPybH5E6M+I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--wusamuel.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=jCbnL6gW; arc=none smtp.client-ip=74.125.82.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--wusamuel.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="jCbnL6gW" Received: by mail-dl1-f74.google.com with SMTP id a92af1059eb24-121b1cb8377so4904341c88.0 for ; Thu, 08 Jan 2026 14:56:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1767913010; x=1768517810; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=CuaylGKmhlV4n+kOnxwaacUMm3XMBF1qN/OxctemuKo=; b=jCbnL6gWyHuDCKcaPrAAtyioE9hZB9mzzsjjpJfXVpFFlBrH3VPv98CY0IeeWCkgbh EvJYr39s8LfREbVC9B+1hCJ1Nk3x0QzJE8MTaDC2CgWRlEt7bl7ZR79s43q9b4rh6wng rGzEnwApZXrWlU1X1LCVdSYB6mgBsnZ/MXkdIksl1iaF6MpWQ3hS9HAOuaZWwxJtdsGd JKbJwLGYY4iSDIS303QQGNUmQGuCGSyMVTTfGi99QxPWIR4gSzu3GxnflfeRGhb+ktS4 5/7fxTD7ScJcD3U8zNoktpZGrp7Ypz5kcSpNc3UM5gMPRplLaFQC4nTS6Qw50/wYW7tP hHsQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1767913010; x=1768517810; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=CuaylGKmhlV4n+kOnxwaacUMm3XMBF1qN/OxctemuKo=; b=KutLl8BMZ3EYrFb7582CaRxEdlCvDdAhn0ljh7x/noNvSSNpo9Yu2WegpiG7NxfI/v KbTXiUhWTx1mTEj9LIYq8zaqkw/x8IsiVFUMlbRpN/VFKqVYIQ1/6SjJKFYmV0QbSa4B eL8AYm4VR/SPOa9uAXi3jfzgWA9SXKEQuFiVKo2x+2U8Ly9YWmZsR3PhHtgEuTJn8ac7 e68uPsKEbu7bfjqxQoqeKVRHV7lHF+ZgWmA/0JXvKYdbb/BJSW2oC1PwvP+WNMA1FKGB 4X8Ob5YWSWUVM4PoKb+SK5Rrxm9Xj/m210vPM9/G2yNtRGpHobvnFodcQmkuI2N2kZrU +KyQ== X-Forwarded-Encrypted: i=1; AJvYcCUCFhhiYT+3X82yYzX8zl0mxadF3SHcpHUg2zmNtyMAq93P0crtCw8IgAlJV3WKHrV+FipwK4On2B4ZgEY=@vger.kernel.org X-Gm-Message-State: AOJu0Yz2IDbmRCPMsNpxx9lKIyJGCVNHWYdZRQxG0RrhHkM/w2Q31ldv fymfp06vW2vaX7MblcQ9LOLh+7t607mSrqVaCQXKtl5Wubncyv+FCtA8A3dCWT4RyOvfPJZBm34 P/N9XDjDdd5Qzpw== X-Google-Smtp-Source: AGHT+IENQBlDEvxTyqSWqxJtIK7u6/aN3XKMd1H9vZCTl6QBchXevnwExPMON9th5RerMP1jT6OOwF5oFTEgqQ== X-Received: from dlbcf27.prod.google.com ([2002:a05:7022:459b:b0:11d:cf87:f4ee]) (user=wusamuel job=prod-delivery.src-stubby-dispatcher) by 2002:a05:7022:ff46:b0:11e:3e9:3e8c with SMTP id a92af1059eb24-121f8b9e460mr7435141c88.49.1767913010038; Thu, 08 Jan 2026 14:56:50 -0800 (PST) Date: Thu, 8 Jan 2026 14:55:19 -0800 In-Reply-To: <20260108225523.3268383-1-wusamuel@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260108225523.3268383-1-wusamuel@google.com> X-Mailer: git-send-email 2.52.0.457.g6b5491de43-goog Message-ID: <20260108225523.3268383-3-wusamuel@google.com> Subject: [PATCH bpf-next v2 2/4] bpf: Open coded BPF for wakeup_sources From: Samuel Wu To: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Shuah Khan Cc: Samuel Wu , kernel-team@android.com, linux-kernel@vger.kernel.org, bpf@vger.kernel.org, linux-kselftest@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add open coded BPF iterators for wakeup_sources, which opens up more options for BPF programs that need to traverse through wakeup_sources. Signed-off-by: Samuel Wu --- kernel/bpf/helpers.c | 3 +++ kernel/bpf/wakeup_source_iter.c | 34 +++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c index 9eaa4185e0a7..ca34d7614c3a 100644 --- a/kernel/bpf/helpers.c +++ b/kernel/bpf/helpers.c @@ -4518,6 +4518,9 @@ BTF_ID_FLAGS(func, bpf_iter_dmabuf_new, KF_ITER_NEW |= KF_SLEEPABLE) BTF_ID_FLAGS(func, bpf_iter_dmabuf_next, KF_ITER_NEXT | KF_RET_NULL | KF_S= LEEPABLE) BTF_ID_FLAGS(func, bpf_iter_dmabuf_destroy, KF_ITER_DESTROY | KF_SLEEPABLE) #endif +BTF_ID_FLAGS(func, bpf_iter_wakeup_source_new, KF_ITER_NEW | KF_SLEEPABLE) +BTF_ID_FLAGS(func, bpf_iter_wakeup_source_next, KF_ITER_NEXT | KF_RET_NULL= | KF_SLEEPABLE) +BTF_ID_FLAGS(func, bpf_iter_wakeup_source_destroy, KF_ITER_DESTROY | KF_SL= EEPABLE) BTF_ID_FLAGS(func, __bpf_trap) BTF_ID_FLAGS(func, bpf_strcmp); BTF_ID_FLAGS(func, bpf_strcasecmp); diff --git a/kernel/bpf/wakeup_source_iter.c b/kernel/bpf/wakeup_source_ite= r.c index ab83d212a1f9..149baecfe436 100644 --- a/kernel/bpf/wakeup_source_iter.c +++ b/kernel/bpf/wakeup_source_iter.c @@ -90,6 +90,40 @@ static struct bpf_iter_reg bpf_wakeup_source_reg_info = =3D { .seq_info =3D &wakeup_source_iter_seq_info, }; =20 +struct bpf_iter_wakeup_source { + struct wakeup_source *ws; + int srcuidx; +}; + +__bpf_kfunc_start_defs(); + +__bpf_kfunc int bpf_iter_wakeup_source_new(struct bpf_iter_wakeup_source *= it) +{ + it->srcuidx =3D wakeup_sources_read_lock(); + it->ws =3D wakeup_sources_walk_start(); + + return 0; +} + +__bpf_kfunc struct wakeup_source *bpf_iter_wakeup_source_next(struct bpf_i= ter_wakeup_source *it) +{ + struct wakeup_source *prev =3D it->ws; + + if (!prev) + return NULL; + + it->ws =3D wakeup_sources_walk_next(it->ws); + + return prev; +} + +__bpf_kfunc void bpf_iter_wakeup_source_destroy(struct bpf_iter_wakeup_sou= rce *it) +{ + wakeup_sources_read_unlock(it->srcuidx); +} + +__bpf_kfunc_end_defs(); + DEFINE_BPF_ITER_FUNC(wakeup_source, struct bpf_iter_meta *meta, struct wakeup_source *wakeup_source) BTF_ID_LIST_SINGLE(bpf_wakeup_source_btf_id, struct, wakeup_source) --=20 2.52.0.457.g6b5491de43-goog From nobody Sun Feb 8 05:42:14 2026 Received: from mail-dl1-f73.google.com (mail-dl1-f73.google.com [74.125.82.73]) (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 C1D6C33C519 for ; Thu, 8 Jan 2026 22:56:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767913018; cv=none; b=kTA/mStaHNUce4ifoH++hvJWKsSMidrUrWwBo3fPJSHfyrqtUvhbxlWx2qe6o5TuVrgOuovb906JyYr6upZtGdWiJt9TSVCNDUctMAdO8gwgSY+F9ZHNZ5l8oYAkjU+RIu0fn1kuUL9ca939FURU4kbQd0FuKZfdy2t/QlZBNt0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767913018; c=relaxed/simple; bh=A9jI17fcs31/t1iRyFhUJM+zf4m3JOvyrT8NoYE4jB0=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=m8uGi9MD/Z7q1y9sYT7AehuntPRTAF2KrV8DGj4yyuALC5bm21e43CAzrVmsbibiSDiI0o/yHrvw2U7JXZvPDhqSji5ZDbxt9CZHNZiVqSjU50hQ6eJMIoDb1E5+pFsgO17hm7m90ilpd7Y8BtGWJxPG+MuTkbUAPG28aesHSNE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--wusamuel.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=VmZmo0iL; arc=none smtp.client-ip=74.125.82.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--wusamuel.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="VmZmo0iL" Received: by mail-dl1-f73.google.com with SMTP id a92af1059eb24-11f3b5411c7so1238006c88.1 for ; Thu, 08 Jan 2026 14:56:55 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1767913015; x=1768517815; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=Rhp4aBOWkHAoDobmjqBAbtC3QTUVVj6dv/kGDpJATC4=; b=VmZmo0iLvg9ip5jcADbfA1WEpWiPlQW8+V92H9gd1tXsEAIsDcKx0hPOo1e6B1xMYH 8E4YoEVGpIIU6F+slpdWSuDm4jKDUedKSE3cB+m5zDhTlwnUHbUl3bNg1rHWIExhLqiX yZhDJXpqF218eodAS9MF7YF9VZFF+HmOYWdApaRu6LPJOIkiBvfOdugbSBCNyNs/qslT rn3FYDilXMsBW5nJiJ1+CoS/arNH0wTvuwRseb6NoKj6XQMGy5oCxqFrK4kQefyU++vy nlXmza5FlfUeCCqVBUNhQHF9yVIbsLN4GkcZXQSVncj38f9fwNRQrh/f8aAdIYjDQEGm fHpQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1767913015; x=1768517815; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=Rhp4aBOWkHAoDobmjqBAbtC3QTUVVj6dv/kGDpJATC4=; b=nwJyz/H1PZDISzsdlpTjf9xVcz2ZV6U/RAK885UDjDi63MLXfv4KmumB8dSBwiqIL8 DFpjeHkzavrF/aKPqEMb/b92eW1wzes8U3Tv0cE9QDDQ1utWe+7ZuaTXD24t/zk9Hy5J Co3kmobnRqzG034rWHWb85d0bcHhEWtFS6z6fMBUbk4UbTgU5JflXDsstnyo5EkiGwEX kjX72dl6X6skwUB2wQC6dQd0sUkzZA+77dOmG3FFhrcT4v12mYJ98LxuumlKtl6uMfLZ fwHSlLE7jfyFH1irx+z49BlHDphmGpH2romtppSAVsdfkvrbjYoQ9++dPqfYYLoGBuSH yhqw== X-Forwarded-Encrypted: i=1; AJvYcCWD9NOhOW/kztgdwi08zEUdPBeGkLZinLKUEUSSlXGQ4ANYqVFqaPwI0yIaCjrkmO7QK1AfGpstkDlYqn4=@vger.kernel.org X-Gm-Message-State: AOJu0Yzt9nosdbfroXHMq0VBzMrrBNcXQbzxhbBlUjZYopXHCg91sugu XpF/OiLpIvtIWMrKgILKuxG1PTq+9l0B0BXM8e30s9jB0V5JIY6Rb7rCrIt8jML2TXiKuoTO8R6 Iwst8rgvto07ALQ== X-Google-Smtp-Source: AGHT+IGGJ3gGsTBzfEEUlqWrpntUe9wgzFyGAg3KxYBa7uLrvMBFpxhg/XQEcGsUPspCiatDsHXq8OHCrduk1g== X-Received: from dlbtx2.prod.google.com ([2002:a05:7022:fc02:b0:11b:1a9a:d2e8]) (user=wusamuel job=prod-delivery.src-stubby-dispatcher) by 2002:a05:7022:2494:b0:11b:ec5f:1c37 with SMTP id a92af1059eb24-121f8ad1c96mr6785720c88.18.1767913014880; Thu, 08 Jan 2026 14:56:54 -0800 (PST) Date: Thu, 8 Jan 2026 14:55:20 -0800 In-Reply-To: <20260108225523.3268383-1-wusamuel@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260108225523.3268383-1-wusamuel@google.com> X-Mailer: git-send-email 2.52.0.457.g6b5491de43-goog Message-ID: <20260108225523.3268383-4-wusamuel@google.com> Subject: [PATCH bpf-next v2 3/4] selftests/bpf: Add tests for wakeup_sources From: Samuel Wu To: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Shuah Khan Cc: Samuel Wu , kernel-team@android.com, linux-kernel@vger.kernel.org, bpf@vger.kernel.org, linux-kselftest@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Sets up the framework to test wakeup_sources iterators using BPF, and adds a few basic tests. Adds several helper functions that for grabbing and releasing a wakelock, abstracting out key functions to setup a framework for testing wakeup_sources. Additionally, adds 3 tests: 1. check_active_count: Checks that stats related to active_count are properly set after several lock/unlock cycles 2. check_sleep_times: Checks that time accounting related to sleep are properly calculated 3. check_no_infinite_reads: Checks that the iterator traversal returns NULL at the end Signed-off-by: Samuel Wu --- tools/testing/selftests/bpf/config | 1 + .../bpf/prog_tests/wakeup_source_iter.c | 281 ++++++++++++++++++ .../selftests/bpf/progs/wakeup_source_iter.c | 70 +++++ 3 files changed, 352 insertions(+) create mode 100644 tools/testing/selftests/bpf/prog_tests/wakeup_source_it= er.c create mode 100644 tools/testing/selftests/bpf/progs/wakeup_source_iter.c diff --git a/tools/testing/selftests/bpf/config b/tools/testing/selftests/b= pf/config index 558839e3c185..c12c5e04b81f 100644 --- a/tools/testing/selftests/bpf/config +++ b/tools/testing/selftests/bpf/config @@ -111,6 +111,7 @@ CONFIG_IP6_NF_IPTABLES=3Dy CONFIG_IP6_NF_FILTER=3Dy CONFIG_NF_NAT=3Dy CONFIG_PACKET=3Dy +CONFIG_PM_WAKELOCKS=3Dy CONFIG_RC_CORE=3Dy CONFIG_SAMPLES=3Dy CONFIG_SAMPLE_LIVEPATCH=3Dm diff --git a/tools/testing/selftests/bpf/prog_tests/wakeup_source_iter.c b/= tools/testing/selftests/bpf/prog_tests/wakeup_source_iter.c new file mode 100644 index 000000000000..31729f11585e --- /dev/null +++ b/tools/testing/selftests/bpf/prog_tests/wakeup_source_iter.c @@ -0,0 +1,281 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2026 Google LLC */ + +#include +#include +#include "wakeup_source_iter.skel.h" + +#include +#include +#include +#include +#include +#include + + +/* Sleep for 10ms to ensure active time is > 0 after converting ns to ms*/ +#define TEST_SLEEP_US 10000 +#define TEST_SLEEP_MS (TEST_SLEEP_US / 1000) +#define WAKEUP_SOURCE_NAME_LEN 32 + +static const char test_ws_name[] =3D "bpf_selftest_ws"; +static bool test_ws_created; + +/* + * Creates a new wakeup source by writing to /sys/power/wake_lock. + * This lock persists until explicitly unlocked. + */ +static int lock_ws(const char *name) +{ + int fd; + ssize_t bytes; + + fd =3D open("/sys/power/wake_lock", O_WRONLY); + if (!ASSERT_OK_FD(fd, "open /sys/power/wake_lock")) + return -1; + + bytes =3D write(fd, name, strlen(name)); + close(fd); + if (!ASSERT_EQ(bytes, strlen(name), "write to wake_lock")) + return -1; + + return 0; +} + +/* + * Destroys the ws by writing the same name to /sys/power/wake_unlock. + */ +static void unlock_ws(const char *name) +{ + int fd; + + fd =3D open("/sys/power/wake_unlock", O_WRONLY); + if (!ASSERT_OK_FD(fd, "open /sys/power/wake_unlock")) + goto cleanup; + + write(fd, name, strlen(name)); + +cleanup: + if (fd) + close(fd); +} + +/* + * Setups for testing ws iterators. Will run once prior to suite of tests. + */ +static int setup_test_ws(void) +{ + if (lock_ws(test_ws_name)) + return -1; + test_ws_created =3D true; + + return 0; +} + +/* + * Tears down and cleanups testing ws iterators. WIll run once after the s= uite + * of tests. + */ +static void teardown_test_ws(void) +{ + if (!test_ws_created) + return; + unlock_ws(test_ws_name); + test_ws_created =3D false; +} + +struct WakeupSourceInfo { + char name[WAKEUP_SOURCE_NAME_LEN]; + unsigned long active_count; + long active_time_ms; + unsigned long event_count; + unsigned long expire_count; + long last_change_ms; + long max_time_ms; + long prevent_sleep_time_ms; + long total_time_ms; + unsigned long wakeup_count; +}; + +/* + * Reads and parses one wakeup_source record from the iterator file. + * A record is a single space-delimited line. + * Returns true on success, false on EOF. Asserts internally on errors. + */ +static bool read_ws_info(FILE *iter_file, struct WakeupSourceInfo *ws_info, + char **line) +{ + size_t linesize; + int items; + + if (getline(line, &linesize, iter_file) =3D=3D -1) + return false; + + (*line)[strcspn(*line, "\n")] =3D 0; + + items =3D sscanf(*line, "%s %lu %ld %lu %lu %ld %ld %ld %ld %lu", + ws_info->name, &ws_info->active_count, + &ws_info->active_time_ms, &ws_info->event_count, + &ws_info->expire_count, &ws_info->last_change_ms, + &ws_info->max_time_ms, &ws_info->prevent_sleep_time_ms, + &ws_info->total_time_ms, &ws_info->wakeup_count); + + if (!ASSERT_EQ(items, 10, "read wakeup source info")) + return false; + + if (!ASSERT_LT(strlen(ws_info->name), WAKEUP_SOURCE_NAME_LEN, + "name length")) + return false; + + return true; +} + +static int get_ws_iter_stream(struct wakeup_source_iter *skel, int *iter_f= d, + FILE **iter_file) +{ + *iter_fd =3D bpf_iter_create( + bpf_link__fd(skel->links.wakeup_source_collector)); + if (!ASSERT_OK_FD(*iter_fd, "iter_create")) + return -1; + + *iter_file =3D fdopen(*iter_fd, "r"); + if (!ASSERT_OK_PTR(*iter_file, "fdopen")) + return -1; + + return 0; +} + +static void subtest_ws_iter_check_active_count(struct wakeup_source_iter *= skel) +{ + static const char subtest_ws_name[] =3D "bpf_selftest_ws_active_count"; + const int lock_unlock_cycles =3D 5; + struct WakeupSourceInfo ws_info; + char *line =3D NULL; + bool found_ws =3D false; + FILE *iter_file =3D NULL; + int iter_fd =3D -1; + int i; + + for (i =3D 0; i < lock_unlock_cycles; i++) { + if (!ASSERT_OK(lock_ws(subtest_ws_name), "lock_ws")) + goto cleanup; + unlock_ws(subtest_ws_name); + } + + if (!get_ws_iter_stream(skel, &iter_fd, &iter_file)) + goto cleanup; + + while (read_ws_info(iter_file, &ws_info, &line)) { + if (strcmp(ws_info.name, subtest_ws_name) =3D=3D 0) { + found_ws =3D true; + ASSERT_EQ(ws_info.active_count, lock_unlock_cycles, + "active_count check"); + ASSERT_EQ(ws_info.wakeup_count, lock_unlock_cycles, + "wakeup_count check"); + break; + } + } + + ASSERT_TRUE(found_ws, "found active_count test ws"); + + free(line); +cleanup: + if (iter_file) + fclose(iter_file); + else if (iter_fd >=3D 0) + close(iter_fd); +} + +static void subtest_ws_iter_check_sleep_times(struct wakeup_source_iter *s= kel) +{ + bool found_test_ws =3D false; + struct WakeupSourceInfo ws_info; + char *line =3D NULL; + FILE *iter_file; + int iter_fd; + + if (!get_ws_iter_stream(skel, &iter_fd, &iter_file)) + goto cleanup; + + while (read_ws_info(iter_file, &ws_info, &line)) { + if (strcmp(ws_info.name, test_ws_name) =3D=3D 0) { + found_test_ws =3D true; + ASSERT_GT(ws_info.last_change_ms, 0, + "Expected non-zero last change"); + ASSERT_GE(ws_info.active_time_ms, TEST_SLEEP_MS, + "Expected active time >=3D TEST_SLEEP_MS"); + ASSERT_GE(ws_info.max_time_ms, TEST_SLEEP_MS, + "Expected max time >=3D TEST_SLEEP_MS"); + ASSERT_GE(ws_info.total_time_ms, TEST_SLEEP_MS, + "Expected total time >=3D TEST_SLEEP_MS"); + break; + } + } + + ASSERT_TRUE(found_test_ws, "found_test_ws"); + + free(line); +cleanup: + if (iter_file) + fclose(iter_file); + else if (iter_fd >=3D 0) + close(iter_fd); +} + +static void subtest_ws_iter_check_no_infinite_reads( + struct wakeup_source_iter *skel) +{ + int iter_fd; + char buf[256]; + + iter_fd =3D bpf_iter_create(bpf_link__fd(skel->links.wakeup_source_collec= tor)); + if (!ASSERT_OK_FD(iter_fd, "iter_create")) + return; + + while (read(iter_fd, buf, sizeof(buf)) > 0) + ; + + /* Final read should return 0 */ + ASSERT_EQ(read(iter_fd, buf, sizeof(buf)), 0, "read"); + + close(iter_fd); +} + +void test_wakeup_source_iter(void) +{ + struct wakeup_source_iter *skel =3D NULL; + + if (geteuid() !=3D 0) { + fprintf(stderr, + "Skipping wakeup_source_iter test, requires root\n"); + test__skip(); + return; + } + + skel =3D wakeup_source_iter__open_and_load(); + if (!ASSERT_OK_PTR(skel, "wakeup_source_iter__open_and_load")) + return; + + if (!ASSERT_OK(setup_test_ws(), "setup_test_ws")) + goto destroy; + + if (!ASSERT_OK(wakeup_source_iter__attach(skel), "skel_attach")) + goto destroy; + + /* + * Sleep on O(ms) to ensure that time stats' resolution isn't lost when + * converting from ns to ms + */ + usleep(TEST_SLEEP_US); + + if (test__start_subtest("active_count")) + subtest_ws_iter_check_active_count(skel); + if (test__start_subtest("sleep_times")) + subtest_ws_iter_check_sleep_times(skel); + if (test__start_subtest("no_infinite_reads")) + subtest_ws_iter_check_no_infinite_reads(skel); + +destroy: + teardown_test_ws(); + wakeup_source_iter__destroy(skel); +} diff --git a/tools/testing/selftests/bpf/progs/wakeup_source_iter.c b/tools= /testing/selftests/bpf/progs/wakeup_source_iter.c new file mode 100644 index 000000000000..9a377fd28f4e --- /dev/null +++ b/tools/testing/selftests/bpf/progs/wakeup_source_iter.c @@ -0,0 +1,70 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2026 Google LLC */ +#include +#include +#include + +#define NSEC_PER_MS 1000000UL +#define WAKEUP_SOURCE_NAME_LEN 32 + +char _license[] SEC("license") =3D "GPL"; + +SEC("iter/wakeup_source") +int wakeup_source_collector(struct bpf_iter__wakeup_source *ctx) +{ + const struct wakeup_source *ws =3D ctx->wakeup_source; + struct seq_file *seq =3D ctx->meta->seq; + char name[WAKEUP_SOURCE_NAME_LEN] =3D {'\0'}; + const char *pname; + bool active, autosleep_enable; + u64 active_count, event_count, expire_count, wakeup_count; + s64 active_time, curr_time, last_change_time, max_time, + prevent_sleep_time, start_prevent_time, total_time; + + if (!ws) + return 0; + + active =3D BPF_CORE_READ_BITFIELD_PROBED(ws, active); + autosleep_enable =3D BPF_CORE_READ_BITFIELD_PROBED(ws, autosleep_enabled); + if (bpf_core_read(&pname, sizeof(pname), &ws->name) || + bpf_probe_read_kernel_str(name, sizeof(name), pname) < 0 || + bpf_core_read(&active_count, sizeof(active_count), &ws->active_count)= || + bpf_core_read(&event_count, sizeof(event_count), &ws->event_count) || + bpf_core_read(&expire_count, sizeof(expire_count), &ws->expire_count)= || + bpf_core_read(&last_change_time, sizeof(last_change_time), &ws->last_= time) || + bpf_core_read(&max_time, sizeof(max_time), &ws->max_time) || + bpf_core_read( + &prevent_sleep_time, sizeof(prevent_sleep_time), &ws->prevent_sleep_time= ) || + bpf_core_read( + &start_prevent_time, sizeof(start_prevent_time), &ws->start_prevent_time= ) || + bpf_core_read(&total_time, sizeof(total_time), &ws->total_time) || + bpf_core_read(&wakeup_count, sizeof(wakeup_count), &ws->wakeup_count)) + return 0; + + + curr_time =3D bpf_ktime_get_ns(); + active_time =3D 0; + if (active) { + active_time =3D curr_time - last_change_time; + total_time +=3D active_time; + if (active_time > max_time) + max_time =3D active_time; + if (autosleep_enable) + prevent_sleep_time +=3D curr_time - start_prevent_time; + + } + + BPF_SEQ_PRINTF(seq, + "%s %lu %ld %lu %lu %ld %ld %ld %ld %lu\n", + name, + active_count, + active_time / NSEC_PER_MS, + event_count, + expire_count, + last_change_time / NSEC_PER_MS, + max_time / NSEC_PER_MS, + prevent_sleep_time / NSEC_PER_MS, + total_time / NSEC_PER_MS, + wakeup_count); + return 0; +} --=20 2.52.0.457.g6b5491de43-goog From nobody Sun Feb 8 05:42:14 2026 Received: from mail-dl1-f74.google.com (mail-dl1-f74.google.com [74.125.82.74]) (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 CCD913382EC for ; Thu, 8 Jan 2026 22:57:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767913022; cv=none; b=Cwavoiawe/XX6NF4vTnElzyBJtMwh0Jsme/RuVj2a/eMGIoZ3RUWdyjWTmLIwyOHMV5LGKagG9iTbpLOMdZ7x6gwSkYZLDjvCMJRIAJd9JpaTt93WSonxTmPFkyISUQQnBgXiYBN8ng6UHGAtbXBFHG8iBsEcPYzUrVsNMWK+QE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767913022; c=relaxed/simple; bh=J3XoNh2+ursfIFHZ04dZbCicr+2/5qQvrat3UOVe13E=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=J2lEV8U9PF1ibr55w0EUOZncmLeUUVqpzdkBFXT/2C4/laWj6X30i+qN4vJcIZu7KetS8t/58usll003Tsqg685piJyL7StZNlNgvpJahbhn66hf5ROxZepTvgorJAaOh3U+jwhdehq53Hsh/uf3SJ/XAAdzyZhGxxczmUikGd0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--wusamuel.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=cNh1gNXD; arc=none smtp.client-ip=74.125.82.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--wusamuel.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="cNh1gNXD" Received: by mail-dl1-f74.google.com with SMTP id a92af1059eb24-122008d48e5so1761191c88.1 for ; Thu, 08 Jan 2026 14:57:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1767913020; x=1768517820; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=dpKXlsbK0t3fSowv1Ag5XF8DahHUNU6JO1yHiv556M0=; b=cNh1gNXD6XVz/fZTmCbklLappsSX5mJGfM1fN/NnhQAF4uaYXxQ/N9IiqzDrhR/1t7 CWEXLkzRfzN3EjM4jh73XANse1tSoq3lGEGZOJ0i5PVz8Nuz8qXVYqA4ljcpeoSJQ4Qz m9q1y7HW4WNGohHziRu14KwHOOSPJYBj0zv7VFnpdTu89mMnFM4xCp1aHSOhR01hffFv CvkqjJmuh6fFd8g9xdPQq624uTt2VVAFgMiD7i1g47/nXOHWnqLdgD3BOyd1lzsuD/vJ NrqrA2YwkMKs2AMsOXmClUoQJNDwNT+5V8uvvYLhEUBSKYsxv0Oy4srGavk0kgU5Qh2i GOiA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1767913020; x=1768517820; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=dpKXlsbK0t3fSowv1Ag5XF8DahHUNU6JO1yHiv556M0=; b=fX0jMrscfhG15QOSUqtTaS2I0sb94O+MOy/6eNMfI49LbUS6nfU07mjfPdgtAHdtqM DXQ5dMkZbMPEohhvSAzpJEdkiAwGmKtRPnA+XwNvUZRlXFQQd9VvW/ml6mCUnfKP+kyF bB93smh49oxXO13WltigzduxQWv1F7sK844lHnkGxnLR/YVXFKEE+cMQOzfbRlRAILnh Ub6Nph1vrVoOY7A0RxP5LwH+GAwMFhXNevPCAcBa9ofJfe1WdaSAoVON5Tih12jhQDf9 5z15wSIupn5wFtkcMk4KrchChG622+C+/vHxQjHGJnzJR5RmYhTfplKtfLmP2BUUgINV Rk2w== X-Forwarded-Encrypted: i=1; AJvYcCUyMfS8/6rykXx5S/IKu9qZYZYaqHp3CFyq7WSXiD/OjeFayanMTPIhcA1A+EZLk2N3vGRcBVNJpSMSaNI=@vger.kernel.org X-Gm-Message-State: AOJu0YxDUs7AOukFy95hOSXXJx3h9OPhZz/u7lcSRLOmtOYkZSHFjy7D ME4gNr1trpMugIUYJVIBq/BQiRT/2tPX/BUzUWtZPLDMh0R+pj7PAuOSNdTdcbGYwLCaKp/RTCw OqFE6gDEnxTSTyw== X-Google-Smtp-Source: AGHT+IG9bQDjpCq6ehJqqADDNDIcyIIU2S/qsuw+XaSMLcji1Lvxu5teMn1SSSthcF42Rd0wF4s4ZbXQTh9E7w== X-Received: from dlbuu5.prod.google.com ([2002:a05:7022:7e85:b0:11d:cfec:1ad2]) (user=wusamuel job=prod-delivery.src-stubby-dispatcher) by 2002:a05:7022:2495:b0:11b:9e5e:1a66 with SMTP id a92af1059eb24-121f8b16424mr6507148c88.14.1767913019880; Thu, 08 Jan 2026 14:56:59 -0800 (PST) Date: Thu, 8 Jan 2026 14:55:21 -0800 In-Reply-To: <20260108225523.3268383-1-wusamuel@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260108225523.3268383-1-wusamuel@google.com> X-Mailer: git-send-email 2.52.0.457.g6b5491de43-goog Message-ID: <20260108225523.3268383-5-wusamuel@google.com> Subject: [PATCH bpf-next v2 4/4] selftests/bpf: Open coded BPF wakeup_sources test From: Samuel Wu To: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Shuah Khan Cc: Samuel Wu , kernel-team@android.com, linux-kernel@vger.kernel.org, bpf@vger.kernel.org, linux-kselftest@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" This commit introduces a new selftest for the BPF wakeup_source iterator to verify the functionality of open-coded iteration. The test adds: - A new BPF map `test_ws_hash` to track iterated wakeup source names. - A BPF program `iter_ws_for_each` that iterates over wakeup sources and updates the `test_ws_hash` map with the names of found sources. - A new subtest `subtest_ws_iter_check_open_coded` to trigger the BPF program and assert that the expected wakeup sources are marked in the map. Signed-off-by: Samuel Wu --- .../testing/selftests/bpf/bpf_experimental.h | 5 ++ .../bpf/prog_tests/wakeup_source_iter.c | 42 +++++++++++++++++ .../selftests/bpf/progs/wakeup_source_iter.c | 47 +++++++++++++++++++ 3 files changed, 94 insertions(+) diff --git a/tools/testing/selftests/bpf/bpf_experimental.h b/tools/testing= /selftests/bpf/bpf_experimental.h index 2cd9165c7348..e532999b91ca 100644 --- a/tools/testing/selftests/bpf/bpf_experimental.h +++ b/tools/testing/selftests/bpf/bpf_experimental.h @@ -598,6 +598,11 @@ extern void bpf_iter_dmabuf_destroy(struct bpf_iter_dm= abuf *it) __weak __ksym; =20 extern int bpf_cgroup_read_xattr(struct cgroup *cgroup, const char *name__= str, struct bpf_dynptr *value_p) __weak __ksym; +struct bpf_iter_wakeup_source; +extern int bpf_iter_wakeup_source_new(struct bpf_iter_wakeup_source *it) _= _weak __ksym; +extern struct wakeup_source *bpf_iter_wakeup_source_next( + struct bpf_iter_wakeup_source *it) __weak __ksym; +extern void bpf_iter_wakeup_source_destroy(struct bpf_iter_wakeup_source *= it) __weak __ksym; =20 #define PREEMPT_BITS 8 #define SOFTIRQ_BITS 8 diff --git a/tools/testing/selftests/bpf/prog_tests/wakeup_source_iter.c b/= tools/testing/selftests/bpf/prog_tests/wakeup_source_iter.c index 31729f11585e..7b4d4cb25fd0 100644 --- a/tools/testing/selftests/bpf/prog_tests/wakeup_source_iter.c +++ b/tools/testing/selftests/bpf/prog_tests/wakeup_source_iter.c @@ -241,9 +241,37 @@ static void subtest_ws_iter_check_no_infinite_reads( close(iter_fd); } =20 +static void subtest_ws_iter_check_open_coded(struct wakeup_source_iter *sk= el, + int map_fd) +{ + LIBBPF_OPTS(bpf_test_run_opts, topts); + char key[WAKEUP_SOURCE_NAME_LEN] =3D {0}; + int err, fd; + bool found =3D false; + + fd =3D bpf_program__fd(skel->progs.iter_ws_for_each); + + err =3D bpf_prog_test_run_opts(fd, &topts); + if (!ASSERT_OK(err, "test_run_opts err")) + return; + if (!ASSERT_OK(topts.retval, "test_run_opts retval")) + return; + + strncpy(key, test_ws_name, WAKEUP_SOURCE_NAME_LEN - 1); + + if (!ASSERT_OK(bpf_map_lookup_elem(map_fd, key, &found), + "lookup test_ws_name")) + return; + + ASSERT_TRUE(found, "found test ws via bpf_for_each"); +} + void test_wakeup_source_iter(void) { struct wakeup_source_iter *skel =3D NULL; + int map_fd; + const bool found_val =3D false; + char key[WAKEUP_SOURCE_NAME_LEN] =3D {0}; =20 if (geteuid() !=3D 0) { fprintf(stderr, @@ -256,6 +284,17 @@ void test_wakeup_source_iter(void) if (!ASSERT_OK_PTR(skel, "wakeup_source_iter__open_and_load")) return; =20 + map_fd =3D bpf_map__fd(skel->maps.test_ws_hash); + if (!ASSERT_OK_FD(map_fd, "map_fd")) + goto destroy_skel; + + /* Copy test name to key buffer, ensuring it's zero-padded */ + strncpy(key, test_ws_name, WAKEUP_SOURCE_NAME_LEN - 1); + + if (!ASSERT_OK(bpf_map_update_elem(map_fd, key, &found_val, BPF_ANY), + "insert test_ws_name")) + goto destroy_skel; + if (!ASSERT_OK(setup_test_ws(), "setup_test_ws")) goto destroy; =20 @@ -274,8 +313,11 @@ void test_wakeup_source_iter(void) subtest_ws_iter_check_sleep_times(skel); if (test__start_subtest("no_infinite_reads")) subtest_ws_iter_check_no_infinite_reads(skel); + if (test__start_subtest("open_coded")) + subtest_ws_iter_check_open_coded(skel, map_fd); =20 destroy: teardown_test_ws(); +destroy_skel: wakeup_source_iter__destroy(skel); } diff --git a/tools/testing/selftests/bpf/progs/wakeup_source_iter.c b/tools= /testing/selftests/bpf/progs/wakeup_source_iter.c index 9a377fd28f4e..a95718dadcc7 100644 --- a/tools/testing/selftests/bpf/progs/wakeup_source_iter.c +++ b/tools/testing/selftests/bpf/progs/wakeup_source_iter.c @@ -9,6 +9,13 @@ =20 char _license[] SEC("license") =3D "GPL"; =20 +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(key_size, WAKEUP_SOURCE_NAME_LEN); + __type(value, bool); + __uint(max_entries, 5); +} test_ws_hash SEC(".maps"); + SEC("iter/wakeup_source") int wakeup_source_collector(struct bpf_iter__wakeup_source *ctx) { @@ -68,3 +75,43 @@ int wakeup_source_collector(struct bpf_iter__wakeup_sour= ce *ctx) wakeup_count); return 0; } + +SEC("syscall") +int iter_ws_for_each(const void *ctx) +{ + struct wakeup_source *ws; + + bpf_for_each(wakeup_source, ws) { + char name[WAKEUP_SOURCE_NAME_LEN]; + const char *pname; + bool *found; + long len; + int i; + + if (bpf_core_read(&pname, sizeof(pname), &ws->name)) + return 1; + + if (!pname) + continue; + + len =3D bpf_probe_read_kernel_str(name, sizeof(name), pname); + if (len < 0) + return 1; + + /* + * Clear the remainder of the buffer to ensure a stable key for + * the map lookup. + */ + bpf_for(i, len, WAKEUP_SOURCE_NAME_LEN) + name[i] =3D 0; + + found =3D bpf_map_lookup_elem(&test_ws_hash, name); + if (found) { + bool t =3D true; + + bpf_map_update_elem(&test_ws_hash, name, &t, BPF_EXIST); + } + } + + return 0; +} --=20 2.52.0.457.g6b5491de43-goog