xref: /linux/fs/gfs2/sys.c (revision 5b825c3af1d8a0af4deb4a5eb349d0d0050c62e5)
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 
10d77d1b58SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
11d77d1b58SJoe Perches 
12b3b94faaSDavid Teigland #include <linux/sched.h>
13*5b825c3aSIngo Molnar #include <linux/cred.h>
14b3b94faaSDavid Teigland #include <linux/spinlock.h>
15b3b94faaSDavid Teigland #include <linux/completion.h>
16b3b94faaSDavid Teigland #include <linux/buffer_head.h>
17b3b94faaSDavid Teigland #include <linux/module.h>
18b3b94faaSDavid Teigland #include <linux/kobject.h>
197c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
20f057f6cdSSteven Whitehouse #include <linux/gfs2_ondisk.h>
2131e54b01SSteven Whitehouse #include <linux/genhd.h>
22b3b94faaSDavid Teigland 
23b3b94faaSDavid Teigland #include "gfs2.h"
245c676f6dSSteven Whitehouse #include "incore.h"
25b3b94faaSDavid Teigland #include "sys.h"
26b3b94faaSDavid Teigland #include "super.h"
27b3b94faaSDavid Teigland #include "glock.h"
28b3b94faaSDavid Teigland #include "quota.h"
295c676f6dSSteven Whitehouse #include "util.h"
3064d576baSSteven Whitehouse #include "glops.h"
316ecd7c2dSTejun Heo #include "recovery.h"
32b3b94faaSDavid Teigland 
3348c2b613SSteven Whitehouse struct gfs2_attr {
3448c2b613SSteven Whitehouse 	struct attribute attr;
3548c2b613SSteven Whitehouse 	ssize_t (*show)(struct gfs2_sbd *, char *);
3648c2b613SSteven Whitehouse 	ssize_t (*store)(struct gfs2_sbd *, const char *, size_t);
3748c2b613SSteven Whitehouse };
3848c2b613SSteven Whitehouse 
3948c2b613SSteven Whitehouse static ssize_t gfs2_attr_show(struct kobject *kobj, struct attribute *attr,
4048c2b613SSteven Whitehouse 			      char *buf)
4148c2b613SSteven Whitehouse {
4248c2b613SSteven Whitehouse 	struct gfs2_sbd *sdp = container_of(kobj, struct gfs2_sbd, sd_kobj);
4348c2b613SSteven Whitehouse 	struct gfs2_attr *a = container_of(attr, struct gfs2_attr, attr);
4448c2b613SSteven Whitehouse 	return a->show ? a->show(sdp, buf) : 0;
4548c2b613SSteven Whitehouse }
4648c2b613SSteven Whitehouse 
4748c2b613SSteven Whitehouse static ssize_t gfs2_attr_store(struct kobject *kobj, struct attribute *attr,
4848c2b613SSteven Whitehouse 			       const char *buf, size_t len)
4948c2b613SSteven Whitehouse {
5048c2b613SSteven Whitehouse 	struct gfs2_sbd *sdp = container_of(kobj, struct gfs2_sbd, sd_kobj);
5148c2b613SSteven Whitehouse 	struct gfs2_attr *a = container_of(attr, struct gfs2_attr, attr);
5248c2b613SSteven Whitehouse 	return a->store ? a->store(sdp, buf, len) : len;
5348c2b613SSteven Whitehouse }
5448c2b613SSteven Whitehouse 
5552cf25d0SEmese Revfy static const struct sysfs_ops gfs2_attr_ops = {
5648c2b613SSteven Whitehouse 	.show  = gfs2_attr_show,
5748c2b613SSteven Whitehouse 	.store = gfs2_attr_store,
5848c2b613SSteven Whitehouse };
5948c2b613SSteven Whitehouse 
6048c2b613SSteven Whitehouse 
6148c2b613SSteven Whitehouse static struct kset *gfs2_kset;
6248c2b613SSteven Whitehouse 
63b3b94faaSDavid Teigland static ssize_t id_show(struct gfs2_sbd *sdp, char *buf)
64b3b94faaSDavid Teigland {
65c7227e46SBob Peterson 	return snprintf(buf, PAGE_SIZE, "%u:%u\n",
66c7227e46SBob Peterson 			MAJOR(sdp->sd_vfs->s_dev), MINOR(sdp->sd_vfs->s_dev));
67b3b94faaSDavid Teigland }
68b3b94faaSDavid Teigland 
69b3b94faaSDavid Teigland static ssize_t fsname_show(struct gfs2_sbd *sdp, char *buf)
70b3b94faaSDavid Teigland {
713204a6c0SDavid Teigland 	return snprintf(buf, PAGE_SIZE, "%s\n", sdp->sd_fsname);
72b3b94faaSDavid Teigland }
73b3b94faaSDavid Teigland 
7402e3cc70SSteven Whitehouse static int gfs2_uuid_valid(const u8 *uuid)
7502e3cc70SSteven Whitehouse {
7602e3cc70SSteven Whitehouse 	int i;
7702e3cc70SSteven Whitehouse 
7802e3cc70SSteven Whitehouse 	for (i = 0; i < 16; i++) {
7902e3cc70SSteven Whitehouse 		if (uuid[i])
8002e3cc70SSteven Whitehouse 			return 1;
8102e3cc70SSteven Whitehouse 	}
8202e3cc70SSteven Whitehouse 	return 0;
8302e3cc70SSteven Whitehouse }
8402e3cc70SSteven Whitehouse 
8502e3cc70SSteven Whitehouse static ssize_t uuid_show(struct gfs2_sbd *sdp, char *buf)
8602e3cc70SSteven Whitehouse {
8732e471efSSteven Whitehouse 	struct super_block *s = sdp->sd_vfs;
8832e471efSSteven Whitehouse 	const u8 *uuid = s->s_uuid;
8902e3cc70SSteven Whitehouse 	buf[0] = '\0';
9002e3cc70SSteven Whitehouse 	if (!gfs2_uuid_valid(uuid))
9102e3cc70SSteven Whitehouse 		return 0;
92f0b34ae6SJoe Perches 	return snprintf(buf, PAGE_SIZE, "%pUB\n", uuid);
9302e3cc70SSteven Whitehouse }
9402e3cc70SSteven Whitehouse 
95b3b94faaSDavid Teigland static ssize_t freeze_show(struct gfs2_sbd *sdp, char *buf)
96b3b94faaSDavid Teigland {
97d564053fSSteven Whitehouse 	struct super_block *sb = sdp->sd_vfs;
98d564053fSSteven Whitehouse 	int frozen = (sb->s_writers.frozen == SB_UNFROZEN) ? 0 : 1;
99b3b94faaSDavid Teigland 
1003566c964Salex chen 	return snprintf(buf, PAGE_SIZE, "%d\n", frozen);
101b3b94faaSDavid Teigland }
102b3b94faaSDavid Teigland 
103b3b94faaSDavid Teigland static ssize_t freeze_store(struct gfs2_sbd *sdp, const char *buf, size_t len)
104b3b94faaSDavid Teigland {
105e50ead48SFabian Frederick 	int error, n;
106e50ead48SFabian Frederick 
107e50ead48SFabian Frederick 	error = kstrtoint(buf, 0, &n);
108e50ead48SFabian Frederick 	if (error)
109e50ead48SFabian Frederick 		return error;
110b3b94faaSDavid Teigland 
111b3b94faaSDavid Teigland 	if (!capable(CAP_SYS_ADMIN))
11241735818SZhao Hongjiang 		return -EPERM;
113b3b94faaSDavid Teigland 
114b3b94faaSDavid Teigland 	switch (n) {
115b3b94faaSDavid Teigland 	case 0:
116d564053fSSteven Whitehouse 		error = thaw_super(sdp->sd_vfs);
117b3b94faaSDavid Teigland 		break;
118b3b94faaSDavid Teigland 	case 1:
119d564053fSSteven Whitehouse 		error = freeze_super(sdp->sd_vfs);
120b3b94faaSDavid Teigland 		break;
121b3b94faaSDavid Teigland 	default:
122d564053fSSteven Whitehouse 		return -EINVAL;
123b3b94faaSDavid Teigland 	}
124b3b94faaSDavid Teigland 
125d564053fSSteven Whitehouse 	if (error) {
126b3b94faaSDavid Teigland 		fs_warn(sdp, "freeze %d error %d", n, error);
127d564053fSSteven Whitehouse 		return error;
128d564053fSSteven Whitehouse 	}
129b3b94faaSDavid Teigland 
130d564053fSSteven Whitehouse 	return len;
131b3b94faaSDavid Teigland }
132b3b94faaSDavid Teigland 
133b3b94faaSDavid Teigland static ssize_t withdraw_show(struct gfs2_sbd *sdp, char *buf)
134b3b94faaSDavid Teigland {
135b3b94faaSDavid Teigland 	unsigned int b = test_bit(SDF_SHUTDOWN, &sdp->sd_flags);
1363204a6c0SDavid Teigland 	return snprintf(buf, PAGE_SIZE, "%u\n", b);
137b3b94faaSDavid Teigland }
138b3b94faaSDavid Teigland 
139b3b94faaSDavid Teigland static ssize_t withdraw_store(struct gfs2_sbd *sdp, const char *buf, size_t len)
140b3b94faaSDavid Teigland {
141e50ead48SFabian Frederick 	int error, val;
142e50ead48SFabian Frederick 
143b3b94faaSDavid Teigland 	if (!capable(CAP_SYS_ADMIN))
14441735818SZhao Hongjiang 		return -EPERM;
145b3b94faaSDavid Teigland 
146e50ead48SFabian Frederick 	error = kstrtoint(buf, 0, &val);
147e50ead48SFabian Frederick 	if (error)
148e50ead48SFabian Frederick 		return error;
149e50ead48SFabian Frederick 
150e50ead48SFabian Frederick 	if (val != 1)
151b3b94faaSDavid Teigland 		return -EINVAL;
152b3b94faaSDavid Teigland 
153cb94eb06SJoe Perches 	gfs2_lm_withdraw(sdp, "withdrawing from cluster at user's request\n");
154cb94eb06SJoe Perches 
155b3b94faaSDavid Teigland 	return len;
156b3b94faaSDavid Teigland }
157b3b94faaSDavid Teigland 
158b3b94faaSDavid Teigland static ssize_t statfs_sync_store(struct gfs2_sbd *sdp, const char *buf,
159b3b94faaSDavid Teigland 				 size_t len)
160b3b94faaSDavid Teigland {
161e50ead48SFabian Frederick 	int error, val;
162e50ead48SFabian Frederick 
163b3b94faaSDavid Teigland 	if (!capable(CAP_SYS_ADMIN))
16441735818SZhao Hongjiang 		return -EPERM;
165b3b94faaSDavid Teigland 
166e50ead48SFabian Frederick 	error = kstrtoint(buf, 0, &val);
167e50ead48SFabian Frederick 	if (error)
168e50ead48SFabian Frederick 		return error;
169e50ead48SFabian Frederick 
170e50ead48SFabian Frederick 	if (val != 1)
171b3b94faaSDavid Teigland 		return -EINVAL;
172b3b94faaSDavid Teigland 
1738c42d637SSteven Whitehouse 	gfs2_statfs_sync(sdp->sd_vfs, 0);
174b3b94faaSDavid Teigland 	return len;
175b3b94faaSDavid Teigland }
176b3b94faaSDavid Teigland 
177b3b94faaSDavid Teigland static ssize_t quota_sync_store(struct gfs2_sbd *sdp, const char *buf,
178b3b94faaSDavid Teigland 				size_t len)
179b3b94faaSDavid Teigland {
180e50ead48SFabian Frederick 	int error, val;
181e50ead48SFabian Frederick 
182b3b94faaSDavid Teigland 	if (!capable(CAP_SYS_ADMIN))
18341735818SZhao Hongjiang 		return -EPERM;
184b3b94faaSDavid Teigland 
185e50ead48SFabian Frederick 	error = kstrtoint(buf, 0, &val);
186e50ead48SFabian Frederick 	if (error)
187e50ead48SFabian Frederick 		return error;
188e50ead48SFabian Frederick 
189e50ead48SFabian Frederick 	if (val != 1)
190b3b94faaSDavid Teigland 		return -EINVAL;
191b3b94faaSDavid Teigland 
192ceed1723SJan Kara 	gfs2_quota_sync(sdp->sd_vfs, 0);
193b3b94faaSDavid Teigland 	return len;
194b3b94faaSDavid Teigland }
195b3b94faaSDavid Teigland 
196b3b94faaSDavid Teigland static ssize_t quota_refresh_user_store(struct gfs2_sbd *sdp, const char *buf,
197b3b94faaSDavid Teigland 					size_t len)
198b3b94faaSDavid Teigland {
199ed87dabcSEric W. Biederman 	struct kqid qid;
200ea762338SSteven Whitehouse 	int error;
201cd915493SSteven Whitehouse 	u32 id;
202b3b94faaSDavid Teigland 
203b3b94faaSDavid Teigland 	if (!capable(CAP_SYS_ADMIN))
20441735818SZhao Hongjiang 		return -EPERM;
205b3b94faaSDavid Teigland 
206e50ead48SFabian Frederick 	error = kstrtou32(buf, 0, &id);
207e50ead48SFabian Frederick 	if (error)
208e50ead48SFabian Frederick 		return error;
209b3b94faaSDavid Teigland 
210ed87dabcSEric W. Biederman 	qid = make_kqid(current_user_ns(), USRQUOTA, id);
211ed87dabcSEric W. Biederman 	if (!qid_valid(qid))
212ed87dabcSEric W. Biederman 		return -EINVAL;
213ed87dabcSEric W. Biederman 
214ed87dabcSEric W. Biederman 	error = gfs2_quota_refresh(sdp, qid);
215ea762338SSteven Whitehouse 	return error ? error : len;
216b3b94faaSDavid Teigland }
217b3b94faaSDavid Teigland 
218b3b94faaSDavid Teigland static ssize_t quota_refresh_group_store(struct gfs2_sbd *sdp, const char *buf,
219b3b94faaSDavid Teigland 					 size_t len)
220b3b94faaSDavid Teigland {
221ed87dabcSEric W. Biederman 	struct kqid qid;
222ea762338SSteven Whitehouse 	int error;
223cd915493SSteven Whitehouse 	u32 id;
224b3b94faaSDavid Teigland 
225b3b94faaSDavid Teigland 	if (!capable(CAP_SYS_ADMIN))
22641735818SZhao Hongjiang 		return -EPERM;
227b3b94faaSDavid Teigland 
228e50ead48SFabian Frederick 	error = kstrtou32(buf, 0, &id);
229e50ead48SFabian Frederick 	if (error)
230e50ead48SFabian Frederick 		return error;
231b3b94faaSDavid Teigland 
232ed87dabcSEric W. Biederman 	qid = make_kqid(current_user_ns(), GRPQUOTA, id);
233ed87dabcSEric W. Biederman 	if (!qid_valid(qid))
234ed87dabcSEric W. Biederman 		return -EINVAL;
235ed87dabcSEric W. Biederman 
236ed87dabcSEric W. Biederman 	error = gfs2_quota_refresh(sdp, qid);
237ea762338SSteven Whitehouse 	return error ? error : len;
238b3b94faaSDavid Teigland }
239b3b94faaSDavid Teigland 
24064d576baSSteven Whitehouse static ssize_t demote_rq_store(struct gfs2_sbd *sdp, const char *buf, size_t len)
24164d576baSSteven Whitehouse {
24264d576baSSteven Whitehouse 	struct gfs2_glock *gl;
24364d576baSSteven Whitehouse 	const struct gfs2_glock_operations *glops;
24464d576baSSteven Whitehouse 	unsigned int glmode;
24564d576baSSteven Whitehouse 	unsigned int gltype;
24664d576baSSteven Whitehouse 	unsigned long long glnum;
24764d576baSSteven Whitehouse 	char mode[16];
24864d576baSSteven Whitehouse 	int rv;
24964d576baSSteven Whitehouse 
25064d576baSSteven Whitehouse 	if (!capable(CAP_SYS_ADMIN))
25141735818SZhao Hongjiang 		return -EPERM;
25264d576baSSteven Whitehouse 
25364d576baSSteven Whitehouse 	rv = sscanf(buf, "%u:%llu %15s", &gltype, &glnum,
25464d576baSSteven Whitehouse 		    mode);
25564d576baSSteven Whitehouse 	if (rv != 3)
25664d576baSSteven Whitehouse 		return -EINVAL;
25764d576baSSteven Whitehouse 
25864d576baSSteven Whitehouse 	if (strcmp(mode, "EX") == 0)
25964d576baSSteven Whitehouse 		glmode = LM_ST_UNLOCKED;
26064d576baSSteven Whitehouse 	else if ((strcmp(mode, "CW") == 0) || (strcmp(mode, "DF") == 0))
26164d576baSSteven Whitehouse 		glmode = LM_ST_DEFERRED;
26264d576baSSteven Whitehouse 	else if ((strcmp(mode, "PR") == 0) || (strcmp(mode, "SH") == 0))
26364d576baSSteven Whitehouse 		glmode = LM_ST_SHARED;
26464d576baSSteven Whitehouse 	else
26564d576baSSteven Whitehouse 		return -EINVAL;
26664d576baSSteven Whitehouse 
26764d576baSSteven Whitehouse 	if (gltype > LM_TYPE_JOURNAL)
26864d576baSSteven Whitehouse 		return -EINVAL;
26924972557SBenjamin Marzinski 	if (gltype == LM_TYPE_NONDISK && glnum == GFS2_FREEZE_LOCK)
27024972557SBenjamin Marzinski 		glops = &gfs2_freeze_glops;
27113466985SSteven Whitehouse 	else
27264d576baSSteven Whitehouse 		glops = gfs2_glops_list[gltype];
27364d576baSSteven Whitehouse 	if (glops == NULL)
27464d576baSSteven Whitehouse 		return -EINVAL;
2756a99be5dSSteven Whitehouse 	if (!test_and_set_bit(SDF_DEMOTE, &sdp->sd_flags))
276913a71d2SSteven Whitehouse 		fs_info(sdp, "demote interface used\n");
27764d576baSSteven Whitehouse 	rv = gfs2_glock_get(sdp, glnum, glops, 0, &gl);
27864d576baSSteven Whitehouse 	if (rv)
27964d576baSSteven Whitehouse 		return rv;
28064d576baSSteven Whitehouse 	gfs2_glock_cb(gl, glmode);
28164d576baSSteven Whitehouse 	gfs2_glock_put(gl);
28264d576baSSteven Whitehouse 	return len;
28364d576baSSteven Whitehouse }
28464d576baSSteven Whitehouse 
285b3b94faaSDavid Teigland 
286b3b94faaSDavid Teigland #define GFS2_ATTR(name, mode, show, store) \
287b3b94faaSDavid Teigland static struct gfs2_attr gfs2_attr_##name = __ATTR(name, mode, show, store)
288b3b94faaSDavid Teigland 
289b3b94faaSDavid Teigland GFS2_ATTR(id,                  0444, id_show,       NULL);
290b3b94faaSDavid Teigland GFS2_ATTR(fsname,              0444, fsname_show,   NULL);
29102e3cc70SSteven Whitehouse GFS2_ATTR(uuid,                0444, uuid_show,     NULL);
292b3b94faaSDavid Teigland GFS2_ATTR(freeze,              0644, freeze_show,   freeze_store);
293b3b94faaSDavid Teigland GFS2_ATTR(withdraw,            0644, withdraw_show, withdraw_store);
294b3b94faaSDavid Teigland GFS2_ATTR(statfs_sync,         0200, NULL,          statfs_sync_store);
295b3b94faaSDavid Teigland GFS2_ATTR(quota_sync,          0200, NULL,          quota_sync_store);
296b3b94faaSDavid Teigland GFS2_ATTR(quota_refresh_user,  0200, NULL,          quota_refresh_user_store);
297b3b94faaSDavid Teigland GFS2_ATTR(quota_refresh_group, 0200, NULL,          quota_refresh_group_store);
29864d576baSSteven Whitehouse GFS2_ATTR(demote_rq,           0200, NULL,	    demote_rq_store);
299b3b94faaSDavid Teigland 
300b3b94faaSDavid Teigland static struct attribute *gfs2_attrs[] = {
301b3b94faaSDavid Teigland 	&gfs2_attr_id.attr,
302b3b94faaSDavid Teigland 	&gfs2_attr_fsname.attr,
30302e3cc70SSteven Whitehouse 	&gfs2_attr_uuid.attr,
304b3b94faaSDavid Teigland 	&gfs2_attr_freeze.attr,
305b3b94faaSDavid Teigland 	&gfs2_attr_withdraw.attr,
306b3b94faaSDavid Teigland 	&gfs2_attr_statfs_sync.attr,
307b3b94faaSDavid Teigland 	&gfs2_attr_quota_sync.attr,
308b3b94faaSDavid Teigland 	&gfs2_attr_quota_refresh_user.attr,
309b3b94faaSDavid Teigland 	&gfs2_attr_quota_refresh_group.attr,
31064d576baSSteven Whitehouse 	&gfs2_attr_demote_rq.attr,
311b3b94faaSDavid Teigland 	NULL,
312b3b94faaSDavid Teigland };
313b3b94faaSDavid Teigland 
3140d515210SBob Peterson static void gfs2_sbd_release(struct kobject *kobj)
3150d515210SBob Peterson {
3160d515210SBob Peterson 	struct gfs2_sbd *sdp = container_of(kobj, struct gfs2_sbd, sd_kobj);
3170d515210SBob Peterson 
3180d515210SBob Peterson 	kfree(sdp);
3190d515210SBob Peterson }
3200d515210SBob Peterson 
321b3b94faaSDavid Teigland static struct kobj_type gfs2_ktype = {
3220d515210SBob Peterson 	.release = gfs2_sbd_release,
323b3b94faaSDavid Teigland 	.default_attrs = gfs2_attrs,
324b3b94faaSDavid Teigland 	.sysfs_ops     = &gfs2_attr_ops,
325b3b94faaSDavid Teigland };
326b3b94faaSDavid Teigland 
327f057f6cdSSteven Whitehouse 
328f057f6cdSSteven Whitehouse /*
329f057f6cdSSteven Whitehouse  * lock_module. Originally from lock_dlm
330f057f6cdSSteven Whitehouse  */
331f057f6cdSSteven Whitehouse 
332f057f6cdSSteven Whitehouse static ssize_t proto_name_show(struct gfs2_sbd *sdp, char *buf)
333f057f6cdSSteven Whitehouse {
334f057f6cdSSteven Whitehouse 	const struct lm_lockops *ops = sdp->sd_lockstruct.ls_ops;
335f057f6cdSSteven Whitehouse 	return sprintf(buf, "%s\n", ops->lm_proto_name);
336f057f6cdSSteven Whitehouse }
337f057f6cdSSteven Whitehouse 
338f057f6cdSSteven Whitehouse static ssize_t block_show(struct gfs2_sbd *sdp, char *buf)
339f057f6cdSSteven Whitehouse {
340f057f6cdSSteven Whitehouse 	struct lm_lockstruct *ls = &sdp->sd_lockstruct;
341f057f6cdSSteven Whitehouse 	ssize_t ret;
342f057f6cdSSteven Whitehouse 	int val = 0;
343f057f6cdSSteven Whitehouse 
344e0c2a9aaSDavid Teigland 	if (test_bit(DFL_BLOCK_LOCKS, &ls->ls_recover_flags))
345f057f6cdSSteven Whitehouse 		val = 1;
346f057f6cdSSteven Whitehouse 	ret = sprintf(buf, "%d\n", val);
347f057f6cdSSteven Whitehouse 	return ret;
348f057f6cdSSteven Whitehouse }
349f057f6cdSSteven Whitehouse 
350f057f6cdSSteven Whitehouse static ssize_t block_store(struct gfs2_sbd *sdp, const char *buf, size_t len)
351f057f6cdSSteven Whitehouse {
352f057f6cdSSteven Whitehouse 	struct lm_lockstruct *ls = &sdp->sd_lockstruct;
353e50ead48SFabian Frederick 	int ret, val;
354f057f6cdSSteven Whitehouse 
355e50ead48SFabian Frederick 	ret = kstrtoint(buf, 0, &val);
356e50ead48SFabian Frederick 	if (ret)
357e50ead48SFabian Frederick 		return ret;
358f057f6cdSSteven Whitehouse 
359f057f6cdSSteven Whitehouse 	if (val == 1)
360e0c2a9aaSDavid Teigland 		set_bit(DFL_BLOCK_LOCKS, &ls->ls_recover_flags);
361f057f6cdSSteven Whitehouse 	else if (val == 0) {
362e0c2a9aaSDavid Teigland 		clear_bit(DFL_BLOCK_LOCKS, &ls->ls_recover_flags);
3634e857c58SPeter Zijlstra 		smp_mb__after_atomic();
364f057f6cdSSteven Whitehouse 		gfs2_glock_thaw(sdp);
365f057f6cdSSteven Whitehouse 	} else {
366e50ead48SFabian Frederick 		return -EINVAL;
367f057f6cdSSteven Whitehouse 	}
368e50ead48SFabian Frederick 	return len;
369f057f6cdSSteven Whitehouse }
370f057f6cdSSteven Whitehouse 
371fd95e81cSSteven Whitehouse static ssize_t wdack_show(struct gfs2_sbd *sdp, char *buf)
372fd95e81cSSteven Whitehouse {
373fd95e81cSSteven Whitehouse 	int val = completion_done(&sdp->sd_wdack) ? 1 : 0;
374fd95e81cSSteven Whitehouse 
375fd95e81cSSteven Whitehouse 	return sprintf(buf, "%d\n", val);
376fd95e81cSSteven Whitehouse }
377fd95e81cSSteven Whitehouse 
378fd95e81cSSteven Whitehouse static ssize_t wdack_store(struct gfs2_sbd *sdp, const char *buf, size_t len)
379fd95e81cSSteven Whitehouse {
380e50ead48SFabian Frederick 	int ret, val;
381fd95e81cSSteven Whitehouse 
382e50ead48SFabian Frederick 	ret = kstrtoint(buf, 0, &val);
383e50ead48SFabian Frederick 	if (ret)
384e50ead48SFabian Frederick 		return ret;
385fd95e81cSSteven Whitehouse 
386fd95e81cSSteven Whitehouse 	if ((val == 1) &&
387fd95e81cSSteven Whitehouse 	    !strcmp(sdp->sd_lockstruct.ls_ops->lm_proto_name, "lock_dlm"))
388fd95e81cSSteven Whitehouse 		complete(&sdp->sd_wdack);
389fd95e81cSSteven Whitehouse 	else
390e50ead48SFabian Frederick 		return -EINVAL;
391e50ead48SFabian Frederick 	return len;
392fd95e81cSSteven Whitehouse }
393fd95e81cSSteven Whitehouse 
394f057f6cdSSteven Whitehouse static ssize_t lkfirst_show(struct gfs2_sbd *sdp, char *buf)
395f057f6cdSSteven Whitehouse {
396f057f6cdSSteven Whitehouse 	struct lm_lockstruct *ls = &sdp->sd_lockstruct;
397f057f6cdSSteven Whitehouse 	return sprintf(buf, "%d\n", ls->ls_first);
398f057f6cdSSteven Whitehouse }
399f057f6cdSSteven Whitehouse 
400ba6e9364SSteven Whitehouse static ssize_t lkfirst_store(struct gfs2_sbd *sdp, const char *buf, size_t len)
401ba6e9364SSteven Whitehouse {
402ba6e9364SSteven Whitehouse 	unsigned first;
403ba6e9364SSteven Whitehouse 	int rv;
404ba6e9364SSteven Whitehouse 
405ba6e9364SSteven Whitehouse 	rv = sscanf(buf, "%u", &first);
406ba6e9364SSteven Whitehouse 	if (rv != 1 || first > 1)
407ba6e9364SSteven Whitehouse 		return -EINVAL;
4083942ae53SSteven Whitehouse 	rv = wait_for_completion_killable(&sdp->sd_locking_init);
4093942ae53SSteven Whitehouse 	if (rv)
4103942ae53SSteven Whitehouse 		return rv;
411ba6e9364SSteven Whitehouse 	spin_lock(&sdp->sd_jindex_spin);
412ba6e9364SSteven Whitehouse 	rv = -EBUSY;
413ba6e9364SSteven Whitehouse 	if (test_bit(SDF_NOJOURNALID, &sdp->sd_flags) == 0)
414ba6e9364SSteven Whitehouse 		goto out;
415ba6e9364SSteven Whitehouse 	rv = -EINVAL;
416ba6e9364SSteven Whitehouse 	if (sdp->sd_args.ar_spectator)
417ba6e9364SSteven Whitehouse 		goto out;
418ba6e9364SSteven Whitehouse 	if (sdp->sd_lockstruct.ls_ops->lm_mount == NULL)
419ba6e9364SSteven Whitehouse 		goto out;
420ba6e9364SSteven Whitehouse 	sdp->sd_lockstruct.ls_first = first;
421ba6e9364SSteven Whitehouse 	rv = 0;
422ba6e9364SSteven Whitehouse out:
423ba6e9364SSteven Whitehouse         spin_unlock(&sdp->sd_jindex_spin);
424ba6e9364SSteven Whitehouse         return rv ? rv : len;
425ba6e9364SSteven Whitehouse }
426ba6e9364SSteven Whitehouse 
427f057f6cdSSteven Whitehouse static ssize_t first_done_show(struct gfs2_sbd *sdp, char *buf)
428f057f6cdSSteven Whitehouse {
429f057f6cdSSteven Whitehouse 	struct lm_lockstruct *ls = &sdp->sd_lockstruct;
430e0c2a9aaSDavid Teigland 	return sprintf(buf, "%d\n", !!test_bit(DFL_FIRST_MOUNT_DONE, &ls->ls_recover_flags));
431f057f6cdSSteven Whitehouse }
432f057f6cdSSteven Whitehouse 
433e0c2a9aaSDavid Teigland int gfs2_recover_set(struct gfs2_sbd *sdp, unsigned jid)
434f057f6cdSSteven Whitehouse {
435f057f6cdSSteven Whitehouse 	struct gfs2_jdesc *jd;
436fe64d517SSteven Whitehouse 	int rv;
437f057f6cdSSteven Whitehouse 
4380e48e055SBob Peterson 	/* Wait for our primary journal to be initialized */
4390e48e055SBob Peterson 	wait_for_completion(&sdp->sd_journal_ready);
4400e48e055SBob Peterson 
441f057f6cdSSteven Whitehouse 	spin_lock(&sdp->sd_jindex_spin);
442fe64d517SSteven Whitehouse 	rv = -EBUSY;
443fe64d517SSteven Whitehouse 	if (sdp->sd_jdesc->jd_jid == jid)
444fe64d517SSteven Whitehouse 		goto out;
445fe64d517SSteven Whitehouse 	rv = -ENOENT;
446f057f6cdSSteven Whitehouse 	list_for_each_entry(jd, &sdp->sd_jindex_list, jd_list) {
447f057f6cdSSteven Whitehouse 		if (jd->jd_jid != jid)
448f057f6cdSSteven Whitehouse 			continue;
4496ecd7c2dSTejun Heo 		rv = gfs2_recover_journal(jd, false);
450f057f6cdSSteven Whitehouse 		break;
451f057f6cdSSteven Whitehouse 	}
452fe64d517SSteven Whitehouse out:
453f057f6cdSSteven Whitehouse 	spin_unlock(&sdp->sd_jindex_spin);
454e0c2a9aaSDavid Teigland 	return rv;
455e0c2a9aaSDavid Teigland }
456e0c2a9aaSDavid Teigland 
457e0c2a9aaSDavid Teigland static ssize_t recover_store(struct gfs2_sbd *sdp, const char *buf, size_t len)
458e0c2a9aaSDavid Teigland {
459e0c2a9aaSDavid Teigland 	unsigned jid;
460e0c2a9aaSDavid Teigland 	int rv;
461e0c2a9aaSDavid Teigland 
462e0c2a9aaSDavid Teigland 	rv = sscanf(buf, "%u", &jid);
463e0c2a9aaSDavid Teigland 	if (rv != 1)
464e0c2a9aaSDavid Teigland 		return -EINVAL;
465e0c2a9aaSDavid Teigland 
4661a058f52SDavid Teigland 	if (test_bit(SDF_NORECOVERY, &sdp->sd_flags)) {
4671a058f52SDavid Teigland 		rv = -ESHUTDOWN;
4681a058f52SDavid Teigland 		goto out;
4691a058f52SDavid Teigland 	}
470e0c2a9aaSDavid Teigland 
4711a058f52SDavid Teigland 	rv = gfs2_recover_set(sdp, jid);
4721a058f52SDavid Teigland out:
473fe64d517SSteven Whitehouse 	return rv ? rv : len;
474f057f6cdSSteven Whitehouse }
475f057f6cdSSteven Whitehouse 
476f057f6cdSSteven Whitehouse static ssize_t recover_done_show(struct gfs2_sbd *sdp, char *buf)
477f057f6cdSSteven Whitehouse {
478f057f6cdSSteven Whitehouse 	struct lm_lockstruct *ls = &sdp->sd_lockstruct;
479f057f6cdSSteven Whitehouse 	return sprintf(buf, "%d\n", ls->ls_recover_jid_done);
480f057f6cdSSteven Whitehouse }
481f057f6cdSSteven Whitehouse 
482f057f6cdSSteven Whitehouse static ssize_t recover_status_show(struct gfs2_sbd *sdp, char *buf)
483f057f6cdSSteven Whitehouse {
484f057f6cdSSteven Whitehouse 	struct lm_lockstruct *ls = &sdp->sd_lockstruct;
485f057f6cdSSteven Whitehouse 	return sprintf(buf, "%d\n", ls->ls_recover_jid_status);
486f057f6cdSSteven Whitehouse }
487f057f6cdSSteven Whitehouse 
488e1b28aabSSteven Whitehouse static ssize_t jid_show(struct gfs2_sbd *sdp, char *buf)
489e1b28aabSSteven Whitehouse {
490feb47ca9SSteven Whitehouse 	return sprintf(buf, "%d\n", sdp->sd_lockstruct.ls_jid);
491e1b28aabSSteven Whitehouse }
492e1b28aabSSteven Whitehouse 
493ba6e9364SSteven Whitehouse static ssize_t jid_store(struct gfs2_sbd *sdp, const char *buf, size_t len)
494ba6e9364SSteven Whitehouse {
495feb47ca9SSteven Whitehouse         int jid;
496ba6e9364SSteven Whitehouse 	int rv;
497ba6e9364SSteven Whitehouse 
498feb47ca9SSteven Whitehouse 	rv = sscanf(buf, "%d", &jid);
499ba6e9364SSteven Whitehouse 	if (rv != 1)
500ba6e9364SSteven Whitehouse 		return -EINVAL;
5013942ae53SSteven Whitehouse 	rv = wait_for_completion_killable(&sdp->sd_locking_init);
5023942ae53SSteven Whitehouse 	if (rv)
5033942ae53SSteven Whitehouse 		return rv;
504ba6e9364SSteven Whitehouse 	spin_lock(&sdp->sd_jindex_spin);
505ba6e9364SSteven Whitehouse 	rv = -EINVAL;
506ba6e9364SSteven Whitehouse 	if (sdp->sd_lockstruct.ls_ops->lm_mount == NULL)
507ba6e9364SSteven Whitehouse 		goto out;
508ba6e9364SSteven Whitehouse 	rv = -EBUSY;
509feb47ca9SSteven Whitehouse 	if (test_bit(SDF_NOJOURNALID, &sdp->sd_flags) == 0)
510ba6e9364SSteven Whitehouse 		goto out;
511feb47ca9SSteven Whitehouse 	rv = 0;
512feb47ca9SSteven Whitehouse 	if (sdp->sd_args.ar_spectator && jid > 0)
513feb47ca9SSteven Whitehouse 		rv = jid = -EINVAL;
514ba6e9364SSteven Whitehouse 	sdp->sd_lockstruct.ls_jid = jid;
515feb47ca9SSteven Whitehouse 	clear_bit(SDF_NOJOURNALID, &sdp->sd_flags);
5164e857c58SPeter Zijlstra 	smp_mb__after_atomic();
517ba6e9364SSteven Whitehouse 	wake_up_bit(&sdp->sd_flags, SDF_NOJOURNALID);
518ba6e9364SSteven Whitehouse out:
519ba6e9364SSteven Whitehouse 	spin_unlock(&sdp->sd_jindex_spin);
520ba6e9364SSteven Whitehouse 	return rv ? rv : len;
521ba6e9364SSteven Whitehouse }
522ba6e9364SSteven Whitehouse 
523f057f6cdSSteven Whitehouse #define GDLM_ATTR(_name,_mode,_show,_store) \
52448c2b613SSteven Whitehouse static struct gfs2_attr gdlm_attr_##_name = __ATTR(_name,_mode,_show,_store)
525f057f6cdSSteven Whitehouse 
526f057f6cdSSteven Whitehouse GDLM_ATTR(proto_name,		0444, proto_name_show,		NULL);
527f057f6cdSSteven Whitehouse GDLM_ATTR(block,		0644, block_show,		block_store);
528fd95e81cSSteven Whitehouse GDLM_ATTR(withdraw,		0644, wdack_show,		wdack_store);
529ba6e9364SSteven Whitehouse GDLM_ATTR(jid,			0644, jid_show,			jid_store);
530ba6e9364SSteven Whitehouse GDLM_ATTR(first,		0644, lkfirst_show,		lkfirst_store);
531f057f6cdSSteven Whitehouse GDLM_ATTR(first_done,		0444, first_done_show,		NULL);
532d7e623daSSteven Whitehouse GDLM_ATTR(recover,		0600, NULL,			recover_store);
533f057f6cdSSteven Whitehouse GDLM_ATTR(recover_done,		0444, recover_done_show,	NULL);
534f057f6cdSSteven Whitehouse GDLM_ATTR(recover_status,	0444, recover_status_show,	NULL);
535f057f6cdSSteven Whitehouse 
536f057f6cdSSteven Whitehouse static struct attribute *lock_module_attrs[] = {
537f057f6cdSSteven Whitehouse 	&gdlm_attr_proto_name.attr,
538f057f6cdSSteven Whitehouse 	&gdlm_attr_block.attr,
539f057f6cdSSteven Whitehouse 	&gdlm_attr_withdraw.attr,
540e1b28aabSSteven Whitehouse 	&gdlm_attr_jid.attr,
541f057f6cdSSteven Whitehouse 	&gdlm_attr_first.attr,
542f057f6cdSSteven Whitehouse 	&gdlm_attr_first_done.attr,
543f057f6cdSSteven Whitehouse 	&gdlm_attr_recover.attr,
544f057f6cdSSteven Whitehouse 	&gdlm_attr_recover_done.attr,
545f057f6cdSSteven Whitehouse 	&gdlm_attr_recover_status.attr,
546ea67eedbSSteven Whitehouse 	NULL,
547b3b94faaSDavid Teigland };
548b3b94faaSDavid Teigland 
549b3b94faaSDavid Teigland /*
550b3b94faaSDavid Teigland  * get and set struct gfs2_tune fields
551b3b94faaSDavid Teigland  */
552b3b94faaSDavid Teigland 
553b3b94faaSDavid Teigland static ssize_t quota_scale_show(struct gfs2_sbd *sdp, char *buf)
554b3b94faaSDavid Teigland {
5553204a6c0SDavid Teigland 	return snprintf(buf, PAGE_SIZE, "%u %u\n",
5563204a6c0SDavid Teigland 			sdp->sd_tune.gt_quota_scale_num,
557b3b94faaSDavid Teigland 			sdp->sd_tune.gt_quota_scale_den);
558b3b94faaSDavid Teigland }
559b3b94faaSDavid Teigland 
560b3b94faaSDavid Teigland static ssize_t quota_scale_store(struct gfs2_sbd *sdp, const char *buf,
561b3b94faaSDavid Teigland 				 size_t len)
562b3b94faaSDavid Teigland {
563b3b94faaSDavid Teigland 	struct gfs2_tune *gt = &sdp->sd_tune;
564b3b94faaSDavid Teigland 	unsigned int x, y;
565b3b94faaSDavid Teigland 
566b3b94faaSDavid Teigland 	if (!capable(CAP_SYS_ADMIN))
56741735818SZhao Hongjiang 		return -EPERM;
568b3b94faaSDavid Teigland 
569b3b94faaSDavid Teigland 	if (sscanf(buf, "%u %u", &x, &y) != 2 || !y)
570b3b94faaSDavid Teigland 		return -EINVAL;
571b3b94faaSDavid Teigland 
572b3b94faaSDavid Teigland 	spin_lock(&gt->gt_spin);
573b3b94faaSDavid Teigland 	gt->gt_quota_scale_num = x;
574b3b94faaSDavid Teigland 	gt->gt_quota_scale_den = y;
575b3b94faaSDavid Teigland 	spin_unlock(&gt->gt_spin);
576b3b94faaSDavid Teigland 	return len;
577b3b94faaSDavid Teigland }
578b3b94faaSDavid Teigland 
579b3b94faaSDavid Teigland static ssize_t tune_set(struct gfs2_sbd *sdp, unsigned int *field,
580b3b94faaSDavid Teigland 			int check_zero, const char *buf, size_t len)
581b3b94faaSDavid Teigland {
582b3b94faaSDavid Teigland 	struct gfs2_tune *gt = &sdp->sd_tune;
583b3b94faaSDavid Teigland 	unsigned int x;
584e50ead48SFabian Frederick 	int error;
585b3b94faaSDavid Teigland 
586b3b94faaSDavid Teigland 	if (!capable(CAP_SYS_ADMIN))
58741735818SZhao Hongjiang 		return -EPERM;
588b3b94faaSDavid Teigland 
589e50ead48SFabian Frederick 	error = kstrtouint(buf, 0, &x);
590e50ead48SFabian Frederick 	if (error)
591e50ead48SFabian Frederick 		return error;
592b3b94faaSDavid Teigland 
593b3b94faaSDavid Teigland 	if (check_zero && !x)
594b3b94faaSDavid Teigland 		return -EINVAL;
595b3b94faaSDavid Teigland 
596b3b94faaSDavid Teigland 	spin_lock(&gt->gt_spin);
597b3b94faaSDavid Teigland 	*field = x;
598b3b94faaSDavid Teigland 	spin_unlock(&gt->gt_spin);
599b3b94faaSDavid Teigland 	return len;
600b3b94faaSDavid Teigland }
601b3b94faaSDavid Teigland 
602b3b94faaSDavid Teigland #define TUNE_ATTR_3(name, show, store)                                        \
60348c2b613SSteven Whitehouse static struct gfs2_attr tune_attr_##name = __ATTR(name, 0644, show, store)
604b3b94faaSDavid Teigland 
605b3b94faaSDavid Teigland #define TUNE_ATTR_2(name, store)                                              \
606b3b94faaSDavid Teigland static ssize_t name##_show(struct gfs2_sbd *sdp, char *buf)                   \
607b3b94faaSDavid Teigland {                                                                             \
6083204a6c0SDavid Teigland 	return snprintf(buf, PAGE_SIZE, "%u\n", sdp->sd_tune.gt_##name);      \
609b3b94faaSDavid Teigland }                                                                             \
610b3b94faaSDavid Teigland TUNE_ATTR_3(name, name##_show, store)
611b3b94faaSDavid Teigland 
612b3b94faaSDavid Teigland #define TUNE_ATTR(name, check_zero)                                           \
613b3b94faaSDavid Teigland static ssize_t name##_store(struct gfs2_sbd *sdp, const char *buf, size_t len)\
614b3b94faaSDavid Teigland {                                                                             \
615b3b94faaSDavid Teigland 	return tune_set(sdp, &sdp->sd_tune.gt_##name, check_zero, buf, len);  \
616b3b94faaSDavid Teigland }                                                                             \
617b3b94faaSDavid Teigland TUNE_ATTR_2(name, name##_store)
618b3b94faaSDavid Teigland 
619b3b94faaSDavid Teigland TUNE_ATTR(quota_warn_period, 0);
620b3b94faaSDavid Teigland TUNE_ATTR(quota_quantum, 0);
621b3b94faaSDavid Teigland TUNE_ATTR(max_readahead, 0);
622b3b94faaSDavid Teigland TUNE_ATTR(complain_secs, 0);
623b3b94faaSDavid Teigland TUNE_ATTR(statfs_slow, 0);
624b3b94faaSDavid Teigland TUNE_ATTR(new_files_jdata, 0);
625b3b94faaSDavid Teigland TUNE_ATTR(statfs_quantum, 1);
626b3b94faaSDavid Teigland TUNE_ATTR_3(quota_scale, quota_scale_show, quota_scale_store);
627b3b94faaSDavid Teigland 
628b3b94faaSDavid Teigland static struct attribute *tune_attrs[] = {
629b3b94faaSDavid Teigland 	&tune_attr_quota_warn_period.attr,
630b3b94faaSDavid Teigland 	&tune_attr_quota_quantum.attr,
631b3b94faaSDavid Teigland 	&tune_attr_max_readahead.attr,
632b3b94faaSDavid Teigland 	&tune_attr_complain_secs.attr,
633b3b94faaSDavid Teigland 	&tune_attr_statfs_slow.attr,
634b3b94faaSDavid Teigland 	&tune_attr_statfs_quantum.attr,
635b3b94faaSDavid Teigland 	&tune_attr_quota_scale.attr,
636b3b94faaSDavid Teigland 	&tune_attr_new_files_jdata.attr,
637ea67eedbSSteven Whitehouse 	NULL,
638b3b94faaSDavid Teigland };
639b3b94faaSDavid Teigland 
640b3b94faaSDavid Teigland static struct attribute_group tune_group = {
641b3b94faaSDavid Teigland 	.name = "tune",
642ea67eedbSSteven Whitehouse 	.attrs = tune_attrs,
643b3b94faaSDavid Teigland };
644b3b94faaSDavid Teigland 
645f057f6cdSSteven Whitehouse static struct attribute_group lock_module_group = {
646f057f6cdSSteven Whitehouse 	.name = "lock_module",
647f057f6cdSSteven Whitehouse 	.attrs = lock_module_attrs,
648f057f6cdSSteven Whitehouse };
649f057f6cdSSteven Whitehouse 
650b3b94faaSDavid Teigland int gfs2_sys_fs_add(struct gfs2_sbd *sdp)
651b3b94faaSDavid Teigland {
652440d6da2SSteven Whitehouse 	struct super_block *sb = sdp->sd_vfs;
653b3b94faaSDavid Teigland 	int error;
654440d6da2SSteven Whitehouse 	char ro[20];
655440d6da2SSteven Whitehouse 	char spectator[20];
656440d6da2SSteven Whitehouse 	char *envp[] = { ro, spectator, NULL };
6570d515210SBob Peterson 	int sysfs_frees_sdp = 0;
658440d6da2SSteven Whitehouse 
659440d6da2SSteven Whitehouse 	sprintf(ro, "RDONLY=%d", (sb->s_flags & MS_RDONLY) ? 1 : 0);
660440d6da2SSteven Whitehouse 	sprintf(spectator, "SPECTATOR=%d", sdp->sd_args.ar_spectator ? 1 : 0);
661b3b94faaSDavid Teigland 
6629bec101aSGreg Kroah-Hartman 	sdp->sd_kobj.kset = gfs2_kset;
663901195edSGreg Kroah-Hartman 	error = kobject_init_and_add(&sdp->sd_kobj, &gfs2_ktype, NULL,
664901195edSGreg Kroah-Hartman 				     "%s", sdp->sd_table_name);
665b3b94faaSDavid Teigland 	if (error)
6660d515210SBob Peterson 		goto fail_reg;
667b3b94faaSDavid Teigland 
6680d515210SBob Peterson 	sysfs_frees_sdp = 1; /* Freeing sdp is now done by sysfs calling
6690d515210SBob Peterson 				function gfs2_sbd_release. */
670b3b94faaSDavid Teigland 	error = sysfs_create_group(&sdp->sd_kobj, &tune_group);
671b3b94faaSDavid Teigland 	if (error)
672f6eb5349SSteven Whitehouse 		goto fail_reg;
673b3b94faaSDavid Teigland 
674f057f6cdSSteven Whitehouse 	error = sysfs_create_group(&sdp->sd_kobj, &lock_module_group);
675f057f6cdSSteven Whitehouse 	if (error)
676f057f6cdSSteven Whitehouse 		goto fail_tune;
677f057f6cdSSteven Whitehouse 
67831e54b01SSteven Whitehouse 	error = sysfs_create_link(&sdp->sd_kobj,
67931e54b01SSteven Whitehouse 				  &disk_to_dev(sb->s_bdev->bd_disk)->kobj,
68031e54b01SSteven Whitehouse 				  "device");
68131e54b01SSteven Whitehouse 	if (error)
68231e54b01SSteven Whitehouse 		goto fail_lock_module;
68331e54b01SSteven Whitehouse 
684440d6da2SSteven Whitehouse 	kobject_uevent_env(&sdp->sd_kobj, KOBJ_ADD, envp);
685b3b94faaSDavid Teigland 	return 0;
686b3b94faaSDavid Teigland 
68731e54b01SSteven Whitehouse fail_lock_module:
68831e54b01SSteven Whitehouse 	sysfs_remove_group(&sdp->sd_kobj, &lock_module_group);
689f057f6cdSSteven Whitehouse fail_tune:
690f057f6cdSSteven Whitehouse 	sysfs_remove_group(&sdp->sd_kobj, &tune_group);
691b3b94faaSDavid Teigland fail_reg:
6920d515210SBob Peterson 	free_percpu(sdp->sd_lkstats);
69365952fb4SDavid Teigland 	fs_err(sdp, "error %d adding sysfs files", error);
6940d515210SBob Peterson 	if (sysfs_frees_sdp)
6950d515210SBob Peterson 		kobject_put(&sdp->sd_kobj);
6960d515210SBob Peterson 	else
6970d515210SBob Peterson 		kfree(sdp);
6980d515210SBob Peterson 	sb->s_fs_info = NULL;
699b3b94faaSDavid Teigland 	return error;
700b3b94faaSDavid Teigland }
701b3b94faaSDavid Teigland 
702b3b94faaSDavid Teigland void gfs2_sys_fs_del(struct gfs2_sbd *sdp)
703b3b94faaSDavid Teigland {
70431e54b01SSteven Whitehouse 	sysfs_remove_link(&sdp->sd_kobj, "device");
705b3b94faaSDavid Teigland 	sysfs_remove_group(&sdp->sd_kobj, &tune_group);
706f057f6cdSSteven Whitehouse 	sysfs_remove_group(&sdp->sd_kobj, &lock_module_group);
707197b12d6SGreg Kroah-Hartman 	kobject_put(&sdp->sd_kobj);
708b3b94faaSDavid Teigland }
709b3b94faaSDavid Teigland 
710fdd1062eSSteven Whitehouse static int gfs2_uevent(struct kset *kset, struct kobject *kobj,
711fdd1062eSSteven Whitehouse 		       struct kobj_uevent_env *env)
712fdd1062eSSteven Whitehouse {
713fdd1062eSSteven Whitehouse 	struct gfs2_sbd *sdp = container_of(kobj, struct gfs2_sbd, sd_kobj);
71432e471efSSteven Whitehouse 	struct super_block *s = sdp->sd_vfs;
71532e471efSSteven Whitehouse 	const u8 *uuid = s->s_uuid;
71602e3cc70SSteven Whitehouse 
717fdd1062eSSteven Whitehouse 	add_uevent_var(env, "LOCKTABLE=%s", sdp->sd_table_name);
718fdd1062eSSteven Whitehouse 	add_uevent_var(env, "LOCKPROTO=%s", sdp->sd_proto_name);
719ba6e9364SSteven Whitehouse 	if (!test_bit(SDF_NOJOURNALID, &sdp->sd_flags))
720feb47ca9SSteven Whitehouse 		add_uevent_var(env, "JOURNALID=%d", sdp->sd_lockstruct.ls_jid);
721f0b34ae6SJoe Perches 	if (gfs2_uuid_valid(uuid))
722f0b34ae6SJoe Perches 		add_uevent_var(env, "UUID=%pUB", uuid);
723fdd1062eSSteven Whitehouse 	return 0;
724fdd1062eSSteven Whitehouse }
725fdd1062eSSteven Whitehouse 
7269cd43611SEmese Revfy static const struct kset_uevent_ops gfs2_uevent_ops = {
727fdd1062eSSteven Whitehouse 	.uevent = gfs2_uevent,
728fdd1062eSSteven Whitehouse };
729fdd1062eSSteven Whitehouse 
730b3b94faaSDavid Teigland int gfs2_sys_init(void)
731b3b94faaSDavid Teigland {
732fdd1062eSSteven Whitehouse 	gfs2_kset = kset_create_and_add("gfs2", &gfs2_uevent_ops, fs_kobj);
7339bec101aSGreg Kroah-Hartman 	if (!gfs2_kset)
7349bec101aSGreg Kroah-Hartman 		return -ENOMEM;
7359bec101aSGreg Kroah-Hartman 	return 0;
736b3b94faaSDavid Teigland }
737b3b94faaSDavid Teigland 
738b3b94faaSDavid Teigland void gfs2_sys_uninit(void)
739b3b94faaSDavid Teigland {
7409bec101aSGreg Kroah-Hartman 	kset_unregister(gfs2_kset);
741b3b94faaSDavid Teigland }
742b3b94faaSDavid Teigland 
743