xref: /linux/fs/gfs2/sys.c (revision b3b94faa5fe5968827ba0640ee9fba4b3e7f736e)
1*b3b94faaSDavid Teigland /*
2*b3b94faaSDavid Teigland  * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
3*b3b94faaSDavid Teigland  * Copyright (C) 2004-2005 Red Hat, Inc.  All rights reserved.
4*b3b94faaSDavid Teigland  *
5*b3b94faaSDavid Teigland  * This copyrighted material is made available to anyone wishing to use,
6*b3b94faaSDavid Teigland  * modify, copy, or redistribute it subject to the terms and conditions
7*b3b94faaSDavid Teigland  * of the GNU General Public License v.2.
8*b3b94faaSDavid Teigland  */
9*b3b94faaSDavid Teigland 
10*b3b94faaSDavid Teigland #include <linux/sched.h>
11*b3b94faaSDavid Teigland #include <linux/slab.h>
12*b3b94faaSDavid Teigland #include <linux/spinlock.h>
13*b3b94faaSDavid Teigland #include <linux/completion.h>
14*b3b94faaSDavid Teigland #include <linux/buffer_head.h>
15*b3b94faaSDavid Teigland #include <linux/module.h>
16*b3b94faaSDavid Teigland #include <linux/kobject.h>
17*b3b94faaSDavid Teigland #include <asm/semaphore.h>
18*b3b94faaSDavid Teigland #include <asm/uaccess.h>
19*b3b94faaSDavid Teigland 
20*b3b94faaSDavid Teigland #include "gfs2.h"
21*b3b94faaSDavid Teigland #include "lm.h"
22*b3b94faaSDavid Teigland #include "sys.h"
23*b3b94faaSDavid Teigland #include "super.h"
24*b3b94faaSDavid Teigland #include "glock.h"
25*b3b94faaSDavid Teigland #include "quota.h"
26*b3b94faaSDavid Teigland 
27*b3b94faaSDavid Teigland char *gfs2_sys_margs;
28*b3b94faaSDavid Teigland spinlock_t gfs2_sys_margs_lock;
29*b3b94faaSDavid Teigland 
30*b3b94faaSDavid Teigland static ssize_t id_show(struct gfs2_sbd *sdp, char *buf)
31*b3b94faaSDavid Teigland {
32*b3b94faaSDavid Teigland 	return sprintf(buf, "%s\n", sdp->sd_vfs->s_id);
33*b3b94faaSDavid Teigland }
34*b3b94faaSDavid Teigland 
35*b3b94faaSDavid Teigland static ssize_t fsname_show(struct gfs2_sbd *sdp, char *buf)
36*b3b94faaSDavid Teigland {
37*b3b94faaSDavid Teigland 	return sprintf(buf, "%s\n", sdp->sd_fsname);
38*b3b94faaSDavid Teigland }
39*b3b94faaSDavid Teigland 
40*b3b94faaSDavid Teigland static ssize_t freeze_show(struct gfs2_sbd *sdp, char *buf)
41*b3b94faaSDavid Teigland {
42*b3b94faaSDavid Teigland 	unsigned int count;
43*b3b94faaSDavid Teigland 
44*b3b94faaSDavid Teigland 	down(&sdp->sd_freeze_lock);
45*b3b94faaSDavid Teigland 	count = sdp->sd_freeze_count;
46*b3b94faaSDavid Teigland 	up(&sdp->sd_freeze_lock);
47*b3b94faaSDavid Teigland 
48*b3b94faaSDavid Teigland 	return sprintf(buf, "%u\n", count);
49*b3b94faaSDavid Teigland }
50*b3b94faaSDavid Teigland 
51*b3b94faaSDavid Teigland static ssize_t freeze_store(struct gfs2_sbd *sdp, const char *buf, size_t len)
52*b3b94faaSDavid Teigland {
53*b3b94faaSDavid Teigland 	ssize_t ret = len;
54*b3b94faaSDavid Teigland 	int error = 0;
55*b3b94faaSDavid Teigland 	int n = simple_strtol(buf, NULL, 0);
56*b3b94faaSDavid Teigland 
57*b3b94faaSDavid Teigland 	if (!capable(CAP_SYS_ADMIN))
58*b3b94faaSDavid Teigland 		return -EACCES;
59*b3b94faaSDavid Teigland 
60*b3b94faaSDavid Teigland 	switch (n) {
61*b3b94faaSDavid Teigland 	case 0:
62*b3b94faaSDavid Teigland 		gfs2_unfreeze_fs(sdp);
63*b3b94faaSDavid Teigland 		break;
64*b3b94faaSDavid Teigland 	case 1:
65*b3b94faaSDavid Teigland 		error = gfs2_freeze_fs(sdp);
66*b3b94faaSDavid Teigland 		break;
67*b3b94faaSDavid Teigland 	default:
68*b3b94faaSDavid Teigland 		ret = -EINVAL;
69*b3b94faaSDavid Teigland 	}
70*b3b94faaSDavid Teigland 
71*b3b94faaSDavid Teigland 	if (error)
72*b3b94faaSDavid Teigland 		fs_warn(sdp, "freeze %d error %d", n, error);
73*b3b94faaSDavid Teigland 
74*b3b94faaSDavid Teigland 	return ret;
75*b3b94faaSDavid Teigland }
76*b3b94faaSDavid Teigland 
77*b3b94faaSDavid Teigland static ssize_t withdraw_show(struct gfs2_sbd *sdp, char *buf)
78*b3b94faaSDavid Teigland {
79*b3b94faaSDavid Teigland 	unsigned int b = test_bit(SDF_SHUTDOWN, &sdp->sd_flags);
80*b3b94faaSDavid Teigland 	return sprintf(buf, "%u\n", b);
81*b3b94faaSDavid Teigland }
82*b3b94faaSDavid Teigland 
83*b3b94faaSDavid Teigland static ssize_t withdraw_store(struct gfs2_sbd *sdp, const char *buf, size_t len)
84*b3b94faaSDavid Teigland {
85*b3b94faaSDavid Teigland 	if (!capable(CAP_SYS_ADMIN))
86*b3b94faaSDavid Teigland 		return -EACCES;
87*b3b94faaSDavid Teigland 
88*b3b94faaSDavid Teigland 	if (simple_strtol(buf, NULL, 0) != 1)
89*b3b94faaSDavid Teigland 		return -EINVAL;
90*b3b94faaSDavid Teigland 
91*b3b94faaSDavid Teigland 	gfs2_lm_withdraw(sdp,
92*b3b94faaSDavid Teigland 		"GFS2: fsid=%s: withdrawing from cluster at user's request\n",
93*b3b94faaSDavid Teigland 		sdp->sd_fsname);
94*b3b94faaSDavid Teigland 	return len;
95*b3b94faaSDavid Teigland }
96*b3b94faaSDavid Teigland 
97*b3b94faaSDavid Teigland static ssize_t statfs_sync_store(struct gfs2_sbd *sdp, const char *buf,
98*b3b94faaSDavid Teigland 				 size_t len)
99*b3b94faaSDavid Teigland {
100*b3b94faaSDavid Teigland 	if (!capable(CAP_SYS_ADMIN))
101*b3b94faaSDavid Teigland 		return -EACCES;
102*b3b94faaSDavid Teigland 
103*b3b94faaSDavid Teigland 	if (simple_strtol(buf, NULL, 0) != 1)
104*b3b94faaSDavid Teigland 		return -EINVAL;
105*b3b94faaSDavid Teigland 
106*b3b94faaSDavid Teigland 	gfs2_statfs_sync(sdp);
107*b3b94faaSDavid Teigland 	return len;
108*b3b94faaSDavid Teigland }
109*b3b94faaSDavid Teigland 
110*b3b94faaSDavid Teigland static ssize_t shrink_store(struct gfs2_sbd *sdp, const char *buf, size_t len)
111*b3b94faaSDavid Teigland {
112*b3b94faaSDavid Teigland 	if (!capable(CAP_SYS_ADMIN))
113*b3b94faaSDavid Teigland 		return -EACCES;
114*b3b94faaSDavid Teigland 
115*b3b94faaSDavid Teigland 	if (simple_strtol(buf, NULL, 0) != 1)
116*b3b94faaSDavid Teigland 		return -EINVAL;
117*b3b94faaSDavid Teigland 
118*b3b94faaSDavid Teigland 	gfs2_gl_hash_clear(sdp, NO_WAIT);
119*b3b94faaSDavid Teigland 	return len;
120*b3b94faaSDavid Teigland }
121*b3b94faaSDavid Teigland 
122*b3b94faaSDavid Teigland static ssize_t quota_sync_store(struct gfs2_sbd *sdp, const char *buf,
123*b3b94faaSDavid Teigland 				size_t len)
124*b3b94faaSDavid Teigland {
125*b3b94faaSDavid Teigland 	if (!capable(CAP_SYS_ADMIN))
126*b3b94faaSDavid Teigland 		return -EACCES;
127*b3b94faaSDavid Teigland 
128*b3b94faaSDavid Teigland 	if (simple_strtol(buf, NULL, 0) != 1)
129*b3b94faaSDavid Teigland 		return -EINVAL;
130*b3b94faaSDavid Teigland 
131*b3b94faaSDavid Teigland 	gfs2_quota_sync(sdp);
132*b3b94faaSDavid Teigland 	return len;
133*b3b94faaSDavid Teigland }
134*b3b94faaSDavid Teigland 
135*b3b94faaSDavid Teigland static ssize_t quota_refresh_user_store(struct gfs2_sbd *sdp, const char *buf,
136*b3b94faaSDavid Teigland 					size_t len)
137*b3b94faaSDavid Teigland {
138*b3b94faaSDavid Teigland 	uint32_t id;
139*b3b94faaSDavid Teigland 
140*b3b94faaSDavid Teigland 	if (!capable(CAP_SYS_ADMIN))
141*b3b94faaSDavid Teigland 		return -EACCES;
142*b3b94faaSDavid Teigland 
143*b3b94faaSDavid Teigland 	id = simple_strtoul(buf, NULL, 0);
144*b3b94faaSDavid Teigland 
145*b3b94faaSDavid Teigland 	gfs2_quota_refresh(sdp, 1, id);
146*b3b94faaSDavid Teigland 	return len;
147*b3b94faaSDavid Teigland }
148*b3b94faaSDavid Teigland 
149*b3b94faaSDavid Teigland static ssize_t quota_refresh_group_store(struct gfs2_sbd *sdp, const char *buf,
150*b3b94faaSDavid Teigland 					 size_t len)
151*b3b94faaSDavid Teigland {
152*b3b94faaSDavid Teigland 	uint32_t id;
153*b3b94faaSDavid Teigland 
154*b3b94faaSDavid Teigland 	if (!capable(CAP_SYS_ADMIN))
155*b3b94faaSDavid Teigland 		return -EACCES;
156*b3b94faaSDavid Teigland 
157*b3b94faaSDavid Teigland 	id = simple_strtoul(buf, NULL, 0);
158*b3b94faaSDavid Teigland 
159*b3b94faaSDavid Teigland 	gfs2_quota_refresh(sdp, 0, id);
160*b3b94faaSDavid Teigland 	return len;
161*b3b94faaSDavid Teigland }
162*b3b94faaSDavid Teigland 
163*b3b94faaSDavid Teigland struct gfs2_attr {
164*b3b94faaSDavid Teigland 	struct attribute attr;
165*b3b94faaSDavid Teigland 	ssize_t (*show)(struct gfs2_sbd *, char *);
166*b3b94faaSDavid Teigland 	ssize_t (*store)(struct gfs2_sbd *, const char *, size_t);
167*b3b94faaSDavid Teigland };
168*b3b94faaSDavid Teigland 
169*b3b94faaSDavid Teigland #define GFS2_ATTR(name, mode, show, store) \
170*b3b94faaSDavid Teigland static struct gfs2_attr gfs2_attr_##name = __ATTR(name, mode, show, store)
171*b3b94faaSDavid Teigland 
172*b3b94faaSDavid Teigland GFS2_ATTR(id,                  0444, id_show,       NULL);
173*b3b94faaSDavid Teigland GFS2_ATTR(fsname,              0444, fsname_show,   NULL);
174*b3b94faaSDavid Teigland GFS2_ATTR(freeze,              0644, freeze_show,   freeze_store);
175*b3b94faaSDavid Teigland GFS2_ATTR(shrink,              0200, NULL,          shrink_store);
176*b3b94faaSDavid Teigland GFS2_ATTR(withdraw,            0644, withdraw_show, withdraw_store);
177*b3b94faaSDavid Teigland GFS2_ATTR(statfs_sync,         0200, NULL,          statfs_sync_store);
178*b3b94faaSDavid Teigland GFS2_ATTR(quota_sync,          0200, NULL,          quota_sync_store);
179*b3b94faaSDavid Teigland GFS2_ATTR(quota_refresh_user,  0200, NULL,          quota_refresh_user_store);
180*b3b94faaSDavid Teigland GFS2_ATTR(quota_refresh_group, 0200, NULL,          quota_refresh_group_store);
181*b3b94faaSDavid Teigland 
182*b3b94faaSDavid Teigland static struct attribute *gfs2_attrs[] = {
183*b3b94faaSDavid Teigland 	&gfs2_attr_id.attr,
184*b3b94faaSDavid Teigland 	&gfs2_attr_fsname.attr,
185*b3b94faaSDavid Teigland 	&gfs2_attr_freeze.attr,
186*b3b94faaSDavid Teigland 	&gfs2_attr_shrink.attr,
187*b3b94faaSDavid Teigland 	&gfs2_attr_withdraw.attr,
188*b3b94faaSDavid Teigland 	&gfs2_attr_statfs_sync.attr,
189*b3b94faaSDavid Teigland 	&gfs2_attr_quota_sync.attr,
190*b3b94faaSDavid Teigland 	&gfs2_attr_quota_refresh_user.attr,
191*b3b94faaSDavid Teigland 	&gfs2_attr_quota_refresh_group.attr,
192*b3b94faaSDavid Teigland 	NULL,
193*b3b94faaSDavid Teigland };
194*b3b94faaSDavid Teigland 
195*b3b94faaSDavid Teigland static ssize_t gfs2_attr_show(struct kobject *kobj, struct attribute *attr,
196*b3b94faaSDavid Teigland 			      char *buf)
197*b3b94faaSDavid Teigland {
198*b3b94faaSDavid Teigland 	struct gfs2_sbd *sdp = container_of(kobj, struct gfs2_sbd, sd_kobj);
199*b3b94faaSDavid Teigland 	struct gfs2_attr *a = container_of(attr, struct gfs2_attr, attr);
200*b3b94faaSDavid Teigland 	return a->show ? a->show(sdp, buf) : 0;
201*b3b94faaSDavid Teigland }
202*b3b94faaSDavid Teigland 
203*b3b94faaSDavid Teigland static ssize_t gfs2_attr_store(struct kobject *kobj, struct attribute *attr,
204*b3b94faaSDavid Teigland 			       const char *buf, size_t len)
205*b3b94faaSDavid Teigland {
206*b3b94faaSDavid Teigland 	struct gfs2_sbd *sdp = container_of(kobj, struct gfs2_sbd, sd_kobj);
207*b3b94faaSDavid Teigland 	struct gfs2_attr *a = container_of(attr, struct gfs2_attr, attr);
208*b3b94faaSDavid Teigland 	return a->store ? a->store(sdp, buf, len) : len;
209*b3b94faaSDavid Teigland }
210*b3b94faaSDavid Teigland 
211*b3b94faaSDavid Teigland static struct sysfs_ops gfs2_attr_ops = {
212*b3b94faaSDavid Teigland 	.show  = gfs2_attr_show,
213*b3b94faaSDavid Teigland 	.store = gfs2_attr_store,
214*b3b94faaSDavid Teigland };
215*b3b94faaSDavid Teigland 
216*b3b94faaSDavid Teigland static struct kobj_type gfs2_ktype = {
217*b3b94faaSDavid Teigland 	.default_attrs = gfs2_attrs,
218*b3b94faaSDavid Teigland 	.sysfs_ops     = &gfs2_attr_ops,
219*b3b94faaSDavid Teigland };
220*b3b94faaSDavid Teigland 
221*b3b94faaSDavid Teigland static struct kset gfs2_kset = {
222*b3b94faaSDavid Teigland 	.subsys = &fs_subsys,
223*b3b94faaSDavid Teigland 	.kobj   = {.name = "gfs2",},
224*b3b94faaSDavid Teigland 	.ktype  = &gfs2_ktype,
225*b3b94faaSDavid Teigland };
226*b3b94faaSDavid Teigland 
227*b3b94faaSDavid Teigland /*
228*b3b94faaSDavid Teigland  * display struct lm_lockstruct fields
229*b3b94faaSDavid Teigland  */
230*b3b94faaSDavid Teigland 
231*b3b94faaSDavid Teigland struct lockstruct_attr {
232*b3b94faaSDavid Teigland 	struct attribute attr;
233*b3b94faaSDavid Teigland 	ssize_t (*show)(struct gfs2_sbd *, char *);
234*b3b94faaSDavid Teigland };
235*b3b94faaSDavid Teigland 
236*b3b94faaSDavid Teigland #define LOCKSTRUCT_ATTR(name, fmt)                                          \
237*b3b94faaSDavid Teigland static ssize_t name##_show(struct gfs2_sbd *sdp, char *buf)                 \
238*b3b94faaSDavid Teigland {                                                                           \
239*b3b94faaSDavid Teigland 	return sprintf(buf, fmt, sdp->sd_lockstruct.ls_##name);             \
240*b3b94faaSDavid Teigland }                                                                           \
241*b3b94faaSDavid Teigland static struct lockstruct_attr lockstruct_attr_##name = __ATTR_RO(name)
242*b3b94faaSDavid Teigland 
243*b3b94faaSDavid Teigland LOCKSTRUCT_ATTR(jid,      "%u\n");
244*b3b94faaSDavid Teigland LOCKSTRUCT_ATTR(first,    "%u\n");
245*b3b94faaSDavid Teigland LOCKSTRUCT_ATTR(lvb_size, "%u\n");
246*b3b94faaSDavid Teigland LOCKSTRUCT_ATTR(flags,    "%d\n");
247*b3b94faaSDavid Teigland 
248*b3b94faaSDavid Teigland static struct attribute *lockstruct_attrs[] = {
249*b3b94faaSDavid Teigland 	&lockstruct_attr_jid.attr,
250*b3b94faaSDavid Teigland 	&lockstruct_attr_first.attr,
251*b3b94faaSDavid Teigland 	&lockstruct_attr_lvb_size.attr,
252*b3b94faaSDavid Teigland 	&lockstruct_attr_flags.attr,
253*b3b94faaSDavid Teigland 	NULL
254*b3b94faaSDavid Teigland };
255*b3b94faaSDavid Teigland 
256*b3b94faaSDavid Teigland /*
257*b3b94faaSDavid Teigland  * display struct gfs2_args fields
258*b3b94faaSDavid Teigland  */
259*b3b94faaSDavid Teigland 
260*b3b94faaSDavid Teigland struct args_attr {
261*b3b94faaSDavid Teigland 	struct attribute attr;
262*b3b94faaSDavid Teigland 	ssize_t (*show)(struct gfs2_sbd *, char *);
263*b3b94faaSDavid Teigland };
264*b3b94faaSDavid Teigland 
265*b3b94faaSDavid Teigland #define ARGS_ATTR(name, fmt)                                                \
266*b3b94faaSDavid Teigland static ssize_t name##_show(struct gfs2_sbd *sdp, char *buf)                 \
267*b3b94faaSDavid Teigland {                                                                           \
268*b3b94faaSDavid Teigland 	return sprintf(buf, fmt, sdp->sd_args.ar_##name);                   \
269*b3b94faaSDavid Teigland }                                                                           \
270*b3b94faaSDavid Teigland static struct args_attr args_attr_##name = __ATTR_RO(name)
271*b3b94faaSDavid Teigland 
272*b3b94faaSDavid Teigland ARGS_ATTR(lockproto,       "%s\n");
273*b3b94faaSDavid Teigland ARGS_ATTR(locktable,       "%s\n");
274*b3b94faaSDavid Teigland ARGS_ATTR(hostdata,        "%s\n");
275*b3b94faaSDavid Teigland ARGS_ATTR(spectator,       "%d\n");
276*b3b94faaSDavid Teigland ARGS_ATTR(ignore_local_fs, "%d\n");
277*b3b94faaSDavid Teigland ARGS_ATTR(localcaching,    "%d\n");
278*b3b94faaSDavid Teigland ARGS_ATTR(localflocks,     "%d\n");
279*b3b94faaSDavid Teigland ARGS_ATTR(debug,           "%d\n");
280*b3b94faaSDavid Teigland ARGS_ATTR(upgrade,         "%d\n");
281*b3b94faaSDavid Teigland ARGS_ATTR(num_glockd,      "%u\n");
282*b3b94faaSDavid Teigland ARGS_ATTR(posix_acl,       "%d\n");
283*b3b94faaSDavid Teigland ARGS_ATTR(quota,           "%u\n");
284*b3b94faaSDavid Teigland ARGS_ATTR(suiddir,         "%d\n");
285*b3b94faaSDavid Teigland ARGS_ATTR(data,            "%d\n");
286*b3b94faaSDavid Teigland 
287*b3b94faaSDavid Teigland /* one oddball doesn't fit the macro mold */
288*b3b94faaSDavid Teigland static ssize_t noatime_show(struct gfs2_sbd *sdp, char *buf)
289*b3b94faaSDavid Teigland {
290*b3b94faaSDavid Teigland 	return sprintf(buf, "%d\n", !!test_bit(SDF_NOATIME, &sdp->sd_flags));
291*b3b94faaSDavid Teigland }
292*b3b94faaSDavid Teigland static struct args_attr args_attr_noatime = __ATTR_RO(noatime);
293*b3b94faaSDavid Teigland 
294*b3b94faaSDavid Teigland static struct attribute *args_attrs[] = {
295*b3b94faaSDavid Teigland 	&args_attr_lockproto.attr,
296*b3b94faaSDavid Teigland 	&args_attr_locktable.attr,
297*b3b94faaSDavid Teigland 	&args_attr_hostdata.attr,
298*b3b94faaSDavid Teigland 	&args_attr_spectator.attr,
299*b3b94faaSDavid Teigland 	&args_attr_ignore_local_fs.attr,
300*b3b94faaSDavid Teigland 	&args_attr_localcaching.attr,
301*b3b94faaSDavid Teigland 	&args_attr_localflocks.attr,
302*b3b94faaSDavid Teigland 	&args_attr_debug.attr,
303*b3b94faaSDavid Teigland 	&args_attr_upgrade.attr,
304*b3b94faaSDavid Teigland 	&args_attr_num_glockd.attr,
305*b3b94faaSDavid Teigland 	&args_attr_posix_acl.attr,
306*b3b94faaSDavid Teigland 	&args_attr_quota.attr,
307*b3b94faaSDavid Teigland 	&args_attr_suiddir.attr,
308*b3b94faaSDavid Teigland 	&args_attr_data.attr,
309*b3b94faaSDavid Teigland 	&args_attr_noatime.attr,
310*b3b94faaSDavid Teigland 	NULL
311*b3b94faaSDavid Teigland };
312*b3b94faaSDavid Teigland 
313*b3b94faaSDavid Teigland /*
314*b3b94faaSDavid Teigland  * display counters from superblock
315*b3b94faaSDavid Teigland  */
316*b3b94faaSDavid Teigland 
317*b3b94faaSDavid Teigland struct counters_attr {
318*b3b94faaSDavid Teigland 	struct attribute attr;
319*b3b94faaSDavid Teigland 	ssize_t (*show)(struct gfs2_sbd *, char *);
320*b3b94faaSDavid Teigland };
321*b3b94faaSDavid Teigland 
322*b3b94faaSDavid Teigland #define COUNTERS_ATTR_GENERAL(name, fmt, val)                               \
323*b3b94faaSDavid Teigland static ssize_t name##_show(struct gfs2_sbd *sdp, char *buf)                 \
324*b3b94faaSDavid Teigland {                                                                           \
325*b3b94faaSDavid Teigland 	return sprintf(buf, fmt, val);                                      \
326*b3b94faaSDavid Teigland }                                                                           \
327*b3b94faaSDavid Teigland static struct counters_attr counters_attr_##name = __ATTR_RO(name)
328*b3b94faaSDavid Teigland 
329*b3b94faaSDavid Teigland #define COUNTERS_ATTR_SIMPLE(name, fmt) \
330*b3b94faaSDavid Teigland 	COUNTERS_ATTR_GENERAL(name, fmt, sdp->sd_##name)
331*b3b94faaSDavid Teigland 
332*b3b94faaSDavid Teigland #define COUNTERS_ATTR_ATOMIC(name, fmt) \
333*b3b94faaSDavid Teigland 	COUNTERS_ATTR_GENERAL(name, fmt, (unsigned int)atomic_read(&sdp->sd_##name))
334*b3b94faaSDavid Teigland 
335*b3b94faaSDavid Teigland COUNTERS_ATTR_ATOMIC(glock_count,          "%u\n");
336*b3b94faaSDavid Teigland COUNTERS_ATTR_ATOMIC(glock_held_count,     "%u\n");
337*b3b94faaSDavid Teigland COUNTERS_ATTR_ATOMIC(inode_count,          "%u\n");
338*b3b94faaSDavid Teigland COUNTERS_ATTR_ATOMIC(bufdata_count,        "%u\n");
339*b3b94faaSDavid Teigland COUNTERS_ATTR_ATOMIC(unlinked_count,       "%u\n");
340*b3b94faaSDavid Teigland COUNTERS_ATTR_ATOMIC(quota_count,          "%u\n");
341*b3b94faaSDavid Teigland COUNTERS_ATTR_SIMPLE(log_num_gl,           "%u\n");
342*b3b94faaSDavid Teigland COUNTERS_ATTR_SIMPLE(log_num_buf,          "%u\n");
343*b3b94faaSDavid Teigland COUNTERS_ATTR_SIMPLE(log_num_revoke,       "%u\n");
344*b3b94faaSDavid Teigland COUNTERS_ATTR_SIMPLE(log_num_rg,           "%u\n");
345*b3b94faaSDavid Teigland COUNTERS_ATTR_SIMPLE(log_num_databuf,      "%u\n");
346*b3b94faaSDavid Teigland COUNTERS_ATTR_SIMPLE(log_blks_free,        "%u\n");
347*b3b94faaSDavid Teigland COUNTERS_ATTR_GENERAL(jd_blocks,           "%u\n", sdp->sd_jdesc->jd_blocks);
348*b3b94faaSDavid Teigland COUNTERS_ATTR_ATOMIC(reclaim_count,        "%u\n");
349*b3b94faaSDavid Teigland COUNTERS_ATTR_SIMPLE(log_wraps,            "%llu\n");
350*b3b94faaSDavid Teigland COUNTERS_ATTR_ATOMIC(fh2dentry_misses,     "%u\n");
351*b3b94faaSDavid Teigland COUNTERS_ATTR_ATOMIC(reclaimed,            "%u\n");
352*b3b94faaSDavid Teigland COUNTERS_ATTR_ATOMIC(log_flush_incore,     "%u\n");
353*b3b94faaSDavid Teigland COUNTERS_ATTR_ATOMIC(log_flush_ondisk,     "%u\n");
354*b3b94faaSDavid Teigland COUNTERS_ATTR_ATOMIC(glock_nq_calls,       "%u\n");
355*b3b94faaSDavid Teigland COUNTERS_ATTR_ATOMIC(glock_dq_calls,       "%u\n");
356*b3b94faaSDavid Teigland COUNTERS_ATTR_ATOMIC(glock_prefetch_calls, "%u\n");
357*b3b94faaSDavid Teigland COUNTERS_ATTR_ATOMIC(lm_lock_calls,        "%u\n");
358*b3b94faaSDavid Teigland COUNTERS_ATTR_ATOMIC(lm_unlock_calls,      "%u\n");
359*b3b94faaSDavid Teigland COUNTERS_ATTR_ATOMIC(lm_callbacks,         "%u\n");
360*b3b94faaSDavid Teigland COUNTERS_ATTR_ATOMIC(ops_address,          "%u\n");
361*b3b94faaSDavid Teigland COUNTERS_ATTR_ATOMIC(ops_dentry,           "%u\n");
362*b3b94faaSDavid Teigland COUNTERS_ATTR_ATOMIC(ops_export,           "%u\n");
363*b3b94faaSDavid Teigland COUNTERS_ATTR_ATOMIC(ops_file,             "%u\n");
364*b3b94faaSDavid Teigland COUNTERS_ATTR_ATOMIC(ops_inode,            "%u\n");
365*b3b94faaSDavid Teigland COUNTERS_ATTR_ATOMIC(ops_super,            "%u\n");
366*b3b94faaSDavid Teigland COUNTERS_ATTR_ATOMIC(ops_vm,               "%u\n");
367*b3b94faaSDavid Teigland 
368*b3b94faaSDavid Teigland static struct attribute *counters_attrs[] = {
369*b3b94faaSDavid Teigland 	&counters_attr_glock_count.attr,
370*b3b94faaSDavid Teigland 	&counters_attr_glock_held_count.attr,
371*b3b94faaSDavid Teigland 	&counters_attr_inode_count.attr,
372*b3b94faaSDavid Teigland 	&counters_attr_bufdata_count.attr,
373*b3b94faaSDavid Teigland 	&counters_attr_unlinked_count.attr,
374*b3b94faaSDavid Teigland 	&counters_attr_quota_count.attr,
375*b3b94faaSDavid Teigland 	&counters_attr_log_num_gl.attr,
376*b3b94faaSDavid Teigland 	&counters_attr_log_num_buf.attr,
377*b3b94faaSDavid Teigland 	&counters_attr_log_num_revoke.attr,
378*b3b94faaSDavid Teigland 	&counters_attr_log_num_rg.attr,
379*b3b94faaSDavid Teigland 	&counters_attr_log_num_databuf.attr,
380*b3b94faaSDavid Teigland 	&counters_attr_log_blks_free.attr,
381*b3b94faaSDavid Teigland 	&counters_attr_jd_blocks.attr,
382*b3b94faaSDavid Teigland 	&counters_attr_reclaim_count.attr,
383*b3b94faaSDavid Teigland 	&counters_attr_log_wraps.attr,
384*b3b94faaSDavid Teigland 	&counters_attr_fh2dentry_misses.attr,
385*b3b94faaSDavid Teigland 	&counters_attr_reclaimed.attr,
386*b3b94faaSDavid Teigland 	&counters_attr_log_flush_incore.attr,
387*b3b94faaSDavid Teigland 	&counters_attr_log_flush_ondisk.attr,
388*b3b94faaSDavid Teigland 	&counters_attr_glock_nq_calls.attr,
389*b3b94faaSDavid Teigland 	&counters_attr_glock_dq_calls.attr,
390*b3b94faaSDavid Teigland 	&counters_attr_glock_prefetch_calls.attr,
391*b3b94faaSDavid Teigland 	&counters_attr_lm_lock_calls.attr,
392*b3b94faaSDavid Teigland 	&counters_attr_lm_unlock_calls.attr,
393*b3b94faaSDavid Teigland 	&counters_attr_lm_callbacks.attr,
394*b3b94faaSDavid Teigland 	&counters_attr_ops_address.attr,
395*b3b94faaSDavid Teigland 	&counters_attr_ops_dentry.attr,
396*b3b94faaSDavid Teigland 	&counters_attr_ops_export.attr,
397*b3b94faaSDavid Teigland 	&counters_attr_ops_file.attr,
398*b3b94faaSDavid Teigland 	&counters_attr_ops_inode.attr,
399*b3b94faaSDavid Teigland 	&counters_attr_ops_super.attr,
400*b3b94faaSDavid Teigland 	&counters_attr_ops_vm.attr,
401*b3b94faaSDavid Teigland 	NULL
402*b3b94faaSDavid Teigland };
403*b3b94faaSDavid Teigland 
404*b3b94faaSDavid Teigland /*
405*b3b94faaSDavid Teigland  * get and set struct gfs2_tune fields
406*b3b94faaSDavid Teigland  */
407*b3b94faaSDavid Teigland 
408*b3b94faaSDavid Teigland static ssize_t quota_scale_show(struct gfs2_sbd *sdp, char *buf)
409*b3b94faaSDavid Teigland {
410*b3b94faaSDavid Teigland 	return sprintf(buf, "%u %u\n", sdp->sd_tune.gt_quota_scale_num,
411*b3b94faaSDavid Teigland 				       sdp->sd_tune.gt_quota_scale_den);
412*b3b94faaSDavid Teigland }
413*b3b94faaSDavid Teigland 
414*b3b94faaSDavid Teigland static ssize_t quota_scale_store(struct gfs2_sbd *sdp, const char *buf,
415*b3b94faaSDavid Teigland 				 size_t len)
416*b3b94faaSDavid Teigland {
417*b3b94faaSDavid Teigland 	struct gfs2_tune *gt = &sdp->sd_tune;
418*b3b94faaSDavid Teigland 	unsigned int x, y;
419*b3b94faaSDavid Teigland 
420*b3b94faaSDavid Teigland 	if (!capable(CAP_SYS_ADMIN))
421*b3b94faaSDavid Teigland 		return -EACCES;
422*b3b94faaSDavid Teigland 
423*b3b94faaSDavid Teigland 	if (sscanf(buf, "%u %u", &x, &y) != 2 || !y)
424*b3b94faaSDavid Teigland 		return -EINVAL;
425*b3b94faaSDavid Teigland 
426*b3b94faaSDavid Teigland 	spin_lock(&gt->gt_spin);
427*b3b94faaSDavid Teigland 	gt->gt_quota_scale_num = x;
428*b3b94faaSDavid Teigland 	gt->gt_quota_scale_den = y;
429*b3b94faaSDavid Teigland 	spin_unlock(&gt->gt_spin);
430*b3b94faaSDavid Teigland 	return len;
431*b3b94faaSDavid Teigland }
432*b3b94faaSDavid Teigland 
433*b3b94faaSDavid Teigland static ssize_t tune_set(struct gfs2_sbd *sdp, unsigned int *field,
434*b3b94faaSDavid Teigland 			int check_zero, const char *buf, size_t len)
435*b3b94faaSDavid Teigland {
436*b3b94faaSDavid Teigland 	struct gfs2_tune *gt = &sdp->sd_tune;
437*b3b94faaSDavid Teigland 	unsigned int x;
438*b3b94faaSDavid Teigland 
439*b3b94faaSDavid Teigland 	if (!capable(CAP_SYS_ADMIN))
440*b3b94faaSDavid Teigland 		return -EACCES;
441*b3b94faaSDavid Teigland 
442*b3b94faaSDavid Teigland 	x = simple_strtoul(buf, NULL, 0);
443*b3b94faaSDavid Teigland 
444*b3b94faaSDavid Teigland 	if (check_zero && !x)
445*b3b94faaSDavid Teigland 		return -EINVAL;
446*b3b94faaSDavid Teigland 
447*b3b94faaSDavid Teigland 	spin_lock(&gt->gt_spin);
448*b3b94faaSDavid Teigland 	*field = x;
449*b3b94faaSDavid Teigland 	spin_unlock(&gt->gt_spin);
450*b3b94faaSDavid Teigland 	return len;
451*b3b94faaSDavid Teigland }
452*b3b94faaSDavid Teigland 
453*b3b94faaSDavid Teigland struct tune_attr {
454*b3b94faaSDavid Teigland 	struct attribute attr;
455*b3b94faaSDavid Teigland 	ssize_t (*show)(struct gfs2_sbd *, char *);
456*b3b94faaSDavid Teigland 	ssize_t (*store)(struct gfs2_sbd *, const char *, size_t);
457*b3b94faaSDavid Teigland };
458*b3b94faaSDavid Teigland 
459*b3b94faaSDavid Teigland #define TUNE_ATTR_3(name, show, store)                                        \
460*b3b94faaSDavid Teigland static struct tune_attr tune_attr_##name = __ATTR(name, 0644, show, store)
461*b3b94faaSDavid Teigland 
462*b3b94faaSDavid Teigland #define TUNE_ATTR_2(name, store)                                              \
463*b3b94faaSDavid Teigland static ssize_t name##_show(struct gfs2_sbd *sdp, char *buf)                   \
464*b3b94faaSDavid Teigland {                                                                             \
465*b3b94faaSDavid Teigland 	return sprintf(buf, "%u\n", sdp->sd_tune.gt_##name);                  \
466*b3b94faaSDavid Teigland }                                                                             \
467*b3b94faaSDavid Teigland TUNE_ATTR_3(name, name##_show, store)
468*b3b94faaSDavid Teigland 
469*b3b94faaSDavid Teigland #define TUNE_ATTR(name, check_zero)                                           \
470*b3b94faaSDavid Teigland static ssize_t name##_store(struct gfs2_sbd *sdp, const char *buf, size_t len)\
471*b3b94faaSDavid Teigland {                                                                             \
472*b3b94faaSDavid Teigland 	return tune_set(sdp, &sdp->sd_tune.gt_##name, check_zero, buf, len);  \
473*b3b94faaSDavid Teigland }                                                                             \
474*b3b94faaSDavid Teigland TUNE_ATTR_2(name, name##_store)
475*b3b94faaSDavid Teigland 
476*b3b94faaSDavid Teigland #define TUNE_ATTR_DAEMON(name, process)                                       \
477*b3b94faaSDavid Teigland static ssize_t name##_store(struct gfs2_sbd *sdp, const char *buf, size_t len)\
478*b3b94faaSDavid Teigland {                                                                             \
479*b3b94faaSDavid Teigland 	ssize_t r = tune_set(sdp, &sdp->sd_tune.gt_##name, 1, buf, len);      \
480*b3b94faaSDavid Teigland 	wake_up_process(sdp->sd_##process);                                   \
481*b3b94faaSDavid Teigland 	return r;                                                             \
482*b3b94faaSDavid Teigland }                                                                             \
483*b3b94faaSDavid Teigland TUNE_ATTR_2(name, name##_store)
484*b3b94faaSDavid Teigland 
485*b3b94faaSDavid Teigland TUNE_ATTR(ilimit, 0);
486*b3b94faaSDavid Teigland TUNE_ATTR(ilimit_tries, 0);
487*b3b94faaSDavid Teigland TUNE_ATTR(ilimit_min, 0);
488*b3b94faaSDavid Teigland TUNE_ATTR(demote_secs, 0);
489*b3b94faaSDavid Teigland TUNE_ATTR(incore_log_blocks, 0);
490*b3b94faaSDavid Teigland TUNE_ATTR(log_flush_secs, 0);
491*b3b94faaSDavid Teigland TUNE_ATTR(jindex_refresh_secs, 0);
492*b3b94faaSDavid Teigland TUNE_ATTR(quota_warn_period, 0);
493*b3b94faaSDavid Teigland TUNE_ATTR(quota_quantum, 0);
494*b3b94faaSDavid Teigland TUNE_ATTR(atime_quantum, 0);
495*b3b94faaSDavid Teigland TUNE_ATTR(max_readahead, 0);
496*b3b94faaSDavid Teigland TUNE_ATTR(complain_secs, 0);
497*b3b94faaSDavid Teigland TUNE_ATTR(reclaim_limit, 0);
498*b3b94faaSDavid Teigland TUNE_ATTR(prefetch_secs, 0);
499*b3b94faaSDavid Teigland TUNE_ATTR(statfs_slow, 0);
500*b3b94faaSDavid Teigland TUNE_ATTR(new_files_jdata, 0);
501*b3b94faaSDavid Teigland TUNE_ATTR(new_files_directio, 0);
502*b3b94faaSDavid Teigland TUNE_ATTR(quota_simul_sync, 1);
503*b3b94faaSDavid Teigland TUNE_ATTR(quota_cache_secs, 1);
504*b3b94faaSDavid Teigland TUNE_ATTR(max_atomic_write, 1);
505*b3b94faaSDavid Teigland TUNE_ATTR(stall_secs, 1);
506*b3b94faaSDavid Teigland TUNE_ATTR(entries_per_readdir, 1);
507*b3b94faaSDavid Teigland TUNE_ATTR(greedy_default, 1);
508*b3b94faaSDavid Teigland TUNE_ATTR(greedy_quantum, 1);
509*b3b94faaSDavid Teigland TUNE_ATTR(greedy_max, 1);
510*b3b94faaSDavid Teigland TUNE_ATTR(statfs_quantum, 1);
511*b3b94faaSDavid Teigland TUNE_ATTR_DAEMON(scand_secs, scand_process);
512*b3b94faaSDavid Teigland TUNE_ATTR_DAEMON(recoverd_secs, recoverd_process);
513*b3b94faaSDavid Teigland TUNE_ATTR_DAEMON(logd_secs, logd_process);
514*b3b94faaSDavid Teigland TUNE_ATTR_DAEMON(quotad_secs, quotad_process);
515*b3b94faaSDavid Teigland TUNE_ATTR_DAEMON(inoded_secs, inoded_process);
516*b3b94faaSDavid Teigland TUNE_ATTR_3(quota_scale, quota_scale_show, quota_scale_store);
517*b3b94faaSDavid Teigland 
518*b3b94faaSDavid Teigland static struct attribute *tune_attrs[] = {
519*b3b94faaSDavid Teigland 	&tune_attr_ilimit.attr,
520*b3b94faaSDavid Teigland 	&tune_attr_ilimit_tries.attr,
521*b3b94faaSDavid Teigland 	&tune_attr_ilimit_min.attr,
522*b3b94faaSDavid Teigland 	&tune_attr_demote_secs.attr,
523*b3b94faaSDavid Teigland 	&tune_attr_incore_log_blocks.attr,
524*b3b94faaSDavid Teigland 	&tune_attr_log_flush_secs.attr,
525*b3b94faaSDavid Teigland 	&tune_attr_jindex_refresh_secs.attr,
526*b3b94faaSDavid Teigland 	&tune_attr_quota_warn_period.attr,
527*b3b94faaSDavid Teigland 	&tune_attr_quota_quantum.attr,
528*b3b94faaSDavid Teigland 	&tune_attr_atime_quantum.attr,
529*b3b94faaSDavid Teigland 	&tune_attr_max_readahead.attr,
530*b3b94faaSDavid Teigland 	&tune_attr_complain_secs.attr,
531*b3b94faaSDavid Teigland 	&tune_attr_reclaim_limit.attr,
532*b3b94faaSDavid Teigland 	&tune_attr_prefetch_secs.attr,
533*b3b94faaSDavid Teigland 	&tune_attr_statfs_slow.attr,
534*b3b94faaSDavid Teigland 	&tune_attr_quota_simul_sync.attr,
535*b3b94faaSDavid Teigland 	&tune_attr_quota_cache_secs.attr,
536*b3b94faaSDavid Teigland 	&tune_attr_max_atomic_write.attr,
537*b3b94faaSDavid Teigland 	&tune_attr_stall_secs.attr,
538*b3b94faaSDavid Teigland 	&tune_attr_entries_per_readdir.attr,
539*b3b94faaSDavid Teigland 	&tune_attr_greedy_default.attr,
540*b3b94faaSDavid Teigland 	&tune_attr_greedy_quantum.attr,
541*b3b94faaSDavid Teigland 	&tune_attr_greedy_max.attr,
542*b3b94faaSDavid Teigland 	&tune_attr_statfs_quantum.attr,
543*b3b94faaSDavid Teigland 	&tune_attr_scand_secs.attr,
544*b3b94faaSDavid Teigland 	&tune_attr_recoverd_secs.attr,
545*b3b94faaSDavid Teigland 	&tune_attr_logd_secs.attr,
546*b3b94faaSDavid Teigland 	&tune_attr_quotad_secs.attr,
547*b3b94faaSDavid Teigland 	&tune_attr_inoded_secs.attr,
548*b3b94faaSDavid Teigland 	&tune_attr_quota_scale.attr,
549*b3b94faaSDavid Teigland 	&tune_attr_new_files_jdata.attr,
550*b3b94faaSDavid Teigland 	&tune_attr_new_files_directio.attr,
551*b3b94faaSDavid Teigland 	NULL
552*b3b94faaSDavid Teigland };
553*b3b94faaSDavid Teigland 
554*b3b94faaSDavid Teigland static struct attribute_group lockstruct_group = {
555*b3b94faaSDavid Teigland 	.name = "lockstruct",
556*b3b94faaSDavid Teigland 	.attrs = lockstruct_attrs
557*b3b94faaSDavid Teigland };
558*b3b94faaSDavid Teigland 
559*b3b94faaSDavid Teigland static struct attribute_group counters_group = {
560*b3b94faaSDavid Teigland 	.name = "counters",
561*b3b94faaSDavid Teigland 	.attrs = counters_attrs
562*b3b94faaSDavid Teigland };
563*b3b94faaSDavid Teigland 
564*b3b94faaSDavid Teigland static struct attribute_group args_group = {
565*b3b94faaSDavid Teigland 	.name = "args",
566*b3b94faaSDavid Teigland 	.attrs = args_attrs
567*b3b94faaSDavid Teigland };
568*b3b94faaSDavid Teigland 
569*b3b94faaSDavid Teigland static struct attribute_group tune_group = {
570*b3b94faaSDavid Teigland 	.name = "tune",
571*b3b94faaSDavid Teigland 	.attrs = tune_attrs
572*b3b94faaSDavid Teigland };
573*b3b94faaSDavid Teigland 
574*b3b94faaSDavid Teigland int gfs2_sys_fs_add(struct gfs2_sbd *sdp)
575*b3b94faaSDavid Teigland {
576*b3b94faaSDavid Teigland 	int error;
577*b3b94faaSDavid Teigland 
578*b3b94faaSDavid Teigland 	sdp->sd_kobj.kset = &gfs2_kset;
579*b3b94faaSDavid Teigland 	sdp->sd_kobj.ktype = &gfs2_ktype;
580*b3b94faaSDavid Teigland 
581*b3b94faaSDavid Teigland 	error = kobject_set_name(&sdp->sd_kobj, "%s", sdp->sd_table_name);
582*b3b94faaSDavid Teigland 	if (error)
583*b3b94faaSDavid Teigland 		goto fail;
584*b3b94faaSDavid Teigland 
585*b3b94faaSDavid Teigland 	error = kobject_register(&sdp->sd_kobj);
586*b3b94faaSDavid Teigland 	if (error)
587*b3b94faaSDavid Teigland 		goto fail;
588*b3b94faaSDavid Teigland 
589*b3b94faaSDavid Teigland 	error = sysfs_create_group(&sdp->sd_kobj, &lockstruct_group);
590*b3b94faaSDavid Teigland 	if (error)
591*b3b94faaSDavid Teigland 		goto fail_reg;
592*b3b94faaSDavid Teigland 
593*b3b94faaSDavid Teigland 	error = sysfs_create_group(&sdp->sd_kobj, &counters_group);
594*b3b94faaSDavid Teigland 	if (error)
595*b3b94faaSDavid Teigland 		goto fail_lockstruct;
596*b3b94faaSDavid Teigland 
597*b3b94faaSDavid Teigland 	error = sysfs_create_group(&sdp->sd_kobj, &args_group);
598*b3b94faaSDavid Teigland 	if (error)
599*b3b94faaSDavid Teigland 		goto fail_counters;
600*b3b94faaSDavid Teigland 
601*b3b94faaSDavid Teigland 	error = sysfs_create_group(&sdp->sd_kobj, &tune_group);
602*b3b94faaSDavid Teigland 	if (error)
603*b3b94faaSDavid Teigland 		goto fail_args;
604*b3b94faaSDavid Teigland 
605*b3b94faaSDavid Teigland 	return 0;
606*b3b94faaSDavid Teigland 
607*b3b94faaSDavid Teigland  fail_args:
608*b3b94faaSDavid Teigland 	sysfs_remove_group(&sdp->sd_kobj, &args_group);
609*b3b94faaSDavid Teigland  fail_counters:
610*b3b94faaSDavid Teigland 	sysfs_remove_group(&sdp->sd_kobj, &counters_group);
611*b3b94faaSDavid Teigland  fail_lockstruct:
612*b3b94faaSDavid Teigland 	sysfs_remove_group(&sdp->sd_kobj, &lockstruct_group);
613*b3b94faaSDavid Teigland  fail_reg:
614*b3b94faaSDavid Teigland 	kobject_unregister(&sdp->sd_kobj);
615*b3b94faaSDavid Teigland  fail:
616*b3b94faaSDavid Teigland 	return error;
617*b3b94faaSDavid Teigland }
618*b3b94faaSDavid Teigland 
619*b3b94faaSDavid Teigland void gfs2_sys_fs_del(struct gfs2_sbd *sdp)
620*b3b94faaSDavid Teigland {
621*b3b94faaSDavid Teigland 	sysfs_remove_group(&sdp->sd_kobj, &tune_group);
622*b3b94faaSDavid Teigland 	sysfs_remove_group(&sdp->sd_kobj, &args_group);
623*b3b94faaSDavid Teigland 	sysfs_remove_group(&sdp->sd_kobj, &counters_group);
624*b3b94faaSDavid Teigland 	sysfs_remove_group(&sdp->sd_kobj, &lockstruct_group);
625*b3b94faaSDavid Teigland 	kobject_unregister(&sdp->sd_kobj);
626*b3b94faaSDavid Teigland }
627*b3b94faaSDavid Teigland 
628*b3b94faaSDavid Teigland int gfs2_sys_init(void)
629*b3b94faaSDavid Teigland {
630*b3b94faaSDavid Teigland 	gfs2_sys_margs = NULL;
631*b3b94faaSDavid Teigland 	spin_lock_init(&gfs2_sys_margs_lock);
632*b3b94faaSDavid Teigland 	return kset_register(&gfs2_kset);
633*b3b94faaSDavid Teigland }
634*b3b94faaSDavid Teigland 
635*b3b94faaSDavid Teigland void gfs2_sys_uninit(void)
636*b3b94faaSDavid Teigland {
637*b3b94faaSDavid Teigland 	kfree(gfs2_sys_margs);
638*b3b94faaSDavid Teigland 	kset_unregister(&gfs2_kset);
639*b3b94faaSDavid Teigland }
640*b3b94faaSDavid Teigland 
641