aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2009-02-12 08:31:58 -0500
committerSteven Whitehouse <steve@dolmen.chygwyn.com>2009-03-24 07:21:22 -0400
commit64d576ba23bfd9b770cbb0279200f479272eb859 (patch)
tree8c119b0e45d288035fc24fd43cf5286da1947fb1 /fs
parent02e3cc70ecbd4352ae4d26459929f43ab1547251 (diff)
GFS2: Add a "demote a glock" interface to sysfs
This adds a sysfs file called demote_rq to GFS2's per filesystem directory. Its possible to use this file to demote arbitrary glocks in exactly the same way as if a request had come in from a remote node. This is intended for testing issues relating to caching of data under glocks. Despite that, the interface is generic enough to send requests to any type of glock, but be careful as its not always safe to send an arbitrary message to an arbitrary glock. For that reason and to prevent DoS, this interface is restricted to root only. The messages look like this: <type>:<glocknumber> <mode> Example: echo -n "2:13324 EX" >/sys/fs/gfs2/unity:myfs/demote_rq Which means "please demote inode glock (type 2) number 13324 so that I can get an EX (exclusive) lock". The lock modes are those which would normally be sent by a remote node in its callback so if you want to unlock a glock, you use EX, to demote to shared, use SH or PR (depending on whether you like GFS2 or DLM lock modes better!). If the glock doesn't exist, you'll get -ENOENT returned. If the arguments don't make sense, you'll get -EINVAL returned. The plan is that this interface will be used in combination with the blktrace patch which I recently posted for comments although it is, of course, still useful in its own right. Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/gfs2/glock.c7
-rw-r--r--fs/gfs2/glops.c12
-rw-r--r--fs/gfs2/glops.h1
-rw-r--r--fs/gfs2/rgrp.c2
-rw-r--r--fs/gfs2/sys.c43
5 files changed, 61 insertions, 4 deletions
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index ad8e121427c0..3984e47d1d33 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -684,10 +684,11 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
684 gl = search_bucket(hash, sdp, &name); 684 gl = search_bucket(hash, sdp, &name);
685 read_unlock(gl_lock_addr(hash)); 685 read_unlock(gl_lock_addr(hash));
686 686
687 if (gl || !create) { 687 *glp = gl;
688 *glp = gl; 688 if (gl)
689 return 0; 689 return 0;
690 } 690 if (!create)
691 return -ENOENT;
691 692
692 gl = kmem_cache_alloc(gfs2_glock_cachep, GFP_KERNEL); 693 gl = kmem_cache_alloc(gfs2_glock_cachep, GFP_KERNEL);
693 if (!gl) 694 if (!gl)
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index a9b7d3a60081..f34bc7093dd1 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -447,3 +447,15 @@ const struct gfs2_glock_operations gfs2_journal_glops = {
447 .go_type = LM_TYPE_JOURNAL, 447 .go_type = LM_TYPE_JOURNAL,
448}; 448};
449 449
450const struct gfs2_glock_operations *gfs2_glops_list[] = {
451 [LM_TYPE_META] = &gfs2_meta_glops,
452 [LM_TYPE_INODE] = &gfs2_inode_glops,
453 [LM_TYPE_RGRP] = &gfs2_rgrp_glops,
454 [LM_TYPE_NONDISK] = &gfs2_trans_glops,
455 [LM_TYPE_IOPEN] = &gfs2_iopen_glops,
456 [LM_TYPE_FLOCK] = &gfs2_flock_glops,
457 [LM_TYPE_NONDISK] = &gfs2_nondisk_glops,
458 [LM_TYPE_QUOTA] = &gfs2_quota_glops,
459 [LM_TYPE_JOURNAL] = &gfs2_journal_glops,
460};
461
diff --git a/fs/gfs2/glops.h b/fs/gfs2/glops.h
index a1d9b5b024e6..b3aa2e3210fd 100644
--- a/fs/gfs2/glops.h
+++ b/fs/gfs2/glops.h
@@ -21,5 +21,6 @@ extern const struct gfs2_glock_operations gfs2_flock_glops;
21extern const struct gfs2_glock_operations gfs2_nondisk_glops; 21extern const struct gfs2_glock_operations gfs2_nondisk_glops;
22extern const struct gfs2_glock_operations gfs2_quota_glops; 22extern const struct gfs2_glock_operations gfs2_quota_glops;
23extern const struct gfs2_glock_operations gfs2_journal_glops; 23extern const struct gfs2_glock_operations gfs2_journal_glops;
24extern const struct gfs2_glock_operations *gfs2_glops_list[];
24 25
25#endif /* __GLOPS_DOT_H__ */ 26#endif /* __GLOPS_DOT_H__ */
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index 789953a2b6a8..a068ac940de1 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -839,7 +839,7 @@ static void gfs2_rgrp_send_discards(struct gfs2_sbd *sdp, u64 offset,
839 const unsigned int sects_per_blk = sdp->sd_sb.sb_bsize / 839 const unsigned int sects_per_blk = sdp->sd_sb.sb_bsize /
840 bdev_hardsect_size(sb->s_bdev); 840 bdev_hardsect_size(sb->s_bdev);
841 u64 blk; 841 u64 blk;
842 sector_t start; 842 sector_t start = 0;
843 sector_t nr_sects = 0; 843 sector_t nr_sects = 0;
844 int rv; 844 int rv;
845 unsigned int x; 845 unsigned int x;
diff --git a/fs/gfs2/sys.c b/fs/gfs2/sys.c
index 4d284d14980b..7655f5025fec 100644
--- a/fs/gfs2/sys.c
+++ b/fs/gfs2/sys.c
@@ -24,6 +24,7 @@
24#include "glock.h" 24#include "glock.h"
25#include "quota.h" 25#include "quota.h"
26#include "util.h" 26#include "util.h"
27#include "glops.h"
27 28
28static ssize_t id_show(struct gfs2_sbd *sdp, char *buf) 29static ssize_t id_show(struct gfs2_sbd *sdp, char *buf)
29{ 30{
@@ -171,6 +172,46 @@ static ssize_t quota_refresh_group_store(struct gfs2_sbd *sdp, const char *buf,
171 return len; 172 return len;
172} 173}
173 174
175static ssize_t demote_rq_store(struct gfs2_sbd *sdp, const char *buf, size_t len)
176{
177 struct gfs2_glock *gl;
178 const struct gfs2_glock_operations *glops;
179 unsigned int glmode;
180 unsigned int gltype;
181 unsigned long long glnum;
182 char mode[16];
183 int rv;
184
185 if (!capable(CAP_SYS_ADMIN))
186 return -EACCES;
187
188 rv = sscanf(buf, "%u:%llu %15s", &gltype, &glnum,
189 mode);
190 if (rv != 3)
191 return -EINVAL;
192
193 if (strcmp(mode, "EX") == 0)
194 glmode = LM_ST_UNLOCKED;
195 else if ((strcmp(mode, "CW") == 0) || (strcmp(mode, "DF") == 0))
196 glmode = LM_ST_DEFERRED;
197 else if ((strcmp(mode, "PR") == 0) || (strcmp(mode, "SH") == 0))
198 glmode = LM_ST_SHARED;
199 else
200 return -EINVAL;
201
202 if (gltype > LM_TYPE_JOURNAL)
203 return -EINVAL;
204 glops = gfs2_glops_list[gltype];
205 if (glops == NULL)
206 return -EINVAL;
207 rv = gfs2_glock_get(sdp, glnum, glops, 0, &gl);
208 if (rv)
209 return rv;
210 gfs2_glock_cb(gl, glmode);
211 gfs2_glock_put(gl);
212 return len;
213}
214
174struct gfs2_attr { 215struct gfs2_attr {
175 struct attribute attr; 216 struct attribute attr;
176 ssize_t (*show)(struct gfs2_sbd *, char *); 217 ssize_t (*show)(struct gfs2_sbd *, char *);
@@ -189,6 +230,7 @@ GFS2_ATTR(statfs_sync, 0200, NULL, statfs_sync_store);
189GFS2_ATTR(quota_sync, 0200, NULL, quota_sync_store); 230GFS2_ATTR(quota_sync, 0200, NULL, quota_sync_store);
190GFS2_ATTR(quota_refresh_user, 0200, NULL, quota_refresh_user_store); 231GFS2_ATTR(quota_refresh_user, 0200, NULL, quota_refresh_user_store);
191GFS2_ATTR(quota_refresh_group, 0200, NULL, quota_refresh_group_store); 232GFS2_ATTR(quota_refresh_group, 0200, NULL, quota_refresh_group_store);
233GFS2_ATTR(demote_rq, 0200, NULL, demote_rq_store);
192 234
193static struct attribute *gfs2_attrs[] = { 235static struct attribute *gfs2_attrs[] = {
194 &gfs2_attr_id.attr, 236 &gfs2_attr_id.attr,
@@ -200,6 +242,7 @@ static struct attribute *gfs2_attrs[] = {
200 &gfs2_attr_quota_sync.attr, 242 &gfs2_attr_quota_sync.attr,
201 &gfs2_attr_quota_refresh_user.attr, 243 &gfs2_attr_quota_refresh_user.attr,
202 &gfs2_attr_quota_refresh_group.attr, 244 &gfs2_attr_quota_refresh_group.attr,
245 &gfs2_attr_demote_rq.attr,
203 NULL, 246 NULL,
204}; 247};
205 248