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@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@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 {
sanlock-devel@lists.fedorahosted.org