nfsd: Use write gathering only with NFSv2
[safe/jmp/linux-2.6] / fs / gfs2 / sys.c
index a78997e..7655f50 100644 (file)
@@ -24,6 +24,7 @@
 #include "glock.h"
 #include "quota.h"
 #include "util.h"
+#include "glops.h"
 
 static ssize_t id_show(struct gfs2_sbd *sdp, char *buf)
 {
@@ -36,6 +37,30 @@ static ssize_t fsname_show(struct gfs2_sbd *sdp, char *buf)
        return snprintf(buf, PAGE_SIZE, "%s\n", sdp->sd_fsname);
 }
 
+static int gfs2_uuid_valid(const u8 *uuid)
+{
+       int i;
+
+       for (i = 0; i < 16; i++) {
+               if (uuid[i])
+                       return 1;
+       }
+       return 0;
+}
+
+static ssize_t uuid_show(struct gfs2_sbd *sdp, char *buf)
+{
+       const u8 *uuid = sdp->sd_sb.sb_uuid;
+       buf[0] = '\0';
+       if (!gfs2_uuid_valid(uuid))
+               return 0;
+       return snprintf(buf, PAGE_SIZE, "%02X%02X%02X%02X-%02X%02X-"
+                       "%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X\n",
+                       uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5],
+                       uuid[6], uuid[7], uuid[8], uuid[9], uuid[10], uuid[11],
+                       uuid[12], uuid[13], uuid[14], uuid[15]);
+}
+
 static ssize_t freeze_show(struct gfs2_sbd *sdp, char *buf)
 {
        unsigned int count;
@@ -147,6 +172,46 @@ static ssize_t quota_refresh_group_store(struct gfs2_sbd *sdp, const char *buf,
        return len;
 }
 
+static ssize_t demote_rq_store(struct gfs2_sbd *sdp, const char *buf, size_t len)
+{
+       struct gfs2_glock *gl;
+       const struct gfs2_glock_operations *glops;
+       unsigned int glmode;
+       unsigned int gltype;
+       unsigned long long glnum;
+       char mode[16];
+       int rv;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EACCES;
+
+       rv = sscanf(buf, "%u:%llu %15s", &gltype, &glnum,
+                   mode);
+       if (rv != 3)
+               return -EINVAL;
+
+       if (strcmp(mode, "EX") == 0)
+               glmode = LM_ST_UNLOCKED;
+       else if ((strcmp(mode, "CW") == 0) || (strcmp(mode, "DF") == 0))
+               glmode = LM_ST_DEFERRED;
+       else if ((strcmp(mode, "PR") == 0) || (strcmp(mode, "SH") == 0))
+               glmode = LM_ST_SHARED;
+       else
+               return -EINVAL;
+
+       if (gltype > LM_TYPE_JOURNAL)
+               return -EINVAL;
+       glops = gfs2_glops_list[gltype];
+       if (glops == NULL)
+               return -EINVAL;
+       rv = gfs2_glock_get(sdp, glnum, glops, 0, &gl);
+       if (rv)
+               return rv;
+       gfs2_glock_cb(gl, glmode);
+       gfs2_glock_put(gl);
+       return len;
+}
+
 struct gfs2_attr {
        struct attribute attr;
        ssize_t (*show)(struct gfs2_sbd *, char *);
@@ -158,22 +223,26 @@ static struct gfs2_attr gfs2_attr_##name = __ATTR(name, mode, show, store)
 
 GFS2_ATTR(id,                  0444, id_show,       NULL);
 GFS2_ATTR(fsname,              0444, fsname_show,   NULL);
+GFS2_ATTR(uuid,                0444, uuid_show,     NULL);
 GFS2_ATTR(freeze,              0644, freeze_show,   freeze_store);
 GFS2_ATTR(withdraw,            0644, withdraw_show, withdraw_store);
 GFS2_ATTR(statfs_sync,         0200, NULL,          statfs_sync_store);
 GFS2_ATTR(quota_sync,          0200, NULL,          quota_sync_store);
 GFS2_ATTR(quota_refresh_user,  0200, NULL,          quota_refresh_user_store);
 GFS2_ATTR(quota_refresh_group, 0200, NULL,          quota_refresh_group_store);
+GFS2_ATTR(demote_rq,           0200, NULL,         demote_rq_store);
 
 static struct attribute *gfs2_attrs[] = {
        &gfs2_attr_id.attr,
        &gfs2_attr_fsname.attr,
+       &gfs2_attr_uuid.attr,
        &gfs2_attr_freeze.attr,
        &gfs2_attr_withdraw.attr,
        &gfs2_attr_statfs_sync.attr,
        &gfs2_attr_quota_sync.attr,
        &gfs2_attr_quota_refresh_user.attr,
        &gfs2_attr_quota_refresh_group.attr,
+       &gfs2_attr_demote_rq.attr,
        NULL,
 };
 
@@ -598,12 +667,23 @@ void gfs2_sys_fs_del(struct gfs2_sbd *sdp)
        kobject_put(&sdp->sd_kobj);
 }
 
+
 static int gfs2_uevent(struct kset *kset, struct kobject *kobj,
                       struct kobj_uevent_env *env)
 {
        struct gfs2_sbd *sdp = container_of(kobj, struct gfs2_sbd, sd_kobj);
+       const u8 *uuid = sdp->sd_sb.sb_uuid;
+
        add_uevent_var(env, "LOCKTABLE=%s", sdp->sd_table_name);
        add_uevent_var(env, "LOCKPROTO=%s", sdp->sd_proto_name);
+       if (gfs2_uuid_valid(uuid)) {
+               add_uevent_var(env, "UUID=%02X%02X%02X%02X-%02X%02X-%02X%02X-"
+                              "%02X%02X-%02X%02X%02X%02X%02X%02X",
+                              uuid[0], uuid[1], uuid[2], uuid[3], uuid[4],
+                              uuid[5], uuid[6], uuid[7], uuid[8], uuid[9],
+                              uuid[10], uuid[11], uuid[12], uuid[13],
+                              uuid[14], uuid[15]);
+       }
        return 0;
 }