diff options
Diffstat (limited to 'fs/gfs2/sys.c')
-rw-r--r-- | fs/gfs2/sys.c | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/fs/gfs2/sys.c b/fs/gfs2/sys.c index 4d284d14980..7655f5025fe 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 | ||
28 | static ssize_t id_show(struct gfs2_sbd *sdp, char *buf) | 29 | static 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 | ||
175 | static 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 | |||
174 | struct gfs2_attr { | 215 | struct 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); | |||
189 | GFS2_ATTR(quota_sync, 0200, NULL, quota_sync_store); | 230 | GFS2_ATTR(quota_sync, 0200, NULL, quota_sync_store); |
190 | GFS2_ATTR(quota_refresh_user, 0200, NULL, quota_refresh_user_store); | 231 | GFS2_ATTR(quota_refresh_user, 0200, NULL, quota_refresh_user_store); |
191 | GFS2_ATTR(quota_refresh_group, 0200, NULL, quota_refresh_group_store); | 232 | GFS2_ATTR(quota_refresh_group, 0200, NULL, quota_refresh_group_store); |
233 | GFS2_ATTR(demote_rq, 0200, NULL, demote_rq_store); | ||
192 | 234 | ||
193 | static struct attribute *gfs2_attrs[] = { | 235 | static 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 | ||