[PATCHES] assorted dcache stuff

From: Al Viro
Date: Fri Nov 24 2023 - 01:09:14 EST


Assorted dcache cleanups. There's a couple of commits that live in
never-rebased branches shared with selinux and overlayfs trees resp.

Lives in #work.dcache-misc, #no-rebase-overlayfs, #merged-selinux
and #work.dcache (all pulled by the last one, as is #work.dcache2) in
git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs.git
Individual patches in followups. Review and testing would be very welcome;
it survives the local beating, but the more the better...

Diffstat (sans #work.dcache2):

fs/dcache.c | 157 +++++++++++++++----------------------------
fs/file_table.c | 5 --
fs/internal.h | 5 ++
fs/libfs.c | 17 ++---
fs/nsfs.c | 7 +-
fs/overlayfs/export.c | 23 +------
include/linux/dcache.h | 142 +++++++++++++++++---------------------
security/selinux/selinuxfs.c | 144 ++++++++++++++++++---------------------
8 files changed, 194 insertions(+), 306 deletions(-)

Shortlog (again, excluding #work.dcache2):

Al Viro (21):
selinux: saner handling of policy reloads
struct dentry: get rid of randomize_layout idiocy
get rid of __dget()
DCACHE_... ->d_flags bits: switch to BIT()
DCACHE_COOKIE: RIP
kill d_{is,set}_fallthru()
dentry.h: trim externs
[software coproarchaeology] dentry.h: kill a mysterious comment
kill d_backing_dentry()
Merge branch 'no-rebase-overlayfs' into work.dcache-misc
kill d_instantate_anon(), fold __d_instantiate_anon() into remaining caller
d_alloc_pseudo(): move setting ->d_op there from the (sole) caller
nsfs: use d_make_root()
Merge branch 'merged-selinux' into work.dcache-misc
simple_fill_super(): don't bother with d_genocide() on failure
d_genocide(): move the extern into fs/internal.h
get rid of DCACHE_GENOCIDE
d_alloc_parallel(): in-lookup hash insertion doesn't need an RCU variant
__d_unalias() doesn't use inode argument
Merge branch 'work.dcache2' into work.dcache
kill DCACHE_MAY_FREE

Amir Goldstein (1):
ovl: stop using d_alloc_anon()/d_instantiate_anon()

Vegard Nossum (1):
dcache: remove unnecessary NULL check in dget_dlock()

[merged-selinux]
1/#) selinux: saner handling of policy reloads
Fix abuses of lock_rename() and d_genocide() in there.

[no-rebase-overlayfs]
2/#) ovl: stop using d_alloc_anon()/d_instantiate_anon()
Switch overlayfs to d_obtain_alias(); overlayfs used keep a data
structure (struct ovl_entry) hanging off a dentry, which prevented the
use of d_obtain_alias() there.
We couldn't call d_obtain_alias() and attach struct ovl_entry to
resulting dentry - new dentry would be exposed as an inode alias while
still not in a usable state.
These days ovl_entry got moved to their inodes and the rest
of the things done in ovl_obtain_alias() turned out to be not needed.
The bottom line: ovl_obtain_alias() can use straight d_obtain_alias()
and doesn't need an access to the guts of that primitive.

[work.dcache-misc]
[the first two used to be in #work.dcache2]
3/#) struct dentry: get rid of randomize_layout idiocy
This is beyond ridiculous. There is a reason why that thing
is cacheline-aligned...

4/#) get rid of __dget()
fold into the sole remaining caller

5/#) DCACHE_... ->d_flags bits: switch to BIT()
For bits 20..22 (inode type cached in ->d_flags) turn the
definitions into expressions like (5 << 20); everything else turns into
straight use of BIT()

6/#) DCACHE_COOKIE: RIP
the last user gone in 2021...

7/#) kill d_{is,set}_fallthru()
Introduced in 2015 and never had any in-tree users...

8/#) dentry.h: trim externs
d_instantiate_unique() had been gone for 7 years; __d_lookup...()
and shrink_dcache_for_umount() are fs/internal.h fodder.

9/#) [software coproarchaeology] dentry.h: kill a mysterious comment
there's a strange comment in front of d_lookup() declaration:
/* appendix may either be NULL or be used for transname suffixes */
Looks like nobody had been curious enough to track its history;
it predates git, it predates bitkeeper and if you look through the
pre-BK trees, you finally arrive at this in 2.1.44-for-davem:
/* appendix may either be NULL or be used for transname suffixes */
-extern struct dentry * d_lookup(struct inode * dir, struct qstr * name,
- struct qstr * appendix);
+extern struct dentry * d_lookup(struct dentry * dir, struct qstr * name);
In other words, it refers to the third argument d_lookup() used to have
back then. It had been introduced in 2.1.43-pre, on June 12 1997,
along with d_lookup(), only to be removed by July 4 1997, presumably
when the Cthulhu-awful thing it used to be used for (look for
CONFIG_TRANS_NAMES in 2.1.43-pre, and keep a heavy-duty barfbag
ready) had been, er, noticed and recognized for what it had been.
Despite the appendectomy, the comment remained. Some things really
need to be put out of their misery...

10/#) kill d_backing_dentry()
no users left

11/#) kill d_instantate_anon(), fold __d_instantiate_anon() into remaining caller
now that the only user of d_instantiate_anon() is gone...

12/#) d_alloc_pseudo(): move setting ->d_op there from the (sole) caller
more obviously safe there...

13/#) nsfs: use d_make_root()
Normally d_make_root() is used to create the root dentry of superblock;
here we use it for a different purpose, but... idiomatic or not, we need the
same operation.

14/#) simple_fill_super(): don't bother with d_genocide() on failure
Failing ->fill_super() will be followed by ->kill_sb(), which should
include kill_litter_super() if the call of simple_fill_super() had been asked
to create anything besides the root dentry. So there's no need to empty the
partially populated tree - it will be trimmed by inevitable kill_litter_super().

15/#) d_genocide(): move the extern into fs/internal.h
... now that the only user is in fs/super.c

16/#) get rid of DCACHE_GENOCIDE
... now that we never call d_genocide() other than from kill_litter_super()

17/#) d_alloc_parallel(): in-lookup hash insertion doesn't need an RCU variant
We only search in the damn thing under hlist_bl_lock(); RCU variant
of insertion was, IIRC, pretty much cargo-culted - mea culpa...

18/#) __d_unalias() doesn't use inode argument
... and hasn't since 2015.

At that point #work.dcache-misc merges with #work.dcache2 into #work.dcache,
with two followups:

19/#) kill DCACHE_MAY_FREE
Redundant with new ordering in __dentry_kill()

20/#) dcache: remove unnecessary NULL check in dget_dlock()
dget_dlock() requires dentry->d_lock to be held when called,
yet contains a NULL check for dentry. After taking out the NULL check,
dget_dlock() becomes almost identical to __dget_dlock(); the only
difference is that dget_dlock() returns the dentry that was passed
in. These are static inline helpers, so we can rely on the compiler to
discard unused return values. We can therefore also remove __dget_dlock()
and replace calls to it by dget_dlock().