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

9p: convert to the new mount API

Convert 9p to the new mount API. This patch consolidates all parsing
into fs/9p/v9fs.c, which stores all results into a filesystem context
which can be passed to the various transports as needed.

Some of the parsing helper functions such as get_cache_mode() have been
eliminated in favor of using the new mount API's enum param type,
for simplicity.

Signed-off-by: Eric Sandeen <sandeen@redhat.com>
Message-ID: <20251010214222.1347785-5-sandeen@redhat.com>
[ Dominique: handled source explicitly as per follow-up discussion ]
Signed-off-by: Dominique Martinet <asmadeus@codewreck.org>

authored by

Eric Sandeen and committed by
Dominique Martinet
1f3e4142 075e8bd4

+432 -660
+291 -277
fs/9p/v9fs.c
··· 13 13 #include <linux/fs.h> 14 14 #include <linux/sched.h> 15 15 #include <linux/cred.h> 16 - #include <linux/parser.h> 16 + #include <linux/fs_parser.h> 17 + #include <linux/fs_context.h> 17 18 #include <linux/slab.h> 18 19 #include <linux/seq_file.h> 19 20 #include <net/9p/9p.h> ··· 34 33 */ 35 34 36 35 enum { 36 + /* Mount-point source, we need to handle this explicitly because 37 + * the code below accepts unknown args and the vfs layer only handles 38 + * source if we rejected it as EINVAL */ 39 + Opt_source, 37 40 /* Options that take integer arguments */ 38 41 Opt_debug, Opt_dfltuid, Opt_dfltgid, Opt_afid, 39 42 /* String options */ ··· 48 43 Opt_access, Opt_posixacl, 49 44 /* Lock timeout option */ 50 45 Opt_locktimeout, 51 - /* Error token */ 52 - Opt_err 46 + 47 + /* Client options */ 48 + Opt_msize, Opt_trans, Opt_legacy, Opt_version, 49 + 50 + /* fd transport options */ 51 + /* Options that take integer arguments */ 52 + Opt_rfdno, Opt_wfdno, 53 + /* Options that take no arguments */ 54 + 55 + /* rdma transport options */ 56 + /* Options that take integer arguments */ 57 + Opt_rq_depth, Opt_sq_depth, Opt_timeout, 58 + 59 + /* Options for both fd and rdma transports */ 60 + Opt_port, Opt_privport, 53 61 }; 54 62 55 - static const match_table_t tokens = { 56 - {Opt_debug, "debug=%x"}, 57 - {Opt_dfltuid, "dfltuid=%u"}, 58 - {Opt_dfltgid, "dfltgid=%u"}, 59 - {Opt_afid, "afid=%u"}, 60 - {Opt_uname, "uname=%s"}, 61 - {Opt_remotename, "aname=%s"}, 62 - {Opt_nodevmap, "nodevmap"}, 63 - {Opt_noxattr, "noxattr"}, 64 - {Opt_directio, "directio"}, 65 - {Opt_ignoreqv, "ignoreqv"}, 66 - {Opt_cache, "cache=%s"}, 67 - {Opt_cachetag, "cachetag=%s"}, 68 - {Opt_access, "access=%s"}, 69 - {Opt_posixacl, "posixacl"}, 70 - {Opt_locktimeout, "locktimeout=%u"}, 71 - {Opt_err, NULL} 63 + static const struct constant_table p9_versions[] = { 64 + { "9p2000", p9_proto_legacy }, 65 + { "9p2000.u", p9_proto_2000u }, 66 + { "9p2000.L", p9_proto_2000L }, 67 + {} 72 68 }; 73 69 74 - /* Interpret mount options for cache mode */ 75 - static int get_cache_mode(char *s) 76 - { 77 - int version = -EINVAL; 70 + static const struct constant_table p9_cache_mode[] = { 71 + { "loose", CACHE_SC_LOOSE }, 72 + { "fscache", CACHE_SC_FSCACHE }, 73 + { "mmap", CACHE_SC_MMAP }, 74 + { "readahead", CACHE_SC_READAHEAD }, 75 + { "none", CACHE_SC_NONE }, 76 + {} 77 + }; 78 78 79 - if (!strcmp(s, "loose")) { 80 - version = CACHE_SC_LOOSE; 81 - p9_debug(P9_DEBUG_9P, "Cache mode: loose\n"); 82 - } else if (!strcmp(s, "fscache")) { 83 - version = CACHE_SC_FSCACHE; 84 - p9_debug(P9_DEBUG_9P, "Cache mode: fscache\n"); 85 - } else if (!strcmp(s, "mmap")) { 86 - version = CACHE_SC_MMAP; 87 - p9_debug(P9_DEBUG_9P, "Cache mode: mmap\n"); 88 - } else if (!strcmp(s, "readahead")) { 89 - version = CACHE_SC_READAHEAD; 90 - p9_debug(P9_DEBUG_9P, "Cache mode: readahead\n"); 91 - } else if (!strcmp(s, "none")) { 92 - version = CACHE_SC_NONE; 93 - p9_debug(P9_DEBUG_9P, "Cache mode: none\n"); 94 - } else if (kstrtoint(s, 0, &version) != 0) { 95 - version = -EINVAL; 96 - pr_info("Unknown Cache mode or invalid value %s\n", s); 97 - } 98 - return version; 99 - } 79 + /* 80 + * This structure contains all parameters used for the core code, 81 + * the client, and all the transports. 82 + */ 83 + const struct fs_parameter_spec v9fs_param_spec[] = { 84 + fsparam_string ("source", Opt_source), 85 + fsparam_u32hex ("debug", Opt_debug), 86 + fsparam_uid ("dfltuid", Opt_dfltuid), 87 + fsparam_gid ("dfltgid", Opt_dfltgid), 88 + fsparam_u32 ("afid", Opt_afid), 89 + fsparam_string ("uname", Opt_uname), 90 + fsparam_string ("aname", Opt_remotename), 91 + fsparam_flag ("nodevmap", Opt_nodevmap), 92 + fsparam_flag ("noxattr", Opt_noxattr), 93 + fsparam_flag ("directio", Opt_directio), 94 + fsparam_flag ("ignoreqv", Opt_ignoreqv), 95 + fsparam_enum ("cache", Opt_cache, p9_cache_mode), 96 + fsparam_string ("cachetag", Opt_cachetag), 97 + fsparam_string ("access", Opt_access), 98 + fsparam_flag ("posixacl", Opt_posixacl), 99 + fsparam_u32 ("locktimeout", Opt_locktimeout), 100 + 101 + /* client options */ 102 + fsparam_u32 ("msize", Opt_msize), 103 + fsparam_flag ("noextend", Opt_legacy), 104 + fsparam_string ("trans", Opt_trans), 105 + fsparam_enum ("version", Opt_version, p9_versions), 106 + 107 + /* fd transport options */ 108 + fsparam_u32 ("rfdno", Opt_rfdno), 109 + fsparam_u32 ("wfdno", Opt_wfdno), 110 + 111 + /* rdma transport options */ 112 + fsparam_u32 ("sq", Opt_sq_depth), 113 + fsparam_u32 ("rq", Opt_rq_depth), 114 + fsparam_u32 ("timeout", Opt_timeout), 115 + 116 + /* fd and rdma transprt options */ 117 + fsparam_u32 ("port", Opt_port), 118 + fsparam_flag ("privport", Opt_privport), 119 + {} 120 + }; 100 121 101 122 /* 102 123 * Display the mount options in /proc/mounts. ··· 184 153 } 185 154 186 155 /** 187 - * v9fs_parse_options - parse mount options into session structure 188 - * @v9ses: existing v9fs session information 189 - * @opts: The mount option string 156 + * v9fs_parse_param - parse a mount option into the filesystem context 157 + * @fc: the filesystem context 158 + * @param: the parameter to parse 190 159 * 191 160 * Return 0 upon success, -ERRNO upon failure. 192 161 */ 193 - 194 - static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts) 162 + int v9fs_parse_param(struct fs_context *fc, struct fs_parameter *param) 195 163 { 196 - char *options, *tmp_options; 197 - substring_t args[MAX_OPT_ARGS]; 198 - char *p; 199 - int option = 0; 164 + struct v9fs_context *ctx = fc->fs_private; 165 + struct fs_parse_result result; 200 166 char *s; 201 - int ret = 0; 167 + int r; 168 + int opt; 169 + struct p9_client_opts *clnt = &ctx->client_opts; 170 + struct p9_fd_opts *fd_opts = &ctx->fd_opts; 171 + struct p9_rdma_opts *rdma_opts = &ctx->rdma_opts; 172 + struct p9_session_opts *session_opts = &ctx->session_opts; 202 173 203 - /* setup defaults */ 204 - v9ses->afid = ~0; 205 - v9ses->debug = 0; 206 - v9ses->cache = CACHE_NONE; 207 - #ifdef CONFIG_9P_FSCACHE 208 - v9ses->cachetag = NULL; 209 - #endif 210 - v9ses->session_lock_timeout = P9_LOCK_TIMEOUT; 174 + opt = fs_parse(fc, v9fs_param_spec, param, &result); 175 + if (opt < 0) { 176 + /* 177 + * We might like to report bad mount options here, but 178 + * traditionally 9p has ignored unknown mount options 179 + */ 180 + if (opt == -ENOPARAM) 181 + return 0; 211 182 212 - if (!opts) 213 - return 0; 214 - 215 - tmp_options = kstrdup(opts, GFP_KERNEL); 216 - if (!tmp_options) { 217 - ret = -ENOMEM; 218 - goto fail_option_alloc; 183 + return opt; 219 184 } 220 - options = tmp_options; 221 185 222 - while ((p = strsep(&options, ",")) != NULL) { 223 - int token, r; 224 - 225 - if (!*p) 226 - continue; 227 - 228 - token = match_token(p, tokens, args); 229 - switch (token) { 230 - case Opt_debug: 231 - r = match_int(&args[0], &option); 232 - if (r < 0) { 233 - p9_debug(P9_DEBUG_ERROR, 234 - "integer field, but no integer?\n"); 235 - ret = r; 236 - } else { 237 - v9ses->debug = option; 238 - #ifdef CONFIG_NET_9P_DEBUG 239 - p9_debug_level = option; 240 - #endif 241 - } 242 - break; 243 - 244 - case Opt_dfltuid: 245 - r = match_int(&args[0], &option); 246 - if (r < 0) { 247 - p9_debug(P9_DEBUG_ERROR, 248 - "integer field, but no integer?\n"); 249 - ret = r; 250 - continue; 251 - } 252 - v9ses->dfltuid = make_kuid(current_user_ns(), option); 253 - if (!uid_valid(v9ses->dfltuid)) { 254 - p9_debug(P9_DEBUG_ERROR, 255 - "uid field, but not a uid?\n"); 256 - ret = -EINVAL; 257 - } 258 - break; 259 - case Opt_dfltgid: 260 - r = match_int(&args[0], &option); 261 - if (r < 0) { 262 - p9_debug(P9_DEBUG_ERROR, 263 - "integer field, but no integer?\n"); 264 - ret = r; 265 - continue; 266 - } 267 - v9ses->dfltgid = make_kgid(current_user_ns(), option); 268 - if (!gid_valid(v9ses->dfltgid)) { 269 - p9_debug(P9_DEBUG_ERROR, 270 - "gid field, but not a gid?\n"); 271 - ret = -EINVAL; 272 - } 273 - break; 274 - case Opt_afid: 275 - r = match_int(&args[0], &option); 276 - if (r < 0) { 277 - p9_debug(P9_DEBUG_ERROR, 278 - "integer field, but no integer?\n"); 279 - ret = r; 280 - } else { 281 - v9ses->afid = option; 282 - } 283 - break; 284 - case Opt_uname: 285 - kfree(v9ses->uname); 286 - v9ses->uname = match_strdup(&args[0]); 287 - if (!v9ses->uname) { 288 - ret = -ENOMEM; 289 - goto free_and_return; 290 - } 291 - break; 292 - case Opt_remotename: 293 - kfree(v9ses->aname); 294 - v9ses->aname = match_strdup(&args[0]); 295 - if (!v9ses->aname) { 296 - ret = -ENOMEM; 297 - goto free_and_return; 298 - } 299 - break; 300 - case Opt_nodevmap: 301 - v9ses->nodev = 1; 302 - break; 303 - case Opt_noxattr: 304 - v9ses->flags |= V9FS_NO_XATTR; 305 - break; 306 - case Opt_directio: 307 - v9ses->flags |= V9FS_DIRECT_IO; 308 - break; 309 - case Opt_ignoreqv: 310 - v9ses->flags |= V9FS_IGNORE_QV; 311 - break; 312 - case Opt_cachetag: 313 - #ifdef CONFIG_9P_FSCACHE 314 - kfree(v9ses->cachetag); 315 - v9ses->cachetag = match_strdup(&args[0]); 316 - if (!v9ses->cachetag) { 317 - ret = -ENOMEM; 318 - goto free_and_return; 319 - } 320 - #endif 321 - break; 322 - case Opt_cache: 323 - s = match_strdup(&args[0]); 324 - if (!s) { 325 - ret = -ENOMEM; 326 - p9_debug(P9_DEBUG_ERROR, 327 - "problem allocating copy of cache arg\n"); 328 - goto free_and_return; 329 - } 330 - r = get_cache_mode(s); 331 - if (r < 0) 332 - ret = r; 333 - else 334 - v9ses->cache = r; 335 - 336 - kfree(s); 337 - break; 338 - 339 - case Opt_access: 340 - s = match_strdup(&args[0]); 341 - if (!s) { 342 - ret = -ENOMEM; 343 - p9_debug(P9_DEBUG_ERROR, 344 - "problem allocating copy of access arg\n"); 345 - goto free_and_return; 346 - } 347 - 348 - v9ses->flags &= ~V9FS_ACCESS_MASK; 349 - if (strcmp(s, "user") == 0) 350 - v9ses->flags |= V9FS_ACCESS_USER; 351 - else if (strcmp(s, "any") == 0) 352 - v9ses->flags |= V9FS_ACCESS_ANY; 353 - else if (strcmp(s, "client") == 0) { 354 - v9ses->flags |= V9FS_ACCESS_CLIENT; 355 - } else { 356 - uid_t uid; 357 - 358 - v9ses->flags |= V9FS_ACCESS_SINGLE; 359 - r = kstrtouint(s, 10, &uid); 360 - if (r) { 361 - ret = r; 362 - pr_info("Unknown access argument %s: %d\n", 363 - s, r); 364 - kfree(s); 365 - continue; 366 - } 367 - v9ses->uid = make_kuid(current_user_ns(), uid); 368 - if (!uid_valid(v9ses->uid)) { 369 - ret = -EINVAL; 370 - pr_info("Unknown uid %s\n", s); 371 - } 372 - } 373 - 374 - kfree(s); 375 - break; 376 - 377 - case Opt_posixacl: 378 - #ifdef CONFIG_9P_FS_POSIX_ACL 379 - v9ses->flags |= V9FS_POSIX_ACL; 380 - #else 381 - p9_debug(P9_DEBUG_ERROR, 382 - "Not defined CONFIG_9P_FS_POSIX_ACL. Ignoring posixacl option\n"); 383 - #endif 384 - break; 385 - 386 - case Opt_locktimeout: 387 - r = match_int(&args[0], &option); 388 - if (r < 0) { 389 - p9_debug(P9_DEBUG_ERROR, 390 - "integer field, but no integer?\n"); 391 - ret = r; 392 - continue; 393 - } 394 - if (option < 1) { 395 - p9_debug(P9_DEBUG_ERROR, 396 - "locktimeout must be a greater than zero integer.\n"); 397 - ret = -EINVAL; 398 - continue; 399 - } 400 - v9ses->session_lock_timeout = (long)option * HZ; 401 - break; 402 - 403 - default: 404 - continue; 186 + switch (opt) { 187 + case Opt_source: 188 + if (fc->source) { 189 + pr_info("p9: multiple sources not supported\n"); 190 + return -EINVAL; 405 191 } 192 + fc->source = param->string; 193 + param->string = NULL; 194 + break; 195 + case Opt_debug: 196 + session_opts->debug = result.uint_32; 197 + #ifdef CONFIG_NET_9P_DEBUG 198 + p9_debug_level = result.uint_32; 199 + #endif 200 + break; 201 + 202 + case Opt_dfltuid: 203 + session_opts->dfltuid = result.uid; 204 + break; 205 + case Opt_dfltgid: 206 + session_opts->dfltgid = result.gid; 207 + break; 208 + case Opt_afid: 209 + session_opts->afid = result.uint_32; 210 + break; 211 + case Opt_uname: 212 + kfree(session_opts->uname); 213 + session_opts->uname = param->string; 214 + param->string = NULL; 215 + break; 216 + case Opt_remotename: 217 + kfree(session_opts->aname); 218 + session_opts->aname = param->string; 219 + param->string = NULL; 220 + break; 221 + case Opt_nodevmap: 222 + session_opts->nodev = 1; 223 + break; 224 + case Opt_noxattr: 225 + session_opts->flags |= V9FS_NO_XATTR; 226 + break; 227 + case Opt_directio: 228 + session_opts->flags |= V9FS_DIRECT_IO; 229 + break; 230 + case Opt_ignoreqv: 231 + session_opts->flags |= V9FS_IGNORE_QV; 232 + break; 233 + case Opt_cachetag: 234 + #ifdef CONFIG_9P_FSCACHE 235 + kfree(session_opts->cachetag); 236 + session_opts->cachetag = param->string; 237 + param->string = NULL; 238 + #endif 239 + break; 240 + case Opt_cache: 241 + session_opts->cache = result.uint_32; 242 + p9_debug(P9_DEBUG_9P, "Cache mode: %s\n", param->string); 243 + break; 244 + case Opt_access: 245 + s = param->string; 246 + session_opts->flags &= ~V9FS_ACCESS_MASK; 247 + if (strcmp(s, "user") == 0) { 248 + session_opts->flags |= V9FS_ACCESS_USER; 249 + } else if (strcmp(s, "any") == 0) { 250 + session_opts->flags |= V9FS_ACCESS_ANY; 251 + } else if (strcmp(s, "client") == 0) { 252 + session_opts->flags |= V9FS_ACCESS_CLIENT; 253 + } else { 254 + uid_t uid; 255 + 256 + session_opts->flags |= V9FS_ACCESS_SINGLE; 257 + r = kstrtouint(s, 10, &uid); 258 + if (r) { 259 + pr_info("Unknown access argument %s: %d\n", 260 + param->string, r); 261 + return r; 262 + } 263 + session_opts->uid = make_kuid(current_user_ns(), uid); 264 + if (!uid_valid(session_opts->uid)) { 265 + pr_info("Unknown uid %s\n", s); 266 + return -EINVAL; 267 + } 268 + } 269 + break; 270 + 271 + case Opt_posixacl: 272 + #ifdef CONFIG_9P_FS_POSIX_ACL 273 + session_opts->flags |= V9FS_POSIX_ACL; 274 + #else 275 + p9_debug(P9_DEBUG_ERROR, 276 + "Not defined CONFIG_9P_FS_POSIX_ACL. Ignoring posixacl option\n"); 277 + #endif 278 + break; 279 + 280 + case Opt_locktimeout: 281 + if (result.uint_32 < 1) { 282 + p9_debug(P9_DEBUG_ERROR, 283 + "locktimeout must be a greater than zero integer.\n"); 284 + return -EINVAL; 285 + } 286 + session_opts->session_lock_timeout = (long)result.uint_32 * HZ; 287 + break; 288 + 289 + /* Options for client */ 290 + case Opt_msize: 291 + if (result.uint_32 < 4096) { 292 + p9_debug(P9_DEBUG_ERROR, "msize should be at least 4k\n"); 293 + return -EINVAL; 294 + } 295 + if (result.uint_32 > INT_MAX) { 296 + p9_debug(P9_DEBUG_ERROR, "msize too big\n"); 297 + return -EINVAL; 298 + } 299 + clnt->msize = result.uint_32; 300 + break; 301 + case Opt_trans: 302 + v9fs_put_trans(clnt->trans_mod); 303 + clnt->trans_mod = v9fs_get_trans_by_name(param->string); 304 + if (!clnt->trans_mod) { 305 + pr_info("Could not find request transport: %s\n", 306 + param->string); 307 + return -EINVAL; 308 + } 309 + break; 310 + case Opt_legacy: 311 + clnt->proto_version = p9_proto_legacy; 312 + break; 313 + case Opt_version: 314 + clnt->proto_version = result.uint_32; 315 + p9_debug(P9_DEBUG_9P, "Protocol version: %s\n", param->string); 316 + break; 317 + /* Options for fd transport */ 318 + case Opt_rfdno: 319 + fd_opts->rfd = result.uint_32; 320 + break; 321 + case Opt_wfdno: 322 + fd_opts->wfd = result.uint_32; 323 + break; 324 + /* Options for rdma transport */ 325 + case Opt_sq_depth: 326 + rdma_opts->sq_depth = result.uint_32; 327 + break; 328 + case Opt_rq_depth: 329 + rdma_opts->rq_depth = result.uint_32; 330 + break; 331 + case Opt_timeout: 332 + rdma_opts->timeout = result.uint_32; 333 + break; 334 + /* Options for both fd and rdma transports */ 335 + case Opt_port: 336 + fd_opts->port = result.uint_32; 337 + rdma_opts->port = result.uint_32; 338 + break; 339 + case Opt_privport: 340 + fd_opts->privport = true; 341 + rdma_opts->port = true; 342 + break; 406 343 } 407 344 408 - free_and_return: 409 - kfree(tmp_options); 410 - fail_option_alloc: 411 - return ret; 345 + return 0; 346 + } 347 + 348 + static void v9fs_apply_options(struct v9fs_session_info *v9ses, 349 + struct fs_context *fc) 350 + { 351 + struct v9fs_context *ctx = fc->fs_private; 352 + 353 + v9ses->debug = ctx->session_opts.debug; 354 + v9ses->dfltuid = ctx->session_opts.dfltuid; 355 + v9ses->dfltgid = ctx->session_opts.dfltgid; 356 + v9ses->afid = ctx->session_opts.afid; 357 + v9ses->uname = ctx->session_opts.uname; 358 + ctx->session_opts.uname = NULL; 359 + v9ses->aname = ctx->session_opts.aname; 360 + ctx->session_opts.aname = NULL; 361 + v9ses->nodev = ctx->session_opts.nodev; 362 + /* 363 + * Note that we must |= flags here as session_init already 364 + * set basic flags. This adds in flags from parsed options. 365 + */ 366 + v9ses->flags |= ctx->session_opts.flags; 367 + #ifdef CONFIG_9P_FSCACHE 368 + v9ses->cachetag = ctx->session_opts.cachetag; 369 + ctx->session_opts.cachetag = NULL; 370 + #endif 371 + v9ses->cache = ctx->session_opts.cache; 372 + v9ses->uid = ctx->session_opts.uid; 373 + v9ses->session_lock_timeout = ctx->session_opts.session_lock_timeout; 412 374 } 413 375 414 376 /** 415 377 * v9fs_session_init - initialize session 416 378 * @v9ses: session information structure 417 - * @dev_name: device being mounted 418 - * @data: options 379 + * @fc: the filesystem mount context 419 380 * 420 381 */ 421 382 422 383 struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses, 423 - const char *dev_name, char *data) 384 + struct fs_context *fc) 424 385 { 425 386 struct p9_fid *fid; 426 387 int rc = -ENOMEM; 427 388 428 - v9ses->uname = kstrdup(V9FS_DEFUSER, GFP_KERNEL); 429 - if (!v9ses->uname) 430 - goto err_names; 431 - 432 - v9ses->aname = kstrdup(V9FS_DEFANAME, GFP_KERNEL); 433 - if (!v9ses->aname) 434 - goto err_names; 435 389 init_rwsem(&v9ses->rename_sem); 436 390 437 - v9ses->uid = INVALID_UID; 438 - v9ses->dfltuid = V9FS_DEFUID; 439 - v9ses->dfltgid = V9FS_DEFGID; 440 - 441 - v9ses->clnt = p9_client_create(dev_name, data); 391 + v9ses->clnt = p9_client_create(fc); 442 392 if (IS_ERR(v9ses->clnt)) { 443 393 rc = PTR_ERR(v9ses->clnt); 444 394 p9_debug(P9_DEBUG_ERROR, "problem initializing 9p client\n"); 445 395 goto err_names; 446 396 } 447 397 398 + /* 399 + * Initialize flags on the real v9ses. v9fs_apply_options below 400 + * will |= the additional flags from parsed options. 401 + */ 448 402 v9ses->flags = V9FS_ACCESS_USER; 449 403 450 404 if (p9_is_proto_dotl(v9ses->clnt)) { ··· 439 423 v9ses->flags |= V9FS_PROTO_2000U; 440 424 } 441 425 442 - rc = v9fs_parse_options(v9ses, data); 443 - if (rc < 0) 444 - goto err_clnt; 426 + v9fs_apply_options(v9ses, fc); 445 427 446 428 v9ses->maxdata = v9ses->clnt->msize - P9_IOHDRSZ; 447 429 ··· 485 471 #ifdef CONFIG_9P_FSCACHE 486 472 /* register the session for caching */ 487 473 if (v9ses->cache & CACHE_FSCACHE) { 488 - rc = v9fs_cache_session_get_cookie(v9ses, dev_name); 474 + rc = v9fs_cache_session_get_cookie(v9ses, fc->source); 489 475 if (rc < 0) 490 476 goto err_clnt; 491 477 }
+6 -1
fs/9p/v9fs.h
··· 10 10 11 11 #include <linux/backing-dev.h> 12 12 #include <linux/netfs.h> 13 + #include <linux/fs_parser.h> 14 + #include <net/9p/client.h> 15 + #include <net/9p/transport.h> 13 16 14 17 /** 15 18 * enum p9_session_flags - option flags for each 9P session ··· 166 163 #endif 167 164 } 168 165 166 + extern const struct fs_parameter_spec v9fs_param_spec[]; 169 167 168 + extern int v9fs_parse_param(struct fs_context *fc, struct fs_parameter *param); 170 169 extern int v9fs_show_options(struct seq_file *m, struct dentry *root); 171 170 172 171 struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses, 173 - const char *dev_name, char *data); 172 + struct fs_context *fc); 174 173 extern void v9fs_session_close(struct v9fs_session_info *v9ses); 175 174 extern void v9fs_session_cancel(struct v9fs_session_info *v9ses); 176 175 extern void v9fs_session_begin_cancel(struct v9fs_session_info *v9ses);
+91 -39
fs/9p/vfs_super.c
··· 19 19 #include <linux/statfs.h> 20 20 #include <linux/magic.h> 21 21 #include <linux/fscache.h> 22 + #include <linux/fs_context.h> 22 23 #include <net/9p/9p.h> 23 24 #include <net/9p/client.h> 24 25 ··· 31 30 32 31 static const struct super_operations v9fs_super_ops, v9fs_super_ops_dotl; 33 32 34 - /** 35 - * v9fs_set_super - set the superblock 36 - * @s: super block 37 - * @data: file system specific data 38 - * 39 - */ 40 - 41 - static int v9fs_set_super(struct super_block *s, void *data) 42 - { 43 - s->s_fs_info = data; 44 - return set_anon_super(s, data); 45 - } 46 - 47 - /** 48 - * v9fs_fill_super - populate superblock with info 49 - * @sb: superblock 50 - * @v9ses: session information 51 - * @flags: flags propagated from v9fs_mount() 52 - * 53 - */ 54 - 55 - static int 56 - v9fs_fill_super(struct super_block *sb, struct v9fs_session_info *v9ses, 57 - int flags) 33 + static int v9fs_fill_super(struct super_block *sb) 58 34 { 59 35 int ret; 36 + struct v9fs_session_info *v9ses = v9ses = sb->s_fs_info; 60 37 61 38 sb->s_maxbytes = MAX_LFS_FILESIZE; 62 39 sb->s_blocksize_bits = fls(v9ses->maxdata - 1); ··· 74 95 } 75 96 76 97 /** 77 - * v9fs_mount - mount a superblock 78 - * @fs_type: file system type 79 - * @flags: mount flags 80 - * @dev_name: device name that was mounted 81 - * @data: mount options 98 + * v9fs_get_tree - create the mountable root and superblock 99 + * @fc: the filesystem context 82 100 * 83 101 */ 84 102 85 - static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags, 86 - const char *dev_name, void *data) 103 + static int v9fs_get_tree(struct fs_context *fc) 87 104 { 88 105 struct super_block *sb = NULL; 89 106 struct inode *inode = NULL; ··· 92 117 93 118 v9ses = kzalloc(sizeof(struct v9fs_session_info), GFP_KERNEL); 94 119 if (!v9ses) 95 - return ERR_PTR(-ENOMEM); 120 + return -ENOMEM; 96 121 97 - fid = v9fs_session_init(v9ses, dev_name, data); 122 + fid = v9fs_session_init(v9ses, fc); 98 123 if (IS_ERR(fid)) { 99 124 retval = PTR_ERR(fid); 100 125 goto free_session; 101 126 } 102 127 103 - sb = sget(fs_type, NULL, v9fs_set_super, flags, v9ses); 128 + fc->s_fs_info = v9ses; 129 + sb = sget_fc(fc, NULL, set_anon_super_fc); 104 130 if (IS_ERR(sb)) { 105 131 retval = PTR_ERR(sb); 106 132 goto clunk_fid; 107 133 } 108 - retval = v9fs_fill_super(sb, v9ses, flags); 134 + retval = v9fs_fill_super(sb); 109 135 if (retval) 110 136 goto release_sb; 111 137 ··· 135 159 v9fs_fid_add(root, &fid); 136 160 137 161 p9_debug(P9_DEBUG_VFS, " simple set mount, return 0\n"); 138 - return dget(sb->s_root); 162 + fc->root = dget(sb->s_root); 163 + return 0; 139 164 140 165 clunk_fid: 141 166 p9_fid_put(fid); 142 167 v9fs_session_close(v9ses); 143 168 free_session: 144 169 kfree(v9ses); 145 - return ERR_PTR(retval); 170 + return retval; 146 171 147 172 release_sb: 148 173 /* ··· 154 177 */ 155 178 p9_fid_put(fid); 156 179 deactivate_locked_super(sb); 157 - return ERR_PTR(retval); 180 + return retval; 158 181 } 159 182 160 183 /** ··· 280 303 .write_inode = v9fs_write_inode_dotl, 281 304 }; 282 305 306 + static void v9fs_free_fc(struct fs_context *fc) 307 + { 308 + struct v9fs_context *ctx = fc->fs_private; 309 + 310 + if (!ctx) 311 + return; 312 + 313 + /* These should be NULL by now but guard against leaks */ 314 + kfree(ctx->session_opts.uname); 315 + kfree(ctx->session_opts.aname); 316 + #ifdef CONFIG_9P_FSCACHE 317 + kfree(ctx->session_opts.cachetag); 318 + #endif 319 + if (ctx->client_opts.trans_mod) 320 + v9fs_put_trans(ctx->client_opts.trans_mod); 321 + kfree(ctx); 322 + } 323 + 324 + static const struct fs_context_operations v9fs_context_ops = { 325 + .parse_param = v9fs_parse_param, 326 + .get_tree = v9fs_get_tree, 327 + .free = v9fs_free_fc, 328 + }; 329 + 330 + static int v9fs_init_fs_context(struct fs_context *fc) 331 + { 332 + struct v9fs_context *ctx; 333 + 334 + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); 335 + if (!ctx) 336 + return -ENOMEM; 337 + 338 + /* initialize core options */ 339 + ctx->session_opts.afid = ~0; 340 + ctx->session_opts.cache = CACHE_NONE; 341 + ctx->session_opts.session_lock_timeout = P9_LOCK_TIMEOUT; 342 + ctx->session_opts.uname = kstrdup(V9FS_DEFUSER, GFP_KERNEL); 343 + if (!ctx->session_opts.uname) 344 + goto error; 345 + 346 + ctx->session_opts.aname = kstrdup(V9FS_DEFANAME, GFP_KERNEL); 347 + if (!ctx->session_opts.aname) 348 + goto error; 349 + 350 + ctx->session_opts.uid = INVALID_UID; 351 + ctx->session_opts.dfltuid = V9FS_DEFUID; 352 + ctx->session_opts.dfltgid = V9FS_DEFGID; 353 + 354 + /* initialize client options */ 355 + ctx->client_opts.proto_version = p9_proto_2000L; 356 + ctx->client_opts.msize = DEFAULT_MSIZE; 357 + 358 + /* initialize fd transport options */ 359 + ctx->fd_opts.port = P9_FD_PORT; 360 + ctx->fd_opts.rfd = ~0; 361 + ctx->fd_opts.wfd = ~0; 362 + ctx->fd_opts.privport = false; 363 + 364 + /* initialize rdma transport options */ 365 + ctx->rdma_opts.port = P9_RDMA_PORT; 366 + ctx->rdma_opts.sq_depth = P9_RDMA_SQ_DEPTH; 367 + ctx->rdma_opts.rq_depth = P9_RDMA_RQ_DEPTH; 368 + ctx->rdma_opts.timeout = P9_RDMA_TIMEOUT; 369 + ctx->rdma_opts.privport = false; 370 + 371 + fc->ops = &v9fs_context_ops; 372 + fc->fs_private = ctx; 373 + 374 + return 0; 375 + error: 376 + fc->need_free = 1; 377 + return -ENOMEM; 378 + } 379 + 283 380 struct file_system_type v9fs_fs_type = { 284 381 .name = "9p", 285 - .mount = v9fs_mount, 286 382 .kill_sb = v9fs_kill_super, 287 383 .owner = THIS_MODULE, 288 384 .fs_flags = FS_RENAME_DOES_D_MOVE, 385 + .init_fs_context = v9fs_init_fs_context, 386 + .parameters = v9fs_param_spec, 289 387 }; 290 388 MODULE_ALIAS_FS("9p");
+1 -1
include/net/9p/client.h
··· 279 279 const char *name); 280 280 int p9_client_renameat(struct p9_fid *olddirfid, const char *old_name, 281 281 struct p9_fid *newdirfid, const char *new_name); 282 - struct p9_client *p9_client_create(const char *dev_name, char *options); 282 + struct p9_client *p9_client_create(struct fs_context *fc); 283 283 void p9_client_destroy(struct p9_client *clnt); 284 284 void p9_client_disconnect(struct p9_client *clnt); 285 285 void p9_client_begin_disconnect(struct p9_client *clnt);
+1 -1
include/net/9p/transport.h
··· 57 57 bool supports_vmalloc; /* can work with vmalloc'd buffers */ 58 58 struct module *owner; 59 59 int (*create)(struct p9_client *client, 60 - const char *devname, char *args); 60 + struct fs_context *fc); 61 61 void (*close)(struct p9_client *client); 62 62 int (*request)(struct p9_client *client, struct p9_req_t *req); 63 63 int (*cancel)(struct p9_client *client, struct p9_req_t *req);
+12 -136
net/9p/client.c
··· 20 20 #include <linux/uio.h> 21 21 #include <linux/netfs.h> 22 22 #include <net/9p/9p.h> 23 - #include <linux/parser.h> 24 23 #include <linux/seq_file.h> 24 + #include <linux/fs_context.h> 25 25 #include <net/9p/client.h> 26 26 #include <net/9p/transport.h> 27 27 #include "protocol.h" ··· 32 32 /* Client Option Parsing (code inspired by NFS code) 33 33 * - a little lazy - parse all client options 34 34 */ 35 - 36 - enum { 37 - Opt_msize, 38 - Opt_trans, 39 - Opt_legacy, 40 - Opt_version, 41 - Opt_err, 42 - }; 43 - 44 - static const match_table_t tokens = { 45 - {Opt_msize, "msize=%u"}, 46 - {Opt_legacy, "noextend"}, 47 - {Opt_trans, "trans=%s"}, 48 - {Opt_version, "version=%s"}, 49 - {Opt_err, NULL}, 50 - }; 51 35 52 36 inline int p9_is_proto_dotl(struct p9_client *clnt) 53 37 { ··· 81 97 return err; 82 98 } 83 99 84 - /* Interpret mount option for protocol version */ 85 - static int get_protocol_version(char *s) 100 + static int apply_client_options(struct p9_client *clnt, struct fs_context *fc) 86 101 { 87 - int version = -EINVAL; 102 + struct v9fs_context *ctx = fc->fs_private; 88 103 89 - if (!strcmp(s, "9p2000")) { 90 - version = p9_proto_legacy; 91 - p9_debug(P9_DEBUG_9P, "Protocol version: Legacy\n"); 92 - } else if (!strcmp(s, "9p2000.u")) { 93 - version = p9_proto_2000u; 94 - p9_debug(P9_DEBUG_9P, "Protocol version: 9P2000.u\n"); 95 - } else if (!strcmp(s, "9p2000.L")) { 96 - version = p9_proto_2000L; 97 - p9_debug(P9_DEBUG_9P, "Protocol version: 9P2000.L\n"); 98 - } else { 99 - pr_info("Unknown protocol version %s\n", s); 100 - } 104 + clnt->msize = ctx->client_opts.msize; 105 + clnt->trans_mod = ctx->client_opts.trans_mod; 106 + ctx->client_opts.trans_mod = NULL; 107 + clnt->proto_version = ctx->client_opts.proto_version; 101 108 102 - return version; 103 - } 104 - 105 - /** 106 - * parse_opts - parse mount options into client structure 107 - * @opts: options string passed from mount 108 - * @clnt: existing v9fs client information 109 - * 110 - * Return 0 upon success, -ERRNO upon failure 111 - */ 112 - 113 - static int parse_opts(char *opts, struct p9_client *clnt) 114 - { 115 - char *options, *tmp_options; 116 - char *p; 117 - substring_t args[MAX_OPT_ARGS]; 118 - int option; 119 - char *s; 120 - int ret = 0; 121 - 122 - clnt->proto_version = p9_proto_2000L; 123 - clnt->msize = DEFAULT_MSIZE; 124 - 125 - if (!opts) 126 - return 0; 127 - 128 - tmp_options = kstrdup(opts, GFP_KERNEL); 129 - if (!tmp_options) 130 - return -ENOMEM; 131 - options = tmp_options; 132 - 133 - while ((p = strsep(&options, ",")) != NULL) { 134 - int token, r; 135 - 136 - if (!*p) 137 - continue; 138 - token = match_token(p, tokens, args); 139 - switch (token) { 140 - case Opt_msize: 141 - r = match_int(&args[0], &option); 142 - if (r < 0) { 143 - p9_debug(P9_DEBUG_ERROR, 144 - "integer field, but no integer?\n"); 145 - ret = r; 146 - continue; 147 - } 148 - if (option < 4096) { 149 - p9_debug(P9_DEBUG_ERROR, 150 - "msize should be at least 4k\n"); 151 - ret = -EINVAL; 152 - continue; 153 - } 154 - clnt->msize = option; 155 - break; 156 - case Opt_trans: 157 - s = match_strdup(&args[0]); 158 - if (!s) { 159 - ret = -ENOMEM; 160 - p9_debug(P9_DEBUG_ERROR, 161 - "problem allocating copy of trans arg\n"); 162 - goto free_and_return; 163 - } 164 - 165 - v9fs_put_trans(clnt->trans_mod); 166 - clnt->trans_mod = v9fs_get_trans_by_name(s); 167 - if (!clnt->trans_mod) { 168 - pr_info("Could not find request transport: %s\n", 169 - s); 170 - ret = -EINVAL; 171 - } 172 - kfree(s); 173 - break; 174 - case Opt_legacy: 175 - clnt->proto_version = p9_proto_legacy; 176 - break; 177 - case Opt_version: 178 - s = match_strdup(&args[0]); 179 - if (!s) { 180 - ret = -ENOMEM; 181 - p9_debug(P9_DEBUG_ERROR, 182 - "problem allocating copy of version arg\n"); 183 - goto free_and_return; 184 - } 185 - r = get_protocol_version(s); 186 - if (r < 0) 187 - ret = r; 188 - else 189 - clnt->proto_version = r; 190 - kfree(s); 191 - break; 192 - default: 193 - continue; 194 - } 195 - } 196 - 197 - free_and_return: 198 - if (ret) 199 - v9fs_put_trans(clnt->trans_mod); 200 - kfree(tmp_options); 201 - return ret; 109 + return 0; 202 110 } 203 111 204 112 static int p9_fcall_init(struct p9_client *c, struct p9_fcall *fc, ··· 851 975 return err; 852 976 } 853 977 854 - struct p9_client *p9_client_create(const char *dev_name, char *options) 978 + struct p9_client *p9_client_create(struct fs_context *fc) 855 979 { 856 980 int err; 857 981 static atomic_t seqno = ATOMIC_INIT(0); ··· 874 998 idr_init(&clnt->fids); 875 999 idr_init(&clnt->reqs); 876 1000 877 - err = parse_opts(options, clnt); 878 - if (err < 0) 1001 + err = apply_client_options(clnt, fc); 1002 + if (err) 879 1003 goto free_client; 880 1004 881 1005 if (!clnt->trans_mod) ··· 891 1015 p9_debug(P9_DEBUG_MUX, "clnt %p trans %p msize %d protocol %d\n", 892 1016 clnt, clnt->trans_mod, clnt->msize, clnt->proto_version); 893 1017 894 - err = clnt->trans_mod->create(clnt, dev_name, options); 1018 + err = clnt->trans_mod->create(clnt, fc); 895 1019 if (err) 896 1020 goto put_trans; 897 1021
+1 -1
net/9p/mod.c
··· 16 16 #include <linux/moduleparam.h> 17 17 #include <net/9p/9p.h> 18 18 #include <linux/fs.h> 19 - #include <linux/parser.h> 20 19 #include <net/9p/client.h> 21 20 #include <net/9p/transport.h> 22 21 #include <linux/list.h> ··· 170 171 if (m) 171 172 module_put(m->owner); 172 173 } 174 + EXPORT_SYMBOL(v9fs_put_trans); 173 175 174 176 /** 175 177 * init_p9 - Initialize module
+11 -98
net/9p/trans_fd.c
··· 22 22 #include <linux/uaccess.h> 23 23 #include <linux/inet.h> 24 24 #include <linux/file.h> 25 - #include <linux/parser.h> 25 + #include <linux/fs_context.h> 26 26 #include <linux/slab.h> 27 27 #include <linux/seq_file.h> 28 28 #include <net/9p/9p.h> ··· 36 36 37 37 static struct p9_trans_module p9_tcp_trans; 38 38 static struct p9_trans_module p9_fd_trans; 39 - 40 - /* 41 - * Option Parsing (code inspired by NFS code) 42 - * - a little lazy - parse all fd-transport options 43 - */ 44 - 45 - enum { 46 - /* Options that take integer arguments */ 47 - Opt_port, Opt_rfdno, Opt_wfdno, Opt_err, 48 - /* Options that take no arguments */ 49 - Opt_privport, 50 - }; 51 - 52 - static const match_table_t tokens = { 53 - {Opt_port, "port=%u"}, 54 - {Opt_rfdno, "rfdno=%u"}, 55 - {Opt_wfdno, "wfdno=%u"}, 56 - {Opt_privport, "privport"}, 57 - {Opt_err, NULL}, 58 - }; 59 39 60 40 enum { 61 41 Rworksched = 1, /* read work scheduled or running */ ··· 717 737 return 0; 718 738 } 719 739 720 - /** 721 - * parse_opts - parse mount options into p9_fd_opts structure 722 - * @params: options string passed from mount 723 - * @opts: fd transport-specific structure to parse options into 724 - * 725 - * Returns 0 upon success, -ERRNO upon failure 726 - */ 727 - 728 - static int parse_opts(char *params, struct p9_fd_opts *opts) 729 - { 730 - char *p; 731 - substring_t args[MAX_OPT_ARGS]; 732 - int option; 733 - char *options, *tmp_options; 734 - 735 - opts->port = P9_FD_PORT; 736 - opts->rfd = ~0; 737 - opts->wfd = ~0; 738 - opts->privport = false; 739 - 740 - if (!params) 741 - return 0; 742 - 743 - tmp_options = kstrdup(params, GFP_KERNEL); 744 - if (!tmp_options) { 745 - p9_debug(P9_DEBUG_ERROR, 746 - "failed to allocate copy of option string\n"); 747 - return -ENOMEM; 748 - } 749 - options = tmp_options; 750 - 751 - while ((p = strsep(&options, ",")) != NULL) { 752 - int token; 753 - int r; 754 - if (!*p) 755 - continue; 756 - token = match_token(p, tokens, args); 757 - if ((token != Opt_err) && (token != Opt_privport)) { 758 - r = match_int(&args[0], &option); 759 - if (r < 0) { 760 - p9_debug(P9_DEBUG_ERROR, 761 - "integer field, but no integer?\n"); 762 - continue; 763 - } 764 - } 765 - switch (token) { 766 - case Opt_port: 767 - opts->port = option; 768 - break; 769 - case Opt_rfdno: 770 - opts->rfd = option; 771 - break; 772 - case Opt_wfdno: 773 - opts->wfd = option; 774 - break; 775 - case Opt_privport: 776 - opts->privport = true; 777 - break; 778 - default: 779 - continue; 780 - } 781 - } 782 - 783 - kfree(tmp_options); 784 - return 0; 785 - } 786 - 787 740 static int p9_fd_open(struct p9_client *client, int rfd, int wfd) 788 741 { 789 742 struct p9_trans_fd *ts = kzalloc(sizeof(struct p9_trans_fd), ··· 871 958 } 872 959 873 960 static int 874 - p9_fd_create_tcp(struct p9_client *client, const char *addr, char *args) 961 + p9_fd_create_tcp(struct p9_client *client, struct fs_context *fc) 875 962 { 963 + const char *addr = fc->source; 964 + struct v9fs_context *ctx = fc->fs_private; 876 965 int err; 877 966 char port_str[6]; 878 967 struct socket *csocket; 879 968 struct sockaddr_storage stor = { 0 }; 880 969 struct p9_fd_opts opts; 881 970 882 - err = parse_opts(args, &opts); 883 - if (err < 0) 884 - return err; 971 + /* opts are already parsed in context */ 972 + opts = ctx->fd_opts; 885 973 886 974 if (!addr) 887 975 return -EINVAL; ··· 929 1015 } 930 1016 931 1017 static int 932 - p9_fd_create_unix(struct p9_client *client, const char *addr, char *args) 1018 + p9_fd_create_unix(struct p9_client *client, struct fs_context *fc) 933 1019 { 1020 + const char *addr = fc->source; 934 1021 int err; 935 1022 struct socket *csocket; 936 1023 struct sockaddr_un sun_server; ··· 970 1055 } 971 1056 972 1057 static int 973 - p9_fd_create(struct p9_client *client, const char *addr, char *args) 1058 + p9_fd_create(struct p9_client *client, struct fs_context *fc) 974 1059 { 1060 + struct v9fs_context *ctx = fc->fs_private; 1061 + struct p9_fd_opts opts = ctx->fd_opts; 975 1062 int err; 976 - struct p9_fd_opts opts; 977 1063 978 - err = parse_opts(args, &opts); 979 - if (err < 0) 980 - return err; 981 1064 client->trans_opts.fd.rfd = opts.rfd; 982 1065 client->trans_opts.fd.wfd = opts.wfd; 983 1066
+8 -100
net/9p/trans_rdma.c
··· 22 22 #include <linux/uaccess.h> 23 23 #include <linux/inet.h> 24 24 #include <linux/file.h> 25 - #include <linux/parser.h> 25 + #include <linux/fs_context.h> 26 26 #include <linux/semaphore.h> 27 27 #include <linux/slab.h> 28 28 #include <linux/seq_file.h> ··· 106 106 }; 107 107 }; 108 108 109 - /* 110 - * Option Parsing (code inspired by NFS code) 111 - */ 112 - enum { 113 - /* Options that take integer arguments */ 114 - Opt_port, Opt_rq_depth, Opt_sq_depth, Opt_timeout, 115 - /* Options that take no argument */ 116 - Opt_privport, 117 - Opt_err, 118 - }; 119 - 120 - static match_table_t tokens = { 121 - {Opt_port, "port=%u"}, 122 - {Opt_sq_depth, "sq=%u"}, 123 - {Opt_rq_depth, "rq=%u"}, 124 - {Opt_timeout, "timeout=%u"}, 125 - {Opt_privport, "privport"}, 126 - {Opt_err, NULL}, 127 - }; 128 - 129 109 static int p9_rdma_show_options(struct seq_file *m, struct p9_client *clnt) 130 110 { 131 111 struct p9_trans_rdma *rdma = clnt->trans; ··· 120 140 seq_printf(m, ",timeout=%lu", rdma->timeout); 121 141 if (rdma->privport) 122 142 seq_puts(m, ",privport"); 123 - return 0; 124 - } 125 - 126 - /** 127 - * parse_opts - parse mount options into rdma options structure 128 - * @params: options string passed from mount 129 - * @opts: rdma transport-specific structure to parse options into 130 - * 131 - * Returns 0 upon success, -ERRNO upon failure 132 - */ 133 - static int parse_opts(char *params, struct p9_rdma_opts *opts) 134 - { 135 - char *p; 136 - substring_t args[MAX_OPT_ARGS]; 137 - int option; 138 - char *options, *tmp_options; 139 - 140 - opts->port = P9_RDMA_PORT; 141 - opts->sq_depth = P9_RDMA_SQ_DEPTH; 142 - opts->rq_depth = P9_RDMA_RQ_DEPTH; 143 - opts->timeout = P9_RDMA_TIMEOUT; 144 - opts->privport = false; 145 - 146 - if (!params) 147 - return 0; 148 - 149 - tmp_options = kstrdup(params, GFP_KERNEL); 150 - if (!tmp_options) { 151 - p9_debug(P9_DEBUG_ERROR, 152 - "failed to allocate copy of option string\n"); 153 - return -ENOMEM; 154 - } 155 - options = tmp_options; 156 - 157 - while ((p = strsep(&options, ",")) != NULL) { 158 - int token; 159 - int r; 160 - if (!*p) 161 - continue; 162 - token = match_token(p, tokens, args); 163 - if ((token != Opt_err) && (token != Opt_privport)) { 164 - r = match_int(&args[0], &option); 165 - if (r < 0) { 166 - p9_debug(P9_DEBUG_ERROR, 167 - "integer field, but no integer?\n"); 168 - continue; 169 - } 170 - } 171 - switch (token) { 172 - case Opt_port: 173 - opts->port = option; 174 - break; 175 - case Opt_sq_depth: 176 - opts->sq_depth = option; 177 - break; 178 - case Opt_rq_depth: 179 - opts->rq_depth = option; 180 - break; 181 - case Opt_timeout: 182 - opts->timeout = option; 183 - break; 184 - case Opt_privport: 185 - opts->privport = true; 186 - break; 187 - default: 188 - continue; 189 - } 190 - } 191 - /* RQ must be at least as large as the SQ */ 192 - opts->rq_depth = max(opts->rq_depth, opts->sq_depth); 193 - kfree(tmp_options); 194 143 return 0; 195 144 } 196 145 ··· 516 607 /** 517 608 * rdma_create_trans - Transport method for creating a transport instance 518 609 * @client: client instance 519 - * @addr: IP address string 520 - * @args: Mount options string 610 + * @fc: The filesystem context 521 611 */ 522 612 static int 523 - rdma_create_trans(struct p9_client *client, const char *addr, char *args) 613 + rdma_create_trans(struct p9_client *client, struct fs_context *fc) 524 614 { 615 + const char *addr = fc->source; 616 + struct v9fs_context *ctx = fc->fs_private; 617 + struct p9_rdma_opts opts = ctx->rdma_opts; 525 618 int err; 526 - struct p9_rdma_opts opts; 527 619 struct p9_trans_rdma *rdma; 528 620 struct rdma_conn_param conn_param; 529 621 struct ib_qp_init_attr qp_attr; ··· 532 622 if (addr == NULL) 533 623 return -EINVAL; 534 624 535 - /* Parse the transport specific mount options */ 536 - err = parse_opts(args, &opts); 537 - if (err < 0) 538 - return err; 625 + /* options are already parsed, in the fs context */ 626 + opts = ctx->rdma_opts; 539 627 540 628 /* Create and initialize the RDMA transport structure */ 541 629 rdma = alloc_rdma(&opts);
+3 -1
net/9p/trans_usbg.c
··· 27 27 #include <linux/cleanup.h> 28 28 #include <linux/kernel.h> 29 29 #include <linux/module.h> 30 + #include <linux/fs_context.h> 30 31 #include <linux/usb/composite.h> 31 32 #include <linux/usb/func_utils.h> 32 33 ··· 377 376 return ret; 378 377 } 379 378 380 - static int p9_usbg_create(struct p9_client *client, const char *devname, char *args) 379 + static int p9_usbg_create(struct p9_client *client, struct fs_context *fc) 381 380 { 381 + const char *devname = fc->source; 382 382 struct f_usb9pfs_dev *dev; 383 383 struct f_usb9pfs *usb9pfs; 384 384 int ret = -ENOENT;
+4 -4
net/9p/trans_virtio.c
··· 26 26 #include <linux/highmem.h> 27 27 #include <linux/slab.h> 28 28 #include <net/9p/9p.h> 29 - #include <linux/parser.h> 29 + #include <linux/fs_context.h> 30 30 #include <net/9p/client.h> 31 31 #include <net/9p/transport.h> 32 32 #include <linux/scatterlist.h> ··· 679 679 /** 680 680 * p9_virtio_create - allocate a new virtio channel 681 681 * @client: client instance invoking this transport 682 - * @devname: string identifying the channel to connect to (unused) 683 - * @args: args passed from sys_mount() for per-transport options (unused) 682 + * @fc: the filesystem context 684 683 * 685 684 * This sets up a transport channel for 9p communication. Right now 686 685 * we only match the first available channel, but eventually we could look up ··· 690 691 */ 691 692 692 693 static int 693 - p9_virtio_create(struct p9_client *client, const char *devname, char *args) 694 + p9_virtio_create(struct p9_client *client, struct fs_context *fc) 694 695 { 696 + const char *devname = fc->source; 695 697 struct virtio_chan *chan; 696 698 int ret = -ENOENT; 697 699 int found = 0;
+3 -1
net/9p/trans_xen.c
··· 15 15 16 16 #include <linux/module.h> 17 17 #include <linux/spinlock.h> 18 + #include <linux/fs_context.h> 18 19 #include <net/9p/9p.h> 19 20 #include <net/9p/client.h> 20 21 #include <net/9p/transport.h> ··· 67 66 return 1; 68 67 } 69 68 70 - static int p9_xen_create(struct p9_client *client, const char *addr, char *args) 69 + static int p9_xen_create(struct p9_client *client, struct fs_context *fc) 71 70 { 71 + const char *addr = fc->source; 72 72 struct xen_9pfs_front_priv *priv; 73 73 74 74 if (addr == NULL)