ARM: 8255/1: perf: Prevent wraparound during overflow
[pandora-kernel.git] / fs / aufs / module.c
1 /*
2  * Copyright (C) 2005-2013 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         /* excluding AuCache_HNOTIFY */
69         BUILD_BUG_ON(AuCache_HNOTIFY + 1 != AuCache_Last);
70         for (i = 0; i < AuCache_HNOTIFY; i++)
71                 if (au_cachep[i]) {
72                         kmem_cache_destroy(au_cachep[i]);
73                         au_cachep[i] = NULL;
74                 }
75 }
76
77 /* ---------------------------------------------------------------------- */
78
79 int au_dir_roflags;
80
81 #ifdef CONFIG_AUFS_SBILIST
82 /*
83  * iterate_supers_type() doesn't protect us from
84  * remounting (branch management)
85  */
86 struct au_splhead au_sbilist;
87 #endif
88
89 struct lock_class_key au_lc_key[AuLcKey_Last];
90
91 /*
92  * functions for module interface.
93  */
94 MODULE_LICENSE("GPL");
95 /* MODULE_LICENSE("GPL v2"); */
96 MODULE_AUTHOR("Junjiro R. Okajima <aufs-users@lists.sourceforge.net>");
97 MODULE_DESCRIPTION(AUFS_NAME
98         " -- Advanced multi layered unification filesystem");
99 MODULE_VERSION(AUFS_VERSION);
100
101 /* this module parameter has no meaning when SYSFS is disabled */
102 int sysaufs_brs = 1;
103 MODULE_PARM_DESC(brs, "use <sysfs>/fs/aufs/si_*/brN");
104 module_param_named(brs, sysaufs_brs, int, S_IRUGO);
105
106 /* ---------------------------------------------------------------------- */
107
108 static char au_esc_chars[0x20 + 3]; /* 0x01-0x20, backslash, del, and NULL */
109
110 int au_seq_path(struct seq_file *seq, struct path *path)
111 {
112         return seq_path(seq, path, au_esc_chars);
113 }
114
115 /* ---------------------------------------------------------------------- */
116
117 static int __init aufs_init(void)
118 {
119         int err, i;
120         char *p;
121
122         p = au_esc_chars;
123         for (i = 1; i <= ' '; i++)
124                 *p++ = i;
125         *p++ = '\\';
126         *p++ = '\x7f';
127         *p = 0;
128
129         au_dir_roflags = au_file_roflags(O_DIRECTORY | O_LARGEFILE);
130
131         au_sbilist_init();
132         sysaufs_brs_init();
133         au_debug_init();
134         au_dy_init();
135         err = sysaufs_init();
136         if (unlikely(err))
137                 goto out;
138         err = au_procfs_init();
139         if (unlikely(err))
140                 goto out_sysaufs;
141         err = au_wkq_init();
142         if (unlikely(err))
143                 goto out_procfs;
144         err = au_loopback_init();
145         if (unlikely(err))
146                 goto out_wkq;
147         err = au_hnotify_init();
148         if (unlikely(err))
149                 goto out_loopback;
150         err = au_sysrq_init();
151         if (unlikely(err))
152                 goto out_hin;
153         err = au_cache_init();
154         if (unlikely(err))
155                 goto out_sysrq;
156         err = register_filesystem(&aufs_fs_type);
157         if (unlikely(err))
158                 goto out_cache;
159         /* since we define pr_fmt, call printk directly */
160         printk(KERN_INFO AUFS_NAME " " AUFS_VERSION "\n");
161         goto out; /* success */
162
163 out_cache:
164         au_cache_fin();
165 out_sysrq:
166         au_sysrq_fin();
167 out_hin:
168         au_hnotify_fin();
169 out_loopback:
170         au_loopback_fin();
171 out_wkq:
172         au_wkq_fin();
173 out_procfs:
174         au_procfs_fin();
175 out_sysaufs:
176         sysaufs_fin();
177         au_dy_fin();
178 out:
179         return err;
180 }
181
182 static void __exit aufs_exit(void)
183 {
184         unregister_filesystem(&aufs_fs_type);
185         au_cache_fin();
186         au_sysrq_fin();
187         au_hnotify_fin();
188         au_loopback_fin();
189         au_wkq_fin();
190         au_procfs_fin();
191         sysaufs_fin();
192         au_dy_fin();
193 }
194
195 module_init(aufs_init);
196 module_exit(aufs_exit);