xref: /linux/fs/gfs2/sys.c (revision 9bec101a0c38d559a8c95b44d850cd09a7b4edef)
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 "lm.h"
24b3b94faaSDavid Teigland #include "sys.h"
25b3b94faaSDavid Teigland #include "super.h"
26b3b94faaSDavid Teigland #include "glock.h"
27b3b94faaSDavid Teigland #include "quota.h"
285c676f6dSSteven Whitehouse #include "util.h"
29b3b94faaSDavid Teigland 
30b3b94faaSDavid Teigland char *gfs2_sys_margs;
31b3b94faaSDavid Teigland spinlock_t gfs2_sys_margs_lock;
32b3b94faaSDavid Teigland 
33b3b94faaSDavid Teigland static ssize_t id_show(struct gfs2_sbd *sdp, char *buf)
34b3b94faaSDavid Teigland {
353204a6c0SDavid Teigland 	return snprintf(buf, PAGE_SIZE, "%s\n", sdp->sd_vfs->s_id);
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 shrink_store(struct gfs2_sbd *sdp, const char *buf, size_t len)
114b3b94faaSDavid Teigland {
115b3b94faaSDavid Teigland 	if (!capable(CAP_SYS_ADMIN))
116b3b94faaSDavid Teigland 		return -EACCES;
117b3b94faaSDavid Teigland 
118b3b94faaSDavid Teigland 	if (simple_strtol(buf, NULL, 0) != 1)
119b3b94faaSDavid Teigland 		return -EINVAL;
120b3b94faaSDavid Teigland 
121b3b94faaSDavid Teigland 	gfs2_gl_hash_clear(sdp, NO_WAIT);
122b3b94faaSDavid Teigland 	return len;
123b3b94faaSDavid Teigland }
124b3b94faaSDavid Teigland 
125b3b94faaSDavid Teigland static ssize_t quota_sync_store(struct gfs2_sbd *sdp, const char *buf,
126b3b94faaSDavid Teigland 				size_t len)
127b3b94faaSDavid Teigland {
128b3b94faaSDavid Teigland 	if (!capable(CAP_SYS_ADMIN))
129b3b94faaSDavid Teigland 		return -EACCES;
130b3b94faaSDavid Teigland 
131b3b94faaSDavid Teigland 	if (simple_strtol(buf, NULL, 0) != 1)
132b3b94faaSDavid Teigland 		return -EINVAL;
133b3b94faaSDavid Teigland 
134b3b94faaSDavid Teigland 	gfs2_quota_sync(sdp);
135b3b94faaSDavid Teigland 	return len;
136b3b94faaSDavid Teigland }
137b3b94faaSDavid Teigland 
138b3b94faaSDavid Teigland static ssize_t quota_refresh_user_store(struct gfs2_sbd *sdp, const char *buf,
139b3b94faaSDavid Teigland 					size_t len)
140b3b94faaSDavid Teigland {
141cd915493SSteven Whitehouse 	u32 id;
142b3b94faaSDavid Teigland 
143b3b94faaSDavid Teigland 	if (!capable(CAP_SYS_ADMIN))
144b3b94faaSDavid Teigland 		return -EACCES;
145b3b94faaSDavid Teigland 
146b3b94faaSDavid Teigland 	id = simple_strtoul(buf, NULL, 0);
147b3b94faaSDavid Teigland 
148b3b94faaSDavid Teigland 	gfs2_quota_refresh(sdp, 1, id);
149b3b94faaSDavid Teigland 	return len;
150b3b94faaSDavid Teigland }
151b3b94faaSDavid Teigland 
152b3b94faaSDavid Teigland static ssize_t quota_refresh_group_store(struct gfs2_sbd *sdp, const char *buf,
153b3b94faaSDavid Teigland 					 size_t len)
154b3b94faaSDavid Teigland {
155cd915493SSteven Whitehouse 	u32 id;
156b3b94faaSDavid Teigland 
157b3b94faaSDavid Teigland 	if (!capable(CAP_SYS_ADMIN))
158b3b94faaSDavid Teigland 		return -EACCES;
159b3b94faaSDavid Teigland 
160b3b94faaSDavid Teigland 	id = simple_strtoul(buf, NULL, 0);
161b3b94faaSDavid Teigland 
162b3b94faaSDavid Teigland 	gfs2_quota_refresh(sdp, 0, id);
163b3b94faaSDavid Teigland 	return len;
164b3b94faaSDavid Teigland }
165b3b94faaSDavid Teigland 
166b3b94faaSDavid Teigland struct gfs2_attr {
167b3b94faaSDavid Teigland 	struct attribute attr;
168b3b94faaSDavid Teigland 	ssize_t (*show)(struct gfs2_sbd *, char *);
169b3b94faaSDavid Teigland 	ssize_t (*store)(struct gfs2_sbd *, const char *, size_t);
170b3b94faaSDavid Teigland };
171b3b94faaSDavid Teigland 
172b3b94faaSDavid Teigland #define GFS2_ATTR(name, mode, show, store) \
173b3b94faaSDavid Teigland static struct gfs2_attr gfs2_attr_##name = __ATTR(name, mode, show, store)
174b3b94faaSDavid Teigland 
175b3b94faaSDavid Teigland GFS2_ATTR(id,                  0444, id_show,       NULL);
176b3b94faaSDavid Teigland GFS2_ATTR(fsname,              0444, fsname_show,   NULL);
177b3b94faaSDavid Teigland GFS2_ATTR(freeze,              0644, freeze_show,   freeze_store);
178b3b94faaSDavid Teigland GFS2_ATTR(shrink,              0200, NULL,          shrink_store);
179b3b94faaSDavid Teigland GFS2_ATTR(withdraw,            0644, withdraw_show, withdraw_store);
180b3b94faaSDavid Teigland GFS2_ATTR(statfs_sync,         0200, NULL,          statfs_sync_store);
181b3b94faaSDavid Teigland GFS2_ATTR(quota_sync,          0200, NULL,          quota_sync_store);
182b3b94faaSDavid Teigland GFS2_ATTR(quota_refresh_user,  0200, NULL,          quota_refresh_user_store);
183b3b94faaSDavid Teigland GFS2_ATTR(quota_refresh_group, 0200, NULL,          quota_refresh_group_store);
184b3b94faaSDavid Teigland 
185b3b94faaSDavid Teigland static struct attribute *gfs2_attrs[] = {
186b3b94faaSDavid Teigland 	&gfs2_attr_id.attr,
187b3b94faaSDavid Teigland 	&gfs2_attr_fsname.attr,
188b3b94faaSDavid Teigland 	&gfs2_attr_freeze.attr,
189b3b94faaSDavid Teigland 	&gfs2_attr_shrink.attr,
190b3b94faaSDavid Teigland 	&gfs2_attr_withdraw.attr,
191b3b94faaSDavid Teigland 	&gfs2_attr_statfs_sync.attr,
192b3b94faaSDavid Teigland 	&gfs2_attr_quota_sync.attr,
193b3b94faaSDavid Teigland 	&gfs2_attr_quota_refresh_user.attr,
194b3b94faaSDavid Teigland 	&gfs2_attr_quota_refresh_group.attr,
195b3b94faaSDavid Teigland 	NULL,
196b3b94faaSDavid Teigland };
197b3b94faaSDavid Teigland 
198b3b94faaSDavid Teigland static ssize_t gfs2_attr_show(struct kobject *kobj, struct attribute *attr,
199b3b94faaSDavid Teigland 			      char *buf)
200b3b94faaSDavid Teigland {
201b3b94faaSDavid Teigland 	struct gfs2_sbd *sdp = container_of(kobj, struct gfs2_sbd, sd_kobj);
202b3b94faaSDavid Teigland 	struct gfs2_attr *a = container_of(attr, struct gfs2_attr, attr);
203b3b94faaSDavid Teigland 	return a->show ? a->show(sdp, buf) : 0;
204b3b94faaSDavid Teigland }
205b3b94faaSDavid Teigland 
206b3b94faaSDavid Teigland static ssize_t gfs2_attr_store(struct kobject *kobj, struct attribute *attr,
207b3b94faaSDavid Teigland 			       const char *buf, size_t len)
208b3b94faaSDavid Teigland {
209b3b94faaSDavid Teigland 	struct gfs2_sbd *sdp = container_of(kobj, struct gfs2_sbd, sd_kobj);
210b3b94faaSDavid Teigland 	struct gfs2_attr *a = container_of(attr, struct gfs2_attr, attr);
211b3b94faaSDavid Teigland 	return a->store ? a->store(sdp, buf, len) : len;
212b3b94faaSDavid Teigland }
213b3b94faaSDavid Teigland 
214b3b94faaSDavid Teigland static struct sysfs_ops gfs2_attr_ops = {
215b3b94faaSDavid Teigland 	.show  = gfs2_attr_show,
216b3b94faaSDavid Teigland 	.store = gfs2_attr_store,
217b3b94faaSDavid Teigland };
218b3b94faaSDavid Teigland 
219b3b94faaSDavid Teigland static struct kobj_type gfs2_ktype = {
220b3b94faaSDavid Teigland 	.default_attrs = gfs2_attrs,
221b3b94faaSDavid Teigland 	.sysfs_ops     = &gfs2_attr_ops,
222b3b94faaSDavid Teigland };
223b3b94faaSDavid Teigland 
224*9bec101aSGreg Kroah-Hartman static struct kset *gfs2_kset;
225b3b94faaSDavid Teigland 
226b3b94faaSDavid Teigland /*
227b3b94faaSDavid Teigland  * display struct lm_lockstruct fields
228b3b94faaSDavid Teigland  */
229b3b94faaSDavid Teigland 
230b3b94faaSDavid Teigland struct lockstruct_attr {
231b3b94faaSDavid Teigland 	struct attribute attr;
232b3b94faaSDavid Teigland 	ssize_t (*show)(struct gfs2_sbd *, char *);
233b3b94faaSDavid Teigland };
234b3b94faaSDavid Teigland 
235b3b94faaSDavid Teigland #define LOCKSTRUCT_ATTR(name, fmt)                                          \
236b3b94faaSDavid Teigland static ssize_t name##_show(struct gfs2_sbd *sdp, char *buf)                 \
237b3b94faaSDavid Teigland {                                                                           \
2383204a6c0SDavid Teigland 	return snprintf(buf, PAGE_SIZE, fmt, sdp->sd_lockstruct.ls_##name); \
239b3b94faaSDavid Teigland }                                                                           \
240b3b94faaSDavid Teigland static struct lockstruct_attr lockstruct_attr_##name = __ATTR_RO(name)
241b3b94faaSDavid Teigland 
242b3b94faaSDavid Teigland LOCKSTRUCT_ATTR(jid,      "%u\n");
243b3b94faaSDavid Teigland LOCKSTRUCT_ATTR(first,    "%u\n");
244b3b94faaSDavid Teigland LOCKSTRUCT_ATTR(lvb_size, "%u\n");
245b3b94faaSDavid Teigland LOCKSTRUCT_ATTR(flags,    "%d\n");
246b3b94faaSDavid Teigland 
247b3b94faaSDavid Teigland static struct attribute *lockstruct_attrs[] = {
248b3b94faaSDavid Teigland 	&lockstruct_attr_jid.attr,
249b3b94faaSDavid Teigland 	&lockstruct_attr_first.attr,
250b3b94faaSDavid Teigland 	&lockstruct_attr_lvb_size.attr,
251b3b94faaSDavid Teigland 	&lockstruct_attr_flags.attr,
252ea67eedbSSteven Whitehouse 	NULL,
253b3b94faaSDavid Teigland };
254b3b94faaSDavid Teigland 
255b3b94faaSDavid Teigland /*
256b3b94faaSDavid Teigland  * display struct gfs2_args fields
257b3b94faaSDavid Teigland  */
258b3b94faaSDavid Teigland 
259b3b94faaSDavid Teigland struct args_attr {
260b3b94faaSDavid Teigland 	struct attribute attr;
261b3b94faaSDavid Teigland 	ssize_t (*show)(struct gfs2_sbd *, char *);
262b3b94faaSDavid Teigland };
263b3b94faaSDavid Teigland 
264b3b94faaSDavid Teigland #define ARGS_ATTR(name, fmt)                                                \
265b3b94faaSDavid Teigland static ssize_t name##_show(struct gfs2_sbd *sdp, char *buf)                 \
266b3b94faaSDavid Teigland {                                                                           \
2673204a6c0SDavid Teigland 	return snprintf(buf, PAGE_SIZE, fmt, sdp->sd_args.ar_##name);       \
268b3b94faaSDavid Teigland }                                                                           \
269b3b94faaSDavid Teigland static struct args_attr args_attr_##name = __ATTR_RO(name)
270b3b94faaSDavid Teigland 
271b3b94faaSDavid Teigland ARGS_ATTR(lockproto,       "%s\n");
272b3b94faaSDavid Teigland ARGS_ATTR(locktable,       "%s\n");
273b3b94faaSDavid Teigland ARGS_ATTR(hostdata,        "%s\n");
274b3b94faaSDavid Teigland ARGS_ATTR(spectator,       "%d\n");
275b3b94faaSDavid Teigland ARGS_ATTR(ignore_local_fs, "%d\n");
276b3b94faaSDavid Teigland ARGS_ATTR(localcaching,    "%d\n");
277b3b94faaSDavid Teigland ARGS_ATTR(localflocks,     "%d\n");
278b3b94faaSDavid Teigland ARGS_ATTR(debug,           "%d\n");
279b3b94faaSDavid Teigland ARGS_ATTR(upgrade,         "%d\n");
280b3b94faaSDavid Teigland ARGS_ATTR(num_glockd,      "%u\n");
281b3b94faaSDavid Teigland ARGS_ATTR(posix_acl,       "%d\n");
282b3b94faaSDavid Teigland ARGS_ATTR(quota,           "%u\n");
283b3b94faaSDavid Teigland ARGS_ATTR(suiddir,         "%d\n");
284b3b94faaSDavid Teigland ARGS_ATTR(data,            "%d\n");
285b3b94faaSDavid Teigland 
286b3b94faaSDavid Teigland /* one oddball doesn't fit the macro mold */
287b3b94faaSDavid Teigland static ssize_t noatime_show(struct gfs2_sbd *sdp, char *buf)
288b3b94faaSDavid Teigland {
2893204a6c0SDavid Teigland 	return snprintf(buf, PAGE_SIZE, "%d\n",
2903204a6c0SDavid Teigland 			!!test_bit(SDF_NOATIME, &sdp->sd_flags));
291b3b94faaSDavid Teigland }
292b3b94faaSDavid Teigland static struct args_attr args_attr_noatime = __ATTR_RO(noatime);
293b3b94faaSDavid Teigland 
294b3b94faaSDavid Teigland static struct attribute *args_attrs[] = {
295b3b94faaSDavid Teigland 	&args_attr_lockproto.attr,
296b3b94faaSDavid Teigland 	&args_attr_locktable.attr,
297b3b94faaSDavid Teigland 	&args_attr_hostdata.attr,
298b3b94faaSDavid Teigland 	&args_attr_spectator.attr,
299b3b94faaSDavid Teigland 	&args_attr_ignore_local_fs.attr,
300b3b94faaSDavid Teigland 	&args_attr_localcaching.attr,
301b3b94faaSDavid Teigland 	&args_attr_localflocks.attr,
302b3b94faaSDavid Teigland 	&args_attr_debug.attr,
303b3b94faaSDavid Teigland 	&args_attr_upgrade.attr,
304b3b94faaSDavid Teigland 	&args_attr_num_glockd.attr,
305b3b94faaSDavid Teigland 	&args_attr_posix_acl.attr,
306b3b94faaSDavid Teigland 	&args_attr_quota.attr,
307b3b94faaSDavid Teigland 	&args_attr_suiddir.attr,
308b3b94faaSDavid Teigland 	&args_attr_data.attr,
309b3b94faaSDavid Teigland 	&args_attr_noatime.attr,
310ea67eedbSSteven Whitehouse 	NULL,
311b3b94faaSDavid Teigland };
312b3b94faaSDavid Teigland 
313b3b94faaSDavid Teigland /*
314b3b94faaSDavid Teigland  * display counters from superblock
315b3b94faaSDavid Teigland  */
316b3b94faaSDavid Teigland 
317b3b94faaSDavid Teigland struct counters_attr {
318b3b94faaSDavid Teigland 	struct attribute attr;
319b3b94faaSDavid Teigland 	ssize_t (*show)(struct gfs2_sbd *, char *);
320b3b94faaSDavid Teigland };
321b3b94faaSDavid Teigland 
3226a6b3d01SDavid Teigland #define COUNTERS_ATTR(name, fmt)                                            \
323b3b94faaSDavid Teigland static ssize_t name##_show(struct gfs2_sbd *sdp, char *buf)                 \
324b3b94faaSDavid Teigland {                                                                           \
3253204a6c0SDavid Teigland 	return snprintf(buf, PAGE_SIZE, fmt,                                \
3263204a6c0SDavid Teigland 			(unsigned int)atomic_read(&sdp->sd_##name));        \
327b3b94faaSDavid Teigland }                                                                           \
328b3b94faaSDavid Teigland static struct counters_attr counters_attr_##name = __ATTR_RO(name)
329b3b94faaSDavid Teigland 
3306a6b3d01SDavid Teigland COUNTERS_ATTR(glock_count,      "%u\n");
3316a6b3d01SDavid Teigland COUNTERS_ATTR(glock_held_count, "%u\n");
3326a6b3d01SDavid Teigland COUNTERS_ATTR(inode_count,      "%u\n");
3336a6b3d01SDavid Teigland COUNTERS_ATTR(reclaimed,        "%u\n");
334b3b94faaSDavid Teigland 
335b3b94faaSDavid Teigland static struct attribute *counters_attrs[] = {
336b3b94faaSDavid Teigland 	&counters_attr_glock_count.attr,
337b3b94faaSDavid Teigland 	&counters_attr_glock_held_count.attr,
338b3b94faaSDavid Teigland 	&counters_attr_inode_count.attr,
339b3b94faaSDavid Teigland 	&counters_attr_reclaimed.attr,
340ea67eedbSSteven Whitehouse 	NULL,
341b3b94faaSDavid Teigland };
342b3b94faaSDavid Teigland 
343b3b94faaSDavid Teigland /*
344b3b94faaSDavid Teigland  * get and set struct gfs2_tune fields
345b3b94faaSDavid Teigland  */
346b3b94faaSDavid Teigland 
347b3b94faaSDavid Teigland static ssize_t quota_scale_show(struct gfs2_sbd *sdp, char *buf)
348b3b94faaSDavid Teigland {
3493204a6c0SDavid Teigland 	return snprintf(buf, PAGE_SIZE, "%u %u\n",
3503204a6c0SDavid Teigland 			sdp->sd_tune.gt_quota_scale_num,
351b3b94faaSDavid Teigland 			sdp->sd_tune.gt_quota_scale_den);
352b3b94faaSDavid Teigland }
353b3b94faaSDavid Teigland 
354b3b94faaSDavid Teigland static ssize_t quota_scale_store(struct gfs2_sbd *sdp, const char *buf,
355b3b94faaSDavid Teigland 				 size_t len)
356b3b94faaSDavid Teigland {
357b3b94faaSDavid Teigland 	struct gfs2_tune *gt = &sdp->sd_tune;
358b3b94faaSDavid Teigland 	unsigned int x, y;
359b3b94faaSDavid Teigland 
360b3b94faaSDavid Teigland 	if (!capable(CAP_SYS_ADMIN))
361b3b94faaSDavid Teigland 		return -EACCES;
362b3b94faaSDavid Teigland 
363b3b94faaSDavid Teigland 	if (sscanf(buf, "%u %u", &x, &y) != 2 || !y)
364b3b94faaSDavid Teigland 		return -EINVAL;
365b3b94faaSDavid Teigland 
366b3b94faaSDavid Teigland 	spin_lock(&gt->gt_spin);
367b3b94faaSDavid Teigland 	gt->gt_quota_scale_num = x;
368b3b94faaSDavid Teigland 	gt->gt_quota_scale_den = y;
369b3b94faaSDavid Teigland 	spin_unlock(&gt->gt_spin);
370b3b94faaSDavid Teigland 	return len;
371b3b94faaSDavid Teigland }
372b3b94faaSDavid Teigland 
373b3b94faaSDavid Teigland static ssize_t tune_set(struct gfs2_sbd *sdp, unsigned int *field,
374b3b94faaSDavid Teigland 			int check_zero, const char *buf, size_t len)
375b3b94faaSDavid Teigland {
376b3b94faaSDavid Teigland 	struct gfs2_tune *gt = &sdp->sd_tune;
377b3b94faaSDavid Teigland 	unsigned int x;
378b3b94faaSDavid Teigland 
379b3b94faaSDavid Teigland 	if (!capable(CAP_SYS_ADMIN))
380b3b94faaSDavid Teigland 		return -EACCES;
381b3b94faaSDavid Teigland 
382b3b94faaSDavid Teigland 	x = simple_strtoul(buf, NULL, 0);
383b3b94faaSDavid Teigland 
384b3b94faaSDavid Teigland 	if (check_zero && !x)
385b3b94faaSDavid Teigland 		return -EINVAL;
386b3b94faaSDavid Teigland 
387b3b94faaSDavid Teigland 	spin_lock(&gt->gt_spin);
388b3b94faaSDavid Teigland 	*field = x;
389b3b94faaSDavid Teigland 	spin_unlock(&gt->gt_spin);
390b3b94faaSDavid Teigland 	return len;
391b3b94faaSDavid Teigland }
392b3b94faaSDavid Teigland 
393b3b94faaSDavid Teigland struct tune_attr {
394b3b94faaSDavid Teigland 	struct attribute attr;
395b3b94faaSDavid Teigland 	ssize_t (*show)(struct gfs2_sbd *, char *);
396b3b94faaSDavid Teigland 	ssize_t (*store)(struct gfs2_sbd *, const char *, size_t);
397b3b94faaSDavid Teigland };
398b3b94faaSDavid Teigland 
399b3b94faaSDavid Teigland #define TUNE_ATTR_3(name, show, store)                                        \
400b3b94faaSDavid Teigland static struct tune_attr tune_attr_##name = __ATTR(name, 0644, show, store)
401b3b94faaSDavid Teigland 
402b3b94faaSDavid Teigland #define TUNE_ATTR_2(name, store)                                              \
403b3b94faaSDavid Teigland static ssize_t name##_show(struct gfs2_sbd *sdp, char *buf)                   \
404b3b94faaSDavid Teigland {                                                                             \
4053204a6c0SDavid Teigland 	return snprintf(buf, PAGE_SIZE, "%u\n", sdp->sd_tune.gt_##name);      \
406b3b94faaSDavid Teigland }                                                                             \
407b3b94faaSDavid Teigland TUNE_ATTR_3(name, name##_show, store)
408b3b94faaSDavid Teigland 
409b3b94faaSDavid Teigland #define TUNE_ATTR(name, check_zero)                                           \
410b3b94faaSDavid Teigland static ssize_t name##_store(struct gfs2_sbd *sdp, const char *buf, size_t len)\
411b3b94faaSDavid Teigland {                                                                             \
412b3b94faaSDavid Teigland 	return tune_set(sdp, &sdp->sd_tune.gt_##name, check_zero, buf, len);  \
413b3b94faaSDavid Teigland }                                                                             \
414b3b94faaSDavid Teigland TUNE_ATTR_2(name, name##_store)
415b3b94faaSDavid Teigland 
416b3b94faaSDavid Teigland #define TUNE_ATTR_DAEMON(name, process)                                       \
417b3b94faaSDavid Teigland static ssize_t name##_store(struct gfs2_sbd *sdp, const char *buf, size_t len)\
418b3b94faaSDavid Teigland {                                                                             \
419b3b94faaSDavid Teigland 	ssize_t r = tune_set(sdp, &sdp->sd_tune.gt_##name, 1, buf, len);      \
420b3b94faaSDavid Teigland 	wake_up_process(sdp->sd_##process);                                   \
421b3b94faaSDavid Teigland 	return r;                                                             \
422b3b94faaSDavid Teigland }                                                                             \
423b3b94faaSDavid Teigland TUNE_ATTR_2(name, name##_store)
424b3b94faaSDavid Teigland 
425b3b94faaSDavid Teigland TUNE_ATTR(demote_secs, 0);
426b3b94faaSDavid Teigland TUNE_ATTR(incore_log_blocks, 0);
427b3b94faaSDavid Teigland TUNE_ATTR(log_flush_secs, 0);
428b3b94faaSDavid Teigland TUNE_ATTR(jindex_refresh_secs, 0);
429b3b94faaSDavid Teigland TUNE_ATTR(quota_warn_period, 0);
430b3b94faaSDavid Teigland TUNE_ATTR(quota_quantum, 0);
431b3b94faaSDavid Teigland TUNE_ATTR(atime_quantum, 0);
432b3b94faaSDavid Teigland TUNE_ATTR(max_readahead, 0);
433b3b94faaSDavid Teigland TUNE_ATTR(complain_secs, 0);
434b3b94faaSDavid Teigland TUNE_ATTR(reclaim_limit, 0);
435b3b94faaSDavid Teigland TUNE_ATTR(statfs_slow, 0);
436b3b94faaSDavid Teigland TUNE_ATTR(new_files_jdata, 0);
437b3b94faaSDavid Teigland TUNE_ATTR(new_files_directio, 0);
438b3b94faaSDavid Teigland TUNE_ATTR(quota_simul_sync, 1);
439b3b94faaSDavid Teigland TUNE_ATTR(quota_cache_secs, 1);
440b3b94faaSDavid Teigland TUNE_ATTR(stall_secs, 1);
441b3b94faaSDavid Teigland TUNE_ATTR(statfs_quantum, 1);
442b3b94faaSDavid Teigland TUNE_ATTR_DAEMON(recoverd_secs, recoverd_process);
443b3b94faaSDavid Teigland TUNE_ATTR_DAEMON(logd_secs, logd_process);
444b3b94faaSDavid Teigland TUNE_ATTR_DAEMON(quotad_secs, quotad_process);
445b3b94faaSDavid Teigland TUNE_ATTR_3(quota_scale, quota_scale_show, quota_scale_store);
446b3b94faaSDavid Teigland 
447b3b94faaSDavid Teigland static struct attribute *tune_attrs[] = {
448b3b94faaSDavid Teigland 	&tune_attr_demote_secs.attr,
449b3b94faaSDavid Teigland 	&tune_attr_incore_log_blocks.attr,
450b3b94faaSDavid Teigland 	&tune_attr_log_flush_secs.attr,
451b3b94faaSDavid Teigland 	&tune_attr_jindex_refresh_secs.attr,
452b3b94faaSDavid Teigland 	&tune_attr_quota_warn_period.attr,
453b3b94faaSDavid Teigland 	&tune_attr_quota_quantum.attr,
454b3b94faaSDavid Teigland 	&tune_attr_atime_quantum.attr,
455b3b94faaSDavid Teigland 	&tune_attr_max_readahead.attr,
456b3b94faaSDavid Teigland 	&tune_attr_complain_secs.attr,
457b3b94faaSDavid Teigland 	&tune_attr_reclaim_limit.attr,
458b3b94faaSDavid Teigland 	&tune_attr_statfs_slow.attr,
459b3b94faaSDavid Teigland 	&tune_attr_quota_simul_sync.attr,
460b3b94faaSDavid Teigland 	&tune_attr_quota_cache_secs.attr,
461b3b94faaSDavid Teigland 	&tune_attr_stall_secs.attr,
462b3b94faaSDavid Teigland 	&tune_attr_statfs_quantum.attr,
463b3b94faaSDavid Teigland 	&tune_attr_recoverd_secs.attr,
464b3b94faaSDavid Teigland 	&tune_attr_logd_secs.attr,
465b3b94faaSDavid Teigland 	&tune_attr_quotad_secs.attr,
466b3b94faaSDavid Teigland 	&tune_attr_quota_scale.attr,
467b3b94faaSDavid Teigland 	&tune_attr_new_files_jdata.attr,
468b3b94faaSDavid Teigland 	&tune_attr_new_files_directio.attr,
469ea67eedbSSteven Whitehouse 	NULL,
470b3b94faaSDavid Teigland };
471b3b94faaSDavid Teigland 
472b3b94faaSDavid Teigland static struct attribute_group lockstruct_group = {
473b3b94faaSDavid Teigland 	.name = "lockstruct",
474ea67eedbSSteven Whitehouse 	.attrs = lockstruct_attrs,
475b3b94faaSDavid Teigland };
476b3b94faaSDavid Teigland 
477b3b94faaSDavid Teigland static struct attribute_group counters_group = {
478b3b94faaSDavid Teigland 	.name = "counters",
479ea67eedbSSteven Whitehouse 	.attrs = counters_attrs,
480b3b94faaSDavid Teigland };
481b3b94faaSDavid Teigland 
482b3b94faaSDavid Teigland static struct attribute_group args_group = {
483b3b94faaSDavid Teigland 	.name = "args",
484ea67eedbSSteven Whitehouse 	.attrs = args_attrs,
485b3b94faaSDavid Teigland };
486b3b94faaSDavid Teigland 
487b3b94faaSDavid Teigland static struct attribute_group tune_group = {
488b3b94faaSDavid Teigland 	.name = "tune",
489ea67eedbSSteven Whitehouse 	.attrs = tune_attrs,
490b3b94faaSDavid Teigland };
491b3b94faaSDavid Teigland 
492b3b94faaSDavid Teigland int gfs2_sys_fs_add(struct gfs2_sbd *sdp)
493b3b94faaSDavid Teigland {
494b3b94faaSDavid Teigland 	int error;
495b3b94faaSDavid Teigland 
496*9bec101aSGreg Kroah-Hartman 	sdp->sd_kobj.kset = gfs2_kset;
497b3b94faaSDavid Teigland 	sdp->sd_kobj.ktype = &gfs2_ktype;
498b3b94faaSDavid Teigland 
499b3b94faaSDavid Teigland 	error = kobject_set_name(&sdp->sd_kobj, "%s", sdp->sd_table_name);
500b3b94faaSDavid Teigland 	if (error)
501b3b94faaSDavid Teigland 		goto fail;
502b3b94faaSDavid Teigland 
503b3b94faaSDavid Teigland 	error = kobject_register(&sdp->sd_kobj);
504b3b94faaSDavid Teigland 	if (error)
505b3b94faaSDavid Teigland 		goto fail;
506b3b94faaSDavid Teigland 
507b3b94faaSDavid Teigland 	error = sysfs_create_group(&sdp->sd_kobj, &lockstruct_group);
508b3b94faaSDavid Teigland 	if (error)
509b3b94faaSDavid Teigland 		goto fail_reg;
510b3b94faaSDavid Teigland 
511b3b94faaSDavid Teigland 	error = sysfs_create_group(&sdp->sd_kobj, &counters_group);
512b3b94faaSDavid Teigland 	if (error)
513b3b94faaSDavid Teigland 		goto fail_lockstruct;
514b3b94faaSDavid Teigland 
515b3b94faaSDavid Teigland 	error = sysfs_create_group(&sdp->sd_kobj, &args_group);
516b3b94faaSDavid Teigland 	if (error)
517b3b94faaSDavid Teigland 		goto fail_counters;
518b3b94faaSDavid Teigland 
519b3b94faaSDavid Teigland 	error = sysfs_create_group(&sdp->sd_kobj, &tune_group);
520b3b94faaSDavid Teigland 	if (error)
521b3b94faaSDavid Teigland 		goto fail_args;
522b3b94faaSDavid Teigland 
523b3b94faaSDavid Teigland 	return 0;
524b3b94faaSDavid Teigland 
525b3b94faaSDavid Teigland fail_args:
526b3b94faaSDavid Teigland 	sysfs_remove_group(&sdp->sd_kobj, &args_group);
527b3b94faaSDavid Teigland fail_counters:
528b3b94faaSDavid Teigland 	sysfs_remove_group(&sdp->sd_kobj, &counters_group);
529b3b94faaSDavid Teigland fail_lockstruct:
530b3b94faaSDavid Teigland 	sysfs_remove_group(&sdp->sd_kobj, &lockstruct_group);
531b3b94faaSDavid Teigland fail_reg:
532b3b94faaSDavid Teigland 	kobject_unregister(&sdp->sd_kobj);
533b3b94faaSDavid Teigland fail:
53465952fb4SDavid Teigland 	fs_err(sdp, "error %d adding sysfs files", error);
535b3b94faaSDavid Teigland 	return error;
536b3b94faaSDavid Teigland }
537b3b94faaSDavid Teigland 
538b3b94faaSDavid Teigland void gfs2_sys_fs_del(struct gfs2_sbd *sdp)
539b3b94faaSDavid Teigland {
540b3b94faaSDavid Teigland 	sysfs_remove_group(&sdp->sd_kobj, &tune_group);
541b3b94faaSDavid Teigland 	sysfs_remove_group(&sdp->sd_kobj, &args_group);
542b3b94faaSDavid Teigland 	sysfs_remove_group(&sdp->sd_kobj, &counters_group);
543b3b94faaSDavid Teigland 	sysfs_remove_group(&sdp->sd_kobj, &lockstruct_group);
544b3b94faaSDavid Teigland 	kobject_unregister(&sdp->sd_kobj);
545b3b94faaSDavid Teigland }
546b3b94faaSDavid Teigland 
547b3b94faaSDavid Teigland int gfs2_sys_init(void)
548b3b94faaSDavid Teigland {
549b3b94faaSDavid Teigland 	gfs2_sys_margs = NULL;
550b3b94faaSDavid Teigland 	spin_lock_init(&gfs2_sys_margs_lock);
551*9bec101aSGreg Kroah-Hartman 	gfs2_kset = kset_create_and_add("gfs2", NULL, fs_kobj);
552*9bec101aSGreg Kroah-Hartman 	if (!gfs2_kset)
553*9bec101aSGreg Kroah-Hartman 		return -ENOMEM;
554*9bec101aSGreg Kroah-Hartman 	return 0;
555b3b94faaSDavid Teigland }
556b3b94faaSDavid Teigland 
557b3b94faaSDavid Teigland void gfs2_sys_uninit(void)
558b3b94faaSDavid Teigland {
559b3b94faaSDavid Teigland 	kfree(gfs2_sys_margs);
560*9bec101aSGreg Kroah-Hartman 	kset_unregister(gfs2_kset);
561b3b94faaSDavid Teigland }
562b3b94faaSDavid Teigland 
563