This is the mail archive of the
cluster-cvs@sourceware.org
mailing list for the cluster.
cluster: master - gfs_controld: use new uevent strings
- From: David Teigland <teigland at fedoraproject dot org>
- To: cluster-cvs-relay at redhat dot com
- Date: Fri, 5 Dec 2008 21:15:02 +0000 (UTC)
- Subject: cluster: master - gfs_controld: use new uevent strings
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=46e0a2ef75abe03455b9e15f22bed2c53a839014
Commit: 46e0a2ef75abe03455b9e15f22bed2c53a839014
Parent: faa3718fee90f3aa225236218157814a64b0e345
Author: David Teigland <teigland@redhat.com>
AuthorDate: Fri Dec 5 15:08:46 2008 -0600
Committer: David Teigland <teigland@redhat.com>
CommitterDate: Fri Dec 5 15:08:46 2008 -0600
gfs_controld: use new uevent strings
Use the new uevent strings when available, otherwise fall back to
using sysfs files.
(Fixes and some minor munging to Steve's initial patch.)
Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Signed-off-by: David Teigland <teigland@redhat.com>
---
group/gfs_controld/cpg-new.c | 45 +++++----
group/gfs_controld/cpg-old.c | 53 ++++++----
group/gfs_controld/gfs_daemon.h | 9 +-
group/gfs_controld/main.c | 219 +++++++++++++++++++++++---------------
4 files changed, 192 insertions(+), 134 deletions(-)
diff --git a/group/gfs_controld/cpg-new.c b/group/gfs_controld/cpg-new.c
index 74806f6..9d8d5dd 100644
--- a/group/gfs_controld/cpg-new.c
+++ b/group/gfs_controld/cpg-new.c
@@ -2078,30 +2078,35 @@ static void apply_changes(struct mountgroup *mg)
and then process the uevent/ipc upon receiving the message for it, so
that it can be processed in the same order by all nodes. */
-void process_recovery_uevent(char *table)
+void process_recovery_uevent(char *name, int jid, int recover_status,
+ int first_done)
{
struct mountgroup *mg;
struct journal *j;
- char *name = strstr(table, ":") + 1;
- int jid, recover_status, first_done;
int rv;
mg = find_mg(name);
if (!mg) {
- log_error("recovery_uevent mg not found %s", table);
+ log_error("recovery_uevent mg not found %s", name);
return;
}
- rv = read_sysfs_int(mg, "recover_done", &jid);
- if (rv < 0) {
- log_error("recovery_uevent recover_done read %d", rv);
- return;
+ if (jid < 0) {
+ /* for back compat, sysfs file deprecated */
+ rv = read_sysfs_int(mg, "recover_done", &jid);
+ if (rv < 0) {
+ log_error("recovery_uevent recover_done read %d", rv);
+ return;
+ }
}
- rv = read_sysfs_int(mg, "recover_status", &recover_status);
- if (rv < 0) {
- log_error("recovery_uevent recover_status read %d", rv);
- return;
+ if (recover_status < 0) {
+ /* for back compat, sysfs file deprecated */
+ rv = read_sysfs_int(mg, "recover_status", &recover_status);
+ if (rv < 0) {
+ log_error("recovery_uevent recover_status read %d", rv);
+ return;
+ }
}
if (!mg->first_recovery_needed) {
@@ -2162,10 +2167,13 @@ void process_recovery_uevent(char *table)
if (mg->first_done_uevent)
return;
- rv = read_sysfs_int(mg, "first_done", &first_done);
- if (rv < 0) {
- log_error("recovery_uevent first_done read %d", rv);
- return;
+ if (first_done < 0) {
+ /* for back compat, sysfs file deprecated */
+ rv = read_sysfs_int(mg, "first_done", &first_done);
+ if (rv < 0) {
+ log_error("recovery_uevent first_done read %d", rv);
+ return;
+ }
}
if (first_done) {
@@ -2678,12 +2686,11 @@ static void leave_mountgroup(struct mountgroup *mg, int mnterr)
log_error("cpg_leave error %d", error);
}
-void do_leave(char *table, int mnterr)
+void do_leave(char *name, int mnterr)
{
struct mountgroup *mg;
- char *name = strstr(table, ":") + 1;
- log_debug("do_leave %s mnterr %d", table, mnterr);
+ log_debug("do_leave %s mnterr %d", name, mnterr);
mg = find_mg(name);
if (!mg) {
diff --git a/group/gfs_controld/cpg-old.c b/group/gfs_controld/cpg-old.c
index 192a403..b353867 100644
--- a/group/gfs_controld/cpg-old.c
+++ b/group/gfs_controld/cpg-old.c
@@ -1563,13 +1563,16 @@ static void recover_journals(struct mountgroup *mg)
these and wait for gfs to be finished with all at which point it calls
others_may_mount() and first_done is set. */
-static int kernel_recovery_done_first(struct mountgroup *mg)
+static int kernel_recovery_done_first(struct mountgroup *mg, int first_done)
{
- int rv, first_done;
+ int rv;
- rv = read_sysfs_int(mg, "first_done", &first_done);
- if (rv < 0)
- return rv;
+ if (first_done < 0) {
+ /* for back compat, sysfs file deprecated */
+ rv = read_sysfs_int(mg, "first_done", &first_done);
+ if (rv < 0)
+ return rv;
+ }
log_group(mg, "kernel_recovery_done_first first_done %d", first_done);
@@ -1604,26 +1607,28 @@ static int need_kernel_recovery_done(struct mountgroup *mg)
remain blocked until an rw node mounts, and the next mounter must
be rw. */
-int process_recovery_uevent_old(char *table)
+int process_recovery_uevent_old(char *name, int jid_done, int status, int first)
{
struct mountgroup *mg;
struct mg_member *memb;
- char *name = strstr(table, ":") + 1;
char *ss;
- int rv, jid_done, status, found = 0;
+ int rv, found = 0;
mg = find_mg(name);
if (!mg) {
- log_error("recovery_done: unknown mount group %s", table);
+ log_error("recovery_done: unknown mount group %s", name);
return -1;
}
if (mg->first_mounter && !mg->first_mounter_done)
- return kernel_recovery_done_first(mg);
+ return kernel_recovery_done_first(mg, first);
- rv = read_sysfs_int(mg, "recover_done", &jid_done);
- if (rv < 0)
- return rv;
+ if (jid_done < 0) {
+ /* for back compat, sysfs file deprecated */
+ rv = read_sysfs_int(mg, "recover_done", &jid_done);
+ if (rv < 0)
+ return rv;
+ }
list_for_each_entry(memb, &mg->members_gone, list) {
if (memb->jid == jid_done) {
@@ -1646,12 +1651,15 @@ int process_recovery_uevent_old(char *table)
return 0;
}
- rv = read_sysfs_int(mg, "recover_status", &status);
- if (rv < 0) {
- log_group(mg, "recovery_done jid %d nodeid %d sysfs error %d",
- memb->jid, memb->nodeid, rv);
- memb->local_recovery_status = RS_NOFS;
- goto out;
+ if (status < 0) {
+ /* for back compat, sysfs file deprecated */
+ rv = read_sysfs_int(mg, "recover_status", &status);
+ if (rv < 0) {
+ log_group(mg, "recovery_done jid %d nodeid %d sysfs error %d",
+ memb->jid, memb->nodeid, rv);
+ memb->local_recovery_status = RS_NOFS;
+ goto out;
+ }
}
switch (status) {
@@ -1724,12 +1732,11 @@ static void leave_mountgroup(struct mountgroup *mg, int mnterr)
group_leave(gh, mg->name);
}
-void do_leave_old(char *table, int mnterr)
+void do_leave_old(char *name, int mnterr)
{
struct mountgroup *mg;
- char *name = strstr(table, ":") + 1;
- log_debug("do_leave_old %s mnterr %d", table, mnterr);
+ log_debug("do_leave_old %s mnterr %d", name, mnterr);
list_for_each_entry(mg, &withdrawn_mounts, list) {
if (strcmp(mg->name, name))
@@ -1780,7 +1787,7 @@ static int wait_for_kernel_mount(struct mountgroup *mg)
sysfs files in place, do_stop() will be able to block
the kernel. */
- rv = read_sysfs_int(mg, "id", &val);
+ rv = read_sysfs_int(mg, "block", &val);
if (!rv)
break;
usleep(100000);
diff --git a/group/gfs_controld/gfs_daemon.h b/group/gfs_controld/gfs_daemon.h
index 3beeb0e..c93d9cc 100644
--- a/group/gfs_controld/gfs_daemon.h
+++ b/group/gfs_controld/gfs_daemon.h
@@ -225,10 +225,10 @@ void process_cpg(int ci);
int setup_dlmcontrol(void);
void process_dlmcontrol(int ci);
int set_protocol(void);
-void process_recovery_uevent(char *table);
+void process_recovery_uevent(char *name, int jid, int status, int first);
void process_mountgroups(void);
int gfs_join_mountgroup(struct mountgroup *mg);
-void do_leave(char *table, int mnterr);
+void do_leave(char *name, int mnterr);
void gfs_mount_done(struct mountgroup *mg);
void send_remount(struct mountgroup *mg, struct gfsc_mount_args *ma);
void send_withdraw(struct mountgroup *mg);
@@ -245,13 +245,12 @@ void close_cpg_old(void);
void process_cpg_old(int ci);
int gfs_join_mountgroup_old(struct mountgroup *mg, struct gfsc_mount_args *ma);
-void do_leave_old(char *table, int mnterr);
+void do_leave_old(char *name, int mnterr);
int send_group_message_old(struct mountgroup *mg, int len, char *buf);
void save_message_old(struct mountgroup *mg, char *buf, int len, int from,
int type);
void send_withdraw_old(struct mountgroup *mg);
-int process_recovery_uevent_old(char *table);
-void ping_kernel_mount_old(char *table);
+int process_recovery_uevent_old(char *name, int jid, int status, int first);
void send_remount_old(struct mountgroup *mg, struct gfsc_mount_args *ma);
void send_mount_status_old(struct mountgroup *mg);
int do_stop(struct mountgroup *mg);
diff --git a/group/gfs_controld/main.c b/group/gfs_controld/main.c
index a2d8ed9..457a5d6 100644
--- a/group/gfs_controld/main.c
+++ b/group/gfs_controld/main.c
@@ -7,6 +7,7 @@
#define LOCKFILE_NAME "/var/run/gfs_controld.pid"
#define CLIENT_NALLOC 32
+#define UEVENT_BUF_SIZE 4096
static int client_maxi;
static int client_size;
@@ -22,7 +23,7 @@ struct client {
struct mountgroup *mg;
};
-static void do_withdraw(char *table);
+static void do_withdraw(char *name);
int do_read(int fd, void *buf, size_t count)
{
@@ -198,62 +199,104 @@ struct mountgroup *find_mg_id(uint32_t id)
return NULL;
}
-#define MAXARGS 8
-
-static char *get_args(char *buf, int *argc, char **argv, char sep, int want)
-{
- char *p = buf, *rp = NULL;
- int i;
-
- argv[0] = p;
-
- for (i = 1; i < MAXARGS; i++) {
- p = strchr(buf, sep);
- if (!p)
- break;
- *p = '\0';
-
- if (want == i) {
- rp = p + 1;
- break;
- }
-
- argv[i] = p + 1;
- buf = p + 1;
- }
- *argc = i;
-
- /* we ended by hitting \0, return the point following that */
- if (!rp)
- rp = strchr(buf, '\0') + 1;
-
- return rp;
-}
-
-static void ping_kernel_mount(char *table)
+static void ping_kernel_mount(char *name)
{
struct mountgroup *mg;
- char *name = strstr(table, ":") + 1;
int rv, val;
mg = find_mg(name);
if (!mg)
return;
- rv = read_sysfs_int(mg, "id", &val);
+ rv = read_sysfs_int(mg, "block", &val);
log_group(mg, "ping_kernel_mount %d", rv);
}
-static void process_uevent(int ci)
+enum {
+ Env_ACTION = 0,
+ Env_SUBSYSTEM,
+ Env_LOCKPROTO,
+ Env_LOCKTABLE,
+ Env_DEVPATH,
+ Env_RECOVERY,
+ Env_FIRSTMOUNT,
+ Env_JID,
+ Env_Last, /* Flag for end of vars */
+};
+
+static const char *uevent_vars[] = {
+ [Env_ACTION] = "ACTION=",
+ [Env_SUBSYSTEM] = "SUBSYSTEM=",
+ [Env_LOCKPROTO] = "LOCKPROTO=",
+ [Env_LOCKTABLE] = "LOCKTABLE=",
+ [Env_DEVPATH] = "DEVPATH=",
+ [Env_RECOVERY] = "RECOVERY=",
+ [Env_FIRSTMOUNT] = "FIRSTMOUNT=",
+ [Env_JID] = "JID=",
+};
+
+/*
+ * Parses a uevent message for the interesting bits. It requires a list
+ * of variables to look for, and an equally long list of pointers into
+ * which to write the results.
+ */
+static void decode_uevent(const char *buf, unsigned len, const char *vars[],
+ unsigned nvars, const char *vals[])
{
- char buf[MAXLINE];
- char *argv[MAXARGS], *act, *sys;
- int rv, argc = 0;
- int lock_module = 0;
+ const char *ptr;
+ unsigned int i;
+ int slen, vlen;
+
+ memset(vals, 0, sizeof(const char *) * nvars);
+
+ while (len > 0) {
+ ptr = buf;
+ slen = strlen(ptr);
+ buf += slen;
+ len -= slen;
+ buf++;
+ len--;
+
+ for (i = 0; i < nvars; i++) {
+ vlen = strlen(vars[i]);
+ if (vlen > slen)
+ continue;
+ if (memcmp(vars[i], ptr, vlen) != 0)
+ continue;
+ vals[i] = ptr + vlen;
+ break;
+ }
+ }
+}
- memset(buf, 0, sizeof(buf));
- memset(argv, 0, sizeof(char *) * MAXARGS);
+static char *uevent_fsname(const char *vars[])
+{
+ char *name = NULL;
+
+ if (vars[Env_LOCKTABLE])
+ name = strchr(vars[Env_LOCKTABLE], ':');
+
+ /* When all kernels are converted, we can dispose with the following
+ * grotty bit. This is for backward compatibility only.
+ */
+ if (!name && vars[Env_DEVPATH]) {
+ name = strchr(vars[Env_DEVPATH], ':');
+ if (name) {
+ char *end = strstr(name, "/lock_module");
+ if (end)
+ *end = 0;
+ }
+ }
+ return (name && name[0]) ? name + 1 : NULL;
+}
+
+static void process_uevent(int ci)
+{
+ char buf[UEVENT_BUF_SIZE];
+ const char *uevent_vals[Env_Last];
+ char *fsname;
+ int rv;
retry_recv:
rv = recv(client[ci].fd, &buf, sizeof(buf), 0);
@@ -264,68 +307,71 @@ static void process_uevent(int ci)
log_error("uevent recv error %d errno %d", rv, errno);
return;
}
+ buf[rv] = 0;
- /* first we get the uevent for removing lock module kobject:
- "remove@/fs/gfs/bull:x/lock_module"
- second is the uevent for removing gfs kobject:
- "remove@/fs/gfs/bull:x"
- */
+ decode_uevent(buf, rv, uevent_vars, Env_Last, uevent_vals);
- if (!strstr(buf, "gfs"))
+ if (!uevent_vals[Env_DEVPATH] ||
+ !uevent_vals[Env_ACTION] ||
+ !uevent_vals[Env_SUBSYSTEM])
return;
- /* if an fs is named "gfs", it results in dlm uevents
- like "remove@/kernel/dlm/gfs" */
-
- if (strstr(buf, "kernel/dlm"))
+ if (!strstr(uevent_vals[Env_DEVPATH], "/fs/gfs"))
return;
- log_debug("uevent: %s", buf);
-
- if (strstr(buf, "lock_module"))
- lock_module = 1;
-
- get_args(buf, &argc, argv, '/', 4);
- if (argc != 4)
- log_error("uevent message has %d args", argc);
- act = argv[0];
- sys = argv[2];
-
- log_debug("kernel: %s %s", act, argv[3]);
+ log_debug("uevent %s %s %s",
+ uevent_vals[Env_ACTION],
+ uevent_vals[Env_SUBSYSTEM],
+ uevent_vals[Env_DEVPATH]);
+
+ fsname = uevent_fsname(uevent_vals);
+ if (!fsname) {
+ log_error("no fsname uevent %s %s %s",
+ uevent_vals[Env_ACTION],
+ uevent_vals[Env_SUBSYSTEM],
+ uevent_vals[Env_DEVPATH]);
+ return;
+ }
- if (!strcmp(act, "remove@")) {
+ if (!strcmp(uevent_vals[Env_ACTION], "remove")) {
/* We want to trigger the leave at the very end of the kernel's
unmount process, i.e. at the end of put_super(), so we do the
leave when the second uevent (from the gfs kobj) arrives. */
- if (lock_module)
+ if (strcmp(uevent_vals[Env_SUBSYSTEM], "lock_dlm") == 0)
return;
-
if (group_mode == GROUP_LIBGROUP)
- do_leave_old(argv[3], 0);
+ do_leave_old(fsname, 0);
else
- do_leave(argv[3], 0);
+ do_leave(fsname, 0);
- } else if (!strcmp(act, "change@")) {
- if (!lock_module)
- return;
+ } else if (!strcmp(uevent_vals[Env_ACTION], "change")) {
+ int jid, status = -1, first = -1;
- if (group_mode == GROUP_LIBGROUP)
- process_recovery_uevent_old(argv[3]);
- else
- process_recovery_uevent(argv[3]);
+ if (!uevent_vals[Env_JID] ||
+ (sscanf(uevent_vals[Env_JID], "%d", &jid) != 1))
+ jid = -1;
- } else if (!strcmp(act, "offline@")) {
- if (!lock_module)
- return;
+ if (uevent_vals[Env_RECOVERY]) {
+ if (strcmp(uevent_vals[Env_RECOVERY], "Done") == 0)
+ status = LM_RD_SUCCESS;
+ if (strcmp(uevent_vals[Env_RECOVERY], "Failed") == 0)
+ status = LM_RD_GAVEUP;
+ }
- do_withdraw(argv[3]);
+ if (uevent_vals[Env_FIRSTMOUNT] &&
+ (strcmp(uevent_vals[Env_FIRSTMOUNT], "Done") == 0))
+ first = 1;
- } else {
- if (!lock_module)
- return;
+ if (group_mode == GROUP_LIBGROUP)
+ process_recovery_uevent_old(fsname, jid, status, first);
+ else
+ process_recovery_uevent(fsname, jid, status, first);
- ping_kernel_mount(argv[3]);
+ } else if (!strcmp(uevent_vals[Env_ACTION], "offline")) {
+ do_withdraw(fsname);
+ } else {
+ ping_kernel_mount(fsname);
}
}
@@ -736,10 +782,9 @@ static void do_join(int ci, struct gfsc_mount_args *ma)
and when it's been removed from the group, it tells the locally withdrawing
gfs to clear out locks. */
-static void do_withdraw(char *table)
+static void do_withdraw(char *name)
{
struct mountgroup *mg;
- char *name = strstr(table, ":") + 1;
int rv;
log_debug("withdraw: %s", name);