xref: /linux/fs/gfs2/sys.c (revision 97cc1025b1a91c52e84f12478dcf0f853abc6564)
1b3b94faaSDavid Teigland /*
2b3b94faaSDavid Teigland  * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
33a8a9a10SSteven Whitehouse  * Copyright (C) 2004-2006 Red Hat, Inc.  All rights reserved.
4b3b94faaSDavid Teigland  *
5b3b94faaSDavid Teigland  * This copyrighted material is made available to anyone wishing to use,
6b3b94faaSDavid Teigland  * modify, copy, or redistribute it subject to the terms and conditions
7e9fc2aa0SSteven Whitehouse  * of the GNU General Public License version 2.
8b3b94faaSDavid Teigland  */
9b3b94faaSDavid Teigland 
10b3b94faaSDavid Teigland #include <linux/sched.h>
11b3b94faaSDavid Teigland #include <linux/slab.h>
12b3b94faaSDavid Teigland #include <linux/spinlock.h>
13b3b94faaSDavid Teigland #include <linux/completion.h>
14b3b94faaSDavid Teigland #include <linux/buffer_head.h>
15b3b94faaSDavid Teigland #include <linux/module.h>
16b3b94faaSDavid Teigland #include <linux/kobject.h>
175c676f6dSSteven Whitehouse #include <linux/gfs2_ondisk.h>
187d308590SFabio Massimo Di Nitto #include <linux/lm_interface.h>
19b3b94faaSDavid Teigland #include <asm/uaccess.h>
20b3b94faaSDavid Teigland 
21b3b94faaSDavid Teigland #include "gfs2.h"
225c676f6dSSteven Whitehouse #include "incore.h"
23b3b94faaSDavid Teigland #include "sys.h"
24b3b94faaSDavid Teigland #include "super.h"
25b3b94faaSDavid Teigland #include "glock.h"
26b3b94faaSDavid Teigland #include "quota.h"
275c676f6dSSteven Whitehouse #include "util.h"
28b3b94faaSDavid Teigland 
29b3b94faaSDavid Teigland char *gfs2_sys_margs;
30b3b94faaSDavid Teigland spinlock_t gfs2_sys_margs_lock;
31b3b94faaSDavid Teigland 
32b3b94faaSDavid Teigland static ssize_t id_show(struct gfs2_sbd *sdp, char *buf)
33b3b94faaSDavid Teigland {
34c7227e46SBob Peterson 	return snprintf(buf, PAGE_SIZE, "%u:%u\n",
35c7227e46SBob Peterson 			MAJOR(sdp->sd_vfs->s_dev), MINOR(sdp->sd_vfs->s_dev));
36b3b94faaSDavid Teigland }
37b3b94faaSDavid Teigland 
38b3b94faaSDavid Teigland static ssize_t fsname_show(struct gfs2_sbd *sdp, char *buf)
39b3b94faaSDavid Teigland {
403204a6c0SDavid Teigland 	return snprintf(buf, PAGE_SIZE, "%s\n", sdp->sd_fsname);
41b3b94faaSDavid Teigland }
42b3b94faaSDavid Teigland 
43b3b94faaSDavid Teigland static ssize_t freeze_show(struct gfs2_sbd *sdp, char *buf)
44b3b94faaSDavid Teigland {
45b3b94faaSDavid Teigland 	unsigned int count;
46b3b94faaSDavid Teigland 
47f55ab26aSSteven Whitehouse 	mutex_lock(&sdp->sd_freeze_lock);
48b3b94faaSDavid Teigland 	count = sdp->sd_freeze_count;
49f55ab26aSSteven Whitehouse 	mutex_unlock(&sdp->sd_freeze_lock);
50b3b94faaSDavid Teigland 
513204a6c0SDavid Teigland 	return snprintf(buf, PAGE_SIZE, "%u\n", count);
52b3b94faaSDavid Teigland }
53b3b94faaSDavid Teigland 
54b3b94faaSDavid Teigland static ssize_t freeze_store(struct gfs2_sbd *sdp, const char *buf, size_t len)
55b3b94faaSDavid Teigland {
56b3b94faaSDavid Teigland 	ssize_t ret = len;
57b3b94faaSDavid Teigland 	int error = 0;
58b3b94faaSDavid Teigland 	int n = simple_strtol(buf, NULL, 0);
59b3b94faaSDavid Teigland 
60b3b94faaSDavid Teigland 	if (!capable(CAP_SYS_ADMIN))
61b3b94faaSDavid Teigland 		return -EACCES;
62b3b94faaSDavid Teigland 
63b3b94faaSDavid Teigland 	switch (n) {
64b3b94faaSDavid Teigland 	case 0:
65b3b94faaSDavid Teigland 		gfs2_unfreeze_fs(sdp);
66b3b94faaSDavid Teigland 		break;
67b3b94faaSDavid Teigland 	case 1:
68b3b94faaSDavid Teigland 		error = gfs2_freeze_fs(sdp);
69b3b94faaSDavid Teigland 		break;
70b3b94faaSDavid Teigland 	default:
71b3b94faaSDavid Teigland 		ret = -EINVAL;
72b3b94faaSDavid Teigland 	}
73b3b94faaSDavid Teigland 
74b3b94faaSDavid Teigland 	if (error)
75b3b94faaSDavid Teigland 		fs_warn(sdp, "freeze %d error %d", n, error);
76b3b94faaSDavid Teigland 
77b3b94faaSDavid Teigland 	return ret;
78b3b94faaSDavid Teigland }
79b3b94faaSDavid Teigland 
80b3b94faaSDavid Teigland static ssize_t withdraw_show(struct gfs2_sbd *sdp, char *buf)
81b3b94faaSDavid Teigland {
82b3b94faaSDavid Teigland 	unsigned int b = test_bit(SDF_SHUTDOWN, &sdp->sd_flags);
833204a6c0SDavid Teigland 	return snprintf(buf, PAGE_SIZE, "%u\n", b);
84b3b94faaSDavid Teigland }
85b3b94faaSDavid Teigland 
86b3b94faaSDavid Teigland static ssize_t withdraw_store(struct gfs2_sbd *sdp, const char *buf, size_t len)
87b3b94faaSDavid Teigland {
88b3b94faaSDavid Teigland 	if (!capable(CAP_SYS_ADMIN))
89b3b94faaSDavid Teigland 		return -EACCES;
90b3b94faaSDavid Teigland 
91b3b94faaSDavid Teigland 	if (simple_strtol(buf, NULL, 0) != 1)
92b3b94faaSDavid Teigland 		return -EINVAL;
93b3b94faaSDavid Teigland 
94b3b94faaSDavid Teigland 	gfs2_lm_withdraw(sdp,
95b3b94faaSDavid Teigland 		"GFS2: fsid=%s: withdrawing from cluster at user's request\n",
96b3b94faaSDavid Teigland 		sdp->sd_fsname);
97b3b94faaSDavid Teigland 	return len;
98b3b94faaSDavid Teigland }
99b3b94faaSDavid Teigland 
100b3b94faaSDavid Teigland static ssize_t statfs_sync_store(struct gfs2_sbd *sdp, const char *buf,
101b3b94faaSDavid Teigland 				 size_t len)
102b3b94faaSDavid Teigland {
103b3b94faaSDavid Teigland 	if (!capable(CAP_SYS_ADMIN))
104b3b94faaSDavid Teigland 		return -EACCES;
105b3b94faaSDavid Teigland 
106b3b94faaSDavid Teigland 	if (simple_strtol(buf, NULL, 0) != 1)
107b3b94faaSDavid Teigland 		return -EINVAL;
108b3b94faaSDavid Teigland 
109b3b94faaSDavid Teigland 	gfs2_statfs_sync(sdp);
110b3b94faaSDavid Teigland 	return len;
111b3b94faaSDavid Teigland }
112b3b94faaSDavid Teigland 
113b3b94faaSDavid Teigland static ssize_t quota_sync_store(struct gfs2_sbd *sdp, const char *buf,
114b3b94faaSDavid Teigland 				size_t len)
115b3b94faaSDavid Teigland {
116b3b94faaSDavid Teigland 	if (!capable(CAP_SYS_ADMIN))
117b3b94faaSDavid Teigland 		return -EACCES;
118b3b94faaSDavid Teigland 
119b3b94faaSDavid Teigland 	if (simple_strtol(buf, NULL, 0) != 1)
120b3b94faaSDavid Teigland 		return -EINVAL;
121b3b94faaSDavid Teigland 
122b3b94faaSDavid Teigland 	gfs2_quota_sync(sdp);
123b3b94faaSDavid Teigland 	return len;
124b3b94faaSDavid Teigland }
125b3b94faaSDavid Teigland 
126b3b94faaSDavid Teigland static ssize_t quota_refresh_user_store(struct gfs2_sbd *sdp, const char *buf,
127b3b94faaSDavid Teigland 					size_t len)
128b3b94faaSDavid Teigland {
129cd915493SSteven Whitehouse 	u32 id;
130b3b94faaSDavid Teigland 
131b3b94faaSDavid Teigland 	if (!capable(CAP_SYS_ADMIN))
132b3b94faaSDavid Teigland 		return -EACCES;
133b3b94faaSDavid Teigland 
134b3b94faaSDavid Teigland 	id = simple_strtoul(buf, NULL, 0);
135b3b94faaSDavid Teigland 
136b3b94faaSDavid Teigland 	gfs2_quota_refresh(sdp, 1, id);
137b3b94faaSDavid Teigland 	return len;
138b3b94faaSDavid Teigland }
139b3b94faaSDavid Teigland 
140b3b94faaSDavid Teigland static ssize_t quota_refresh_group_store(struct gfs2_sbd *sdp, const char *buf,
141b3b94faaSDavid Teigland 					 size_t len)
142b3b94faaSDavid Teigland {
143cd915493SSteven Whitehouse 	u32 id;
144b3b94faaSDavid Teigland 
145b3b94faaSDavid Teigland 	if (!capable(CAP_SYS_ADMIN))
146b3b94faaSDavid Teigland 		return -EACCES;
147b3b94faaSDavid Teigland 
148b3b94faaSDavid Teigland 	id = simple_strtoul(buf, NULL, 0);
149b3b94faaSDavid Teigland 
150b3b94faaSDavid Teigland 	gfs2_quota_refresh(sdp, 0, id);
151b3b94faaSDavid Teigland 	return len;
152b3b94faaSDavid Teigland }
153b3b94faaSDavid Teigland 
154b3b94faaSDavid Teigland struct gfs2_attr {
155b3b94faaSDavid Teigland 	struct attribute attr;
156b3b94faaSDavid Teigland 	ssize_t (*show)(struct gfs2_sbd *, char *);
157b3b94faaSDavid Teigland 	ssize_t (*store)(struct gfs2_sbd *, const char *, size_t);
158b3b94faaSDavid Teigland };
159b3b94faaSDavid Teigland 
160b3b94faaSDavid Teigland #define GFS2_ATTR(name, mode, show, store) \
161b3b94faaSDavid Teigland static struct gfs2_attr gfs2_attr_##name = __ATTR(name, mode, show, store)
162b3b94faaSDavid Teigland 
163b3b94faaSDavid Teigland GFS2_ATTR(id,                  0444, id_show,       NULL);
164b3b94faaSDavid Teigland GFS2_ATTR(fsname,              0444, fsname_show,   NULL);
165b3b94faaSDavid Teigland GFS2_ATTR(freeze,              0644, freeze_show,   freeze_store);
166b3b94faaSDavid Teigland GFS2_ATTR(withdraw,            0644, withdraw_show, withdraw_store);
167b3b94faaSDavid Teigland GFS2_ATTR(statfs_sync,         0200, NULL,          statfs_sync_store);
168b3b94faaSDavid Teigland GFS2_ATTR(quota_sync,          0200, NULL,          quota_sync_store);
169b3b94faaSDavid Teigland GFS2_ATTR(quota_refresh_user,  0200, NULL,          quota_refresh_user_store);
170b3b94faaSDavid Teigland GFS2_ATTR(quota_refresh_group, 0200, NULL,          quota_refresh_group_store);
171b3b94faaSDavid Teigland 
172b3b94faaSDavid Teigland static struct attribute *gfs2_attrs[] = {
173b3b94faaSDavid Teigland 	&gfs2_attr_id.attr,
174b3b94faaSDavid Teigland 	&gfs2_attr_fsname.attr,
175b3b94faaSDavid Teigland 	&gfs2_attr_freeze.attr,
176b3b94faaSDavid Teigland 	&gfs2_attr_withdraw.attr,
177b3b94faaSDavid Teigland 	&gfs2_attr_statfs_sync.attr,
178b3b94faaSDavid Teigland 	&gfs2_attr_quota_sync.attr,
179b3b94faaSDavid Teigland 	&gfs2_attr_quota_refresh_user.attr,
180b3b94faaSDavid Teigland 	&gfs2_attr_quota_refresh_group.attr,
181b3b94faaSDavid Teigland 	NULL,
182b3b94faaSDavid Teigland };
183b3b94faaSDavid Teigland 
184b3b94faaSDavid Teigland static ssize_t gfs2_attr_show(struct kobject *kobj, struct attribute *attr,
185b3b94faaSDavid Teigland 			      char *buf)
186b3b94faaSDavid Teigland {
187b3b94faaSDavid Teigland 	struct gfs2_sbd *sdp = container_of(kobj, struct gfs2_sbd, sd_kobj);
188b3b94faaSDavid Teigland 	struct gfs2_attr *a = container_of(attr, struct gfs2_attr, attr);
189b3b94faaSDavid Teigland 	return a->show ? a->show(sdp, buf) : 0;
190b3b94faaSDavid Teigland }
191b3b94faaSDavid Teigland 
192b3b94faaSDavid Teigland static ssize_t gfs2_attr_store(struct kobject *kobj, struct attribute *attr,
193b3b94faaSDavid Teigland 			       const char *buf, size_t len)
194b3b94faaSDavid Teigland {
195b3b94faaSDavid Teigland 	struct gfs2_sbd *sdp = container_of(kobj, struct gfs2_sbd, sd_kobj);
196b3b94faaSDavid Teigland 	struct gfs2_attr *a = container_of(attr, struct gfs2_attr, attr);
197b3b94faaSDavid Teigland 	return a->store ? a->store(sdp, buf, len) : len;
198b3b94faaSDavid Teigland }
199b3b94faaSDavid Teigland 
200b3b94faaSDavid Teigland static struct sysfs_ops gfs2_attr_ops = {
201b3b94faaSDavid Teigland 	.show  = gfs2_attr_show,
202b3b94faaSDavid Teigland 	.store = gfs2_attr_store,
203b3b94faaSDavid Teigland };
204b3b94faaSDavid Teigland 
205b3b94faaSDavid Teigland static struct kobj_type gfs2_ktype = {
206b3b94faaSDavid Teigland 	.default_attrs = gfs2_attrs,
207b3b94faaSDavid Teigland 	.sysfs_ops     = &gfs2_attr_ops,
208b3b94faaSDavid Teigland };
209b3b94faaSDavid Teigland 
2109bec101aSGreg Kroah-Hartman static struct kset *gfs2_kset;
211b3b94faaSDavid Teigland 
212b3b94faaSDavid Teigland /*
213b3b94faaSDavid Teigland  * display struct lm_lockstruct fields
214b3b94faaSDavid Teigland  */
215b3b94faaSDavid Teigland 
216b3b94faaSDavid Teigland struct lockstruct_attr {
217b3b94faaSDavid Teigland 	struct attribute attr;
218b3b94faaSDavid Teigland 	ssize_t (*show)(struct gfs2_sbd *, char *);
219b3b94faaSDavid Teigland };
220b3b94faaSDavid Teigland 
221b3b94faaSDavid Teigland #define LOCKSTRUCT_ATTR(name, fmt)                                          \
222b3b94faaSDavid Teigland static ssize_t name##_show(struct gfs2_sbd *sdp, char *buf)                 \
223b3b94faaSDavid Teigland {                                                                           \
2243204a6c0SDavid Teigland 	return snprintf(buf, PAGE_SIZE, fmt, sdp->sd_lockstruct.ls_##name); \
225b3b94faaSDavid Teigland }                                                                           \
226b3b94faaSDavid Teigland static struct lockstruct_attr lockstruct_attr_##name = __ATTR_RO(name)
227b3b94faaSDavid Teigland 
228b3b94faaSDavid Teigland LOCKSTRUCT_ATTR(jid,      "%u\n");
229b3b94faaSDavid Teigland LOCKSTRUCT_ATTR(first,    "%u\n");
230b3b94faaSDavid Teigland LOCKSTRUCT_ATTR(lvb_size, "%u\n");
231b3b94faaSDavid Teigland LOCKSTRUCT_ATTR(flags,    "%d\n");
232b3b94faaSDavid Teigland 
233b3b94faaSDavid Teigland static struct attribute *lockstruct_attrs[] = {
234b3b94faaSDavid Teigland 	&lockstruct_attr_jid.attr,
235b3b94faaSDavid Teigland 	&lockstruct_attr_first.attr,
236b3b94faaSDavid Teigland 	&lockstruct_attr_lvb_size.attr,
237b3b94faaSDavid Teigland 	&lockstruct_attr_flags.attr,
238ea67eedbSSteven Whitehouse 	NULL,
239b3b94faaSDavid Teigland };
240b3b94faaSDavid Teigland 
241b3b94faaSDavid Teigland /*
242b3b94faaSDavid Teigland  * display struct gfs2_args fields
243b3b94faaSDavid Teigland  */
244b3b94faaSDavid Teigland 
245b3b94faaSDavid Teigland struct args_attr {
246b3b94faaSDavid Teigland 	struct attribute attr;
247b3b94faaSDavid Teigland 	ssize_t (*show)(struct gfs2_sbd *, char *);
248b3b94faaSDavid Teigland };
249b3b94faaSDavid Teigland 
250b3b94faaSDavid Teigland #define ARGS_ATTR(name, fmt)                                                \
251b3b94faaSDavid Teigland static ssize_t name##_show(struct gfs2_sbd *sdp, char *buf)                 \
252b3b94faaSDavid Teigland {                                                                           \
2533204a6c0SDavid Teigland 	return snprintf(buf, PAGE_SIZE, fmt, sdp->sd_args.ar_##name);       \
254b3b94faaSDavid Teigland }                                                                           \
255b3b94faaSDavid Teigland static struct args_attr args_attr_##name = __ATTR_RO(name)
256b3b94faaSDavid Teigland 
257b3b94faaSDavid Teigland ARGS_ATTR(lockproto,       "%s\n");
258b3b94faaSDavid Teigland ARGS_ATTR(locktable,       "%s\n");
259b3b94faaSDavid Teigland ARGS_ATTR(hostdata,        "%s\n");
260b3b94faaSDavid Teigland ARGS_ATTR(spectator,       "%d\n");
261b3b94faaSDavid Teigland ARGS_ATTR(ignore_local_fs, "%d\n");
262b3b94faaSDavid Teigland ARGS_ATTR(localcaching,    "%d\n");
263b3b94faaSDavid Teigland ARGS_ATTR(localflocks,     "%d\n");
264b3b94faaSDavid Teigland ARGS_ATTR(debug,           "%d\n");
265b3b94faaSDavid Teigland ARGS_ATTR(upgrade,         "%d\n");
266b3b94faaSDavid Teigland ARGS_ATTR(posix_acl,       "%d\n");
267b3b94faaSDavid Teigland ARGS_ATTR(quota,           "%u\n");
268b3b94faaSDavid Teigland ARGS_ATTR(suiddir,         "%d\n");
269b3b94faaSDavid Teigland ARGS_ATTR(data,            "%d\n");
270b3b94faaSDavid Teigland 
271b3b94faaSDavid Teigland static struct attribute *args_attrs[] = {
272b3b94faaSDavid Teigland 	&args_attr_lockproto.attr,
273b3b94faaSDavid Teigland 	&args_attr_locktable.attr,
274b3b94faaSDavid Teigland 	&args_attr_hostdata.attr,
275b3b94faaSDavid Teigland 	&args_attr_spectator.attr,
276b3b94faaSDavid Teigland 	&args_attr_ignore_local_fs.attr,
277b3b94faaSDavid Teigland 	&args_attr_localcaching.attr,
278b3b94faaSDavid Teigland 	&args_attr_localflocks.attr,
279b3b94faaSDavid Teigland 	&args_attr_debug.attr,
280b3b94faaSDavid Teigland 	&args_attr_upgrade.attr,
281b3b94faaSDavid Teigland 	&args_attr_posix_acl.attr,
282b3b94faaSDavid Teigland 	&args_attr_quota.attr,
283b3b94faaSDavid Teigland 	&args_attr_suiddir.attr,
284b3b94faaSDavid Teigland 	&args_attr_data.attr,
285ea67eedbSSteven Whitehouse 	NULL,
286b3b94faaSDavid Teigland };
287b3b94faaSDavid Teigland 
288b3b94faaSDavid Teigland /*
289b3b94faaSDavid Teigland  * get and set struct gfs2_tune fields
290b3b94faaSDavid Teigland  */
291b3b94faaSDavid Teigland 
292b3b94faaSDavid Teigland static ssize_t quota_scale_show(struct gfs2_sbd *sdp, char *buf)
293b3b94faaSDavid Teigland {
2943204a6c0SDavid Teigland 	return snprintf(buf, PAGE_SIZE, "%u %u\n",
2953204a6c0SDavid Teigland 			sdp->sd_tune.gt_quota_scale_num,
296b3b94faaSDavid Teigland 			sdp->sd_tune.gt_quota_scale_den);
297b3b94faaSDavid Teigland }
298b3b94faaSDavid Teigland 
299b3b94faaSDavid Teigland static ssize_t quota_scale_store(struct gfs2_sbd *sdp, const char *buf,
300b3b94faaSDavid Teigland 				 size_t len)
301b3b94faaSDavid Teigland {
302b3b94faaSDavid Teigland 	struct gfs2_tune *gt = &sdp->sd_tune;
303b3b94faaSDavid Teigland 	unsigned int x, y;
304b3b94faaSDavid Teigland 
305b3b94faaSDavid Teigland 	if (!capable(CAP_SYS_ADMIN))
306b3b94faaSDavid Teigland 		return -EACCES;
307b3b94faaSDavid Teigland 
308b3b94faaSDavid Teigland 	if (sscanf(buf, "%u %u", &x, &y) != 2 || !y)
309b3b94faaSDavid Teigland 		return -EINVAL;
310b3b94faaSDavid Teigland 
311b3b94faaSDavid Teigland 	spin_lock(&gt->gt_spin);
312b3b94faaSDavid Teigland 	gt->gt_quota_scale_num = x;
313b3b94faaSDavid Teigland 	gt->gt_quota_scale_den = y;
314b3b94faaSDavid Teigland 	spin_unlock(&gt->gt_spin);
315b3b94faaSDavid Teigland 	return len;
316b3b94faaSDavid Teigland }
317b3b94faaSDavid Teigland 
318b3b94faaSDavid Teigland static ssize_t tune_set(struct gfs2_sbd *sdp, unsigned int *field,
319b3b94faaSDavid Teigland 			int check_zero, const char *buf, size_t len)
320b3b94faaSDavid Teigland {
321b3b94faaSDavid Teigland 	struct gfs2_tune *gt = &sdp->sd_tune;
322b3b94faaSDavid Teigland 	unsigned int x;
323b3b94faaSDavid Teigland 
324b3b94faaSDavid Teigland 	if (!capable(CAP_SYS_ADMIN))
325b3b94faaSDavid Teigland 		return -EACCES;
326b3b94faaSDavid Teigland 
327b3b94faaSDavid Teigland 	x = simple_strtoul(buf, NULL, 0);
328b3b94faaSDavid Teigland 
329b3b94faaSDavid Teigland 	if (check_zero && !x)
330b3b94faaSDavid Teigland 		return -EINVAL;
331b3b94faaSDavid Teigland 
332b3b94faaSDavid Teigland 	spin_lock(&gt->gt_spin);
333b3b94faaSDavid Teigland 	*field = x;
334b3b94faaSDavid Teigland 	spin_unlock(&gt->gt_spin);
335b3b94faaSDavid Teigland 	return len;
336b3b94faaSDavid Teigland }
337b3b94faaSDavid Teigland 
338b3b94faaSDavid Teigland struct tune_attr {
339b3b94faaSDavid Teigland 	struct attribute attr;
340b3b94faaSDavid Teigland 	ssize_t (*show)(struct gfs2_sbd *, char *);
341b3b94faaSDavid Teigland 	ssize_t (*store)(struct gfs2_sbd *, const char *, size_t);
342b3b94faaSDavid Teigland };
343b3b94faaSDavid Teigland 
344b3b94faaSDavid Teigland #define TUNE_ATTR_3(name, show, store)                                        \
345b3b94faaSDavid Teigland static struct tune_attr tune_attr_##name = __ATTR(name, 0644, show, store)
346b3b94faaSDavid Teigland 
347b3b94faaSDavid Teigland #define TUNE_ATTR_2(name, store)                                              \
348b3b94faaSDavid Teigland static ssize_t name##_show(struct gfs2_sbd *sdp, char *buf)                   \
349b3b94faaSDavid Teigland {                                                                             \
3503204a6c0SDavid Teigland 	return snprintf(buf, PAGE_SIZE, "%u\n", sdp->sd_tune.gt_##name);      \
351b3b94faaSDavid Teigland }                                                                             \
352b3b94faaSDavid Teigland TUNE_ATTR_3(name, name##_show, store)
353b3b94faaSDavid Teigland 
354b3b94faaSDavid Teigland #define TUNE_ATTR(name, check_zero)                                           \
355b3b94faaSDavid Teigland static ssize_t name##_store(struct gfs2_sbd *sdp, const char *buf, size_t len)\
356b3b94faaSDavid Teigland {                                                                             \
357b3b94faaSDavid Teigland 	return tune_set(sdp, &sdp->sd_tune.gt_##name, check_zero, buf, len);  \
358b3b94faaSDavid Teigland }                                                                             \
359b3b94faaSDavid Teigland TUNE_ATTR_2(name, name##_store)
360b3b94faaSDavid Teigland 
361b3b94faaSDavid Teigland #define TUNE_ATTR_DAEMON(name, process)                                       \
362b3b94faaSDavid Teigland static ssize_t name##_store(struct gfs2_sbd *sdp, const char *buf, size_t len)\
363b3b94faaSDavid Teigland {                                                                             \
364b3b94faaSDavid Teigland 	ssize_t r = tune_set(sdp, &sdp->sd_tune.gt_##name, 1, buf, len);      \
365b3b94faaSDavid Teigland 	wake_up_process(sdp->sd_##process);                                   \
366b3b94faaSDavid Teigland 	return r;                                                             \
367b3b94faaSDavid Teigland }                                                                             \
368b3b94faaSDavid Teigland TUNE_ATTR_2(name, name##_store)
369b3b94faaSDavid Teigland 
370b3b94faaSDavid Teigland TUNE_ATTR(incore_log_blocks, 0);
371b3b94faaSDavid Teigland TUNE_ATTR(log_flush_secs, 0);
372b3b94faaSDavid Teigland TUNE_ATTR(quota_warn_period, 0);
373b3b94faaSDavid Teigland TUNE_ATTR(quota_quantum, 0);
374b3b94faaSDavid Teigland TUNE_ATTR(max_readahead, 0);
375b3b94faaSDavid Teigland TUNE_ATTR(complain_secs, 0);
376b3b94faaSDavid Teigland TUNE_ATTR(statfs_slow, 0);
377b3b94faaSDavid Teigland TUNE_ATTR(new_files_jdata, 0);
378b3b94faaSDavid Teigland TUNE_ATTR(quota_simul_sync, 1);
379b3b94faaSDavid Teigland TUNE_ATTR(quota_cache_secs, 1);
380b3b94faaSDavid Teigland TUNE_ATTR(stall_secs, 1);
381b3b94faaSDavid Teigland TUNE_ATTR(statfs_quantum, 1);
382b3b94faaSDavid Teigland TUNE_ATTR_DAEMON(recoverd_secs, recoverd_process);
383b3b94faaSDavid Teigland TUNE_ATTR_DAEMON(logd_secs, logd_process);
384b3b94faaSDavid Teigland TUNE_ATTR_3(quota_scale, quota_scale_show, quota_scale_store);
385b3b94faaSDavid Teigland 
386b3b94faaSDavid Teigland static struct attribute *tune_attrs[] = {
387b3b94faaSDavid Teigland 	&tune_attr_incore_log_blocks.attr,
388b3b94faaSDavid Teigland 	&tune_attr_log_flush_secs.attr,
389b3b94faaSDavid Teigland 	&tune_attr_quota_warn_period.attr,
390b3b94faaSDavid Teigland 	&tune_attr_quota_quantum.attr,
391b3b94faaSDavid Teigland 	&tune_attr_max_readahead.attr,
392b3b94faaSDavid Teigland 	&tune_attr_complain_secs.attr,
393b3b94faaSDavid Teigland 	&tune_attr_statfs_slow.attr,
394b3b94faaSDavid Teigland 	&tune_attr_quota_simul_sync.attr,
395b3b94faaSDavid Teigland 	&tune_attr_quota_cache_secs.attr,
396b3b94faaSDavid Teigland 	&tune_attr_stall_secs.attr,
397b3b94faaSDavid Teigland 	&tune_attr_statfs_quantum.attr,
398b3b94faaSDavid Teigland 	&tune_attr_recoverd_secs.attr,
399b3b94faaSDavid Teigland 	&tune_attr_logd_secs.attr,
400b3b94faaSDavid Teigland 	&tune_attr_quota_scale.attr,
401b3b94faaSDavid Teigland 	&tune_attr_new_files_jdata.attr,
402ea67eedbSSteven Whitehouse 	NULL,
403b3b94faaSDavid Teigland };
404b3b94faaSDavid Teigland 
405b3b94faaSDavid Teigland static struct attribute_group lockstruct_group = {
406b3b94faaSDavid Teigland 	.name = "lockstruct",
407ea67eedbSSteven Whitehouse 	.attrs = lockstruct_attrs,
408b3b94faaSDavid Teigland };
409b3b94faaSDavid Teigland 
410b3b94faaSDavid Teigland static struct attribute_group args_group = {
411b3b94faaSDavid Teigland 	.name = "args",
412ea67eedbSSteven Whitehouse 	.attrs = args_attrs,
413b3b94faaSDavid Teigland };
414b3b94faaSDavid Teigland 
415b3b94faaSDavid Teigland static struct attribute_group tune_group = {
416b3b94faaSDavid Teigland 	.name = "tune",
417ea67eedbSSteven Whitehouse 	.attrs = tune_attrs,
418b3b94faaSDavid Teigland };
419b3b94faaSDavid Teigland 
420b3b94faaSDavid Teigland int gfs2_sys_fs_add(struct gfs2_sbd *sdp)
421b3b94faaSDavid Teigland {
422b3b94faaSDavid Teigland 	int error;
423b3b94faaSDavid Teigland 
4249bec101aSGreg Kroah-Hartman 	sdp->sd_kobj.kset = gfs2_kset;
425901195edSGreg Kroah-Hartman 	error = kobject_init_and_add(&sdp->sd_kobj, &gfs2_ktype, NULL,
426901195edSGreg Kroah-Hartman 				     "%s", sdp->sd_table_name);
427b3b94faaSDavid Teigland 	if (error)
428b3b94faaSDavid Teigland 		goto fail;
429b3b94faaSDavid Teigland 
430b3b94faaSDavid Teigland 	error = sysfs_create_group(&sdp->sd_kobj, &lockstruct_group);
431b3b94faaSDavid Teigland 	if (error)
432b3b94faaSDavid Teigland 		goto fail_reg;
433b3b94faaSDavid Teigland 
434b3b94faaSDavid Teigland 	error = sysfs_create_group(&sdp->sd_kobj, &args_group);
435b3b94faaSDavid Teigland 	if (error)
436*97cc1025SSteven Whitehouse 		goto fail_lockstruct;
437b3b94faaSDavid Teigland 
438b3b94faaSDavid Teigland 	error = sysfs_create_group(&sdp->sd_kobj, &tune_group);
439b3b94faaSDavid Teigland 	if (error)
440b3b94faaSDavid Teigland 		goto fail_args;
441b3b94faaSDavid Teigland 
442901195edSGreg Kroah-Hartman 	kobject_uevent(&sdp->sd_kobj, KOBJ_ADD);
443b3b94faaSDavid Teigland 	return 0;
444b3b94faaSDavid Teigland 
445b3b94faaSDavid Teigland fail_args:
446b3b94faaSDavid Teigland 	sysfs_remove_group(&sdp->sd_kobj, &args_group);
447b3b94faaSDavid Teigland fail_lockstruct:
448b3b94faaSDavid Teigland 	sysfs_remove_group(&sdp->sd_kobj, &lockstruct_group);
449b3b94faaSDavid Teigland fail_reg:
450197b12d6SGreg Kroah-Hartman 	kobject_put(&sdp->sd_kobj);
451b3b94faaSDavid Teigland fail:
45265952fb4SDavid Teigland 	fs_err(sdp, "error %d adding sysfs files", error);
453b3b94faaSDavid Teigland 	return error;
454b3b94faaSDavid Teigland }
455b3b94faaSDavid Teigland 
456b3b94faaSDavid Teigland void gfs2_sys_fs_del(struct gfs2_sbd *sdp)
457b3b94faaSDavid Teigland {
458b3b94faaSDavid Teigland 	sysfs_remove_group(&sdp->sd_kobj, &tune_group);
459b3b94faaSDavid Teigland 	sysfs_remove_group(&sdp->sd_kobj, &args_group);
460b3b94faaSDavid Teigland 	sysfs_remove_group(&sdp->sd_kobj, &lockstruct_group);
461197b12d6SGreg Kroah-Hartman 	kobject_put(&sdp->sd_kobj);
462b3b94faaSDavid Teigland }
463b3b94faaSDavid Teigland 
464b3b94faaSDavid Teigland int gfs2_sys_init(void)
465b3b94faaSDavid Teigland {
466b3b94faaSDavid Teigland 	gfs2_sys_margs = NULL;
467b3b94faaSDavid Teigland 	spin_lock_init(&gfs2_sys_margs_lock);
4689bec101aSGreg Kroah-Hartman 	gfs2_kset = kset_create_and_add("gfs2", NULL, fs_kobj);
4699bec101aSGreg Kroah-Hartman 	if (!gfs2_kset)
4709bec101aSGreg Kroah-Hartman 		return -ENOMEM;
4719bec101aSGreg Kroah-Hartman 	return 0;
472b3b94faaSDavid Teigland }
473b3b94faaSDavid Teigland 
474b3b94faaSDavid Teigland void gfs2_sys_uninit(void)
475b3b94faaSDavid Teigland {
476b3b94faaSDavid Teigland 	kfree(gfs2_sys_margs);
4779bec101aSGreg Kroah-Hartman 	kset_unregister(gfs2_kset);
478b3b94faaSDavid Teigland }
479b3b94faaSDavid Teigland 
480