src/client.c src/cmd.c src/main.c src/sanlock_admin.h src/sanlock_internal.h src/sanlock_sock.h

David Teigland teigland at fedoraproject.org
Fri Jan 31 15:54:45 UTC 2014


 src/client.c           |   33 +++++++++++++++++
 src/cmd.c              |   43 +++++++++++++++++++++-
 src/main.c             |   94 +++++++++++++++++++++++++++++++++++++++++++++++--
 src/sanlock_admin.h    |    2 +
 src/sanlock_internal.h |    8 ++++
 src/sanlock_sock.h     |    2 +
 6 files changed, 178 insertions(+), 4 deletions(-)

New commits:
commit 78885dec2747e17af7e648146b0fe7ab5b388483
Author: David Teigland <teigland at redhat.com>
Date:   Mon Jan 27 15:53:58 2014 -0600

    sanlock: version interface
    
    Add the ability for a client to get the version
    of the running daemon.
    
    Start using the "version" field in the sm_header
    struct used for daemon/client ipc.  This is not
    the sanlock version, but the socket ipc protocol
    version.
    
    Signed-off-by: David Teigland <teigland at redhat.com>

diff --git a/src/client.c b/src/client.c
index 14c70d1..9e523ae 100644
--- a/src/client.c
+++ b/src/client.c
@@ -71,6 +71,7 @@ static int send_header(int sock, int cmd, uint32_t cmd_flags, int datalen,
 
 	memset(&header, 0, sizeof(struct sm_header));
 	header.magic = SM_MAGIC;
+	header.version = SM_PROTO;
 	header.cmd = cmd;
 	header.cmd_flags = cmd_flags;
 	header.length = sizeof(header) + datalen;
@@ -741,6 +742,38 @@ int sanlock_restrict(int sock, uint32_t flags)
 	return rv;
 }
 
+int sanlock_version(uint32_t flags, uint32_t *version, uint32_t *proto)
+{
+	struct sm_header h;
+	int fd, rv;
+
+	rv = connect_socket(&fd);
+	if (rv < 0)
+		return rv;
+
+	rv = send_header(fd, SM_CMD_VERSION, flags, 0, 0, 0);
+	if (rv < 0)
+		return rv;
+
+	memset(&h, 0, sizeof(struct sm_header));
+
+	rv = recv(fd, &h, sizeof(h), MSG_WAITALL);
+	if (rv < 0)
+		return -errno;
+	if (rv != sizeof(h))
+		return -1;
+
+	if (proto)
+		*proto = h.version;
+
+	rv = (int)h.data;
+	if (rv < 0)
+		return rv;
+
+	*version = h.data2;
+	return 0;
+}
+
 int sanlock_killpath(int sock, uint32_t flags, const char *path, char *args)
 {
 	char path_max[SANLK_HELPER_PATH_LEN];
diff --git a/src/cmd.c b/src/cmd.c
index 13ad405..f19e8fb 100644
--- a/src/cmd.c
+++ b/src/cmd.c
@@ -826,6 +826,7 @@ static void cmd_inquire(struct task *task, struct cmd_args *ca)
 	}
 
 	memcpy(&h, &ca->header, sizeof(struct sm_header));
+	h.version = SM_PROTO;
 	h.data = result;
 	h.data2 = res_count;
 
@@ -1143,6 +1144,7 @@ static void cmd_get_lvb(struct task *task GNUC_UNUSED, struct cmd_args *ca)
 	result = res_get_lvb(&res, &lvb, &lvblen);
  reply:
 	memcpy(&h, &ca->header, sizeof(struct sm_header));
+	h.version = SM_PROTO;
 	h.data = result;
 	h.data2 = 0;
 	h.length = sizeof(h) + lvblen;
@@ -1439,6 +1441,7 @@ static void cmd_read_lockspace(struct task *task, struct cmd_args *ca)
 	log_debug("cmd_read_lockspace %d,%d done %d", ca->ci_in, fd, result);
 
 	memcpy(&h, &ca->header, sizeof(struct sm_header));
+	h.version = SM_PROTO;
 	h.data = result;
 	h.data2 = io_timeout;
 	h.length = sizeof(h) + sizeof(lockspace);
@@ -1531,6 +1534,7 @@ static void cmd_read_resource(struct task *task, struct cmd_args *ca)
 	log_debug("cmd_read_resource %d,%d done %d", ca->ci_in, fd, result);
 
 	memcpy(&h, &ca->header, sizeof(struct sm_header));
