[PATCH] netfs: Fix gcc-12 warning by embedding vfs inode in netfs_i_context

Linus Torvalds torvalds at linux-foundation.org
Thu Jun 9 22:04:01 UTC 2022

On Thu, Jun 9, 2022 at 1:46 PM David Howells <dhowells at redhat.com> wrote:
>         struct my_inode {
> -               struct {
> -                       /* These must be contiguous */
> -                       struct inode            vfs_inode;
> -                       struct netfs_i_context  netfs_ctx;
> -               };
> +               struct netfs_inode netfs; /* Netfslib context and vfs inode */
>                 ...

Side note: I think this could have been done with an unnamed union as

        struct my_inode {
                union {
                        struct inode            vfs_inode;
                        struct netfs_inode netfs_inode;

instead, with the rule that 'netfs_inode' always starts with a 'struct inode'.

The advantage would have been that the old 'vfs_inode' syntax would
have continued to work, and much less of the ugliness.

So a fair amount of the noise in this patch could have been avoided.

That said, I think the end result is fine (and maybe less complicated
than using that union trick), so that's not the big deal.

But what I actually *really* detest in this patch is that

        struct netfs_inode *ctx = netfs_inode(file_inode(file));


In several cases that's just a different syntax for almost the same
problem that gcc-12 already complained about.

And yes, in some cases you do need it - particularly in the
"mapping->host" situation, you really have lost sight of the fact that
you really have a "struct netfs_inode *", and all you have is the
"struct inode *".

But in a lot of cases you really could do so much better: you *have* a
"struct netfs_inode" to begin with, but you converted it to just
"struct inode *", and now you're converting it back.

Look at that AFS code, for example, where we have afs_vnode_cache() doing

        return netfs_i_cookie(&vnode->netfs.inode);

and look how it *had* a netfs structure, and it was passing it to a
netfs function, but it explicitly passed the WRONG TYPE, so now we've
lost the type information and it is using that cast to fake it all

So I think the 'netfs' functions should take a 'struct netfs_inode
*ctx' as their argument.

Because the callers know what kind of inode they have, and they can -
and should - then pass the proper netfs context down.

IOW, I think you really should do something like the attached on top
of this all.

Only *very* lightly build-tested, but let me quote part of the diff to explain:

  -static inline struct fscache_cookie *netfs_i_cookie(struct inode *inode)
  +static inline struct fscache_cookie *netfs_i_cookie(struct netfs_inode *ctx)
  -       struct netfs_inode *ctx = netfs_inode(inode);
          return ctx->cache;

look, this part is obvious. If you are doing a "netfs_i_cookie()"
call, you had *better* know that you actually have a netfs_inode, not
some random "inode".

And most of the users already knew exactly that, so other paths of the
patch actually get cleaner too:

  -       return netfs_i_cookie(&v9inode->netfs.inode);
  +       return netfs_i_cookie(&v9inode->netfs);

but even when that wasn't the case, as in netfs_inode_init() use, we have:

   static void v9fs_set_netfs_context(struct inode *inode)
  -       netfs_inode_init(inode, &v9fs_req_ops);
  +       struct v9fs_inode *v9inode = V9FS_I(inode);
  +       netfs_inode_init(&v9inode->netfs, &v9fs_req_ops);

and now we're basically doing that same "taek inode pointer, convert
it to someting else" that I'm complaining about wrt the netfs code,
but notice how we are now doing it within the context of the 9p

So now we're converting not a 'random inode pointer that could come
from many different filesystems', but an *actual* well-defined 'this
is a 9p inode, so doing that V9FS_I(inode) conversion is normal' kind
of situation.

And at that point, we now have that 'struct netfs_inode' directly, and
don't need to play any other games.

Yes, a few 'netfs_inode()' users still remain. I don't love them
either, but they tend to be places where we really did get just the
raw inode pointer from the VFS layer (eg netfs_readahead is just used
directly as the ".readahead" function for filesystems).


-------------- next part --------------
A non-text attachment was scrubbed...
Name: patch.diff
Type: text/x-patch
Size: 8703 bytes
Desc: not available
URL: <http://lists.samba.org/pipermail/samba-technical/attachments/20220609/0e33aabb/patch.bin>

More information about the samba-technical mailing list