Blame view

fs/afs/super.c 12.3 KB
ec26815ad   David Howells   [AFS]: Clean up t...
1
2
  /* AFS superblock handling
   *
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
3
   * Copyright (c) 2002, 2007 Red Hat, Inc. All rights reserved.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4
5
6
7
8
9
10
11
12
   *
   * This software may be freely redistributed under the terms of the
   * GNU General Public License.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   *
   * Authors: David Howells <dhowells@redhat.com>
44d1b980c   David Woodhouse   Fix various old e...
13
   *          David Woodhouse <dwmw2@infradead.org>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
14
15
16
17
18
   *
   */
  
  #include <linux/kernel.h>
  #include <linux/module.h>
bec5eb614   wanglei   AFS: Implement an...
19
  #include <linux/mount.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
21
22
23
  #include <linux/init.h>
  #include <linux/slab.h>
  #include <linux/fs.h>
  #include <linux/pagemap.h>
80c72fe41   David Howells   [AFS/AF_RXRPC]: M...
24
  #include <linux/parser.h>
45222b9e0   David Howells   AFS: implement st...
25
  #include <linux/statfs.h>
e8edc6e03   Alexey Dobriyan   Detach sched.h fr...
26
  #include <linux/sched.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27
28
29
  #include "internal.h"
  
  #define AFS_FS_MAGIC 0x6B414653 /* 'kAFS' */
51cc50685   Alexey Dobriyan   SL*B: drop kmem c...
30
  static void afs_i_init_once(void *foo);
f7442b3be   Al Viro   convert afs
31
32
  static struct dentry *afs_mount(struct file_system_type *fs_type,
  		      int flags, const char *dev_name, void *data);