+	h.version = SM_PROTO;
 	h.data = result;
 	h.data2 = 0;
 	h.length = sizeof(h) + sizeof(res);
@@ -1626,6 +1630,7 @@ static void cmd_read_resource_owners(struct task *task, struct cmd_args *ca)
 	log_debug("cmd_read_resource_owners %d,%d count %d done %d", ca->ci_in, fd, count, result);
 
 	memcpy(&h, &ca->header, sizeof(struct sm_header));
+	h.version = SM_PROTO;
 	h.data = result;
 	h.data2 = count;
 	h.length = sizeof(h) + sizeof(res) + send_len;
@@ -1938,7 +1943,11 @@ static int print_state_daemon(char *str)
 		 "helper_kill_fd=%d "
 		 "helper_full_count=%u "
 		 "helper_last_status=%llu "
-		 "monotime=%llu",
+		 "monotime=%llu "
+		 "version_str=%s "
+		 "version_num=%u.%u.%u "
+		 "version_hex=%08x "
+		 "smproto_hex=%08x",
 		 our_host_name_global,
 		 main_task.use_aio,
 		 kill_grace_seconds,
@@ -1946,7 +1955,13 @@ static int print_state_daemon(char *str)
 		 helper_kill_fd,
 		 helper_full_count,
 		 (unsigned long long)helper_last_status,
-		 (unsigned long long)monotime());
+		 (unsigned long long)monotime(),
+		 VERSION,
+		 sanlock_version_major,
+		 sanlock_version_minor,
+		 sanlock_version_patch,
+		 sanlock_version_combined,
+		 SM_PROTO);
 
 	return strlen(str) + 1;
 }
@@ -2195,6 +2210,7 @@ static void cmd_status(int fd, struct sm_header *h_recv, int client_maxi)
 
 	memset(&h, 0, sizeof(h));
 	memcpy(&h, h_recv, sizeof(struct sm_header));
+	h.version = SM_PROTO;
 	h.length = sizeof(h);
 	h.data = 0;
 
@@ -2248,6 +2264,7 @@ static void cmd_host_status(int fd, struct sm_header *h_recv)
 
 	memset(&h, 0, sizeof(h));
 	memcpy(&h, h_recv, sizeof(struct sm_header));
+	h.version = SM_PROTO;
 	h.length = sizeof(h);
 	h.data = 0;
 
@@ -2303,6 +2320,7 @@ static void cmd_log_dump(int fd, struct sm_header *h_recv)
 
 	copy_log_dump(send_data_buf, &len);
 
+	h_recv->version = SM_PROTO;
 	h_recv->data = len;
 
 	send(fd, h_recv, sizeof(struct sm_header), MSG_NOSIGNAL);
@@ -2315,6 +2333,7 @@ static void cmd_get_lockspaces(int fd, struct sm_header *h_recv)
 
 	rv = get_lockspaces(send_data_buf, &len, &count, LOG_DUMP_SIZE);
 
+	h_recv->version = SM_PROTO;
 	h_recv->length = sizeof(struct sm_header) + len;
 	h_recv->data = rv;
 	h_recv->data2 = count;
@@ -2331,6 +2350,7 @@ static void cmd_get_hosts(int fd, struct sm_header *h_recv)
 
 	memset(&h, 0, sizeof(h));
 	memcpy(&h, h_recv, sizeof(struct sm_header));
+	h.version = SM_PROTO;
 	h.length = sizeof(h);
 	h.data = 0;
 
@@ -2358,9 +2378,24 @@ static void cmd_restrict(int ci, int fd, struct sm_header *h_recv)
 
 	client[ci].restricted = h_recv->cmd_flags;
 
+	h_recv->version = SM_PROTO;
 	send_result(fd, h_recv, 0);
 }
 
