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