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(a)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(a)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 {