aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/afs/internal.h8
-rw-r--r--fs/afs/mntpt.c1
-rw-r--r--fs/afs/super.c460
-rw-r--r--fs/afs/volume.c4
4 files changed, 259 insertions, 214 deletions
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index 8871b9e8645f..3ed0550a2e29 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -36,15 +36,15 @@
36struct pagevec; 36struct pagevec;
37struct afs_call; 37struct afs_call;
38 38
39struct afs_mount_params { 39struct afs_fs_context {
40 bool rwpath; /* T if the parent should be considered R/W */ 40 bool rwpath; /* T if the parent should be considered R/W */
41 bool force; /* T to force cell type */ 41 bool force; /* T to force cell type */
42 bool autocell; /* T if set auto mount operation */ 42 bool autocell; /* T if set auto mount operation */
43 bool dyn_root; /* T if dynamic root */ 43 bool dyn_root; /* T if dynamic root */
44 bool no_cell; /* T if the source is "none" (for dynroot) */
44 afs_voltype_t type; /* type of volume requested */ 45 afs_voltype_t type; /* type of volume requested */
45 int volnamesz; /* size of volume name */ 46 unsigned int volnamesz; /* size of volume name */
46 const char *volname; /* name of volume to mount */ 47 const char *volname; /* name of volume to mount */
47 struct net *net_ns; /* Network namespace in effect */
48 struct afs_net *net; /* the AFS net namespace stuff */ 48 struct afs_net *net; /* the AFS net namespace stuff */
49 struct afs_cell *cell; /* cell in which to find volume */ 49 struct afs_cell *cell; /* cell in which to find volume */
50 struct afs_volume *volume; /* volume record */ 50 struct afs_volume *volume; /* volume record */
@@ -1274,7 +1274,7 @@ static inline struct afs_volume *__afs_get_volume(struct afs_volume *volume)
1274 return volume; 1274 return volume;
1275} 1275}
1276 1276
1277extern struct afs_volume *afs_create_volume(struct afs_mount_params *); 1277extern struct afs_volume *afs_create_volume(struct afs_fs_context *);
1278extern void afs_activate_volume(struct afs_volume *); 1278extern void afs_activate_volume(struct afs_volume *);
1279extern void afs_deactivate_volume(struct afs_volume *); 1279extern void afs_deactivate_volume(struct afs_volume *);
1280extern void afs_put_volume(struct afs_cell *, struct afs_volume *); 1280extern void afs_put_volume(struct afs_cell *, struct afs_volume *);
diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c
index 2e51c6994148..b3f41d27590b 100644
--- a/fs/afs/mntpt.c
+++ b/fs/afs/mntpt.c
@@ -17,6 +17,7 @@
17#include <linux/mount.h> 17#include <linux/mount.h>
18#include <linux/namei.h> 18#include <linux/namei.h>
19#include <linux/gfp.h> 19#include <linux/gfp.h>
20#include <linux/fs_context.h>
20#include "internal.h" 21#include "internal.h"
21 22
22 23
diff --git a/fs/afs/super.c b/fs/afs/super.c
index dcd07fe99871..e1a7a8085262 100644
--- a/fs/afs/super.c
+++ b/fs/afs/super.c
@@ -1,6 +1,6 @@
1/* AFS superblock handling 1/* AFS superblock handling
2 * 2 *
3 * Copyright (c) 2002, 2007 Red Hat, Inc. All rights reserved. 3 * Copyright (c) 2002, 2007, 2018 Red Hat, Inc. All rights reserved.
4 * 4 *
5 * This software may be freely redistributed under the terms of the 5 * This software may be freely redistributed under the terms of the
6 * GNU General Public License. 6 * GNU General Public License.
@@ -21,7 +21,7 @@
21#include <linux/slab.h> 21#include <linux/slab.h>
22#include <linux/fs.h> 22#include <linux/fs.h>
23#include <linux/pagemap.h> 23#include <linux/pagemap.h>
24#include <linux/parser.h> 24#include <linux/fs_parser.h>
25#include <linux/statfs.h> 25#include <linux/statfs.h>
26#include <linux/sched.h> 26#include <linux/sched.h>
27#include <linux/nsproxy.h> 27#include <linux/nsproxy.h>
@@ -30,21 +30,22 @@
30#include "internal.h" 30#include "internal.h"
31 31
32static void afs_i_init_once(void *foo); 32static void afs_i_init_once(void *foo);
33static struct dentry *afs_mount(struct file_system_type *fs_type,
34 int flags, const char *dev_name, void *data);
35static void afs_kill_super(struct super_block *sb); 33static void afs_kill_super(struct super_block *sb);
36static struct inode *afs_alloc_inode(struct super_block *sb); 34static struct inode *afs_alloc_inode(struct super_block *sb);
37static void afs_destroy_inode(struct inode *inode); 35static void afs_destroy_inode(struct inode *inode);
38static int afs_statfs(struct dentry *dentry, struct kstatfs *buf); 36static int afs_statfs(struct dentry *dentry, struct kstatfs *buf);
39static int afs_show_devname(struct seq_file *m, struct dentry *root); 37static int afs_show_devname(struct seq_file *m, struct dentry *root);
40static int afs_show_options(struct seq_file *m, struct dentry *root); 38static int afs_show_options(struct seq_file *m, struct dentry *root);
39static int afs_init_fs_context(struct fs_context *fc);
40static const struct fs_parameter_description afs_fs_parameters;
41 41
42struct file_system_type afs_fs_type = { 42struct file_system_type afs_fs_type = {
43 .owner = THIS_MODULE, 43 .owner = THIS_MODULE,
44 .name = "afs", 44 .name = "afs",
45 .mount = afs_mount, 45 .init_fs_context = afs_init_fs_context,
46 .kill_sb = afs_kill_super, 46 .parameters = &afs_fs_parameters,
47 .fs_flags = 0, 47 .kill_sb = afs_kill_super,
48 .fs_flags = 0,
48}; 49};
49MODULE_ALIAS_FS("afs"); 50MODULE_ALIAS_FS("afs");
50 51
@@ -63,22 +64,28 @@ static const struct super_operations afs_super_ops = {
63static struct kmem_cache *afs_inode_cachep; 64static struct kmem_cache *afs_inode_cachep;
64static atomic_t afs_count_active_inodes; 65static atomic_t afs_count_active_inodes;
65 66
66enum { 67enum afs_param {
67 afs_no_opt, 68 Opt_autocell,
68 afs_opt_cell, 69 Opt_cell,
69 afs_opt_dyn, 70 Opt_dyn,
70 afs_opt_rwpath, 71 Opt_rwpath,
71 afs_opt_vol, 72 Opt_source,
72 afs_opt_autocell, 73 Opt_vol,
73}; 74};
74 75
75static const match_table_t afs_options_list = { 76static const struct fs_parameter_spec afs_param_specs[] = {
76 { afs_opt_cell, "cell=%s" }, 77 fsparam_flag ("autocell", Opt_autocell),
77 { afs_opt_dyn, "dyn" }, 78 fsparam_string("cell", Opt_cell),
78 { afs_opt_rwpath, "rwpath" }, 79 fsparam_flag ("dyn", Opt_dyn),
79 { afs_opt_vol, "vol=%s" }, 80 fsparam_flag ("rwpath", Opt_rwpath),
80 { afs_opt_autocell, "autocell" }, 81 fsparam_string("source", Opt_source),
81 { afs_no_opt, NULL }, 82 fsparam_string("vol", Opt_vol),
83 {}
84};
85
86static const struct fs_parameter_description afs_fs_parameters = {
87 .name = "kAFS",
88 .specs = afs_param_specs,
82}; 89};
83 90
84/* 91/*
@@ -190,71 +197,10 @@ static int afs_show_options(struct seq_file *m, struct dentry *root)
190} 197}
191 198
192/* 199/*
193 * parse the mount options 200 * Parse the source name to get cell name, volume name, volume type and R/W
194 * - this function has been shamelessly adapted from the ext3 fs which 201 * selector.
195 * shamelessly adapted it from the msdos fs 202 *
196 */ 203 * This can be one of the following:
197static int afs_parse_options(struct afs_mount_params *params,
198 char *options, const char **devname)
199{
200 struct afs_cell *cell;
201 substring_t args[MAX_OPT_ARGS];
202 char *p;
203 int token;
204
205 _enter("%s", options);
206
207 options[PAGE_SIZE - 1] = 0;
208
209 while ((p = strsep(&options, ","))) {
210 if (!*p)
211 continue;
212
213 token = match_token(p, afs_options_list, args);
214 switch (token) {
215 case afs_opt_cell:
216 rcu_read_lock();
217 cell = afs_lookup_cell_rcu(params->net,
218 args[0].from,
219 args[0].to - args[0].from);
220 rcu_read_unlock();
221 if (IS_ERR(cell))
222 return PTR_ERR(cell);
223 afs_put_cell(params->net, params->cell);
224 params->cell = cell;
225 break;
226
227 case afs_opt_rwpath:
228 params->rwpath = true;
229 break;
230
231 case afs_opt_vol:
232 *devname = args[0].from;
233 break;
234
235 case afs_opt_autocell:
236 params->autocell = true;
237 break;
238
239 case afs_opt_dyn:
240 params->dyn_root = true;
241 break;
242
243 default:
244 printk(KERN_ERR "kAFS:"
245 " Unknown or invalid mount option: '%s'\n", p);
246 return -EINVAL;
247 }
248 }
249
250 _leave(" = 0");
251 return 0;
252}
253
254/*
255 * parse a device name to get cell name, volume name, volume type and R/W
256 * selector
257 * - this can be one of the following:
258 * "%[cell:]volume[.]" R/W volume 204 * "%[cell:]volume[.]" R/W volume
259 * "#[cell:]volume[.]" R/O or R/W volume (rwpath=0), 205 * "#[cell:]volume[.]" R/O or R/W volume (rwpath=0),
260 * or R/W (rwpath=1) volume 206 * or R/W (rwpath=1) volume
@@ -263,11 +209,11 @@ static int afs_parse_options(struct afs_mount_params *params,
263 * "%[cell:]volume.backup" Backup volume 209 * "%[cell:]volume.backup" Backup volume
264 * "#[cell:]volume.backup" Backup volume 210 * "#[cell:]volume.backup" Backup volume
265 */ 211 */
266static int afs_parse_device_name(struct afs_mount_params *params, 212static int afs_parse_source(struct fs_context *fc, struct fs_parameter *param)
267 const char *name)
268{ 213{
214 struct afs_fs_context *ctx = fc->fs_private;
269 struct afs_cell *cell; 215 struct afs_cell *cell;
270 const char *cellname, *suffix; 216 const char *cellname, *suffix, *name = param->string;
271 int cellnamesz; 217 int cellnamesz;
272 218
273 _enter(",%s", name); 219 _enter(",%s", name);
@@ -278,69 +224,174 @@ static int afs_parse_device_name(struct afs_mount_params *params,
278 } 224 }
279 225
280 if ((name[0] != '%' && name[0] != '#') || !name[1]) { 226 if ((name[0] != '%' && name[0] != '#') || !name[1]) {
227 /* To use dynroot, we don't want to have to provide a source */
228 if (strcmp(name, "none") == 0) {
229 ctx->no_cell = true;
230 return 0;
231 }
281 printk(KERN_ERR "kAFS: unparsable volume name\n"); 232 printk(KERN_ERR "kAFS: unparsable volume name\n");
282 return -EINVAL; 233 return -EINVAL;
283 } 234 }
284 235
285 /* determine the type of volume we're looking for */ 236 /* determine the type of volume we're looking for */
286 params->type = AFSVL_ROVOL; 237 ctx->type = AFSVL_ROVOL;
287 params->force = false; 238 ctx->force = false;
288 if (params->rwpath || name[0] == '%') { 239 if (ctx->rwpath || name[0] == '%') {
289 params->type = AFSVL_RWVOL; 240 ctx->type = AFSVL_RWVOL;
290 params->force = true; 241 ctx->force = true;
291 } 242 }
292 name++; 243 name++;
293 244
294 /* split the cell name out if there is one */ 245 /* split the cell name out if there is one */
295 params->volname = strchr(name, ':'); 246 ctx->volname = strchr(name, ':');
296 if (params->volname) { 247 if (ctx->volname) {
297 cellname = name; 248 cellname = name;
298 cellnamesz = params->volname - name; 249 cellnamesz = ctx->volname - name;
299 params->volname++; 250 ctx->volname++;
300 } else { 251 } else {
301 params->volname = name; 252 ctx->volname = name;
302 cellname = NULL; 253 cellname = NULL;
303 cellnamesz = 0; 254 cellnamesz = 0;
304 } 255 }
305 256
306 /* the volume type is further affected by a possible suffix */ 257 /* the volume type is further affected by a possible suffix */
307 suffix = strrchr(params->volname, '.'); 258 suffix = strrchr(ctx->volname, '.');
308 if (suffix) { 259 if (suffix) {
309 if (strcmp(suffix, ".readonly") == 0) { 260 if (strcmp(suffix, ".readonly") == 0) {
310 params->type = AFSVL_ROVOL; 261 ctx->type = AFSVL_ROVOL;
311 params->force = true; 262 ctx->force = true;
312 } else if (strcmp(suffix, ".backup") == 0) { 263 } else if (strcmp(suffix, ".backup") == 0) {
313 params->type = AFSVL_BACKVOL; 264 ctx->type = AFSVL_BACKVOL;
314 params->force = true; 265 ctx->force = true;
315 } else if (suffix[1] == 0) { 266 } else if (suffix[1] == 0) {
316 } else { 267 } else {
317 suffix = NULL; 268 suffix = NULL;
318 } 269 }
319 } 270 }
320 271
321 params->volnamesz = suffix ? 272 ctx->volnamesz = suffix ?
322 suffix - params->volname : strlen(params->volname); 273 suffix - ctx->volname : strlen(ctx->volname);
323 274
324 _debug("cell %*.*s [%p]", 275 _debug("cell %*.*s [%p]",
325 cellnamesz, cellnamesz, cellname ?: "", params->cell); 276 cellnamesz, cellnamesz, cellname ?: "", ctx->cell);
326 277
327 /* lookup the cell record */ 278 /* lookup the cell record */
328 if (cellname || !params->cell) { 279 if (cellname) {
329 cell = afs_lookup_cell(params->net, cellname, cellnamesz, 280 cell = afs_lookup_cell(ctx->net, cellname, cellnamesz,
330 NULL, false); 281 NULL, false);
331 if (IS_ERR(cell)) { 282 if (IS_ERR(cell)) {
332 printk(KERN_ERR "kAFS: unable to lookup cell '%*.*s'\n", 283 pr_err("kAFS: unable to lookup cell '%*.*s'\n",
333 cellnamesz, cellnamesz, cellname ?: ""); 284 cellnamesz, cellnamesz, cellname ?: "");
334 return PTR_ERR(cell); 285 return PTR_ERR(cell);
335 } 286 }
336 afs_put_cell(params->net, params->cell); 287 afs_put_cell(ctx->net, ctx->cell);
337 params->cell = cell; 288 ctx->cell = cell;
338 } 289 }
339 290
340 _debug("CELL:%s [%p] VOLUME:%*.*s SUFFIX:%s TYPE:%d%s", 291 _debug("CELL:%s [%p] VOLUME:%*.*s SUFFIX:%s TYPE:%d%s",
341 params->cell->name, params->cell, 292 ctx->cell->name, ctx->cell,
342 params->volnamesz, params->volnamesz, params->volname, 293 ctx->volnamesz, ctx->volnamesz, ctx->volname,
343 suffix ?: "-", params->type, params->force ? " FORCE" : ""); 294 suffix ?: "-", ctx->type, ctx->force ? " FORCE" : "");
295
296 fc->source = param->string;
297 param->string = NULL;
298 return 0;
299}
300
301/*
302 * Parse a single mount parameter.
303 */
304static int afs_parse_param(struct fs_context *fc, struct fs_parameter *param)
305{
306 struct fs_parse_result result;
307 struct afs_fs_context *ctx = fc->fs_private;
308 struct afs_cell *cell;
309 int opt;
310
311 opt = fs_parse(fc, &afs_fs_parameters, param, &result);
312 if (opt < 0)
313 return opt;
314
315 switch (opt) {
316 case Opt_cell:
317 if (param->size <= 0)
318 return -EINVAL;
319 if (param->size > AFS_MAXCELLNAME)
320 return -ENAMETOOLONG;
321
322 rcu_read_lock();
323 cell = afs_lookup_cell_rcu(ctx->net, param->string, param->size);
324 rcu_read_unlock();
325 if (IS_ERR(cell))
326 return PTR_ERR(cell);
327 afs_put_cell(ctx->net, ctx->cell);
328 ctx->cell = cell;
329 break;
330
331 case Opt_source:
332 return afs_parse_source(fc, param);
333
334 case Opt_autocell:
335 ctx->autocell = true;
336 break;
337
338 case Opt_dyn:
339 ctx->dyn_root = true;
340 break;
341
342 case Opt_rwpath:
343 ctx->rwpath = true;
344 break;
345
346 case Opt_vol:
347 return invalf(fc, "'vol' param is obsolete");
348
349 default:
350 return -EINVAL;
351 }
352
353 _leave(" = 0");
354 return 0;
355}
356
357/*
358 * Validate the options, get the cell key and look up the volume.
359 */
360static int afs_validate_fc(struct fs_context *fc)
361{
362 struct afs_fs_context *ctx = fc->fs_private;
363 struct afs_volume *volume;
364 struct key *key;
365
366 if (!ctx->dyn_root) {
367 if (ctx->no_cell) {
368 pr_warn("kAFS: Can only specify source 'none' with -o dyn\n");
369 return -EINVAL;
370 }
371
372 if (!ctx->cell) {
373 pr_warn("kAFS: No cell specified\n");
374 return -EDESTADDRREQ;
375 }
376
377 /* We try to do the mount securely. */
378 key = afs_request_key(ctx->cell);
379 if (IS_ERR(key))
380 return PTR_ERR(key);
381
382 ctx->key = key;
383
384 if (ctx->volume) {
385 afs_put_volume(ctx->cell, ctx->volume);
386 ctx->volume = NULL;
387 }
388
389 volume = afs_create_volume(ctx);
390 if (IS_ERR(volume))
391 return PTR_ERR(volume);
392
393 ctx->volume = volume;
394 }
344 395
345 return 0; 396 return 0;
346} 397}
@@ -348,39 +399,34 @@ static int afs_parse_device_name(struct afs_mount_params *params,
348/* 399/*
349 * check a superblock to see if it's the one we're looking for 400 * check a superblock to see if it's the one we're looking for
350 */ 401 */
351static int afs_test_super(struct super_block *sb, void *data) 402static int afs_test_super(struct super_block *sb, struct fs_context *fc)
352{ 403{
353 struct afs_super_info *as1 = data; 404 struct afs_fs_context *ctx = fc->fs_private;
354 struct afs_super_info *as = AFS_FS_S(sb); 405 struct afs_super_info *as = AFS_FS_S(sb);
355 406
356 return (as->net_ns == as1->net_ns && 407 return (as->net_ns == fc->net_ns &&
357 as->volume && 408 as->volume &&
358 as->volume->vid == as1->volume->vid && 409 as->volume->vid == ctx->volume->vid &&
359 !as->dyn_root); 410 !as->dyn_root);
360} 411}
361 412
362static int afs_dynroot_test_super(struct super_block *sb, void *data) 413static int afs_dynroot_test_super(struct super_block *sb, struct fs_context *fc)
363{ 414{
364 struct afs_super_info *as1 = data;
365 struct afs_super_info *as = AFS_FS_S(sb); 415 struct afs_super_info *as = AFS_FS_S(sb);
366 416
367 return (as->net_ns == as1->net_ns && 417 return (as->net_ns == fc->net_ns &&
368 as->dyn_root); 418 as->dyn_root);
369} 419}
370 420
371static int afs_set_super(struct super_block *sb, void *data) 421static int afs_set_super(struct super_block *sb, struct fs_context *fc)
372{ 422{
373 struct afs_super_info *as = data;
374
375 sb->s_fs_info = as;
376 return set_anon_super(sb, NULL); 423 return set_anon_super(sb, NULL);
377} 424}
378 425
379/* 426/*
380 * fill in the superblock 427 * fill in the superblock
381 */ 428 */
382static int afs_fill_super(struct super_block *sb, 429static int afs_fill_super(struct super_block *sb, struct afs_fs_context *ctx)
383 struct afs_mount_params *params)
384{ 430{
385 struct afs_super_info *as = AFS_FS_S(sb); 431 struct afs_super_info *as = AFS_FS_S(sb);
386 struct afs_fid fid; 432 struct afs_fid fid;
@@ -412,13 +458,13 @@ static int afs_fill_super(struct super_block *sb,
412 fid.vnode = 1; 458 fid.vnode = 1;
413 fid.vnode_hi = 0; 459 fid.vnode_hi = 0;
414 fid.unique = 1; 460 fid.unique = 1;
415 inode = afs_iget(sb, params->key, &fid, NULL, NULL, NULL); 461 inode = afs_iget(sb, ctx->key, &fid, NULL, NULL, NULL);
416 } 462 }
417 463
418 if (IS_ERR(inode)) 464 if (IS_ERR(inode))
419 return PTR_ERR(inode); 465 return PTR_ERR(inode);
420 466
421 if (params->autocell || params->dyn_root) 467 if (ctx->autocell || as->dyn_root)
422 set_bit(AFS_VNODE_AUTOCELL, &AFS_FS_I(inode)->flags); 468 set_bit(AFS_VNODE_AUTOCELL, &AFS_FS_I(inode)->flags);
423 469
424 ret = -ENOMEM; 470 ret = -ENOMEM;
@@ -443,17 +489,20 @@ error:
443 return ret; 489 return ret;
444} 490}
445 491
446static struct afs_super_info *afs_alloc_sbi(struct afs_mount_params *params) 492static struct afs_super_info *afs_alloc_sbi(struct fs_context *fc)
447{ 493{
494 struct afs_fs_context *ctx = fc->fs_private;
448 struct afs_super_info *as; 495 struct afs_super_info *as;
449 496
450 as = kzalloc(sizeof(struct afs_super_info), GFP_KERNEL); 497 as = kzalloc(sizeof(struct afs_super_info), GFP_KERNEL);
451 if (as) { 498 if (as) {
452 as->net_ns = get_net(params->net_ns); 499 as->net_ns = get_net(fc->net_ns);
453 if (params->dyn_root) 500 if (ctx->dyn_root) {
454 as->dyn_root = true; 501 as->dyn_root = true;
455 else 502 } else {
456 as->cell = afs_get_cell(params->cell); 503 as->cell = afs_get_cell(ctx->cell);
504 as->volume = __afs_get_volume(ctx->volume);
505 }
457 } 506 }
458 return as; 507 return as;
459} 508}
@@ -475,7 +524,7 @@ static void afs_kill_super(struct super_block *sb)
475 524
476 if (as->dyn_root) 525 if (as->dyn_root)
477 afs_dynroot_depopulate(sb); 526 afs_dynroot_depopulate(sb);
478 527
479 /* Clear the callback interests (which will do ilookup5) before 528 /* Clear the callback interests (which will do ilookup5) before
480 * deactivating the superblock. 529 * deactivating the superblock.
481 */ 530 */
@@ -488,111 +537,106 @@ static void afs_kill_super(struct super_block *sb)
488} 537}
489 538
490/* 539/*
491 * get an AFS superblock 540 * Get an AFS superblock and root directory.
492 */ 541 */
493static struct dentry *afs_mount(struct file_system_type *fs_type, 542static int afs_get_tree(struct fs_context *fc)
494 int flags, const char *dev_name, void *options)
495{ 543{
496 struct afs_mount_params params; 544 struct afs_fs_context *ctx = fc->fs_private;
497 struct super_block *sb; 545 struct super_block *sb;
498 struct afs_volume *candidate;
499 struct key *key;
500 struct afs_super_info *as; 546 struct afs_super_info *as;
501 int ret; 547 int ret;
502 548
503 _enter(",,%s,%p", dev_name, options); 549 ret = afs_validate_fc(fc);
504 550 if (ret)
505 memset(&params, 0, sizeof(params));
506
507 ret = -EINVAL;
508 if (current->nsproxy->net_ns != &init_net)
509 goto error; 551 goto error;
510 params.net_ns = current->nsproxy->net_ns;
511 params.net = afs_net(params.net_ns);
512
513 /* parse the options and device name */
514 if (options) {
515 ret = afs_parse_options(&params, options, &dev_name);
516 if (ret < 0)
517 goto error;
518 }
519
520 if (!params.dyn_root) {
521 ret = afs_parse_device_name(&params, dev_name);
522 if (ret < 0)
523 goto error;
524 552
525 /* try and do the mount securely */ 553 _enter("");
526 key = afs_request_key(params.cell);
527 if (IS_ERR(key)) {
528 _leave(" = %ld [key]", PTR_ERR(key));
529 ret = PTR_ERR(key);
530 goto error;
531 }
532 params.key = key;
533 }
534 554
535 /* allocate a superblock info record */ 555 /* allocate a superblock info record */
536 ret = -ENOMEM; 556 ret = -ENOMEM;
537 as = afs_alloc_sbi(&params); 557 as = afs_alloc_sbi(fc);
538 if (!as) 558 if (!as)
539 goto error_key; 559 goto error;
540 560 fc->s_fs_info = as;
541 if (!params.dyn_root) {
542 /* Assume we're going to need a volume record; at the very
543 * least we can use it to update the volume record if we have
544 * one already. This checks that the volume exists within the
545 * cell.
546 */
547 candidate = afs_create_volume(&params);
548 if (IS_ERR(candidate)) {
549 ret = PTR_ERR(candidate);
550 goto error_as;
551 }
552
553 as->volume = candidate;
554 }
555 561
556 /* allocate a deviceless superblock */ 562 /* allocate a deviceless superblock */
557 sb = sget(fs_type, 563 sb = sget_fc(fc,
558 as->dyn_root ? afs_dynroot_test_super : afs_test_super, 564 as->dyn_root ? afs_dynroot_test_super : afs_test_super,
559 afs_set_super, flags, as); 565 afs_set_super);
560 if (IS_ERR(sb)) { 566 if (IS_ERR(sb)) {
561 ret = PTR_ERR(sb); 567 ret = PTR_ERR(sb);
562 goto error_as; 568 goto error;
563 } 569 }
564 570
565 if (!sb->s_root) { 571 if (!sb->s_root) {
566 /* initial superblock/root creation */ 572 /* initial superblock/root creation */
567 _debug("create"); 573 _debug("create");
568 ret = afs_fill_super(sb, &params); 574 ret = afs_fill_super(sb, ctx);
569 if (ret < 0) 575 if (ret < 0)
570 goto error_sb; 576 goto error_sb;
571 as = NULL;
572 sb->s_flags |= SB_ACTIVE; 577 sb->s_flags |= SB_ACTIVE;
573 } else { 578 } else {
574 _debug("reuse"); 579 _debug("reuse");
575 ASSERTCMP(sb->s_flags, &, SB_ACTIVE); 580 ASSERTCMP(sb->s_flags, &, SB_ACTIVE);
576 afs_destroy_sbi(as);
577 as = NULL;
578 } 581 }
579 582
580 afs_put_cell(params.net, params.cell); 583 fc->root = dget(sb->s_root);
581 key_put(params.key);
582 _leave(" = 0 [%p]", sb); 584 _leave(" = 0 [%p]", sb);
583 return dget(sb->s_root); 585 return 0;
584 586
585error_sb: 587error_sb:
586 deactivate_locked_super(sb); 588 deactivate_locked_super(sb);
587 goto error_key;
588error_as:
589 afs_destroy_sbi(as);
590error_key:
591 key_put(params.key);
592error: 589error:
593 afs_put_cell(params.net, params.cell);
594 _leave(" = %d", ret); 590 _leave(" = %d", ret);
595 return ERR_PTR(ret); 591 return ret;
592}
593
594static void afs_free_fc(struct fs_context *fc)
595{
596 struct afs_fs_context *ctx = fc->fs_private;
597
598 afs_destroy_sbi(fc->s_fs_info);
599 afs_put_volume(ctx->cell, ctx->volume);
600 afs_put_cell(ctx->net, ctx->cell);
601 key_put(ctx->key);
602 kfree(ctx);
603}
604
605static const struct fs_context_operations afs_context_ops = {
606 .free = afs_free_fc,
607 .parse_param = afs_parse_param,
608 .get_tree = afs_get_tree,
609};
610
611/*
612 * Set up the filesystem mount context.
613 */
614static int afs_init_fs_context(struct fs_context *fc)
615{
616 struct afs_fs_context *ctx;
617 struct afs_cell *cell;
618
619 if (current->nsproxy->net_ns != &init_net)
620 return -EINVAL;
621
622 ctx = kzalloc(sizeof(struct afs_fs_context), GFP_KERNEL);
623 if (!ctx)
624 return -ENOMEM;
625
626 ctx->type = AFSVL_ROVOL;
627 ctx->net = afs_net(fc->net_ns);
628
629 /* Default to the workstation cell. */
630 rcu_read_lock();
631 cell = afs_lookup_cell_rcu(ctx->net, NULL, 0);
632 rcu_read_unlock();
633 if (IS_ERR(cell))
634 cell = NULL;
635 ctx->cell = cell;
636
637 fc->fs_private = ctx;
638 fc->ops = &afs_context_ops;
639 return 0;
596} 640}
597 641
598/* 642/*
diff --git a/fs/afs/volume.c b/fs/afs/volume.c
index 00975ed3640f..f6eba2def0a1 100644
--- a/fs/afs/volume.c
+++ b/fs/afs/volume.c
@@ -21,7 +21,7 @@ static const char *const afs_voltypes[] = { "R/W", "R/O", "BAK" };
21/* 21/*
22 * Allocate a volume record and load it up from a vldb record. 22 * Allocate a volume record and load it up from a vldb record.
23 */ 23 */
24static struct afs_volume *afs_alloc_volume(struct afs_mount_params *params, 24static struct afs_volume *afs_alloc_volume(struct afs_fs_context *params,
25 struct afs_vldb_entry *vldb, 25 struct afs_vldb_entry *vldb,
26 unsigned long type_mask) 26 unsigned long type_mask)
27{ 27{
@@ -113,7 +113,7 @@ static struct afs_vldb_entry *afs_vl_lookup_vldb(struct afs_cell *cell,
113 * - Rule 3: If parent volume is R/W, then only mount R/W volume unless 113 * - Rule 3: If parent volume is R/W, then only mount R/W volume unless
114 * explicitly told otherwise 114 * explicitly told otherwise
115 */ 115 */
116struct afs_volume *afs_create_volume(struct afs_mount_params *params) 116struct afs_volume *afs_create_volume(struct afs_fs_context *params)
117{ 117{
118 struct afs_vldb_entry *vldb; 118 struct afs_vldb_entry *vldb;
119 struct afs_volume *volume; 119 struct afs_volume *volume;