[RFC][PATCH 13/13] struct filename ->refcnt doesn't need to be atomic

Al Viro
2025-11-09T06:37:48Z

... or visible outside of audit, really. Note that references
held in delayed_filename always have refcount 1, and from the
moment of complete_getname() or equivalent point in getname...()
there is no references to struct filename instance anywhere
that would be visible to other threads.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/namei.c | 8 ++++----
include/linux/fs.h | 8 +-------
kernel/auditsc.c | 6 ++++++
3 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/fs/namei.c b/fs/namei.c
index bb306177b8a3..9863cc319181 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -128,7 +128,7 @@
static inline void initname(struct filename *name)
{
name->aname = NULL;
- atomic_set(&name->refcnt, 1);
+ name->refcnt = 1;
}

static struct filename *
@@ -283,13 +283,13 @@ void putname(struct filename *name)
if (IS_ERR_OR_NULL(name))
return;

- refcnt = atomic_read(&name->refcnt);
+ refcnt = name->refcnt;
if (unlikely(refcnt != 1)) {
if (WARN_ON_ONCE(!refcnt))
return;

- if (!atomic_dec_and_test(&name->refcnt))
- return;
+ name->refcnt--;
+ return;
}

if (unlikely(name->name != name->iname)) {
diff --git a/include/linux/fs.h b/include/linux/fs.h
index d57c8e21be13..4ea32aba847b 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2835,7 +2835,7 @@ extern struct kobject *fs_kobj;
struct audit_names;
struct filename {
const char *name; /* pointer to actual string */
- atomic_t refcnt;
+ int refcnt;
struct audit_names *aname;
const char iname[];
};
@@ -2944,12 +2944,6 @@ int delayed_getname_uflags(struct delayed_filename *v, const char __user *, int)
void dismiss_delayed_filename(struct delayed_filename *);
struct filename *complete_getname(struct delayed_filename *);

-static inline struct filename *refname(struct filename *name)
-{
- atomic_inc(&name->refcnt);
- return name;
-}
-
extern int finish_open(struct file *file, struct dentry *dentry,
int (*open)(struct inode *, struct file *));
extern int finish_no_open(struct file *file, struct dentry *dentry);
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index e59a094bb9f7..d71fc73455b2 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -2169,6 +2169,12 @@ static struct audit_names *audit_alloc_name(struct audit_context *context,
return aname;
}

+static inline struct filename *refname(struct filename *name)
+{
+ name->refcnt++;
+ return name;
+}
+
/**
* __audit_getname - add a name to the list
* @name: name to add
--
2.47.3