+static void cmd_version(int ci GNUC_UNUSED, int fd, struct sm_header *h_recv)
+{
+	h_recv->magic = SM_MAGIC;
+	h_recv->version = SM_PROTO;
+	h_recv->cmd = SM_CMD_VERSION;
+	h_recv->cmd_flags = 0;
+	h_recv->length = sizeof(struct sm_header);
+	h_recv->seq = 0;
+	h_recv->data = 0;
+	h_recv->data2 = sanlock_version_combined;
+
+	send(fd, h_recv, sizeof(struct sm_header), MSG_NOSIGNAL);
+}
+
 static int get_peer_pid(int fd, int *pid)
 {
 	struct ucred cred;
@@ -2409,6 +2444,10 @@ void call_cmd_daemon(int ci, struct sm_header *h_recv, int client_maxi)
 		cmd_restrict(ci, fd, h_recv);
 		auto_close = 0;
 		break;
+	case SM_CMD_VERSION:
+		cmd_version(ci, fd, h_recv);
+		auto_close = 0;
+		break;
 	case SM_CMD_SHUTDOWN:
 		strcpy(client[ci].owner_name, "shutdown");
 		if (h_recv->data) {
diff --git a/src/main.c b/src/main.c
index 421ea67..5f3c6ed 100644
--- a/src/main.c
+++ b/src/main.c
@@ -436,6 +436,7 @@ void send_result(int fd, struct sm_header *h_recv, int result)
 	struct sm_header h;
 
 	memcpy(&h, h_recv, sizeof(struct sm_header));
+	h.version = SM_PROTO;
 	h.length = sizeof(h);
 	h.data = result;
 	h.data2 = 0;
@@ -1158,12 +1159,19 @@ static void process_connection(int ci)
 			  ci, client[ci].fd, client[ci].pid, h.cmd);
 		goto dead;
 	}
+	if (h.version && (h.cmd != SM_CMD_VERSION) &&
+	    (h.version & 0xFFFF0000) > (SM_PROTO & 0xFFFF0000)) {
+		log_error("ci %d recv %d proto %x vs %x",
+			  ci, rv, h.version , SM_PROTO);
+		goto dead;
+	}
 
 	client[ci].cmd_last = h.cmd;
 
 	switch (h.cmd) {
 	case SM_CMD_REGISTER:
 	case SM_CMD_RESTRICT:
+	case SM_CMD_VERSION:
 	case SM_CMD_SHUTDOWN:
 	case SM_CMD_STATUS:
 	case SM_CMD_HOST_STATUS:
@@ -1864,8 +1872,14 @@ static int read_command_line(int argc, char *argv[])
 		exit(EXIT_SUCCESS);
 	}
 
