]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blob - fs/aufs/module.c
UBUNTU: SAUCE: AUFS
[mirror_ubuntu-jammy-kernel.git] / fs / aufs / module.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (C) 2005-2021 Junjiro R. Okajima
4 *
5 * This program, aufs is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
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 /* shrinkable realloc */
28 void *au_krealloc(void *p, unsigned int new_sz, gfp_t gfp, int may_shrink)
29 {
30 size_t sz;
31 int diff;
32
33 sz = 0;
34 diff = -1;
35 if (p) {
36 #if 0 /* unused */
37 if (!new_sz) {
38 au_kfree_rcu(p);
39 p = NULL;
40 goto out;
41 }
42 #else
43 AuDebugOn(!new_sz);
44 #endif
45 sz = ksize(p);
46 diff = au_kmidx_sub(sz, new_sz);
47 }
48 if (sz && !diff)
49 goto out;
50
51 if (sz < new_sz)
52 /* expand or SLOB */
53 p = krealloc(p, new_sz, gfp);
54 else if (new_sz < sz && may_shrink) {
55 /* shrink */
56 void *q;
57
58 q = kmalloc(new_sz, gfp);
59 if (q) {
60 if (p) {
61 memcpy(q, p, new_sz);
62 au_kfree_try_rcu(p);
63 }
64 p = q;
65 } else
66 p = NULL;
67 }
68
69 out:
70 return p;
71 }
72
73 void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp,
74 int may_shrink)
75 {
76 p = au_krealloc(p, new_sz, gfp, may_shrink);
77 if (p && new_sz > nused)
78 memset(p + nused, 0, new_sz - nused);
79 return p;
80 }
81
82 /* ---------------------------------------------------------------------- */
83 /*
84 * aufs caches
85 */
86 struct kmem_cache *au_cache[AuCache_Last];
87
88 static void au_cache_fin(void)
89 {
90 int i;
91
92 /*
93 * Make sure all delayed rcu free inodes are flushed before we
94 * destroy cache.
95 */
96 rcu_barrier();
97
98 /* excluding AuCache_HNOTIFY */
99 BUILD_BUG_ON(AuCache_HNOTIFY + 1 != AuCache_Last);
100 for (i = 0; i < AuCache_HNOTIFY; i++) {
101 kmem_cache_destroy(au_cache[i]);
102 au_cache[i] = NULL;
103 }
104 }
105
106 static int __init au_cache_init(void)
107 {
108 au_cache[AuCache_DINFO] = AuCacheCtor(au_dinfo, au_di_init_once);
109 if (au_cache[AuCache_DINFO])
110 /* SLAB_DESTROY_BY_RCU */
111 au_cache[AuCache_ICNTNR] = AuCacheCtor(au_icntnr,
112 au_icntnr_init_once);
113 if (au_cache[AuCache_ICNTNR])
114 au_cache[AuCache_FINFO] = AuCacheCtor(au_finfo,
115 au_fi_init_once);
116 if (au_cache[AuCache_FINFO])
117 au_cache[AuCache_VDIR] = AuCache(au_vdir);
118 if (au_cache[AuCache_VDIR])
119 au_cache[AuCache_DEHSTR] = AuCache(au_vdir_dehstr);
120 if (au_cache[AuCache_DEHSTR])
121 return 0;
122
123 au_cache_fin();
124 return -ENOMEM;
125 }
126
127 /* ---------------------------------------------------------------------- */
128
129 int au_dir_roflags;
130
131 #ifdef CONFIG_AUFS_SBILIST
132 /*
133 * iterate_supers_type() doesn't protect us from
134 * remounting (branch management)
135 */
136 struct hlist_bl_head au_sbilist;
137 #endif
138
139 /*
140 * functions for module interface.
141 */
142 MODULE_LICENSE("GPL");
143 /* MODULE_LICENSE("GPL v2"); */
144 MODULE_AUTHOR("Junjiro R. Okajima <aufs-users@lists.sourceforge.net>");
145 MODULE_DESCRIPTION(AUFS_NAME
146 " -- Advanced multi layered unification filesystem");
147 MODULE_VERSION(AUFS_VERSION);
148 MODULE_ALIAS_FS(AUFS_NAME);
149
150 /* this module parameter has no meaning when SYSFS is disabled */
151 int sysaufs_brs = 1;
152 MODULE_PARM_DESC(brs, "use <sysfs>/fs/aufs/si_*/brN");
153 module_param_named(brs, sysaufs_brs, int, 0444);
154
155 /* this module parameter has no meaning when USER_NS is disabled */
156 bool au_userns;
157 MODULE_PARM_DESC(allow_userns, "allow unprivileged to mount under userns");
158 module_param_named(allow_userns, au_userns, bool, 0444);
159
160 /* ---------------------------------------------------------------------- */
161
162 static char au_esc_chars[0x20 + 3]; /* 0x01-0x20, backslash, del, and NULL */
163
164 int au_seq_path(struct seq_file *seq, struct path *path)
165 {
166 int err;
167
168 err = seq_path(seq, path, au_esc_chars);
169 if (err >= 0)
170 err = 0;
171 else
172 err = -ENOMEM;
173
174 return err;
175 }
176
177 /* ---------------------------------------------------------------------- */
178
179 static int __init aufs_init(void)
180 {
181 int err, i;
182 char *p;
183
184 p = au_esc_chars;
185 for (i = 1; i <= ' '; i++)
186 *p++ = i;
187 *p++ = '\\';
188 *p++ = '\x7f';
189 *p = 0;
190
191 au_dir_roflags = au_file_roflags(O_DIRECTORY | O_LARGEFILE);
192
193 memcpy(aufs_iop_nogetattr, aufs_iop, sizeof(aufs_iop));
194 for (i = 0; i < AuIop_Last; i++)
195 aufs_iop_nogetattr[i].getattr = NULL;
196
197 memset(au_cache, 0, sizeof(au_cache)); /* including hnotify */
198
199 au_sbilist_init();
200 sysaufs_brs_init();
201 au_debug_init();
202 au_dy_init();
203 err = sysaufs_init();
204 if (unlikely(err))
205 goto out;
206 err = dbgaufs_init();
207 if (unlikely(err))
208 goto out_sysaufs;
209 err = au_procfs_init();
210 if (unlikely(err))
211 goto out_dbgaufs;
212 err = au_wkq_init();
213 if (unlikely(err))
214 goto out_procfs;
215 err = au_loopback_init();
216 if (unlikely(err))
217 goto out_wkq;
218 err = au_hnotify_init();
219 if (unlikely(err))
220 goto out_loopback;
221 err = au_sysrq_init();
222 if (unlikely(err))
223 goto out_hin;
224 err = au_cache_init();
225 if (unlikely(err))
226 goto out_sysrq;
227
228 aufs_fs_type.fs_flags |= au_userns ? FS_USERNS_MOUNT : 0;
229 err = register_filesystem(&aufs_fs_type);
230 if (unlikely(err))
231 goto out_cache;
232
233 /* since we define pr_fmt, call printk directly */
234 printk(KERN_INFO AUFS_NAME " " AUFS_VERSION "\n");
235 goto out; /* success */
236
237 out_cache:
238 au_cache_fin();
239 out_sysrq:
240 au_sysrq_fin();
241 out_hin:
242 au_hnotify_fin();
243 out_loopback:
244 au_loopback_fin();
245 out_wkq:
246 au_wkq_fin();
247 out_procfs:
248 au_procfs_fin();
249 out_dbgaufs:
250 dbgaufs_fin();
251 out_sysaufs:
252 sysaufs_fin();
253 au_dy_fin();
254 out:
255 return err;
256 }
257
258 static void __exit aufs_exit(void)
259 {
260 unregister_filesystem(&aufs_fs_type);
261 au_cache_fin();
262 au_sysrq_fin();
263 au_hnotify_fin();
264 au_loopback_fin();
265 au_wkq_fin();
266 au_procfs_fin();
267 dbgaufs_fin();
268 sysaufs_fin();
269 au_dy_fin();
270 }
271
272 module_init(aufs_init);
273 module_exit(aufs_exit);