Skip to content

Commit e9c5263

Browse files
committed
libfs: improve path_from_stashed()
Right now we pass a bunch of info that is fs specific which doesn't make a lot of sense and it bleeds fs sepcific details into the generic helper. nsfs and pidfs have slightly different needs when initializing inodes. Add simple operations that are stashed in sb->s_fs_info that both can implement. This also allows us to get rid of cleaning up references in the caller. All in all path_from_stashed() becomes way simpler. Signed-off-by: Christian Brauner <brauner@kernel.org>
1 parent 2558e3b commit e9c5263

File tree

4 files changed

+66
-40
lines changed

4 files changed

+66
-40
lines changed

fs/internal.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -310,8 +310,10 @@ ssize_t __kernel_write_iter(struct file *file, struct iov_iter *from, loff_t *po
310310
struct mnt_idmap *alloc_mnt_idmap(struct user_namespace *mnt_userns);
311311
struct mnt_idmap *mnt_idmap_get(struct mnt_idmap *idmap);
312312
void mnt_idmap_put(struct mnt_idmap *idmap);
313+
struct stashed_operations {
314+
void (*put_data)(void *data);
315+
void (*init_inode)(struct inode *inode, void *data);
316+
};
313317
int path_from_stashed(struct dentry **stashed, unsigned long ino,
314-
struct vfsmount *mnt, const struct file_operations *fops,
315-
const struct inode_operations *iops, void *data,
316-
struct path *path);
318+
struct vfsmount *mnt, void *data, struct path *path);
317319
void stashed_dentry_prune(struct dentry *dentry);

fs/libfs.c

