hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/fs/afs/super.c
....@@ -1,6 +1,6 @@
11 /* AFS superblock handling
22 *
3
- * Copyright (c) 2002, 2007 Red Hat, Inc. All rights reserved.
3
+ * Copyright (c) 2002, 2007, 2018 Red Hat, Inc. All rights reserved.
44 *
55 * This software may be freely redistributed under the terms of the
66 * GNU General Public License.
....@@ -21,7 +21,7 @@
2121 #include <linux/slab.h>
2222 #include <linux/fs.h>
2323 #include <linux/pagemap.h>
24
-#include <linux/parser.h>
24
+#include <linux/fs_parser.h>
2525 #include <linux/statfs.h>
2626 #include <linux/sched.h>
2727 #include <linux/nsproxy.h>
....@@ -30,21 +30,23 @@
3030 #include "internal.h"
3131
3232 static void afs_i_init_once(void *foo);
33
-static struct dentry *afs_mount(struct file_system_type *fs_type,
34
- int flags, const char *dev_name, void *data);
3533 static void afs_kill_super(struct super_block *sb);
3634 static struct inode *afs_alloc_inode(struct super_block *sb);
3735 static void afs_destroy_inode(struct inode *inode);
36
+static void afs_free_inode(struct inode *inode);
3837 static int afs_statfs(struct dentry *dentry, struct kstatfs *buf);
3938 static int afs_show_devname(struct seq_file *m, struct dentry *root);
4039 static int afs_show_options(struct seq_file *m, struct dentry *root);
40
+static int afs_init_fs_context(struct fs_context *fc);
41
+static const struct fs_parameter_spec afs_fs_parameters[];
4142
4243 struct file_system_type afs_fs_type = {
43
- .owner = THIS_MODULE,
44
- .name = "afs",
45
- .mount = afs_mount,
46
- .kill_sb = afs_kill_super,
47
- .fs_flags = 0,
44
+ .owner = THIS_MODULE,
45
+ .name = "afs",
46
+ .init_fs_context = afs_init_fs_context,
47
+ .parameters = afs_fs_parameters,
48
+ .kill_sb = afs_kill_super,
49
+ .fs_flags = FS_RENAME_DOES_D_MOVE,
4850 };
4951 MODULE_ALIAS_FS("afs");
5052
....@@ -55,6 +57,7 @@
5557 .alloc_inode = afs_alloc_inode,
5658 .drop_inode = afs_drop_inode,
5759 .destroy_inode = afs_destroy_inode,
60
+ .free_inode = afs_free_inode,
5861 .evict_inode = afs_evict_inode,
5962 .show_devname = afs_show_devname,
6063 .show_options = afs_show_options,
....@@ -63,22 +66,27 @@
6366 static struct kmem_cache *afs_inode_cachep;
6467 static atomic_t afs_count_active_inodes;
6568
66
-enum {
67
- afs_no_opt,
68
- afs_opt_cell,
69
- afs_opt_dyn,
70
- afs_opt_rwpath,
71
- afs_opt_vol,
72
- afs_opt_autocell,
69
+enum afs_param {
70
+ Opt_autocell,
71
+ Opt_dyn,
72
+ Opt_flock,
73
+ Opt_source,
7374 };
7475
75
-static const match_table_t afs_options_list = {
76
- { afs_opt_cell, "cell=%s" },
77
- { afs_opt_dyn, "dyn" },
78
- { afs_opt_rwpath, "rwpath" },
79
- { afs_opt_vol, "vol=%s" },
80
- { afs_opt_autocell, "autocell" },
81
- { afs_no_opt, NULL },
76
+static const struct constant_table afs_param_flock[] = {
77
+ {"local", afs_flock_mode_local },
78
+ {"openafs", afs_flock_mode_openafs },
79
+ {"strict", afs_flock_mode_strict },
80
+ {"write", afs_flock_mode_write },
81
+ {}
82
+};
83
+
84
+static const struct fs_parameter_spec afs_fs_parameters[] = {
85
+ fsparam_flag ("autocell", Opt_autocell),
86
+ fsparam_flag ("dyn", Opt_dyn),
87
+ fsparam_enum ("flock", Opt_flock, afs_param_flock),
88
+ fsparam_string("source", Opt_source),
89
+ {}
8290 };
8391
8492 /*
....@@ -181,96 +189,49 @@
181189 static int afs_show_options(struct seq_file *m, struct dentry *root)
182190 {
183191 struct afs_super_info *as = AFS_FS_S(root->d_sb);
192
+ const char *p = NULL;
184193
185194 if (as->dyn_root)
186195 seq_puts(m, ",dyn");
187196 if (test_bit(AFS_VNODE_AUTOCELL, &AFS_FS_I(d_inode(root))->flags))
188197 seq_puts(m, ",autocell");
189
- return 0;
190
-}
191
-
192
-/*
193
- * parse the mount options
194
- * - this function has been shamelessly adapted from the ext3 fs which
195
- * shamelessly adapted it from the msdos fs
196
- */
197
-static 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
- }
198
+ switch (as->flock_mode) {
199
+ case afs_flock_mode_unset: break;
200
+ case afs_flock_mode_local: p = "local"; break;
201
+ case afs_flock_mode_openafs: p = "openafs"; break;
202
+ case afs_flock_mode_strict: p = "strict"; break;
203
+ case afs_flock_mode_write: p = "write"; break;
248204 }
205
+ if (p)
206
+ seq_printf(m, ",flock=%s", p);
249207
250
- _leave(" = 0");
251208 return 0;
252209 }
253210
254211 /*
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:
212
+ * Parse the source name to get cell name, volume name, volume type and R/W
213
+ * selector.
214
+ *
215
+ * This can be one of the following:
258216 * "%[cell:]volume[.]" R/W volume
259
- * "#[cell:]volume[.]" R/O or R/W volume (rwpath=0),
260
- * or R/W (rwpath=1) volume
217
+ * "#[cell:]volume[.]" R/O or R/W volume (R/O parent),
218
+ * or R/W (R/W parent) volume
261219 * "%[cell:]volume.readonly" R/O volume
262220 * "#[cell:]volume.readonly" R/O volume
263221 * "%[cell:]volume.backup" Backup volume
264222 * "#[cell:]volume.backup" Backup volume
265223 */
266
-static int afs_parse_device_name(struct afs_mount_params *params,
267
- const char *name)
224
+static int afs_parse_source(struct fs_context *fc, struct fs_parameter *param)
268225 {
226
+ struct afs_fs_context *ctx = fc->fs_private;
269227 struct afs_cell *cell;
270
- const char *cellname, *suffix;
228
+ const char *cellname, *suffix, *name = param->string;
271229 int cellnamesz;
272230
273231 _enter(",%s", name);
232
+
233
+ if (fc->source)
234
+ return invalf(fc, "kAFS: Multiple sources not supported");
274235
275236 if (!name) {
276237 printk(KERN_ERR "kAFS: no volume name specified\n");
....@@ -278,69 +239,174 @@
278239 }
279240
280241 if ((name[0] != '%' && name[0] != '#') || !name[1]) {
242
+ /* To use dynroot, we don't want to have to provide a source */
243
+ if (strcmp(name, "none") == 0) {
244
+ ctx->no_cell = true;
245
+ return 0;
246
+ }
281247 printk(KERN_ERR "kAFS: unparsable volume name\n");
282248 return -EINVAL;
283249 }
284250
285251 /* determine the type of volume we're looking for */
286
- params->type = AFSVL_ROVOL;
287
- params->force = false;
288
- if (params->rwpath || name[0] == '%') {
289
- params->type = AFSVL_RWVOL;
290
- params->force = true;
252
+ if (name[0] == '%') {
253
+ ctx->type = AFSVL_RWVOL;
254
+ ctx->force = true;
291255 }
292256 name++;
293257
294258 /* split the cell name out if there is one */
295
- params->volname = strchr(name, ':');
296
- if (params->volname) {
259
+ ctx->volname = strchr(name, ':');
260
+ if (ctx->volname) {
297261 cellname = name;
298
- cellnamesz = params->volname - name;
299
- params->volname++;
262
+ cellnamesz = ctx->volname - name;
263
+ ctx->volname++;
300264 } else {
301
- params->volname = name;
265
+ ctx->volname = name;
302266 cellname = NULL;
303267 cellnamesz = 0;
304268 }
305269
306270 /* the volume type is further affected by a possible suffix */
307
- suffix = strrchr(params->volname, '.');
271
+ suffix = strrchr(ctx->volname, '.');
308272 if (suffix) {
309273 if (strcmp(suffix, ".readonly") == 0) {
310
- params->type = AFSVL_ROVOL;
311
- params->force = true;
274
+ ctx->type = AFSVL_ROVOL;
275
+ ctx->force = true;
312276 } else if (strcmp(suffix, ".backup") == 0) {
313
- params->type = AFSVL_BACKVOL;
314
- params->force = true;
277
+ ctx->type = AFSVL_BACKVOL;
278
+ ctx->force = true;
315279 } else if (suffix[1] == 0) {
316280 } else {
317281 suffix = NULL;
318282 }
319283 }
320284
321
- params->volnamesz = suffix ?
322
- suffix - params->volname : strlen(params->volname);
285
+ ctx->volnamesz = suffix ?
286
+ suffix - ctx->volname : strlen(ctx->volname);
323287
324288 _debug("cell %*.*s [%p]",
325
- cellnamesz, cellnamesz, cellname ?: "", params->cell);
289
+ cellnamesz, cellnamesz, cellname ?: "", ctx->cell);
326290
327291 /* lookup the cell record */
328
- if (cellname || !params->cell) {
329
- cell = afs_lookup_cell(params->net, cellname, cellnamesz,
292
+ if (cellname) {
293
+ cell = afs_lookup_cell(ctx->net, cellname, cellnamesz,
330294 NULL, false);
331295 if (IS_ERR(cell)) {
332
- printk(KERN_ERR "kAFS: unable to lookup cell '%*.*s'\n",
296
+ pr_err("kAFS: unable to lookup cell '%*.*s'\n",
333297 cellnamesz, cellnamesz, cellname ?: "");
334298 return PTR_ERR(cell);
335299 }
336
- afs_put_cell(params->net, params->cell);
337
- params->cell = cell;
300
+ afs_unuse_cell(ctx->net, ctx->cell, afs_cell_trace_unuse_parse);
301
+ afs_see_cell(cell, afs_cell_trace_see_source);
302
+ ctx->cell = cell;
338303 }
339304
340305 _debug("CELL:%s [%p] VOLUME:%*.*s SUFFIX:%s TYPE:%d%s",
341
- params->cell->name, params->cell,
342
- params->volnamesz, params->volnamesz, params->volname,
343
- suffix ?: "-", params->type, params->force ? " FORCE" : "");
306
+ ctx->cell->name, ctx->cell,
307
+ ctx->volnamesz, ctx->volnamesz, ctx->volname,
308
+ suffix ?: "-", ctx->type, ctx->force ? " FORCE" : "");
309
+
310
+ fc->source = param->string;
311
+ param->string = NULL;
312
+ return 0;
313
+}
314
+
315
+/*
316
+ * Parse a single mount parameter.
317
+ */
318
+static int afs_parse_param(struct fs_context *fc, struct fs_parameter *param)
319
+{
320
+ struct fs_parse_result result;
321
+ struct afs_fs_context *ctx = fc->fs_private;
322
+ int opt;
323
+
324
+ opt = fs_parse(fc, afs_fs_parameters, param, &result);
325
+ if (opt < 0)
326
+ return opt;
327
+
328
+ switch (opt) {
329
+ case Opt_source:
330
+ return afs_parse_source(fc, param);
331
+
332
+ case Opt_autocell:
333
+ ctx->autocell = true;
334
+ break;
335
+
336
+ case Opt_dyn:
337
+ ctx->dyn_root = true;
338
+ break;
339
+
340
+ case Opt_flock:
341
+ ctx->flock_mode = result.uint_32;
342
+ break;
343
+
344
+ default:
345
+ return -EINVAL;
346
+ }
347
+
348
+ _leave(" = 0");
349
+ return 0;
350
+}
351
+
352
+/*
353
+ * Validate the options, get the cell key and look up the volume.
354
+ */
355
+static int afs_validate_fc(struct fs_context *fc)
356
+{
357
+ struct afs_fs_context *ctx = fc->fs_private;
358
+ struct afs_volume *volume;
359
+ struct afs_cell *cell;
360
+ struct key *key;
361
+ int ret;
362
+
363
+ if (!ctx->dyn_root) {
364
+ if (ctx->no_cell) {
365
+ pr_warn("kAFS: Can only specify source 'none' with -o dyn\n");
366
+ return -EINVAL;
367
+ }
368
+
369
+ if (!ctx->cell) {
370
+ pr_warn("kAFS: No cell specified\n");
371
+ return -EDESTADDRREQ;
372
+ }
373
+
374
+ reget_key:
375
+ /* We try to do the mount securely. */
376
+ key = afs_request_key(ctx->cell);
377
+ if (IS_ERR(key))
378
+ return PTR_ERR(key);
379
+
380
+ ctx->key = key;
381
+
382
+ if (ctx->volume) {
383
+ afs_put_volume(ctx->net, ctx->volume,
384
+ afs_volume_trace_put_validate_fc);
385
+ ctx->volume = NULL;
386
+ }
387
+
388
+ if (test_bit(AFS_CELL_FL_CHECK_ALIAS, &ctx->cell->flags)) {
389
+ ret = afs_cell_detect_alias(ctx->cell, key);
390
+ if (ret < 0)
391
+ return ret;
392
+ if (ret == 1) {
393
+ _debug("switch to alias");
394
+ key_put(ctx->key);
395
+ ctx->key = NULL;
396
+ cell = afs_use_cell(ctx->cell->alias_of,
397
+ afs_cell_trace_use_fc_alias);
398
+ afs_unuse_cell(ctx->net, ctx->cell, afs_cell_trace_unuse_fc);
399
+ ctx->cell = cell;
400
+ goto reget_key;
401
+ }
402
+ }
403
+
404
+ volume = afs_create_volume(ctx);
405
+ if (IS_ERR(volume))
406
+ return PTR_ERR(volume);
407
+
408
+ ctx->volume = volume;
409
+ }
344410
345411 return 0;
346412 }
....@@ -348,43 +414,37 @@
348414 /*
349415 * check a superblock to see if it's the one we're looking for
350416 */
351
-static int afs_test_super(struct super_block *sb, void *data)
417
+static int afs_test_super(struct super_block *sb, struct fs_context *fc)
352418 {
353
- struct afs_super_info *as1 = data;
419
+ struct afs_fs_context *ctx = fc->fs_private;
354420 struct afs_super_info *as = AFS_FS_S(sb);
355421
356
- return (as->net_ns == as1->net_ns &&
422
+ return (as->net_ns == fc->net_ns &&
357423 as->volume &&
358
- as->volume->vid == as1->volume->vid &&
359
- as->cell == as1->cell &&
424
+ as->volume->vid == ctx->volume->vid &&
425
+ as->cell == ctx->cell &&
360426 !as->dyn_root);
361427 }
362428
363
-static int afs_dynroot_test_super(struct super_block *sb, void *data)
429
+static int afs_dynroot_test_super(struct super_block *sb, struct fs_context *fc)
364430 {
365
- struct afs_super_info *as1 = data;
366431 struct afs_super_info *as = AFS_FS_S(sb);
367432
368
- return (as->net_ns == as1->net_ns &&
433
+ return (as->net_ns == fc->net_ns &&
369434 as->dyn_root);
370435 }
371436
372
-static int afs_set_super(struct super_block *sb, void *data)
437
+static int afs_set_super(struct super_block *sb, struct fs_context *fc)
373438 {
374
- struct afs_super_info *as = data;
375
-
376
- sb->s_fs_info = as;
377439 return set_anon_super(sb, NULL);
378440 }
379441
380442 /*
381443 * fill in the superblock
382444 */
383
-static int afs_fill_super(struct super_block *sb,
384
- struct afs_mount_params *params)
445
+static int afs_fill_super(struct super_block *sb, struct afs_fs_context *ctx)
385446 {
386447 struct afs_super_info *as = AFS_FS_S(sb);
387
- struct afs_fid fid;
388448 struct inode *inode = NULL;
389449 int ret;
390450
....@@ -401,24 +461,20 @@
401461 ret = super_setup_bdi(sb);
402462 if (ret)
403463 return ret;
404
- sb->s_bdi->ra_pages = VM_MAX_READAHEAD * 1024 / PAGE_SIZE;
405464
406465 /* allocate the root inode and dentry */
407466 if (as->dyn_root) {
408467 inode = afs_iget_pseudo_dir(sb, true);
409468 } else {
410
- sprintf(sb->s_id, "%u", as->volume->vid);
469
+ sprintf(sb->s_id, "%llu", as->volume->vid);
411470 afs_activate_volume(as->volume);
412
- fid.vid = as->volume->vid;
413
- fid.vnode = 1;
414
- fid.unique = 1;
415
- inode = afs_iget(sb, params->key, &fid, NULL, NULL, NULL);
471
+ inode = afs_root_iget(sb, ctx->key);
416472 }
417473
418474 if (IS_ERR(inode))
419475 return PTR_ERR(inode);
420476
421
- if (params->autocell || params->dyn_root)
477
+ if (ctx->autocell || as->dyn_root)
422478 set_bit(AFS_VNODE_AUTOCELL, &AFS_FS_I(inode)->flags);
423479
424480 ret = -ENOMEM;
....@@ -433,6 +489,7 @@
433489 goto error;
434490 } else {
435491 sb->s_d_op = &afs_fs_dentry_operations;
492
+ rcu_assign_pointer(as->volume->sb, sb);
436493 }
437494
438495 _leave(" = 0");
....@@ -443,17 +500,22 @@
443500 return ret;
444501 }
445502
446
-static struct afs_super_info *afs_alloc_sbi(struct afs_mount_params *params)
503
+static struct afs_super_info *afs_alloc_sbi(struct fs_context *fc)
447504 {
505
+ struct afs_fs_context *ctx = fc->fs_private;
448506 struct afs_super_info *as;
449507
450508 as = kzalloc(sizeof(struct afs_super_info), GFP_KERNEL);
451509 if (as) {
452
- as->net_ns = get_net(params->net_ns);
453
- if (params->dyn_root)
510
+ as->net_ns = get_net(fc->net_ns);
511
+ as->flock_mode = ctx->flock_mode;
512
+ if (ctx->dyn_root) {
454513 as->dyn_root = true;
455
- else
456
- as->cell = afs_get_cell(params->cell);
514
+ } else {
515
+ as->cell = afs_use_cell(ctx->cell, afs_cell_trace_use_sbi);
516
+ as->volume = afs_get_volume(ctx->volume,
517
+ afs_volume_trace_get_alloc_sbi);
518
+ }
457519 }
458520 return as;
459521 }
....@@ -461,8 +523,9 @@
461523 static void afs_destroy_sbi(struct afs_super_info *as)
462524 {
463525 if (as) {
464
- afs_put_volume(as->cell, as->volume);
465
- afs_put_cell(afs_net(as->net_ns), as->cell);
526
+ struct afs_net *net = afs_net(as->net_ns);
527
+ afs_put_volume(net, as->volume, afs_volume_trace_put_destroy_sbi);
528
+ afs_unuse_cell(net, as->cell, afs_cell_trace_unuse_sbi);
466529 put_net(as->net_ns);
467530 kfree(as);
468531 }
....@@ -471,16 +534,15 @@
471534 static void afs_kill_super(struct super_block *sb)
472535 {
473536 struct afs_super_info *as = AFS_FS_S(sb);
474
- struct afs_net *net = afs_net(as->net_ns);
475537
476538 if (as->dyn_root)
477539 afs_dynroot_depopulate(sb);
478
-
540
+
479541 /* Clear the callback interests (which will do ilookup5) before
480542 * deactivating the superblock.
481543 */
482544 if (as->volume)
483
- afs_clear_callback_interests(net, as->volume->servers);
545
+ rcu_assign_pointer(as->volume->sb, NULL);
484546 kill_anon_super(sb);
485547 if (as->volume)
486548 afs_deactivate_volume(as->volume);
....@@ -488,111 +550,102 @@
488550 }
489551
490552 /*
491
- * get an AFS superblock
553
+ * Get an AFS superblock and root directory.
492554 */
493
-static struct dentry *afs_mount(struct file_system_type *fs_type,
494
- int flags, const char *dev_name, void *options)
555
+static int afs_get_tree(struct fs_context *fc)
495556 {
496
- struct afs_mount_params params;
557
+ struct afs_fs_context *ctx = fc->fs_private;
497558 struct super_block *sb;
498
- struct afs_volume *candidate;
499
- struct key *key;
500559 struct afs_super_info *as;
501560 int ret;
502561
503
- _enter(",,%s,%p", dev_name, options);
504
-
505
- memset(&params, 0, sizeof(params));
506
-
507
- ret = -EINVAL;
508
- if (current->nsproxy->net_ns != &init_net)
562
+ ret = afs_validate_fc(fc);
563
+ if (ret)
509564 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
- }
519565
520
- if (!params.dyn_root) {
521
- ret = afs_parse_device_name(&params, dev_name);
522
- if (ret < 0)
523
- goto error;
524
-
525
- /* try and do the mount securely */
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
- }
566
+ _enter("");
534567
535568 /* allocate a superblock info record */
536569 ret = -ENOMEM;
537
- as = afs_alloc_sbi(&params);
570
+ as = afs_alloc_sbi(fc);
538571 if (!as)
539
- goto error_key;
540
-
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
- }
572
+ goto error;
573
+ fc->s_fs_info = as;
555574
556575 /* allocate a deviceless superblock */
557
- sb = sget(fs_type,
558
- as->dyn_root ? afs_dynroot_test_super : afs_test_super,
559
- afs_set_super, flags, as);
576
+ sb = sget_fc(fc,
577
+ as->dyn_root ? afs_dynroot_test_super : afs_test_super,
578
+ afs_set_super);
560579 if (IS_ERR(sb)) {
561580 ret = PTR_ERR(sb);
562
- goto error_as;
581
+ goto error;
563582 }
564583
565584 if (!sb->s_root) {
566585 /* initial superblock/root creation */
567586 _debug("create");
568
- ret = afs_fill_super(sb, &params);
587
+ ret = afs_fill_super(sb, ctx);
569588 if (ret < 0)
570589 goto error_sb;
571
- as = NULL;
572590 sb->s_flags |= SB_ACTIVE;
573591 } else {
574592 _debug("reuse");
575593 ASSERTCMP(sb->s_flags, &, SB_ACTIVE);
576
- afs_destroy_sbi(as);
577
- as = NULL;
578594 }
579595
580
- afs_put_cell(params.net, params.cell);
581
- key_put(params.key);
596
+ fc->root = dget(sb->s_root);
597
+ trace_afs_get_tree(as->cell, as->volume);
582598 _leave(" = 0 [%p]", sb);
583
- return dget(sb->s_root);
599
+ return 0;
584600
585601 error_sb:
586602 deactivate_locked_super(sb);
587
- goto error_key;
588
-error_as:
589
- afs_destroy_sbi(as);
590
-error_key:
591
- key_put(params.key);
592603 error:
593
- afs_put_cell(params.net, params.cell);
594604 _leave(" = %d", ret);
595
- return ERR_PTR(ret);
605
+ return ret;
606
+}
607
+
608
+static void afs_free_fc(struct fs_context *fc)
609
+{
610
+ struct afs_fs_context *ctx = fc->fs_private;
611
+
612
+ afs_destroy_sbi(fc->s_fs_info);
613
+ afs_put_volume(ctx->net, ctx->volume, afs_volume_trace_put_free_fc);
614
+ afs_unuse_cell(ctx->net, ctx->cell, afs_cell_trace_unuse_fc);
615
+ key_put(ctx->key);
616
+ kfree(ctx);
617
+}
618
+
619
+static const struct fs_context_operations afs_context_ops = {
620
+ .free = afs_free_fc,
621
+ .parse_param = afs_parse_param,
622
+ .get_tree = afs_get_tree,
623
+};
624
+
625
+/*
626
+ * Set up the filesystem mount context.
627
+ */
628
+static int afs_init_fs_context(struct fs_context *fc)
629
+{
630
+ struct afs_fs_context *ctx;
631
+ struct afs_cell *cell;
632
+
633
+ ctx = kzalloc(sizeof(struct afs_fs_context), GFP_KERNEL);
634
+ if (!ctx)
635
+ return -ENOMEM;
636
+
637
+ ctx->type = AFSVL_ROVOL;
638
+ ctx->net = afs_net(fc->net_ns);
639
+
640
+ /* Default to the workstation cell. */
641
+ cell = afs_find_cell(ctx->net, NULL, 0, afs_cell_trace_use_fc);
642
+ if (IS_ERR(cell))
643
+ cell = NULL;
644
+ ctx->cell = cell;
645
+
646
+ fc->fs_private = ctx;
647
+ fc->ops = &afs_context_ops;
648
+ return 0;
596649 }
597650
598651 /*
....@@ -637,24 +690,22 @@
637690 vnode->volume = NULL;
638691 vnode->lock_key = NULL;
639692 vnode->permit_cache = NULL;
640
- vnode->cb_interest = NULL;
641693 #ifdef CONFIG_AFS_FSCACHE
642694 vnode->cache = NULL;
643695 #endif
644696
645697 vnode->flags = 1 << AFS_VNODE_UNSET;
646
- vnode->cb_type = 0;
647698 vnode->lock_state = AFS_VNODE_LOCK_NONE;
699
+
700
+ init_rwsem(&vnode->rmdir_lock);
648701
649702 _leave(" = %p", &vnode->vfs_inode);
650703 return &vnode->vfs_inode;
651704 }
652705
653
-static void afs_i_callback(struct rcu_head *head)
706
+static void afs_free_inode(struct inode *inode)
654707 {
655
- struct inode *inode = container_of(head, struct inode, i_rcu);
656
- struct afs_vnode *vnode = AFS_FS_I(inode);
657
- kmem_cache_free(afs_inode_cachep, vnode);
708
+ kmem_cache_free(afs_inode_cachep, AFS_FS_I(inode));
658709 }
659710
660711 /*
....@@ -664,15 +715,33 @@
664715 {
665716 struct afs_vnode *vnode = AFS_FS_I(inode);
666717
667
- _enter("%p{%x:%u}", inode, vnode->fid.vid, vnode->fid.vnode);
718
+ _enter("%p{%llx:%llu}", inode, vnode->fid.vid, vnode->fid.vnode);
668719
669720 _debug("DESTROY INODE %p", inode);
670721
671
- ASSERTCMP(vnode->cb_interest, ==, NULL);
672
-
673
- call_rcu(&inode->i_rcu, afs_i_callback);
674722 atomic_dec(&afs_count_active_inodes);
675723 }
724
+
725
+static void afs_get_volume_status_success(struct afs_operation *op)
726
+{
727
+ struct afs_volume_status *vs = &op->volstatus.vs;
728
+ struct kstatfs *buf = op->volstatus.buf;
729
+
730
+ if (vs->max_quota == 0)
731
+ buf->f_blocks = vs->part_max_blocks;
732
+ else
733
+ buf->f_blocks = vs->max_quota;
734
+
735
+ if (buf->f_blocks > vs->blocks_in_use)
736
+ buf->f_bavail = buf->f_bfree =
737
+ buf->f_blocks - vs->blocks_in_use;
738
+}
739
+
740
+static const struct afs_operation_ops afs_get_volume_status_operation = {
741
+ .issue_afs_rpc = afs_fs_get_volume_status,
742
+ .issue_yfs_rpc = yfs_fs_get_volume_status,
743
+ .success = afs_get_volume_status_success,
744
+};
676745
677746 /*
678747 * return information about an AFS volume
....@@ -680,11 +749,8 @@
680749 static int afs_statfs(struct dentry *dentry, struct kstatfs *buf)
681750 {
682751 struct afs_super_info *as = AFS_FS_S(dentry->d_sb);
683
- struct afs_fs_cursor fc;
684
- struct afs_volume_status vs;
752
+ struct afs_operation *op;
685753 struct afs_vnode *vnode = AFS_FS_I(d_inode(dentry));
686
- struct key *key;
687
- int ret;
688754
689755 buf->f_type = dentry->d_sb->s_magic;
690756 buf->f_bsize = AFS_BLOCK_SIZE;
....@@ -697,32 +763,13 @@
697763 return 0;
698764 }
699765
700
- key = afs_request_key(vnode->volume->cell);
701
- if (IS_ERR(key))
702
- return PTR_ERR(key);
766
+ op = afs_alloc_operation(NULL, as->volume);
767
+ if (IS_ERR(op))
768
+ return PTR_ERR(op);
703769
704
- ret = -ERESTARTSYS;
705
- if (afs_begin_vnode_operation(&fc, vnode, key)) {
706
- fc.flags |= AFS_FS_CURSOR_NO_VSLEEP;
707
- while (afs_select_fileserver(&fc)) {
708
- fc.cb_break = afs_calc_vnode_cb_break(vnode);
709
- afs_fs_get_volume_status(&fc, &vs);
710
- }
711
-
712
- afs_check_for_remote_deletion(&fc, fc.vnode);
713
- afs_vnode_commit_status(&fc, vnode, fc.cb_break);
714
- ret = afs_end_vnode_operation(&fc);
715
- }
716
-
717
- key_put(key);
718
-
719
- if (ret == 0) {
720
- if (vs.max_quota == 0)
721
- buf->f_blocks = vs.part_max_blocks;
722
- else
723
- buf->f_blocks = vs.max_quota;
724
- buf->f_bavail = buf->f_bfree = buf->f_blocks - vs.blocks_in_use;
725
- }
726
-
727
- return ret;
770
+ afs_op_set_vnode(op, 0, vnode);
771
+ op->nr_files = 1;
772
+ op->volstatus.buf = buf;
773
+ op->ops = &afs_get_volume_status_operation;
774
+ return afs_do_sync_operation(op);
728775 }