All of lore.kernel.org
 help / color / mirror / Atom feed
From: Al Viro <viro@zeniv.linux.org.uk>
To: Mateusz Guzik <mjguzik@gmail.com>
Cc: brauner@kernel.org, jack@suse.cz, linux-kernel@vger.kernel.org,
	linux-fsdevel@vger.kernel.org
Subject: Re: [PATCH v2] fs: hide names_cache behind runtime const machinery
Date: Tue, 2 Dec 2025 05:52:58 +0000	[thread overview]
Message-ID: <20251202055258.GB1712166@ZenIV> (raw)
In-Reply-To: <CAGudoHGbYvSAq=eJySxsf-AqkQ+ne_1gzuaojidA-GH+znw2hw@mail.gmail.com>

On Tue, Dec 02, 2025 at 06:10:36AM +0100, Mateusz Guzik wrote:

> So IIUC whatever APIs aside, the crux of this idea is to have
> kmem_cache objs defined instead of having pointers to them, as in:
> -struct kmem_cache *names_cachep __ro_after_init;
> +struct kmem_cache names_cachep __ro_after_init;

Huh?  __ro_after_init will break instantly - the contents changes with
each allocation, after all.  What I want is
static struct kmem_cache_store names_cache;

As for the many places to modify...

fs/file.c:390:  newf = kmem_cache_alloc(files_cachep, GFP_KERNEL);
fs/file.c:422:                  kmem_cache_free(files_cachep, newf);
fs/file.c:514:          kmem_cache_free(files_cachep, files);
include/linux/fdtable.h:116:extern struct kmem_cache *files_cachep;
kernel/fork.c:429:struct kmem_cache *files_cachep;
kernel/fork.c:2987:     files_cachep = kmem_cache_create("files_cache",
samples/kmemleak/kmemleak-test.c:52:    pr_info("kmem_cache_alloc(files_cachep) = 0x%px\n",
samples/kmemleak/kmemleak-test.c:53:            kmem_cache_alloc(files_cachep, GFP_KERNEL));
samples/kmemleak/kmemleak-test.c:54:    pr_info("kmem_cache_alloc(files_cachep) = 0x%px\n",
samples/kmemleak/kmemleak-test.c:55:            kmem_cache_alloc(files_cachep, GFP_KERNEL));

I would argue for making it static in fs/file.c, where we have the grand
total of 3 places using the sucker, between two functions.

dentry_cache:
fs/dcache.c:345:        kmem_cache_free(dentry_cache, dentry); 
fs/dcache.c:352:        kmem_cache_free(dentry_cache, dentry);
fs/dcache.c:1690:       dentry = kmem_cache_alloc_lru(dentry_cache, &sb->s_dentry_lru,
fs/dcache.c:1711:                       kmem_cache_free(dentry_cache, dentry); 
fs/dcache.c:1748:                       kmem_cache_free(dentry_cache, dentry);

5 lines, between 3 functions (__d_free(), __d_free_external(), __d_allock()).

mnt_cache:
fs/namespace.c:293:     struct mount *mnt = kmem_cache_zalloc(mnt_cache, GFP_KERNEL);
fs/namespace.c:342:     kmem_cache_free(mnt_cache, mnt);
fs/namespace.c:737:     kmem_cache_free(mnt_cache, mnt);

3 lines, alloc_vfsmnt() and free_vfsmnt()

sock_inode_cachep:
net/socket.c:322:       ei = alloc_inode_sb(sb, sock_inode_cachep, GFP_KERNEL);
net/socket.c:343:       kmem_cache_free(sock_inode_cachep, ei);

2 lines, sock_alloc_inode() and sock_free_inode() (sockets are coallocated with
inodes).

struct filename: two lines after that series.

task_struct_cachep:
kernel/fork.c:184:      return kmem_cache_alloc_node(task_struct_cachep, GFP_KERNEL, node);
kernel/fork.c:189:      kmem_cache_free(task_struct_cachep, tsk);

and so it goes; that's the sane pattern - you want few places where objects of given
type are allocated and freed, so that tracing the callchains would be feasible.
names_cachep used to be shitty in that respect, what with its abuse by weird __getname()
callers.  It's not the common situation, thankfully.

The delicate part is headers, indeed - we don't want to expose struct kmem_cache guts
anywhere outside of mm/*, and not the entire mm/* either.  But that's not hard to
deal with - see include/generate/bounds.h, include/generate/rq-offsets.h, etc.
Exact same technics can be used to get sizeof(struct kmem_cache) calculated and
put into generated header.  Then we get something like struct kmem_cache_store with
the right size and alignment, and _that_ would be what the variables would be.
With static inline struct kmem_cache *to_kmem_cache(struct kmem_cache_store *)
returning a cast and e.g.

static inline void free_filename(struct __filename *p)
{
        kmem_cache_free(to_kmem_cache(&names_cache), p);
}

as an example of use.

Anyway, for now I've applied your patch pretty much as-is; conversion of the
sort described above can be done afterwards just fine.

  reply	other threads:[~2025-12-02  5:52 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-12-01  8:32 [PATCH v2] fs: hide names_cache behind runtime const machinery Mateusz Guzik
2025-12-01  8:51 ` Al Viro
2025-12-02  2:31   ` Al Viro
2025-12-02  5:10     ` Mateusz Guzik
2025-12-02  5:52       ` Al Viro [this message]
2025-12-02  6:18         ` Mateusz Guzik
2025-12-02  6:32           ` Al Viro
2025-12-02  7:21             ` Al Viro
2025-12-02  6:20         ` Al Viro

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=20251202055258.GB1712166@ZenIV \
    --to=viro@zeniv.linux.org.uk \
    --cc=brauner@kernel.org \
    --cc=jack@suse.cz \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mjguzik@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.