On Tue, Feb 20, 2024 at 03:13:50PM -0600, Eric Sandeen wrote: > From: David Howells <dhowells@xxxxxxxxxx> > > Convert the coda filesystem to the new internal mount API as the old > one will be obsoleted and removed. This allows greater flexibility in > communication of mount parameters between userspace, the VFS and the > filesystem. > > See Documentation/filesystems/mount_api.rst for more information. > > Note this is slightly tricky as coda currently only has a binary mount data > interface. This is handled through the parse_monolithic hook. > > Also add a more conventional interface with a parameter named "fd" that > takes an fd that refers to a coda psdev, thereby specifying the index to > use. > > Signed-off-by: David Howells <dhowells@xxxxxxxxxx> > Co-developed-by: Eric Sandeen <sandeen@xxxxxxxxxx> > Signed-off-by: Eric Sandeen <sandeen@xxxxxxxxxx> > [sandeen: forward port to current upstream mount API interfaces] > Tested-by: Jan Harkes <jaharkes@xxxxxxxxxx> > cc: coda@xxxxxxxxxx > > --- > > NB: This updated patch is based on > https://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git/commit/?h=mount-api-viro&id=4aec2ba3ca543e39944604774b8cab9c4d592651 > > hence the From: David above. > > fs/coda/inode.c | 140 +++++++++++++++++++++++++++++++++--------------- > 1 file changed, 98 insertions(+), 42 deletions(-) > > diff --git a/fs/coda/inode.c b/fs/coda/inode.c > index 0c7c2528791e..479c45b7b621 100644 > --- a/fs/coda/inode.c > +++ b/fs/coda/inode.c > @@ -24,6 +24,8 @@ > #include <linux/pid_namespace.h> > #include <linux/uaccess.h> > #include <linux/fs.h> > +#include <linux/fs_context.h> > +#include <linux/fs_parser.h> > #include <linux/vmalloc.h> > > #include <linux/coda.h> > @@ -87,10 +89,10 @@ void coda_destroy_inodecache(void) > kmem_cache_destroy(coda_inode_cachep); > } > > -static int coda_remount(struct super_block *sb, int *flags, char *data) > +static int coda_reconfigure(struct fs_context *fc) > { > - sync_filesystem(sb); > - *flags |= SB_NOATIME; > + sync_filesystem(fc->root->d_sb); > + fc->sb_flags |= SB_NOATIME; > return 0; > } > > @@ -102,78 +104,105 @@ static const struct super_operations coda_super_operations = > .evict_inode = coda_evict_inode, > .put_super = coda_put_super, > .statfs = coda_statfs, > - .remount_fs = coda_remount, > }; > > -static int get_device_index(struct coda_mount_data *data) > +struct coda_fs_context { > + int idx; > +}; > + > +enum { > + Opt_fd, > +}; > + > +static const struct fs_parameter_spec coda_param_specs[] = { > + fsparam_fd ("fd", Opt_fd), > + {} > +}; > + > +static int coda_parse_fd(struct fs_context *fc, int fd) > { > + struct coda_fs_context *ctx = fc->fs_private; > struct fd f; > struct inode *inode; > int idx; > > - if (data == NULL) { > - pr_warn("%s: Bad mount data\n", __func__); > - return -1; > - } > - > - if (data->version != CODA_MOUNT_VERSION) { > - pr_warn("%s: Bad mount version\n", __func__); > - return -1; > - } > - > - f = fdget(data->fd); > + f = fdget(fd); > if (!f.file) > - goto Ebadf; > + return -EBADF; > inode = file_inode(f.file); > if (!S_ISCHR(inode->i_mode) || imajor(inode) != CODA_PSDEV_MAJOR) { > fdput(f); > - goto Ebadf; > + return invalf(fc, "code: Not coda psdev"); > } > > idx = iminor(inode); > fdput(f); > > - if (idx < 0 || idx >= MAX_CODADEVS) { > - pr_warn("%s: Bad minor number\n", __func__); > - return -1; > + if (idx < 0 || idx >= MAX_CODADEVS) > + return invalf(fc, "coda: Bad minor number"); > + ctx->idx = idx; > + return 0; > +} > + > +static int coda_parse_param(struct fs_context *fc, struct fs_parameter *param) > +{ > + struct fs_parse_result result; > + int opt; > + > + opt = fs_parse(fc, coda_param_specs, param, &result); > + if (opt < 0) > + return opt; > + > + switch (opt) { > + case Opt_fd: > + return coda_parse_fd(fc, result.uint_32); > } > > - return idx; > -Ebadf: > - pr_warn("%s: Bad file\n", __func__); > - return -1; > + return 0; > } > > -static int coda_fill_super(struct super_block *sb, void *data, int silent) > +/* > + * Parse coda's binary mount data form. We ignore any errors and go with index > + * 0 if we get one for backward compatibility. > + */ > +static int coda_parse_monolithic(struct fs_context *fc, void *_data) > { > + struct coda_mount_data *data = _data; > + > + if (!data) > + return invalf(fc, "coda: Bad mount data"); > + > + if (data->version != CODA_MOUNT_VERSION) > + return invalf(fc, "coda: Bad mount version"); > + > + coda_parse_fd(fc, data->fd); > + return 0; > +} > + > +static int coda_fill_super(struct super_block *sb, struct fs_context *fc) > +{ > + struct coda_fs_context *ctx = fc->fs_private; > struct inode *root = NULL; > struct venus_comm *vc; > struct CodaFid fid; > int error; > - int idx; > > if (task_active_pid_ns(current) != &init_pid_ns) > return -EINVAL; > > - idx = get_device_index((struct coda_mount_data *) data); > + infof(fc, "coda: device index: %i\n", ctx->idx); > > - /* Ignore errors in data, for backward compatibility */ > - if(idx == -1) > - idx = 0; > - > - pr_info("%s: device index: %i\n", __func__, idx); > - > - vc = &coda_comms[idx]; > + vc = &coda_comms[ctx->idx]; > mutex_lock(&vc->vc_mutex); > > if (!vc->vc_inuse) { > - pr_warn("%s: No pseudo device\n", __func__); > + errorf(fc, "coda: No pseudo device"); > error = -EINVAL; > goto unlock_out; > } > > if (vc->vc_sb) { > - pr_warn("%s: Device already mounted\n", __func__); > + errorf(fc, "coda: Device already mounted"); > error = -EBUSY; > goto unlock_out; > } > @@ -313,18 +342,45 @@ static int coda_statfs(struct dentry *dentry, struct kstatfs *buf) > return 0; > } > > -/* init_coda: used by filesystems.c to register coda */ > +static int coda_get_tree(struct fs_context *fc) > +{ > + if (task_active_pid_ns(current) != &init_pid_ns) > + return -EINVAL; Fwiw, this check is redundant since you're performing the same check in coda_fill_super() again.