-	if (!strcmp(arg1, "version") || !strcmp(arg1, "--version") ||
-	    !strcmp(arg1, "-V")) {
+	if (!strcmp(arg1, "version")) {
+		printf("%u.%u.%u\n",
+		       sanlock_version_major, sanlock_version_minor,
+		       sanlock_version_patch);
+		exit(EXIT_SUCCESS);
+	}
+
+	if (!strcmp(arg1, "--version") || !strcmp(arg1, "-V")) {
 		printf("%s %s (built %s %s)\n",
 		       argv[0], VERSION, __DATE__, __TIME__);
 		exit(EXIT_SUCCESS);
@@ -1939,6 +1953,8 @@ static int read_command_line(int argc, char *argv[])
 			com.action = ACT_CLIENT_INIT;
 		else if (!strcmp(act, "read"))
 			com.action = ACT_CLIENT_READ;
+		else if (!strcmp(act, "version"))
+			com.action = ACT_VERSION;
 		else {
 			log_tool("client action \"%s\" is unknown", act);
 			exit(EXIT_FAILURE);
@@ -2315,6 +2331,38 @@ static int do_client_read(void)
 	return rv;
 }
 
+static void do_client_version(void)
+{
+	uint32_t version = 0;
+	uint32_t proto = 0;
+	int rv;
+
+	rv = sanlock_version(0, &version, &proto);
+	if (rv < 0) {
+		log_tool("daemon version error %d", rv);
+	}
+
+	log_tool("client version %u.%u.%u (0x%08x)",
+		 sanlock_version_major,
+		 sanlock_version_minor,
+		 sanlock_version_patch,
+		 sanlock_version_combined);
+
+	log_tool("daemon version %u.%u.%u (0x%08x)",
+		 (version & 0xFF000000) >> 24,
+		 (version & 0x00FF0000) >> 16,
+		 (version & 0x0000FF00) >> 8,
+		 version);
+
+	log_tool("client socket protocol %u.%u",
+		  (SM_PROTO & 0xFFFF0000) >> 16,
+		  (SM_PROTO & 0x0000FFFF));
+
+	log_tool("daemon socket protocol %u.%u",
+		  (proto & 0xFFFF0000) >> 16,
+		  (proto & 0x0000FFFF));
+}
+
 static int do_client(void)
 {
 	struct sanlk_resource **res_args = NULL;
@@ -2499,6 +2547,10 @@ static int do_client(void)
 		rv = do_client_read();
 		break;
 
+	case ACT_VERSION:
+		do_client_version();
+		break;
+
 	default:
 		log_tool("action not implemented");
 		rv = -1;
@@ -2608,6 +2660,42 @@ static int do_direct(void)
 	return rv;
 }
 
+static void set_sanlock_version(void)
+{
+	char version_str[64];
+	char *major_str, *minor_str, *patch_str;
+	char *d1, *d2;
+
+	strncpy(version_str, VERSION, 64);
+
+	d1 = strstr(version_str, ".");
+	if (!d1)
+		return;
+
+	d2 = strstr(d1 + 1, ".");
+	if (!d2)
+		return;
+
+	major_str = version_str;
+	minor_str = d1 + 1;
+	patch_str = d2 + 1;
+
+	*d1 = '\0';
+	*d2 = '\0';
+
+	sanlock_version_major = atoi(major_str);
+	sanlock_version_minor = atoi(minor_str);
+	sanlock_version_patch = atoi(patch_str);
+
+	sanlock_version_build = 0; /* TODO */
+
+	sanlock_version_combined = 0;
+	sanlock_version_combined |= sanlock_version_major << 24;
+	sanlock_version_combined |= sanlock_version_minor << 16;
+	sanlock_version_combined |= sanlock_version_patch << 8;
+	sanlock_version_combined |= sanlock_version_build;
+}
+
 int main(int argc, char *argv[])
 {
 	int rv;
@@ -2618,6 +2706,8 @@ int main(int argc, char *argv[])
 
 	/* initialize global EXTERN variables */
 
+	set_sanlock_version();
+
 	kill_count_max = 100;
 	kill_grace_seconds = DEFAULT_GRACE_SEC;
 	helper_ci = -1;
diff --git a/src/sanlock_admin.h b/src/sanlock_admin.h
index 1a781b1..f76b2dc 100644
--- a/src/sanlock_admin.h
+++ b/src/sanlock_admin.h
@@ -276,4 +276,6 @@ int sanlock_test_resource_owners(struct sanlk_resource *res, uint32_t flags,
 				 struct sanlk_host *hosts, int hosts_count,
 				 uint32_t *test_flags);
 
+int sanlock_version(uint32_t flags, uint32_t *version, uint32_t *proto);
+
 #endif
diff --git a/src/sanlock_internal.h b/src/sanlock_internal.h
index a448a5c..c3fa574 100644
--- a/src/sanlock_internal.h
+++ b/src/sanlock_internal.h
@@ -325,6 +325,7 @@ enum {
 	ACT_CLIENT_ALIGN,
 	ACT_EXAMINE,
 	ACT_GETS,
+	ACT_VERSION,
 };
 
 EXTERN int external_shutdown;
@@ -344,5 +345,12 @@ EXTERN struct list_head spaces_rem;
 EXTERN struct list_head spaces_add;
 EXTERN pthread_mutex_t spaces_mutex;
 
+/* major.minor.patch-build (TODO: get build) */
+EXTERN uint8_t sanlock_version_major;
+EXTERN uint8_t sanlock_version_minor;
+EXTERN uint8_t sanlock_version_patch;
+EXTERN uint8_t sanlock_version_build;
+EXTERN uint32_t sanlock_version_combined;
+
 #endif
 
diff --git a/src/sanlock_sock.h b/src/sanlock_sock.h
index b2f7304..c5c1ec9 100644
--- a/src/sanlock_sock.h
+++ b/src/sanlock_sock.h
@@ -14,6 +14,7 @@
 #define SANLK_SOCKET_NAME "sanlock.sock"
 
 #define SM_MAGIC 0x04282010
+#define SM_PROTO 0x00000001
 
 #define MAX_CLIENT_MSG (1024 * 1024) /* TODO: this is random */
 
@@ -45,6 +46,7 @@ enum {
 	SM_CMD_SET_LVB		 = 25,
 	SM_CMD_GET_LVB		 = 26,
 	SM_CMD_CONVERT		 = 27,
+	SM_CMD_VERSION		 = 28,
 };
 
 struct sm_header {




More information about the sanlock-devel mailing list