Merge branch 'stable-3.2' into pandora-3.2
[pandora-kernel.git] / fs / aufs / module.c
1 /*
2  * Copyright (C) 2005-2012 Junjiro R. Okajima
3  *
4  * This program, aufs is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17  */
18
19 /*
20  * module global variables and operations
21  */
22
23 #include <linux/module.h>
24 #include <linux/seq_file.h>
25 #include "aufs.h"
26
27 void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp)
28 {
29         if (new_sz <= nused)
30                 return p;
31
32         p = krealloc(p, new_sz, gfp);
33         if (p)
34                 memset(p + nused, 0, new_sz - nused);
35         return p;
36 }
37
38 /* ---------------------------------------------------------------------- */
39
40 /*
41  * aufs caches
42  */
43 struct kmem_cache *au_cachep[AuCache_Last];
44 static int __init au_cache_init(void)
45 {
46         au_cachep[AuCache_DINFO] = AuCacheCtor(au_dinfo, au_di_init_once);
47         if (au_cachep[AuCache_DINFO])
48                 /* SLAB_DESTROY_BY_RCU */
49                 au_cachep[AuCache_ICNTNR] = AuCacheCtor(au_icntnr,
50                                                         au_icntnr_init_once);
51         if (au_cachep[AuCache_ICNTNR])
52                 au_cachep[AuCache_FINFO] = AuCacheCtor(au_finfo,
53                                                        au_fi_init_once);
54         if (au_cachep[AuCache_FINFO])
55                 au_cachep[AuCache_VDIR] = AuCache(au_vdir);
56         if (au_cachep[AuCache_VDIR])
57                 au_cachep[AuCache_DEHSTR] = AuCache(au_vdir_dehstr);
58         if (au_cachep[AuCache_DEHSTR])
59                 return 0;
60
61         return -ENOMEM;
62 }
63
64 static void au_cache_fin(void)
65 {
66         int i;
67
68         /* including AuCache_HNOTIFY */
69         for (i = 0; i < AuCache_Last; i++)
70                 if (au_cachep[i]) {
71                         kmem_cache_destroy(au_cachep[i]);
72                         au_cachep[i] = NULL;
73                 }
74 }
75
76 /* ---------------------------------------------------------------------- */
77
78 int au_dir_roflags;
79
80 #ifdef CONFIG_AUFS_SBILIST
81 /*
82  * iterate_supers_type() doesn't protect us from
83  * remounting (branch management)
84  */
85 struct au_splhead au_sbilist;
86 #endif
87
88 struct lock_class_key au_lc_key[AuLcKey_Last];
89
90 /*
91  * functions for module interface.
92  */
93 MODULE_LICENSE("GPL");
94 /* MODULE_LICENSE("GPL v2"); */
95 MODULE_AUTHOR("Junjiro R. Okajima <aufs-users@lists.sourceforge.net>");
96 MODULE_DESCRIPTION(AUFS_NAME
97         " -- Advanced multi layered unification filesystem");
98 MODULE_VERSION(AUFS_VERSION);
99
100 /* this module parameter has no meaning when SYSFS is disabled */
101 int sysaufs_brs = 1;
102 MODULE_PARM_DESC(brs, "use <sysfs>/fs/aufs/si_*/brN");
103 module_param_named(brs, sysaufs_brs, int, S_IRUGO);
104
105 /* ---------------------------------------------------------------------- */
106
107 static char au_esc_chars[0x20 + 3]; /* 0x01-0x20, backslash, del, and NULL */
108
109 int au_seq_path(struct seq_file *seq, struct path *path)
110 {
111         return seq_path(seq, path, au_esc_chars);
112 }
113
114 /* ---------------------------------------------------------------------- */
115
116 static int __init aufs_init(void)
117 {
118         int err, i;
119         char *p;
120
121         p = au_esc_chars;
122         for (i = 1; i <= ' '; i++)
123                 *p++ = i;
124         *p++ = '\\';
125         *p++ = '\x7f';
126         *p = 0;
127
128         au_dir_roflags = au_file_roflags(O_DIRECTORY | O_LARGEFILE);
129
130         au_sbilist_init();
131         sysaufs_brs_init();
132         au_debug_init();
133         au_dy_init();
134         err = sysaufs_init();
135         if (unlikely(err))
136                 goto out;
137         err = au_procfs_init();
138         if (unlikely(err))
139                 goto out_sysaufs;
140         err = au_wkq_init();
141         if (unlikely(err))
142                 goto out_procfs;
143         err = au_loopback_init();
144         if (unlikely(err))
145                 goto out_wkq;
146         err = au_hnotify_init();
147         if (unlikely(err))
148                 goto out_loopback;
149         err = au_sysrq_init();
150         if (unlikely(err))
151                 goto out_hin;
152         err = au_cache_init();
153         if (unlikely(err))
154                 goto out_sysrq;
155         err = register_filesystem(&aufs_fs_type);
156         if (unlikely(err))
157                 goto out_cache;
158         /* since we define pr_fmt, call printk directly */
159         printk(KERN_INFO AUFS_NAME " " AUFS_VERSION "\n");
160         goto out; /* success */
161
162 out_cache:
163         au_cache_fin();
164 out_sysrq:
165         au_sysrq_fin();
166 out_hin:
167         au_hnotify_fin();
168 out_loopback:
169         au_loopback_fin();
170 out_wkq:
171         au_wkq_fin();
172 out_procfs:
173         au_procfs_fin();
174 out_sysaufs:
175         sysaufs_fin();
176         au_dy_fin();
177 out:
178         return err;
179 }
180
181 static void __exit aufs_exit(void)
182 {
183         unregister_filesystem(&aufs_fs_type);
184         au_cache_fin();
185         au_sysrq_fin();
186         au_hnotify_fin();
187         au_loopback_fin();
188         au_wkq_fin();
189         au_procfs_fin();
190         sysaufs_fin();
191         au_dy_fin();
192 }
193
194 module_init(aufs_init);
195 module_exit(aufs_exit);