1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
4 | * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. |
5 | */ |
6 | |
7 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
8 | |
9 | #include <linux/slab.h> |
10 | #include <linux/spinlock.h> |
11 | #include <linux/completion.h> |
12 | #include <linux/buffer_head.h> |
13 | #include <linux/module.h> |
14 | #include <linux/init.h> |
15 | #include <linux/gfs2_ondisk.h> |
16 | #include <linux/rcupdate.h> |
17 | #include <linux/rculist_bl.h> |
18 | #include <linux/atomic.h> |
19 | #include <linux/mempool.h> |
20 | |
21 | #include "gfs2.h" |
22 | #include "incore.h" |
23 | #include "super.h" |
24 | #include "sys.h" |
25 | #include "util.h" |
26 | #include "glock.h" |
27 | #include "quota.h" |
28 | #include "recovery.h" |
29 | #include "dir.h" |
30 | #include "glops.h" |
31 | |
32 | struct workqueue_struct *gfs2_control_wq; |
33 | |
34 | static void gfs2_init_inode_once(void *foo) |
35 | { |
36 | struct gfs2_inode *ip = foo; |
37 | |
38 | inode_init_once(&ip->i_inode); |
39 | atomic_set(v: &ip->i_sizehint, i: 0); |
40 | init_rwsem(&ip->i_rw_mutex); |
41 | INIT_LIST_HEAD(list: &ip->i_ordered); |
42 | ip->i_qadata = NULL; |
43 | gfs2_holder_mark_uninitialized(gh: &ip->i_rgd_gh); |
44 | memset(&ip->i_res, 0, sizeof(ip->i_res)); |
45 | RB_CLEAR_NODE(&ip->i_res.rs_node); |
46 | ip->i_hash_cache = NULL; |
47 | gfs2_holder_mark_uninitialized(gh: &ip->i_iopen_gh); |
48 | } |
49 | |
50 | static void gfs2_init_glock_once(void *foo) |
51 | { |
52 | struct gfs2_glock *gl = foo; |
53 | |
54 | spin_lock_init(&gl->gl_lockref.lock); |
55 | INIT_LIST_HEAD(list: &gl->gl_holders); |
56 | INIT_LIST_HEAD(list: &gl->gl_lru); |
57 | INIT_LIST_HEAD(list: &gl->gl_ail_list); |
58 | atomic_set(v: &gl->gl_ail_count, i: 0); |
59 | atomic_set(v: &gl->gl_revokes, i: 0); |
60 | } |
61 | |
62 | static void gfs2_init_gl_aspace_once(void *foo) |
63 | { |
64 | struct gfs2_glock_aspace *gla = foo; |
65 | |
66 | gfs2_init_glock_once(foo: &gla->glock); |
67 | address_space_init_once(mapping: &gla->mapping); |
68 | } |
69 | |
70 | /** |
71 | * init_gfs2_fs - Register GFS2 as a filesystem |
72 | * |
73 | * Returns: 0 on success, error code on failure |
74 | */ |
75 | |
76 | static int __init init_gfs2_fs(void) |
77 | { |
78 | int error; |
79 | |
80 | gfs2_str2qstr(name: &gfs2_qdot, fname: "." ); |
81 | gfs2_str2qstr(name: &gfs2_qdotdot, fname: ".." ); |
82 | gfs2_quota_hash_init(); |
83 | |
84 | error = gfs2_sys_init(); |
85 | if (error) |
86 | return error; |
87 | |
88 | error = list_lru_init(&gfs2_qd_lru); |
89 | if (error) |
90 | goto fail_lru; |
91 | |
92 | error = gfs2_glock_init(); |
93 | if (error) |
94 | goto fail_glock; |
95 | |
96 | error = -ENOMEM; |
97 | gfs2_glock_cachep = kmem_cache_create(name: "gfs2_glock" , |
98 | size: sizeof(struct gfs2_glock), |
99 | align: 0, SLAB_RECLAIM_ACCOUNT, |
100 | ctor: gfs2_init_glock_once); |
101 | if (!gfs2_glock_cachep) |
102 | goto fail_cachep1; |
103 | |
104 | gfs2_glock_aspace_cachep = kmem_cache_create(name: "gfs2_glock(aspace)" , |
105 | size: sizeof(struct gfs2_glock_aspace), |
106 | align: 0, flags: 0, ctor: gfs2_init_gl_aspace_once); |
107 | |
108 | if (!gfs2_glock_aspace_cachep) |
109 | goto fail_cachep2; |
110 | |
111 | gfs2_inode_cachep = kmem_cache_create(name: "gfs2_inode" , |
112 | size: sizeof(struct gfs2_inode), |
113 | align: 0, SLAB_RECLAIM_ACCOUNT| |
114 | SLAB_ACCOUNT, |
115 | ctor: gfs2_init_inode_once); |
116 | if (!gfs2_inode_cachep) |
117 | goto fail_cachep3; |
118 | |
119 | gfs2_bufdata_cachep = kmem_cache_create(name: "gfs2_bufdata" , |
120 | size: sizeof(struct gfs2_bufdata), |
121 | align: 0, flags: 0, NULL); |
122 | if (!gfs2_bufdata_cachep) |
123 | goto fail_cachep4; |
124 | |
125 | gfs2_rgrpd_cachep = kmem_cache_create(name: "gfs2_rgrpd" , |
126 | size: sizeof(struct gfs2_rgrpd), |
127 | align: 0, flags: 0, NULL); |
128 | if (!gfs2_rgrpd_cachep) |
129 | goto fail_cachep5; |
130 | |
131 | gfs2_quotad_cachep = kmem_cache_create(name: "gfs2_quotad" , |
132 | size: sizeof(struct gfs2_quota_data), |
133 | align: 0, SLAB_RECLAIM_ACCOUNT, NULL); |
134 | if (!gfs2_quotad_cachep) |
135 | goto fail_cachep6; |
136 | |
137 | gfs2_qadata_cachep = kmem_cache_create(name: "gfs2_qadata" , |
138 | size: sizeof(struct gfs2_qadata), |
139 | align: 0, flags: 0, NULL); |
140 | if (!gfs2_qadata_cachep) |
141 | goto fail_cachep7; |
142 | |
143 | gfs2_trans_cachep = kmem_cache_create(name: "gfs2_trans" , |
144 | size: sizeof(struct gfs2_trans), |
145 | align: 0, flags: 0, NULL); |
146 | if (!gfs2_trans_cachep) |
147 | goto fail_cachep8; |
148 | |
149 | error = gfs2_qd_shrinker_init(); |
150 | if (error) |
151 | goto fail_shrinker; |
152 | |
153 | error = -ENOMEM; |
154 | gfs2_recovery_wq = alloc_workqueue(fmt: "gfs2_recovery" , |
155 | flags: WQ_MEM_RECLAIM | WQ_FREEZABLE, max_active: 0); |
156 | if (!gfs2_recovery_wq) |
157 | goto fail_wq1; |
158 | |
159 | gfs2_control_wq = alloc_workqueue(fmt: "gfs2_control" , |
160 | flags: WQ_UNBOUND | WQ_FREEZABLE, max_active: 0); |
161 | if (!gfs2_control_wq) |
162 | goto fail_wq2; |
163 | |
164 | gfs2_freeze_wq = alloc_workqueue(fmt: "gfs2_freeze" , flags: 0, max_active: 0); |
165 | |
166 | if (!gfs2_freeze_wq) |
167 | goto fail_wq3; |
168 | |
169 | gfs2_page_pool = mempool_create_page_pool(min_nr: 64, order: 0); |
170 | if (!gfs2_page_pool) |
171 | goto fail_mempool; |
172 | |
173 | gfs2_register_debugfs(); |
174 | error = register_filesystem(&gfs2_fs_type); |
175 | if (error) |
176 | goto fail_fs1; |
177 | |
178 | error = register_filesystem(&gfs2meta_fs_type); |
179 | if (error) |
180 | goto fail_fs2; |
181 | |
182 | |
183 | pr_info("GFS2 installed\n" ); |
184 | |
185 | return 0; |
186 | |
187 | fail_fs2: |
188 | unregister_filesystem(&gfs2_fs_type); |
189 | fail_fs1: |
190 | mempool_destroy(pool: gfs2_page_pool); |
191 | fail_mempool: |
192 | destroy_workqueue(wq: gfs2_freeze_wq); |
193 | fail_wq3: |
194 | destroy_workqueue(wq: gfs2_control_wq); |
195 | fail_wq2: |
196 | destroy_workqueue(wq: gfs2_recovery_wq); |
197 | fail_wq1: |
198 | gfs2_qd_shrinker_exit(); |
199 | fail_shrinker: |
200 | kmem_cache_destroy(s: gfs2_trans_cachep); |
201 | fail_cachep8: |
202 | kmem_cache_destroy(s: gfs2_qadata_cachep); |
203 | fail_cachep7: |
204 | kmem_cache_destroy(s: gfs2_quotad_cachep); |
205 | fail_cachep6: |
206 | kmem_cache_destroy(s: gfs2_rgrpd_cachep); |
207 | fail_cachep5: |
208 | kmem_cache_destroy(s: gfs2_bufdata_cachep); |
209 | fail_cachep4: |
210 | kmem_cache_destroy(s: gfs2_inode_cachep); |
211 | fail_cachep3: |
212 | kmem_cache_destroy(s: gfs2_glock_aspace_cachep); |
213 | fail_cachep2: |
214 | kmem_cache_destroy(s: gfs2_glock_cachep); |
215 | fail_cachep1: |
216 | gfs2_glock_exit(); |
217 | fail_glock: |
218 | list_lru_destroy(lru: &gfs2_qd_lru); |
219 | fail_lru: |
220 | gfs2_sys_uninit(); |
221 | return error; |
222 | } |
223 | |
224 | /** |
225 | * exit_gfs2_fs - Unregister the file system |
226 | * |
227 | */ |
228 | |
229 | static void __exit exit_gfs2_fs(void) |
230 | { |
231 | gfs2_qd_shrinker_exit(); |
232 | gfs2_glock_exit(); |
233 | gfs2_unregister_debugfs(); |
234 | unregister_filesystem(&gfs2_fs_type); |
235 | unregister_filesystem(&gfs2meta_fs_type); |
236 | destroy_workqueue(wq: gfs2_recovery_wq); |
237 | destroy_workqueue(wq: gfs2_control_wq); |
238 | destroy_workqueue(wq: gfs2_freeze_wq); |
239 | list_lru_destroy(lru: &gfs2_qd_lru); |
240 | |
241 | rcu_barrier(); |
242 | |
243 | mempool_destroy(pool: gfs2_page_pool); |
244 | kmem_cache_destroy(s: gfs2_trans_cachep); |
245 | kmem_cache_destroy(s: gfs2_qadata_cachep); |
246 | kmem_cache_destroy(s: gfs2_quotad_cachep); |
247 | kmem_cache_destroy(s: gfs2_rgrpd_cachep); |
248 | kmem_cache_destroy(s: gfs2_bufdata_cachep); |
249 | kmem_cache_destroy(s: gfs2_inode_cachep); |
250 | kmem_cache_destroy(s: gfs2_glock_aspace_cachep); |
251 | kmem_cache_destroy(s: gfs2_glock_cachep); |
252 | |
253 | gfs2_sys_uninit(); |
254 | } |
255 | |
256 | MODULE_DESCRIPTION("Global File System" ); |
257 | MODULE_AUTHOR("Red Hat, Inc." ); |
258 | MODULE_LICENSE("GPL" ); |
259 | |
260 | module_init(init_gfs2_fs); |
261 | module_exit(exit_gfs2_fs); |
262 | |
263 | |