[PATCH 2/8] fs/dcache: use rcu_ptr instead of rcu_head for external names

Harry Yoo (Oracle)
2026-04-16T09:10:38Z

When a file name length exceeds 31 (DCACHE_INLINE_LEN-1),
struct external_name is dynamically allocated. Because only kfree_rcu()
is used to free the objects, struct rcu_ptr is enough and saves a pointer
per object.

Under the author's home directory, there are 230k unique file names that
are longer than 31. Some memory saving benefit is expected.

Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Cc: Christian Brauner <brauner@kernel.org>
Cc: Jan Kara <jack@suse.cz>
Signed-off-by: Harry Yoo (Oracle) <harry@kernel.org>
---
fs/dcache.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/fs/dcache.c b/fs/dcache.c
index 7ba1801d8132..fa37e3964b38 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -325,12 +325,12 @@ static inline int dentry_cmp(const struct dentry *dentry, const unsigned char *c
/*
* long names are allocated separately from dentry and never modified.
* Refcounted, freeing is RCU-delayed. See take_dentry_name_snapshot()
- * for the reason why ->count and ->head can't be combined into a union.
+ * for the reason why ->count and ->rcu can't be combined into a union.
* dentry_string_cmp() relies upon ->name[] being word-aligned.
*/
struct external_name {
atomic_t count;
- struct rcu_head head;
+ struct rcu_ptr rcu;
unsigned char name[] __aligned(sizeof(unsigned long));
};

@@ -393,7 +393,7 @@ void release_dentry_name_snapshot(struct name_snapshot *name)
struct external_name *p;
p = container_of(name->name.name, struct external_name, name[0]);
if (unlikely(atomic_dec_and_test(&p->count)))
- kfree_rcu(p, head);
+ kfree_rcu(p, rcu);
}
}
EXPORT_SYMBOL(release_dentry_name_snapshot);
@@ -2863,7 +2863,7 @@ static void copy_name(struct dentry *dentry, struct dentry *target)
dentry->__d_name.hash_len = target->__d_name.hash_len;
}
if (old_name && likely(atomic_dec_and_test(&old_name->count)))
- kfree_rcu(old_name, head);
+ kfree_rcu(old_name, rcu);
}

/*
--
2.43.0