linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
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



  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