dde194a64   Al Viro   afs: fix sget() r...
33
  static void afs_kill_super(struct super_block *sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
  static struct inode *afs_alloc_inode(struct super_block *sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35
  static void afs_destroy_inode(struct inode *inode);
45222b9e0   David Howells   AFS: implement st...
36
  static int afs_statfs(struct dentry *dentry, struct kstatfs *buf);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37

1f5ce9e93   Trond Myklebust   VFS: Unexport do_...
38
  struct file_system_type afs_fs_type = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
39
40
  	.owner		= THIS_MODULE,
  	.name		= "afs",
f7442b3be   Al Viro   convert afs
41
  	.mount		= afs_mount,
dde194a64   Al Viro   afs: fix sget() r...
42
  	.kill_sb	= afs_kill_super,
80c72fe41   David Howells   [AFS/AF_RXRPC]: M...
43
  	.fs_flags	= 0,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
44
  };
ee9b6d61a   Josef 'Jeff' Sipek   [PATCH] Mark stru...
45
  static const struct super_operations afs_super_ops = {
45222b9e0   David Howells   AFS: implement st...
46
  	.statfs		= afs_statfs,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
47
  	.alloc_inode	= afs_alloc_inode,
bec5eb614   wanglei   AFS: Implement an...
48
  	.drop_inode	= afs_drop_inode,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49
  	.destroy_inode	= afs_destroy_inode,
b57922d97   Al Viro   convert remaining...
50
  	.evict_inode	= afs_evict_inode,
969729d56   Miklos Szeredi   mount options: fi...
51
  	.show_options	= generic_show_options,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
52
  };
e18b890bb   Christoph Lameter   [PATCH] slab: rem...
53
  static struct kmem_cache *afs_inode_cachep;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
54
  static atomic_t afs_count_active_inodes;
80c72fe41   David Howells   [AFS/AF_RXRPC]: M...
55
56
57
58
59
  enum {
  	afs_no_opt,
  	afs_opt_cell,
  	afs_opt_rwpath,
  	afs_opt_vol,
bec5eb614   wanglei   AFS: Implement an...
60
  	afs_opt_autocell,
80c72fe41   David Howells   [AFS/AF_RXRPC]: M...
61
  };
a447c0932   Steven Whitehouse   vfs: Use const fo...
62
  static const match_table_t afs_options_list = {
80c72fe41   David Howells   [AFS/AF_RXRPC]: M...
63
64
65
  	{ afs_opt_cell,		"cell=%s"	},
  	{ afs_opt_rwpath,	"rwpath"	},
  	{ afs_opt_vol,		"vol=%s"	},
bec5eb614   wanglei   AFS: Implement an...
66
  	{ afs_opt_autocell,	"autocell"	},
80c72fe41   David Howells   [AFS/AF_RXRPC]: M...
67
68
  	{ afs_no_opt,		NULL		},
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
69
70
71
72
73
74
75
76
  /*
   * initialise the filesystem
   */
  int __init afs_fs_init(void)
  {
  	int ret;
  
  	_enter("");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
77
78
79
80
81
82
83
84
  	/* create ourselves an inode cache */
  	atomic_set(&afs_count_active_inodes, 0);
  
  	ret = -ENOMEM;
  	afs_inode_cachep = kmem_cache_create("afs_inode_cache",
  					     sizeof(struct afs_vnode),
  					     0,
  					     SLAB_HWCACHE_ALIGN,
20c2df83d   Paul Mundt   mm: Remove slab d...
85
  					     afs_i_init_once);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
86
87
88
89
90
91
92
93
94
95
  	if (!afs_inode_cachep) {
  		printk(KERN_NOTICE "kAFS: Failed to allocate inode cache
  ");
  		return ret;
  	}
  
  	/* now export our filesystem to lesser mortals */
  	ret = register_filesystem(&afs_fs_type);
  	if (ret < 0) {
  		kmem_cache_destroy(afs_inode_cachep);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
96
  		_leave(" = %d", ret);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
97
98
  		return ret;
  	}
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
99
  	_leave(" = 0");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
100
  	return 0;
ec26815ad   David Howells   [AFS]: Clean up t...
101
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
102

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
103
104
105
106
107
  /*
   * clean up the filesystem
   */
  void __exit afs_fs_exit(void)
  {
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
108
109
110
  	_enter("");
  
  	afs_mntpt_kill_timer();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
111
112
113
114
115
116
117
118
119
120
  	unregister_filesystem(&afs_fs_type);
  
  	if (atomic_read(&afs_count_active_inodes) != 0) {
  		printk("kAFS: %d active inode objects still present
  ",
  		       atomic_read(&afs_count_active_inodes));
  		BUG();
  	}
  
  	kmem_cache_destroy(afs_inode_cachep);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
121
  	_leave("");
ec26815ad   David Howells   [AFS]: Clean up t...
122
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
123

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
124
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
125
126
127
128
   * parse the mount options
   * - this function has been shamelessly adapted from the ext3 fs which
   *   shamelessly adapted it from the msdos fs
   */
00d3b7a45   David Howells   [AFS]: Add securi...
129
130
  static int afs_parse_options(struct afs_mount_params *params,
  			     char *options, const char **devname)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
131
  {
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
132
  	struct afs_cell *cell;
80c72fe41   David Howells   [AFS/AF_RXRPC]: M...
133
134
135
  	substring_t args[MAX_OPT_ARGS];
  	char *p;
  	int token;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
136
137
138
139
  
  	_enter("%s", options);
  
  	options[PAGE_SIZE - 1] = 0;
80c72fe41   David Howells   [AFS/AF_RXRPC]: M...
140
141
142
  	while ((p = strsep(&options, ","))) {
  		if (!*p)
  			continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
143

80c72fe41   David Howells   [AFS/AF_RXRPC]: M...
144
145
146
147
  		token = match_token(p, afs_options_list, args);
  		switch (token) {
  		case afs_opt_cell:
  			cell = afs_cell_lookup(args[0].from,
bec5eb614   wanglei   AFS: Implement an...
148
149
  					       args[0].to - args[0].from,
  					       false);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
150
151
  			if (IS_ERR(cell))
  				return PTR_ERR(cell);
00d3b7a45   David Howells   [AFS]: Add securi...
152
153
  			afs_put_cell(params->cell);
  			params->cell = cell;
80c72fe41   David Howells   [AFS/AF_RXRPC]: M...
154
155
156
157
158
159
160
161
162
  			break;
  
  		case afs_opt_rwpath:
  			params->rwpath = 1;
  			break;
  
  		case afs_opt_vol:
  			*devname = args[0].from;
  			break;
bec5eb614   wanglei   AFS: Implement an...
163
164
165
  		case afs_opt_autocell:
  			params->autocell = 1;
  			break;
80c72fe41   David Howells   [AFS/AF_RXRPC]: M...
166
167
168
169
170
  		default:
  			printk(KERN_ERR "kAFS:"
  			       " Unknown or invalid mount option: '%s'
  ", p);
  			return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
171
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
172
  	}
80c72fe41   David Howells   [AFS/AF_RXRPC]: M...
173
174
  	_leave(" = 0");
  	return 0;
ec26815ad   David Howells   [AFS]: Clean up t...
175
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
176

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
177
  /*
00d3b7a45   David Howells   [AFS]: Add securi...
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
   * parse a device name to get cell name, volume name, volume type and R/W
   * selector
   * - this can be one of the following:
   *	"%[cell:]volume[.]"		R/W volume
   *	"#[cell:]volume[.]"		R/O or R/W volume (rwpath=0),
   *					 or R/W (rwpath=1) volume
   *	"%[cell:]volume.readonly"	R/O volume
   *	"#[cell:]volume.readonly"	R/O volume
   *	"%[cell:]volume.backup"		Backup volume
   *	"#[cell:]volume.backup"		Backup volume
   */
  static int afs_parse_device_name(struct afs_mount_params *params,
  				 const char *name)
  {
  	struct afs_cell *cell;
  	const char *cellname, *suffix;
  	int cellnamesz;
  
  	_enter(",%s", name);
  
  	if (!name) {
  		printk(KERN_ERR "kAFS: no volume name specified
  ");
  		return -EINVAL;
  	}
  
  	if ((name[0] != '%' && name[0] != '#') || !name[1]) {
  		printk(KERN_ERR "kAFS: unparsable volume name
  ");
  		return -EINVAL;
  	}
  
  	/* determine the type of volume we're looking for */
  	params->type = AFSVL_ROVOL;
  	params->force = false;
  	if (params->rwpath || name[0] == '%') {
  		params->type = AFSVL_RWVOL;
  		params->force = true;
  	}
  	name++;
  
  	/* split the cell name out if there is one */
  	params->volname = strchr(name, ':');
  	if (params->volname) {
  		cellname = name;
  		cellnamesz = params->volname - name;
  		params->volname++;
  	} else {
  		params->volname = name;
  		cellname = NULL;
  		cellnamesz = 0;
  	}
  
  	/* the volume type is further affected by a possible suffix */
  	suffix = strrchr(params->volname, '.');
  	if (suffix) {
  		if (strcmp(suffix, ".readonly") == 0) {
  			params->type = AFSVL_ROVOL;
  			params->force = true;
  		} else if (strcmp(suffix, ".backup") == 0) {
  			params->type = AFSVL_BACKVOL;
  			params->force = true;
  		} else if (suffix[1] == 0) {
  		} else {
  			suffix = NULL;
  		}
  	}
  
  	params->volnamesz = suffix ?
  		suffix - params->volname : strlen(params->volname);
  
  	_debug("cell %*.*s [%p]",
  	       cellnamesz, cellnamesz, cellname ?: "", params->cell);
  
  	/* lookup the cell record */
  	if (cellname || !params->cell) {
bec5eb614   wanglei   AFS: Implement an...
254
  		cell = afs_cell_lookup(cellname, cellnamesz, true);
00d3b7a45   David Howells   [AFS]: Add securi...
255
  		if (IS_ERR(cell)) {
bec5eb614   wanglei   AFS: Implement an...
256
257
258
  			printk(KERN_ERR "kAFS: unable to lookup cell '%*.*s'
  ",
  			       cellnamesz, cellnamesz, cellname ?: "");
00d3b7a45   David Howells   [AFS]: Add securi...
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
  			return PTR_ERR(cell);
  		}
  		afs_put_cell(params->cell);
  		params->cell = cell;
  	}
  
  	_debug("CELL:%s [%p] VOLUME:%*.*s SUFFIX:%s TYPE:%d%s",
  	       params->cell->name, params->cell,
  	       params->volnamesz, params->volnamesz, params->volname,
  	       suffix ?: "-", params->type, params->force ? " FORCE" : "");
  
  	return 0;
  }
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
274
275
276
277
   * check a superblock to see if it's the one we're looking for
   */
  static int afs_test_super(struct super_block *sb, void *data)
  {
dde194a64   Al Viro   afs: fix sget() r...
278
  	struct afs_super_info *as1 = data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
279
  	struct afs_super_info *as = sb->s_fs_info;
dde194a64   Al Viro   afs: fix sget() r...
280
281
282
283
284
285
286
  	return as->volume == as1->volume;
  }
  
  static int afs_set_super(struct super_block *sb, void *data)
  {
  	sb->s_fs_info = data;
  	return set_anon_super(sb, NULL);
ec26815ad   David Howells   [AFS]: Clean up t...
287
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
288

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
289
290
291
  /*
   * fill in the superblock
   */
dde194a64   Al Viro   afs: fix sget() r...
292
293
  static int afs_fill_super(struct super_block *sb,
  			  struct afs_mount_params *params)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
294
  {
dde194a64   Al Viro   afs: fix sget() r...
295
  	struct afs_super_info *as = sb->s_fs_info;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
296
297
298
299
  	struct afs_fid fid;
  	struct dentry *root = NULL;
  	struct inode *inode = NULL;
  	int ret;
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
300
  	_enter("");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
301

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
302
303
304
305
306
  	/* fill in the superblock */
  	sb->s_blocksize		= PAGE_CACHE_SIZE;
  	sb->s_blocksize_bits	= PAGE_CACHE_SHIFT;
  	sb->s_magic		= AFS_FS_MAGIC;
  	sb->s_op		= &afs_super_ops;
e1da02227   Jens Axboe   afs: add bdi back...
307
  	sb->s_bdi		= &as->volume->bdi;
2e41ae225   David Howells   AFS: Set s_id in ...
308
  	strlcpy(sb->s_id, as->volume->vlocation->vldb.name, sizeof(sb->s_id));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
309
310
311
312
313
  
  	/* allocate the root inode and dentry */
  	fid.vid		= as->volume->vid;
  	fid.vnode	= 1;
  	fid.unique	= 1;
260a98031   David Howells   [AFS]: Add "direc...
314
  	inode = afs_iget(sb, params->key, &fid, NULL, NULL);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
315
  	if (IS_ERR(inode))
dde194a64   Al Viro   afs: fix sget() r...
316
  		return PTR_ERR(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
317

bec5eb614   wanglei   AFS: Implement an...
318
319
  	if (params->autocell)
  		set_bit(AFS_VNODE_AUTOCELL, &AFS_FS_I(inode)->flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
320
321
322
323
  	ret = -ENOMEM;
  	root = d_alloc_root(inode);
  	if (!root)
  		goto error;
d61dcce29   Al Viro   switch afs
324
  	sb->s_d_op = &afs_fs_dentry_operations;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
325
  	sb->s_root = root;
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
326
  	_leave(" = 0");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
327
  	return 0;
ec26815ad   David Howells   [AFS]: Clean up t...
328
  error:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
329
  	iput(inode);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
330
  	_leave(" = %d", ret);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
331
  	return ret;
ec26815ad   David Howells   [AFS]: Clean up t...
332
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
333

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
334
335
  /*
   * get an AFS superblock
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
336
   */
f7442b3be   Al Viro   convert afs
337
338
  static struct dentry *afs_mount(struct file_system_type *fs_type,
  		      int flags, const char *dev_name, void *options)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
339
340
341
  {
  	struct afs_mount_params params;
  	struct super_block *sb;
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
342
  	struct afs_volume *vol;
00d3b7a45   David Howells   [AFS]: Add securi...
343
  	struct key *key;
969729d56   Miklos Szeredi   mount options: fi...
344
  	char *new_opts = kstrdup(options, GFP_KERNEL);
dde194a64   Al Viro   afs: fix sget() r...
345
  	struct afs_super_info *as;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
346
347
348
349
350
  	int ret;
  
  	_enter(",,%s,%p", dev_name, options);
  
  	memset(&params, 0, sizeof(params));
00d3b7a45   David Howells   [AFS]: Add securi...
351
  	/* parse the options and device name */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
352
  	if (options) {
00d3b7a45   David Howells   [AFS]: Add securi...
353
  		ret = afs_parse_options(&params, options, &dev_name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
354
355
  		if (ret < 0)
  			goto error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
356
  	}
00d3b7a45   David Howells   [AFS]: Add securi...
357
358
359
360
361
362
363
364
365
366
367
368
  	ret = afs_parse_device_name(&params, dev_name);
  	if (ret < 0)
  		goto error;
  
  	/* try and do the mount securely */
  	key = afs_request_key(params.cell);
  	if (IS_ERR(key)) {
  		_leave(" = %ld [key]", PTR_ERR(key));
  		ret = PTR_ERR(key);
  		goto error;
  	}
  	params.key = key;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
369
  	/* parse the device name */
00d3b7a45   David Howells   [AFS]: Add securi...
370
  	vol = afs_volume_lookup(&params);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
371
372
  	if (IS_ERR(vol)) {
  		ret = PTR_ERR(vol);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
373
  		goto error;
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
374
  	}
dde194a64   Al Viro   afs: fix sget() r...
375
376
377
378
379
380
381
382
383
  
  	/* allocate a superblock info record */
  	as = kzalloc(sizeof(struct afs_super_info), GFP_KERNEL);
  	if (!as) {
  		ret = -ENOMEM;
  		afs_put_volume(vol);
  		goto error;
  	}
  	as->volume = vol;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
384
385
  
  	/* allocate a deviceless superblock */
dde194a64   Al Viro   afs: fix sget() r...
386
  	sb = sget(fs_type, afs_test_super, afs_set_super, as);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
387
388
  	if (IS_ERR(sb)) {
  		ret = PTR_ERR(sb);
dde194a64   Al Viro   afs: fix sget() r...
389
390
  		afs_put_volume(vol);
  		kfree(as);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
391
  		goto error;
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
392
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
393

436058a49   David Howells   [AFS]: Handle mul...
394
395
396
397
398
399
  	if (!sb->s_root) {
  		/* initial superblock/root creation */
  		_debug("create");
  		sb->s_flags = flags;
  		ret = afs_fill_super(sb, &params);
  		if (ret < 0) {
6f5bbff9a   Al Viro   Convert obvious p...
400
  			deactivate_locked_super(sb);
436058a49   David Howells   [AFS]: Handle mul...
401
402
  			goto error;
  		}
2a32cebd6   Al Viro   Fix races around ...
403
  		save_mount_options(sb, new_opts);
436058a49   David Howells   [AFS]: Handle mul...
404
405
406
407
  		sb->s_flags |= MS_ACTIVE;
  	} else {
  		_debug("reuse");
  		ASSERTCMP(sb->s_flags, &, MS_ACTIVE);
dde194a64   Al Viro   afs: fix sget() r...
408
409
  		afs_put_volume(vol);
  		kfree(as);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
410
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
411

00d3b7a45   David Howells   [AFS]: Add securi...
412
  	afs_put_cell(params.cell);
2a32cebd6   Al Viro   Fix races around ...
413
  	kfree(new_opts);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
414
  	_leave(" = 0 [%p]", sb);
f7442b3be   Al Viro   convert afs
415
  	return dget(sb->s_root);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
416

ec26815ad   David Howells   [AFS]: Clean up t...
417
  error:
00d3b7a45   David Howells   [AFS]: Add securi...
418
419
  	afs_put_cell(params.cell);
  	key_put(params.key);
969729d56   Miklos Szeredi   mount options: fi...
420
  	kfree(new_opts);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
421
  	_leave(" = %d", ret);
f7442b3be   Al Viro   convert afs
422
  	return ERR_PTR(ret);
ec26815ad   David Howells   [AFS]: Clean up t...
423
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
424

dde194a64   Al Viro   afs: fix sget() r...
425
  static void afs_kill_super(struct super_block *sb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
426
427
  {
  	struct afs_super_info *as = sb->s_fs_info;
dde194a64   Al Viro   afs: fix sget() r...
428
  	kill_anon_super(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
429
  	afs_put_volume(as->volume);
dde194a64   Al Viro   afs: fix sget() r...
430
  	kfree(as);
ec26815ad   David Howells   [AFS]: Clean up t...
431
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
432

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
433
434
435
  /*
   * initialise an inode cache slab element prior to any use
   */
51cc50685   Alexey Dobriyan   SL*B: drop kmem c...
436
  static void afs_i_init_once(void *_vnode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
437
  {
ec26815ad   David Howells   [AFS]: Clean up t...
438
  	struct afs_vnode *vnode = _vnode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
439

a35afb830   Christoph Lameter   Remove SLAB_CTOR_...
440
441
442
443
444
445
446
447
  	memset(vnode, 0, sizeof(*vnode));
  	inode_init_once(&vnode->vfs_inode);
  	init_waitqueue_head(&vnode->update_waitq);
  	mutex_init(&vnode->permits_lock);
  	mutex_init(&vnode->validate_lock);
  	spin_lock_init(&vnode->writeback_lock);
  	spin_lock_init(&vnode->lock);
  	INIT_LIST_HEAD(&vnode->writebacks);
e8d6c5541   David Howells   AFS: implement fi...
448
449
450
  	INIT_LIST_HEAD(&vnode->pending_locks);
  	INIT_LIST_HEAD(&vnode->granted_locks);
  	INIT_DELAYED_WORK(&vnode->lock_work, afs_lock_work);
a35afb830   Christoph Lameter   Remove SLAB_CTOR_...
451
  	INIT_WORK(&vnode->cb_broken_work, afs_broken_callback_work);
ec26815ad   David Howells   [AFS]: Clean up t...
452
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
453

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
454
455
456
457
458
459
  /*
   * allocate an AFS inode struct from our slab cache
   */
  static struct inode *afs_alloc_inode(struct super_block *sb)
  {
  	struct afs_vnode *vnode;
ec26815ad   David Howells   [AFS]: Clean up t...
460
  	vnode = kmem_cache_alloc(afs_inode_cachep, GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
461
462
463
464
465
466
467
468
469
470
  	if (!vnode)
  		return NULL;
  
  	atomic_inc(&afs_count_active_inodes);
  
  	memset(&vnode->fid, 0, sizeof(vnode->fid));
  	memset(&vnode->status, 0, sizeof(vnode->status));
  
  	vnode->volume		= NULL;
  	vnode->update_cnt	= 0;
260a98031   David Howells   [AFS]: Add "direc...
471
  	vnode->flags		= 1 << AFS_VNODE_UNSET;
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
472
  	vnode->cb_promised	= false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
473

0f300ca92   David Howells   AFS: fix a couple...
474
  	_leave(" = %p", &vnode->vfs_inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
475
  	return &vnode->vfs_inode;
ec26815ad   David Howells   [AFS]: Clean up t...
476
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
477

fa0d7e3de   Nick Piggin   fs: icache RCU fr...
478
479
480
481
  static void afs_i_callback(struct rcu_head *head)
  {
  	struct inode *inode = container_of(head, struct inode, i_rcu);
  	struct afs_vnode *vnode = AFS_FS_I(inode);
fa0d7e3de   Nick Piggin   fs: icache RCU fr...
482
483
  	kmem_cache_free(afs_inode_cachep, vnode);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
484
485
486
487
488
  /*
   * destroy an AFS inode struct
   */
  static void afs_destroy_inode(struct inode *inode)
  {
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
489
  	struct afs_vnode *vnode = AFS_FS_I(inode);
0f300ca92   David Howells   AFS: fix a couple...
490
  	_enter("%p{%x:%u}", inode, vnode->fid.vid, vnode->fid.vnode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
491

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
492
493
494
  	_debug("DESTROY INODE %p", inode);
  
  	ASSERTCMP(vnode->server, ==, NULL);
fa0d7e3de   Nick Piggin   fs: icache RCU fr...
495
  	call_rcu(&inode->i_rcu, afs_i_callback);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
496
  	atomic_dec(&afs_count_active_inodes);
ec26815ad   David Howells   [AFS]: Clean up t...
497
  }
45222b9e0   David Howells   AFS: implement st...
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
  
  /*
   * return information about an AFS volume
   */
  static int afs_statfs(struct dentry *dentry, struct kstatfs *buf)
  {
  	struct afs_volume_status vs;
  	struct afs_vnode *vnode = AFS_FS_I(dentry->d_inode);
  	struct key *key;
  	int ret;
  
  	key = afs_request_key(vnode->volume->cell);
  	if (IS_ERR(key))
  		return PTR_ERR(key);
  
  	ret = afs_vnode_get_volume_status(vnode, key, &vs);
  	key_put(key);
  	if (ret < 0) {
  		_leave(" = %d", ret);
  		return ret;
  	}
  
  	buf->f_type	= dentry->d_sb->s_magic;
  	buf->f_bsize	= AFS_BLOCK_SIZE;
  	buf->f_namelen	= AFSNAMEMAX - 1;
  
  	if (vs.max_quota == 0)
  		buf->f_blocks = vs.part_max_blocks;
  	else
  		buf->f_blocks = vs.max_quota;
  	buf->f_bavail = buf->f_bfree = buf->f_blocks - vs.blocks_in_use;
  	return 0;
  }