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