This commit was manufactured by cvs2svn to create tag
[linux-2.6.git] / fs / rcfs / super.c
1 /* 
2  * fs/rcfs/super.c 
3  *
4  * Copyright (C) Shailabh Nagar,  IBM Corp. 2004
5  *               Vivek Kashyap,   IBM Corp. 2004
6  *           
7  * Super block operations for rcfs
8  * 
9  *
10  * Latest version, more details at http://ckrm.sf.net
11  * 
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  */
18
19 /* Changes
20  *
21  * 08 Mar 2004
22  *        Created.
23  */
24
25 #include <linux/module.h>
26 #include <linux/fs.h>
27 #include <linux/namei.h>
28 #include <linux/namespace.h>
29 #include <linux/dcache.h>
30 #include <linux/seq_file.h>
31 #include <linux/pagemap.h>
32 #include <linux/highmem.h>
33 #include <linux/init.h>
34 #include <linux/string.h>
35 #include <linux/smp_lock.h>
36 #include <linux/backing-dev.h>
37 #include <linux/parser.h>
38
39 #include <asm/uaccess.h>
40
41 #include <linux/rcfs.h>
42 #include <linux/ckrm.h>
43 #include <linux/ckrm_rc.h>
44 #include <linux/ckrm_ce.h>
45
46 static kmem_cache_t *rcfs_inode_cachep;
47
48 inline struct rcfs_inode_info *RCFS_I(struct inode *inode)
49 {
50         return container_of(inode, struct rcfs_inode_info, vfs_inode);
51 }
52
53 EXPORT_SYMBOL(RCFS_I);
54
55 static struct inode *rcfs_alloc_inode(struct super_block *sb)
56 {
57         struct rcfs_inode_info *ri;
58         ri = (struct rcfs_inode_info *)kmem_cache_alloc(rcfs_inode_cachep,
59                                                         SLAB_KERNEL);
60         if (!ri)
61                 return NULL;
62         ri->name = NULL;
63         return &ri->vfs_inode;
64 }
65
66 static void rcfs_destroy_inode(struct inode *inode)
67 {
68         struct rcfs_inode_info *ri = RCFS_I(inode);
69
70         kfree(ri->name);
71         kmem_cache_free(rcfs_inode_cachep, ri);
72 }
73
74 static void
75 rcfs_init_once(void *foo, kmem_cache_t * cachep, unsigned long flags)
76 {
77         struct rcfs_inode_info *ri = (struct rcfs_inode_info *)foo;
78
79         if ((flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) ==
80             SLAB_CTOR_CONSTRUCTOR)
81                 inode_init_once(&ri->vfs_inode);
82 }
83
84 int rcfs_init_inodecache(void)
85 {
86         rcfs_inode_cachep = kmem_cache_create("rcfs_inode_cache",
87                                               sizeof(struct rcfs_inode_info),
88                                               0,
89                                               SLAB_HWCACHE_ALIGN |
90                                               SLAB_RECLAIM_ACCOUNT,
91                                               rcfs_init_once, NULL);
92         if (rcfs_inode_cachep == NULL)
93                 return -ENOMEM;
94         return 0;
95 }
96
97 void rcfs_destroy_inodecache(void)
98 {
99         printk(KERN_WARNING "destroy inodecache was called\n");
100         if (kmem_cache_destroy(rcfs_inode_cachep))
101                 printk(KERN_INFO
102                        "rcfs_inode_cache: not all structures were freed\n");
103 }
104
105 struct super_operations rcfs_super_ops = {
106         .alloc_inode = rcfs_alloc_inode,
107         .destroy_inode = rcfs_destroy_inode,
108         .statfs = simple_statfs,
109         .drop_inode = generic_delete_inode,
110 };
111
112 struct dentry *rcfs_rootde;     /* redundant; can also get it from sb */
113 static struct inode *rcfs_root;
114 static struct rcfs_inode_info *rcfs_rootri;
115
116 static int rcfs_fill_super(struct super_block *sb, void *data, int silent)
117 {
118         struct inode *inode;
119         struct dentry *root;
120         struct rcfs_inode_info *rootri;
121         struct ckrm_classtype *clstype;
122         int i, rc;
123
124         sb->s_fs_info = NULL;
125         if (rcfs_mounted) {
126                 return -EPERM;
127         }
128         rcfs_mounted++;
129
130         sb->s_blocksize = PAGE_CACHE_SIZE;
131         sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
132         sb->s_magic = RCFS_MAGIC;
133         sb->s_op = &rcfs_super_ops;
134         inode = rcfs_get_inode(sb, S_IFDIR | 0755, 0);
135         if (!inode)
136                 return -ENOMEM;
137         inode->i_op = &rcfs_rootdir_inode_operations;
138
139         root = d_alloc_root(inode);
140         if (!root) {
141                 iput(inode);
142                 return -ENOMEM;
143         }
144         sb->s_root = root;
145
146         // Link inode and core class 
147         rootri = RCFS_I(inode);
148         rootri->name = kmalloc(strlen(RCFS_ROOT) + 1, GFP_KERNEL);
149         if (!rootri->name) {
150                 d_delete(root);
151                 iput(inode);
152                 return -ENOMEM;
153         }
154         strcpy(rootri->name, RCFS_ROOT);
155         rootri->core = NULL;
156
157         rcfs_root = inode;
158         sb->s_fs_info = rcfs_root = inode;
159         rcfs_rootde = root;
160         rcfs_rootri = rootri;
161
162         // register metatypes
163         for (i = 0; i < CKRM_MAX_CLASSTYPES; i++) {
164                 clstype = ckrm_classtypes[i];
165                 if (clstype == NULL)
166                         continue;
167                 printk(KERN_DEBUG "A non null classtype\n");
168
169                 if ((rc = rcfs_register_classtype(clstype)))
170                         continue;       // could return with an error too 
171         }
172
173         // do post-mount initializations needed by CE
174         // this is distinct from CE registration done on rcfs module load
175         if (rcfs_engine_regd) {
176                 if (rcfs_eng_callbacks.mnt)
177                         if ((rc = (*rcfs_eng_callbacks.mnt) ())) {
178                                 printk(KERN_ERR "Error in CE mnt %d\n", rc);
179                         }
180         }
181         // Following comment handled by code above; keep nonetheless if it
182         // can be done better
183         //
184         // register CE's with rcfs 
185         // check if CE loaded
186         // call rcfs_register_engine for each classtype
187         // AND rcfs_mkroot (preferably subsume latter in former) 
188
189         return 0;
190 }
191
192 static struct super_block *rcfs_get_sb(struct file_system_type *fs_type,
193                                        int flags, const char *dev_name,
194                                        void *data)
195 {
196         return get_sb_nodev(fs_type, flags, data, rcfs_fill_super);
197 }
198
199 void rcfs_kill_sb(struct super_block *sb)
200 {
201         int i, rc;
202         struct ckrm_classtype *clstype;
203
204         if (sb->s_fs_info != rcfs_root) {
205                 generic_shutdown_super(sb);
206                 return;
207         }
208         rcfs_mounted--;
209
210         for (i = 0; i < CKRM_MAX_CLASSTYPES; i++) {
211
212                 clstype = ckrm_classtypes[i];
213                 if (clstype == NULL || clstype->rootde == NULL)
214                         continue;
215
216                 if ((rc = rcfs_deregister_classtype(clstype))) {
217                         printk(KERN_ERR "Error removing classtype %s\n",
218                                clstype->name);
219                         // return ;   // can also choose to stop here
220                 }
221         }
222
223         // do pre-umount shutdown needed by CE
224         // this is distinct from CE deregistration done on rcfs module unload
225         if (rcfs_engine_regd) {
226                 if (rcfs_eng_callbacks.umnt)
227                         if ((rc = (*rcfs_eng_callbacks.umnt) ())) {
228                                 printk(KERN_ERR "Error in CE umnt %d\n", rc);
229                                 // return ; until error handling improves
230                         }
231         }
232         // Following comment handled by code above; keep nonetheless if it 
233         // can be done better
234         //
235         // deregister CE with rcfs
236         // Check if loaded
237         // if ce is in  one directory /rcfs/ce, 
238         //       rcfs_deregister_engine for all classtypes within above 
239         //             codebase 
240         //       followed by
241         //       rcfs_rmroot here
242         // if ce in multiple (per-classtype) directories
243         //       call rbce_deregister_engine within ckrm_deregister_classtype
244
245         // following will automatically clear rcfs root entry including its 
246         //  rcfs_inode_info
247
248         generic_shutdown_super(sb);
249
250         // printk(KERN_ERR "Removed all entries\n");
251 }
252
253 static struct file_system_type rcfs_fs_type = {
254         .name = "rcfs",
255         .get_sb = rcfs_get_sb,
256         .kill_sb = rcfs_kill_sb,
257 };
258
259 struct rcfs_functions my_rcfs_fn = {
260         .mkroot = rcfs_mkroot,
261         .rmroot = rcfs_rmroot,
262         .register_classtype = rcfs_register_classtype,
263         .deregister_classtype = rcfs_deregister_classtype,
264 };
265
266 extern struct rcfs_functions rcfs_fn;
267
268 static int __init init_rcfs_fs(void)
269 {
270         int ret;
271
272         ret = register_filesystem(&rcfs_fs_type);
273         if (ret)
274                 goto init_register_err;
275
276         ret = rcfs_init_inodecache();
277         if (ret)
278                 goto init_cache_err;
279
280         rcfs_fn = my_rcfs_fn;
281
282         // Due to tight coupling of this module with ckrm
283         // do not allow this module to be removed.
284         try_module_get(THIS_MODULE);
285         return ret;
286
287       init_cache_err:
288         unregister_filesystem(&rcfs_fs_type);
289       init_register_err:
290         return ret;
291 }
292
293 static void __exit exit_rcfs_fs(void)
294 {
295         rcfs_destroy_inodecache();
296         unregister_filesystem(&rcfs_fs_type);
297 }
298
299 module_init(init_rcfs_fs)
300     module_exit(exit_rcfs_fs)
301
302     MODULE_LICENSE("GPL");