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