* [PATCH 02/21] new helper: d_splice_alias_ops()
2025-02-24 21:20 ` [PATCH 01/21] procfs: kill ->proc_dops Al Viro
@ 2025-02-24 21:20 ` Al Viro
2025-02-26 8:28 ` Christian Brauner
2025-02-24 21:20 ` [PATCH 03/21] switch procfs from d_set_d_op() to d_splice_alias_ops() Al Viro
` (21 subsequent siblings)
22 siblings, 1 reply; 87+ messages in thread
From: Al Viro @ 2025-02-24 21:20 UTC (permalink / raw)
To: linux-fsdevel
Cc: Linus Torvalds, Christian Brauner, Neil Brown, Miklos Szeredi,
Jan Kara
Uses of d_set_d_op() on live dentry can be very dangerous; it is going
to be withdrawn and replaced with saner things.
The best way for a filesystem is to have the default dentry_operations
set at mount time and be done with that - __d_alloc() will use that.
Currently there are two cases when d_set_d_op() is used on a live dentry -
one is procfs, which has several genuinely different dentry_operations
instances (different ->d_revalidate(), etc.) and another is
simple_lookup(), where we would be better off without overriding ->d_op.
For procfs we have d_set_d_op() calls followed by d_splice_alias();
provide a new helper (d_splice_alias_ops(inode, dentry, d_ops)) that would
combine those two, and do the d_set_d_op() part while under ->d_lock.
That eliminates one of the places where ->d_flags had been modified
without holding ->d_lock; current behaviour is not racy, but the reasons
for that are far too brittle. Better move to uniform locking rules and
simpler proof of correctness...
The next commit will convert procfs to use of that helper; it is not
exported and won't be until somebody comes up with convincing modular
user for it.
Again, the best approach is to have default ->d_op and let __d_alloc()
do the right thing; filesystem _may_ need non-uniform ->d_op (procfs
does), but there'd better be good reasons for that.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/dcache.c | 63 ++++++++++++++++++++++++------------------
include/linux/dcache.h | 3 ++
2 files changed, 39 insertions(+), 27 deletions(-)
diff --git a/fs/dcache.c b/fs/dcache.c
index e3634916ffb9..c85efbda133a 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -2641,7 +2641,8 @@ EXPORT_SYMBOL(__d_lookup_unhash_wake);
/* inode->i_lock held if inode is non-NULL */
-static inline void __d_add(struct dentry *dentry, struct inode *inode)
+static inline void __d_add(struct dentry *dentry, struct inode *inode,
+ const struct dentry_operations *ops)
{
wait_queue_head_t *d_wait;
struct inode *dir = NULL;
@@ -2652,6 +2653,8 @@ static inline void __d_add(struct dentry *dentry, struct inode *inode)
n = start_dir_add(dir);
d_wait = __d_lookup_unhash(dentry);
}
+ if (unlikely(ops))
+ d_set_d_op(dentry, ops);
if (inode) {
unsigned add_flags = d_flags_for_inode(inode);
hlist_add_head(&dentry->d_u.d_alias, &inode->i_dentry);
@@ -2683,7 +2686,7 @@ void d_add(struct dentry *entry, struct inode *inode)
security_d_instantiate(entry, inode);
spin_lock(&inode->i_lock);
}
- __d_add(entry, inode);
+ __d_add(entry, inode, NULL);
}
EXPORT_SYMBOL(d_add);
@@ -2981,30 +2984,8 @@ static int __d_unalias(struct dentry *dentry, struct dentry *alias)
return ret;
}
-/**
- * d_splice_alias - splice a disconnected dentry into the tree if one exists
- * @inode: the inode which may have a disconnected dentry
- * @dentry: a negative dentry which we want to point to the inode.
- *
- * If inode is a directory and has an IS_ROOT alias, then d_move that in
- * place of the given dentry and return it, else simply d_add the inode
- * to the dentry and return NULL.
- *
- * If a non-IS_ROOT directory is found, the filesystem is corrupt, and
- * we should error out: directories can't have multiple aliases.
- *
- * This is needed in the lookup routine of any filesystem that is exportable
- * (via knfsd) so that we can build dcache paths to directories effectively.
- *
- * If a dentry was found and moved, then it is returned. Otherwise NULL
- * is returned. This matches the expected return value of ->lookup.
- *
- * Cluster filesystems may call this function with a negative, hashed dentry.
- * In that case, we know that the inode will be a regular file, and also this
- * will only occur during atomic_open. So we need to check for the dentry
- * being already hashed only in the final case.
- */
-struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry)
+struct dentry *d_splice_alias_ops(struct inode *inode, struct dentry *dentry,
+ const struct dentry_operations *ops)
{
if (IS_ERR(inode))
return ERR_CAST(inode);
@@ -3050,9 +3031,37 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry)
}
}
out:
- __d_add(dentry, inode);
+ __d_add(dentry, inode, ops);
return NULL;
}
+
+/**
+ * d_splice_alias - splice a disconnected dentry into the tree if one exists
+ * @inode: the inode which may have a disconnected dentry
+ * @dentry: a negative dentry which we want to point to the inode.
+ *
+ * If inode is a directory and has an IS_ROOT alias, then d_move that in
+ * place of the given dentry and return it, else simply d_add the inode
+ * to the dentry and return NULL.
+ *
+ * If a non-IS_ROOT directory is found, the filesystem is corrupt, and
+ * we should error out: directories can't have multiple aliases.
+ *
+ * This is needed in the lookup routine of any filesystem that is exportable
+ * (via knfsd) so that we can build dcache paths to directories effectively.
+ *
+ * If a dentry was found and moved, then it is returned. Otherwise NULL
+ * is returned. This matches the expected return value of ->lookup.
+ *
+ * Cluster filesystems may call this function with a negative, hashed dentry.
+ * In that case, we know that the inode will be a regular file, and also this
+ * will only occur during atomic_open. So we need to check for the dentry
+ * being already hashed only in the final case.
+ */
+struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry)
+{
+ return d_splice_alias_ops(inode, dentry, NULL);
+}
EXPORT_SYMBOL(d_splice_alias);
/*
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index 4afb60365675..f47f3a47d97b 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -250,6 +250,9 @@ extern struct dentry * d_alloc_anon(struct super_block *);
extern struct dentry * d_alloc_parallel(struct dentry *, const struct qstr *,
wait_queue_head_t *);
extern struct dentry * d_splice_alias(struct inode *, struct dentry *);
+/* weird procfs mess; *NOT* exported */
+extern struct dentry * d_splice_alias_ops(struct inode *, struct dentry *,
+ const struct dentry_operations *);
extern struct dentry * d_add_ci(struct dentry *, struct inode *, struct qstr *);
extern bool d_same_name(const struct dentry *dentry, const struct dentry *parent,
const struct qstr *name);
--
2.39.5
^ permalink raw reply related [flat|nested] 87+ messages in thread* Re: [PATCH 02/21] new helper: d_splice_alias_ops()
2025-02-24 21:20 ` [PATCH 02/21] new helper: d_splice_alias_ops() Al Viro
@ 2025-02-26 8:28 ` Christian Brauner
0 siblings, 0 replies; 87+ messages in thread
From: Christian Brauner @ 2025-02-26 8:28 UTC (permalink / raw)
To: Al Viro; +Cc: linux-fsdevel, Linus Torvalds, Neil Brown, Miklos Szeredi,
Jan Kara
On Mon, Feb 24, 2025 at 09:20:32PM +0000, Al Viro wrote:
> Uses of d_set_d_op() on live dentry can be very dangerous; it is going
> to be withdrawn and replaced with saner things.
>
> The best way for a filesystem is to have the default dentry_operations
> set at mount time and be done with that - __d_alloc() will use that.
>
> Currently there are two cases when d_set_d_op() is used on a live dentry -
> one is procfs, which has several genuinely different dentry_operations
> instances (different ->d_revalidate(), etc.) and another is
> simple_lookup(), where we would be better off without overriding ->d_op.
>
> For procfs we have d_set_d_op() calls followed by d_splice_alias();
> provide a new helper (d_splice_alias_ops(inode, dentry, d_ops)) that would
> combine those two, and do the d_set_d_op() part while under ->d_lock.
> That eliminates one of the places where ->d_flags had been modified
> without holding ->d_lock; current behaviour is not racy, but the reasons
> for that are far too brittle. Better move to uniform locking rules and
> simpler proof of correctness...
>
> The next commit will convert procfs to use of that helper; it is not
> exported and won't be until somebody comes up with convincing modular
> user for it.
>
> Again, the best approach is to have default ->d_op and let __d_alloc()
> do the right thing; filesystem _may_ need non-uniform ->d_op (procfs
> does), but there'd better be good reasons for that.
>
> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
> ---
Reviewed-by: Christian Brauner <brauner@kernel.org>
> fs/dcache.c | 63 ++++++++++++++++++++++++------------------
> include/linux/dcache.h | 3 ++
> 2 files changed, 39 insertions(+), 27 deletions(-)
>
> diff --git a/fs/dcache.c b/fs/dcache.c
> index e3634916ffb9..c85efbda133a 100644
> --- a/fs/dcache.c
> +++ b/fs/dcache.c
> @@ -2641,7 +2641,8 @@ EXPORT_SYMBOL(__d_lookup_unhash_wake);
>
> /* inode->i_lock held if inode is non-NULL */
>
> -static inline void __d_add(struct dentry *dentry, struct inode *inode)
> +static inline void __d_add(struct dentry *dentry, struct inode *inode,
> + const struct dentry_operations *ops)
> {
> wait_queue_head_t *d_wait;
> struct inode *dir = NULL;
> @@ -2652,6 +2653,8 @@ static inline void __d_add(struct dentry *dentry, struct inode *inode)
> n = start_dir_add(dir);
> d_wait = __d_lookup_unhash(dentry);
> }
> + if (unlikely(ops))
> + d_set_d_op(dentry, ops);
> if (inode) {
> unsigned add_flags = d_flags_for_inode(inode);
> hlist_add_head(&dentry->d_u.d_alias, &inode->i_dentry);
> @@ -2683,7 +2686,7 @@ void d_add(struct dentry *entry, struct inode *inode)
> security_d_instantiate(entry, inode);
> spin_lock(&inode->i_lock);
> }
> - __d_add(entry, inode);
> + __d_add(entry, inode, NULL);
> }
> EXPORT_SYMBOL(d_add);
>
> @@ -2981,30 +2984,8 @@ static int __d_unalias(struct dentry *dentry, struct dentry *alias)
> return ret;
> }
>
> -/**
> - * d_splice_alias - splice a disconnected dentry into the tree if one exists
> - * @inode: the inode which may have a disconnected dentry
> - * @dentry: a negative dentry which we want to point to the inode.
> - *
> - * If inode is a directory and has an IS_ROOT alias, then d_move that in
> - * place of the given dentry and return it, else simply d_add the inode
> - * to the dentry and return NULL.
> - *
> - * If a non-IS_ROOT directory is found, the filesystem is corrupt, and
> - * we should error out: directories can't have multiple aliases.
> - *
> - * This is needed in the lookup routine of any filesystem that is exportable
> - * (via knfsd) so that we can build dcache paths to directories effectively.
> - *
> - * If a dentry was found and moved, then it is returned. Otherwise NULL
> - * is returned. This matches the expected return value of ->lookup.
> - *
> - * Cluster filesystems may call this function with a negative, hashed dentry.
> - * In that case, we know that the inode will be a regular file, and also this
> - * will only occur during atomic_open. So we need to check for the dentry
> - * being already hashed only in the final case.
> - */
> -struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry)
> +struct dentry *d_splice_alias_ops(struct inode *inode, struct dentry *dentry,
> + const struct dentry_operations *ops)
> {
> if (IS_ERR(inode))
> return ERR_CAST(inode);
> @@ -3050,9 +3031,37 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry)
> }
> }
> out:
> - __d_add(dentry, inode);
> + __d_add(dentry, inode, ops);
> return NULL;
> }
> +
> +/**
> + * d_splice_alias - splice a disconnected dentry into the tree if one exists
> + * @inode: the inode which may have a disconnected dentry
> + * @dentry: a negative dentry which we want to point to the inode.
> + *
> + * If inode is a directory and has an IS_ROOT alias, then d_move that in
> + * place of the given dentry and return it, else simply d_add the inode
> + * to the dentry and return NULL.
> + *
> + * If a non-IS_ROOT directory is found, the filesystem is corrupt, and
> + * we should error out: directories can't have multiple aliases.
> + *
> + * This is needed in the lookup routine of any filesystem that is exportable
> + * (via knfsd) so that we can build dcache paths to directories effectively.
> + *
> + * If a dentry was found and moved, then it is returned. Otherwise NULL
> + * is returned. This matches the expected return value of ->lookup.
> + *
> + * Cluster filesystems may call this function with a negative, hashed dentry.
> + * In that case, we know that the inode will be a regular file, and also this
> + * will only occur during atomic_open. So we need to check for the dentry
> + * being already hashed only in the final case.
> + */
> +struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry)
> +{
> + return d_splice_alias_ops(inode, dentry, NULL);
> +}
> EXPORT_SYMBOL(d_splice_alias);
>
> /*
> diff --git a/include/linux/dcache.h b/include/linux/dcache.h
> index 4afb60365675..f47f3a47d97b 100644
> --- a/include/linux/dcache.h
> +++ b/include/linux/dcache.h
> @@ -250,6 +250,9 @@ extern struct dentry * d_alloc_anon(struct super_block *);
> extern struct dentry * d_alloc_parallel(struct dentry *, const struct qstr *,
> wait_queue_head_t *);
> extern struct dentry * d_splice_alias(struct inode *, struct dentry *);
> +/* weird procfs mess; *NOT* exported */
> +extern struct dentry * d_splice_alias_ops(struct inode *, struct dentry *,
> + const struct dentry_operations *);
> extern struct dentry * d_add_ci(struct dentry *, struct inode *, struct qstr *);
> extern bool d_same_name(const struct dentry *dentry, const struct dentry *parent,
> const struct qstr *name);
> --
> 2.39.5
>
^ permalink raw reply [flat|nested] 87+ messages in thread
* [PATCH 03/21] switch procfs from d_set_d_op() to d_splice_alias_ops()
2025-02-24 21:20 ` [PATCH 01/21] procfs: kill ->proc_dops Al Viro
2025-02-24 21:20 ` [PATCH 02/21] new helper: d_splice_alias_ops() Al Viro
@ 2025-02-24 21:20 ` Al Viro
2025-02-26 8:29 ` Christian Brauner
2025-02-24 21:20 ` [PATCH 04/21] fuse: no need for special dentry_operations for root dentry Al Viro
` (20 subsequent siblings)
22 siblings, 1 reply; 87+ messages in thread
From: Al Viro @ 2025-02-24 21:20 UTC (permalink / raw)
To: linux-fsdevel
Cc: Linus Torvalds, Christian Brauner, Neil Brown, Miklos Szeredi,
Jan Kara
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/proc/base.c | 9 +++------
fs/proc/generic.c | 8 ++++----
fs/proc/internal.h | 3 +--
fs/proc/namespaces.c | 3 +--
fs/proc/proc_sysctl.c | 7 +++----
5 files changed, 12 insertions(+), 18 deletions(-)
diff --git a/fs/proc/base.c b/fs/proc/base.c
index cd89e956c322..397a9f6f463e 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -2709,8 +2709,7 @@ static struct dentry *proc_pident_instantiate(struct dentry *dentry,
inode->i_fop = p->fop;
ei->op = p->op;
pid_update_inode(task, inode);
- d_set_d_op(dentry, &pid_dentry_operations);
- return d_splice_alias(inode, dentry);
+ return d_splice_alias_ops(inode, dentry, &pid_dentry_operations);
}
static struct dentry *proc_pident_lookup(struct inode *dir,
@@ -3508,8 +3507,7 @@ static struct dentry *proc_pid_instantiate(struct dentry * dentry,
set_nlink(inode, nlink_tgid);
pid_update_inode(task, inode);
- d_set_d_op(dentry, &pid_dentry_operations);
- return d_splice_alias(inode, dentry);
+ return d_splice_alias_ops(inode, dentry, &pid_dentry_operations);
}
struct dentry *proc_pid_lookup(struct dentry *dentry, unsigned int flags)
@@ -3813,8 +3811,7 @@ static struct dentry *proc_task_instantiate(struct dentry *dentry,
set_nlink(inode, nlink_tid);
pid_update_inode(task, inode);
- d_set_d_op(dentry, &pid_dentry_operations);
- return d_splice_alias(inode, dentry);
+ return d_splice_alias_ops(inode, dentry, &pid_dentry_operations);
}
static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry, unsigned int flags)
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 499c2bf67488..774e18372914 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -255,10 +255,10 @@ struct dentry *proc_lookup_de(struct inode *dir, struct dentry *dentry,
if (!inode)
return ERR_PTR(-ENOMEM);
if (de->flags & PROC_ENTRY_FORCE_LOOKUP)
- d_set_d_op(dentry, &proc_net_dentry_ops);
- else
- d_set_d_op(dentry, &proc_misc_dentry_ops);
- return d_splice_alias(inode, dentry);
+ return d_splice_alias_ops(inode, dentry,
+ &proc_net_dentry_ops);
+ return d_splice_alias_ops(inode, dentry,
+ &proc_misc_dentry_ops);
}
read_unlock(&proc_subdir_lock);
return ERR_PTR(-ENOENT);
diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index 07f75c959173..48410381036b 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -358,7 +358,6 @@ static inline void pde_force_lookup(struct proc_dir_entry *pde)
static inline struct dentry *proc_splice_unmountable(struct inode *inode,
struct dentry *dentry, const struct dentry_operations *d_ops)
{
- d_set_d_op(dentry, d_ops);
dont_mount(dentry);
- return d_splice_alias(inode, dentry);
+ return d_splice_alias_ops(inode, dentry, d_ops);
}
diff --git a/fs/proc/namespaces.c b/fs/proc/namespaces.c
index c610224faf10..4403a2e20c16 100644
--- a/fs/proc/namespaces.c
+++ b/fs/proc/namespaces.c
@@ -111,8 +111,7 @@ static struct dentry *proc_ns_instantiate(struct dentry *dentry,
ei->ns_ops = ns_ops;
pid_update_inode(task, inode);
- d_set_d_op(dentry, &pid_dentry_operations);
- return d_splice_alias(inode, dentry);
+ return d_splice_alias_ops(inode, dentry, &pid_dentry_operations);
}
static int proc_ns_dir_readdir(struct file *file, struct dir_context *ctx)
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index cc9d74a06ff0..7a8bffc03dc8 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -540,9 +540,8 @@ static struct dentry *proc_sys_lookup(struct inode *dir, struct dentry *dentry,
goto out;
}
- d_set_d_op(dentry, &proc_sys_dentry_operations);
inode = proc_sys_make_inode(dir->i_sb, h ? h : head, p);
- err = d_splice_alias(inode, dentry);
+ err = d_splice_alias_ops(inode, dentry, &proc_sys_dentry_operations);
out:
if (h)
@@ -699,9 +698,9 @@ static bool proc_sys_fill_cache(struct file *file,
return false;
if (d_in_lookup(child)) {
struct dentry *res;
- d_set_d_op(child, &proc_sys_dentry_operations);
inode = proc_sys_make_inode(dir->d_sb, head, table);
- res = d_splice_alias(inode, child);
+ res = d_splice_alias_ops(inode, child,
+ &proc_sys_dentry_operations);
d_lookup_done(child);
if (unlikely(res)) {
dput(child);
--
2.39.5
^ permalink raw reply related [flat|nested] 87+ messages in thread* Re: [PATCH 03/21] switch procfs from d_set_d_op() to d_splice_alias_ops()
2025-02-24 21:20 ` [PATCH 03/21] switch procfs from d_set_d_op() to d_splice_alias_ops() Al Viro
@ 2025-02-26 8:29 ` Christian Brauner
0 siblings, 0 replies; 87+ messages in thread
From: Christian Brauner @ 2025-02-26 8:29 UTC (permalink / raw)
To: Al Viro; +Cc: linux-fsdevel, Linus Torvalds, Neil Brown, Miklos Szeredi,
Jan Kara
On Mon, Feb 24, 2025 at 09:20:33PM +0000, Al Viro wrote:
> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
> ---
Reviewed-by: Christian Brauner <brauner@kernel.org>
> fs/proc/base.c | 9 +++------
> fs/proc/generic.c | 8 ++++----
> fs/proc/internal.h | 3 +--
> fs/proc/namespaces.c | 3 +--
> fs/proc/proc_sysctl.c | 7 +++----
> 5 files changed, 12 insertions(+), 18 deletions(-)
>
> diff --git a/fs/proc/base.c b/fs/proc/base.c
> index cd89e956c322..397a9f6f463e 100644
> --- a/fs/proc/base.c
> +++ b/fs/proc/base.c
> @@ -2709,8 +2709,7 @@ static struct dentry *proc_pident_instantiate(struct dentry *dentry,
> inode->i_fop = p->fop;
> ei->op = p->op;
> pid_update_inode(task, inode);
> - d_set_d_op(dentry, &pid_dentry_operations);
> - return d_splice_alias(inode, dentry);
> + return d_splice_alias_ops(inode, dentry, &pid_dentry_operations);
> }
>
> static struct dentry *proc_pident_lookup(struct inode *dir,
> @@ -3508,8 +3507,7 @@ static struct dentry *proc_pid_instantiate(struct dentry * dentry,
> set_nlink(inode, nlink_tgid);
> pid_update_inode(task, inode);
>
> - d_set_d_op(dentry, &pid_dentry_operations);
> - return d_splice_alias(inode, dentry);
> + return d_splice_alias_ops(inode, dentry, &pid_dentry_operations);
> }
>
> struct dentry *proc_pid_lookup(struct dentry *dentry, unsigned int flags)
> @@ -3813,8 +3811,7 @@ static struct dentry *proc_task_instantiate(struct dentry *dentry,
> set_nlink(inode, nlink_tid);
> pid_update_inode(task, inode);
>
> - d_set_d_op(dentry, &pid_dentry_operations);
> - return d_splice_alias(inode, dentry);
> + return d_splice_alias_ops(inode, dentry, &pid_dentry_operations);
> }
>
> static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry, unsigned int flags)
> diff --git a/fs/proc/generic.c b/fs/proc/generic.c
> index 499c2bf67488..774e18372914 100644
> --- a/fs/proc/generic.c
> +++ b/fs/proc/generic.c
> @@ -255,10 +255,10 @@ struct dentry *proc_lookup_de(struct inode *dir, struct dentry *dentry,
> if (!inode)
> return ERR_PTR(-ENOMEM);
> if (de->flags & PROC_ENTRY_FORCE_LOOKUP)
> - d_set_d_op(dentry, &proc_net_dentry_ops);
> - else
> - d_set_d_op(dentry, &proc_misc_dentry_ops);
> - return d_splice_alias(inode, dentry);
> + return d_splice_alias_ops(inode, dentry,
> + &proc_net_dentry_ops);
> + return d_splice_alias_ops(inode, dentry,
> + &proc_misc_dentry_ops);
> }
> read_unlock(&proc_subdir_lock);
> return ERR_PTR(-ENOENT);
> diff --git a/fs/proc/internal.h b/fs/proc/internal.h
> index 07f75c959173..48410381036b 100644
> --- a/fs/proc/internal.h
> +++ b/fs/proc/internal.h
> @@ -358,7 +358,6 @@ static inline void pde_force_lookup(struct proc_dir_entry *pde)
> static inline struct dentry *proc_splice_unmountable(struct inode *inode,
> struct dentry *dentry, const struct dentry_operations *d_ops)
> {
> - d_set_d_op(dentry, d_ops);
> dont_mount(dentry);
> - return d_splice_alias(inode, dentry);
> + return d_splice_alias_ops(inode, dentry, d_ops);
> }
> diff --git a/fs/proc/namespaces.c b/fs/proc/namespaces.c
> index c610224faf10..4403a2e20c16 100644
> --- a/fs/proc/namespaces.c
> +++ b/fs/proc/namespaces.c
> @@ -111,8 +111,7 @@ static struct dentry *proc_ns_instantiate(struct dentry *dentry,
> ei->ns_ops = ns_ops;
> pid_update_inode(task, inode);
>
> - d_set_d_op(dentry, &pid_dentry_operations);
> - return d_splice_alias(inode, dentry);
> + return d_splice_alias_ops(inode, dentry, &pid_dentry_operations);
> }
>
> static int proc_ns_dir_readdir(struct file *file, struct dir_context *ctx)
> diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
> index cc9d74a06ff0..7a8bffc03dc8 100644
> --- a/fs/proc/proc_sysctl.c
> +++ b/fs/proc/proc_sysctl.c
> @@ -540,9 +540,8 @@ static struct dentry *proc_sys_lookup(struct inode *dir, struct dentry *dentry,
> goto out;
> }
>
> - d_set_d_op(dentry, &proc_sys_dentry_operations);
> inode = proc_sys_make_inode(dir->i_sb, h ? h : head, p);
> - err = d_splice_alias(inode, dentry);
> + err = d_splice_alias_ops(inode, dentry, &proc_sys_dentry_operations);
>
> out:
> if (h)
> @@ -699,9 +698,9 @@ static bool proc_sys_fill_cache(struct file *file,
> return false;
> if (d_in_lookup(child)) {
> struct dentry *res;
> - d_set_d_op(child, &proc_sys_dentry_operations);
> inode = proc_sys_make_inode(dir->d_sb, head, table);
> - res = d_splice_alias(inode, child);
> + res = d_splice_alias_ops(inode, child,
> + &proc_sys_dentry_operations);
> d_lookup_done(child);
> if (unlikely(res)) {
> dput(child);
> --
> 2.39.5
>
^ permalink raw reply [flat|nested] 87+ messages in thread
* [PATCH 04/21] fuse: no need for special dentry_operations for root dentry
2025-02-24 21:20 ` [PATCH 01/21] procfs: kill ->proc_dops Al Viro
2025-02-24 21:20 ` [PATCH 02/21] new helper: d_splice_alias_ops() Al Viro
2025-02-24 21:20 ` [PATCH 03/21] switch procfs from d_set_d_op() to d_splice_alias_ops() Al Viro
@ 2025-02-24 21:20 ` Al Viro
2025-02-26 8:29 ` Christian Brauner
2025-02-27 14:33 ` Miklos Szeredi
2025-02-24 21:20 ` [PATCH 05/21] new helper: set_default_d_op() Al Viro
` (19 subsequent siblings)
22 siblings, 2 replies; 87+ messages in thread
From: Al Viro @ 2025-02-24 21:20 UTC (permalink / raw)
To: linux-fsdevel
Cc: Linus Torvalds, Christian Brauner, Neil Brown, Miklos Szeredi,
Jan Kara
->d_revalidate() is never called for root anyway...
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/fuse/dir.c | 7 -------
fs/fuse/fuse_i.h | 1 -
fs/fuse/inode.c | 4 +---
3 files changed, 1 insertion(+), 11 deletions(-)
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 198862b086ff..24979d5413fa 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -336,13 +336,6 @@ const struct dentry_operations fuse_dentry_operations = {
.d_automount = fuse_dentry_automount,
};
-const struct dentry_operations fuse_root_dentry_operations = {
-#if BITS_PER_LONG < 64
- .d_init = fuse_dentry_init,
- .d_release = fuse_dentry_release,
-#endif
-};
-
int fuse_valid_type(int m)
{
return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) ||
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index fee96fe7887b..71a2b3900854 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -1069,7 +1069,6 @@ static inline void fuse_sync_bucket_dec(struct fuse_sync_bucket *bucket)
extern const struct file_operations fuse_dev_operations;
extern const struct dentry_operations fuse_dentry_operations;
-extern const struct dentry_operations fuse_root_dentry_operations;
/**
* Get a filled in inode
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index e9db2cb8c150..57a1ee016b73 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -1800,12 +1800,10 @@ int fuse_fill_super_common(struct super_block *sb, struct fuse_fs_context *ctx)
err = -ENOMEM;
root = fuse_get_root_inode(sb, ctx->rootmode);
- sb->s_d_op = &fuse_root_dentry_operations;
+ sb->s_d_op = &fuse_dentry_operations;
root_dentry = d_make_root(root);
if (!root_dentry)
goto err_dev_free;
- /* Root dentry doesn't have .d_revalidate */
- sb->s_d_op = &fuse_dentry_operations;
mutex_lock(&fuse_mutex);
err = -EINVAL;
--
2.39.5
^ permalink raw reply related [flat|nested] 87+ messages in thread* Re: [PATCH 04/21] fuse: no need for special dentry_operations for root dentry
2025-02-24 21:20 ` [PATCH 04/21] fuse: no need for special dentry_operations for root dentry Al Viro
@ 2025-02-26 8:29 ` Christian Brauner
2025-02-27 14:33 ` Miklos Szeredi
1 sibling, 0 replies; 87+ messages in thread
From: Christian Brauner @ 2025-02-26 8:29 UTC (permalink / raw)
To: Al Viro; +Cc: linux-fsdevel, Linus Torvalds, Neil Brown, Miklos Szeredi,
Jan Kara
On Mon, Feb 24, 2025 at 09:20:34PM +0000, Al Viro wrote:
> ->d_revalidate() is never called for root anyway...
>
> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
> ---
Reviewed-by: Christian Brauner <brauner@kernel.org>
> fs/fuse/dir.c | 7 -------
> fs/fuse/fuse_i.h | 1 -
> fs/fuse/inode.c | 4 +---
> 3 files changed, 1 insertion(+), 11 deletions(-)
>
> diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
> index 198862b086ff..24979d5413fa 100644
> --- a/fs/fuse/dir.c
> +++ b/fs/fuse/dir.c
> @@ -336,13 +336,6 @@ const struct dentry_operations fuse_dentry_operations = {
> .d_automount = fuse_dentry_automount,
> };
>
> -const struct dentry_operations fuse_root_dentry_operations = {
> -#if BITS_PER_LONG < 64
> - .d_init = fuse_dentry_init,
> - .d_release = fuse_dentry_release,
> -#endif
> -};
> -
> int fuse_valid_type(int m)
> {
> return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) ||
> diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
> index fee96fe7887b..71a2b3900854 100644
> --- a/fs/fuse/fuse_i.h
> +++ b/fs/fuse/fuse_i.h
> @@ -1069,7 +1069,6 @@ static inline void fuse_sync_bucket_dec(struct fuse_sync_bucket *bucket)
> extern const struct file_operations fuse_dev_operations;
>
> extern const struct dentry_operations fuse_dentry_operations;
> -extern const struct dentry_operations fuse_root_dentry_operations;
>
> /**
> * Get a filled in inode
> diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
> index e9db2cb8c150..57a1ee016b73 100644
> --- a/fs/fuse/inode.c
> +++ b/fs/fuse/inode.c
> @@ -1800,12 +1800,10 @@ int fuse_fill_super_common(struct super_block *sb, struct fuse_fs_context *ctx)
>
> err = -ENOMEM;
> root = fuse_get_root_inode(sb, ctx->rootmode);
> - sb->s_d_op = &fuse_root_dentry_operations;
> + sb->s_d_op = &fuse_dentry_operations;
> root_dentry = d_make_root(root);
> if (!root_dentry)
> goto err_dev_free;
> - /* Root dentry doesn't have .d_revalidate */
> - sb->s_d_op = &fuse_dentry_operations;
>
> mutex_lock(&fuse_mutex);
> err = -EINVAL;
> --
> 2.39.5
>
^ permalink raw reply [flat|nested] 87+ messages in thread* Re: [PATCH 04/21] fuse: no need for special dentry_operations for root dentry
2025-02-24 21:20 ` [PATCH 04/21] fuse: no need for special dentry_operations for root dentry Al Viro
2025-02-26 8:29 ` Christian Brauner
@ 2025-02-27 14:33 ` Miklos Szeredi
1 sibling, 0 replies; 87+ messages in thread
From: Miklos Szeredi @ 2025-02-27 14:33 UTC (permalink / raw)
To: Al Viro
Cc: linux-fsdevel, Linus Torvalds, Christian Brauner, Neil Brown,
Jan Kara
On Mon, 24 Feb 2025 at 22:20, Al Viro <viro@zeniv.linux.org.uk> wrote:
>
> ->d_revalidate() is never called for root anyway...
>
> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Acked-by: Miklos Szeredi <mszeredi@redhat.com>
^ permalink raw reply [flat|nested] 87+ messages in thread
* [PATCH 05/21] new helper: set_default_d_op()
2025-02-24 21:20 ` [PATCH 01/21] procfs: kill ->proc_dops Al Viro
` (2 preceding siblings ...)
2025-02-24 21:20 ` [PATCH 04/21] fuse: no need for special dentry_operations for root dentry Al Viro
@ 2025-02-24 21:20 ` Al Viro
2025-02-26 8:30 ` Christian Brauner
2025-02-24 21:20 ` [PATCH 06/21] split d_flags calculation out of d_set_d_op() Al Viro
` (18 subsequent siblings)
22 siblings, 1 reply; 87+ messages in thread
From: Al Viro @ 2025-02-24 21:20 UTC (permalink / raw)
To: linux-fsdevel
Cc: Linus Torvalds, Christian Brauner, Neil Brown, Miklos Szeredi,
Jan Kara
... to be used instead of manually assigning to ->s_d_op.
All in-tree filesystem converted (and field itself is renamed,
so any out-of-tree ones in need of conversion will be caught
by compiler).
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
Documentation/filesystems/porting.rst | 7 +++++++
fs/9p/vfs_super.c | 4 ++--
fs/adfs/super.c | 2 +-
fs/affs/super.c | 4 ++--
fs/afs/super.c | 4 ++--
fs/autofs/inode.c | 2 +-
fs/btrfs/super.c | 2 +-
fs/ceph/super.c | 2 +-
fs/coda/inode.c | 2 +-
fs/configfs/mount.c | 2 +-
fs/dcache.c | 10 ++++++++--
fs/debugfs/inode.c | 2 +-
fs/devpts/inode.c | 2 +-
fs/ecryptfs/main.c | 2 +-
fs/efivarfs/super.c | 2 +-
fs/exfat/super.c | 4 ++--
fs/fat/namei_msdos.c | 2 +-
fs/fat/namei_vfat.c | 4 ++--
fs/fuse/inode.c | 4 ++--
fs/gfs2/ops_fstype.c | 2 +-
fs/hfs/super.c | 2 +-
fs/hfsplus/super.c | 2 +-
fs/hostfs/hostfs_kern.c | 2 +-
fs/hpfs/super.c | 2 +-
fs/isofs/inode.c | 2 +-
fs/jfs/super.c | 2 +-
fs/kernfs/mount.c | 2 +-
fs/libfs.c | 16 ++++++++--------
fs/nfs/super.c | 2 +-
fs/ntfs3/super.c | 3 ++-
fs/ocfs2/super.c | 2 +-
fs/orangefs/super.c | 2 +-
fs/overlayfs/super.c | 2 +-
fs/smb/client/cifsfs.c | 4 ++--
fs/tracefs/inode.c | 2 +-
fs/vboxsf/super.c | 2 +-
include/linux/dcache.h | 2 ++
include/linux/fs.h | 2 +-
mm/shmem.c | 2 +-
net/sunrpc/rpc_pipe.c | 2 +-
40 files changed, 69 insertions(+), 53 deletions(-)
diff --git a/Documentation/filesystems/porting.rst b/Documentation/filesystems/porting.rst
index 1639e78e3146..004cd69617a2 100644
--- a/Documentation/filesystems/porting.rst
+++ b/Documentation/filesystems/porting.rst
@@ -1157,3 +1157,10 @@ in normal case it points into the pathname being looked up.
NOTE: if you need something like full path from the root of filesystem,
you are still on your own - this assists with simple cases, but it's not
magic.
+
+---
+
+**mandatory**
+
+If your filesystem sets the default dentry_operations, use set_default_d_op()
+rather than manually setting sb->s_d_op.
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
index 489db161abc9..5c3dc3efb909 100644
--- a/fs/9p/vfs_super.c
+++ b/fs/9p/vfs_super.c
@@ -135,9 +135,9 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags,
goto release_sb;
if (v9ses->cache & (CACHE_META|CACHE_LOOSE))
- sb->s_d_op = &v9fs_cached_dentry_operations;
+ set_default_d_op(sb, &v9fs_cached_dentry_operations);
else
- sb->s_d_op = &v9fs_dentry_operations;
+ set_default_d_op(sb, &v9fs_dentry_operations);
inode = v9fs_get_new_inode_from_fid(v9ses, fid, sb);
if (IS_ERR(inode)) {
diff --git a/fs/adfs/super.c b/fs/adfs/super.c
index 017c48a80203..fdccdbbfc213 100644
--- a/fs/adfs/super.c
+++ b/fs/adfs/super.c
@@ -397,7 +397,7 @@ static int adfs_fill_super(struct super_block *sb, struct fs_context *fc)
if (asb->s_ftsuffix)
asb->s_namelen += 4;
- sb->s_d_op = &adfs_dentry_operations;
+ set_default_d_op(sb, &adfs_dentry_operations);
root = adfs_iget(sb, &root_obj);
sb->s_root = d_make_root(root);
if (!sb->s_root) {
diff --git a/fs/affs/super.c b/fs/affs/super.c
index 2fa40337776d..44f8aa883100 100644
--- a/fs/affs/super.c
+++ b/fs/affs/super.c
@@ -500,9 +500,9 @@ static int affs_fill_super(struct super_block *sb, struct fs_context *fc)
return PTR_ERR(root_inode);
if (affs_test_opt(AFFS_SB(sb)->s_flags, SF_INTL))
- sb->s_d_op = &affs_intl_dentry_operations;
+ set_default_d_op(sb, &affs_intl_dentry_operations);
else
- sb->s_d_op = &affs_dentry_operations;
+ set_default_d_op(sb, &affs_dentry_operations);
sb->s_root = d_make_root(root_inode);
if (!sb->s_root) {
diff --git a/fs/afs/super.c b/fs/afs/super.c
index a9bee610674e..13d0414a1ddb 100644
--- a/fs/afs/super.c
+++ b/fs/afs/super.c
@@ -487,12 +487,12 @@ static int afs_fill_super(struct super_block *sb, struct afs_fs_context *ctx)
goto error;
if (as->dyn_root) {
- sb->s_d_op = &afs_dynroot_dentry_operations;
+ set_default_d_op(sb, &afs_dynroot_dentry_operations);
ret = afs_dynroot_populate(sb);
if (ret < 0)
goto error;
} else {
- sb->s_d_op = &afs_fs_dentry_operations;
+ set_default_d_op(sb, &afs_fs_dentry_operations);
rcu_assign_pointer(as->volume->sb, sb);
}
diff --git a/fs/autofs/inode.c b/fs/autofs/inode.c
index ee2edccaef70..f5c16ffba013 100644
--- a/fs/autofs/inode.c
+++ b/fs/autofs/inode.c
@@ -311,7 +311,7 @@ static int autofs_fill_super(struct super_block *s, struct fs_context *fc)
s->s_blocksize_bits = 10;
s->s_magic = AUTOFS_SUPER_MAGIC;
s->s_op = &autofs_sops;
- s->s_d_op = &autofs_dentry_operations;
+ set_default_d_op(s, &autofs_dentry_operations);
s->s_time_gran = 1;
/*
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index dc4fee519ca6..5f39857ea3ae 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -954,7 +954,7 @@ static int btrfs_fill_super(struct super_block *sb,
sb->s_maxbytes = MAX_LFS_FILESIZE;
sb->s_magic = BTRFS_SUPER_MAGIC;
sb->s_op = &btrfs_super_ops;
- sb->s_d_op = &btrfs_dentry_operations;
+ set_default_d_op(sb, &btrfs_dentry_operations);
sb->s_export_op = &btrfs_export_ops;
#ifdef CONFIG_FS_VERITY
sb->s_vop = &btrfs_verityops;
diff --git a/fs/ceph/super.c b/fs/ceph/super.c
index 4344e1f11806..adec6e2f01c4 100644
--- a/fs/ceph/super.c
+++ b/fs/ceph/super.c
@@ -1220,7 +1220,7 @@ static int ceph_set_super(struct super_block *s, struct fs_context *fc)
fsc->max_file_size = 1ULL << 40; /* temp value until we get mdsmap */
s->s_op = &ceph_super_ops;
- s->s_d_op = &ceph_dentry_ops;
+ set_default_d_op(s, &ceph_dentry_ops);
s->s_export_op = &ceph_export_ops;
s->s_time_gran = 1;
diff --git a/fs/coda/inode.c b/fs/coda/inode.c
index 6896fce122e1..08450d006016 100644
--- a/fs/coda/inode.c
+++ b/fs/coda/inode.c
@@ -230,7 +230,7 @@ static int coda_fill_super(struct super_block *sb, struct fs_context *fc)
sb->s_blocksize_bits = 12;
sb->s_magic = CODA_SUPER_MAGIC;
sb->s_op = &coda_super_operations;
- sb->s_d_op = &coda_dentry_operations;
+ set_default_d_op(sb, &coda_dentry_operations);
sb->s_time_gran = 1;
sb->s_time_min = S64_MIN;
sb->s_time_max = S64_MAX;
diff --git a/fs/configfs/mount.c b/fs/configfs/mount.c
index c2d820063ec4..20412eaca972 100644
--- a/fs/configfs/mount.c
+++ b/fs/configfs/mount.c
@@ -92,7 +92,7 @@ static int configfs_fill_super(struct super_block *sb, struct fs_context *fc)
configfs_root_group.cg_item.ci_dentry = root;
root->d_fsdata = &configfs_root;
sb->s_root = root;
- sb->s_d_op = &configfs_dentry_ops; /* the rest get that */
+ set_default_d_op(sb, &configfs_dentry_ops); /* the rest get that */
return 0;
}
diff --git a/fs/dcache.c b/fs/dcache.c
index c85efbda133a..cd5e5139ca4c 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1712,7 +1712,7 @@ static struct dentry *__d_alloc(struct super_block *sb, const struct qstr *name)
INIT_HLIST_HEAD(&dentry->d_children);
INIT_HLIST_NODE(&dentry->d_u.d_alias);
INIT_HLIST_NODE(&dentry->d_sib);
- d_set_d_op(dentry, dentry->d_sb->s_d_op);
+ d_set_d_op(dentry, dentry->d_sb->__s_d_op);
if (dentry->d_op && dentry->d_op->d_init) {
err = dentry->d_op->d_init(dentry);
@@ -1795,7 +1795,7 @@ struct dentry *d_alloc_pseudo(struct super_block *sb, const struct qstr *name)
struct dentry *dentry = __d_alloc(sb, name);
if (likely(dentry)) {
dentry->d_flags |= DCACHE_NORCU;
- if (!sb->s_d_op)
+ if (!dentry->d_op)
d_set_d_op(dentry, &anon_ops);
}
return dentry;
@@ -1841,6 +1841,12 @@ void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op)
}
EXPORT_SYMBOL(d_set_d_op);
+void set_default_d_op(struct super_block *s, const struct dentry_operations *ops)
+{
+ s->__s_d_op = ops;
+}
+EXPORT_SYMBOL(set_default_d_op);
+
static unsigned d_flags_for_inode(struct inode *inode)
{
unsigned add_flags = DCACHE_REGULAR_TYPE;
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index 75715d8877ee..f54a8fd960e4 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -273,7 +273,7 @@ static int debugfs_fill_super(struct super_block *sb, struct fs_context *fc)
return err;
sb->s_op = &debugfs_super_operations;
- sb->s_d_op = &debugfs_dops;
+ set_default_d_op(sb, &debugfs_dops);
debugfs_apply_options(sb);
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
index 1096ff8562fa..f092973236ef 100644
--- a/fs/devpts/inode.c
+++ b/fs/devpts/inode.c
@@ -433,7 +433,7 @@ devpts_fill_super(struct super_block *s, void *data, int silent)
s->s_blocksize_bits = 10;
s->s_magic = DEVPTS_SUPER_MAGIC;
s->s_op = &devpts_sops;
- s->s_d_op = &simple_dentry_operations;
+ set_default_d_op(s, &simple_dentry_operations);
s->s_time_gran = 1;
error = -ENOMEM;
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index 8dd1d7189c3b..45f9ca4465da 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -471,7 +471,7 @@ static int ecryptfs_get_tree(struct fs_context *fc)
sbi = NULL;
s->s_op = &ecryptfs_sops;
s->s_xattr = ecryptfs_xattr_handlers;
- s->s_d_op = &ecryptfs_dops;
+ set_default_d_op(s, &ecryptfs_dops);
err = "Reading sb failed";
rc = kern_path(fc->source, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path);
diff --git a/fs/efivarfs/super.c b/fs/efivarfs/super.c
index 09fcf731e65d..3f3188e0cfa7 100644
--- a/fs/efivarfs/super.c
+++ b/fs/efivarfs/super.c
@@ -345,7 +345,7 @@ static int efivarfs_fill_super(struct super_block *sb, struct fs_context *fc)
sb->s_blocksize_bits = PAGE_SHIFT;
sb->s_magic = EFIVARFS_MAGIC;
sb->s_op = &efivarfs_ops;
- sb->s_d_op = &efivarfs_d_ops;
+ set_default_d_op(sb, &efivarfs_d_ops);
sb->s_time_gran = 1;
if (!efivar_supports_writes())
diff --git a/fs/exfat/super.c b/fs/exfat/super.c
index bd57844414aa..c821582fa1ef 100644
--- a/fs/exfat/super.c
+++ b/fs/exfat/super.c
@@ -697,9 +697,9 @@ static int exfat_fill_super(struct super_block *sb, struct fs_context *fc)
}
if (sbi->options.utf8)
- sb->s_d_op = &exfat_utf8_dentry_ops;
+ set_default_d_op(sb, &exfat_utf8_dentry_ops);
else
- sb->s_d_op = &exfat_dentry_ops;
+ set_default_d_op(sb, &exfat_dentry_ops);
root_inode = new_inode(sb);
if (!root_inode) {
diff --git a/fs/fat/namei_msdos.c b/fs/fat/namei_msdos.c
index f06f6ba643cc..71302291d33c 100644
--- a/fs/fat/namei_msdos.c
+++ b/fs/fat/namei_msdos.c
@@ -646,7 +646,7 @@ static const struct inode_operations msdos_dir_inode_operations = {
static void setup(struct super_block *sb)
{
MSDOS_SB(sb)->dir_ops = &msdos_dir_inode_operations;
- sb->s_d_op = &msdos_dentry_operations;
+ set_default_d_op(sb, &msdos_dentry_operations);
sb->s_flags |= SB_NOATIME;
}
diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c
index 926c26e90ef8..2476afd1304d 100644
--- a/fs/fat/namei_vfat.c
+++ b/fs/fat/namei_vfat.c
@@ -1187,9 +1187,9 @@ static void setup(struct super_block *sb)
{
MSDOS_SB(sb)->dir_ops = &vfat_dir_inode_operations;
if (MSDOS_SB(sb)->options.name_check != 's')
- sb->s_d_op = &vfat_ci_dentry_ops;
+ set_default_d_op(sb, &vfat_ci_dentry_ops);
else
- sb->s_d_op = &vfat_dentry_ops;
+ set_default_d_op(sb, &vfat_dentry_ops);
}
static int vfat_fill_super(struct super_block *sb, struct fs_context *fc)
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 57a1ee016b73..9994f3b33a9f 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -1665,7 +1665,7 @@ static int fuse_fill_super_submount(struct super_block *sb,
fi = get_fuse_inode(root);
fi->nlookup--;
- sb->s_d_op = &fuse_dentry_operations;
+ set_default_d_op(sb, &fuse_dentry_operations);
sb->s_root = d_make_root(root);
if (!sb->s_root)
return -ENOMEM;
@@ -1800,7 +1800,7 @@ int fuse_fill_super_common(struct super_block *sb, struct fuse_fs_context *ctx)
err = -ENOMEM;
root = fuse_get_root_inode(sb, ctx->rootmode);
- sb->s_d_op = &fuse_dentry_operations;
+ set_default_d_op(sb, &fuse_dentry_operations);
root_dentry = d_make_root(root);
if (!root_dentry)
goto err_dev_free;
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
index e83d293c3614..949bbdb5b564 100644
--- a/fs/gfs2/ops_fstype.c
+++ b/fs/gfs2/ops_fstype.c
@@ -1156,7 +1156,7 @@ static int gfs2_fill_super(struct super_block *sb, struct fs_context *fc)
sb->s_flags |= SB_NOSEC;
sb->s_magic = GFS2_MAGIC;
sb->s_op = &gfs2_super_ops;
- sb->s_d_op = &gfs2_dops;
+ set_default_d_op(sb, &gfs2_dops);
sb->s_export_op = &gfs2_export_ops;
sb->s_qcop = &gfs2_quotactl_ops;
sb->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP;
diff --git a/fs/hfs/super.c b/fs/hfs/super.c
index fe09c2093a93..388a318297ec 100644
--- a/fs/hfs/super.c
+++ b/fs/hfs/super.c
@@ -365,7 +365,7 @@ static int hfs_fill_super(struct super_block *sb, struct fs_context *fc)
if (!root_inode)
goto bail_no_root;
- sb->s_d_op = &hfs_dentry_operations;
+ set_default_d_op(sb, &hfs_dentry_operations);
res = -ENOMEM;
sb->s_root = d_make_root(root_inode);
if (!sb->s_root)
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
index 948b8aaee33e..0caf7aa1c249 100644
--- a/fs/hfsplus/super.c
+++ b/fs/hfsplus/super.c
@@ -508,7 +508,7 @@ static int hfsplus_fill_super(struct super_block *sb, struct fs_context *fc)
goto out_put_alloc_file;
}
- sb->s_d_op = &hfsplus_dentry_operations;
+ set_default_d_op(sb, &hfsplus_dentry_operations);
sb->s_root = d_make_root(root);
if (!sb->s_root) {
err = -ENOMEM;
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index e0741e468956..a0e0563a29d7 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -920,7 +920,7 @@ static int hostfs_fill_super(struct super_block *sb, struct fs_context *fc)
sb->s_blocksize_bits = 10;
sb->s_magic = HOSTFS_SUPER_MAGIC;
sb->s_op = &hostfs_sbops;
- sb->s_d_op = &simple_dentry_operations;
+ set_default_d_op(sb, &simple_dentry_operations);
sb->s_maxbytes = MAX_LFS_FILESIZE;
err = super_setup_bdi(sb);
if (err)
diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c
index 27567920abe4..42b779b4d87f 100644
--- a/fs/hpfs/super.c
+++ b/fs/hpfs/super.c
@@ -554,7 +554,7 @@ static int hpfs_fill_super(struct super_block *s, struct fs_context *fc)
/* Fill superblock stuff */
s->s_magic = HPFS_SUPER_MAGIC;
s->s_op = &hpfs_sops;
- s->s_d_op = &hpfs_dentry_operations;
+ set_default_d_op(s, &hpfs_dentry_operations);
s->s_time_min = local_to_gmt(s, 0);
s->s_time_max = local_to_gmt(s, U32_MAX);
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index 47038e660812..05ddc2544ade 100644
--- a/fs/isofs/inode.c
+++ b/fs/isofs/inode.c
@@ -939,7 +939,7 @@ static int isofs_fill_super(struct super_block *s, struct fs_context *fc)
sbi->s_check = opt->check;
if (table)
- s->s_d_op = &isofs_dentry_ops[table - 1];
+ set_default_d_op(s, &isofs_dentry_ops[table - 1]);
/* get the root dentry */
s->s_root = d_make_root(inode);
diff --git a/fs/jfs/super.c b/fs/jfs/super.c
index 223d9ac59839..10c3cb714423 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -542,7 +542,7 @@ static int jfs_fill_super(struct super_block *sb, struct fs_context *fc)
sb->s_magic = JFS_SUPER_MAGIC;
if (sbi->mntflag & JFS_OS2)
- sb->s_d_op = &jfs_ci_dentry_operations;
+ set_default_d_op(sb, &jfs_ci_dentry_operations);
inode = jfs_iget(sb, ROOT_I);
if (IS_ERR(inode)) {
diff --git a/fs/kernfs/mount.c b/fs/kernfs/mount.c
index 1358c21837f1..91e788d15073 100644
--- a/fs/kernfs/mount.c
+++ b/fs/kernfs/mount.c
@@ -281,7 +281,7 @@ static int kernfs_fill_super(struct super_block *sb, struct kernfs_fs_context *k
return -ENOMEM;
}
sb->s_root = root;
- sb->s_d_op = &kernfs_dops;
+ set_default_d_op(sb, &kernfs_dops);
return 0;
}
diff --git a/fs/libfs.c b/fs/libfs.c
index 8444f5cc4064..929bef0fecbd 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -75,7 +75,7 @@ struct dentry *simple_lookup(struct inode *dir, struct dentry *dentry, unsigned
{
if (dentry->d_name.len > NAME_MAX)
return ERR_PTR(-ENAMETOOLONG);
- if (!dentry->d_sb->s_d_op)
+ if (!dentry->d_op)
d_set_d_op(dentry, &simple_dentry_operations);
if (IS_ENABLED(CONFIG_UNICODE) && IS_CASEFOLDED(dir))
@@ -683,7 +683,7 @@ static int pseudo_fs_fill_super(struct super_block *s, struct fs_context *fc)
s->s_root = d_make_root(root);
if (!s->s_root)
return -ENOMEM;
- s->s_d_op = ctx->dops;
+ set_default_d_op(s, ctx->dops);
return 0;
}
@@ -1943,22 +1943,22 @@ static const struct dentry_operations generic_encrypted_dentry_ops = {
* @sb: superblock to be configured
*
* Filesystems supporting casefolding and/or fscrypt can call this
- * helper at mount-time to configure sb->s_d_op to best set of dentry
- * operations required for the enabled features. The helper must be
- * called after these have been configured, but before the root dentry
- * is created.
+ * helper at mount-time to configure default dentry_operations to the
+ * best set of dentry operations required for the enabled features.
+ * The helper must be called after these have been configured, but
+ * before the root dentry is created.
*/
void generic_set_sb_d_ops(struct super_block *sb)
{
#if IS_ENABLED(CONFIG_UNICODE)
if (sb->s_encoding) {
- sb->s_d_op = &generic_ci_dentry_ops;
+ set_default_d_op(sb, &generic_ci_dentry_ops);
return;
}
#endif
#ifdef CONFIG_FS_ENCRYPTION
if (sb->s_cop) {
- sb->s_d_op = &generic_encrypted_dentry_ops;
+ set_default_d_op(sb, &generic_encrypted_dentry_ops);
return;
}
#endif
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index aeb715b4a690..38b0ecf02ad6 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -1169,7 +1169,7 @@ static int nfs_set_super(struct super_block *s, struct fs_context *fc)
struct nfs_server *server = fc->s_fs_info;
int ret;
- s->s_d_op = server->nfs_client->rpc_ops->dentry_ops;
+ set_default_d_op(s, server->nfs_client->rpc_ops->dentry_ops);
ret = set_anon_super(s, server);
if (ret == 0)
server->s_dev = s->s_dev;
diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c
index 6a0f6b0a3ab2..90f5361ae13f 100644
--- a/fs/ntfs3/super.c
+++ b/fs/ntfs3/super.c
@@ -1182,7 +1182,8 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc)
sb->s_export_op = &ntfs_export_ops;
sb->s_time_gran = NTFS_TIME_GRAN; // 100 nsec
sb->s_xattr = ntfs_xattr_handlers;
- sb->s_d_op = options->nocase ? &ntfs_dentry_ops : NULL;
+ if (options->nocase)
+ set_default_d_op(sb, &ntfs_dentry_ops);
options->nls = ntfs_load_nls(options->nls_name);
if (IS_ERR(options->nls)) {
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index 8bb5022f3082..411f72be4a9b 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -1959,7 +1959,7 @@ static int ocfs2_initialize_super(struct super_block *sb,
sb->s_fs_info = osb;
sb->s_op = &ocfs2_sops;
- sb->s_d_op = &ocfs2_dentry_ops;
+ set_default_d_op(sb, &ocfs2_dentry_ops);
sb->s_export_op = &ocfs2_export_ops;
sb->s_qcop = &dquot_quotactl_sysfile_ops;
sb->dq_op = &ocfs2_quota_operations;
diff --git a/fs/orangefs/super.c b/fs/orangefs/super.c
index eba3e357192e..d4c8d8b32f14 100644
--- a/fs/orangefs/super.c
+++ b/fs/orangefs/super.c
@@ -434,7 +434,7 @@ static int orangefs_fill_sb(struct super_block *sb,
sb->s_xattr = orangefs_xattr_handlers;
sb->s_magic = ORANGEFS_SUPER_MAGIC;
sb->s_op = &orangefs_s_ops;
- sb->s_d_op = &orangefs_dentry_operations;
+ set_default_d_op(sb, &orangefs_dentry_operations);
sb->s_blocksize = PAGE_SIZE;
sb->s_blocksize_bits = PAGE_SHIFT;
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index 86ae6f6da36b..5f7a5a8c0778 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -1315,7 +1315,7 @@ int ovl_fill_super(struct super_block *sb, struct fs_context *fc)
if (WARN_ON(fc->user_ns != current_user_ns()))
goto out_err;
- sb->s_d_op = &ovl_dentry_operations;
+ set_default_d_op(sb, &ovl_dentry_operations);
err = -ENOMEM;
ofs->creator_cred = cred = prepare_creds();
diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c
index 6a3bd652d251..5ba1046d1e5a 100644
--- a/fs/smb/client/cifsfs.c
+++ b/fs/smb/client/cifsfs.c
@@ -261,9 +261,9 @@ cifs_read_super(struct super_block *sb)
}
if (tcon->nocase)
- sb->s_d_op = &cifs_ci_dentry_ops;
+ set_default_d_op(sb, &cifs_ci_dentry_ops);
else
- sb->s_d_op = &cifs_dentry_ops;
+ set_default_d_op(sb, &cifs_dentry_ops);
sb->s_root = d_make_root(inode);
if (!sb->s_root) {
diff --git a/fs/tracefs/inode.c b/fs/tracefs/inode.c
index 53214499e384..30a951133831 100644
--- a/fs/tracefs/inode.c
+++ b/fs/tracefs/inode.c
@@ -480,7 +480,7 @@ static int tracefs_fill_super(struct super_block *sb, struct fs_context *fc)
return err;
sb->s_op = &tracefs_super_operations;
- sb->s_d_op = &tracefs_dentry_operations;
+ set_default_d_op(sb, &tracefs_dentry_operations);
return 0;
}
diff --git a/fs/vboxsf/super.c b/fs/vboxsf/super.c
index 1d94bb784108..46eea52beb23 100644
--- a/fs/vboxsf/super.c
+++ b/fs/vboxsf/super.c
@@ -190,7 +190,7 @@ static int vboxsf_fill_super(struct super_block *sb, struct fs_context *fc)
sb->s_blocksize = 1024;
sb->s_maxbytes = MAX_LFS_FILESIZE;
sb->s_op = &vboxsf_super_ops;
- sb->s_d_op = &vboxsf_dentry_ops;
+ set_default_d_op(sb, &vboxsf_dentry_ops);
iroot = iget_locked(sb, 0);
if (!iroot) {
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index f47f3a47d97b..e8cf1d0fdd08 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -619,4 +619,6 @@ static inline struct dentry *d_next_sibling(const struct dentry *dentry)
return hlist_entry_safe(dentry->d_sib.next, struct dentry, d_sib);
}
+void set_default_d_op(struct super_block *, const struct dentry_operations *);
+
#endif /* __LINUX_DCACHE_H */
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 2c3b2f8a621f..23fd8b0d4e81 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1405,7 +1405,7 @@ struct super_block {
*/
const char *s_subtype;
- const struct dentry_operations *s_d_op; /* default d_op for dentries */
+ const struct dentry_operations *__s_d_op; /* default d_op for dentries */
struct shrinker *s_shrink; /* per-sb shrinker handle */
diff --git a/mm/shmem.c b/mm/shmem.c
index 4ea6109a8043..0ecb49113bb2 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -5019,7 +5019,7 @@ static int shmem_fill_super(struct super_block *sb, struct fs_context *fc)
if (ctx->encoding) {
sb->s_encoding = ctx->encoding;
- sb->s_d_op = &shmem_ci_dentry_ops;
+ set_default_d_op(sb, &shmem_ci_dentry_ops);
if (ctx->strict_encoding)
sb->s_encoding_flags = SB_ENC_STRICT_MODE_FL;
}
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index eadc00410ebc..e093e4cf20fa 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -1363,7 +1363,7 @@ rpc_fill_super(struct super_block *sb, struct fs_context *fc)
sb->s_blocksize_bits = PAGE_SHIFT;
sb->s_magic = RPCAUTH_GSSMAGIC;
sb->s_op = &s_ops;
- sb->s_d_op = &simple_dentry_operations;
+ set_default_d_op(sb, &simple_dentry_operations);
sb->s_time_gran = 1;
inode = rpc_get_inode(sb, S_IFDIR | 0555);
--
2.39.5
^ permalink raw reply related [flat|nested] 87+ messages in thread* Re: [PATCH 05/21] new helper: set_default_d_op()
2025-02-24 21:20 ` [PATCH 05/21] new helper: set_default_d_op() Al Viro
@ 2025-02-26 8:30 ` Christian Brauner
0 siblings, 0 replies; 87+ messages in thread
From: Christian Brauner @ 2025-02-26 8:30 UTC (permalink / raw)
To: Al Viro; +Cc: linux-fsdevel, Linus Torvalds, Neil Brown, Miklos Szeredi,
Jan Kara
On Mon, Feb 24, 2025 at 09:20:35PM +0000, Al Viro wrote:
> ... to be used instead of manually assigning to ->s_d_op.
> All in-tree filesystem converted (and field itself is renamed,
> so any out-of-tree ones in need of conversion will be caught
> by compiler).
>
> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
> ---
Reviewed-by: Christian Brauner <brauner@kernel.org>
> Documentation/filesystems/porting.rst | 7 +++++++
> fs/9p/vfs_super.c | 4 ++--
> fs/adfs/super.c | 2 +-
> fs/affs/super.c | 4 ++--
> fs/afs/super.c | 4 ++--
> fs/autofs/inode.c | 2 +-
> fs/btrfs/super.c | 2 +-
> fs/ceph/super.c | 2 +-
> fs/coda/inode.c | 2 +-
> fs/configfs/mount.c | 2 +-
> fs/dcache.c | 10 ++++++++--
> fs/debugfs/inode.c | 2 +-
> fs/devpts/inode.c | 2 +-
> fs/ecryptfs/main.c | 2 +-
> fs/efivarfs/super.c | 2 +-
> fs/exfat/super.c | 4 ++--
> fs/fat/namei_msdos.c | 2 +-
> fs/fat/namei_vfat.c | 4 ++--
> fs/fuse/inode.c | 4 ++--
> fs/gfs2/ops_fstype.c | 2 +-
> fs/hfs/super.c | 2 +-
> fs/hfsplus/super.c | 2 +-
> fs/hostfs/hostfs_kern.c | 2 +-
> fs/hpfs/super.c | 2 +-
> fs/isofs/inode.c | 2 +-
> fs/jfs/super.c | 2 +-
> fs/kernfs/mount.c | 2 +-
> fs/libfs.c | 16 ++++++++--------
> fs/nfs/super.c | 2 +-
> fs/ntfs3/super.c | 3 ++-
> fs/ocfs2/super.c | 2 +-
> fs/orangefs/super.c | 2 +-
> fs/overlayfs/super.c | 2 +-
> fs/smb/client/cifsfs.c | 4 ++--
> fs/tracefs/inode.c | 2 +-
> fs/vboxsf/super.c | 2 +-
> include/linux/dcache.h | 2 ++
> include/linux/fs.h | 2 +-
> mm/shmem.c | 2 +-
> net/sunrpc/rpc_pipe.c | 2 +-
> 40 files changed, 69 insertions(+), 53 deletions(-)
>
> diff --git a/Documentation/filesystems/porting.rst b/Documentation/filesystems/porting.rst
> index 1639e78e3146..004cd69617a2 100644
> --- a/Documentation/filesystems/porting.rst
> +++ b/Documentation/filesystems/porting.rst
> @@ -1157,3 +1157,10 @@ in normal case it points into the pathname being looked up.
> NOTE: if you need something like full path from the root of filesystem,
> you are still on your own - this assists with simple cases, but it's not
> magic.
> +
> +---
> +
> +**mandatory**
> +
> +If your filesystem sets the default dentry_operations, use set_default_d_op()
> +rather than manually setting sb->s_d_op.
> diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
> index 489db161abc9..5c3dc3efb909 100644
> --- a/fs/9p/vfs_super.c
> +++ b/fs/9p/vfs_super.c
> @@ -135,9 +135,9 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags,
> goto release_sb;
>
> if (v9ses->cache & (CACHE_META|CACHE_LOOSE))
> - sb->s_d_op = &v9fs_cached_dentry_operations;
> + set_default_d_op(sb, &v9fs_cached_dentry_operations);
> else
> - sb->s_d_op = &v9fs_dentry_operations;
> + set_default_d_op(sb, &v9fs_dentry_operations);
>
> inode = v9fs_get_new_inode_from_fid(v9ses, fid, sb);
> if (IS_ERR(inode)) {
> diff --git a/fs/adfs/super.c b/fs/adfs/super.c
> index 017c48a80203..fdccdbbfc213 100644
> --- a/fs/adfs/super.c
> +++ b/fs/adfs/super.c
> @@ -397,7 +397,7 @@ static int adfs_fill_super(struct super_block *sb, struct fs_context *fc)
> if (asb->s_ftsuffix)
> asb->s_namelen += 4;
>
> - sb->s_d_op = &adfs_dentry_operations;
> + set_default_d_op(sb, &adfs_dentry_operations);
> root = adfs_iget(sb, &root_obj);
> sb->s_root = d_make_root(root);
> if (!sb->s_root) {
> diff --git a/fs/affs/super.c b/fs/affs/super.c
> index 2fa40337776d..44f8aa883100 100644
> --- a/fs/affs/super.c
> +++ b/fs/affs/super.c
> @@ -500,9 +500,9 @@ static int affs_fill_super(struct super_block *sb, struct fs_context *fc)
> return PTR_ERR(root_inode);
>
> if (affs_test_opt(AFFS_SB(sb)->s_flags, SF_INTL))
> - sb->s_d_op = &affs_intl_dentry_operations;
> + set_default_d_op(sb, &affs_intl_dentry_operations);
> else
> - sb->s_d_op = &affs_dentry_operations;
> + set_default_d_op(sb, &affs_dentry_operations);
>
> sb->s_root = d_make_root(root_inode);
> if (!sb->s_root) {
> diff --git a/fs/afs/super.c b/fs/afs/super.c
> index a9bee610674e..13d0414a1ddb 100644
> --- a/fs/afs/super.c
> +++ b/fs/afs/super.c
> @@ -487,12 +487,12 @@ static int afs_fill_super(struct super_block *sb, struct afs_fs_context *ctx)
> goto error;
>
> if (as->dyn_root) {
> - sb->s_d_op = &afs_dynroot_dentry_operations;
> + set_default_d_op(sb, &afs_dynroot_dentry_operations);
> ret = afs_dynroot_populate(sb);
> if (ret < 0)
> goto error;
> } else {
> - sb->s_d_op = &afs_fs_dentry_operations;
> + set_default_d_op(sb, &afs_fs_dentry_operations);
> rcu_assign_pointer(as->volume->sb, sb);
> }
>
> diff --git a/fs/autofs/inode.c b/fs/autofs/inode.c
> index ee2edccaef70..f5c16ffba013 100644
> --- a/fs/autofs/inode.c
> +++ b/fs/autofs/inode.c
> @@ -311,7 +311,7 @@ static int autofs_fill_super(struct super_block *s, struct fs_context *fc)
> s->s_blocksize_bits = 10;
> s->s_magic = AUTOFS_SUPER_MAGIC;
> s->s_op = &autofs_sops;
> - s->s_d_op = &autofs_dentry_operations;
> + set_default_d_op(s, &autofs_dentry_operations);
> s->s_time_gran = 1;
>
> /*
> diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
> index dc4fee519ca6..5f39857ea3ae 100644
> --- a/fs/btrfs/super.c
> +++ b/fs/btrfs/super.c
> @@ -954,7 +954,7 @@ static int btrfs_fill_super(struct super_block *sb,
> sb->s_maxbytes = MAX_LFS_FILESIZE;
> sb->s_magic = BTRFS_SUPER_MAGIC;
> sb->s_op = &btrfs_super_ops;
> - sb->s_d_op = &btrfs_dentry_operations;
> + set_default_d_op(sb, &btrfs_dentry_operations);
> sb->s_export_op = &btrfs_export_ops;
> #ifdef CONFIG_FS_VERITY
> sb->s_vop = &btrfs_verityops;
> diff --git a/fs/ceph/super.c b/fs/ceph/super.c
> index 4344e1f11806..adec6e2f01c4 100644
> --- a/fs/ceph/super.c
> +++ b/fs/ceph/super.c
> @@ -1220,7 +1220,7 @@ static int ceph_set_super(struct super_block *s, struct fs_context *fc)
> fsc->max_file_size = 1ULL << 40; /* temp value until we get mdsmap */
>
> s->s_op = &ceph_super_ops;
> - s->s_d_op = &ceph_dentry_ops;
> + set_default_d_op(s, &ceph_dentry_ops);
> s->s_export_op = &ceph_export_ops;
>
> s->s_time_gran = 1;
> diff --git a/fs/coda/inode.c b/fs/coda/inode.c
> index 6896fce122e1..08450d006016 100644
> --- a/fs/coda/inode.c
> +++ b/fs/coda/inode.c
> @@ -230,7 +230,7 @@ static int coda_fill_super(struct super_block *sb, struct fs_context *fc)
> sb->s_blocksize_bits = 12;
> sb->s_magic = CODA_SUPER_MAGIC;
> sb->s_op = &coda_super_operations;
> - sb->s_d_op = &coda_dentry_operations;
> + set_default_d_op(sb, &coda_dentry_operations);
> sb->s_time_gran = 1;
> sb->s_time_min = S64_MIN;
> sb->s_time_max = S64_MAX;
> diff --git a/fs/configfs/mount.c b/fs/configfs/mount.c
> index c2d820063ec4..20412eaca972 100644
> --- a/fs/configfs/mount.c
> +++ b/fs/configfs/mount.c
> @@ -92,7 +92,7 @@ static int configfs_fill_super(struct super_block *sb, struct fs_context *fc)
> configfs_root_group.cg_item.ci_dentry = root;
> root->d_fsdata = &configfs_root;
> sb->s_root = root;
> - sb->s_d_op = &configfs_dentry_ops; /* the rest get that */
> + set_default_d_op(sb, &configfs_dentry_ops); /* the rest get that */
> return 0;
> }
>
> diff --git a/fs/dcache.c b/fs/dcache.c
> index c85efbda133a..cd5e5139ca4c 100644
> --- a/fs/dcache.c
> +++ b/fs/dcache.c
> @@ -1712,7 +1712,7 @@ static struct dentry *__d_alloc(struct super_block *sb, const struct qstr *name)
> INIT_HLIST_HEAD(&dentry->d_children);
> INIT_HLIST_NODE(&dentry->d_u.d_alias);
> INIT_HLIST_NODE(&dentry->d_sib);
> - d_set_d_op(dentry, dentry->d_sb->s_d_op);
> + d_set_d_op(dentry, dentry->d_sb->__s_d_op);
>
> if (dentry->d_op && dentry->d_op->d_init) {
> err = dentry->d_op->d_init(dentry);
> @@ -1795,7 +1795,7 @@ struct dentry *d_alloc_pseudo(struct super_block *sb, const struct qstr *name)
> struct dentry *dentry = __d_alloc(sb, name);
> if (likely(dentry)) {
> dentry->d_flags |= DCACHE_NORCU;
> - if (!sb->s_d_op)
> + if (!dentry->d_op)
> d_set_d_op(dentry, &anon_ops);
> }
> return dentry;
> @@ -1841,6 +1841,12 @@ void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op)
> }
> EXPORT_SYMBOL(d_set_d_op);
>
> +void set_default_d_op(struct super_block *s, const struct dentry_operations *ops)
> +{
> + s->__s_d_op = ops;
> +}
> +EXPORT_SYMBOL(set_default_d_op);
> +
> static unsigned d_flags_for_inode(struct inode *inode)
> {
> unsigned add_flags = DCACHE_REGULAR_TYPE;
> diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
> index 75715d8877ee..f54a8fd960e4 100644
> --- a/fs/debugfs/inode.c
> +++ b/fs/debugfs/inode.c
> @@ -273,7 +273,7 @@ static int debugfs_fill_super(struct super_block *sb, struct fs_context *fc)
> return err;
>
> sb->s_op = &debugfs_super_operations;
> - sb->s_d_op = &debugfs_dops;
> + set_default_d_op(sb, &debugfs_dops);
>
> debugfs_apply_options(sb);
>
> diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
> index 1096ff8562fa..f092973236ef 100644
> --- a/fs/devpts/inode.c
> +++ b/fs/devpts/inode.c
> @@ -433,7 +433,7 @@ devpts_fill_super(struct super_block *s, void *data, int silent)
> s->s_blocksize_bits = 10;
> s->s_magic = DEVPTS_SUPER_MAGIC;
> s->s_op = &devpts_sops;
> - s->s_d_op = &simple_dentry_operations;
> + set_default_d_op(s, &simple_dentry_operations);
> s->s_time_gran = 1;
>
> error = -ENOMEM;
> diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
> index 8dd1d7189c3b..45f9ca4465da 100644
> --- a/fs/ecryptfs/main.c
> +++ b/fs/ecryptfs/main.c
> @@ -471,7 +471,7 @@ static int ecryptfs_get_tree(struct fs_context *fc)
> sbi = NULL;
> s->s_op = &ecryptfs_sops;
> s->s_xattr = ecryptfs_xattr_handlers;
> - s->s_d_op = &ecryptfs_dops;
> + set_default_d_op(s, &ecryptfs_dops);
>
> err = "Reading sb failed";
> rc = kern_path(fc->source, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path);
> diff --git a/fs/efivarfs/super.c b/fs/efivarfs/super.c
> index 09fcf731e65d..3f3188e0cfa7 100644
> --- a/fs/efivarfs/super.c
> +++ b/fs/efivarfs/super.c
> @@ -345,7 +345,7 @@ static int efivarfs_fill_super(struct super_block *sb, struct fs_context *fc)
> sb->s_blocksize_bits = PAGE_SHIFT;
> sb->s_magic = EFIVARFS_MAGIC;
> sb->s_op = &efivarfs_ops;
> - sb->s_d_op = &efivarfs_d_ops;
> + set_default_d_op(sb, &efivarfs_d_ops);
> sb->s_time_gran = 1;
>
> if (!efivar_supports_writes())
> diff --git a/fs/exfat/super.c b/fs/exfat/super.c
> index bd57844414aa..c821582fa1ef 100644
> --- a/fs/exfat/super.c
> +++ b/fs/exfat/super.c
> @@ -697,9 +697,9 @@ static int exfat_fill_super(struct super_block *sb, struct fs_context *fc)
> }
>
> if (sbi->options.utf8)
> - sb->s_d_op = &exfat_utf8_dentry_ops;
> + set_default_d_op(sb, &exfat_utf8_dentry_ops);
> else
> - sb->s_d_op = &exfat_dentry_ops;
> + set_default_d_op(sb, &exfat_dentry_ops);
>
> root_inode = new_inode(sb);
> if (!root_inode) {
> diff --git a/fs/fat/namei_msdos.c b/fs/fat/namei_msdos.c
> index f06f6ba643cc..71302291d33c 100644
> --- a/fs/fat/namei_msdos.c
> +++ b/fs/fat/namei_msdos.c
> @@ -646,7 +646,7 @@ static const struct inode_operations msdos_dir_inode_operations = {
> static void setup(struct super_block *sb)
> {
> MSDOS_SB(sb)->dir_ops = &msdos_dir_inode_operations;
> - sb->s_d_op = &msdos_dentry_operations;
> + set_default_d_op(sb, &msdos_dentry_operations);
> sb->s_flags |= SB_NOATIME;
> }
>
> diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c
> index 926c26e90ef8..2476afd1304d 100644
> --- a/fs/fat/namei_vfat.c
> +++ b/fs/fat/namei_vfat.c
> @@ -1187,9 +1187,9 @@ static void setup(struct super_block *sb)
> {
> MSDOS_SB(sb)->dir_ops = &vfat_dir_inode_operations;
> if (MSDOS_SB(sb)->options.name_check != 's')
> - sb->s_d_op = &vfat_ci_dentry_ops;
> + set_default_d_op(sb, &vfat_ci_dentry_ops);
> else
> - sb->s_d_op = &vfat_dentry_ops;
> + set_default_d_op(sb, &vfat_dentry_ops);
> }
>
> static int vfat_fill_super(struct super_block *sb, struct fs_context *fc)
> diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
> index 57a1ee016b73..9994f3b33a9f 100644
> --- a/fs/fuse/inode.c
> +++ b/fs/fuse/inode.c
> @@ -1665,7 +1665,7 @@ static int fuse_fill_super_submount(struct super_block *sb,
> fi = get_fuse_inode(root);
> fi->nlookup--;
>
> - sb->s_d_op = &fuse_dentry_operations;
> + set_default_d_op(sb, &fuse_dentry_operations);
> sb->s_root = d_make_root(root);
> if (!sb->s_root)
> return -ENOMEM;
> @@ -1800,7 +1800,7 @@ int fuse_fill_super_common(struct super_block *sb, struct fuse_fs_context *ctx)
>
> err = -ENOMEM;
> root = fuse_get_root_inode(sb, ctx->rootmode);
> - sb->s_d_op = &fuse_dentry_operations;
> + set_default_d_op(sb, &fuse_dentry_operations);
> root_dentry = d_make_root(root);
> if (!root_dentry)
> goto err_dev_free;
> diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
> index e83d293c3614..949bbdb5b564 100644
> --- a/fs/gfs2/ops_fstype.c
> +++ b/fs/gfs2/ops_fstype.c
> @@ -1156,7 +1156,7 @@ static int gfs2_fill_super(struct super_block *sb, struct fs_context *fc)
> sb->s_flags |= SB_NOSEC;
> sb->s_magic = GFS2_MAGIC;
> sb->s_op = &gfs2_super_ops;
> - sb->s_d_op = &gfs2_dops;
> + set_default_d_op(sb, &gfs2_dops);
> sb->s_export_op = &gfs2_export_ops;
> sb->s_qcop = &gfs2_quotactl_ops;
> sb->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP;
> diff --git a/fs/hfs/super.c b/fs/hfs/super.c
> index fe09c2093a93..388a318297ec 100644
> --- a/fs/hfs/super.c
> +++ b/fs/hfs/super.c
> @@ -365,7 +365,7 @@ static int hfs_fill_super(struct super_block *sb, struct fs_context *fc)
> if (!root_inode)
> goto bail_no_root;
>
> - sb->s_d_op = &hfs_dentry_operations;
> + set_default_d_op(sb, &hfs_dentry_operations);
> res = -ENOMEM;
> sb->s_root = d_make_root(root_inode);
> if (!sb->s_root)
> diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
> index 948b8aaee33e..0caf7aa1c249 100644
> --- a/fs/hfsplus/super.c
> +++ b/fs/hfsplus/super.c
> @@ -508,7 +508,7 @@ static int hfsplus_fill_super(struct super_block *sb, struct fs_context *fc)
> goto out_put_alloc_file;
> }
>
> - sb->s_d_op = &hfsplus_dentry_operations;
> + set_default_d_op(sb, &hfsplus_dentry_operations);
> sb->s_root = d_make_root(root);
> if (!sb->s_root) {
> err = -ENOMEM;
> diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
> index e0741e468956..a0e0563a29d7 100644
> --- a/fs/hostfs/hostfs_kern.c
> +++ b/fs/hostfs/hostfs_kern.c
> @@ -920,7 +920,7 @@ static int hostfs_fill_super(struct super_block *sb, struct fs_context *fc)
> sb->s_blocksize_bits = 10;
> sb->s_magic = HOSTFS_SUPER_MAGIC;
> sb->s_op = &hostfs_sbops;
> - sb->s_d_op = &simple_dentry_operations;
> + set_default_d_op(sb, &simple_dentry_operations);
> sb->s_maxbytes = MAX_LFS_FILESIZE;
> err = super_setup_bdi(sb);
> if (err)
> diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c
> index 27567920abe4..42b779b4d87f 100644
> --- a/fs/hpfs/super.c
> +++ b/fs/hpfs/super.c
> @@ -554,7 +554,7 @@ static int hpfs_fill_super(struct super_block *s, struct fs_context *fc)
> /* Fill superblock stuff */
> s->s_magic = HPFS_SUPER_MAGIC;
> s->s_op = &hpfs_sops;
> - s->s_d_op = &hpfs_dentry_operations;
> + set_default_d_op(s, &hpfs_dentry_operations);
> s->s_time_min = local_to_gmt(s, 0);
> s->s_time_max = local_to_gmt(s, U32_MAX);
>
> diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
> index 47038e660812..05ddc2544ade 100644
> --- a/fs/isofs/inode.c
> +++ b/fs/isofs/inode.c
> @@ -939,7 +939,7 @@ static int isofs_fill_super(struct super_block *s, struct fs_context *fc)
> sbi->s_check = opt->check;
>
> if (table)
> - s->s_d_op = &isofs_dentry_ops[table - 1];
> + set_default_d_op(s, &isofs_dentry_ops[table - 1]);
>
> /* get the root dentry */
> s->s_root = d_make_root(inode);
> diff --git a/fs/jfs/super.c b/fs/jfs/super.c
> index 223d9ac59839..10c3cb714423 100644
> --- a/fs/jfs/super.c
> +++ b/fs/jfs/super.c
> @@ -542,7 +542,7 @@ static int jfs_fill_super(struct super_block *sb, struct fs_context *fc)
> sb->s_magic = JFS_SUPER_MAGIC;
>
> if (sbi->mntflag & JFS_OS2)
> - sb->s_d_op = &jfs_ci_dentry_operations;
> + set_default_d_op(sb, &jfs_ci_dentry_operations);
>
> inode = jfs_iget(sb, ROOT_I);
> if (IS_ERR(inode)) {
> diff --git a/fs/kernfs/mount.c b/fs/kernfs/mount.c
> index 1358c21837f1..91e788d15073 100644
> --- a/fs/kernfs/mount.c
> +++ b/fs/kernfs/mount.c
> @@ -281,7 +281,7 @@ static int kernfs_fill_super(struct super_block *sb, struct kernfs_fs_context *k
> return -ENOMEM;
> }
> sb->s_root = root;
> - sb->s_d_op = &kernfs_dops;
> + set_default_d_op(sb, &kernfs_dops);
> return 0;
> }
>
> diff --git a/fs/libfs.c b/fs/libfs.c
> index 8444f5cc4064..929bef0fecbd 100644
> --- a/fs/libfs.c
> +++ b/fs/libfs.c
> @@ -75,7 +75,7 @@ struct dentry *simple_lookup(struct inode *dir, struct dentry *dentry, unsigned
> {
> if (dentry->d_name.len > NAME_MAX)
> return ERR_PTR(-ENAMETOOLONG);
> - if (!dentry->d_sb->s_d_op)
> + if (!dentry->d_op)
> d_set_d_op(dentry, &simple_dentry_operations);
>
> if (IS_ENABLED(CONFIG_UNICODE) && IS_CASEFOLDED(dir))
> @@ -683,7 +683,7 @@ static int pseudo_fs_fill_super(struct super_block *s, struct fs_context *fc)
> s->s_root = d_make_root(root);
> if (!s->s_root)
> return -ENOMEM;
> - s->s_d_op = ctx->dops;
> + set_default_d_op(s, ctx->dops);
> return 0;
> }
>
> @@ -1943,22 +1943,22 @@ static const struct dentry_operations generic_encrypted_dentry_ops = {
> * @sb: superblock to be configured
> *
> * Filesystems supporting casefolding and/or fscrypt can call this
> - * helper at mount-time to configure sb->s_d_op to best set of dentry
> - * operations required for the enabled features. The helper must be
> - * called after these have been configured, but before the root dentry
> - * is created.
> + * helper at mount-time to configure default dentry_operations to the
> + * best set of dentry operations required for the enabled features.
> + * The helper must be called after these have been configured, but
> + * before the root dentry is created.
> */
> void generic_set_sb_d_ops(struct super_block *sb)
> {
> #if IS_ENABLED(CONFIG_UNICODE)
> if (sb->s_encoding) {
> - sb->s_d_op = &generic_ci_dentry_ops;
> + set_default_d_op(sb, &generic_ci_dentry_ops);
> return;
> }
> #endif
> #ifdef CONFIG_FS_ENCRYPTION
> if (sb->s_cop) {
> - sb->s_d_op = &generic_encrypted_dentry_ops;
> + set_default_d_op(sb, &generic_encrypted_dentry_ops);
> return;
> }
> #endif
> diff --git a/fs/nfs/super.c b/fs/nfs/super.c
> index aeb715b4a690..38b0ecf02ad6 100644
> --- a/fs/nfs/super.c
> +++ b/fs/nfs/super.c
> @@ -1169,7 +1169,7 @@ static int nfs_set_super(struct super_block *s, struct fs_context *fc)
> struct nfs_server *server = fc->s_fs_info;
> int ret;
>
> - s->s_d_op = server->nfs_client->rpc_ops->dentry_ops;
> + set_default_d_op(s, server->nfs_client->rpc_ops->dentry_ops);
> ret = set_anon_super(s, server);
> if (ret == 0)
> server->s_dev = s->s_dev;
> diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c
> index 6a0f6b0a3ab2..90f5361ae13f 100644
> --- a/fs/ntfs3/super.c
> +++ b/fs/ntfs3/super.c
> @@ -1182,7 +1182,8 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc)
> sb->s_export_op = &ntfs_export_ops;
> sb->s_time_gran = NTFS_TIME_GRAN; // 100 nsec
> sb->s_xattr = ntfs_xattr_handlers;
> - sb->s_d_op = options->nocase ? &ntfs_dentry_ops : NULL;
> + if (options->nocase)
> + set_default_d_op(sb, &ntfs_dentry_ops);
>
> options->nls = ntfs_load_nls(options->nls_name);
> if (IS_ERR(options->nls)) {
> diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
> index 8bb5022f3082..411f72be4a9b 100644
> --- a/fs/ocfs2/super.c
> +++ b/fs/ocfs2/super.c
> @@ -1959,7 +1959,7 @@ static int ocfs2_initialize_super(struct super_block *sb,
>
> sb->s_fs_info = osb;
> sb->s_op = &ocfs2_sops;
> - sb->s_d_op = &ocfs2_dentry_ops;
> + set_default_d_op(sb, &ocfs2_dentry_ops);
> sb->s_export_op = &ocfs2_export_ops;
> sb->s_qcop = &dquot_quotactl_sysfile_ops;
> sb->dq_op = &ocfs2_quota_operations;
> diff --git a/fs/orangefs/super.c b/fs/orangefs/super.c
> index eba3e357192e..d4c8d8b32f14 100644
> --- a/fs/orangefs/super.c
> +++ b/fs/orangefs/super.c
> @@ -434,7 +434,7 @@ static int orangefs_fill_sb(struct super_block *sb,
> sb->s_xattr = orangefs_xattr_handlers;
> sb->s_magic = ORANGEFS_SUPER_MAGIC;
> sb->s_op = &orangefs_s_ops;
> - sb->s_d_op = &orangefs_dentry_operations;
> + set_default_d_op(sb, &orangefs_dentry_operations);
>
> sb->s_blocksize = PAGE_SIZE;
> sb->s_blocksize_bits = PAGE_SHIFT;
> diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
> index 86ae6f6da36b..5f7a5a8c0778 100644
> --- a/fs/overlayfs/super.c
> +++ b/fs/overlayfs/super.c
> @@ -1315,7 +1315,7 @@ int ovl_fill_super(struct super_block *sb, struct fs_context *fc)
> if (WARN_ON(fc->user_ns != current_user_ns()))
> goto out_err;
>
> - sb->s_d_op = &ovl_dentry_operations;
> + set_default_d_op(sb, &ovl_dentry_operations);
>
> err = -ENOMEM;
> ofs->creator_cred = cred = prepare_creds();
> diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c
> index 6a3bd652d251..5ba1046d1e5a 100644
> --- a/fs/smb/client/cifsfs.c
> +++ b/fs/smb/client/cifsfs.c
> @@ -261,9 +261,9 @@ cifs_read_super(struct super_block *sb)
> }
>
> if (tcon->nocase)
> - sb->s_d_op = &cifs_ci_dentry_ops;
> + set_default_d_op(sb, &cifs_ci_dentry_ops);
> else
> - sb->s_d_op = &cifs_dentry_ops;
> + set_default_d_op(sb, &cifs_dentry_ops);
>
> sb->s_root = d_make_root(inode);
> if (!sb->s_root) {
> diff --git a/fs/tracefs/inode.c b/fs/tracefs/inode.c
> index 53214499e384..30a951133831 100644
> --- a/fs/tracefs/inode.c
> +++ b/fs/tracefs/inode.c
> @@ -480,7 +480,7 @@ static int tracefs_fill_super(struct super_block *sb, struct fs_context *fc)
> return err;
>
> sb->s_op = &tracefs_super_operations;
> - sb->s_d_op = &tracefs_dentry_operations;
> + set_default_d_op(sb, &tracefs_dentry_operations);
>
> return 0;
> }
> diff --git a/fs/vboxsf/super.c b/fs/vboxsf/super.c
> index 1d94bb784108..46eea52beb23 100644
> --- a/fs/vboxsf/super.c
> +++ b/fs/vboxsf/super.c
> @@ -190,7 +190,7 @@ static int vboxsf_fill_super(struct super_block *sb, struct fs_context *fc)
> sb->s_blocksize = 1024;
> sb->s_maxbytes = MAX_LFS_FILESIZE;
> sb->s_op = &vboxsf_super_ops;
> - sb->s_d_op = &vboxsf_dentry_ops;
> + set_default_d_op(sb, &vboxsf_dentry_ops);
>
> iroot = iget_locked(sb, 0);
> if (!iroot) {
> diff --git a/include/linux/dcache.h b/include/linux/dcache.h
> index f47f3a47d97b..e8cf1d0fdd08 100644
> --- a/include/linux/dcache.h
> +++ b/include/linux/dcache.h
> @@ -619,4 +619,6 @@ static inline struct dentry *d_next_sibling(const struct dentry *dentry)
> return hlist_entry_safe(dentry->d_sib.next, struct dentry, d_sib);
> }
>
> +void set_default_d_op(struct super_block *, const struct dentry_operations *);
> +
> #endif /* __LINUX_DCACHE_H */
> diff --git a/include/linux/fs.h b/include/linux/fs.h
> index 2c3b2f8a621f..23fd8b0d4e81 100644
> --- a/include/linux/fs.h
> +++ b/include/linux/fs.h
> @@ -1405,7 +1405,7 @@ struct super_block {
> */
> const char *s_subtype;
>
> - const struct dentry_operations *s_d_op; /* default d_op for dentries */
> + const struct dentry_operations *__s_d_op; /* default d_op for dentries */
>
> struct shrinker *s_shrink; /* per-sb shrinker handle */
>
> diff --git a/mm/shmem.c b/mm/shmem.c
> index 4ea6109a8043..0ecb49113bb2 100644
> --- a/mm/shmem.c
> +++ b/mm/shmem.c
> @@ -5019,7 +5019,7 @@ static int shmem_fill_super(struct super_block *sb, struct fs_context *fc)
>
> if (ctx->encoding) {
> sb->s_encoding = ctx->encoding;
> - sb->s_d_op = &shmem_ci_dentry_ops;
> + set_default_d_op(sb, &shmem_ci_dentry_ops);
> if (ctx->strict_encoding)
> sb->s_encoding_flags = SB_ENC_STRICT_MODE_FL;
> }
> diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
> index eadc00410ebc..e093e4cf20fa 100644
> --- a/net/sunrpc/rpc_pipe.c
> +++ b/net/sunrpc/rpc_pipe.c
> @@ -1363,7 +1363,7 @@ rpc_fill_super(struct super_block *sb, struct fs_context *fc)
> sb->s_blocksize_bits = PAGE_SHIFT;
> sb->s_magic = RPCAUTH_GSSMAGIC;
> sb->s_op = &s_ops;
> - sb->s_d_op = &simple_dentry_operations;
> + set_default_d_op(sb, &simple_dentry_operations);
> sb->s_time_gran = 1;
>
> inode = rpc_get_inode(sb, S_IFDIR | 0555);
> --
> 2.39.5
>
^ permalink raw reply [flat|nested] 87+ messages in thread
* [PATCH 06/21] split d_flags calculation out of d_set_d_op()
2025-02-24 21:20 ` [PATCH 01/21] procfs: kill ->proc_dops Al Viro
` (3 preceding siblings ...)
2025-02-24 21:20 ` [PATCH 05/21] new helper: set_default_d_op() Al Viro
@ 2025-02-24 21:20 ` Al Viro
2025-02-26 8:31 ` Christian Brauner
2025-02-24 21:20 ` [PATCH 07/21] set_default_d_op(): calculate the matching value for ->d_flags Al Viro
` (17 subsequent siblings)
22 siblings, 1 reply; 87+ messages in thread
From: Al Viro @ 2025-02-24 21:20 UTC (permalink / raw)
To: linux-fsdevel
Cc: Linus Torvalds, Christian Brauner, Neil Brown, Miklos Szeredi,
Jan Kara
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/dcache.c | 53 ++++++++++++++++++++++++++++++-----------------------
1 file changed, 30 insertions(+), 23 deletions(-)
diff --git a/fs/dcache.c b/fs/dcache.c
index cd5e5139ca4c..1201149e1e2c 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1811,33 +1811,40 @@ struct dentry *d_alloc_name(struct dentry *parent, const char *name)
}
EXPORT_SYMBOL(d_alloc_name);
+#define DCACHE_OP_FLAGS \
+ (DCACHE_OP_HASH | DCACHE_OP_COMPARE | DCACHE_OP_REVALIDATE | \
+ DCACHE_OP_WEAK_REVALIDATE | DCACHE_OP_DELETE | DCACHE_OP_REAL)
+
+static unsigned int d_op_flags(const struct dentry_operations *op)
+{
+ unsigned int flags = 0;
+ if (op) {
+ if (op->d_hash)
+ flags |= DCACHE_OP_HASH;
+ if (op->d_compare)
+ flags |= DCACHE_OP_COMPARE;
+ if (op->d_revalidate)
+ flags |= DCACHE_OP_REVALIDATE;
+ if (op->d_weak_revalidate)
+ flags |= DCACHE_OP_WEAK_REVALIDATE;
+ if (op->d_delete)
+ flags |= DCACHE_OP_DELETE;
+ if (op->d_prune)
+ flags |= DCACHE_OP_PRUNE;
+ if (op->d_real)
+ flags |= DCACHE_OP_REAL;
+ }
+ return flags;
+}
+
void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op)
{
+ unsigned int flags = d_op_flags(op);
WARN_ON_ONCE(dentry->d_op);
- WARN_ON_ONCE(dentry->d_flags & (DCACHE_OP_HASH |
- DCACHE_OP_COMPARE |
- DCACHE_OP_REVALIDATE |
- DCACHE_OP_WEAK_REVALIDATE |
- DCACHE_OP_DELETE |
- DCACHE_OP_REAL));
+ WARN_ON_ONCE(dentry->d_flags & DCACHE_OP_FLAGS);
dentry->d_op = op;
- if (!op)
- return;
- if (op->d_hash)
- dentry->d_flags |= DCACHE_OP_HASH;
- if (op->d_compare)
- dentry->d_flags |= DCACHE_OP_COMPARE;
- if (op->d_revalidate)
- dentry->d_flags |= DCACHE_OP_REVALIDATE;
- if (op->d_weak_revalidate)
- dentry->d_flags |= DCACHE_OP_WEAK_REVALIDATE;
- if (op->d_delete)
- dentry->d_flags |= DCACHE_OP_DELETE;
- if (op->d_prune)
- dentry->d_flags |= DCACHE_OP_PRUNE;
- if (op->d_real)
- dentry->d_flags |= DCACHE_OP_REAL;
-
+ if (flags)
+ dentry->d_flags |= flags;
}
EXPORT_SYMBOL(d_set_d_op);
--
2.39.5
^ permalink raw reply related [flat|nested] 87+ messages in thread* Re: [PATCH 06/21] split d_flags calculation out of d_set_d_op()
2025-02-24 21:20 ` [PATCH 06/21] split d_flags calculation out of d_set_d_op() Al Viro
@ 2025-02-26 8:31 ` Christian Brauner
0 siblings, 0 replies; 87+ messages in thread
From: Christian Brauner @ 2025-02-26 8:31 UTC (permalink / raw)
To: Al Viro; +Cc: linux-fsdevel, Linus Torvalds, Neil Brown, Miklos Szeredi,
Jan Kara
On Mon, Feb 24, 2025 at 09:20:36PM +0000, Al Viro wrote:
> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
> ---
Reviewed-by: Christian Brauner <brauner@kernel.org>
> fs/dcache.c | 53 ++++++++++++++++++++++++++++++-----------------------
> 1 file changed, 30 insertions(+), 23 deletions(-)
>
> diff --git a/fs/dcache.c b/fs/dcache.c
> index cd5e5139ca4c..1201149e1e2c 100644
> --- a/fs/dcache.c
> +++ b/fs/dcache.c
> @@ -1811,33 +1811,40 @@ struct dentry *d_alloc_name(struct dentry *parent, const char *name)
> }
> EXPORT_SYMBOL(d_alloc_name);
>
> +#define DCACHE_OP_FLAGS \
> + (DCACHE_OP_HASH | DCACHE_OP_COMPARE | DCACHE_OP_REVALIDATE | \
> + DCACHE_OP_WEAK_REVALIDATE | DCACHE_OP_DELETE | DCACHE_OP_REAL)
> +
> +static unsigned int d_op_flags(const struct dentry_operations *op)
> +{
> + unsigned int flags = 0;
> + if (op) {
> + if (op->d_hash)
> + flags |= DCACHE_OP_HASH;
> + if (op->d_compare)
> + flags |= DCACHE_OP_COMPARE;
> + if (op->d_revalidate)
> + flags |= DCACHE_OP_REVALIDATE;
> + if (op->d_weak_revalidate)
> + flags |= DCACHE_OP_WEAK_REVALIDATE;
> + if (op->d_delete)
> + flags |= DCACHE_OP_DELETE;
> + if (op->d_prune)
> + flags |= DCACHE_OP_PRUNE;
> + if (op->d_real)
> + flags |= DCACHE_OP_REAL;
> + }
> + return flags;
> +}
> +
> void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op)
> {
> + unsigned int flags = d_op_flags(op);
> WARN_ON_ONCE(dentry->d_op);
> - WARN_ON_ONCE(dentry->d_flags & (DCACHE_OP_HASH |
> - DCACHE_OP_COMPARE |
> - DCACHE_OP_REVALIDATE |
> - DCACHE_OP_WEAK_REVALIDATE |
> - DCACHE_OP_DELETE |
> - DCACHE_OP_REAL));
> + WARN_ON_ONCE(dentry->d_flags & DCACHE_OP_FLAGS);
> dentry->d_op = op;
> - if (!op)
> - return;
> - if (op->d_hash)
> - dentry->d_flags |= DCACHE_OP_HASH;
> - if (op->d_compare)
> - dentry->d_flags |= DCACHE_OP_COMPARE;
> - if (op->d_revalidate)
> - dentry->d_flags |= DCACHE_OP_REVALIDATE;
> - if (op->d_weak_revalidate)
> - dentry->d_flags |= DCACHE_OP_WEAK_REVALIDATE;
> - if (op->d_delete)
> - dentry->d_flags |= DCACHE_OP_DELETE;
> - if (op->d_prune)
> - dentry->d_flags |= DCACHE_OP_PRUNE;
> - if (op->d_real)
> - dentry->d_flags |= DCACHE_OP_REAL;
> -
> + if (flags)
> + dentry->d_flags |= flags;
> }
> EXPORT_SYMBOL(d_set_d_op);
>
> --
> 2.39.5
>
^ permalink raw reply [flat|nested] 87+ messages in thread
* [PATCH 07/21] set_default_d_op(): calculate the matching value for ->d_flags
2025-02-24 21:20 ` [PATCH 01/21] procfs: kill ->proc_dops Al Viro
` (4 preceding siblings ...)
2025-02-24 21:20 ` [PATCH 06/21] split d_flags calculation out of d_set_d_op() Al Viro
@ 2025-02-24 21:20 ` Al Viro
2025-02-26 8:33 ` Christian Brauner
2025-02-24 21:20 ` [PATCH 08/21] simple_lookup(): just set DCACHE_DONTCACHE Al Viro
` (16 subsequent siblings)
22 siblings, 1 reply; 87+ messages in thread
From: Al Viro @ 2025-02-24 21:20 UTC (permalink / raw)
To: linux-fsdevel
Cc: Linus Torvalds, Christian Brauner, Neil Brown, Miklos Szeredi,
Jan Kara
... and store it in ->s_d_flags, to be used in __d_alloc()
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/dcache.c | 6 ++++--
include/linux/fs.h | 1 +
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/fs/dcache.c b/fs/dcache.c
index 1201149e1e2c..a4795617c3db 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1705,14 +1705,14 @@ static struct dentry *__d_alloc(struct super_block *sb, const struct qstr *name)
dentry->d_inode = NULL;
dentry->d_parent = dentry;
dentry->d_sb = sb;
- dentry->d_op = NULL;
+ dentry->d_op = sb->__s_d_op;
+ dentry->d_flags = sb->s_d_flags;
dentry->d_fsdata = NULL;
INIT_HLIST_BL_NODE(&dentry->d_hash);
INIT_LIST_HEAD(&dentry->d_lru);
INIT_HLIST_HEAD(&dentry->d_children);
INIT_HLIST_NODE(&dentry->d_u.d_alias);
INIT_HLIST_NODE(&dentry->d_sib);
- d_set_d_op(dentry, dentry->d_sb->__s_d_op);
if (dentry->d_op && dentry->d_op->d_init) {
err = dentry->d_op->d_init(dentry);
@@ -1850,7 +1850,9 @@ EXPORT_SYMBOL(d_set_d_op);
void set_default_d_op(struct super_block *s, const struct dentry_operations *ops)
{
+ unsigned int flags = d_op_flags(ops);
s->__s_d_op = ops;
+ s->s_d_flags = (s->s_d_flags & ~DCACHE_OP_FLAGS) | flags;
}
EXPORT_SYMBOL(set_default_d_op);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 23fd8b0d4e81..473a9de5fc8f 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1392,6 +1392,7 @@ struct super_block {
char s_sysfs_name[UUID_STRING_LEN + 1];
unsigned int s_max_links;
+ unsigned int s_d_flags;
/*
* The next field is for VFS *only*. No filesystems have any business
--
2.39.5
^ permalink raw reply related [flat|nested] 87+ messages in thread* Re: [PATCH 07/21] set_default_d_op(): calculate the matching value for ->d_flags
2025-02-24 21:20 ` [PATCH 07/21] set_default_d_op(): calculate the matching value for ->d_flags Al Viro
@ 2025-02-26 8:33 ` Christian Brauner
0 siblings, 0 replies; 87+ messages in thread
From: Christian Brauner @ 2025-02-26 8:33 UTC (permalink / raw)
To: Al Viro; +Cc: linux-fsdevel, Linus Torvalds, Neil Brown, Miklos Szeredi,
Jan Kara
On Mon, Feb 24, 2025 at 09:20:37PM +0000, Al Viro wrote:
> ... and store it in ->s_d_flags, to be used in __d_alloc()
>
> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
> ---
Reviewed-by: Christian Brauner <brauner@kernel.org>
> fs/dcache.c | 6 ++++--
> include/linux/fs.h | 1 +
> 2 files changed, 5 insertions(+), 2 deletions(-)
>
> diff --git a/fs/dcache.c b/fs/dcache.c
> index 1201149e1e2c..a4795617c3db 100644
> --- a/fs/dcache.c
> +++ b/fs/dcache.c
> @@ -1705,14 +1705,14 @@ static struct dentry *__d_alloc(struct super_block *sb, const struct qstr *name)
> dentry->d_inode = NULL;
> dentry->d_parent = dentry;
> dentry->d_sb = sb;
> - dentry->d_op = NULL;
> + dentry->d_op = sb->__s_d_op;
> + dentry->d_flags = sb->s_d_flags;
> dentry->d_fsdata = NULL;
> INIT_HLIST_BL_NODE(&dentry->d_hash);
> INIT_LIST_HEAD(&dentry->d_lru);
> INIT_HLIST_HEAD(&dentry->d_children);
> INIT_HLIST_NODE(&dentry->d_u.d_alias);
> INIT_HLIST_NODE(&dentry->d_sib);
> - d_set_d_op(dentry, dentry->d_sb->__s_d_op);
>
> if (dentry->d_op && dentry->d_op->d_init) {
> err = dentry->d_op->d_init(dentry);
> @@ -1850,7 +1850,9 @@ EXPORT_SYMBOL(d_set_d_op);
>
> void set_default_d_op(struct super_block *s, const struct dentry_operations *ops)
> {
> + unsigned int flags = d_op_flags(ops);
> s->__s_d_op = ops;
> + s->s_d_flags = (s->s_d_flags & ~DCACHE_OP_FLAGS) | flags;
> }
> EXPORT_SYMBOL(set_default_d_op);
>
> diff --git a/include/linux/fs.h b/include/linux/fs.h
> index 23fd8b0d4e81..473a9de5fc8f 100644
> --- a/include/linux/fs.h
> +++ b/include/linux/fs.h
> @@ -1392,6 +1392,7 @@ struct super_block {
> char s_sysfs_name[UUID_STRING_LEN + 1];
>
> unsigned int s_max_links;
> + unsigned int s_d_flags;
>
> /*
> * The next field is for VFS *only*. No filesystems have any business
> --
> 2.39.5
>
^ permalink raw reply [flat|nested] 87+ messages in thread
* [PATCH 08/21] simple_lookup(): just set DCACHE_DONTCACHE
2025-02-24 21:20 ` [PATCH 01/21] procfs: kill ->proc_dops Al Viro
` (5 preceding siblings ...)
2025-02-24 21:20 ` [PATCH 07/21] set_default_d_op(): calculate the matching value for ->d_flags Al Viro
@ 2025-02-24 21:20 ` Al Viro
2025-02-26 8:34 ` Christian Brauner
2025-02-24 21:20 ` [PATCH 09/21] make d_set_d_op() static Al Viro
` (15 subsequent siblings)
22 siblings, 1 reply; 87+ messages in thread
From: Al Viro @ 2025-02-24 21:20 UTC (permalink / raw)
To: linux-fsdevel
Cc: Linus Torvalds, Christian Brauner, Neil Brown, Miklos Szeredi,
Jan Kara
No need to mess with ->d_op at all. Note that ->d_delete that always
returns 1 is equivalent to having DCACHE_DONTCACHE in ->d_flags.
Later the same thing will be placed into ->s_d_flags of the filesystems
where we want that behaviour for all dentries; then the check in
simple_lookup() will at least get unlikely() slapped on it.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/libfs.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/fs/libfs.c b/fs/libfs.c
index 929bef0fecbd..b15a2148714e 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -75,9 +75,11 @@ struct dentry *simple_lookup(struct inode *dir, struct dentry *dentry, unsigned
{
if (dentry->d_name.len > NAME_MAX)
return ERR_PTR(-ENAMETOOLONG);
- if (!dentry->d_op)
- d_set_d_op(dentry, &simple_dentry_operations);
-
+ if (!(dentry->d_flags & DCACHE_DONTCACHE)) {
+ spin_lock(&dentry->d_lock);
+ dentry->d_flags |= DCACHE_DONTCACHE;
+ spin_unlock(&dentry->d_lock);
+ }
if (IS_ENABLED(CONFIG_UNICODE) && IS_CASEFOLDED(dir))
return NULL;
--
2.39.5
^ permalink raw reply related [flat|nested] 87+ messages in thread* Re: [PATCH 08/21] simple_lookup(): just set DCACHE_DONTCACHE
2025-02-24 21:20 ` [PATCH 08/21] simple_lookup(): just set DCACHE_DONTCACHE Al Viro
@ 2025-02-26 8:34 ` Christian Brauner
0 siblings, 0 replies; 87+ messages in thread
From: Christian Brauner @ 2025-02-26 8:34 UTC (permalink / raw)
To: Al Viro; +Cc: linux-fsdevel, Linus Torvalds, Neil Brown, Miklos Szeredi,
Jan Kara
On Mon, Feb 24, 2025 at 09:20:38PM +0000, Al Viro wrote:
> No need to mess with ->d_op at all. Note that ->d_delete that always
> returns 1 is equivalent to having DCACHE_DONTCACHE in ->d_flags.
> Later the same thing will be placed into ->s_d_flags of the filesystems
> where we want that behaviour for all dentries; then the check in
> simple_lookup() will at least get unlikely() slapped on it.
>
> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
> ---
Reviewed-by: Christian Brauner <brauner@kernel.org>
> fs/libfs.c | 8 +++++---
> 1 file changed, 5 insertions(+), 3 deletions(-)
>
> diff --git a/fs/libfs.c b/fs/libfs.c
> index 929bef0fecbd..b15a2148714e 100644
> --- a/fs/libfs.c
> +++ b/fs/libfs.c
> @@ -75,9 +75,11 @@ struct dentry *simple_lookup(struct inode *dir, struct dentry *dentry, unsigned
> {
> if (dentry->d_name.len > NAME_MAX)
> return ERR_PTR(-ENAMETOOLONG);
> - if (!dentry->d_op)
> - d_set_d_op(dentry, &simple_dentry_operations);
> -
> + if (!(dentry->d_flags & DCACHE_DONTCACHE)) {
> + spin_lock(&dentry->d_lock);
> + dentry->d_flags |= DCACHE_DONTCACHE;
> + spin_unlock(&dentry->d_lock);
> + }
> if (IS_ENABLED(CONFIG_UNICODE) && IS_CASEFOLDED(dir))
> return NULL;
>
> --
> 2.39.5
>
^ permalink raw reply [flat|nested] 87+ messages in thread
* [PATCH 09/21] make d_set_d_op() static
2025-02-24 21:20 ` [PATCH 01/21] procfs: kill ->proc_dops Al Viro
` (6 preceding siblings ...)
2025-02-24 21:20 ` [PATCH 08/21] simple_lookup(): just set DCACHE_DONTCACHE Al Viro
@ 2025-02-24 21:20 ` Al Viro
2025-02-25 23:09 ` NeilBrown
2025-02-26 8:35 ` Christian Brauner
2025-02-24 21:20 ` [PATCH 10/21] d_alloc_parallel(): set DCACHE_PAR_LOOKUP earlier Al Viro
` (14 subsequent siblings)
22 siblings, 2 replies; 87+ messages in thread
From: Al Viro @ 2025-02-24 21:20 UTC (permalink / raw)
To: linux-fsdevel
Cc: Linus Torvalds, Christian Brauner, Neil Brown, Miklos Szeredi,
Jan Kara
Convert the last user (d_alloc_pseudo()) and be done with that.
Any out-of-tree filesystem using it should switch to d_splice_alias_ops()
or, better yet, check whether it really needs to have ->d_op vary among
its dentries.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
Documentation/filesystems/porting.rst | 11 +++++++++++
fs/dcache.c | 5 ++---
include/linux/dcache.h | 1 -
3 files changed, 13 insertions(+), 4 deletions(-)
diff --git a/Documentation/filesystems/porting.rst b/Documentation/filesystems/porting.rst
index 004cd69617a2..61b5771dde53 100644
--- a/Documentation/filesystems/porting.rst
+++ b/Documentation/filesystems/porting.rst
@@ -1164,3 +1164,14 @@ magic.
If your filesystem sets the default dentry_operations, use set_default_d_op()
rather than manually setting sb->s_d_op.
+
+---
+
+**mandatory**
+
+d_set_d_op() is no longer exported (or public, for that matter); _if_
+your filesystem really needed that, make use of d_splice_alias_ops()
+to have them set. Better yet, think hard whether you need different
+->d_op for different dentries - if not, just use set_default_d_op()
+at mount time and be done with that. Currently procfs is the only
+thing that really needs ->d_op varying between dentries.
diff --git a/fs/dcache.c b/fs/dcache.c
index a4795617c3db..29db27228d97 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1796,7 +1796,7 @@ struct dentry *d_alloc_pseudo(struct super_block *sb, const struct qstr *name)
if (likely(dentry)) {
dentry->d_flags |= DCACHE_NORCU;
if (!dentry->d_op)
- d_set_d_op(dentry, &anon_ops);
+ dentry->d_op = &anon_ops;
}
return dentry;
}
@@ -1837,7 +1837,7 @@ static unsigned int d_op_flags(const struct dentry_operations *op)
return flags;
}
-void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op)
+static void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op)
{
unsigned int flags = d_op_flags(op);
WARN_ON_ONCE(dentry->d_op);
@@ -1846,7 +1846,6 @@ void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op)
if (flags)
dentry->d_flags |= flags;
}
-EXPORT_SYMBOL(d_set_d_op);
void set_default_d_op(struct super_block *s, const struct dentry_operations *ops)
{
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index e8cf1d0fdd08..5a03e85f92a4 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -242,7 +242,6 @@ extern void d_instantiate_new(struct dentry *, struct inode *);
extern void __d_drop(struct dentry *dentry);
extern void d_drop(struct dentry *dentry);
extern void d_delete(struct dentry *);
-extern void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op);
/* allocate/de-allocate */
extern struct dentry * d_alloc(struct dentry *, const struct qstr *);
--
2.39.5
^ permalink raw reply related [flat|nested] 87+ messages in thread* Re: [PATCH 09/21] make d_set_d_op() static
2025-02-24 21:20 ` [PATCH 09/21] make d_set_d_op() static Al Viro
@ 2025-02-25 23:09 ` NeilBrown
2025-02-26 8:35 ` Christian Brauner
1 sibling, 0 replies; 87+ messages in thread
From: NeilBrown @ 2025-02-25 23:09 UTC (permalink / raw)
To: Al Viro
Cc: linux-fsdevel, Linus Torvalds, Christian Brauner, Miklos Szeredi,
Jan Kara
On Tue, 25 Feb 2025, Al Viro wrote:
> Convert the last user (d_alloc_pseudo()) and be done with that.
> Any out-of-tree filesystem using it should switch to d_splice_alias_ops()
> or, better yet, check whether it really needs to have ->d_op vary among
> its dentries.
>
> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
> ---
> Documentation/filesystems/porting.rst | 11 +++++++++++
> fs/dcache.c | 5 ++---
> include/linux/dcache.h | 1 -
> 3 files changed, 13 insertions(+), 4 deletions(-)
>
> diff --git a/Documentation/filesystems/porting.rst b/Documentation/filesystems/porting.rst
> index 004cd69617a2..61b5771dde53 100644
> --- a/Documentation/filesystems/porting.rst
> +++ b/Documentation/filesystems/porting.rst
> @@ -1164,3 +1164,14 @@ magic.
>
> If your filesystem sets the default dentry_operations, use set_default_d_op()
> rather than manually setting sb->s_d_op.
> +
> +---
> +
> +**mandatory**
> +
> +d_set_d_op() is no longer exported (or public, for that matter); _if_
> +your filesystem really needed that, make use of d_splice_alias_ops()
> +to have them set. Better yet, think hard whether you need different
> +->d_op for different dentries - if not, just use set_default_d_op()
> +at mount time and be done with that. Currently procfs is the only
> +thing that really needs ->d_op varying between dentries.
> diff --git a/fs/dcache.c b/fs/dcache.c
> index a4795617c3db..29db27228d97 100644
> --- a/fs/dcache.c
> +++ b/fs/dcache.c
> @@ -1796,7 +1796,7 @@ struct dentry *d_alloc_pseudo(struct super_block *sb, const struct qstr *name)
> if (likely(dentry)) {
> dentry->d_flags |= DCACHE_NORCU;
> if (!dentry->d_op)
> - d_set_d_op(dentry, &anon_ops);
> + dentry->d_op = &anon_ops;
This is safe because d_op_flags(anon_ops) is zero so there is no need to
update dentry->d_flags. I wonder if that deserves a comment.
Thanks,
NeilBrown
> }
> return dentry;
> }
> @@ -1837,7 +1837,7 @@ static unsigned int d_op_flags(const struct dentry_operations *op)
> return flags;
> }
>
> -void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op)
> +static void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op)
> {
> unsigned int flags = d_op_flags(op);
> WARN_ON_ONCE(dentry->d_op);
> @@ -1846,7 +1846,6 @@ void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op)
> if (flags)
> dentry->d_flags |= flags;
> }
> -EXPORT_SYMBOL(d_set_d_op);
>
> void set_default_d_op(struct super_block *s, const struct dentry_operations *ops)
> {
> diff --git a/include/linux/dcache.h b/include/linux/dcache.h
> index e8cf1d0fdd08..5a03e85f92a4 100644
> --- a/include/linux/dcache.h
> +++ b/include/linux/dcache.h
> @@ -242,7 +242,6 @@ extern void d_instantiate_new(struct dentry *, struct inode *);
> extern void __d_drop(struct dentry *dentry);
> extern void d_drop(struct dentry *dentry);
> extern void d_delete(struct dentry *);
> -extern void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op);
>
> /* allocate/de-allocate */
> extern struct dentry * d_alloc(struct dentry *, const struct qstr *);
> --
> 2.39.5
>
>
^ permalink raw reply [flat|nested] 87+ messages in thread* Re: [PATCH 09/21] make d_set_d_op() static
2025-02-24 21:20 ` [PATCH 09/21] make d_set_d_op() static Al Viro
2025-02-25 23:09 ` NeilBrown
@ 2025-02-26 8:35 ` Christian Brauner
1 sibling, 0 replies; 87+ messages in thread
From: Christian Brauner @ 2025-02-26 8:35 UTC (permalink / raw)
To: Al Viro; +Cc: linux-fsdevel, Linus Torvalds, Neil Brown, Miklos Szeredi,
Jan Kara
On Mon, Feb 24, 2025 at 09:20:39PM +0000, Al Viro wrote:
> Convert the last user (d_alloc_pseudo()) and be done with that.
> Any out-of-tree filesystem using it should switch to d_splice_alias_ops()
> or, better yet, check whether it really needs to have ->d_op vary among
> its dentries.
>
> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
> ---
Reviewed-by: Christian Brauner <brauner@kernel.org>
> Documentation/filesystems/porting.rst | 11 +++++++++++
> fs/dcache.c | 5 ++---
> include/linux/dcache.h | 1 -
> 3 files changed, 13 insertions(+), 4 deletions(-)
>
> diff --git a/Documentation/filesystems/porting.rst b/Documentation/filesystems/porting.rst
> index 004cd69617a2..61b5771dde53 100644
> --- a/Documentation/filesystems/porting.rst
> +++ b/Documentation/filesystems/porting.rst
> @@ -1164,3 +1164,14 @@ magic.
>
> If your filesystem sets the default dentry_operations, use set_default_d_op()
> rather than manually setting sb->s_d_op.
> +
> +---
> +
> +**mandatory**
> +
> +d_set_d_op() is no longer exported (or public, for that matter); _if_
> +your filesystem really needed that, make use of d_splice_alias_ops()
> +to have them set. Better yet, think hard whether you need different
> +->d_op for different dentries - if not, just use set_default_d_op()
> +at mount time and be done with that. Currently procfs is the only
> +thing that really needs ->d_op varying between dentries.
> diff --git a/fs/dcache.c b/fs/dcache.c
> index a4795617c3db..29db27228d97 100644
> --- a/fs/dcache.c
> +++ b/fs/dcache.c
> @@ -1796,7 +1796,7 @@ struct dentry *d_alloc_pseudo(struct super_block *sb, const struct qstr *name)
> if (likely(dentry)) {
> dentry->d_flags |= DCACHE_NORCU;
> if (!dentry->d_op)
> - d_set_d_op(dentry, &anon_ops);
> + dentry->d_op = &anon_ops;
> }
> return dentry;
> }
> @@ -1837,7 +1837,7 @@ static unsigned int d_op_flags(const struct dentry_operations *op)
> return flags;
> }
>
> -void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op)
> +static void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op)
> {
> unsigned int flags = d_op_flags(op);
> WARN_ON_ONCE(dentry->d_op);
> @@ -1846,7 +1846,6 @@ void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op)
> if (flags)
> dentry->d_flags |= flags;
> }
> -EXPORT_SYMBOL(d_set_d_op);
>
> void set_default_d_op(struct super_block *s, const struct dentry_operations *ops)
> {
> diff --git a/include/linux/dcache.h b/include/linux/dcache.h
> index e8cf1d0fdd08..5a03e85f92a4 100644
> --- a/include/linux/dcache.h
> +++ b/include/linux/dcache.h
> @@ -242,7 +242,6 @@ extern void d_instantiate_new(struct dentry *, struct inode *);
> extern void __d_drop(struct dentry *dentry);
> extern void d_drop(struct dentry *dentry);
> extern void d_delete(struct dentry *);
> -extern void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op);
>
> /* allocate/de-allocate */
> extern struct dentry * d_alloc(struct dentry *, const struct qstr *);
> --
> 2.39.5
>
^ permalink raw reply [flat|nested] 87+ messages in thread
* [PATCH 10/21] d_alloc_parallel(): set DCACHE_PAR_LOOKUP earlier
2025-02-24 21:20 ` [PATCH 01/21] procfs: kill ->proc_dops Al Viro
` (7 preceding siblings ...)
2025-02-24 21:20 ` [PATCH 09/21] make d_set_d_op() static Al Viro
@ 2025-02-24 21:20 ` Al Viro
2025-02-26 8:36 ` Christian Brauner
2025-02-24 21:20 ` [PATCH 11/21] nsfs, pidfs: drop the pointless ->d_delete() Al Viro
` (13 subsequent siblings)
22 siblings, 1 reply; 87+ messages in thread
From: Al Viro @ 2025-02-24 21:20 UTC (permalink / raw)
To: linux-fsdevel
Cc: Linus Torvalds, Christian Brauner, Neil Brown, Miklos Szeredi,
Jan Kara
Do that before new dentry is visible anywhere. It does create
a new possible state for dentries present in ->d_children/->d_sib -
DCACHE_PAR_LOOKUP present, negative, unhashed, not in in-lookup
hash chains, refcount positive. Those are going to be skipped
by all tree-walkers (both d_walk() callbacks in fs/dcache.c and
explicit loops over children/sibling lists elsewhere) and
dput() is fine with those.
NOTE: dropping the final reference to a "normal" in-lookup dentry
(in in-lookup hash) is a bug - somebody must've forgotten to
call d_lookup_done() on it and bad things will happen. With those
it's OK; if/when we get around to making __dentry_kill() complain
about such breakage, remember that predicate to check should
*not* be just d_in_lookup(victim) but rather a combination of that
with hlist_bl_unhashed(&victim->d_u.d_in_lookup_hash). Might
be worth to consider later...
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/dcache.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/fs/dcache.c b/fs/dcache.c
index 29db27228d97..9ad7cbb5a6b0 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -2518,13 +2518,19 @@ struct dentry *d_alloc_parallel(struct dentry *parent,
unsigned int hash = name->hash;
struct hlist_bl_head *b = in_lookup_hash(parent, hash);
struct hlist_bl_node *node;
- struct dentry *new = d_alloc(parent, name);
+ struct dentry *new = __d_alloc(parent->d_sb, name);
struct dentry *dentry;
unsigned seq, r_seq, d_seq;
if (unlikely(!new))
return ERR_PTR(-ENOMEM);
+ new->d_flags |= DCACHE_PAR_LOOKUP;
+ spin_lock(&parent->d_lock);
+ new->d_parent = dget_dlock(parent);
+ hlist_add_head(&new->d_sib, &parent->d_children);
+ spin_unlock(&parent->d_lock);
+
retry:
rcu_read_lock();
seq = smp_load_acquire(&parent->d_inode->i_dir_seq);
@@ -2608,8 +2614,6 @@ struct dentry *d_alloc_parallel(struct dentry *parent,
return dentry;
}
rcu_read_unlock();
- /* we can't take ->d_lock here; it's OK, though. */
- new->d_flags |= DCACHE_PAR_LOOKUP;
new->d_wait = wq;
hlist_bl_add_head(&new->d_u.d_in_lookup_hash, b);
hlist_bl_unlock(b);
--
2.39.5
^ permalink raw reply related [flat|nested] 87+ messages in thread* Re: [PATCH 10/21] d_alloc_parallel(): set DCACHE_PAR_LOOKUP earlier
2025-02-24 21:20 ` [PATCH 10/21] d_alloc_parallel(): set DCACHE_PAR_LOOKUP earlier Al Viro
@ 2025-02-26 8:36 ` Christian Brauner
0 siblings, 0 replies; 87+ messages in thread
From: Christian Brauner @ 2025-02-26 8:36 UTC (permalink / raw)
To: Al Viro; +Cc: linux-fsdevel, Linus Torvalds, Neil Brown, Miklos Szeredi,
Jan Kara
On Mon, Feb 24, 2025 at 09:20:40PM +0000, Al Viro wrote:
> Do that before new dentry is visible anywhere. It does create
> a new possible state for dentries present in ->d_children/->d_sib -
> DCACHE_PAR_LOOKUP present, negative, unhashed, not in in-lookup
> hash chains, refcount positive. Those are going to be skipped
> by all tree-walkers (both d_walk() callbacks in fs/dcache.c and
> explicit loops over children/sibling lists elsewhere) and
> dput() is fine with those.
>
> NOTE: dropping the final reference to a "normal" in-lookup dentry
> (in in-lookup hash) is a bug - somebody must've forgotten to
> call d_lookup_done() on it and bad things will happen. With those
> it's OK; if/when we get around to making __dentry_kill() complain
> about such breakage, remember that predicate to check should
> *not* be just d_in_lookup(victim) but rather a combination of that
> with hlist_bl_unhashed(&victim->d_u.d_in_lookup_hash). Might
> be worth to consider later...
>
> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
> ---
Reviewed-by: Christian Brauner <brauner@kernel.org>
> fs/dcache.c | 10 +++++++---
> 1 file changed, 7 insertions(+), 3 deletions(-)
>
> diff --git a/fs/dcache.c b/fs/dcache.c
> index 29db27228d97..9ad7cbb5a6b0 100644
> --- a/fs/dcache.c
> +++ b/fs/dcache.c
> @@ -2518,13 +2518,19 @@ struct dentry *d_alloc_parallel(struct dentry *parent,
> unsigned int hash = name->hash;
> struct hlist_bl_head *b = in_lookup_hash(parent, hash);
> struct hlist_bl_node *node;
> - struct dentry *new = d_alloc(parent, name);
> + struct dentry *new = __d_alloc(parent->d_sb, name);
> struct dentry *dentry;
> unsigned seq, r_seq, d_seq;
>
> if (unlikely(!new))
> return ERR_PTR(-ENOMEM);
This is minor but it would be clearer if the __d_alloc() call was placed
directly above the error handling.
>
> + new->d_flags |= DCACHE_PAR_LOOKUP;
> + spin_lock(&parent->d_lock);
> + new->d_parent = dget_dlock(parent);
> + hlist_add_head(&new->d_sib, &parent->d_children);
> + spin_unlock(&parent->d_lock);
> +
> retry:
> rcu_read_lock();
> seq = smp_load_acquire(&parent->d_inode->i_dir_seq);
> @@ -2608,8 +2614,6 @@ struct dentry *d_alloc_parallel(struct dentry *parent,
> return dentry;
> }
> rcu_read_unlock();
> - /* we can't take ->d_lock here; it's OK, though. */
> - new->d_flags |= DCACHE_PAR_LOOKUP;
> new->d_wait = wq;
> hlist_bl_add_head(&new->d_u.d_in_lookup_hash, b);
> hlist_bl_unlock(b);
> --
> 2.39.5
>
^ permalink raw reply [flat|nested] 87+ messages in thread
* [PATCH 11/21] nsfs, pidfs: drop the pointless ->d_delete()
2025-02-24 21:20 ` [PATCH 01/21] procfs: kill ->proc_dops Al Viro
` (8 preceding siblings ...)
2025-02-24 21:20 ` [PATCH 10/21] d_alloc_parallel(): set DCACHE_PAR_LOOKUP earlier Al Viro
@ 2025-02-24 21:20 ` Al Viro
2025-02-26 8:37 ` Christian Brauner
2025-02-24 21:20 ` [PATCH 12/21] shmem: no dentry retention past the refcount reaching zero Al Viro
` (12 subsequent siblings)
22 siblings, 1 reply; 87+ messages in thread
From: Al Viro @ 2025-02-24 21:20 UTC (permalink / raw)
To: linux-fsdevel
Cc: Linus Torvalds, Christian Brauner, Neil Brown, Miklos Szeredi,
Jan Kara
No dentries are ever hashed on those, so ->d_delete() wouldn't be
even looked at. If it's unhashed, we are not retaining it in dcache
once the refcount hits zero, no matter what.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/nsfs.c | 1 -
fs/pidfs.c | 1 -
2 files changed, 2 deletions(-)
diff --git a/fs/nsfs.c b/fs/nsfs.c
index 663f8656158d..f7fddf8ecf73 100644
--- a/fs/nsfs.c
+++ b/fs/nsfs.c
@@ -37,7 +37,6 @@ static char *ns_dname(struct dentry *dentry, char *buffer, int buflen)
}
const struct dentry_operations ns_dentry_operations = {
- .d_delete = always_delete_dentry,
.d_dname = ns_dname,
.d_prune = stashed_dentry_prune,
};
diff --git a/fs/pidfs.c b/fs/pidfs.c
index 63f9699ebac3..c0478b3c55d9 100644
--- a/fs/pidfs.c
+++ b/fs/pidfs.c
@@ -521,7 +521,6 @@ static char *pidfs_dname(struct dentry *dentry, char *buffer, int buflen)
}
const struct dentry_operations pidfs_dentry_operations = {
- .d_delete = always_delete_dentry,
.d_dname = pidfs_dname,
.d_prune = stashed_dentry_prune,
};
--
2.39.5
^ permalink raw reply related [flat|nested] 87+ messages in thread* Re: [PATCH 11/21] nsfs, pidfs: drop the pointless ->d_delete()
2025-02-24 21:20 ` [PATCH 11/21] nsfs, pidfs: drop the pointless ->d_delete() Al Viro
@ 2025-02-26 8:37 ` Christian Brauner
0 siblings, 0 replies; 87+ messages in thread
From: Christian Brauner @ 2025-02-26 8:37 UTC (permalink / raw)
To: Al Viro; +Cc: linux-fsdevel, Linus Torvalds, Neil Brown, Miklos Szeredi,
Jan Kara
On Mon, Feb 24, 2025 at 09:20:41PM +0000, Al Viro wrote:
> No dentries are ever hashed on those, so ->d_delete() wouldn't be
> even looked at. If it's unhashed, we are not retaining it in dcache
> once the refcount hits zero, no matter what.
>
> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
> ---
Patches to remove this have already been merged into mainline.
> fs/nsfs.c | 1 -
> fs/pidfs.c | 1 -
> 2 files changed, 2 deletions(-)
>
> diff --git a/fs/nsfs.c b/fs/nsfs.c
> index 663f8656158d..f7fddf8ecf73 100644
> --- a/fs/nsfs.c
> +++ b/fs/nsfs.c
> @@ -37,7 +37,6 @@ static char *ns_dname(struct dentry *dentry, char *buffer, int buflen)
> }
>
> const struct dentry_operations ns_dentry_operations = {
> - .d_delete = always_delete_dentry,
> .d_dname = ns_dname,
> .d_prune = stashed_dentry_prune,
> };
> diff --git a/fs/pidfs.c b/fs/pidfs.c
> index 63f9699ebac3..c0478b3c55d9 100644
> --- a/fs/pidfs.c
> +++ b/fs/pidfs.c
> @@ -521,7 +521,6 @@ static char *pidfs_dname(struct dentry *dentry, char *buffer, int buflen)
> }
>
> const struct dentry_operations pidfs_dentry_operations = {
> - .d_delete = always_delete_dentry,
> .d_dname = pidfs_dname,
> .d_prune = stashed_dentry_prune,
> };
> --
> 2.39.5
>
^ permalink raw reply [flat|nested] 87+ messages in thread
* [PATCH 12/21] shmem: no dentry retention past the refcount reaching zero
2025-02-24 21:20 ` [PATCH 01/21] procfs: kill ->proc_dops Al Viro
` (9 preceding siblings ...)
2025-02-24 21:20 ` [PATCH 11/21] nsfs, pidfs: drop the pointless ->d_delete() Al Viro
@ 2025-02-24 21:20 ` Al Viro
2025-02-26 8:38 ` Christian Brauner
2025-02-24 21:20 ` [PATCH 13/21] devpts, sunrpc: don't bother with ->d_delete or ->d_op, for that matter Al Viro
` (11 subsequent siblings)
22 siblings, 1 reply; 87+ messages in thread
From: Al Viro @ 2025-02-24 21:20 UTC (permalink / raw)
To: linux-fsdevel
Cc: Linus Torvalds, Christian Brauner, Neil Brown, Miklos Szeredi,
Jan Kara
Just set DCACHE_DONTCACHE in ->s_d_flags and be done with that.
Dentries there live for as long as they are pinned; once the
refcount hits zero, that's it. The same, of course, goes for
other tree-in-dcache filesystems - more in the next commits...
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
mm/shmem.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mm/shmem.c b/mm/shmem.c
index 0ecb49113bb2..dd84b1c554a8 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -4971,7 +4971,6 @@ static void shmem_put_super(struct super_block *sb)
static const struct dentry_operations shmem_ci_dentry_ops = {
.d_hash = generic_ci_d_hash,
.d_compare = generic_ci_d_compare,
- .d_delete = always_delete_dentry,
};
#endif
@@ -5028,6 +5027,7 @@ static int shmem_fill_super(struct super_block *sb, struct fs_context *fc)
#else
sb->s_flags |= SB_NOUSER;
#endif /* CONFIG_TMPFS */
+ sb->s_d_flags |= DCACHE_DONTCACHE;
sbinfo->max_blocks = ctx->blocks;
sbinfo->max_inodes = ctx->inodes;
sbinfo->free_ispace = sbinfo->max_inodes * BOGO_INODE_SIZE;
--
2.39.5
^ permalink raw reply related [flat|nested] 87+ messages in thread* Re: [PATCH 12/21] shmem: no dentry retention past the refcount reaching zero
2025-02-24 21:20 ` [PATCH 12/21] shmem: no dentry retention past the refcount reaching zero Al Viro
@ 2025-02-26 8:38 ` Christian Brauner
0 siblings, 0 replies; 87+ messages in thread
From: Christian Brauner @ 2025-02-26 8:38 UTC (permalink / raw)
To: Al Viro; +Cc: linux-fsdevel, Linus Torvalds, Neil Brown, Miklos Szeredi,
Jan Kara
On Mon, Feb 24, 2025 at 09:20:42PM +0000, Al Viro wrote:
> Just set DCACHE_DONTCACHE in ->s_d_flags and be done with that.
> Dentries there live for as long as they are pinned; once the
> refcount hits zero, that's it. The same, of course, goes for
> other tree-in-dcache filesystems - more in the next commits...
>
> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
> ---
Reviewed-by: Christian Brauner <brauner@kernel.org>
> mm/shmem.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/mm/shmem.c b/mm/shmem.c
> index 0ecb49113bb2..dd84b1c554a8 100644
> --- a/mm/shmem.c
> +++ b/mm/shmem.c
> @@ -4971,7 +4971,6 @@ static void shmem_put_super(struct super_block *sb)
> static const struct dentry_operations shmem_ci_dentry_ops = {
> .d_hash = generic_ci_d_hash,
> .d_compare = generic_ci_d_compare,
> - .d_delete = always_delete_dentry,
> };
> #endif
>
> @@ -5028,6 +5027,7 @@ static int shmem_fill_super(struct super_block *sb, struct fs_context *fc)
> #else
> sb->s_flags |= SB_NOUSER;
> #endif /* CONFIG_TMPFS */
> + sb->s_d_flags |= DCACHE_DONTCACHE;
> sbinfo->max_blocks = ctx->blocks;
> sbinfo->max_inodes = ctx->inodes;
> sbinfo->free_ispace = sbinfo->max_inodes * BOGO_INODE_SIZE;
> --
> 2.39.5
>
^ permalink raw reply [flat|nested] 87+ messages in thread
* [PATCH 13/21] devpts, sunrpc: don't bother with ->d_delete or ->d_op, for that matter
2025-02-24 21:20 ` [PATCH 01/21] procfs: kill ->proc_dops Al Viro
` (10 preceding siblings ...)
2025-02-24 21:20 ` [PATCH 12/21] shmem: no dentry retention past the refcount reaching zero Al Viro
@ 2025-02-24 21:20 ` Al Viro
2025-02-26 8:38 ` Christian Brauner
2025-02-24 21:20 ` [PATCH 14/21] hostfs: don't bother with ->d_op Al Viro
` (10 subsequent siblings)
22 siblings, 1 reply; 87+ messages in thread
From: Al Viro @ 2025-02-24 21:20 UTC (permalink / raw)
To: linux-fsdevel
Cc: Linus Torvalds, Christian Brauner, Neil Brown, Miklos Szeredi,
Jan Kara
Just put DCACHE_DONTCACHE into ->s_d_flags.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/devpts/inode.c | 2 +-
net/sunrpc/rpc_pipe.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
index f092973236ef..39344af02d1f 100644
--- a/fs/devpts/inode.c
+++ b/fs/devpts/inode.c
@@ -433,7 +433,7 @@ devpts_fill_super(struct super_block *s, void *data, int silent)
s->s_blocksize_bits = 10;
s->s_magic = DEVPTS_SUPER_MAGIC;
s->s_op = &devpts_sops;
- set_default_d_op(s, &simple_dentry_operations);
+ s->s_d_flags = DCACHE_DONTCACHE;
s->s_time_gran = 1;
error = -ENOMEM;
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index e093e4cf20fa..acb28a502580 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -1363,7 +1363,7 @@ rpc_fill_super(struct super_block *sb, struct fs_context *fc)
sb->s_blocksize_bits = PAGE_SHIFT;
sb->s_magic = RPCAUTH_GSSMAGIC;
sb->s_op = &s_ops;
- set_default_d_op(sb, &simple_dentry_operations);
+ sb->s_d_flags = DCACHE_DONTCACHE;
sb->s_time_gran = 1;
inode = rpc_get_inode(sb, S_IFDIR | 0555);
--
2.39.5
^ permalink raw reply related [flat|nested] 87+ messages in thread* Re: [PATCH 13/21] devpts, sunrpc: don't bother with ->d_delete or ->d_op, for that matter
2025-02-24 21:20 ` [PATCH 13/21] devpts, sunrpc: don't bother with ->d_delete or ->d_op, for that matter Al Viro
@ 2025-02-26 8:38 ` Christian Brauner
0 siblings, 0 replies; 87+ messages in thread
From: Christian Brauner @ 2025-02-26 8:38 UTC (permalink / raw)
To: Al Viro; +Cc: linux-fsdevel, Linus Torvalds, Neil Brown, Miklos Szeredi,
Jan Kara
On Mon, Feb 24, 2025 at 09:20:43PM +0000, Al Viro wrote:
> Just put DCACHE_DONTCACHE into ->s_d_flags.
>
> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
> ---
Reviewed-by: Christian Brauner <brauner@kernel.org>
> fs/devpts/inode.c | 2 +-
> net/sunrpc/rpc_pipe.c | 2 +-
> 2 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
> index f092973236ef..39344af02d1f 100644
> --- a/fs/devpts/inode.c
> +++ b/fs/devpts/inode.c
> @@ -433,7 +433,7 @@ devpts_fill_super(struct super_block *s, void *data, int silent)
> s->s_blocksize_bits = 10;
> s->s_magic = DEVPTS_SUPER_MAGIC;
> s->s_op = &devpts_sops;
> - set_default_d_op(s, &simple_dentry_operations);
> + s->s_d_flags = DCACHE_DONTCACHE;
> s->s_time_gran = 1;
>
> error = -ENOMEM;
> diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
> index e093e4cf20fa..acb28a502580 100644
> --- a/net/sunrpc/rpc_pipe.c
> +++ b/net/sunrpc/rpc_pipe.c
> @@ -1363,7 +1363,7 @@ rpc_fill_super(struct super_block *sb, struct fs_context *fc)
> sb->s_blocksize_bits = PAGE_SHIFT;
> sb->s_magic = RPCAUTH_GSSMAGIC;
> sb->s_op = &s_ops;
> - set_default_d_op(sb, &simple_dentry_operations);
> + sb->s_d_flags = DCACHE_DONTCACHE;
> sb->s_time_gran = 1;
>
> inode = rpc_get_inode(sb, S_IFDIR | 0555);
> --
> 2.39.5
>
^ permalink raw reply [flat|nested] 87+ messages in thread
* [PATCH 14/21] hostfs: don't bother with ->d_op
2025-02-24 21:20 ` [PATCH 01/21] procfs: kill ->proc_dops Al Viro
` (11 preceding siblings ...)
2025-02-24 21:20 ` [PATCH 13/21] devpts, sunrpc: don't bother with ->d_delete or ->d_op, for that matter Al Viro
@ 2025-02-24 21:20 ` Al Viro
2025-02-26 8:38 ` Christian Brauner
2025-02-24 21:20 ` [PATCH 15/21] kill simple_dentry_operations Al Viro
` (9 subsequent siblings)
22 siblings, 1 reply; 87+ messages in thread
From: Al Viro @ 2025-02-24 21:20 UTC (permalink / raw)
To: linux-fsdevel
Cc: Linus Torvalds, Christian Brauner, Neil Brown, Miklos Szeredi,
Jan Kara
All we have there is ->d_delete equal to always_delete_dentry() and we
want that for all dentries on that things. Setting DCACHE_DONTCACHE in
->s_d_flags will do just that.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/hostfs/hostfs_kern.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index a0e0563a29d7..52479205cefe 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -920,7 +920,7 @@ static int hostfs_fill_super(struct super_block *sb, struct fs_context *fc)
sb->s_blocksize_bits = 10;
sb->s_magic = HOSTFS_SUPER_MAGIC;
sb->s_op = &hostfs_sbops;
- set_default_d_op(sb, &simple_dentry_operations);
+ sb->s_d_flags = DCACHE_DONTCACHE;
sb->s_maxbytes = MAX_LFS_FILESIZE;
err = super_setup_bdi(sb);
if (err)
--
2.39.5
^ permalink raw reply related [flat|nested] 87+ messages in thread* Re: [PATCH 14/21] hostfs: don't bother with ->d_op
2025-02-24 21:20 ` [PATCH 14/21] hostfs: don't bother with ->d_op Al Viro
@ 2025-02-26 8:38 ` Christian Brauner
0 siblings, 0 replies; 87+ messages in thread
From: Christian Brauner @ 2025-02-26 8:38 UTC (permalink / raw)
To: Al Viro; +Cc: linux-fsdevel, Linus Torvalds, Neil Brown, Miklos Szeredi,
Jan Kara
On Mon, Feb 24, 2025 at 09:20:44PM +0000, Al Viro wrote:
> All we have there is ->d_delete equal to always_delete_dentry() and we
> want that for all dentries on that things. Setting DCACHE_DONTCACHE in
> ->s_d_flags will do just that.
>
> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
> ---
Reviewed-by: Christian Brauner <brauner@kernel.org>
> fs/hostfs/hostfs_kern.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
> index a0e0563a29d7..52479205cefe 100644
> --- a/fs/hostfs/hostfs_kern.c
> +++ b/fs/hostfs/hostfs_kern.c
> @@ -920,7 +920,7 @@ static int hostfs_fill_super(struct super_block *sb, struct fs_context *fc)
> sb->s_blocksize_bits = 10;
> sb->s_magic = HOSTFS_SUPER_MAGIC;
> sb->s_op = &hostfs_sbops;
> - set_default_d_op(sb, &simple_dentry_operations);
> + sb->s_d_flags = DCACHE_DONTCACHE;
> sb->s_maxbytes = MAX_LFS_FILESIZE;
> err = super_setup_bdi(sb);
> if (err)
> --
> 2.39.5
>
^ permalink raw reply [flat|nested] 87+ messages in thread
* [PATCH 15/21] kill simple_dentry_operations
2025-02-24 21:20 ` [PATCH 01/21] procfs: kill ->proc_dops Al Viro
` (12 preceding siblings ...)
2025-02-24 21:20 ` [PATCH 14/21] hostfs: don't bother with ->d_op Al Viro
@ 2025-02-24 21:20 ` Al Viro
2025-02-26 8:39 ` Christian Brauner
2025-02-24 21:20 ` [PATCH 16/21] ramfs, hugetlbfs, mqueue: set DCACHE_DONTCACHE Al Viro
` (8 subsequent siblings)
22 siblings, 1 reply; 87+ messages in thread
From: Al Viro @ 2025-02-24 21:20 UTC (permalink / raw)
To: linux-fsdevel
Cc: Linus Torvalds, Christian Brauner, Neil Brown, Miklos Szeredi,
Jan Kara
No users left and anything that wants it would be better off just
setting DCACHE_DONTCACHE in their ->s_d_flags.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/libfs.c | 5 -----
include/linux/fs.h | 1 -
2 files changed, 6 deletions(-)
diff --git a/fs/libfs.c b/fs/libfs.c
index b15a2148714e..7eebaee9d082 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -62,11 +62,6 @@ int always_delete_dentry(const struct dentry *dentry)
}
EXPORT_SYMBOL(always_delete_dentry);
-const struct dentry_operations simple_dentry_operations = {
- .d_delete = always_delete_dentry,
-};
-EXPORT_SYMBOL(simple_dentry_operations);
-
/*
* Lookup the data. This is trivial - if the dentry didn't already
* exist, we know it is negative. Set d_op to delete negative dentries.
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 473a9de5fc8f..bdaf2f85e1ad 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -3540,7 +3540,6 @@ extern const struct address_space_operations ram_aops;
extern int always_delete_dentry(const struct dentry *);
extern struct inode *alloc_anon_inode(struct super_block *);
extern int simple_nosetlease(struct file *, int, struct file_lease **, void **);
-extern const struct dentry_operations simple_dentry_operations;
extern struct dentry *simple_lookup(struct inode *, struct dentry *, unsigned int flags);
extern ssize_t generic_read_dir(struct file *, char __user *, size_t, loff_t *);
--
2.39.5
^ permalink raw reply related [flat|nested] 87+ messages in thread* Re: [PATCH 15/21] kill simple_dentry_operations
2025-02-24 21:20 ` [PATCH 15/21] kill simple_dentry_operations Al Viro
@ 2025-02-26 8:39 ` Christian Brauner
0 siblings, 0 replies; 87+ messages in thread
From: Christian Brauner @ 2025-02-26 8:39 UTC (permalink / raw)
To: Al Viro; +Cc: linux-fsdevel, Linus Torvalds, Neil Brown, Miklos Szeredi,
Jan Kara
On Mon, Feb 24, 2025 at 09:20:45PM +0000, Al Viro wrote:
> No users left and anything that wants it would be better off just
> setting DCACHE_DONTCACHE in their ->s_d_flags.
>
> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
> ---
Reviewed-by: Christian Brauner <brauner@kernel.org>
> fs/libfs.c | 5 -----
> include/linux/fs.h | 1 -
> 2 files changed, 6 deletions(-)
>
> diff --git a/fs/libfs.c b/fs/libfs.c
> index b15a2148714e..7eebaee9d082 100644
> --- a/fs/libfs.c
> +++ b/fs/libfs.c
> @@ -62,11 +62,6 @@ int always_delete_dentry(const struct dentry *dentry)
> }
> EXPORT_SYMBOL(always_delete_dentry);
>
> -const struct dentry_operations simple_dentry_operations = {
> - .d_delete = always_delete_dentry,
> -};
> -EXPORT_SYMBOL(simple_dentry_operations);
> -
> /*
> * Lookup the data. This is trivial - if the dentry didn't already
> * exist, we know it is negative. Set d_op to delete negative dentries.
> diff --git a/include/linux/fs.h b/include/linux/fs.h
> index 473a9de5fc8f..bdaf2f85e1ad 100644
> --- a/include/linux/fs.h
> +++ b/include/linux/fs.h
> @@ -3540,7 +3540,6 @@ extern const struct address_space_operations ram_aops;
> extern int always_delete_dentry(const struct dentry *);
> extern struct inode *alloc_anon_inode(struct super_block *);
> extern int simple_nosetlease(struct file *, int, struct file_lease **, void **);
> -extern const struct dentry_operations simple_dentry_operations;
>
> extern struct dentry *simple_lookup(struct inode *, struct dentry *, unsigned int flags);
> extern ssize_t generic_read_dir(struct file *, char __user *, size_t, loff_t *);
> --
> 2.39.5
>
^ permalink raw reply [flat|nested] 87+ messages in thread
* [PATCH 16/21] ramfs, hugetlbfs, mqueue: set DCACHE_DONTCACHE
2025-02-24 21:20 ` [PATCH 01/21] procfs: kill ->proc_dops Al Viro
` (13 preceding siblings ...)
2025-02-24 21:20 ` [PATCH 15/21] kill simple_dentry_operations Al Viro
@ 2025-02-24 21:20 ` Al Viro
2025-02-25 23:25 ` NeilBrown
2025-02-26 8:39 ` Christian Brauner
2025-02-24 21:20 ` [PATCH 17/21] 9p: don't bother with always_delete_dentry Al Viro
` (7 subsequent siblings)
22 siblings, 2 replies; 87+ messages in thread
From: Al Viro @ 2025-02-24 21:20 UTC (permalink / raw)
To: linux-fsdevel
Cc: Linus Torvalds, Christian Brauner, Neil Brown, Miklos Szeredi,
Jan Kara
makes simple_lookup() slightly cheaper there.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/hugetlbfs/inode.c | 1 +
fs/ramfs/inode.c | 1 +
ipc/mqueue.c | 1 +
3 files changed, 3 insertions(+)
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 0fc179a59830..205dd7562be1 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -1431,6 +1431,7 @@ hugetlbfs_fill_super(struct super_block *sb, struct fs_context *fc)
sb->s_blocksize_bits = huge_page_shift(ctx->hstate);
sb->s_magic = HUGETLBFS_MAGIC;
sb->s_op = &hugetlbfs_ops;
+ sb->s_d_flags = DCACHE_DONTCACHE;
sb->s_time_gran = 1;
/*
diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c
index 8006faaaf0ec..c4ee67870c4b 100644
--- a/fs/ramfs/inode.c
+++ b/fs/ramfs/inode.c
@@ -269,6 +269,7 @@ static int ramfs_fill_super(struct super_block *sb, struct fs_context *fc)
sb->s_blocksize_bits = PAGE_SHIFT;
sb->s_magic = RAMFS_MAGIC;
sb->s_op = &ramfs_ops;
+ sb->s_d_flags = DCACHE_DONTCACHE;
sb->s_time_gran = 1;
inode = ramfs_get_inode(sb, NULL, S_IFDIR | fsi->mount_opts.mode, 0);
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index 35b4f8659904..dbd5c74eecb2 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -411,6 +411,7 @@ static int mqueue_fill_super(struct super_block *sb, struct fs_context *fc)
sb->s_blocksize_bits = PAGE_SHIFT;
sb->s_magic = MQUEUE_MAGIC;
sb->s_op = &mqueue_super_ops;
+ sb->s_d_flags = DCACHE_DONTCACHE;
inode = mqueue_get_inode(sb, ns, S_IFDIR | S_ISVTX | S_IRWXUGO, NULL);
if (IS_ERR(inode))
--
2.39.5
^ permalink raw reply related [flat|nested] 87+ messages in thread* Re: [PATCH 16/21] ramfs, hugetlbfs, mqueue: set DCACHE_DONTCACHE
2025-02-24 21:20 ` [PATCH 16/21] ramfs, hugetlbfs, mqueue: set DCACHE_DONTCACHE Al Viro
@ 2025-02-25 23:25 ` NeilBrown
2025-02-25 23:36 ` Al Viro
2025-02-26 8:39 ` Christian Brauner
1 sibling, 1 reply; 87+ messages in thread
From: NeilBrown @ 2025-02-25 23:25 UTC (permalink / raw)
To: Al Viro
Cc: linux-fsdevel, Linus Torvalds, Christian Brauner, Miklos Szeredi,
Jan Kara
On Tue, 25 Feb 2025, Al Viro wrote:
> makes simple_lookup() slightly cheaper there.
I think the patch make sense because there is no point keeping negative
dentries for these filesystems - and positive dentries get an extra
refcount so DCACHE_DONTCACHE doesn't apply.
But I don't see how this makes simple_lookup() cheaper. It means that
if someone repeatedly looks up the same non-existent name then
simple_lookup() will be called more often (because we didn't cache the
result of the previous time) but otherwise I don't see the relevance to
simple_lookup(). Am I missing something?
Thanks,
NeilBrown
>
> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
> ---
> fs/hugetlbfs/inode.c | 1 +
> fs/ramfs/inode.c | 1 +
> ipc/mqueue.c | 1 +
> 3 files changed, 3 insertions(+)
>
> diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
> index 0fc179a59830..205dd7562be1 100644
> --- a/fs/hugetlbfs/inode.c
> +++ b/fs/hugetlbfs/inode.c
> @@ -1431,6 +1431,7 @@ hugetlbfs_fill_super(struct super_block *sb, struct fs_context *fc)
> sb->s_blocksize_bits = huge_page_shift(ctx->hstate);
> sb->s_magic = HUGETLBFS_MAGIC;
> sb->s_op = &hugetlbfs_ops;
> + sb->s_d_flags = DCACHE_DONTCACHE;
> sb->s_time_gran = 1;
>
> /*
> diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c
> index 8006faaaf0ec..c4ee67870c4b 100644
> --- a/fs/ramfs/inode.c
> +++ b/fs/ramfs/inode.c
> @@ -269,6 +269,7 @@ static int ramfs_fill_super(struct super_block *sb, struct fs_context *fc)
> sb->s_blocksize_bits = PAGE_SHIFT;
> sb->s_magic = RAMFS_MAGIC;
> sb->s_op = &ramfs_ops;
> + sb->s_d_flags = DCACHE_DONTCACHE;
> sb->s_time_gran = 1;
>
> inode = ramfs_get_inode(sb, NULL, S_IFDIR | fsi->mount_opts.mode, 0);
> diff --git a/ipc/mqueue.c b/ipc/mqueue.c
> index 35b4f8659904..dbd5c74eecb2 100644
> --- a/ipc/mqueue.c
> +++ b/ipc/mqueue.c
> @@ -411,6 +411,7 @@ static int mqueue_fill_super(struct super_block *sb, struct fs_context *fc)
> sb->s_blocksize_bits = PAGE_SHIFT;
> sb->s_magic = MQUEUE_MAGIC;
> sb->s_op = &mqueue_super_ops;
> + sb->s_d_flags = DCACHE_DONTCACHE;
>
> inode = mqueue_get_inode(sb, ns, S_IFDIR | S_ISVTX | S_IRWXUGO, NULL);
> if (IS_ERR(inode))
> --
> 2.39.5
>
>
^ permalink raw reply [flat|nested] 87+ messages in thread
* Re: [PATCH 16/21] ramfs, hugetlbfs, mqueue: set DCACHE_DONTCACHE
2025-02-25 23:25 ` NeilBrown
@ 2025-02-25 23:36 ` Al Viro
2025-02-25 23:40 ` NeilBrown
0 siblings, 1 reply; 87+ messages in thread
From: Al Viro @ 2025-02-25 23:36 UTC (permalink / raw)
To: NeilBrown
Cc: linux-fsdevel, Linus Torvalds, Christian Brauner, Miklos Szeredi,
Jan Kara
On Wed, Feb 26, 2025 at 10:25:12AM +1100, NeilBrown wrote:
> On Tue, 25 Feb 2025, Al Viro wrote:
> > makes simple_lookup() slightly cheaper there.
>
> I think the patch make sense because there is no point keeping negative
> dentries for these filesystems - and positive dentries get an extra
> refcount so DCACHE_DONTCACHE doesn't apply.
>
> But I don't see how this makes simple_lookup() cheaper. It means that
> if someone repeatedly looks up the same non-existent name then
> simple_lookup() will be called more often (because we didn't cache the
> result of the previous time) but otherwise I don't see the relevance to
> simple_lookup(). Am I missing something?
This:
if (!(dentry->d_flags & DCACHE_DONTCACHE)) {
spin_lock(&dentry->d_lock);
dentry->d_flags |= DCACHE_DONTCACHE;
spin_unlock(&dentry->d_lock);
}
IOW, no need to mark that sucker as "don't retain past the moment when
its refcount drops to zero" - they'll all be marked that way since
they'd been created.
Note that we used to switch then to ->d_op that had ->d_delete always
returning true. That had been replaced with setting DCACHE_DONTCACHE;
that was an equivalent transformation. So retention rules have not changed;
the only change here is that this flag doesn't need to be set.
^ permalink raw reply [flat|nested] 87+ messages in thread* Re: [PATCH 16/21] ramfs, hugetlbfs, mqueue: set DCACHE_DONTCACHE
2025-02-25 23:36 ` Al Viro
@ 2025-02-25 23:40 ` NeilBrown
0 siblings, 0 replies; 87+ messages in thread
From: NeilBrown @ 2025-02-25 23:40 UTC (permalink / raw)
To: Al Viro
Cc: linux-fsdevel, Linus Torvalds, Christian Brauner, Miklos Szeredi,
Jan Kara
On Wed, 26 Feb 2025, Al Viro wrote:
> On Wed, Feb 26, 2025 at 10:25:12AM +1100, NeilBrown wrote:
> > On Tue, 25 Feb 2025, Al Viro wrote:
> > > makes simple_lookup() slightly cheaper there.
> >
> > I think the patch make sense because there is no point keeping negative
> > dentries for these filesystems - and positive dentries get an extra
> > refcount so DCACHE_DONTCACHE doesn't apply.
> >
> > But I don't see how this makes simple_lookup() cheaper. It means that
> > if someone repeatedly looks up the same non-existent name then
> > simple_lookup() will be called more often (because we didn't cache the
> > result of the previous time) but otherwise I don't see the relevance to
> > simple_lookup(). Am I missing something?
>
> This:
> if (!(dentry->d_flags & DCACHE_DONTCACHE)) {
> spin_lock(&dentry->d_lock);
> dentry->d_flags |= DCACHE_DONTCACHE;
> spin_unlock(&dentry->d_lock);
> }
Ah - right. Thanks.
NeilBrown
>
> IOW, no need to mark that sucker as "don't retain past the moment when
> its refcount drops to zero" - they'll all be marked that way since
> they'd been created.
>
> Note that we used to switch then to ->d_op that had ->d_delete always
> returning true. That had been replaced with setting DCACHE_DONTCACHE;
> that was an equivalent transformation. So retention rules have not changed;
> the only change here is that this flag doesn't need to be set.
>
^ permalink raw reply [flat|nested] 87+ messages in thread
* Re: [PATCH 16/21] ramfs, hugetlbfs, mqueue: set DCACHE_DONTCACHE
2025-02-24 21:20 ` [PATCH 16/21] ramfs, hugetlbfs, mqueue: set DCACHE_DONTCACHE Al Viro
2025-02-25 23:25 ` NeilBrown
@ 2025-02-26 8:39 ` Christian Brauner
1 sibling, 0 replies; 87+ messages in thread
From: Christian Brauner @ 2025-02-26 8:39 UTC (permalink / raw)
To: Al Viro; +Cc: linux-fsdevel, Linus Torvalds, Neil Brown, Miklos Szeredi,
Jan Kara
On Mon, Feb 24, 2025 at 09:20:46PM +0000, Al Viro wrote:
> makes simple_lookup() slightly cheaper there.
>
> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
> ---
Reviewed-by: Christian Brauner <brauner@kernel.org>
> fs/hugetlbfs/inode.c | 1 +
> fs/ramfs/inode.c | 1 +
> ipc/mqueue.c | 1 +
> 3 files changed, 3 insertions(+)
>
> diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
> index 0fc179a59830..205dd7562be1 100644
> --- a/fs/hugetlbfs/inode.c
> +++ b/fs/hugetlbfs/inode.c
> @@ -1431,6 +1431,7 @@ hugetlbfs_fill_super(struct super_block *sb, struct fs_context *fc)
> sb->s_blocksize_bits = huge_page_shift(ctx->hstate);
> sb->s_magic = HUGETLBFS_MAGIC;
> sb->s_op = &hugetlbfs_ops;
> + sb->s_d_flags = DCACHE_DONTCACHE;
> sb->s_time_gran = 1;
>
> /*
> diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c
> index 8006faaaf0ec..c4ee67870c4b 100644
> --- a/fs/ramfs/inode.c
> +++ b/fs/ramfs/inode.c
> @@ -269,6 +269,7 @@ static int ramfs_fill_super(struct super_block *sb, struct fs_context *fc)
> sb->s_blocksize_bits = PAGE_SHIFT;
> sb->s_magic = RAMFS_MAGIC;
> sb->s_op = &ramfs_ops;
> + sb->s_d_flags = DCACHE_DONTCACHE;
> sb->s_time_gran = 1;
>
> inode = ramfs_get_inode(sb, NULL, S_IFDIR | fsi->mount_opts.mode, 0);
> diff --git a/ipc/mqueue.c b/ipc/mqueue.c
> index 35b4f8659904..dbd5c74eecb2 100644
> --- a/ipc/mqueue.c
> +++ b/ipc/mqueue.c
> @@ -411,6 +411,7 @@ static int mqueue_fill_super(struct super_block *sb, struct fs_context *fc)
> sb->s_blocksize_bits = PAGE_SHIFT;
> sb->s_magic = MQUEUE_MAGIC;
> sb->s_op = &mqueue_super_ops;
> + sb->s_d_flags = DCACHE_DONTCACHE;
>
> inode = mqueue_get_inode(sb, ns, S_IFDIR | S_ISVTX | S_IRWXUGO, NULL);
> if (IS_ERR(inode))
> --
> 2.39.5
>
^ permalink raw reply [flat|nested] 87+ messages in thread
* [PATCH 17/21] 9p: don't bother with always_delete_dentry
2025-02-24 21:20 ` [PATCH 01/21] procfs: kill ->proc_dops Al Viro
` (14 preceding siblings ...)
2025-02-24 21:20 ` [PATCH 16/21] ramfs, hugetlbfs, mqueue: set DCACHE_DONTCACHE Al Viro
@ 2025-02-24 21:20 ` Al Viro
2025-02-26 8:40 ` Christian Brauner
2025-02-24 21:20 ` [PATCH 18/21] efivarfs: use DCACHE_DONTCACHE instead of always_delete_dentry() Al Viro
` (6 subsequent siblings)
22 siblings, 1 reply; 87+ messages in thread
From: Al Viro @ 2025-02-24 21:20 UTC (permalink / raw)
To: linux-fsdevel
Cc: Linus Torvalds, Christian Brauner, Neil Brown, Miklos Szeredi,
Jan Kara
just set DCACHE_DONTCACHE for "don't cache" mounts...
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/9p/vfs_dentry.c | 1 -
fs/9p/vfs_super.c | 6 ++++--
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/fs/9p/vfs_dentry.c b/fs/9p/vfs_dentry.c
index 5061f192eafd..04795508a795 100644
--- a/fs/9p/vfs_dentry.c
+++ b/fs/9p/vfs_dentry.c
@@ -127,7 +127,6 @@ const struct dentry_operations v9fs_cached_dentry_operations = {
};
const struct dentry_operations v9fs_dentry_operations = {
- .d_delete = always_delete_dentry,
.d_release = v9fs_dentry_release,
.d_unalias_trylock = v9fs_dentry_unalias_trylock,
.d_unalias_unlock = v9fs_dentry_unalias_unlock,
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
index 5c3dc3efb909..795c6388744c 100644
--- a/fs/9p/vfs_super.c
+++ b/fs/9p/vfs_super.c
@@ -134,10 +134,12 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags,
if (retval)
goto release_sb;
- if (v9ses->cache & (CACHE_META|CACHE_LOOSE))
+ if (v9ses->cache & (CACHE_META|CACHE_LOOSE)) {
set_default_d_op(sb, &v9fs_cached_dentry_operations);
- else
+ } else {
set_default_d_op(sb, &v9fs_dentry_operations);
+ sb->s_d_flags |= DCACHE_DONTCACHE;
+ }
inode = v9fs_get_new_inode_from_fid(v9ses, fid, sb);
if (IS_ERR(inode)) {
--
2.39.5
^ permalink raw reply related [flat|nested] 87+ messages in thread* Re: [PATCH 17/21] 9p: don't bother with always_delete_dentry
2025-02-24 21:20 ` [PATCH 17/21] 9p: don't bother with always_delete_dentry Al Viro
@ 2025-02-26 8:40 ` Christian Brauner
0 siblings, 0 replies; 87+ messages in thread
From: Christian Brauner @ 2025-02-26 8:40 UTC (permalink / raw)
To: Al Viro; +Cc: linux-fsdevel, Linus Torvalds, Neil Brown, Miklos Szeredi,
Jan Kara
On Mon, Feb 24, 2025 at 09:20:47PM +0000, Al Viro wrote:
> just set DCACHE_DONTCACHE for "don't cache" mounts...
>
> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
> ---
Reviewed-by: Christian Brauner <brauner@kernel.org>
> fs/9p/vfs_dentry.c | 1 -
> fs/9p/vfs_super.c | 6 ++++--
> 2 files changed, 4 insertions(+), 3 deletions(-)
>
> diff --git a/fs/9p/vfs_dentry.c b/fs/9p/vfs_dentry.c
> index 5061f192eafd..04795508a795 100644
> --- a/fs/9p/vfs_dentry.c
> +++ b/fs/9p/vfs_dentry.c
> @@ -127,7 +127,6 @@ const struct dentry_operations v9fs_cached_dentry_operations = {
> };
>
> const struct dentry_operations v9fs_dentry_operations = {
> - .d_delete = always_delete_dentry,
> .d_release = v9fs_dentry_release,
> .d_unalias_trylock = v9fs_dentry_unalias_trylock,
> .d_unalias_unlock = v9fs_dentry_unalias_unlock,
> diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
> index 5c3dc3efb909..795c6388744c 100644
> --- a/fs/9p/vfs_super.c
> +++ b/fs/9p/vfs_super.c
> @@ -134,10 +134,12 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags,
> if (retval)
> goto release_sb;
>
> - if (v9ses->cache & (CACHE_META|CACHE_LOOSE))
> + if (v9ses->cache & (CACHE_META|CACHE_LOOSE)) {
> set_default_d_op(sb, &v9fs_cached_dentry_operations);
> - else
> + } else {
> set_default_d_op(sb, &v9fs_dentry_operations);
> + sb->s_d_flags |= DCACHE_DONTCACHE;
> + }
>
> inode = v9fs_get_new_inode_from_fid(v9ses, fid, sb);
> if (IS_ERR(inode)) {
> --
> 2.39.5
>
^ permalink raw reply [flat|nested] 87+ messages in thread
* [PATCH 18/21] efivarfs: use DCACHE_DONTCACHE instead of always_delete_dentry()
2025-02-24 21:20 ` [PATCH 01/21] procfs: kill ->proc_dops Al Viro
` (15 preceding siblings ...)
2025-02-24 21:20 ` [PATCH 17/21] 9p: don't bother with always_delete_dentry Al Viro
@ 2025-02-24 21:20 ` Al Viro
2025-02-26 8:40 ` Christian Brauner
2025-02-24 21:20 ` [PATCH 19/21] debugfs: use DCACHE_DONTCACHE Al Viro
` (5 subsequent siblings)
22 siblings, 1 reply; 87+ messages in thread
From: Al Viro @ 2025-02-24 21:20 UTC (permalink / raw)
To: linux-fsdevel
Cc: Linus Torvalds, Christian Brauner, Neil Brown, Miklos Szeredi,
Jan Kara
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/efivarfs/super.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/efivarfs/super.c b/fs/efivarfs/super.c
index 3f3188e0cfa7..e5d3147cfcea 100644
--- a/fs/efivarfs/super.c
+++ b/fs/efivarfs/super.c
@@ -175,7 +175,6 @@ static int efivarfs_d_hash(const struct dentry *dentry, struct qstr *qstr)
static const struct dentry_operations efivarfs_d_ops = {
.d_compare = efivarfs_d_compare,
.d_hash = efivarfs_d_hash,
- .d_delete = always_delete_dentry,
};
static struct dentry *efivarfs_alloc_dentry(struct dentry *parent, char *name)
@@ -346,6 +345,7 @@ static int efivarfs_fill_super(struct super_block *sb, struct fs_context *fc)
sb->s_magic = EFIVARFS_MAGIC;
sb->s_op = &efivarfs_ops;
set_default_d_op(sb, &efivarfs_d_ops);
+ sb->s_d_flags |= DCACHE_DONTCACHE;
sb->s_time_gran = 1;
if (!efivar_supports_writes())
--
2.39.5
^ permalink raw reply related [flat|nested] 87+ messages in thread* Re: [PATCH 18/21] efivarfs: use DCACHE_DONTCACHE instead of always_delete_dentry()
2025-02-24 21:20 ` [PATCH 18/21] efivarfs: use DCACHE_DONTCACHE instead of always_delete_dentry() Al Viro
@ 2025-02-26 8:40 ` Christian Brauner
0 siblings, 0 replies; 87+ messages in thread
From: Christian Brauner @ 2025-02-26 8:40 UTC (permalink / raw)
To: Al Viro; +Cc: linux-fsdevel, Linus Torvalds, Neil Brown, Miklos Szeredi,
Jan Kara
On Mon, Feb 24, 2025 at 09:20:48PM +0000, Al Viro wrote:
> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
> ---
Reviewed-by: Christian Brauner <brauner@kernel.org>
> fs/efivarfs/super.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/fs/efivarfs/super.c b/fs/efivarfs/super.c
> index 3f3188e0cfa7..e5d3147cfcea 100644
> --- a/fs/efivarfs/super.c
> +++ b/fs/efivarfs/super.c
> @@ -175,7 +175,6 @@ static int efivarfs_d_hash(const struct dentry *dentry, struct qstr *qstr)
> static const struct dentry_operations efivarfs_d_ops = {
> .d_compare = efivarfs_d_compare,
> .d_hash = efivarfs_d_hash,
> - .d_delete = always_delete_dentry,
> };
>
> static struct dentry *efivarfs_alloc_dentry(struct dentry *parent, char *name)
> @@ -346,6 +345,7 @@ static int efivarfs_fill_super(struct super_block *sb, struct fs_context *fc)
> sb->s_magic = EFIVARFS_MAGIC;
> sb->s_op = &efivarfs_ops;
> set_default_d_op(sb, &efivarfs_d_ops);
> + sb->s_d_flags |= DCACHE_DONTCACHE;
> sb->s_time_gran = 1;
>
> if (!efivar_supports_writes())
> --
> 2.39.5
>
^ permalink raw reply [flat|nested] 87+ messages in thread
* [PATCH 19/21] debugfs: use DCACHE_DONTCACHE
2025-02-24 21:20 ` [PATCH 01/21] procfs: kill ->proc_dops Al Viro
` (16 preceding siblings ...)
2025-02-24 21:20 ` [PATCH 18/21] efivarfs: use DCACHE_DONTCACHE instead of always_delete_dentry() Al Viro
@ 2025-02-24 21:20 ` Al Viro
2025-02-26 8:40 ` Christian Brauner
2025-02-24 21:20 ` [PATCH 20/21] configfs: " Al Viro
` (4 subsequent siblings)
22 siblings, 1 reply; 87+ messages in thread
From: Al Viro @ 2025-02-24 21:20 UTC (permalink / raw)
To: linux-fsdevel
Cc: Linus Torvalds, Christian Brauner, Neil Brown, Miklos Szeredi,
Jan Kara
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/debugfs/inode.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index f54a8fd960e4..1c71d9932a67 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -258,7 +258,6 @@ static struct vfsmount *debugfs_automount(struct path *path)
}
static const struct dentry_operations debugfs_dops = {
- .d_delete = always_delete_dentry,
.d_release = debugfs_release_dentry,
.d_automount = debugfs_automount,
};
@@ -274,6 +273,7 @@ static int debugfs_fill_super(struct super_block *sb, struct fs_context *fc)
sb->s_op = &debugfs_super_operations;
set_default_d_op(sb, &debugfs_dops);
+ sb->s_d_flags |= DCACHE_DONTCACHE;
debugfs_apply_options(sb);
--
2.39.5
^ permalink raw reply related [flat|nested] 87+ messages in thread* Re: [PATCH 19/21] debugfs: use DCACHE_DONTCACHE
2025-02-24 21:20 ` [PATCH 19/21] debugfs: use DCACHE_DONTCACHE Al Viro
@ 2025-02-26 8:40 ` Christian Brauner
0 siblings, 0 replies; 87+ messages in thread
From: Christian Brauner @ 2025-02-26 8:40 UTC (permalink / raw)
To: Al Viro; +Cc: linux-fsdevel, Linus Torvalds, Neil Brown, Miklos Szeredi,
Jan Kara
On Mon, Feb 24, 2025 at 09:20:49PM +0000, Al Viro wrote:
> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
> ---
Reviewed-by: Christian Brauner <brauner@kernel.org>
> fs/debugfs/inode.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
> index f54a8fd960e4..1c71d9932a67 100644
> --- a/fs/debugfs/inode.c
> +++ b/fs/debugfs/inode.c
> @@ -258,7 +258,6 @@ static struct vfsmount *debugfs_automount(struct path *path)
> }
>
> static const struct dentry_operations debugfs_dops = {
> - .d_delete = always_delete_dentry,
> .d_release = debugfs_release_dentry,
> .d_automount = debugfs_automount,
> };
> @@ -274,6 +273,7 @@ static int debugfs_fill_super(struct super_block *sb, struct fs_context *fc)
>
> sb->s_op = &debugfs_super_operations;
> set_default_d_op(sb, &debugfs_dops);
> + sb->s_d_flags |= DCACHE_DONTCACHE;
>
> debugfs_apply_options(sb);
>
> --
> 2.39.5
>
^ permalink raw reply [flat|nested] 87+ messages in thread
* [PATCH 20/21] configfs: use DCACHE_DONTCACHE
2025-02-24 21:20 ` [PATCH 01/21] procfs: kill ->proc_dops Al Viro
` (17 preceding siblings ...)
2025-02-24 21:20 ` [PATCH 19/21] debugfs: use DCACHE_DONTCACHE Al Viro
@ 2025-02-24 21:20 ` Al Viro
2025-02-26 8:40 ` Christian Brauner
2025-02-24 21:20 ` [PATCH 21/21] afs dynroot: " Al Viro
` (3 subsequent siblings)
22 siblings, 1 reply; 87+ messages in thread
From: Al Viro @ 2025-02-24 21:20 UTC (permalink / raw)
To: linux-fsdevel
Cc: Linus Torvalds, Christian Brauner, Neil Brown, Miklos Szeredi,
Jan Kara
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/configfs/dir.c | 1 -
fs/configfs/mount.c | 1 +
2 files changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c
index 7d10278db30d..637267a76ad8 100644
--- a/fs/configfs/dir.c
+++ b/fs/configfs/dir.c
@@ -67,7 +67,6 @@ static void configfs_d_iput(struct dentry * dentry,
const struct dentry_operations configfs_dentry_ops = {
.d_iput = configfs_d_iput,
- .d_delete = always_delete_dentry,
};
#ifdef CONFIG_LOCKDEP
diff --git a/fs/configfs/mount.c b/fs/configfs/mount.c
index 20412eaca972..740f18b60c9d 100644
--- a/fs/configfs/mount.c
+++ b/fs/configfs/mount.c
@@ -93,6 +93,7 @@ static int configfs_fill_super(struct super_block *sb, struct fs_context *fc)
root->d_fsdata = &configfs_root;
sb->s_root = root;
set_default_d_op(sb, &configfs_dentry_ops); /* the rest get that */
+ sb->s_d_flags |= DCACHE_DONTCACHE;
return 0;
}
--
2.39.5
^ permalink raw reply related [flat|nested] 87+ messages in thread* Re: [PATCH 20/21] configfs: use DCACHE_DONTCACHE
2025-02-24 21:20 ` [PATCH 20/21] configfs: " Al Viro
@ 2025-02-26 8:40 ` Christian Brauner
0 siblings, 0 replies; 87+ messages in thread
From: Christian Brauner @ 2025-02-26 8:40 UTC (permalink / raw)
To: Al Viro; +Cc: linux-fsdevel, Linus Torvalds, Neil Brown, Miklos Szeredi,
Jan Kara
On Mon, Feb 24, 2025 at 09:20:50PM +0000, Al Viro wrote:
> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
> ---
Reviewed-by: Christian Brauner <brauner@kernel.org>
> fs/configfs/dir.c | 1 -
> fs/configfs/mount.c | 1 +
> 2 files changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c
> index 7d10278db30d..637267a76ad8 100644
> --- a/fs/configfs/dir.c
> +++ b/fs/configfs/dir.c
> @@ -67,7 +67,6 @@ static void configfs_d_iput(struct dentry * dentry,
>
> const struct dentry_operations configfs_dentry_ops = {
> .d_iput = configfs_d_iput,
> - .d_delete = always_delete_dentry,
> };
>
> #ifdef CONFIG_LOCKDEP
> diff --git a/fs/configfs/mount.c b/fs/configfs/mount.c
> index 20412eaca972..740f18b60c9d 100644
> --- a/fs/configfs/mount.c
> +++ b/fs/configfs/mount.c
> @@ -93,6 +93,7 @@ static int configfs_fill_super(struct super_block *sb, struct fs_context *fc)
> root->d_fsdata = &configfs_root;
> sb->s_root = root;
> set_default_d_op(sb, &configfs_dentry_ops); /* the rest get that */
> + sb->s_d_flags |= DCACHE_DONTCACHE;
> return 0;
> }
>
> --
> 2.39.5
>
^ permalink raw reply [flat|nested] 87+ messages in thread
* [PATCH 21/21] afs dynroot: use DCACHE_DONTCACHE
2025-02-24 21:20 ` [PATCH 01/21] procfs: kill ->proc_dops Al Viro
` (18 preceding siblings ...)
2025-02-24 21:20 ` [PATCH 20/21] configfs: " Al Viro
@ 2025-02-24 21:20 ` Al Viro
2025-02-26 8:41 ` Christian Brauner
2025-02-25 15:55 ` [PATCH 01/21] procfs: kill ->proc_dops Jan Kara
` (2 subsequent siblings)
22 siblings, 1 reply; 87+ messages in thread
From: Al Viro @ 2025-02-24 21:20 UTC (permalink / raw)
To: linux-fsdevel
Cc: Linus Torvalds, Christian Brauner, Neil Brown, Miklos Szeredi,
Jan Kara
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/afs/dynroot.c | 1 -
fs/afs/super.c | 1 +
2 files changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/afs/dynroot.c b/fs/afs/dynroot.c
index d8bf52f77d93..2fad2987a6dc 100644
--- a/fs/afs/dynroot.c
+++ b/fs/afs/dynroot.c
@@ -211,7 +211,6 @@ const struct inode_operations afs_dynroot_inode_operations = {
};
const struct dentry_operations afs_dynroot_dentry_operations = {
- .d_delete = always_delete_dentry,
.d_release = afs_d_release,
.d_automount = afs_d_automount,
};
diff --git a/fs/afs/super.c b/fs/afs/super.c
index 13d0414a1ddb..b48f524c1cb6 100644
--- a/fs/afs/super.c
+++ b/fs/afs/super.c
@@ -488,6 +488,7 @@ static int afs_fill_super(struct super_block *sb, struct afs_fs_context *ctx)
if (as->dyn_root) {
set_default_d_op(sb, &afs_dynroot_dentry_operations);
+ sb->s_d_flags |= DCACHE_DONTCACHE;
ret = afs_dynroot_populate(sb);
if (ret < 0)
goto error;
--
2.39.5
^ permalink raw reply related [flat|nested] 87+ messages in thread* Re: [PATCH 21/21] afs dynroot: use DCACHE_DONTCACHE
2025-02-24 21:20 ` [PATCH 21/21] afs dynroot: " Al Viro
@ 2025-02-26 8:41 ` Christian Brauner
0 siblings, 0 replies; 87+ messages in thread
From: Christian Brauner @ 2025-02-26 8:41 UTC (permalink / raw)
To: Al Viro; +Cc: linux-fsdevel, Linus Torvalds, Neil Brown, Miklos Szeredi,
Jan Kara
On Mon, Feb 24, 2025 at 09:20:51PM +0000, Al Viro wrote:
> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
> ---
Reviewed-by: Christian Brauner <brauner@kernel.org>
> fs/afs/dynroot.c | 1 -
> fs/afs/super.c | 1 +
> 2 files changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/fs/afs/dynroot.c b/fs/afs/dynroot.c
> index d8bf52f77d93..2fad2987a6dc 100644
> --- a/fs/afs/dynroot.c
> +++ b/fs/afs/dynroot.c
> @@ -211,7 +211,6 @@ const struct inode_operations afs_dynroot_inode_operations = {
> };
>
> const struct dentry_operations afs_dynroot_dentry_operations = {
> - .d_delete = always_delete_dentry,
> .d_release = afs_d_release,
> .d_automount = afs_d_automount,
> };
> diff --git a/fs/afs/super.c b/fs/afs/super.c
> index 13d0414a1ddb..b48f524c1cb6 100644
> --- a/fs/afs/super.c
> +++ b/fs/afs/super.c
> @@ -488,6 +488,7 @@ static int afs_fill_super(struct super_block *sb, struct afs_fs_context *ctx)
>
> if (as->dyn_root) {
> set_default_d_op(sb, &afs_dynroot_dentry_operations);
> + sb->s_d_flags |= DCACHE_DONTCACHE;
> ret = afs_dynroot_populate(sb);
> if (ret < 0)
> goto error;
> --
> 2.39.5
>
^ permalink raw reply [flat|nested] 87+ messages in thread
* Re: [PATCH 01/21] procfs: kill ->proc_dops
2025-02-24 21:20 ` [PATCH 01/21] procfs: kill ->proc_dops Al Viro
` (19 preceding siblings ...)
2025-02-24 21:20 ` [PATCH 21/21] afs dynroot: " Al Viro
@ 2025-02-25 15:55 ` Jan Kara
2025-02-25 23:30 ` NeilBrown
2025-02-25 22:51 ` NeilBrown
2025-02-26 8:25 ` Christian Brauner
22 siblings, 1 reply; 87+ messages in thread
From: Jan Kara @ 2025-02-25 15:55 UTC (permalink / raw)
To: Al Viro
Cc: linux-fsdevel, Linus Torvalds, Christian Brauner, Neil Brown,
Miklos Szeredi, Jan Kara
On Mon 24-02-25 21:20:31, Al Viro wrote:
> It has two possible values - one for "forced lookup" entries, another
> for the normal ones. We'd be better off with that as an explicit
> flag anyway and in addition to that it opens some fun possibilities
> with ->d_op and ->d_flags handling.
>
> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
FWIW I went through the patches and I like them. They look mostly
straightforward enough to me and as good simplifications.
Honza
> ---
> fs/proc/generic.c | 8 +++++---
> fs/proc/internal.h | 5 +++--
> 2 files changed, 8 insertions(+), 5 deletions(-)
>
> diff --git a/fs/proc/generic.c b/fs/proc/generic.c
> index 8ec90826a49e..499c2bf67488 100644
> --- a/fs/proc/generic.c
> +++ b/fs/proc/generic.c
> @@ -254,7 +254,10 @@ struct dentry *proc_lookup_de(struct inode *dir, struct dentry *dentry,
> inode = proc_get_inode(dir->i_sb, de);
> if (!inode)
> return ERR_PTR(-ENOMEM);
> - d_set_d_op(dentry, de->proc_dops);
> + if (de->flags & PROC_ENTRY_FORCE_LOOKUP)
> + d_set_d_op(dentry, &proc_net_dentry_ops);
> + else
> + d_set_d_op(dentry, &proc_misc_dentry_ops);
> return d_splice_alias(inode, dentry);
> }
> read_unlock(&proc_subdir_lock);
> @@ -448,9 +451,8 @@ static struct proc_dir_entry *__proc_create(struct proc_dir_entry **parent,
> INIT_LIST_HEAD(&ent->pde_openers);
> proc_set_user(ent, (*parent)->uid, (*parent)->gid);
>
> - ent->proc_dops = &proc_misc_dentry_ops;
> /* Revalidate everything under /proc/${pid}/net */
> - if ((*parent)->proc_dops == &proc_net_dentry_ops)
> + if ((*parent)->flags & PROC_ENTRY_FORCE_LOOKUP)
> pde_force_lookup(ent);
>
> out:
> diff --git a/fs/proc/internal.h b/fs/proc/internal.h
> index 1695509370b8..07f75c959173 100644
> --- a/fs/proc/internal.h
> +++ b/fs/proc/internal.h
> @@ -44,7 +44,6 @@ struct proc_dir_entry {
> const struct proc_ops *proc_ops;
> const struct file_operations *proc_dir_ops;
> };
> - const struct dentry_operations *proc_dops;
> union {
> const struct seq_operations *seq_ops;
> int (*single_show)(struct seq_file *, void *);
> @@ -67,6 +66,8 @@ struct proc_dir_entry {
> char inline_name[];
> } __randomize_layout;
>
> +#define PROC_ENTRY_FORCE_LOOKUP 2 /* same space as PROC_ENTRY_PERMANENT */
> +
> #define SIZEOF_PDE ( \
> sizeof(struct proc_dir_entry) < 128 ? 128 : \
> sizeof(struct proc_dir_entry) < 192 ? 192 : \
> @@ -346,7 +347,7 @@ extern const struct dentry_operations proc_net_dentry_ops;
> static inline void pde_force_lookup(struct proc_dir_entry *pde)
> {
> /* /proc/net/ entries can be changed under us by setns(CLONE_NEWNET) */
> - pde->proc_dops = &proc_net_dentry_ops;
> + pde->flags |= PROC_ENTRY_FORCE_LOOKUP;
> }
>
> /*
> --
> 2.39.5
>
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
^ permalink raw reply [flat|nested] 87+ messages in thread* Re: [PATCH 01/21] procfs: kill ->proc_dops
2025-02-25 15:55 ` [PATCH 01/21] procfs: kill ->proc_dops Jan Kara
@ 2025-02-25 23:30 ` NeilBrown
2025-02-25 23:56 ` Al Viro
0 siblings, 1 reply; 87+ messages in thread
From: NeilBrown @ 2025-02-25 23:30 UTC (permalink / raw)
To: Jan Kara
Cc: Al Viro, linux-fsdevel, Linus Torvalds, Christian Brauner,
Miklos Szeredi, Jan Kara
On Wed, 26 Feb 2025, Jan Kara wrote:
> On Mon 24-02-25 21:20:31, Al Viro wrote:
> > It has two possible values - one for "forced lookup" entries, another
> > for the normal ones. We'd be better off with that as an explicit
> > flag anyway and in addition to that it opens some fun possibilities
> > with ->d_op and ->d_flags handling.
> >
> > Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
>
> FWIW I went through the patches and I like them. They look mostly
> straightforward enough to me and as good simplifications.
>
Ditto. Nice clean-up
It might be good to document s_d_flags and particularly the value of
setting DCACHE_DONTCACHE. That flag is documented in the list of
DCACHE_ flags, but making the connection that it can usefully be put in
s_d_flags might be a step to far for many.
Thanks,
NeilBrown
^ permalink raw reply [flat|nested] 87+ messages in thread
* Re: [PATCH 01/21] procfs: kill ->proc_dops
2025-02-25 23:30 ` NeilBrown
@ 2025-02-25 23:56 ` Al Viro
0 siblings, 0 replies; 87+ messages in thread
From: Al Viro @ 2025-02-25 23:56 UTC (permalink / raw)
To: NeilBrown
Cc: Jan Kara, linux-fsdevel, Linus Torvalds, Christian Brauner,
Miklos Szeredi
On Wed, Feb 26, 2025 at 10:30:21AM +1100, NeilBrown wrote:
> On Wed, 26 Feb 2025, Jan Kara wrote:
> > On Mon 24-02-25 21:20:31, Al Viro wrote:
> > > It has two possible values - one for "forced lookup" entries, another
> > > for the normal ones. We'd be better off with that as an explicit
> > > flag anyway and in addition to that it opens some fun possibilities
> > > with ->d_op and ->d_flags handling.
> > >
> > > Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
> >
> > FWIW I went through the patches and I like them. They look mostly
> > straightforward enough to me and as good simplifications.
> >
>
> Ditto. Nice clean-up
> It might be good to document s_d_flags and particularly the value of
> setting DCACHE_DONTCACHE. That flag is documented in the list of
> DCACHE_ flags, but making the connection that it can usefully be put in
> s_d_flags might be a step to far for many.
Probably... The thing is, I'm resurrecting the DCACHE_PERSISTENT
patchset (aka tree-in-dcache stuff) and that will have non-trivial
interplay there. But you are right - it's probably worth documenting
that thing in this series.
Re documentation - I'll be posting bits and pieces of dcache
docs/audit/proofs of correctness over the next few weeks; at some
point we'll need to collect that into a single text, but at the
moment what I've got is too disjoint for that. OTOH, we could
start a WIP variant in D/f/<something> and have it augmented as
we go... Not sure.
^ permalink raw reply [flat|nested] 87+ messages in thread
* Re: [PATCH 01/21] procfs: kill ->proc_dops
2025-02-24 21:20 ` [PATCH 01/21] procfs: kill ->proc_dops Al Viro
` (20 preceding siblings ...)
2025-02-25 15:55 ` [PATCH 01/21] procfs: kill ->proc_dops Jan Kara
@ 2025-02-25 22:51 ` NeilBrown
2025-02-26 0:03 ` Al Viro
2025-02-26 8:25 ` Christian Brauner
22 siblings, 1 reply; 87+ messages in thread
From: NeilBrown @ 2025-02-25 22:51 UTC (permalink / raw)
To: Al Viro
Cc: linux-fsdevel, Linus Torvalds, Christian Brauner, Miklos Szeredi,
Jan Kara
On Tue, 25 Feb 2025, Al Viro wrote:
> It has two possible values - one for "forced lookup" entries, another
> for the normal ones. We'd be better off with that as an explicit
> flag anyway and in addition to that it opens some fun possibilities
> with ->d_op and ->d_flags handling.
>
> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
> ---
> fs/proc/generic.c | 8 +++++---
> fs/proc/internal.h | 5 +++--
> 2 files changed, 8 insertions(+), 5 deletions(-)
>
> diff --git a/fs/proc/generic.c b/fs/proc/generic.c
> index 8ec90826a49e..499c2bf67488 100644
> --- a/fs/proc/generic.c
> +++ b/fs/proc/generic.c
> @@ -254,7 +254,10 @@ struct dentry *proc_lookup_de(struct inode *dir, struct dentry *dentry,
> inode = proc_get_inode(dir->i_sb, de);
> if (!inode)
> return ERR_PTR(-ENOMEM);
> - d_set_d_op(dentry, de->proc_dops);
> + if (de->flags & PROC_ENTRY_FORCE_LOOKUP)
> + d_set_d_op(dentry, &proc_net_dentry_ops);
> + else
> + d_set_d_op(dentry, &proc_misc_dentry_ops);
> return d_splice_alias(inode, dentry);
> }
> read_unlock(&proc_subdir_lock);
> @@ -448,9 +451,8 @@ static struct proc_dir_entry *__proc_create(struct proc_dir_entry **parent,
> INIT_LIST_HEAD(&ent->pde_openers);
> proc_set_user(ent, (*parent)->uid, (*parent)->gid);
>
> - ent->proc_dops = &proc_misc_dentry_ops;
> /* Revalidate everything under /proc/${pid}/net */
> - if ((*parent)->proc_dops == &proc_net_dentry_ops)
> + if ((*parent)->flags & PROC_ENTRY_FORCE_LOOKUP)
> pde_force_lookup(ent);
>
> out:
> diff --git a/fs/proc/internal.h b/fs/proc/internal.h
> index 1695509370b8..07f75c959173 100644
> --- a/fs/proc/internal.h
> +++ b/fs/proc/internal.h
> @@ -44,7 +44,6 @@ struct proc_dir_entry {
> const struct proc_ops *proc_ops;
> const struct file_operations *proc_dir_ops;
> };
> - const struct dentry_operations *proc_dops;
> union {
> const struct seq_operations *seq_ops;
> int (*single_show)(struct seq_file *, void *);
> @@ -67,6 +66,8 @@ struct proc_dir_entry {
> char inline_name[];
> } __randomize_layout;
>
> +#define PROC_ENTRY_FORCE_LOOKUP 2 /* same space as PROC_ENTRY_PERMANENT */
Should there be a note in include/linux/proc_fs.h say that '2' is in
use?
Otherwise it seems sensible.
Thanks,
NeilBrown
> +
> #define SIZEOF_PDE ( \
> sizeof(struct proc_dir_entry) < 128 ? 128 : \
> sizeof(struct proc_dir_entry) < 192 ? 192 : \
> @@ -346,7 +347,7 @@ extern const struct dentry_operations proc_net_dentry_ops;
> static inline void pde_force_lookup(struct proc_dir_entry *pde)
> {
> /* /proc/net/ entries can be changed under us by setns(CLONE_NEWNET) */
> - pde->proc_dops = &proc_net_dentry_ops;
> + pde->flags |= PROC_ENTRY_FORCE_LOOKUP;
> }
>
> /*
> --
> 2.39.5
>
>
^ permalink raw reply [flat|nested] 87+ messages in thread* Re: [PATCH 01/21] procfs: kill ->proc_dops
2025-02-25 22:51 ` NeilBrown
@ 2025-02-26 0:03 ` Al Viro
0 siblings, 0 replies; 87+ messages in thread
From: Al Viro @ 2025-02-26 0:03 UTC (permalink / raw)
To: NeilBrown
Cc: linux-fsdevel, Linus Torvalds, Christian Brauner, Miklos Szeredi,
Jan Kara
On Wed, Feb 26, 2025 at 09:51:32AM +1100, NeilBrown wrote:
> > char inline_name[];
> > } __randomize_layout;
> >
> > +#define PROC_ENTRY_FORCE_LOOKUP 2 /* same space as PROC_ENTRY_PERMANENT */
>
> Should there be a note in include/linux/proc_fs.h say that '2' is in
> use?
Umm... Point, I guess - or we could just put "all other bits are belong to us"
there ;-)
^ permalink raw reply [flat|nested] 87+ messages in thread
* Re: [PATCH 01/21] procfs: kill ->proc_dops
2025-02-24 21:20 ` [PATCH 01/21] procfs: kill ->proc_dops Al Viro
` (21 preceding siblings ...)
2025-02-25 22:51 ` NeilBrown
@ 2025-02-26 8:25 ` Christian Brauner
22 siblings, 0 replies; 87+ messages in thread
From: Christian Brauner @ 2025-02-26 8:25 UTC (permalink / raw)
To: Al Viro; +Cc: linux-fsdevel, Linus Torvalds, Neil Brown, Miklos Szeredi,
Jan Kara
On Mon, Feb 24, 2025 at 09:20:31PM +0000, Al Viro wrote:
> It has two possible values - one for "forced lookup" entries, another
> for the normal ones. We'd be better off with that as an explicit
> flag anyway and in addition to that it opens some fun possibilities
> with ->d_op and ->d_flags handling.
>
> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
> ---
Reviewed-by: Christian Brauner <brauner@kernel.org>
^ permalink raw reply [flat|nested] 87+ messages in thread