From: Jakob Koschel <jakobkoschel@gmail.com>
To: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Xiaomeng Tong <xiam0nd.tong@gmail.com>,
Arnd Bergmann <arnd@arndb.de>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Jann Horn <jannh@google.com>, Kees Cook <keescook@chromium.org>,
Linux Kbuild mailing list <linux-kbuild@vger.kernel.org>,
Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
Linux-MM <linux-mm@kvack.org>, Netdev <netdev@vger.kernel.org>
Subject: Re: [PATCH 2/6] list: add new MACROs to make iterator invisiable outside the loop
Date: Sun, 6 Mar 2022 13:19:09 +0100 [thread overview]
Message-ID: <634CBC77-281E-421C-9ED9-DB9E7224E7EA@gmail.com> (raw)
In-Reply-To: <CAHk-=wiacQM76xec=Hr7cLchVZ8Mo9VDHmXRJzJ_EX4sOsApEA@mail.gmail.com>
> On 6. Mar 2022, at 01:35, Linus Torvalds <torvalds@linux-foundation.org> wrote:
>
> On Sat, Mar 5, 2022 at 1:09 PM Linus Torvalds
> <torvalds@linux-foundation.org> wrote:
>>
>> Now, I'd love for the list head entry itself to "declare the type",
>> and solve it that way. That would in many ways be the optimal
>> situation, in that when a structure has that
>>
>> struct list_head xyz;
>>
>> entry, it would be lovely to declare *there* what the list entry type
>> is - and have 'list_for_each_entry()' just pick it up that way.
>>
>> It would be doable in theory - with some preprocessor trickery [...]
>
> Ok, I decided to look at how that theory looks in real life.
>
> The attached patch does actually work for me. I'm not saying this is
> *beautiful*, but I made the changes to kernel/exit.c to show how this
> can be used, and while the preprocessor tricks and the odd "unnamed
> union with a special member to give the target type" is all kinds of
> hacky, the actual use case code looks quite nice.
>
> In particular, look at the "good case" list_for_each_entry() transformation:
>
> static int do_wait_thread(struct wait_opts *wo, struct task_struct *tsk)
> {
> - struct task_struct *p;
> -
> - list_for_each_entry(p, &tsk->children, sibling) {
> + list_traverse(p, &tsk->children, sibling) {
>
> IOW, it avoided the need to declare 'p' entirely, and it avoids the
> need for a type, because the macro now *knows* the type of that
> 'tsk->children' list and picks it out automatically.
>
> So 'list_traverse()' is basically a simplified version of
> 'list_for_each_entry()'.
>
> That patch also has - as another example - the "use outside the loop"
> case in mm_update_next_owner(). That is more of a "rewrite the loop
> cleanly using list_traverse() thing, but it's also quite simple and
> natural.
>
> One nice part of this approach is that it allows for incremental changes.
>
> In fact, the patch very much is meant to demonstrate exactly that:
> yes, it converts the uses in kernel/exit.c, but it does *not* convert
> the code in kernel/fork.c, which still does that old-style traversal:
>
> list_for_each_entry(child, &parent->children, sibling) {
>
> and the kernel/fork.c code continues to work as well as it ever did.
>
> So that new 'list_traverse()' function allows for people to say "ok, I
> will now declare that list head with that list_traversal_head() macro,
> and then I can convert 'list_for_each_entry()' users one by one to
> this simpler syntax that also doesn't allow the list iterator to be
> used outside the list.
>
> What do people think? Is this clever and useful, or just too subtle
> and odd to exist?
>
> NOTE! I decided to add that "name of the target head in the target
> type" to the list_traversal_head() macro, but it's not actually used
> as is. It's more of a wishful "maybe we could add some sanity checking
> of the target list entries later".
>
> Comments?
I guess we could apply this to list_for_each_entry() as well
once all the uses after the loop are fixed?
I feel like this simply introduces a new set of macros
(we would also need list_traverse_reverse(), list_traverse_continue_reverse()
etc) and end up with a second set of macros that do pretty much
the same as the first one.
I like the way of using list_traversal_head() to only remember the type.
The interface of list_traverse() is the same as list_for_each_entry() so
we could just do this with a simple coccinelle script once 'pos' is no
longer used after the loop:
-struct some_struct *pos;
+list_traversal_head(struct some_struct, pos, target_member);
although there are *some* cases where 'pos' is also used separately
in the function which would need to change, e.g.:
struct some_struct *pos = some_variable;
if (pos)
// do one thing
else
list_for_each_entry(pos, ..., ...)
(I've fixed ~440/450 cases now and I'm chunking it into patch sets right now.
The once left over are non-obvious code I would need some input on)
Personally I guess I also prefer the name list_for_each_entry() over list_traverse()
and not having two types of iterators for the same thing at the same time.
>
> Linus
> <patch.diff>
Jakob
next prev parent reply other threads:[~2022-03-06 12:19 UTC|newest]
Thread overview: 38+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-03-01 7:58 [PATCH 0/6] list_for_each_entry*: " Xiaomeng Tong
2022-03-01 7:58 ` [PATCH 1/6] Kbuild: compile kernel with gnu11 std Xiaomeng Tong
2022-03-01 17:59 ` kernel test robot
2022-03-01 20:16 ` Linus Torvalds
2022-03-01 20:54 ` Arnd Bergmann
2022-03-01 21:04 ` Linus Torvalds
2022-03-01 21:15 ` Linus Torvalds
2022-03-01 21:43 ` Xiaomeng Tong
2022-03-01 7:58 ` [PATCH 2/6] list: add new MACROs to make iterator invisiable outside the loop Xiaomeng Tong
2022-03-02 2:52 ` kernel test robot
2022-03-02 13:02 ` James Bottomley
2022-03-03 3:31 ` Xiaomeng Tong
2022-03-06 14:33 ` James Bottomley
2022-03-03 20:02 ` Linus Torvalds
2022-03-04 2:51 ` Xiaomeng Tong
2022-03-05 21:09 ` Linus Torvalds
2022-03-06 0:35 ` Linus Torvalds
2022-03-06 12:19 ` Jakob Koschel [this message]
2022-03-06 18:57 ` Linus Torvalds
2022-03-06 14:06 ` Xiaomeng Tong
2022-03-10 23:54 ` [PATCH 2/6] list: add new MACROs to make iterator invisiable Michał Mirosław
2022-03-11 0:46 ` Linus Torvalds
2022-03-12 10:24 ` Michał Mirosław
2022-03-12 21:43 ` Linus Torvalds
2022-03-11 7:15 ` [RFC PATCH] list: test: Add a test for list_traverse David Gow
2022-03-11 14:27 ` [PATCH 2/6] list: add new MACROs to make iterator invisiable outside the loop Daniel Thompson
2022-03-11 18:41 ` Linus Torvalds
2022-03-16 15:45 ` Daniel Thompson
2022-03-01 7:58 ` [PATCH 3/6] kernel: remove iterator use " Xiaomeng Tong
2022-03-01 10:41 ` Greg KH
2022-03-01 11:34 ` Xiaomeng Tong
2022-03-01 11:48 ` Xiaomeng Tong
2022-03-01 7:58 ` [PATCH 4/6] mm: " Xiaomeng Tong
2022-03-01 12:19 ` Xiaomeng Tong
2022-03-01 7:58 ` [PATCH 5/6] net/core: " Xiaomeng Tong
2022-03-01 12:23 ` Xiaomeng Tong
2022-03-01 7:58 ` [PATCH 6/6] drivers/dma: " Xiaomeng Tong
2022-03-01 12:25 ` Xiaomeng Tong
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=634CBC77-281E-421C-9ED9-DB9E7224E7EA@gmail.com \
--to=jakobkoschel@gmail.com \
--cc=arnd@arndb.de \
--cc=gregkh@linuxfoundation.org \
--cc=jannh@google.com \
--cc=keescook@chromium.org \
--cc=linux-kbuild@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=netdev@vger.kernel.org \
--cc=torvalds@linux-foundation.org \
--cc=xiam0nd.tong@gmail.com \
/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