Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/fs/afs/super.c
26282 views
1
/* AFS superblock handling
2
*
3
* Copyright (c) 2002, 2007, 2018 Red Hat, Inc. All rights reserved.
4
*
5
* This software may be freely redistributed under the terms of the
6
* GNU General Public License.
7
*
8
* You should have received a copy of the GNU General Public License
9
* along with this program; if not, write to the Free Software
10
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
11
*
12
* Authors: David Howells <[email protected]>
13
* David Woodhouse <[email protected]>
14
*
15
*/
16
17
#include <linux/kernel.h>
18
#include <linux/module.h>
19
#include <linux/mount.h>
20
#include <linux/init.h>
21
#include <linux/slab.h>
22
#include <linux/fs.h>
23
#include <linux/pagemap.h>
24
#include <linux/fs_parser.h>
25
#include <linux/statfs.h>
26
#include <linux/sched.h>
27
#include <linux/nsproxy.h>
28
#include <linux/magic.h>
29
#include <net/net_namespace.h>
30
#include "internal.h"
31
32
static void afs_i_init_once(void *foo);
33
static void afs_kill_super(struct super_block *sb);
34
static struct inode *afs_alloc_inode(struct super_block *sb);
35
static void afs_destroy_inode(struct inode *inode);
36
static void afs_free_inode(struct inode *inode);
37
static int afs_statfs(struct dentry *dentry, struct kstatfs *buf);
38
static int afs_show_devname(struct seq_file *m, struct dentry *root);
39
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[];
42
43
struct file_system_type afs_fs_type = {
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,
50
};
51
MODULE_ALIAS_FS("afs");
52
53
int afs_net_id;
54
55
static const struct super_operations afs_super_ops = {
56
.statfs = afs_statfs,
57
.alloc_inode = afs_alloc_inode,
58
.write_inode = netfs_unpin_writeback,
59
.drop_inode = afs_drop_inode,
60
.destroy_inode = afs_destroy_inode,
61
.free_inode = afs_free_inode,
62
.evict_inode = afs_evict_inode,
63
.show_devname = afs_show_devname,
64
.show_options = afs_show_options,
65
};
66
67
static struct kmem_cache *afs_inode_cachep;
68
static atomic_t afs_count_active_inodes;
69
70
enum afs_param {
71
Opt_autocell,
72
Opt_dyn,
73
Opt_flock,
74
Opt_source,
75
};
76
77
static const struct constant_table afs_param_flock[] = {
78
{"local", afs_flock_mode_local },
79
{"openafs", afs_flock_mode_openafs },
80
{"strict", afs_flock_mode_strict },
81
{"write", afs_flock_mode_write },
82
{}
83
};
84
85
static const struct fs_parameter_spec afs_fs_parameters[] = {
86
fsparam_flag ("autocell", Opt_autocell),
87
fsparam_flag ("dyn", Opt_dyn),
88
fsparam_enum ("flock", Opt_flock, afs_param_flock),
89
fsparam_string("source", Opt_source),
90
{}
91
};
92
93
/*
94
* initialise the filesystem
95
*/
96
int __init afs_fs_init(void)
97
{
98
int ret;
99
100
_enter("");
101
102
/* create ourselves an inode cache */
103
atomic_set(&afs_count_active_inodes, 0);
104
105
ret = -ENOMEM;
106
afs_inode_cachep = kmem_cache_create("afs_inode_cache",
107
sizeof(struct afs_vnode),
108
0,
109
SLAB_HWCACHE_ALIGN|SLAB_ACCOUNT,
110
afs_i_init_once);
111
if (!afs_inode_cachep) {
112
printk(KERN_NOTICE "kAFS: Failed to allocate inode cache\n");
113
return ret;
114
}
115
116
/* now export our filesystem to lesser mortals */
117
ret = register_filesystem(&afs_fs_type);
118
if (ret < 0) {
119
kmem_cache_destroy(afs_inode_cachep);
120
_leave(" = %d", ret);
121
return ret;
122
}
123
124
_leave(" = 0");
125
return 0;
126
}
127
128
/*
129
* clean up the filesystem
130
*/
131
void afs_fs_exit(void)
132
{
133
_enter("");
134
135
afs_mntpt_kill_timer();
136
unregister_filesystem(&afs_fs_type);
137
138
if (atomic_read(&afs_count_active_inodes) != 0) {
139
printk("kAFS: %d active inode objects still present\n",
140
atomic_read(&afs_count_active_inodes));
141
BUG();
142
}
143
144
/*
145
* Make sure all delayed rcu free inodes are flushed before we
146
* destroy cache.
147
*/
148
rcu_barrier();
149
kmem_cache_destroy(afs_inode_cachep);
150
_leave("");
151
}
152
153
/*
154
* Display the mount device name in /proc/mounts.
155
*/
156
static int afs_show_devname(struct seq_file *m, struct dentry *root)
157
{
158
struct afs_super_info *as = AFS_FS_S(root->d_sb);
159
struct afs_volume *volume = as->volume;
160
struct afs_cell *cell = as->cell;
161
const char *suf = "";
162
char pref = '%';
163
164
if (as->dyn_root) {
165
seq_puts(m, "none");
166
return 0;
167
}
168
169
switch (volume->type) {
170
case AFSVL_RWVOL:
171
break;
172
case AFSVL_ROVOL:
173
pref = '#';
174
if (volume->type_force)
175
suf = ".readonly";
176
break;
177
case AFSVL_BACKVOL:
178
pref = '#';
179
suf = ".backup";
180
break;
181
}
182
183
seq_printf(m, "%c%s:%s%s", pref, cell->name, volume->name, suf);
184
return 0;
185
}
186
187
/*
188
* Display the mount options in /proc/mounts.
189
*/
190
static int afs_show_options(struct seq_file *m, struct dentry *root)
191
{
192
struct afs_super_info *as = AFS_FS_S(root->d_sb);
193
const char *p = NULL;
194
195
if (as->dyn_root)
196
seq_puts(m, ",dyn");
197
switch (as->flock_mode) {
198
case afs_flock_mode_unset: break;
199
case afs_flock_mode_local: p = "local"; break;
200
case afs_flock_mode_openafs: p = "openafs"; break;
201
case afs_flock_mode_strict: p = "strict"; break;
202
case afs_flock_mode_write: p = "write"; break;
203
}
204
if (p)
205
seq_printf(m, ",flock=%s", p);
206
207
return 0;
208
}
209
210
/*
211
* Parse the source name to get cell name, volume name, volume type and R/W
212
* selector.
213
*
214
* This can be one of the following:
215
* "%[cell:]volume[.]" R/W volume
216
* "#[cell:]volume[.]" R/O or R/W volume (R/O parent),
217
* or R/W (R/W parent) volume
218
* "%[cell:]volume.readonly" R/O volume
219
* "#[cell:]volume.readonly" R/O volume
220
* "%[cell:]volume.backup" Backup volume
221
* "#[cell:]volume.backup" Backup volume
222
*/
223
static int afs_parse_source(struct fs_context *fc, struct fs_parameter *param)
224
{
225
struct afs_fs_context *ctx = fc->fs_private;
226
struct afs_cell *cell;
227
const char *cellname, *suffix, *name = param->string;
228
int cellnamesz;
229
230
_enter(",%s", name);
231
232
if (fc->source)
233
return invalf(fc, "kAFS: Multiple sources not supported");
234
235
if (!name) {
236
printk(KERN_ERR "kAFS: no volume name specified\n");
237
return -EINVAL;
238
}
239
240
if ((name[0] != '%' && name[0] != '#') || !name[1]) {
241
/* To use dynroot, we don't want to have to provide a source */
242
if (strcmp(name, "none") == 0) {
243
ctx->no_cell = true;
244
return 0;
245
}
246
printk(KERN_ERR "kAFS: unparsable volume name\n");
247
return -EINVAL;
248
}
249
250
/* determine the type of volume we're looking for */
251
if (name[0] == '%') {
252
ctx->type = AFSVL_RWVOL;
253
ctx->force = true;
254
}
255
name++;
256
257
/* split the cell name out if there is one */
258
ctx->volname = strchr(name, ':');
259
if (ctx->volname) {
260
cellname = name;
261
cellnamesz = ctx->volname - name;
262
ctx->volname++;
263
} else {
264
ctx->volname = name;
265
cellname = NULL;
266
cellnamesz = 0;
267
}
268
269
/* the volume type is further affected by a possible suffix */
270
suffix = strrchr(ctx->volname, '.');
271
if (suffix) {
272
if (strcmp(suffix, ".readonly") == 0) {
273
ctx->type = AFSVL_ROVOL;
274
ctx->force = true;
275
} else if (strcmp(suffix, ".backup") == 0) {
276
ctx->type = AFSVL_BACKVOL;
277
ctx->force = true;
278
} else if (suffix[1] == 0) {
279
} else {
280
suffix = NULL;
281
}
282
}
283
284
ctx->volnamesz = suffix ?
285
suffix - ctx->volname : strlen(ctx->volname);
286
287
_debug("cell %*.*s [%p]",
288
cellnamesz, cellnamesz, cellname ?: "", ctx->cell);
289
290
/* lookup the cell record */
291
if (cellname) {
292
cell = afs_lookup_cell(ctx->net, cellname, cellnamesz,
293
NULL, false,
294
afs_cell_trace_use_lookup_mount);
295
if (IS_ERR(cell)) {
296
pr_err("kAFS: unable to lookup cell '%*.*s'\n",
297
cellnamesz, cellnamesz, cellname ?: "");
298
return PTR_ERR(cell);
299
}
300
afs_unuse_cell(ctx->cell, afs_cell_trace_unuse_parse);
301
afs_see_cell(cell, afs_cell_trace_see_source);
302
ctx->cell = cell;
303
}
304
305
_debug("CELL:%s [%p] VOLUME:%*.*s SUFFIX:%s TYPE:%d%s",
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->volume, afs_volume_trace_put_validate_fc);
384
ctx->volume = NULL;
385
}
386
387
if (test_bit(AFS_CELL_FL_CHECK_ALIAS, &ctx->cell->flags)) {
388
ret = afs_cell_detect_alias(ctx->cell, key);
389
if (ret < 0)
390
return ret;
391
if (ret == 1) {
392
_debug("switch to alias");
393
key_put(ctx->key);
394
ctx->key = NULL;
395
cell = afs_use_cell(ctx->cell->alias_of,
396
afs_cell_trace_use_fc_alias);
397
afs_unuse_cell(ctx->cell, afs_cell_trace_unuse_fc);
398
ctx->cell = cell;
399
goto reget_key;
400
}
401
}
402
403
volume = afs_create_volume(ctx);
404
if (IS_ERR(volume))
405
return PTR_ERR(volume);
406
407
ctx->volume = volume;
408
if (volume->type != AFSVL_RWVOL) {
409
ctx->flock_mode = afs_flock_mode_local;
410
fc->sb_flags |= SB_RDONLY;
411
}
412
}
413
414
return 0;
415
}
416
417
/*
418
* check a superblock to see if it's the one we're looking for
419
*/
420
static int afs_test_super(struct super_block *sb, struct fs_context *fc)
421
{
422
struct afs_fs_context *ctx = fc->fs_private;
423
struct afs_super_info *as = AFS_FS_S(sb);
424
425
return (as->net_ns == fc->net_ns &&
426
as->volume &&
427
as->volume->vid == ctx->volume->vid &&
428
as->cell == ctx->cell &&
429
!as->dyn_root);
430
}
431
432
static int afs_dynroot_test_super(struct super_block *sb, struct fs_context *fc)
433
{
434
struct afs_super_info *as = AFS_FS_S(sb);
435
436
return (as->net_ns == fc->net_ns &&
437
as->dyn_root);
438
}
439
440
static int afs_set_super(struct super_block *sb, struct fs_context *fc)
441
{
442
return set_anon_super(sb, NULL);
443
}
444
445
/*
446
* fill in the superblock
447
*/
448
static int afs_fill_super(struct super_block *sb, struct afs_fs_context *ctx)
449
{
450
struct afs_super_info *as = AFS_FS_S(sb);
451
struct inode *inode = NULL;
452
int ret;
453
454
_enter("");
455
456
/* fill in the superblock */
457
sb->s_blocksize = PAGE_SIZE;
458
sb->s_blocksize_bits = PAGE_SHIFT;
459
sb->s_maxbytes = MAX_LFS_FILESIZE;
460
sb->s_magic = AFS_FS_MAGIC;
461
sb->s_op = &afs_super_ops;
462
if (!as->dyn_root)
463
sb->s_xattr = afs_xattr_handlers;
464
ret = super_setup_bdi(sb);
465
if (ret)
466
return ret;
467
468
/* allocate the root inode and dentry */
469
if (as->dyn_root) {
470
inode = afs_dynroot_iget_root(sb);
471
} else {
472
sprintf(sb->s_id, "%llu", as->volume->vid);
473
afs_activate_volume(as->volume);
474
inode = afs_root_iget(sb, ctx->key);
475
}
476
477
if (IS_ERR(inode))
478
return PTR_ERR(inode);
479
480
ret = -ENOMEM;
481
sb->s_root = d_make_root(inode);
482
if (!sb->s_root)
483
goto error;
484
485
if (as->dyn_root) {
486
set_default_d_op(sb, &afs_dynroot_dentry_operations);
487
} else {
488
set_default_d_op(sb, &afs_fs_dentry_operations);
489
rcu_assign_pointer(as->volume->sb, sb);
490
}
491
492
_leave(" = 0");
493
return 0;
494
495
error:
496
_leave(" = %d", ret);
497
return ret;
498
}
499
500
static struct afs_super_info *afs_alloc_sbi(struct fs_context *fc)
501
{
502
struct afs_fs_context *ctx = fc->fs_private;
503
struct afs_super_info *as;
504
505
as = kzalloc(sizeof(struct afs_super_info), GFP_KERNEL);
506
if (as) {
507
as->net_ns = get_net(fc->net_ns);
508
as->flock_mode = ctx->flock_mode;
509
if (ctx->dyn_root) {
510
as->dyn_root = true;
511
} else {
512
as->cell = afs_use_cell(ctx->cell, afs_cell_trace_use_sbi);
513
as->volume = afs_get_volume(ctx->volume,
514
afs_volume_trace_get_alloc_sbi);
515
}
516
}
517
return as;
518
}
519
520
static void afs_destroy_sbi(struct afs_super_info *as)
521
{
522
if (as) {
523
afs_put_volume(as->volume, afs_volume_trace_put_destroy_sbi);
524
afs_unuse_cell(as->cell, afs_cell_trace_unuse_sbi);
525
put_net(as->net_ns);
526
kfree(as);
527
}
528
}
529
530
static void afs_kill_super(struct super_block *sb)
531
{
532
struct afs_super_info *as = AFS_FS_S(sb);
533
534
/* Clear the callback interests (which will do ilookup5) before
535
* deactivating the superblock.
536
*/
537
if (as->volume)
538
rcu_assign_pointer(as->volume->sb, NULL);
539
kill_anon_super(sb);
540
if (as->volume)
541
afs_deactivate_volume(as->volume);
542
afs_destroy_sbi(as);
543
}
544
545
/*
546
* Get an AFS superblock and root directory.
547
*/
548
static int afs_get_tree(struct fs_context *fc)
549
{
550
struct afs_fs_context *ctx = fc->fs_private;
551
struct super_block *sb;
552
struct afs_super_info *as;
553
int ret;
554
555
ret = afs_validate_fc(fc);
556
if (ret)
557
goto error;
558
559
_enter("");
560
561
/* allocate a superblock info record */
562
ret = -ENOMEM;
563
as = afs_alloc_sbi(fc);
564
if (!as)
565
goto error;
566
fc->s_fs_info = as;
567
568
/* allocate a deviceless superblock */
569
sb = sget_fc(fc,
570
as->dyn_root ? afs_dynroot_test_super : afs_test_super,
571
afs_set_super);
572
if (IS_ERR(sb)) {
573
ret = PTR_ERR(sb);
574
goto error;
575
}
576
577
if (!sb->s_root) {
578
/* initial superblock/root creation */
579
_debug("create");
580
ret = afs_fill_super(sb, ctx);
581
if (ret < 0)
582
goto error_sb;
583
sb->s_flags |= SB_ACTIVE;
584
} else {
585
_debug("reuse");
586
ASSERTCMP(sb->s_flags, &, SB_ACTIVE);
587
}
588
589
fc->root = dget(sb->s_root);
590
trace_afs_get_tree(as->cell, as->volume);
591
_leave(" = 0 [%p]", sb);
592
return 0;
593
594
error_sb:
595
deactivate_locked_super(sb);
596
error:
597
_leave(" = %d", ret);
598
return ret;
599
}
600
601
static void afs_free_fc(struct fs_context *fc)
602
{
603
struct afs_fs_context *ctx = fc->fs_private;
604
605
afs_destroy_sbi(fc->s_fs_info);
606
afs_put_volume(ctx->volume, afs_volume_trace_put_free_fc);
607
afs_unuse_cell(ctx->cell, afs_cell_trace_unuse_fc);
608
key_put(ctx->key);
609
kfree(ctx);
610
}
611
612
static const struct fs_context_operations afs_context_ops = {
613
.free = afs_free_fc,
614
.parse_param = afs_parse_param,
615
.get_tree = afs_get_tree,
616
};
617
618
/*
619
* Set up the filesystem mount context.
620
*/
621
static int afs_init_fs_context(struct fs_context *fc)
622
{
623
struct afs_fs_context *ctx;
624
struct afs_cell *cell;
625
626
ctx = kzalloc(sizeof(struct afs_fs_context), GFP_KERNEL);
627
if (!ctx)
628
return -ENOMEM;
629
630
ctx->type = AFSVL_ROVOL;
631
ctx->net = afs_net(fc->net_ns);
632
633
/* Default to the workstation cell. */
634
cell = afs_find_cell(ctx->net, NULL, 0, afs_cell_trace_use_fc);
635
if (IS_ERR(cell))
636
cell = NULL;
637
ctx->cell = cell;
638
639
fc->fs_private = ctx;
640
fc->ops = &afs_context_ops;
641
return 0;
642
}
643
644
/*
645
* Initialise an inode cache slab element prior to any use. Note that
646
* afs_alloc_inode() *must* reset anything that could incorrectly leak from one
647
* inode to another.
648
*/
649
static void afs_i_init_once(void *_vnode)
650
{
651
struct afs_vnode *vnode = _vnode;
652
653
memset(vnode, 0, sizeof(*vnode));
654
inode_init_once(&vnode->netfs.inode);
655
INIT_LIST_HEAD(&vnode->io_lock_waiters);
656
init_rwsem(&vnode->validate_lock);
657
spin_lock_init(&vnode->wb_lock);
658
spin_lock_init(&vnode->lock);
659
INIT_LIST_HEAD(&vnode->wb_keys);
660
INIT_LIST_HEAD(&vnode->pending_locks);
661
INIT_LIST_HEAD(&vnode->granted_locks);
662
INIT_DELAYED_WORK(&vnode->lock_work, afs_lock_work);
663
INIT_LIST_HEAD(&vnode->cb_mmap_link);
664
seqlock_init(&vnode->cb_lock);
665
}
666
667
/*
668
* allocate an AFS inode struct from our slab cache
669
*/
670
static struct inode *afs_alloc_inode(struct super_block *sb)
671
{
672
struct afs_vnode *vnode;
673
674
vnode = alloc_inode_sb(sb, afs_inode_cachep, GFP_KERNEL);
675
if (!vnode)
676
return NULL;
677
678
atomic_inc(&afs_count_active_inodes);
679
680
/* Reset anything that shouldn't leak from one inode to the next. */
681
memset(&vnode->fid, 0, sizeof(vnode->fid));
682
memset(&vnode->status, 0, sizeof(vnode->status));
683
afs_vnode_set_cache(vnode, NULL);
684
685
vnode->volume = NULL;
686
vnode->lock_key = NULL;
687
vnode->permit_cache = NULL;
688
vnode->directory = NULL;
689
vnode->directory_size = 0;
690
691
vnode->flags = 1 << AFS_VNODE_UNSET;
692
vnode->lock_state = AFS_VNODE_LOCK_NONE;
693
694
init_rwsem(&vnode->rmdir_lock);
695
INIT_WORK(&vnode->cb_work, afs_invalidate_mmap_work);
696
697
_leave(" = %p", &vnode->netfs.inode);
698
return &vnode->netfs.inode;
699
}
700
701
static void afs_free_inode(struct inode *inode)
702
{
703
kmem_cache_free(afs_inode_cachep, AFS_FS_I(inode));
704
}
705
706
/*
707
* destroy an AFS inode struct
708
*/
709
static void afs_destroy_inode(struct inode *inode)
710
{
711
struct afs_vnode *vnode = AFS_FS_I(inode);
712
713
_enter("%p{%llx:%llu}", inode, vnode->fid.vid, vnode->fid.vnode);
714
715
_debug("DESTROY INODE %p", inode);
716
717
atomic_dec(&afs_count_active_inodes);
718
}
719
720
static void afs_get_volume_status_success(struct afs_operation *op)
721
{
722
struct afs_volume_status *vs = &op->volstatus.vs;
723
struct kstatfs *buf = op->volstatus.buf;
724
725
if (vs->max_quota == 0)
726
buf->f_blocks = vs->part_max_blocks;
727
else
728
buf->f_blocks = vs->max_quota;
729
730
if (buf->f_blocks > vs->blocks_in_use)
731
buf->f_bavail = buf->f_bfree =
732
buf->f_blocks - vs->blocks_in_use;
733
}
734
735
static const struct afs_operation_ops afs_get_volume_status_operation = {
736
.issue_afs_rpc = afs_fs_get_volume_status,
737
.issue_yfs_rpc = yfs_fs_get_volume_status,
738
.success = afs_get_volume_status_success,
739
};
740
741
/*
742
* return information about an AFS volume
743
*/
744
static int afs_statfs(struct dentry *dentry, struct kstatfs *buf)
745
{
746
struct afs_super_info *as = AFS_FS_S(dentry->d_sb);
747
struct afs_operation *op;
748
struct afs_vnode *vnode = AFS_FS_I(d_inode(dentry));
749
750
buf->f_type = dentry->d_sb->s_magic;
751
buf->f_bsize = AFS_BLOCK_SIZE;
752
buf->f_namelen = AFSNAMEMAX - 1;
753
754
if (as->dyn_root) {
755
buf->f_blocks = 1;
756
buf->f_bavail = 0;
757
buf->f_bfree = 0;
758
return 0;
759
}
760
761
op = afs_alloc_operation(NULL, as->volume);
762
if (IS_ERR(op))
763
return PTR_ERR(op);
764
765
afs_op_set_vnode(op, 0, vnode);
766
op->nr_files = 1;
767
op->volstatus.buf = buf;
768
op->ops = &afs_get_volume_status_operation;
769
return afs_do_sync_operation(op);
770
}
771
772