* [PATCH v1 1/3] list: add primitives for private list manipulations
2025-11-26 18:57 [PATCH v1 0/3] list: add primitives for private list manipulations Pasha Tatashin
@ 2025-11-26 18:57 ` Pasha Tatashin
2025-11-26 18:57 ` [PATCH v1 2/3] list: add kunit test for private list primitives Pasha Tatashin
` (3 subsequent siblings)
4 siblings, 0 replies; 14+ messages in thread
From: Pasha Tatashin @ 2025-11-26 18:57 UTC (permalink / raw)
To: corbet, pasha.tatashin, nicolas.frattaroli, linux-doc,
linux-kernel, akpm, kees, davidgow, pmladek, tamird, raemoar63,
ebiggers, diego.daniel.professional, rppt, pratyush, jasonmiu,
graf, dmatlack, rientjes
Linux recently added an ability to add private members to structs (i.e.
__private) and access them via ACCESS_PRIVATE(). This ensures that those
members are only accessible by the subsystem which owns the struct type,
and not to the object owner.
However, struct list_head often needs to be placed into the private
section to be manipulated privately by the subsystem.
Add macros to support private list manipulations in
<linux/list_private.h>.
Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
---
Documentation/core-api/list.rst | 9 ++
include/linux/list_private.h | 256 ++++++++++++++++++++++++++++++++
2 files changed, 265 insertions(+)
create mode 100644 include/linux/list_private.h
diff --git a/Documentation/core-api/list.rst b/Documentation/core-api/list.rst
index 86873ce9adbf..241464ca0549 100644
--- a/Documentation/core-api/list.rst
+++ b/Documentation/core-api/list.rst
@@ -774,3 +774,12 @@ Full List API
.. kernel-doc:: include/linux/list.h
:internal:
+
+Private List API
+================
+
+.. kernel-doc:: include/linux/list_private.h
+ :doc: Private List Primitives
+
+.. kernel-doc:: include/linux/list_private.h
+ :internal:
diff --git a/include/linux/list_private.h b/include/linux/list_private.h
new file mode 100644
index 000000000000..6f93d54e797a
--- /dev/null
+++ b/include/linux/list_private.h
@@ -0,0 +1,256 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/*
+ * Copyright (c) 2025, Google LLC.
+ * Pasha Tatashin <pasha.tatashin@soleen.com>
+ */
+#ifndef _LINUX_LIST_PRIVATE_H
+#define _LINUX_LIST_PRIVATE_H
+
+/**
+ * DOC: Private List Primitives
+ *
+ * Provides a set of list primitives identical in function to those in
+ * ``<linux/list.h>``, but designed for cases where the embedded
+ * ``&struct list_head`` is private member.
+ */
+
+#include <linux/compiler.h>
+#include <linux/list.h>
+
+#define __list_private_offset(type, member) \
+ ((size_t)(&ACCESS_PRIVATE(((type *)0), member)))
+
+/**
+ * list_private_entry - get the struct for this entry
+ * @ptr: the &struct list_head pointer.
+ * @type: the type of the struct this is embedded in.
+ * @member: the identifier passed to ACCESS_PRIVATE.
+ */
+#define list_private_entry(ptr, type, member) ({ \
+ const struct list_head *__mptr = (ptr); \
+ (type *)((char *)__mptr - __list_private_offset(type, member)); \
+})
+
+/**
+ * list_private_first_entry - get the first element from a list
+ * @ptr: the list head to take the element from.
+ * @type: the type of the struct this is embedded in.
+ * @member: the identifier passed to ACCESS_PRIVATE.
+ */
+#define list_private_first_entry(ptr, type, member) \
+ list_private_entry((ptr)->next, type, member)
+
+/**
+ * list_private_last_entry - get the last element from a list
+ * @ptr: the list head to take the element from.
+ * @type: the type of the struct this is embedded in.
+ * @member: the identifier passed to ACCESS_PRIVATE.
+ */
+#define list_private_last_entry(ptr, type, member) \
+ list_private_entry((ptr)->prev, type, member)
+
+/**
+ * list_private_next_entry - get the next element in list
+ * @pos: the type * to cursor
+ * @member: the name of the list_head within the struct.
+ */
+#define list_private_next_entry(pos, member) \
+ list_private_entry(ACCESS_PRIVATE(pos, member).next, typeof(*(pos)), member)
+
+/**
+ * list_private_next_entry_circular - get the next element in list
+ * @pos: the type * to cursor.
+ * @head: the list head to take the element from.
+ * @member: the name of the list_head within the struct.
+ *
+ * Wraparound if pos is the last element (return the first element).
+ * Note, that list is expected to be not empty.
+ */
+#define list_private_next_entry_circular(pos, head, member) \
+ (list_is_last(&ACCESS_PRIVATE(pos, member), head) ? \
+ list_private_first_entry(head, typeof(*(pos)), member) : \
+ list_private_next_entry(pos, member))
+
+/**
+ * list_private_prev_entry - get the prev element in list
+ * @pos: the type * to cursor
+ * @member: the name of the list_head within the struct.
+ */
+#define list_private_prev_entry(pos, member) \
+ list_private_entry(ACCESS_PRIVATE(pos, member).prev, typeof(*(pos)), member)
+
+/**
+ * list_prev_entry_circular - get the prev element in list
+ * @pos: the type * to cursor.
+ * @head: the list head to take the element from.
+ * @member: the name of the list_head within the struct.
+ *
+ * Wraparound if pos is the first element (return the last element).
+ * Note, that list is expected to be not empty.
+ */
+#define list_private_prev_entry_circular(pos, head, member) \
+ (list_is_first(&ACCESS_PRIVATE(pos, member), head) ? \
+ list_private_last_entry(head, typeof(*(pos)), member) : \
+ list_private_prev_entry(pos, member))
+
+/**
+ * list_private_entry_is_head - test if the entry points to the head of the list
+ * @pos: the type * to cursor
+ * @head: the head for your list.
+ * @member: the name of the list_head within the struct.
+ */
+#define list_private_entry_is_head(pos, head, member) \
+ list_is_head(&ACCESS_PRIVATE(pos, member), (head))
+
+/**
+ * list_private_for_each_entry - iterate over list of given type
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_head within the struct.
+ */
+#define list_private_for_each_entry(pos, head, member) \
+ for (pos = list_private_first_entry(head, typeof(*pos), member); \
+ !list_private_entry_is_head(pos, head, member); \
+ pos = list_private_next_entry(pos, member))
+
+/**
+ * list_private_for_each_entry_reverse - iterate backwards over list of given type.
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_head within the struct.
+ */
+#define list_private_for_each_entry_reverse(pos, head, member) \
+ for (pos = list_private_last_entry(head, typeof(*pos), member); \
+ !list_private_entry_is_head(pos, head, member); \
+ pos = list_private_prev_entry(pos, member))
+
+/**
+ * list_private_for_each_entry_continue - continue iteration over list of given type
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_head within the struct.
+ *
+ * Continue to iterate over list of given type, continuing after
+ * the current position.
+ */
+#define list_private_for_each_entry_continue(pos, head, member) \
+ for (pos = list_private_next_entry(pos, member); \
+ !list_private_entry_is_head(pos, head, member); \
+ pos = list_private_next_entry(pos, member))
+
+/**
+ * list_private_for_each_entry_continue_reverse - iterate backwards from the given point
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_head within the struct.
+ *
+ * Start to iterate over list of given type backwards, continuing after
+ * the current position.
+ */
+#define list_private_for_each_entry_continue_reverse(pos, head, member) \
+ for (pos = list_private_prev_entry(pos, member); \
+ !list_private_entry_is_head(pos, head, member); \
+ pos = list_private_prev_entry(pos, member))
+
+/**
+ * list_private_for_each_entry_from - iterate over list of given type from the current point
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_head within the struct.
+ *
+ * Iterate over list of given type, continuing from current position.
+ */
+#define list_private_for_each_entry_from(pos, head, member) \
+ for (; !list_private_entry_is_head(pos, head, member); \
+ pos = list_private_next_entry(pos, member))
+
+/**
+ * list_private_for_each_entry_from_reverse - iterate backwards over list of given type
+ * from the current point
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_head within the struct.
+ *
+ * Iterate backwards over list of given type, continuing from current position.
+ */
+#define list_private_for_each_entry_from_reverse(pos, head, member) \
+ for (; !list_private_entry_is_head(pos, head, member); \
+ pos = list_private_prev_entry(pos, member))
+
+/**
+ * list_private_for_each_entry_safe - iterate over list of given type safe against removal of list entry
+ * @pos: the type * to use as a loop cursor.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_head within the struct.
+ */
+#define list_private_for_each_entry_safe(pos, n, head, member) \
+ for (pos = list_private_first_entry(head, typeof(*pos), member), \
+ n = list_private_next_entry(pos, member); \
+ !list_private_entry_is_head(pos, head, member); \
+ pos = n, n = list_private_next_entry(n, member))
+
+/**
+ * list_private_for_each_entry_safe_continue - continue list iteration safe against removal
+ * @pos: the type * to use as a loop cursor.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_head within the struct.
+ *
+ * Iterate over list of given type, continuing after current point,
+ * safe against removal of list entry.
+ */
+#define list_private_for_each_entry_safe_continue(pos, n, head, member) \
+ for (pos = list_private_next_entry(pos, member), \
+ n = list_private_next_entry(pos, member); \
+ !list_private_entry_is_head(pos, head, member); \
+ pos = n, n = list_private_next_entry(n, member))
+
+/**
+ * list_private_for_each_entry_safe_from - iterate over list from current point safe against removal
+ * @pos: the type * to use as a loop cursor.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_head within the struct.
+ *
+ * Iterate over list of given type from current point, safe against
+ * removal of list entry.
+ */
+#define list_private_for_each_entry_safe_from(pos, n, head, member) \
+ for (n = list_private_next_entry(pos, member); \
+ !list_private_entry_is_head(pos, head, member); \
+ pos = n, n = list_private_next_entry(n, member))
+
+/**
+ * list_private_for_each_entry_safe_reverse - iterate backwards over list safe against removal
+ * @pos: the type * to use as a loop cursor.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_head within the struct.
+ *
+ * Iterate backwards over list of given type, safe against removal
+ * of list entry.
+ */
+#define list_private_for_each_entry_safe_reverse(pos, n, head, member) \
+ for (pos = list_private_last_entry(head, typeof(*pos), member), \
+ n = list_private_prev_entry(pos, member); \
+ !list_private_entry_is_head(pos, head, member); \
+ pos = n, n = list_private_prev_entry(n, member))
+
+/**
+ * list_private_safe_reset_next - reset a stale list_for_each_entry_safe loop
+ * @pos: the loop cursor used in the list_for_each_entry_safe loop
+ * @n: temporary storage used in list_for_each_entry_safe
+ * @member: the name of the list_head within the struct.
+ *
+ * list_safe_reset_next is not safe to use in general if the list may be
+ * modified concurrently (eg. the lock is dropped in the loop body). An
+ * exception to this is if the cursor element (pos) is pinned in the list,
+ * and list_safe_reset_next is called after re-taking the lock and before
+ * completing the current iteration of the loop body.
+ */
+#define list_private_safe_reset_next(pos, n, member) \
+ n = list_private_next_entry(pos, member)
+
+#endif /* _LINUX_LIST_PRIVATE_H */
--
2.52.0.487.g5c8c507ade-goog
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH v1 2/3] list: add kunit test for private list primitives
2025-11-26 18:57 [PATCH v1 0/3] list: add primitives for private list manipulations Pasha Tatashin
2025-11-26 18:57 ` [PATCH v1 1/3] " Pasha Tatashin
@ 2025-11-26 18:57 ` Pasha Tatashin
2025-11-29 7:47 ` David Gow
2025-11-26 18:57 ` [PATCH v1 3/3] liveupdate: luo_file: Use private list Pasha Tatashin
` (2 subsequent siblings)
4 siblings, 1 reply; 14+ messages in thread
From: Pasha Tatashin @ 2025-11-26 18:57 UTC (permalink / raw)
To: corbet, pasha.tatashin, nicolas.frattaroli, linux-doc,
linux-kernel, akpm, kees, davidgow, pmladek, tamird, raemoar63,
ebiggers, diego.daniel.professional, rppt, pratyush, jasonmiu,
graf, dmatlack, rientjes
Add a KUnit test suite for the new private list primitives.
The test defines a struct with a __private list_head and exercises every
macro defined in <linux/list_private.h>.
This ensures that the macros correctly handle the ACCESS_PRIVATE()
abstraction and compile without warnings when acting on private members,
verifying that qualifiers are stripped and offsets are calculated
correctly.
Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
---
lib/Kconfig.debug | 14 +++++++
lib/tests/Makefile | 1 +
lib/tests/list-private-test.c | 76 +++++++++++++++++++++++++++++++++++
3 files changed, 91 insertions(+)
create mode 100644 lib/tests/list-private-test.c
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 42143686151f..fa9388726182 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -2788,6 +2788,20 @@ config LIST_KUNIT_TEST
If unsure, say N.
+config LIST_PRIVATE_KUNIT_TEST
+ tristate "KUnit Test for Kernel Private Linked-list structures" if !KUNIT_ALL_TESTS
+ depends on KUNIT
+ default KUNIT_ALL_TESTS
+ help
+ This builds the KUnit test for the private linked-list primitives
+ defined in include/linux/list_private.h.
+
+ These primitives allow manipulation of list_head members that are
+ marked as private and require special accessors (ACCESS_PRIVATE)
+ to strip qualifiers or handle encapsulation.
+
+ If unsure, say N.
+
config HASHTABLE_KUNIT_TEST
tristate "KUnit Test for Kernel Hashtable structures" if !KUNIT_ALL_TESTS
depends on KUNIT
diff --git a/lib/tests/Makefile b/lib/tests/Makefile
index 601dba4b7d96..62a7f115f622 100644
--- a/lib/tests/Makefile
+++ b/lib/tests/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_TEST_IOV_ITER) += kunit_iov_iter.o
obj-$(CONFIG_IS_SIGNED_TYPE_KUNIT_TEST) += is_signed_type_kunit.o
obj-$(CONFIG_KPROBES_SANITY_TEST) += test_kprobes.o
obj-$(CONFIG_LIST_KUNIT_TEST) += list-test.o
+obj-$(CONFIG_LIST_PRIVATE_KUNIT_TEST) += list-private-test.o
obj-$(CONFIG_KFIFO_KUNIT_TEST) += kfifo_kunit.o
obj-$(CONFIG_TEST_LIST_SORT) += test_list_sort.o
obj-$(CONFIG_LINEAR_RANGES_TEST) += test_linear_ranges.o
diff --git a/lib/tests/list-private-test.c b/lib/tests/list-private-test.c
new file mode 100644
index 000000000000..3bd62939ae67
--- /dev/null
+++ b/lib/tests/list-private-test.c
@@ -0,0 +1,76 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * KUnit compilation/smoke test for Private list primitives.
+ *
+ * Copyright (c) 2025, Google LLC.
+ * Pasha Tatashin <pasha.tatashin@soleen.com>
+ */
+#include <linux/list_private.h>
+#include <kunit/test.h>
+
+/*
+ * This forces compiler to warn if you access it directly, because list
+ * primitives expect (struct list_head *), not (volatile struct list_head *).
+ */
+#undef __private
+#define __private volatile
+
+/* Redefine ACCESS_PRIVATE for this test. */
+#undef ACCESS_PRIVATE
+#define ACCESS_PRIVATE(p, member) \
+ (*((struct list_head *)((unsigned long)&((p)->member))))
+
+struct list_test_struct {
+ int data;
+ struct list_head __private list;
+};
+
+static void list_private_compile_test(struct kunit *test)
+{
+ struct list_test_struct entry;
+ struct list_test_struct *pos, *n;
+ LIST_HEAD(head);
+
+ INIT_LIST_HEAD(&ACCESS_PRIVATE(&entry, list));
+ list_add(&ACCESS_PRIVATE(&entry, list), &head);
+ pos = &entry;
+
+ pos = list_private_entry(&ACCESS_PRIVATE(&entry, list), struct list_test_struct, list);
+ pos = list_private_first_entry(&head, struct list_test_struct, list);
+ pos = list_private_last_entry(&head, struct list_test_struct, list);
+ pos = list_private_next_entry(pos, list);
+ pos = list_private_prev_entry(pos, list);
+ pos = list_private_next_entry_circular(pos, &head, list);
+ pos = list_private_prev_entry_circular(pos, &head, list);
+
+ if (list_private_entry_is_head(pos, &head, list))
+ return;
+
+ list_private_for_each_entry(pos, &head, list) { }
+ list_private_for_each_entry_reverse(pos, &head, list) { }
+ list_private_for_each_entry_continue(pos, &head, list) { }
+ list_private_for_each_entry_continue_reverse(pos, &head, list) { }
+ list_private_for_each_entry_from(pos, &head, list) { }
+ list_private_for_each_entry_from_reverse(pos, &head, list) { }
+
+ list_private_for_each_entry_safe(pos, n, &head, list)
+ list_private_safe_reset_next(pos, n, list);
+ list_private_for_each_entry_safe_continue(pos, n, &head, list) { }
+ list_private_for_each_entry_safe_from(pos, n, &head, list) { }
+ list_private_for_each_entry_safe_reverse(pos, n, &head, list) { }
+}
+
+static struct kunit_case list_private_test_cases[] = {
+ KUNIT_CASE(list_private_compile_test),
+ {},
+};
+
+static struct kunit_suite list_private_test_module = {
+ .name = "list-private-kunit-test",
+ .test_cases = list_private_test_cases,
+};
+
+kunit_test_suite(list_private_test_module);
+
+MODULE_DESCRIPTION("KUnit compilation test for private list primitives");
+MODULE_LICENSE("GPL");
--
2.52.0.487.g5c8c507ade-goog
^ permalink raw reply related [flat|nested] 14+ messages in thread* Re: [PATCH v1 2/3] list: add kunit test for private list primitives
2025-11-26 18:57 ` [PATCH v1 2/3] list: add kunit test for private list primitives Pasha Tatashin
@ 2025-11-29 7:47 ` David Gow
2025-11-29 19:48 ` Pasha Tatashin
0 siblings, 1 reply; 14+ messages in thread
From: David Gow @ 2025-11-29 7:47 UTC (permalink / raw)
To: Pasha Tatashin
Cc: corbet, nicolas.frattaroli, linux-doc, linux-kernel, akpm, kees,
pmladek, tamird, raemoar63, ebiggers, diego.daniel.professional,
rppt, pratyush, jasonmiu, graf, dmatlack, rientjes
[-- Attachment #1: Type: text/plain, Size: 5826 bytes --]
On Thu, 27 Nov 2025 at 02:57, Pasha Tatashin <pasha.tatashin@soleen.com> wrote:
>
> Add a KUnit test suite for the new private list primitives.
>
> The test defines a struct with a __private list_head and exercises every
> macro defined in <linux/list_private.h>.
>
> This ensures that the macros correctly handle the ACCESS_PRIVATE()
> abstraction and compile without warnings when acting on private members,
> verifying that qualifiers are stripped and offsets are calculated
> correctly.
>
> Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
> ---
Thanks -- I'm glad to see tests added with this!
I'd be okay with this living in the same config option as the other
list tests (LIST_KUNIT_TEST) if you'd prefer, but don't particularly
mind either way.
Reviewed-by: David Gow <davidgow@google.com>
Cheers,
-- David
> lib/Kconfig.debug | 14 +++++++
> lib/tests/Makefile | 1 +
> lib/tests/list-private-test.c | 76 +++++++++++++++++++++++++++++++++++
> 3 files changed, 91 insertions(+)
> create mode 100644 lib/tests/list-private-test.c
>
> diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
> index 42143686151f..fa9388726182 100644
> --- a/lib/Kconfig.debug
> +++ b/lib/Kconfig.debug
> @@ -2788,6 +2788,20 @@ config LIST_KUNIT_TEST
>
> If unsure, say N.
>
> +config LIST_PRIVATE_KUNIT_TEST
> + tristate "KUnit Test for Kernel Private Linked-list structures" if !KUNIT_ALL_TESTS
> + depends on KUNIT
> + default KUNIT_ALL_TESTS
> + help
> + This builds the KUnit test for the private linked-list primitives
> + defined in include/linux/list_private.h.
> +
> + These primitives allow manipulation of list_head members that are
> + marked as private and require special accessors (ACCESS_PRIVATE)
> + to strip qualifiers or handle encapsulation.
> +
> + If unsure, say N.
> +
> config HASHTABLE_KUNIT_TEST
> tristate "KUnit Test for Kernel Hashtable structures" if !KUNIT_ALL_TESTS
> depends on KUNIT
> diff --git a/lib/tests/Makefile b/lib/tests/Makefile
> index 601dba4b7d96..62a7f115f622 100644
> --- a/lib/tests/Makefile
> +++ b/lib/tests/Makefile
> @@ -25,6 +25,7 @@ obj-$(CONFIG_TEST_IOV_ITER) += kunit_iov_iter.o
> obj-$(CONFIG_IS_SIGNED_TYPE_KUNIT_TEST) += is_signed_type_kunit.o
> obj-$(CONFIG_KPROBES_SANITY_TEST) += test_kprobes.o
> obj-$(CONFIG_LIST_KUNIT_TEST) += list-test.o
> +obj-$(CONFIG_LIST_PRIVATE_KUNIT_TEST) += list-private-test.o
> obj-$(CONFIG_KFIFO_KUNIT_TEST) += kfifo_kunit.o
> obj-$(CONFIG_TEST_LIST_SORT) += test_list_sort.o
> obj-$(CONFIG_LINEAR_RANGES_TEST) += test_linear_ranges.o
> diff --git a/lib/tests/list-private-test.c b/lib/tests/list-private-test.c
> new file mode 100644
> index 000000000000..3bd62939ae67
> --- /dev/null
> +++ b/lib/tests/list-private-test.c
> @@ -0,0 +1,76 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * KUnit compilation/smoke test for Private list primitives.
> + *
> + * Copyright (c) 2025, Google LLC.
> + * Pasha Tatashin <pasha.tatashin@soleen.com>
> + */
> +#include <linux/list_private.h>
> +#include <kunit/test.h>
> +
> +/*
> + * This forces compiler to warn if you access it directly, because list
> + * primitives expect (struct list_head *), not (volatile struct list_head *).
> + */
> +#undef __private
> +#define __private volatile
> +
> +/* Redefine ACCESS_PRIVATE for this test. */
> +#undef ACCESS_PRIVATE
> +#define ACCESS_PRIVATE(p, member) \
> + (*((struct list_head *)((unsigned long)&((p)->member))))
> +
> +struct list_test_struct {
> + int data;
> + struct list_head __private list;
> +};
> +
> +static void list_private_compile_test(struct kunit *test)
> +{
> + struct list_test_struct entry;
> + struct list_test_struct *pos, *n;
> + LIST_HEAD(head);
> +
> + INIT_LIST_HEAD(&ACCESS_PRIVATE(&entry, list));
> + list_add(&ACCESS_PRIVATE(&entry, list), &head);
> + pos = &entry;
> +
> + pos = list_private_entry(&ACCESS_PRIVATE(&entry, list), struct list_test_struct, list);
> + pos = list_private_first_entry(&head, struct list_test_struct, list);
> + pos = list_private_last_entry(&head, struct list_test_struct, list);
> + pos = list_private_next_entry(pos, list);
> + pos = list_private_prev_entry(pos, list);
> + pos = list_private_next_entry_circular(pos, &head, list);
> + pos = list_private_prev_entry_circular(pos, &head, list);
> +
> + if (list_private_entry_is_head(pos, &head, list))
> + return;
> +
> + list_private_for_each_entry(pos, &head, list) { }
> + list_private_for_each_entry_reverse(pos, &head, list) { }
> + list_private_for_each_entry_continue(pos, &head, list) { }
> + list_private_for_each_entry_continue_reverse(pos, &head, list) { }
> + list_private_for_each_entry_from(pos, &head, list) { }
> + list_private_for_each_entry_from_reverse(pos, &head, list) { }
> +
> + list_private_for_each_entry_safe(pos, n, &head, list)
> + list_private_safe_reset_next(pos, n, list);
> + list_private_for_each_entry_safe_continue(pos, n, &head, list) { }
> + list_private_for_each_entry_safe_from(pos, n, &head, list) { }
> + list_private_for_each_entry_safe_reverse(pos, n, &head, list) { }
> +}
> +
> +static struct kunit_case list_private_test_cases[] = {
> + KUNIT_CASE(list_private_compile_test),
> + {},
> +};
> +
> +static struct kunit_suite list_private_test_module = {
> + .name = "list-private-kunit-test",
> + .test_cases = list_private_test_cases,
> +};
> +
> +kunit_test_suite(list_private_test_module);
> +
> +MODULE_DESCRIPTION("KUnit compilation test for private list primitives");
> +MODULE_LICENSE("GPL");
> --
> 2.52.0.487.g5c8c507ade-goog
>
[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 5281 bytes --]
^ permalink raw reply [flat|nested] 14+ messages in thread* Re: [PATCH v1 2/3] list: add kunit test for private list primitives
2025-11-29 7:47 ` David Gow
@ 2025-11-29 19:48 ` Pasha Tatashin
0 siblings, 0 replies; 14+ messages in thread
From: Pasha Tatashin @ 2025-11-29 19:48 UTC (permalink / raw)
To: David Gow
Cc: corbet, nicolas.frattaroli, linux-doc, linux-kernel, akpm, kees,
pmladek, tamird, raemoar63, ebiggers, diego.daniel.professional,
rppt, pratyush, jasonmiu, graf, dmatlack, rientjes
On Sat, Nov 29, 2025 at 2:47 AM David Gow <davidgow@google.com> wrote:
>
> On Thu, 27 Nov 2025 at 02:57, Pasha Tatashin <pasha.tatashin@soleen.com> wrote:
> >
> > Add a KUnit test suite for the new private list primitives.
> >
> > The test defines a struct with a __private list_head and exercises every
> > macro defined in <linux/list_private.h>.
> >
> > This ensures that the macros correctly handle the ACCESS_PRIVATE()
> > abstraction and compile without warnings when acting on private members,
> > verifying that qualifiers are stripped and offsets are calculated
> > correctly.
> >
> > Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
> > ---
>
> Thanks -- I'm glad to see tests added with this!
>
> I'd be okay with this living in the same config option as the other
> list tests (LIST_KUNIT_TEST) if you'd prefer, but don't particularly
> mind either way.
I prefer to keep them separate just because they work differently. The
other list tests emphasis on runtime correctness, and here emphasizes
on verifying ACCESS_PRIVATE() does not generate compiler warnings.
> Reviewed-by: David Gow <davidgow@google.com>
Thanks!
Pasha
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v1 3/3] liveupdate: luo_file: Use private list
2025-11-26 18:57 [PATCH v1 0/3] list: add primitives for private list manipulations Pasha Tatashin
2025-11-26 18:57 ` [PATCH v1 1/3] " Pasha Tatashin
2025-11-26 18:57 ` [PATCH v1 2/3] list: add kunit test for private list primitives Pasha Tatashin
@ 2025-11-26 18:57 ` Pasha Tatashin
2025-12-17 22:47 ` Andrew Morton
2025-11-26 19:19 ` [PATCH v1 0/3] list: add primitives for private list manipulations Andrew Morton
2025-11-27 5:09 ` Mike Rapoport
4 siblings, 1 reply; 14+ messages in thread
From: Pasha Tatashin @ 2025-11-26 18:57 UTC (permalink / raw)
To: corbet, pasha.tatashin, nicolas.frattaroli, linux-doc,
linux-kernel, akpm, kees, davidgow, pmladek, tamird, raemoar63,
ebiggers, diego.daniel.professional, rppt, pratyush, jasonmiu,
graf, dmatlack, rientjes
Switch LUO to use the private list iterators.
Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
---
kernel/liveupdate/luo_file.c | 7 ++++---
kernel/liveupdate/luo_internal.h | 7 -------
2 files changed, 4 insertions(+), 10 deletions(-)
diff --git a/kernel/liveupdate/luo_file.c b/kernel/liveupdate/luo_file.c
index ddff87917b21..c3af22fc2fd8 100644
--- a/kernel/liveupdate/luo_file.c
+++ b/kernel/liveupdate/luo_file.c
@@ -104,6 +104,7 @@
#include <linux/io.h>
#include <linux/kexec_handover.h>
#include <linux/kho/abi/luo.h>
+#include <linux/list_private.h>
#include <linux/liveupdate.h>
#include <linux/module.h>
#include <linux/sizes.h>
@@ -273,7 +274,7 @@ int luo_preserve_file(struct luo_file_set *file_set, u64 token, int fd)
goto err_fput;
err = -ENOENT;
- luo_list_for_each_private(fh, &luo_file_handler_list, list) {
+ list_private_for_each_entry(fh, &luo_file_handler_list, list) {
if (fh->ops->can_preserve(fh, file)) {
err = 0;
break;
@@ -757,7 +758,7 @@ int luo_file_deserialize(struct luo_file_set *file_set,
bool handler_found = false;
struct luo_file *luo_file;
- luo_list_for_each_private(fh, &luo_file_handler_list, list) {
+ list_private_for_each_entry(fh, &luo_file_handler_list, list) {
if (!strcmp(fh->compatible, file_ser[i].compatible)) {
handler_found = true;
break;
@@ -832,7 +833,7 @@ int liveupdate_register_file_handler(struct liveupdate_file_handler *fh)
return -EBUSY;
/* Check for duplicate compatible strings */
- luo_list_for_each_private(fh_iter, &luo_file_handler_list, list) {
+ list_private_for_each_entry(fh_iter, &luo_file_handler_list, list) {
if (!strcmp(fh_iter->compatible, fh->compatible)) {
pr_err("File handler registration failed: Compatible string '%s' already registered.\n",
fh->compatible);
diff --git a/kernel/liveupdate/luo_internal.h b/kernel/liveupdate/luo_internal.h
index c8973b543d1d..3f1e0c94637e 100644
--- a/kernel/liveupdate/luo_internal.h
+++ b/kernel/liveupdate/luo_internal.h
@@ -40,13 +40,6 @@ static inline int luo_ucmd_respond(struct luo_ucmd *ucmd,
*/
#define luo_restore_fail(__fmt, ...) panic(__fmt, ##__VA_ARGS__)
-/* Mimics list_for_each_entry() but for private list head entries */
-#define luo_list_for_each_private(pos, head, member) \
- for (struct list_head *__iter = (head)->next; \
- __iter != (head) && \
- ({ pos = container_of(__iter, typeof(*(pos)), member); 1; }); \
- __iter = __iter->next)
-
/**
* struct luo_file_set - A set of files that belong to the same sessions.
* @files_list: An ordered list of files associated with this session, it is
--
2.52.0.487.g5c8c507ade-goog
^ permalink raw reply related [flat|nested] 14+ messages in thread* Re: [PATCH v1 3/3] liveupdate: luo_file: Use private list
2025-11-26 18:57 ` [PATCH v1 3/3] liveupdate: luo_file: Use private list Pasha Tatashin
@ 2025-12-17 22:47 ` Andrew Morton
2025-12-18 0:58 ` Pasha Tatashin
0 siblings, 1 reply; 14+ messages in thread
From: Andrew Morton @ 2025-12-17 22:47 UTC (permalink / raw)
To: Pasha Tatashin
Cc: corbet, nicolas.frattaroli, linux-doc, linux-kernel, kees,
davidgow, pmladek, tamird, raemoar63, ebiggers,
diego.daniel.professional, rppt, pratyush, jasonmiu, graf,
dmatlack, rientjes
On Wed, 26 Nov 2025 13:57:25 -0500 Pasha Tatashin <pasha.tatashin@soleen.com> wrote:
> Switch LUO to use the private list iterators.
Seems kernel/liveupdate/luo_flb.c now needs conversion. Oh well, I'll
await v2.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v1 3/3] liveupdate: luo_file: Use private list
2025-12-17 22:47 ` Andrew Morton
@ 2025-12-18 0:58 ` Pasha Tatashin
0 siblings, 0 replies; 14+ messages in thread
From: Pasha Tatashin @ 2025-12-18 0:58 UTC (permalink / raw)
To: Andrew Morton
Cc: corbet, nicolas.frattaroli, linux-doc, linux-kernel, kees,
davidgow, pmladek, tamird, raemoar63, ebiggers,
diego.daniel.professional, rppt, pratyush, jasonmiu, graf,
dmatlack, rientjes
On Wed, Dec 17, 2025 at 5:48 PM Andrew Morton <akpm@linux-foundation.org> wrote:
>
> On Wed, 26 Nov 2025 13:57:25 -0500 Pasha Tatashin <pasha.tatashin@soleen.com> wrote:
>
> > Switch LUO to use the private list iterators.
>
> Seems kernel/liveupdate/luo_flb.c now needs conversion. Oh well, I'll
> await v2.
Now that list_private in your branch, I will send an updated FLB.
Thank you,
Pasha
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v1 0/3] list: add primitives for private list manipulations
2025-11-26 18:57 [PATCH v1 0/3] list: add primitives for private list manipulations Pasha Tatashin
` (2 preceding siblings ...)
2025-11-26 18:57 ` [PATCH v1 3/3] liveupdate: luo_file: Use private list Pasha Tatashin
@ 2025-11-26 19:19 ` Andrew Morton
2025-11-28 14:45 ` Pasha Tatashin
2025-11-27 5:09 ` Mike Rapoport
4 siblings, 1 reply; 14+ messages in thread
From: Andrew Morton @ 2025-11-26 19:19 UTC (permalink / raw)
To: Pasha Tatashin
Cc: corbet, nicolas.frattaroli, linux-doc, linux-kernel, kees,
davidgow, pmladek, tamird, raemoar63, ebiggers,
diego.daniel.professional, rppt, pratyush, jasonmiu, graf,
dmatlack, rientjes
On Wed, 26 Nov 2025 13:57:22 -0500 Pasha Tatashin <pasha.tatashin@soleen.com> wrote:
> Recently
Well, 2015, in ad315455d396, it seems.
> linux introduced the ability to mark structure members as
> __private and access them via ACCESS_PRIVATE(). This mechanism ensures
> that internal implementation details are only accessible by the owning
> subsystem, enforcing better encapsulation.
Didn't know about this. It's a thing which requires running sparse
(which is fine, people run sparse). It isn't used much at all.
> However, struct list_head is frequently used as an internal linkage
> mechanism within these private sections. The standard macros in
> <linux/list.h> (such as list_entry and list_for_each_entry) do not
> support ACCESS_PRIVATE() natively. Consequently, subsystems using
> private lists are forced to implement ad-hoc workarounds, verbose
> casting, or local iterator macros to avoid compiler warnings and access
> violations.
>
> This series introduces <linux/list_private.h>, which provides a set of
> primitives identical in function to those in <linux/list.h>, but
> designed specifically for cases where the embedded struct list_head is a
> private member.
>
> The series is structured as follows:
> Core Implementation: Adds the list_private.h header with support for
> entry retrieval and iteration (forward, reverse, safe, etc.).
>
> Testing: Adds a KUnit test suite to verify that the macros compile
> correctly and handle pointer offsets/qualifiers as expected.
>
> Adoption: Updates the liveupdate subsystem to use the new generic API,
> replacing its local luo_list_for_each_private implementation.
Fair enough. Let's push this into the next -rc cycle, OK?
^ permalink raw reply [flat|nested] 14+ messages in thread* Re: [PATCH v1 0/3] list: add primitives for private list manipulations
2025-11-26 19:19 ` [PATCH v1 0/3] list: add primitives for private list manipulations Andrew Morton
@ 2025-11-28 14:45 ` Pasha Tatashin
2025-12-06 0:52 ` Pasha Tatashin
0 siblings, 1 reply; 14+ messages in thread
From: Pasha Tatashin @ 2025-11-28 14:45 UTC (permalink / raw)
To: Andrew Morton
Cc: corbet, nicolas.frattaroli, linux-doc, linux-kernel, kees,
davidgow, pmladek, tamird, raemoar63, ebiggers,
diego.daniel.professional, rppt, pratyush, jasonmiu, graf,
dmatlack, rientjes
On Wed, Nov 26, 2025 at 2:19 PM Andrew Morton <akpm@linux-foundation.org> wrote:
>
> On Wed, 26 Nov 2025 13:57:22 -0500 Pasha Tatashin <pasha.tatashin@soleen.com> wrote:
>
> > Recently
>
> Well, 2015, in ad315455d396, it seems.
>
> > linux introduced the ability to mark structure members as
> > __private and access them via ACCESS_PRIVATE(). This mechanism ensures
> > that internal implementation details are only accessible by the owning
> > subsystem, enforcing better encapsulation.
>
> Didn't know about this. It's a thing which requires running sparse
> (which is fine, people run sparse). It isn't used much at all.
>
> > However, struct list_head is frequently used as an internal linkage
> > mechanism within these private sections. The standard macros in
> > <linux/list.h> (such as list_entry and list_for_each_entry) do not
> > support ACCESS_PRIVATE() natively. Consequently, subsystems using
> > private lists are forced to implement ad-hoc workarounds, verbose
> > casting, or local iterator macros to avoid compiler warnings and access
> > violations.
> >
> > This series introduces <linux/list_private.h>, which provides a set of
> > primitives identical in function to those in <linux/list.h>, but
> > designed specifically for cases where the embedded struct list_head is a
> > private member.
> >
> > The series is structured as follows:
> > Core Implementation: Adds the list_private.h header with support for
> > entry retrieval and iteration (forward, reverse, safe, etc.).
> >
> > Testing: Adds a KUnit test suite to verify that the macros compile
> > correctly and handle pointer offsets/qualifiers as expected.
> >
> > Adoption: Updates the liveupdate subsystem to use the new generic API,
> > replacing its local luo_list_for_each_private implementation.
>
> Fair enough. Let's push this into the next -rc cycle, OK?
Yes, this works.
Thank you,
Pasha
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v1 0/3] list: add primitives for private list manipulations
2025-11-28 14:45 ` Pasha Tatashin
@ 2025-12-06 0:52 ` Pasha Tatashin
2025-12-06 21:39 ` Andrew Morton
0 siblings, 1 reply; 14+ messages in thread
From: Pasha Tatashin @ 2025-12-06 0:52 UTC (permalink / raw)
To: Andrew Morton
Cc: corbet, nicolas.frattaroli, linux-doc, linux-kernel, kees,
davidgow, pmladek, tamird, raemoar63, ebiggers,
diego.daniel.professional, rppt, pratyush, jasonmiu, graf,
dmatlack, rientjes
> > > Adoption: Updates the liveupdate subsystem to use the new generic API,
> > > replacing its local luo_list_for_each_private implementation.
> >
> > Fair enough. Let's push this into the next -rc cycle, OK?
>
Hi Andrew,
Could you please take this into nonmm-unstable branch, I want to send
a new version of LUO-FLB, and would like change it to use this API as
well.
Thank you,
Pasha
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v1 0/3] list: add primitives for private list manipulations
2025-12-06 0:52 ` Pasha Tatashin
@ 2025-12-06 21:39 ` Andrew Morton
2025-12-06 23:25 ` Pasha Tatashin
0 siblings, 1 reply; 14+ messages in thread
From: Andrew Morton @ 2025-12-06 21:39 UTC (permalink / raw)
To: Pasha Tatashin
Cc: corbet, nicolas.frattaroli, linux-doc, linux-kernel, kees,
davidgow, pmladek, tamird, raemoar63, ebiggers,
diego.daniel.professional, rppt, pratyush, jasonmiu, graf,
dmatlack, rientjes
On Fri, 5 Dec 2025 16:52:32 -0800 Pasha Tatashin <pasha.tatashin@soleen.com> wrote:
> > > > Adoption: Updates the liveupdate subsystem to use the new generic API,
> > > > replacing its local luo_list_for_each_private implementation.
> > >
> > > Fair enough. Let's push this into the next -rc cycle, OK?
> >
>
> Hi Andrew,
>
> Could you please take this into nonmm-unstable branch, I want to send
> a new version of LUO-FLB, and would like change it to use this API as
> well.
We're in the middle of the merge window and this is next-rc-cycle
material. mm-nonmm-unstable is included in linux-next and linux-next
rules request that we not add new material to -next until the merge
window has ended.
So please resend this material after -rc1 is released, thanks.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v1 0/3] list: add primitives for private list manipulations
2025-12-06 21:39 ` Andrew Morton
@ 2025-12-06 23:25 ` Pasha Tatashin
0 siblings, 0 replies; 14+ messages in thread
From: Pasha Tatashin @ 2025-12-06 23:25 UTC (permalink / raw)
To: Andrew Morton
Cc: corbet, nicolas.frattaroli, linux-doc, linux-kernel, kees,
davidgow, pmladek, tamird, raemoar63, ebiggers,
diego.daniel.professional, rppt, pratyush, jasonmiu, graf,
dmatlack, rientjes
On Sat, Dec 6, 2025 at 2:39 PM Andrew Morton <akpm@linux-foundation.org> wrote:
>
> On Fri, 5 Dec 2025 16:52:32 -0800 Pasha Tatashin <pasha.tatashin@soleen.com> wrote:
>
> > > > > Adoption: Updates the liveupdate subsystem to use the new generic API,
> > > > > replacing its local luo_list_for_each_private implementation.
> > > >
> > > > Fair enough. Let's push this into the next -rc cycle, OK?
> > >
> >
> > Hi Andrew,
> >
> > Could you please take this into nonmm-unstable branch, I want to send
> > a new version of LUO-FLB, and would like change it to use this API as
> > well.
>
> We're in the middle of the merge window and this is next-rc-cycle
> material. mm-nonmm-unstable is included in linux-next and linux-next
> rules request that we not add new material to -next until the merge
> window has ended.
>
> So please resend this material after -rc1 is released, thanks.
I see, thank you for your clarification. I will resent after rc1.
Thanks,
Pasha
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v1 0/3] list: add primitives for private list manipulations
2025-11-26 18:57 [PATCH v1 0/3] list: add primitives for private list manipulations Pasha Tatashin
` (3 preceding siblings ...)
2025-11-26 19:19 ` [PATCH v1 0/3] list: add primitives for private list manipulations Andrew Morton
@ 2025-11-27 5:09 ` Mike Rapoport
4 siblings, 0 replies; 14+ messages in thread
From: Mike Rapoport @ 2025-11-27 5:09 UTC (permalink / raw)
To: Pasha Tatashin
Cc: Dan Carpenter, corbet, nicolas.frattaroli, linux-doc,
linux-kernel, akpm, kees, davidgow, pmladek, tamird, raemoar63,
ebiggers, diego.daniel.professional, pratyush, jasonmiu, graf,
dmatlack, rientjes
(added Dan Carpenter)
On Wed, Nov 26, 2025 at 01:57:22PM -0500, Pasha Tatashin wrote:
> Recently linux introduced the ability to mark structure members as
> __private and access them via ACCESS_PRIVATE(). This mechanism ensures
> that internal implementation details are only accessible by the owning
> subsystem, enforcing better encapsulation.
>
> However, struct list_head is frequently used as an internal linkage
> mechanism within these private sections. The standard macros in
> <linux/list.h> (such as list_entry and list_for_each_entry) do not
> support ACCESS_PRIVATE() natively. Consequently, subsystems using
> private lists are forced to implement ad-hoc workarounds, verbose
> casting, or local iterator macros to avoid compiler warnings and access
> violations.
>
> This series introduces <linux/list_private.h>, which provides a set of
> primitives identical in function to those in <linux/list.h>, but
> designed specifically for cases where the embedded struct list_head is a
> private member.
>
> The series is structured as follows:
> Core Implementation: Adds the list_private.h header with support for
> entry retrieval and iteration (forward, reverse, safe, etc.).
>
> Testing: Adds a KUnit test suite to verify that the macros compile
> correctly and handle pointer offsets/qualifiers as expected.
>
> Adoption: Updates the liveupdate subsystem to use the new generic API,
> replacing its local luo_list_for_each_private implementation.
>
> Pasha Tatashin (3):
> list: add primitives for private list manipulations
> list: add kunit test for private list primitives
> liveupdate: luo_file: Use private list
>
> Documentation/core-api/list.rst | 9 ++
> include/linux/list_private.h | 256 +++++++++++++++++++++++++++++++
> kernel/liveupdate/luo_file.c | 7 +-
> kernel/liveupdate/luo_internal.h | 7 -
> lib/Kconfig.debug | 14 ++
> lib/tests/Makefile | 1 +
> lib/tests/list-private-test.c | 76 +++++++++
> 7 files changed, 360 insertions(+), 10 deletions(-)
> create mode 100644 include/linux/list_private.h
> create mode 100644 lib/tests/list-private-test.c
>
>
> base-commit: 663d0d1af3faefe673cabf4b6b077149a87ad71f
> --
> 2.52.0.487.g5c8c507ade-goog
>
--
Sincerely yours,
Mike.
^ permalink raw reply [flat|nested] 14+ messages in thread