linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Linus Torvalds <torvalds@linux-foundation.org>
To: Kees Cook <keescook@chromium.org>
Cc: James Bottomley <James.Bottomley@hansenpartnership.com>,
	Allen Pais <allen.lkml@gmail.com>,
	Andrew Morton <akpm@linux-foundation.org>,
	Thomas Gleixner <tglx@linutronix.de>,
	Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	Jens Axboe <axboe@kernel.dk>
Subject: Re: [PATCH] linux/kernel.h: add container_from()
Date: Thu, 27 Aug 2020 13:46:33 -0700	[thread overview]
Message-ID: <CAHk-=whDhHWQo_QjZp36=x=GLMGOJ2xnfsUk9xkUuWRz=i9gOg@mail.gmail.com> (raw)
In-Reply-To: <202008271150.7231B901@keescook>

On Thu, Aug 27, 2020 at 12:28 PM Kees Cook <keescook@chromium.org> wrote:
>
> The common raw pattern for callbacks is:
>
> void callback(struct callback_handle *inner)
> {
>         struct outer *instance;
>         ...
>         instance = container_of(inner, struct outer, member_name_of_inner);
>
> There's so much redundancy here.

What?

It's not all that complicated or even particularly redundant. The main
redundancy comes from you splitting up the declaration from the
initialization - which is certainly fine, and often a good idea, but
it does mean that you mention "struct outer" and "instance" twice.

I don't see that kind of redundancy being a _problem_, though. "So
much redundancy" is just over-stating the issue completely.

In fact, we often encourage people to split declaration from
initialization exactly because it results in simpler expressions and
more legible code, even if that name is now redundant. So it's a small
extra typing of the type. Big deal.

The above is also a common pattern that once you know how
container_of() works, it's very legible.

Sure, if you're new to the kernel, and haven't seen "container_of()"
in other projects, it might initially be a bit of an odd pattern, but
that's the advantage of having one single standardized model: it
becomes a pattern, and you don't have to think about it.

And particularly with that argument-type pattern, you really have to
work at making over-long lines, since the indentation level will by
definition be just one.

Looking around, I do see a lot of people doing line-breaks, but that
tends to be when they insist on putting the variable initialization in
the declaration. And even then, it often seems pointless (eg

        struct idp_led *led = container_of(cdev,
                        struct idp_led, cdev);

was split for no good reason I can see, but it seems to be a pattern
in that file).

You really have to pick some pretty excessive type names (or variable
names) to get close to 80 characters. Again, to pick an example:

        struct timer_group_priv *priv = container_of(handle,
                        struct timer_group_priv, timer[handle->num]);

ends up being long even if you were to split it, but that funky
container_from() wouldn't have helped the real problem - the fact that
the above is complex and nasty.

And I had to _search_ for that example. All the normal cases of
split-line container-of's were due to doing it with the declaration,
or beause the first argument ended up being an expression in itself
and the nested expressions made it more complex.

And in the above example, the real complexity - and the reason the
line ends up long - is because the "member" isn't a member. The above
case works - and it's in fact *intended* to work, I'm not claiming
it's some mis-use of the macro.  But it's really a rather complex
case, where it would probably have been a good idea to add a comment
about how this really depends on handle->num being set correctly.

And in fact, it would probably have been a *perfect* example of where
a helper function really would have improved the code, not so much
from a line length perspective, but exactly because the above is a
much more complicated case than most container_of() cases are.

So a helper function like the kvm one I quoted would have been a good
idea. In ways that "container_from()" would not have been, since it
doesn't actually even address the source of complexity.

               Linus

  reply	other threads:[~2020-08-27 20:46 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-08-27  1:36 [PATCH] linux/kernel.h: add container_from() Allen Pais
2020-08-27  2:31 ` Kees Cook
2020-08-27 12:19   ` Greg Kroah-Hartman
2020-08-27 17:50     ` Kees Cook
2020-08-27 18:04 ` Linus Torvalds
2020-08-27 18:32   ` James Bottomley
2020-08-27 18:40     ` Linus Torvalds
2020-08-27 18:48       ` Linus Torvalds
2020-08-27 19:28         ` Kees Cook
2020-08-27 20:46           ` Linus Torvalds [this message]
2020-08-27 21:36             ` Al Viro
2020-08-27 22:14               ` Kees Cook
2020-08-28  7:09                 ` Allen
2020-08-28  7:07             ` Allen
2020-08-27 18:07 ` Rasmus Villemoes

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='CAHk-=whDhHWQo_QjZp36=x=GLMGOJ2xnfsUk9xkUuWRz=i9gOg@mail.gmail.com' \
    --to=torvalds@linux-foundation.org \
    --cc=James.Bottomley@hansenpartnership.com \
    --cc=akpm@linux-foundation.org \
    --cc=allen.lkml@gmail.com \
    --cc=axboe@kernel.dk \
    --cc=gregkh@linuxfoundation.org \
    --cc=keescook@chromium.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=tglx@linutronix.de \
    /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;
as well as URLs for NNTP newsgroup(s).