This is the mail archive of the cluster-cvs@sourceware.org mailing list for the cluster.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]