xref: /openbmc/linux/fs/afs/super.c (revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2)
1*1da177e4SLinus Torvalds /*
2*1da177e4SLinus Torvalds  * Copyright (c) 2002 Red Hat, Inc. All rights reserved.
3*1da177e4SLinus Torvalds  *
4*1da177e4SLinus Torvalds  * This software may be freely redistributed under the terms of the
5*1da177e4SLinus Torvalds  * GNU General Public License.
6*1da177e4SLinus Torvalds  *
7*1da177e4SLinus Torvalds  * You should have received a copy of the GNU General Public License
8*1da177e4SLinus Torvalds  * along with this program; if not, write to the Free Software
9*1da177e4SLinus Torvalds  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
10*1da177e4SLinus Torvalds  *
11*1da177e4SLinus Torvalds  * Authors: David Howells <dhowells@redhat.com>
12*1da177e4SLinus Torvalds  *          David Woodhouse <dwmw2@cambridge.redhat.com>
13*1da177e4SLinus Torvalds  *
14*1da177e4SLinus Torvalds  */
15*1da177e4SLinus Torvalds 
16*1da177e4SLinus Torvalds #include <linux/kernel.h>
17*1da177e4SLinus Torvalds #include <linux/module.h>
18*1da177e4SLinus Torvalds #include <linux/init.h>
19*1da177e4SLinus Torvalds #include <linux/slab.h>
20*1da177e4SLinus Torvalds #include <linux/fs.h>
21*1da177e4SLinus Torvalds #include <linux/pagemap.h>
22*1da177e4SLinus Torvalds #include "vnode.h"
23*1da177e4SLinus Torvalds #include "volume.h"
24*1da177e4SLinus Torvalds #include "cell.h"
25*1da177e4SLinus Torvalds #include "cmservice.h"
26*1da177e4SLinus Torvalds #include "fsclient.h"
27*1da177e4SLinus Torvalds #include "super.h"
28*1da177e4SLinus Torvalds #include "internal.h"
29*1da177e4SLinus Torvalds 
30*1da177e4SLinus Torvalds #define AFS_FS_MAGIC 0x6B414653 /* 'kAFS' */
31*1da177e4SLinus Torvalds 
32*1da177e4SLinus Torvalds struct afs_mount_params {
33*1da177e4SLinus Torvalds 	int			rwpath;
34*1da177e4SLinus Torvalds 	struct afs_cell		*default_cell;
35*1da177e4SLinus Torvalds 	struct afs_volume	*volume;
36*1da177e4SLinus Torvalds };
37*1da177e4SLinus Torvalds 
38*1da177e4SLinus Torvalds static void afs_i_init_once(void *foo, kmem_cache_t *cachep,
39*1da177e4SLinus Torvalds 			    unsigned long flags);
40*1da177e4SLinus Torvalds 
41*1da177e4SLinus Torvalds static struct super_block *afs_get_sb(struct file_system_type *fs_type,
42*1da177e4SLinus Torvalds 				      int flags, const char *dev_name,
43*1da177e4SLinus Torvalds 				      void *data);
44*1da177e4SLinus Torvalds 
45*1da177e4SLinus Torvalds static struct inode *afs_alloc_inode(struct super_block *sb);
46*1da177e4SLinus Torvalds 
47*1da177e4SLinus Torvalds static void afs_put_super(struct super_block *sb);
48*1da177e4SLinus Torvalds 
49*1da177e4SLinus Torvalds static void afs_destroy_inode(struct inode *inode);
50*1da177e4SLinus Torvalds 
51*1da177e4SLinus Torvalds static struct file_system_type afs_fs_type = {
52*1da177e4SLinus Torvalds 	.owner		= THIS_MODULE,
53*1da177e4SLinus Torvalds 	.name		= "afs",
54*1da177e4SLinus Torvalds 	.get_sb		= afs_get_sb,
55*1da177e4SLinus Torvalds 	.kill_sb	= kill_anon_super,
56*1da177e4SLinus Torvalds 	.fs_flags	= FS_BINARY_MOUNTDATA,
57*1da177e4SLinus Torvalds };
58*1da177e4SLinus Torvalds 
59*1da177e4SLinus Torvalds static struct super_operations afs_super_ops = {
60*1da177e4SLinus Torvalds 	.statfs		= simple_statfs,
61*1da177e4SLinus Torvalds 	.alloc_inode	= afs_alloc_inode,
62*1da177e4SLinus Torvalds 	.drop_inode	= generic_delete_inode,
63*1da177e4SLinus Torvalds 	.destroy_inode	= afs_destroy_inode,
64*1da177e4SLinus Torvalds 	.clear_inode	= afs_clear_inode,
65*1da177e4SLinus Torvalds 	.put_super	= afs_put_super,
66*1da177e4SLinus Torvalds };
67*1da177e4SLinus Torvalds 
68*1da177e4SLinus Torvalds static kmem_cache_t *afs_inode_cachep;
69*1da177e4SLinus Torvalds static atomic_t afs_count_active_inodes;
70*1da177e4SLinus Torvalds 
71*1da177e4SLinus Torvalds /*****************************************************************************/
72*1da177e4SLinus Torvalds /*
73*1da177e4SLinus Torvalds  * initialise the filesystem
74*1da177e4SLinus Torvalds  */
75*1da177e4SLinus Torvalds int __init afs_fs_init(void)
76*1da177e4SLinus Torvalds {
77*1da177e4SLinus Torvalds 	int ret;
78*1da177e4SLinus Torvalds 
79*1da177e4SLinus Torvalds 	_enter("");
80*1da177e4SLinus Torvalds 
81*1da177e4SLinus Torvalds 	afs_timer_init(&afs_mntpt_expiry_timer, &afs_mntpt_expiry_timer_ops);
82*1da177e4SLinus Torvalds 
83*1da177e4SLinus Torvalds 	/* create ourselves an inode cache */
84*1da177e4SLinus Torvalds 	atomic_set(&afs_count_active_inodes, 0);
85*1da177e4SLinus Torvalds 
86*1da177e4SLinus Torvalds 	ret = -ENOMEM;
87*1da177e4SLinus Torvalds 	afs_inode_cachep = kmem_cache_create("afs_inode_cache",
88*1da177e4SLinus Torvalds 					     sizeof(struct afs_vnode),
89*1da177e4SLinus Torvalds 					     0,
90*1da177e4SLinus Torvalds 					     SLAB_HWCACHE_ALIGN,
91*1da177e4SLinus Torvalds 					     afs_i_init_once,
92*1da177e4SLinus Torvalds 					     NULL);
93*1da177e4SLinus Torvalds 	if (!afs_inode_cachep) {
94*1da177e4SLinus Torvalds 		printk(KERN_NOTICE "kAFS: Failed to allocate inode cache\n");
95*1da177e4SLinus Torvalds 		return ret;
96*1da177e4SLinus Torvalds 	}
97*1da177e4SLinus Torvalds 
98*1da177e4SLinus Torvalds 	/* now export our filesystem to lesser mortals */
99*1da177e4SLinus Torvalds 	ret = register_filesystem(&afs_fs_type);
100*1da177e4SLinus Torvalds 	if (ret < 0) {
101*1da177e4SLinus Torvalds 		kmem_cache_destroy(afs_inode_cachep);
102*1da177e4SLinus Torvalds 		kleave(" = %d", ret);
103*1da177e4SLinus Torvalds 		return ret;
104*1da177e4SLinus Torvalds 	}
105*1da177e4SLinus Torvalds 
106*1da177e4SLinus Torvalds 	kleave(" = 0");
107*1da177e4SLinus Torvalds 	return 0;
108*1da177e4SLinus Torvalds } /* end afs_fs_init() */
109*1da177e4SLinus Torvalds 
110*1da177e4SLinus Torvalds /*****************************************************************************/
111*1da177e4SLinus Torvalds /*
112*1da177e4SLinus Torvalds  * clean up the filesystem
113*1da177e4SLinus Torvalds  */
114*1da177e4SLinus Torvalds void __exit afs_fs_exit(void)
115*1da177e4SLinus Torvalds {
116*1da177e4SLinus Torvalds 	unregister_filesystem(&afs_fs_type);
117*1da177e4SLinus Torvalds 
118*1da177e4SLinus Torvalds 	if (atomic_read(&afs_count_active_inodes) != 0) {
119*1da177e4SLinus Torvalds 		printk("kAFS: %d active inode objects still present\n",
120*1da177e4SLinus Torvalds 		       atomic_read(&afs_count_active_inodes));
121*1da177e4SLinus Torvalds 		BUG();
122*1da177e4SLinus Torvalds 	}
123*1da177e4SLinus Torvalds 
124*1da177e4SLinus Torvalds 	kmem_cache_destroy(afs_inode_cachep);
125*1da177e4SLinus Torvalds 
126*1da177e4SLinus Torvalds } /* end afs_fs_exit() */
127*1da177e4SLinus Torvalds 
128*1da177e4SLinus Torvalds /*****************************************************************************/
129*1da177e4SLinus Torvalds /*
130*1da177e4SLinus Torvalds  * check that an argument has a value
131*1da177e4SLinus Torvalds  */
132*1da177e4SLinus Torvalds static int want_arg(char **_value, const char *option)
133*1da177e4SLinus Torvalds {
134*1da177e4SLinus Torvalds 	if (!_value || !*_value || !**_value) {
135*1da177e4SLinus Torvalds 		printk(KERN_NOTICE "kAFS: %s: argument missing\n", option);
136*1da177e4SLinus Torvalds 		return 0;
137*1da177e4SLinus Torvalds 	}
138*1da177e4SLinus Torvalds 	return 1;
139*1da177e4SLinus Torvalds } /* end want_arg() */
140*1da177e4SLinus Torvalds 
141*1da177e4SLinus Torvalds /*****************************************************************************/
142*1da177e4SLinus Torvalds /*
143*1da177e4SLinus Torvalds  * check that there's no subsequent value
144*1da177e4SLinus Torvalds  */
145*1da177e4SLinus Torvalds static int want_no_value(char *const *_value, const char *option)
146*1da177e4SLinus Torvalds {
147*1da177e4SLinus Torvalds 	if (*_value && **_value) {
148*1da177e4SLinus Torvalds 		printk(KERN_NOTICE "kAFS: %s: Invalid argument: %s\n",
149*1da177e4SLinus Torvalds 		       option, *_value);
150*1da177e4SLinus Torvalds 		return 0;
151*1da177e4SLinus Torvalds 	}
152*1da177e4SLinus Torvalds 	return 1;
153*1da177e4SLinus Torvalds } /* end want_no_value() */
154*1da177e4SLinus Torvalds 
155*1da177e4SLinus Torvalds /*****************************************************************************/
156*1da177e4SLinus Torvalds /*
157*1da177e4SLinus Torvalds  * parse the mount options
158*1da177e4SLinus Torvalds  * - this function has been shamelessly adapted from the ext3 fs which
159*1da177e4SLinus Torvalds  *   shamelessly adapted it from the msdos fs
160*1da177e4SLinus Torvalds  */
161*1da177e4SLinus Torvalds static int afs_super_parse_options(struct afs_mount_params *params,
162*1da177e4SLinus Torvalds 				   char *options,
163*1da177e4SLinus Torvalds 				   const char **devname)
164*1da177e4SLinus Torvalds {
165*1da177e4SLinus Torvalds 	char *key, *value;
166*1da177e4SLinus Torvalds 	int ret;
167*1da177e4SLinus Torvalds 
168*1da177e4SLinus Torvalds 	_enter("%s", options);
169*1da177e4SLinus Torvalds 
170*1da177e4SLinus Torvalds 	options[PAGE_SIZE - 1] = 0;
171*1da177e4SLinus Torvalds 
172*1da177e4SLinus Torvalds 	ret = 0;
173*1da177e4SLinus Torvalds 	while ((key = strsep(&options, ",")) != 0)
174*1da177e4SLinus Torvalds 	{
175*1da177e4SLinus Torvalds 		value = strchr(key, '=');
176*1da177e4SLinus Torvalds 		if (value)
177*1da177e4SLinus Torvalds 			*value++ = 0;
178*1da177e4SLinus Torvalds 
179*1da177e4SLinus Torvalds 		printk("kAFS: KEY: %s, VAL:%s\n", key, value ?: "-");
180*1da177e4SLinus Torvalds 
181*1da177e4SLinus Torvalds 		if (strcmp(key, "rwpath") == 0) {
182*1da177e4SLinus Torvalds 			if (!want_no_value(&value, "rwpath"))
183*1da177e4SLinus Torvalds 				return -EINVAL;
184*1da177e4SLinus Torvalds 			params->rwpath = 1;
185*1da177e4SLinus Torvalds 			continue;
186*1da177e4SLinus Torvalds 		}
187*1da177e4SLinus Torvalds 		else if (strcmp(key, "vol") == 0) {
188*1da177e4SLinus Torvalds 			if (!want_arg(&value, "vol"))
189*1da177e4SLinus Torvalds 				return -EINVAL;
190*1da177e4SLinus Torvalds 			*devname = value;
191*1da177e4SLinus Torvalds 			continue;
192*1da177e4SLinus Torvalds 		}
193*1da177e4SLinus Torvalds 		else if (strcmp(key, "cell") == 0) {
194*1da177e4SLinus Torvalds 			if (!want_arg(&value, "cell"))
195*1da177e4SLinus Torvalds 				return -EINVAL;
196*1da177e4SLinus Torvalds 			afs_put_cell(params->default_cell);
197*1da177e4SLinus Torvalds 			ret = afs_cell_lookup(value,
198*1da177e4SLinus Torvalds 					      strlen(value),
199*1da177e4SLinus Torvalds 					      &params->default_cell);
200*1da177e4SLinus Torvalds 			if (ret < 0)
201*1da177e4SLinus Torvalds 				return -EINVAL;
202*1da177e4SLinus Torvalds 			continue;
203*1da177e4SLinus Torvalds 		}
204*1da177e4SLinus Torvalds 
205*1da177e4SLinus Torvalds 		printk("kAFS: Unknown mount option: '%s'\n",  key);
206*1da177e4SLinus Torvalds 		ret = -EINVAL;
207*1da177e4SLinus Torvalds 		goto error;
208*1da177e4SLinus Torvalds 	}
209*1da177e4SLinus Torvalds 
210*1da177e4SLinus Torvalds 	ret = 0;
211*1da177e4SLinus Torvalds 
212*1da177e4SLinus Torvalds  error:
213*1da177e4SLinus Torvalds 	_leave(" = %d", ret);
214*1da177e4SLinus Torvalds 	return ret;
215*1da177e4SLinus Torvalds } /* end afs_super_parse_options() */
216*1da177e4SLinus Torvalds 
217*1da177e4SLinus Torvalds /*****************************************************************************/
218*1da177e4SLinus Torvalds /*
219*1da177e4SLinus Torvalds  * check a superblock to see if it's the one we're looking for
220*1da177e4SLinus Torvalds  */
221*1da177e4SLinus Torvalds static int afs_test_super(struct super_block *sb, void *data)
222*1da177e4SLinus Torvalds {
223*1da177e4SLinus Torvalds 	struct afs_mount_params *params = data;
224*1da177e4SLinus Torvalds 	struct afs_super_info *as = sb->s_fs_info;
225*1da177e4SLinus Torvalds 
226*1da177e4SLinus Torvalds 	return as->volume == params->volume;
227*1da177e4SLinus Torvalds } /* end afs_test_super() */
228*1da177e4SLinus Torvalds 
229*1da177e4SLinus Torvalds /*****************************************************************************/
230*1da177e4SLinus Torvalds /*
231*1da177e4SLinus Torvalds  * fill in the superblock
232*1da177e4SLinus Torvalds  */
233*1da177e4SLinus Torvalds static int afs_fill_super(struct super_block *sb, void *data, int silent)
234*1da177e4SLinus Torvalds {
235*1da177e4SLinus Torvalds 	struct afs_mount_params *params = data;
236*1da177e4SLinus Torvalds 	struct afs_super_info *as = NULL;
237*1da177e4SLinus Torvalds 	struct afs_fid fid;
238*1da177e4SLinus Torvalds 	struct dentry *root = NULL;
239*1da177e4SLinus Torvalds 	struct inode *inode = NULL;
240*1da177e4SLinus Torvalds 	int ret;
241*1da177e4SLinus Torvalds 
242*1da177e4SLinus Torvalds 	kenter("");
243*1da177e4SLinus Torvalds 
244*1da177e4SLinus Torvalds 	/* allocate a superblock info record */
245*1da177e4SLinus Torvalds 	as = kmalloc(sizeof(struct afs_super_info), GFP_KERNEL);
246*1da177e4SLinus Torvalds 	if (!as) {
247*1da177e4SLinus Torvalds 		_leave(" = -ENOMEM");
248*1da177e4SLinus Torvalds 		return -ENOMEM;
249*1da177e4SLinus Torvalds 	}
250*1da177e4SLinus Torvalds 
251*1da177e4SLinus Torvalds 	memset(as, 0, sizeof(struct afs_super_info));
252*1da177e4SLinus Torvalds 
253*1da177e4SLinus Torvalds 	afs_get_volume(params->volume);
254*1da177e4SLinus Torvalds 	as->volume = params->volume;
255*1da177e4SLinus Torvalds 
256*1da177e4SLinus Torvalds 	/* fill in the superblock */
257*1da177e4SLinus Torvalds 	sb->s_blocksize		= PAGE_CACHE_SIZE;
258*1da177e4SLinus Torvalds 	sb->s_blocksize_bits	= PAGE_CACHE_SHIFT;
259*1da177e4SLinus Torvalds 	sb->s_magic		= AFS_FS_MAGIC;
260*1da177e4SLinus Torvalds 	sb->s_op		= &afs_super_ops;
261*1da177e4SLinus Torvalds 	sb->s_fs_info		= as;
262*1da177e4SLinus Torvalds 
263*1da177e4SLinus Torvalds 	/* allocate the root inode and dentry */
264*1da177e4SLinus Torvalds 	fid.vid		= as->volume->vid;
265*1da177e4SLinus Torvalds 	fid.vnode	= 1;
266*1da177e4SLinus Torvalds 	fid.unique	= 1;
267*1da177e4SLinus Torvalds 	ret = afs_iget(sb, &fid, &inode);
268*1da177e4SLinus Torvalds 	if (ret < 0)
269*1da177e4SLinus Torvalds 		goto error;
270*1da177e4SLinus Torvalds 
271*1da177e4SLinus Torvalds 	ret = -ENOMEM;
272*1da177e4SLinus Torvalds 	root = d_alloc_root(inode);
273*1da177e4SLinus Torvalds 	if (!root)
274*1da177e4SLinus Torvalds 		goto error;
275*1da177e4SLinus Torvalds 
276*1da177e4SLinus Torvalds 	sb->s_root = root;
277*1da177e4SLinus Torvalds 
278*1da177e4SLinus Torvalds 	kleave(" = 0");
279*1da177e4SLinus Torvalds 	return 0;
280*1da177e4SLinus Torvalds 
281*1da177e4SLinus Torvalds  error:
282*1da177e4SLinus Torvalds 	iput(inode);
283*1da177e4SLinus Torvalds 	afs_put_volume(as->volume);
284*1da177e4SLinus Torvalds 	kfree(as);
285*1da177e4SLinus Torvalds 
286*1da177e4SLinus Torvalds 	sb->s_fs_info = NULL;
287*1da177e4SLinus Torvalds 
288*1da177e4SLinus Torvalds 	kleave(" = %d", ret);
289*1da177e4SLinus Torvalds 	return ret;
290*1da177e4SLinus Torvalds } /* end afs_fill_super() */
291*1da177e4SLinus Torvalds 
292*1da177e4SLinus Torvalds /*****************************************************************************/
293*1da177e4SLinus Torvalds /*
294*1da177e4SLinus Torvalds  * get an AFS superblock
295*1da177e4SLinus Torvalds  * - TODO: don't use get_sb_nodev(), but rather call sget() directly
296*1da177e4SLinus Torvalds  */
297*1da177e4SLinus Torvalds static struct super_block *afs_get_sb(struct file_system_type *fs_type,
298*1da177e4SLinus Torvalds 				      int flags,
299*1da177e4SLinus Torvalds 				      const char *dev_name,
300*1da177e4SLinus Torvalds 				      void *options)
301*1da177e4SLinus Torvalds {
302*1da177e4SLinus Torvalds 	struct afs_mount_params params;
303*1da177e4SLinus Torvalds 	struct super_block *sb;
304*1da177e4SLinus Torvalds 	int ret;
305*1da177e4SLinus Torvalds 
306*1da177e4SLinus Torvalds 	_enter(",,%s,%p", dev_name, options);
307*1da177e4SLinus Torvalds 
308*1da177e4SLinus Torvalds 	memset(&params, 0, sizeof(params));
309*1da177e4SLinus Torvalds 
310*1da177e4SLinus Torvalds 	/* start the cache manager */
311*1da177e4SLinus Torvalds 	ret = afscm_start();
312*1da177e4SLinus Torvalds 	if (ret < 0) {
313*1da177e4SLinus Torvalds 		_leave(" = %d", ret);
314*1da177e4SLinus Torvalds 		return ERR_PTR(ret);
315*1da177e4SLinus Torvalds 	}
316*1da177e4SLinus Torvalds 
317*1da177e4SLinus Torvalds 	/* parse the options */
318*1da177e4SLinus Torvalds 	if (options) {
319*1da177e4SLinus Torvalds 		ret = afs_super_parse_options(&params, options, &dev_name);
320*1da177e4SLinus Torvalds 		if (ret < 0)
321*1da177e4SLinus Torvalds 			goto error;
322*1da177e4SLinus Torvalds 		if (!dev_name) {
323*1da177e4SLinus Torvalds 			printk("kAFS: no volume name specified\n");
324*1da177e4SLinus Torvalds 			ret = -EINVAL;
325*1da177e4SLinus Torvalds 			goto error;
326*1da177e4SLinus Torvalds 		}
327*1da177e4SLinus Torvalds 	}
328*1da177e4SLinus Torvalds 
329*1da177e4SLinus Torvalds 	/* parse the device name */
330*1da177e4SLinus Torvalds 	ret = afs_volume_lookup(dev_name,
331*1da177e4SLinus Torvalds 				params.default_cell,
332*1da177e4SLinus Torvalds 				params.rwpath,
333*1da177e4SLinus Torvalds 				&params.volume);
334*1da177e4SLinus Torvalds 	if (ret < 0)
335*1da177e4SLinus Torvalds 		goto error;
336*1da177e4SLinus Torvalds 
337*1da177e4SLinus Torvalds 	/* allocate a deviceless superblock */
338*1da177e4SLinus Torvalds 	sb = sget(fs_type, afs_test_super, set_anon_super, &params);
339*1da177e4SLinus Torvalds 	if (IS_ERR(sb))
340*1da177e4SLinus Torvalds 		goto error;
341*1da177e4SLinus Torvalds 
342*1da177e4SLinus Torvalds 	sb->s_flags = flags;
343*1da177e4SLinus Torvalds 
344*1da177e4SLinus Torvalds 	ret = afs_fill_super(sb, &params, flags & MS_VERBOSE ? 1 : 0);
345*1da177e4SLinus Torvalds 	if (ret < 0) {
346*1da177e4SLinus Torvalds 		up_write(&sb->s_umount);
347*1da177e4SLinus Torvalds 		deactivate_super(sb);
348*1da177e4SLinus Torvalds 		goto error;
349*1da177e4SLinus Torvalds 	}
350*1da177e4SLinus Torvalds 	sb->s_flags |= MS_ACTIVE;
351*1da177e4SLinus Torvalds 
352*1da177e4SLinus Torvalds 	afs_put_volume(params.volume);
353*1da177e4SLinus Torvalds 	afs_put_cell(params.default_cell);
354*1da177e4SLinus Torvalds 	_leave(" = %p", sb);
355*1da177e4SLinus Torvalds 	return sb;
356*1da177e4SLinus Torvalds 
357*1da177e4SLinus Torvalds  error:
358*1da177e4SLinus Torvalds 	afs_put_volume(params.volume);
359*1da177e4SLinus Torvalds 	afs_put_cell(params.default_cell);
360*1da177e4SLinus Torvalds 	afscm_stop();
361*1da177e4SLinus Torvalds 	_leave(" = %d", ret);
362*1da177e4SLinus Torvalds 	return ERR_PTR(ret);
363*1da177e4SLinus Torvalds } /* end afs_get_sb() */
364*1da177e4SLinus Torvalds 
365*1da177e4SLinus Torvalds /*****************************************************************************/
366*1da177e4SLinus Torvalds /*
367*1da177e4SLinus Torvalds  * finish the unmounting process on the superblock
368*1da177e4SLinus Torvalds  */
369*1da177e4SLinus Torvalds static void afs_put_super(struct super_block *sb)
370*1da177e4SLinus Torvalds {
371*1da177e4SLinus Torvalds 	struct afs_super_info *as = sb->s_fs_info;
372*1da177e4SLinus Torvalds 
373*1da177e4SLinus Torvalds 	_enter("");
374*1da177e4SLinus Torvalds 
375*1da177e4SLinus Torvalds 	afs_put_volume(as->volume);
376*1da177e4SLinus Torvalds 	afscm_stop();
377*1da177e4SLinus Torvalds 
378*1da177e4SLinus Torvalds 	_leave("");
379*1da177e4SLinus Torvalds } /* end afs_put_super() */
380*1da177e4SLinus Torvalds 
381*1da177e4SLinus Torvalds /*****************************************************************************/
382*1da177e4SLinus Torvalds /*
383*1da177e4SLinus Torvalds  * initialise an inode cache slab element prior to any use
384*1da177e4SLinus Torvalds  */
385*1da177e4SLinus Torvalds static void afs_i_init_once(void *_vnode, kmem_cache_t *cachep,
386*1da177e4SLinus Torvalds 			    unsigned long flags)
387*1da177e4SLinus Torvalds {
388*1da177e4SLinus Torvalds 	struct afs_vnode *vnode = (struct afs_vnode *) _vnode;
389*1da177e4SLinus Torvalds 
390*1da177e4SLinus Torvalds 	if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
391*1da177e4SLinus Torvalds 	    SLAB_CTOR_CONSTRUCTOR) {
392*1da177e4SLinus Torvalds 		memset(vnode, 0, sizeof(*vnode));
393*1da177e4SLinus Torvalds 		inode_init_once(&vnode->vfs_inode);
394*1da177e4SLinus Torvalds 		init_waitqueue_head(&vnode->update_waitq);
395*1da177e4SLinus Torvalds 		spin_lock_init(&vnode->lock);
396*1da177e4SLinus Torvalds 		INIT_LIST_HEAD(&vnode->cb_link);
397*1da177e4SLinus Torvalds 		INIT_LIST_HEAD(&vnode->cb_hash_link);
398*1da177e4SLinus Torvalds 		afs_timer_init(&vnode->cb_timeout,
399*1da177e4SLinus Torvalds 			       &afs_vnode_cb_timed_out_ops);
400*1da177e4SLinus Torvalds 	}
401*1da177e4SLinus Torvalds 
402*1da177e4SLinus Torvalds } /* end afs_i_init_once() */
403*1da177e4SLinus Torvalds 
404*1da177e4SLinus Torvalds /*****************************************************************************/
405*1da177e4SLinus Torvalds /*
406*1da177e4SLinus Torvalds  * allocate an AFS inode struct from our slab cache
407*1da177e4SLinus Torvalds  */
408*1da177e4SLinus Torvalds static struct inode *afs_alloc_inode(struct super_block *sb)
409*1da177e4SLinus Torvalds {
410*1da177e4SLinus Torvalds 	struct afs_vnode *vnode;
411*1da177e4SLinus Torvalds 
412*1da177e4SLinus Torvalds 	vnode = (struct afs_vnode *)
413*1da177e4SLinus Torvalds 		kmem_cache_alloc(afs_inode_cachep, SLAB_KERNEL);
414*1da177e4SLinus Torvalds 	if (!vnode)
415*1da177e4SLinus Torvalds 		return NULL;
416*1da177e4SLinus Torvalds 
417*1da177e4SLinus Torvalds 	atomic_inc(&afs_count_active_inodes);
418*1da177e4SLinus Torvalds 
419*1da177e4SLinus Torvalds 	memset(&vnode->fid, 0, sizeof(vnode->fid));
420*1da177e4SLinus Torvalds 	memset(&vnode->status, 0, sizeof(vnode->status));
421*1da177e4SLinus Torvalds 
422*1da177e4SLinus Torvalds 	vnode->volume		= NULL;
423*1da177e4SLinus Torvalds 	vnode->update_cnt	= 0;
424*1da177e4SLinus Torvalds 	vnode->flags		= 0;
425*1da177e4SLinus Torvalds 
426*1da177e4SLinus Torvalds 	return &vnode->vfs_inode;
427*1da177e4SLinus Torvalds } /* end afs_alloc_inode() */
428*1da177e4SLinus Torvalds 
429*1da177e4SLinus Torvalds /*****************************************************************************/
430*1da177e4SLinus Torvalds /*
431*1da177e4SLinus Torvalds  * destroy an AFS inode struct
432*1da177e4SLinus Torvalds  */
433*1da177e4SLinus Torvalds static void afs_destroy_inode(struct inode *inode)
434*1da177e4SLinus Torvalds {
435*1da177e4SLinus Torvalds 	_enter("{%lu}", inode->i_ino);
436*1da177e4SLinus Torvalds 
437*1da177e4SLinus Torvalds 	kmem_cache_free(afs_inode_cachep, AFS_FS_I(inode));
438*1da177e4SLinus Torvalds 
439*1da177e4SLinus Torvalds 	atomic_dec(&afs_count_active_inodes);
440*1da177e4SLinus Torvalds 
441*1da177e4SLinus Torvalds } /* end afs_destroy_inode() */
442