Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Convert coda to use the new mount API

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@redhat.com>
Co-developed-by: Eric Sandeen <sandeen@redhat.com>
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
[sandeen: forward port to current upstream mount API interfaces]
Link: https://lore.kernel.org/r/97650eeb-94c7-4041-b58c-90e81e76b699@redhat.com
Tested-by: Jan Harkes <jaharkes@cs.cmu.edu>
Reviewed-by: Ian Kent <raven@themaw.net>
cc: coda@cs.cmu.edu
Signed-off-by: Christian Brauner <brauner@kernel.org>

authored by

David Howells and committed by
Christian Brauner
5916f439 0611a640

+101 -48
+101 -48
fs/coda/inode.c
··· 24 24 #include <linux/pid_namespace.h> 25 25 #include <linux/uaccess.h> 26 26 #include <linux/fs.h> 27 + #include <linux/fs_context.h> 28 + #include <linux/fs_parser.h> 27 29 #include <linux/vmalloc.h> 28 30 29 31 #include <linux/coda.h> ··· 89 87 kmem_cache_destroy(coda_inode_cachep); 90 88 } 91 89 92 - static int coda_remount(struct super_block *sb, int *flags, char *data) 90 + static int coda_reconfigure(struct fs_context *fc) 93 91 { 94 - sync_filesystem(sb); 95 - *flags |= SB_NOATIME; 92 + sync_filesystem(fc->root->d_sb); 93 + fc->sb_flags |= SB_NOATIME; 96 94 return 0; 97 95 } 98 96 ··· 104 102 .evict_inode = coda_evict_inode, 105 103 .put_super = coda_put_super, 106 104 .statfs = coda_statfs, 107 - .remount_fs = coda_remount, 108 105 }; 109 106 110 - static int get_device_index(struct coda_mount_data *data) 107 + struct coda_fs_context { 108 + int idx; 109 + }; 110 + 111 + enum { 112 + Opt_fd, 113 + }; 114 + 115 + static const struct fs_parameter_spec coda_param_specs[] = { 116 + fsparam_fd ("fd", Opt_fd), 117 + {} 118 + }; 119 + 120 + static int coda_parse_fd(struct fs_context *fc, int fd) 111 121 { 122 + struct coda_fs_context *ctx = fc->fs_private; 112 123 struct fd f; 113 124 struct inode *inode; 114 125 int idx; 115 126 116 - if (data == NULL) { 117 - pr_warn("%s: Bad mount data\n", __func__); 118 - return -1; 119 - } 120 - 121 - if (data->version != CODA_MOUNT_VERSION) { 122 - pr_warn("%s: Bad mount version\n", __func__); 123 - return -1; 124 - } 125 - 126 - f = fdget(data->fd); 127 + f = fdget(fd); 127 128 if (!f.file) 128 - goto Ebadf; 129 + return -EBADF; 129 130 inode = file_inode(f.file); 130 131 if (!S_ISCHR(inode->i_mode) || imajor(inode) != CODA_PSDEV_MAJOR) { 131 132 fdput(f); 132 - goto Ebadf; 133 + return invalf(fc, "code: Not coda psdev"); 133 134 } 134 135 135 136 idx = iminor(inode); 136 137 fdput(f); 137 138 138 - if (idx < 0 || idx >= MAX_CODADEVS) { 139 - pr_warn("%s: Bad minor number\n", __func__); 140 - return -1; 141 - } 142 - 143 - return idx; 144 - Ebadf: 145 - pr_warn("%s: Bad file\n", __func__); 146 - return -1; 139 + if (idx < 0 || idx >= MAX_CODADEVS) 140 + return invalf(fc, "coda: Bad minor number"); 141 + ctx->idx = idx; 142 + return 0; 147 143 } 148 144 149 - static int coda_fill_super(struct super_block *sb, void *data, int silent) 145 + static int coda_parse_param(struct fs_context *fc, struct fs_parameter *param) 150 146 { 147 + struct fs_parse_result result; 148 + int opt; 149 + 150 + opt = fs_parse(fc, coda_param_specs, param, &result); 151 + if (opt < 0) 152 + return opt; 153 + 154 + switch (opt) { 155 + case Opt_fd: 156 + return coda_parse_fd(fc, result.uint_32); 157 + } 158 + 159 + return 0; 160 + } 161 + 162 + /* 163 + * Parse coda's binary mount data form. We ignore any errors and go with index 164 + * 0 if we get one for backward compatibility. 165 + */ 166 + static int coda_parse_monolithic(struct fs_context *fc, void *_data) 167 + { 168 + struct coda_mount_data *data = _data; 169 + 170 + if (!data) 171 + return invalf(fc, "coda: Bad mount data"); 172 + 173 + if (data->version != CODA_MOUNT_VERSION) 174 + return invalf(fc, "coda: Bad mount version"); 175 + 176 + coda_parse_fd(fc, data->fd); 177 + return 0; 178 + } 179 + 180 + static int coda_fill_super(struct super_block *sb, struct fs_context *fc) 181 + { 182 + struct coda_fs_context *ctx = fc->fs_private; 151 183 struct inode *root = NULL; 152 184 struct venus_comm *vc; 153 185 struct CodaFid fid; 154 186 int error; 155 - int idx; 156 187 157 - if (task_active_pid_ns(current) != &init_pid_ns) 158 - return -EINVAL; 188 + infof(fc, "coda: device index: %i\n", ctx->idx); 159 189 160 - idx = get_device_index((struct coda_mount_data *) data); 161 - 162 - /* Ignore errors in data, for backward compatibility */ 163 - if(idx == -1) 164 - idx = 0; 165 - 166 - pr_info("%s: device index: %i\n", __func__, idx); 167 - 168 - vc = &coda_comms[idx]; 190 + vc = &coda_comms[ctx->idx]; 169 191 mutex_lock(&vc->vc_mutex); 170 192 171 193 if (!vc->vc_inuse) { 172 - pr_warn("%s: No pseudo device\n", __func__); 194 + errorf(fc, "coda: No pseudo device"); 173 195 error = -EINVAL; 174 196 goto unlock_out; 175 197 } 176 198 177 199 if (vc->vc_sb) { 178 - pr_warn("%s: Device already mounted\n", __func__); 200 + errorf(fc, "coda: Device already mounted"); 179 201 error = -EBUSY; 180 202 goto unlock_out; 181 203 } ··· 339 313 return 0; 340 314 } 341 315 342 - /* init_coda: used by filesystems.c to register coda */ 343 - 344 - static struct dentry *coda_mount(struct file_system_type *fs_type, 345 - int flags, const char *dev_name, void *data) 316 + static int coda_get_tree(struct fs_context *fc) 346 317 { 347 - return mount_nodev(fs_type, flags, data, coda_fill_super); 318 + if (task_active_pid_ns(current) != &init_pid_ns) 319 + return -EINVAL; 320 + 321 + return get_tree_nodev(fc, coda_fill_super); 322 + } 323 + 324 + static void coda_free_fc(struct fs_context *fc) 325 + { 326 + kfree(fc->fs_private); 327 + } 328 + 329 + static const struct fs_context_operations coda_context_ops = { 330 + .free = coda_free_fc, 331 + .parse_param = coda_parse_param, 332 + .parse_monolithic = coda_parse_monolithic, 333 + .get_tree = coda_get_tree, 334 + .reconfigure = coda_reconfigure, 335 + }; 336 + 337 + static int coda_init_fs_context(struct fs_context *fc) 338 + { 339 + struct coda_fs_context *ctx; 340 + 341 + ctx = kzalloc(sizeof(struct coda_fs_context), GFP_KERNEL); 342 + if (!ctx) 343 + return -ENOMEM; 344 + 345 + fc->fs_private = ctx; 346 + fc->ops = &coda_context_ops; 347 + return 0; 348 348 } 349 349 350 350 struct file_system_type coda_fs_type = { 351 351 .owner = THIS_MODULE, 352 352 .name = "coda", 353 - .mount = coda_mount, 353 + .init_fs_context = coda_init_fs_context, 354 + .parameters = coda_param_specs, 354 355 .kill_sb = kill_anon_super, 355 356 .fs_flags = FS_BINARY_MOUNTDATA, 356 357 };