From: Kaitao Cheng <kaitao.cheng@linux.dev>
To: "Andy Shevchenko" <andriy.shevchenko@linux.intel.com>,
"Muchun Song" <muchun.song@linux.dev>,
"Philipp Reisner" <philipp.reisner@linbit.com>,
"Lars Ellenberg" <lars.ellenberg@linbit.com>,
"Christoph Böhmwalder" <christoph.boehmwalder@linbit.com>,
"Jens Axboe" <axboe@kernel.dk>,
"Takashi Sakamoto" <o-takashi@sakamocchi.jp>,
"Andrzej Hajda" <andrzej.hajda@intel.com>,
"Neil Armstrong" <neil.armstrong@linaro.org>,
"Robert Foss" <rfoss@kernel.org>,
"Maarten Lankhorst" <maarten.lankhorst@linux.intel.com>,
"Maxime Ripard" <mripard@kernel.org>,
"Thomas Zimmermann" <tzimmermann@suse.de>,
"David Airlie" <airlied@gmail.com>,
"Simona Vetter" <simona@ffwll.ch>,
"Jani Nikula" <jani.nikula@linux.intel.com>,
"Joonas Lahtinen" <joonas.lahtinen@linux.intel.com>,
"Rodrigo Vivi" <rodrigo.vivi@intel.com>,
"Tvrtko Ursulin" <tursulin@ursulin.net>,
"Christian Koenig" <christian.koenig@amd.com>,
"Huang Rui" <ray.huang@amd.com>,
"Eddie James" <eajames@linux.ibm.com>,
"Mark Brown" <broonie@kernel.org>,
"Maxime Coquelin" <mcoquelin.stm32@gmail.com>,
"Alexandre Torgue" <alexandre.torgue@foss.st.com>,
"Laxman Dewangan" <ldewangan@nvidia.com>,
"Thierry Reding" <thierry.reding@kernel.org>,
"Jonathan Hunter" <jonathanh@nvidia.com>,
"Sowjanya Komatineni" <skomatineni@nvidia.com>,
"Davidlohr Bueso" <dave@stgolabs.net>,
"Paul E . McKenney" <paulmck@kernel.org>,
"Josh Triplett" <josh@joshtriplett.org>,
"Peter Zijlstra" <peterz@infradead.org>,
"Ingo Molnar" <mingo@redhat.com>, "Will Deacon" <will@kernel.org>,
"Boqun Feng" <boqun@kernel.org>,
"Liam Girdwood" <lgirdwood@gmail.com>,
"Jaroslav Kysela" <perex@perex.cz>,
"Takashi Iwai" <tiwai@suse.com>
Cc: Laurent Pinchart <Laurent.pinchart@ideasonboard.com>,
Jonas Karlman <jonas@kwiboo.se>,
Jernej Skrabec <jernej.skrabec@gmail.com>,
Matthew Auld <matthew.auld@intel.com>,
Matthew Brost <matthew.brost@intel.com>,
Waiman Long <longman@redhat.com>,
drbd-dev@lists.linbit.com, linux-block@vger.kernel.org,
linux1394-devel@lists.sourceforge.net,
dri-devel@lists.freedesktop.org, intel-gfx@lists.freedesktop.org,
linux-spi@vger.kernel.org,
linux-stm32@st-md-mailman.stormreply.com,
linux-arm-kernel@lists.infradead.org,
linux-tegra@vger.kernel.org, linux-sound@vger.kernel.org,
linux-kernel@vger.kernel.org,
Andrew Morton <akpm@linux-foundation.org>,
Randy Dunlap <rdunlap@infradead.org>,
Christian Brauner <brauner@kernel.org>,
David Howells <dhowells@redhat.com>,
Luca Ceresoli <luca.ceresoli@bootlin.com>,
Kaitao Cheng <kaitao.cheng@linux.dev>,
Kaitao Cheng <chengkaitao@kylinos.cn>
Subject: [PATCH v2 14/14] list: Cache cursors in entry iterators
Date: Tue, 9 Jun 2026 14:41:22 +0800 [thread overview]
Message-ID: <20260609064122.95825-2-kaitao.cheng@linux.dev> (raw)
In-Reply-To: <20260609064122.95825-1-kaitao.cheng@linux.dev>
From: Kaitao Cheng <chengkaitao@kylinos.cn>
The non-safe list_for_each_entry() family advances by deriving the next
element from the current cursor in the loop step. If the loop body
unlinks the current entry, the step can no longer rely on the current
entry's list pointers.
Callers can use the _safe variants today, but those interfaces require a
temporary cursor to be declared outside the macro. That is necessary when
the caller actually needs the temporary cursor, but it looks redundant
and awkward when the cursor is only there to satisfy the macro and is
never otherwise used.
Add private next and previous cursors for the common entry iterators and
use unique internal names so callers keep the same interface. This lets
the loop step use a cursor captured before the body runs, while callers
that need to alter traversal state can still open-code the walk.
The safe variants remain useful when the caller needs access to the
temporary cursor or has stronger mutation requirements. Update their
comments to steer users toward the simpler iterators when that temporary
cursor is not needed.
Signed-off-by: Kaitao Cheng <chengkaitao@kylinos.cn>
---
include/linux/list.h | 46 +++++++++++++++++++++++++++++++++-----------
1 file changed, 35 insertions(+), 11 deletions(-)
diff --git a/include/linux/list.h b/include/linux/list.h
index 09d979976b3b..9df84a56a789 100644
--- a/include/linux/list.h
+++ b/include/linux/list.h
@@ -809,6 +809,29 @@ static inline size_t list_count_nodes(struct list_head *head)
#define list_entry_is_head(pos, head, member) \
list_is_head(&pos->member, (head))
+#define __list_for_each_entry(pos, next, head, member) \
+ for (typeof(pos) next = list_next_entry(pos = \
+ list_first_entry(head, typeof(*pos), member), member); \
+ !list_entry_is_head(pos, head, member); \
+ pos = next, next = list_next_entry(next, member))
+
+#define __list_for_each_entry_reverse(pos, prev, head, member) \
+ for (typeof(pos) prev = list_prev_entry(pos = \
+ list_last_entry(head, typeof(*pos), member), member); \
+ !list_entry_is_head(pos, head, member); \
+ pos = prev, prev = list_prev_entry(prev, member))
+
+#define __list_for_each_entry_continue(pos, next, head, member) \
+ for (typeof(pos) next = list_next_entry(pos = \
+ list_next_entry(pos, member), member); \
+ !list_entry_is_head(pos, head, member); \
+ pos = next, next = list_next_entry(next, member))
+
+#define __list_for_each_entry_from(pos, next, head, member) \
+ for (typeof(pos) next = list_next_entry(pos, member); \
+ !list_entry_is_head(pos, head, member); \
+ pos = next, next = list_next_entry(next, member))
+
/**
* list_for_each_entry - iterate over list of given type
* @pos: the type * to use as a loop cursor.
@@ -816,9 +839,7 @@ static inline size_t list_count_nodes(struct list_head *head)
* @member: the name of the list_head within the struct.
*/
#define list_for_each_entry(pos, head, member) \
- for (pos = list_first_entry(head, typeof(*pos), member); \
- !list_entry_is_head(pos, head, member); \
- pos = list_next_entry(pos, member))
+ __list_for_each_entry(pos, __UNIQUE_ID(next), head, member)
/**
* list_for_each_entry_reverse - iterate backwards over list of given type.
@@ -827,9 +848,7 @@ static inline size_t list_count_nodes(struct list_head *head)
* @member: the name of the list_head within the struct.
*/
#define list_for_each_entry_reverse(pos, head, member) \
- for (pos = list_last_entry(head, typeof(*pos), member); \
- !list_entry_is_head(pos, head, member); \
- pos = list_prev_entry(pos, member))
+ __list_for_each_entry_reverse(pos, __UNIQUE_ID(prev), head, member)
/**
* list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
@@ -852,9 +871,7 @@ static inline size_t list_count_nodes(struct list_head *head)
* the current position.
*/
#define list_for_each_entry_continue(pos, head, member) \
- for (pos = list_next_entry(pos, member); \
- !list_entry_is_head(pos, head, member); \
- pos = list_next_entry(pos, member))
+ __list_for_each_entry_continue(pos, __UNIQUE_ID(next), head, member)
/**
* list_for_each_entry_continue_reverse - iterate backwards from the given point
@@ -879,8 +896,7 @@ static inline size_t list_count_nodes(struct list_head *head)
* Iterate over list of given type, continuing from current position.
*/
#define list_for_each_entry_from(pos, head, member) \
- for (; !list_entry_is_head(pos, head, member); \
- pos = list_next_entry(pos, member))
+ __list_for_each_entry_from(pos, __UNIQUE_ID(next), head, member)
/**
* list_for_each_entry_from_reverse - iterate backwards over list of given type
@@ -901,6 +917,8 @@ static inline size_t list_count_nodes(struct list_head *head)
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_head within the struct.
+ *
+ * Prefer list_for_each_entry() unless the temporary cursor is needed.
*/
#define list_for_each_entry_safe(pos, n, head, member) \
for (pos = list_first_entry(head, typeof(*pos), member), \
@@ -917,6 +935,8 @@ static inline size_t list_count_nodes(struct list_head *head)
*
* Iterate over list of given type, continuing after current point,
* safe against removal of list entry.
+ *
+ * Prefer list_for_each_entry_continue() unless the temporary cursor is needed.
*/
#define list_for_each_entry_safe_continue(pos, n, head, member) \
for (pos = list_next_entry(pos, member), \
@@ -933,6 +953,8 @@ static inline size_t list_count_nodes(struct list_head *head)
*
* Iterate over list of given type from current point, safe against
* removal of list entry.
+ *
+ * Prefer list_for_each_entry_from() unless the temporary cursor is needed.
*/
#define list_for_each_entry_safe_from(pos, n, head, member) \
for (n = list_next_entry(pos, member); \
@@ -948,6 +970,8 @@ static inline size_t list_count_nodes(struct list_head *head)
*
* Iterate backwards over list of given type, safe against removal
* of list entry.
+ *
+ * Prefer list_for_each_entry_reverse() unless the temporary cursor is needed.
*/
#define list_for_each_entry_safe_reverse(pos, n, head, member) \
for (pos = list_last_entry(head, typeof(*pos), member), \
--
2.43.0
next prev parent reply other threads:[~2026-06-09 6:43 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-09 6:13 [PATCH v2 00/14] list: Prepare entry iterators to cache cursor state Kaitao Cheng
2026-06-09 6:13 ` [PATCH v2 01/14] drbd: Open-code transfer log list walk Kaitao Cheng
2026-06-09 6:13 ` [PATCH v2 02/14] firewire: core: Open-code topology " Kaitao Cheng
2026-06-09 6:25 ` [PATCH v2 03/14] drm/bridge: Open-code bridge chain list walks Kaitao Cheng
2026-06-09 6:25 ` [PATCH v2 04/14] drm/i915/gt: Open-code active timeline walk Kaitao Cheng
2026-06-09 7:00 ` Andy Shevchenko
2026-06-09 6:25 ` [PATCH v2 05/14] drm/i915: Open-code DFS dependency list walk Kaitao Cheng
2026-06-09 6:25 ` [PATCH v2 06/14] drm/ttm: Open-code reservation " Kaitao Cheng
2026-06-09 6:25 ` [PATCH v2 07/14] spi: fsi: Open-code message transfer walk Kaitao Cheng
2026-06-09 7:02 ` Andy Shevchenko
2026-06-09 6:25 ` [PATCH v2 08/14] spi: stm32-ospi: " Kaitao Cheng
2026-06-09 6:25 ` [PATCH v2 09/14] spi: stm32-qspi: " Kaitao Cheng
2026-06-09 6:38 ` [PATCH v2 10/14] spi: tegra210-quad: " Kaitao Cheng
2026-06-09 6:38 ` [PATCH v2 11/14] locking/locktorture: Open-code ww mutex list walk Kaitao Cheng
2026-06-09 6:38 ` [PATCH v2 12/14] locking/ww_mutex: Open-code stress reorder " Kaitao Cheng
2026-06-09 6:41 ` [PATCH v2 13/14] ASoC: dapm: Open-code widget invalidation walk Kaitao Cheng
2026-06-09 6:41 ` Kaitao Cheng [this message]
2026-06-09 6:47 ` [PATCH v2 00/14] list: Prepare entry iterators to cache cursor state Andy Shevchenko
2026-06-09 7:05 ` Andy Shevchenko
2026-06-09 10:33 ` Christian König
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260609064122.95825-2-kaitao.cheng@linux.dev \
--to=kaitao.cheng@linux.dev \
--cc=Laurent.pinchart@ideasonboard.com \
--cc=airlied@gmail.com \
--cc=akpm@linux-foundation.org \
--cc=alexandre.torgue@foss.st.com \
--cc=andriy.shevchenko@linux.intel.com \
--cc=andrzej.hajda@intel.com \
--cc=axboe@kernel.dk \
--cc=boqun@kernel.org \
--cc=brauner@kernel.org \
--cc=broonie@kernel.org \
--cc=chengkaitao@kylinos.cn \
--cc=christian.koenig@amd.com \
--cc=christoph.boehmwalder@linbit.com \
--cc=dave@stgolabs.net \
--cc=dhowells@redhat.com \
--cc=drbd-dev@lists.linbit.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=eajames@linux.ibm.com \
--cc=intel-gfx@lists.freedesktop.org \
--cc=jani.nikula@linux.intel.com \
--cc=jernej.skrabec@gmail.com \
--cc=jonas@kwiboo.se \
--cc=jonathanh@nvidia.com \
--cc=joonas.lahtinen@linux.intel.com \
--cc=josh@joshtriplett.org \
--cc=lars.ellenberg@linbit.com \
--cc=ldewangan@nvidia.com \
--cc=lgirdwood@gmail.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-block@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-sound@vger.kernel.org \
--cc=linux-spi@vger.kernel.org \
--cc=linux-stm32@st-md-mailman.stormreply.com \
--cc=linux-tegra@vger.kernel.org \
--cc=linux1394-devel@lists.sourceforge.net \
--cc=longman@redhat.com \
--cc=luca.ceresoli@bootlin.com \
--cc=maarten.lankhorst@linux.intel.com \
--cc=matthew.auld@intel.com \
--cc=matthew.brost@intel.com \
--cc=mcoquelin.stm32@gmail.com \
--cc=mingo@redhat.com \
--cc=mripard@kernel.org \
--cc=muchun.song@linux.dev \
--cc=neil.armstrong@linaro.org \
--cc=o-takashi@sakamocchi.jp \
--cc=paulmck@kernel.org \
--cc=perex@perex.cz \
--cc=peterz@infradead.org \
--cc=philipp.reisner@linbit.com \
--cc=ray.huang@amd.com \
--cc=rdunlap@infradead.org \
--cc=rfoss@kernel.org \
--cc=rodrigo.vivi@intel.com \
--cc=simona@ffwll.ch \
--cc=skomatineni@nvidia.com \
--cc=thierry.reding@kernel.org \
--cc=tiwai@suse.com \
--cc=tursulin@ursulin.net \
--cc=tzimmermann@suse.de \
--cc=will@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox