Skip to content

Commit 2558e3b

Browse files
committed
libfs: add stashed_dentry_prune()
Both pidfs and nsfs use a memory location to stash a dentry for reuse by concurrent openers. Right now two custom dentry->d_prune::{ns,pidfs}_prune_dentry() methods are needed that do the same thing. The only thing that differs is that they need to get to the memory location to store or retrieve the dentry from differently. Fix that by remember the stashing location for the dentry in dentry->d_fsdata which allows us to retrieve it in dentry->d_prune. That in turn makes it possible to add a common helper that pidfs and nsfs can both use. Link: https://lore.kernel.org/r/CAHk-=wg8cHY=i3m6RnXQ2Y2W8psicKWQEZq1=94ivUiviM-0OA@mail.gmail.com Signed-off-by: Christian Brauner <brauner@kernel.org>
1 parent 159a0d9 commit 2558e3b

File tree

4 files changed

+31
-28
lines changed

4 files changed

+31
-28
lines changed

fs/internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,3 +314,4 @@ int path_from_stashed(struct dentry **stashed, unsigned long ino,
314314
struct vfsmount *mnt, const struct file_operations *fops,
315315
const struct inode_operations *iops, void *data,
316316
struct path *path);
317+
void stashed_dentry_prune(struct dentry *dentry);

fs/libfs.c

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1988,7 +1988,8 @@ static inline struct dentry *get_stashed_dentry(struct dentry *stashed)
19881988
return dentry;
19891989
}
19901990

1991-
static struct dentry *prepare_anon_dentry(unsigned long ino,
1991+
static struct dentry *prepare_anon_dentry(struct dentry **stashed,
1992+
unsigned long ino,
19921993
struct super_block *sb,
19931994
const struct file_operations *fops,
19941995
const struct inode_operations *iops,
@@ -2019,6 +2020,9 @@ static struct dentry *prepare_anon_dentry(unsigned long ino,
20192020
inode->i_private = data;
20202021
simple_inode_init_ts(inode);
20212022

2023+
/* Store address of location where dentry's supposed to be stashed. */
2024+
dentry->d_fsdata = stashed;
2025+
20222026
/* @data is now owned by the fs */
20232027
d_instantiate(dentry, inode);
20242028
return dentry;
@@ -2081,7 +2085,7 @@ int path_from_stashed(struct dentry **stashed, unsigned long ino,
20812085
goto out_path;
20822086

20832087
/* Allocate a new dentry. */
2084-
dentry = prepare_anon_dentry(ino, mnt->mnt_sb, fops, iops, data);
2088+
dentry = prepare_anon_dentry(stashed, ino, mnt->mnt_sb, fops, iops, data);
20852089
if (IS_ERR(dentry))
20862090
return PTR_ERR(dentry);
20872091

@@ -2092,6 +2096,27 @@ int path_from_stashed(struct dentry **stashed, unsigned long ino,
20922096
ret = 1;
20932097

20942098
out_path:
2099+
WARN_ON_ONCE(path->dentry->d_fsdata != stashed);
2100+
WARN_ON_ONCE(d_inode(path->dentry)->i_private != data);
20952101
path->mnt = mntget(mnt);
20962102
return ret;
20972103
}
2104+
2105+
void stashed_dentry_prune(struct dentry *dentry)
2106+
{
2107+
struct dentry **stashed = dentry->d_fsdata;
2108+
struct inode *inode = d_inode(dentry);
2109+
2110+
if (WARN_ON_ONCE(!stashed))
2111+
return;
2112+
2113+
if (!inode)
2114+
return;
2115+
2116+
/*
2117+
* Only replace our own @dentry as someone else might've
2118+
* already cleared out @dentry and stashed their own
2119+
* dentry in there.
2120+
*/
2121+
cmpxchg(stashed, dentry, NULL);
2122+
}

fs/nsfs.c

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -34,22 +34,10 @@ static char *ns_dname(struct dentry *dentry, char *buffer, int buflen)
3434
ns_ops->name, inode->i_ino);
3535
}
3636

37-
static void ns_prune_dentry(struct dentry *dentry)
38-
{
39-
struct inode *inode;
40-
41-
inode = d_inode(dentry);
42-
if (inode) {
43-
struct ns_common *ns = inode->i_private;
44-
cmpxchg(&ns->stashed, dentry, NULL);
45-
}
46-
}
47-
48-
const struct dentry_operations ns_dentry_operations =
49-
{
50-
.d_prune = ns_prune_dentry,
37+
const struct dentry_operations ns_dentry_operations = {
5138
.d_delete = always_delete_dentry,
5239
.d_dname = ns_dname,
40+
.d_prune = stashed_dentry_prune,
5341
};
5442

5543
static void nsfs_evict(struct inode *inode)

fs/pidfs.c

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -187,21 +187,10 @@ static char *pidfs_dname(struct dentry *dentry, char *buffer, int buflen)
187187
d_inode(dentry)->i_ino);
188188
}
189189

190-
static void pidfs_prune_dentry(struct dentry *dentry)
191-
{
192-
struct inode *inode;
193-
194-
inode = d_inode(dentry);
195-
if (inode) {
196-
struct pid *pid = inode->i_private;
197-
cmpxchg(&pid->stashed, dentry, NULL);
198-
}
199-
}
200-
201190
static const struct dentry_operations pidfs_dentry_operations = {
202191
.d_delete = always_delete_dentry,
203192
.d_dname = pidfs_dname,
204-
.d_prune = pidfs_prune_dentry,
193+
.d_prune = stashed_dentry_prune,
205194
};
206195

207196
static int pidfs_init_fs_context(struct fs_context *fc)

0 commit comments

Comments
 (0)