Lines changed: 18 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1991,12 +1991,11 @@ static inline struct dentry *get_stashed_dentry(struct dentry *stashed)
19911991
static struct dentry *prepare_anon_dentry(struct dentry **stashed,
19921992
unsigned long ino,
19931993
struct super_block *sb,
1994-
const struct file_operations *fops,
1995-
const struct inode_operations *iops,
19961994
void *data)
19971995
{
19981996
struct dentry *dentry;
19991997
struct inode *inode;
1998+
const struct stashed_operations *sops = sb->s_fs_info;
20001999

20012000
dentry = d_alloc_anon(sb);
20022001
if (!dentry)
@@ -2010,15 +2009,13 @@ static struct dentry *prepare_anon_dentry(struct dentry **stashed,
20102009

20112010
inode->i_ino = ino;
20122011
inode->i_flags |= S_IMMUTABLE;
2013-
if (is_pidfs_sb(sb))
2014-
inode->i_flags |= S_PRIVATE;
2015-
inode->i_mode = S_IFREG | S_IRUGO;
2016-
if (iops)
2017-
inode->i_op = iops;
2018-
if (fops)
2019-
inode->i_fop = fops;
2020-
inode->i_private = data;
2012+
inode->i_mode = S_IFREG;
20212013
simple_inode_init_ts(inode);
2014+
sops->init_inode(inode, data);
2015+
2016+
/* Notice when this is changed. */
2017+
WARN_ON_ONCE(!S_ISREG(inode->i_mode));
2018+
WARN_ON_ONCE(!IS_IMMUTABLE(inode));
20222019

20232020
/* Store address of location where dentry's supposed to be stashed. */
20242021
dentry->d_fsdata = stashed;
@@ -2055,8 +2052,6 @@ static struct dentry *stash_dentry(struct dentry **stashed,
20552052
* @stashed: where to retrieve or stash dentry
20562053
* @ino: inode number to use
20572054
* @mnt: mnt of the filesystems to use
2058-
* @iops: inode operations to use
2059-
* @fops: file operations to use
20602055
* @data: data to store in inode->i_private
20612056
* @path: path to create
20622057
*
@@ -2068,38 +2063,38 @@ static struct dentry *stash_dentry(struct dentry **stashed,
20682063
*
20692064
* Special-purpose helper for nsfs and pidfs.
20702065
*
2071-
* Return: If 0 or an error is returned the caller can be sure that @data must
2072-
* be cleaned up. If 1 is returned @data is owned by the filesystem.
2066+
* Return: On success zero and on failure a negative error is returned.
20732067
*/
20742068
int path_from_stashed(struct dentry **stashed, unsigned long ino,
2075-
struct vfsmount *mnt, const struct file_operations *fops,
2076-
const struct inode_operations *iops, void *data,
2077-
struct path *path)
2069+
struct vfsmount *mnt, void *data, struct path *path)
20782070
{
20792071
struct dentry *dentry;
2080-
int ret = 0;
2072+
const struct stashed_operations *sops = mnt->mnt_sb->s_fs_info;
20812073

20822074
/* See if dentry can be reused. */
20832075
path->dentry = get_stashed_dentry(*stashed);
2084-
if (path->dentry)
2076+
if (path->dentry) {
2077+
sops->put_data(data);
20852078
goto out_path;
2079+
}
20862080

20872081
/* Allocate a new dentry. */
2088-
dentry = prepare_anon_dentry(stashed, ino, mnt->mnt_sb, fops, iops, data);
2089-
if (IS_ERR(dentry))
2082+
dentry = prepare_anon_dentry(stashed, ino, mnt->mnt_sb, data);
2083+
if (IS_ERR(dentry)) {
2084+
sops->put_data(data);
20902085
return PTR_ERR(dentry);
2086+
}
20912087

20922088
/* Added a new dentry. @data is now owned by the filesystem. */
20932089
path->dentry = stash_dentry(stashed, dentry);
20942090
if (path->dentry != dentry)
20952091
dput(dentry);
2096-
ret = 1;
20972092

20982093
out_path:
20992094
WARN_ON_ONCE(path->dentry->d_fsdata != stashed);
21002095
WARN_ON_ONCE(d_inode(path->dentry)->i_private != data);
21012096
path->mnt = mntget(mnt);
2102-
return ret;
2097+
return 0;
21032098
}
21042099

21052100
void stashed_dentry_prune(struct dentry *dentry)

fs/nsfs.c

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -50,19 +50,13 @@ static void nsfs_evict(struct inode *inode)
5050
int ns_get_path_cb(struct path *path, ns_get_path_helper_t *ns_get_cb,
5151
void *private_data)
5252
{
53-
int ret;
5453
struct ns_common *ns;
5554

5655
ns = ns_get_cb(private_data);
5756
if (!ns)
5857
return -ENOENT;
59-
ret = path_from_stashed(&ns->stashed, ns->inum, nsfs_mnt,
60-
&ns_file_operations, NULL, ns, path);
61-
if (ret <= 0)
62-
ns->ops->put(ns);
63-
if (ret < 0)
64-
return ret;
65-
return 0;
58+
59+
return path_from_stashed(&ns->stashed, ns->inum, nsfs_mnt, ns, path);
6660
}
6761

6862
struct ns_get_path_task_args {
@@ -108,9 +102,7 @@ int open_related_ns(struct ns_common *ns,
108102
}
109103

110104
err = path_from_stashed(&relative->stashed, relative->inum, nsfs_mnt,
111-
&ns_file_operations, NULL, relative, &path);
112-
if (err <= 0)
113-
relative->ops->put(relative);
105+
relative, &path);
114106
if (err < 0) {
115107
put_unused_fd(fd);
116108
return err;
@@ -207,13 +199,32 @@ static const struct super_operations nsfs_ops = {
207199
.show_path = nsfs_show_path,
208200
};
209201

202+
static void nsfs_init_inode(struct inode *inode, void *data)
203+
{
204+
inode->i_private = data;
205+
inode->i_mode |= S_IRUGO;
206+
inode->i_fop = &ns_file_operations;
207+
}
208+
209+
static void nsfs_put_data(void *data)
210+
{
211+
struct ns_common *ns = data;
212+
ns->ops->put(ns);
213+
}
214+
215+
static const struct stashed_operations nsfs_stashed_ops = {
216+
.init_inode = nsfs_init_inode,
217+
.put_data = nsfs_put_data,
218+
};
219+
210220
static int nsfs_init_fs_context(struct fs_context *fc)
211221
{
212222
struct pseudo_fs_context *ctx = init_pseudo(fc, NSFS_MAGIC);
213223
if (!ctx)
214224
return -ENOMEM;
215225
ctx->ops = &nsfs_ops;
216226
ctx->dops = &ns_dentry_operations;
227+
fc->s_fs_info = (void *)&nsfs_stashed_ops;
217228
return 0;
218229
}
219230

fs/pidfs.c

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,26 @@ static const struct dentry_operations pidfs_dentry_operations = {
193193
.d_prune = stashed_dentry_prune,
194194
};
195195

196+
static void pidfs_init_inode(struct inode *inode, void *data)
197+
{
198+
inode->i_private = data;
199+
inode->i_flags |= S_PRIVATE;
200+
inode->i_mode |= S_IRWXU;
201+
inode->i_op = &pidfs_inode_operations;
202+
inode->i_fop = &pidfs_file_operations;
203+
}
204+
205+
static void pidfs_put_data(void *data)
206+
{
207+
struct pid *pid = data;
208+
put_pid(pid);
209+
}
210+
211+
static const struct stashed_operations pidfs_stashed_ops = {
212+
.init_inode = pidfs_init_inode,
213+
.put_data = pidfs_put_data,
214+
};
215+
196216
static int pidfs_init_fs_context(struct fs_context *fc)
197217
{
198218
struct pseudo_fs_context *ctx;
@@ -203,6 +223,7 @@ static int pidfs_init_fs_context(struct fs_context *fc)
203223

204224
ctx->ops = &pidfs_sops;
205225
ctx->dops = &pidfs_dentry_operations;
226+
fc->s_fs_info = (void *)&pidfs_stashed_ops;
206227
return 0;
207228
}
208229

@@ -225,10 +246,7 @@ struct file *pidfs_alloc_file(struct pid *pid, unsigned int flags)
225246
* for pseudo filesystems.
226247
*/
227248
ret = path_from_stashed(&pid->stashed, pid->ino, pidfs_mnt,
228-
&pidfs_file_operations, &pidfs_inode_operations,
229249
get_pid(pid), &path);
230-
if (ret <= 0)
231-
put_pid(pid);
232250
if (ret < 0)
233251
return ERR_PTR(ret);
234252

0 commit comments

Comments
 (0)