• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/fs/gfs2/
1/*
2 * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
3 * Copyright (C) 2004-2006 Red Hat, Inc.  All rights reserved.
4 *
5 * This copyrighted material is made available to anyone wishing to use,
6 * modify, copy, or redistribute it subject to the terms and conditions
7 * of the GNU General Public License version 2.
8 */
9
10#include <linux/slab.h>
11#include <linux/spinlock.h>
12#include <linux/completion.h>
13#include <linux/buffer_head.h>
14#include <linux/module.h>
15#include <linux/init.h>
16#include <linux/gfs2_ondisk.h>
17#include <asm/atomic.h>
18
19#include "gfs2.h"
20#include "incore.h"
21#include "super.h"
22#include "sys.h"
23#include "util.h"
24#include "glock.h"
25#include "quota.h"
26#include "recovery.h"
27
28static struct shrinker qd_shrinker = {
29	.shrink = gfs2_shrink_qd_memory,
30	.seeks = DEFAULT_SEEKS,
31};
32
33static void gfs2_init_inode_once(void *foo)
34{
35	struct gfs2_inode *ip = foo;
36
37	inode_init_once(&ip->i_inode);
38	init_rwsem(&ip->i_rw_mutex);
39	INIT_LIST_HEAD(&ip->i_trunc_list);
40	ip->i_alloc = NULL;
41}
42
43static void gfs2_init_glock_once(void *foo)
44{
45	struct gfs2_glock *gl = foo;
46
47	INIT_HLIST_NODE(&gl->gl_list);
48	spin_lock_init(&gl->gl_spin);
49	INIT_LIST_HEAD(&gl->gl_holders);
50	INIT_LIST_HEAD(&gl->gl_lru);
51	INIT_LIST_HEAD(&gl->gl_ail_list);
52	atomic_set(&gl->gl_ail_count, 0);
53}
54
55static void gfs2_init_gl_aspace_once(void *foo)
56{
57	struct gfs2_glock *gl = foo;
58	struct address_space *mapping = (struct address_space *)(gl + 1);
59
60	gfs2_init_glock_once(gl);
61	memset(mapping, 0, sizeof(*mapping));
62	INIT_RADIX_TREE(&mapping->page_tree, GFP_ATOMIC);
63	spin_lock_init(&mapping->tree_lock);
64	spin_lock_init(&mapping->i_mmap_lock);
65	INIT_LIST_HEAD(&mapping->private_list);
66	spin_lock_init(&mapping->private_lock);
67	INIT_RAW_PRIO_TREE_ROOT(&mapping->i_mmap);
68	INIT_LIST_HEAD(&mapping->i_mmap_nonlinear);
69}
70
71/**
72 * init_gfs2_fs - Register GFS2 as a filesystem
73 *
74 * Returns: 0 on success, error code on failure
75 */
76
77static int __init init_gfs2_fs(void)
78{
79	int error;
80
81	error = gfs2_sys_init();
82	if (error)
83		return error;
84
85	error = gfs2_glock_init();
86	if (error)
87		goto fail;
88
89	error = -ENOMEM;
90	gfs2_glock_cachep = kmem_cache_create("gfs2_glock",
91					      sizeof(struct gfs2_glock),
92					      0, 0,
93					      gfs2_init_glock_once);
94	if (!gfs2_glock_cachep)
95		goto fail;
96
97	gfs2_glock_aspace_cachep = kmem_cache_create("gfs2_glock(aspace)",
98					sizeof(struct gfs2_glock) +
99					sizeof(struct address_space),
100					0, 0, gfs2_init_gl_aspace_once);
101
102	if (!gfs2_glock_aspace_cachep)
103		goto fail;
104
105	gfs2_inode_cachep = kmem_cache_create("gfs2_inode",
106					      sizeof(struct gfs2_inode),
107					      0,  SLAB_RECLAIM_ACCOUNT|
108					          SLAB_MEM_SPREAD,
109					      gfs2_init_inode_once);
110	if (!gfs2_inode_cachep)
111		goto fail;
112
113	gfs2_bufdata_cachep = kmem_cache_create("gfs2_bufdata",
114						sizeof(struct gfs2_bufdata),
115					        0, 0, NULL);
116	if (!gfs2_bufdata_cachep)
117		goto fail;
118
119	gfs2_rgrpd_cachep = kmem_cache_create("gfs2_rgrpd",
120					      sizeof(struct gfs2_rgrpd),
121					      0, 0, NULL);
122	if (!gfs2_rgrpd_cachep)
123		goto fail;
124
125	gfs2_quotad_cachep = kmem_cache_create("gfs2_quotad",
126					       sizeof(struct gfs2_quota_data),
127					       0, 0, NULL);
128	if (!gfs2_quotad_cachep)
129		goto fail;
130
131	register_shrinker(&qd_shrinker);
132
133	error = register_filesystem(&gfs2_fs_type);
134	if (error)
135		goto fail;
136
137	error = register_filesystem(&gfs2meta_fs_type);
138	if (error)
139		goto fail_unregister;
140
141	error = -ENOMEM;
142	gfs_recovery_wq = alloc_workqueue("gfs_recovery",
143					  WQ_NON_REENTRANT | WQ_RESCUER, 0);
144	if (!gfs_recovery_wq)
145		goto fail_wq;
146
147	gfs2_register_debugfs();
148
149	printk("GFS2 (built %s %s) installed\n", __DATE__, __TIME__);
150
151	return 0;
152
153fail_wq:
154	unregister_filesystem(&gfs2meta_fs_type);
155fail_unregister:
156	unregister_filesystem(&gfs2_fs_type);
157fail:
158	unregister_shrinker(&qd_shrinker);
159	gfs2_glock_exit();
160
161	if (gfs2_quotad_cachep)
162		kmem_cache_destroy(gfs2_quotad_cachep);
163
164	if (gfs2_rgrpd_cachep)
165		kmem_cache_destroy(gfs2_rgrpd_cachep);
166
167	if (gfs2_bufdata_cachep)
168		kmem_cache_destroy(gfs2_bufdata_cachep);
169
170	if (gfs2_inode_cachep)
171		kmem_cache_destroy(gfs2_inode_cachep);
172
173	if (gfs2_glock_aspace_cachep)
174		kmem_cache_destroy(gfs2_glock_aspace_cachep);
175
176	if (gfs2_glock_cachep)
177		kmem_cache_destroy(gfs2_glock_cachep);
178
179	gfs2_sys_uninit();
180	return error;
181}
182
183/**
184 * exit_gfs2_fs - Unregister the file system
185 *
186 */
187
188static void __exit exit_gfs2_fs(void)
189{
190	unregister_shrinker(&qd_shrinker);
191	gfs2_glock_exit();
192	gfs2_unregister_debugfs();
193	unregister_filesystem(&gfs2_fs_type);
194	unregister_filesystem(&gfs2meta_fs_type);
195	destroy_workqueue(gfs_recovery_wq);
196
197	kmem_cache_destroy(gfs2_quotad_cachep);
198	kmem_cache_destroy(gfs2_rgrpd_cachep);
199	kmem_cache_destroy(gfs2_bufdata_cachep);
200	kmem_cache_destroy(gfs2_inode_cachep);
201	kmem_cache_destroy(gfs2_glock_aspace_cachep);
202	kmem_cache_destroy(gfs2_glock_cachep);
203
204	gfs2_sys_uninit();
205}
206
207MODULE_DESCRIPTION("Global File System");
208MODULE_AUTHOR("Red Hat, Inc.");
209MODULE_LICENSE("GPL");
210
211module_init(init_gfs2_fs);
212module_exit(exit_gfs2_fs);
213