src/Makefile | 1 src/client.c | 172 ------------------- src/client_cmd.c | 287 ++++++++++++++++++++++++++++++++ src/client_cmd.h | 17 + src/direct_lib.c | 4 src/host_id.c | 56 +----- src/host_id.h | 5 src/log.c | 2 src/log.h | 2 src/main.c | 434 +++++++++++++++++++++++++++++++++---------------- src/sanlock.8 | 6 src/sanlock_admin.h | 8 src/sanlock_internal.h | 27 ++- src/sanlock_sock.h | 6 src/token_manager.c | 22 -- 15 files changed, 652 insertions(+), 397 deletions(-)
New commits: commit 241606a1ae1d4db45cff28902e052e00d541b9e6 Author: David Teigland teigland@redhat.com Date: Thu Sep 8 17:27:13 2011 -0500
sanlock: new status and host_status
Change the client status command to operate on global resource lists instead of per client tokens.
Add new client host_status command to print a lockspace's saved info about hosts.
diff --git a/src/Makefile b/src/Makefile index 8afbd8a..5d710e4 100644 --- a/src/Makefile +++ b/src/Makefile @@ -30,6 +30,7 @@ CMD_SOURCE = \ token_manager.c \ watchdog.c \ monotime.c \ + client_cmd.c \ sanlock_sock.c
LIB_ENTIRE_SOURCE = \ diff --git a/src/client.c b/src/client.c index 4987867..ea25832 100644 --- a/src/client.c +++ b/src/client.c @@ -81,7 +81,9 @@ static int send_header(int sock, int cmd, uint32_t cmd_flags, int datalen, return 0; }
-static int send_command(int cmd, uint32_t data) +int send_command(int cmd, uint32_t data); + +int send_command(int cmd, uint32_t data) { int rv, sock;
@@ -114,174 +116,6 @@ static int recv_result(int fd) return (int)h.data; }
-int sanlock_shutdown(void) -{ - int fd; - - fd = send_command(SM_CMD_SHUTDOWN, 0); - if (fd < 0) - return fd; - - close(fd); - return 0; -} - -int sanlock_log_dump(void) -{ - struct sm_header h; - char buf[4096]; - int fd, rv; - - fd = send_command(SM_CMD_LOG_DUMP, 0); - if (fd < 0) - return fd; - - memset(&h, 0, sizeof(h)); - - rv = recv(fd, &h, sizeof(h), MSG_WAITALL); - if (rv != sizeof(h)) { - rv = -1; - goto out; - } - - while (1) { - memset(buf, 0, sizeof(buf)); - - rv = recv(fd, buf, sizeof(buf) - 1, MSG_WAITALL); - - if (rv > 0) - printf("%s", buf); - else - break; - } - printf("\n"); - out: - close(fd); - return rv; -} - -static void print_debug(char *str, int len) -{ - char *p; - int i; - - p = &str[0]; - for (i = 0; i < len-1; i++) { - if (str[i] == ' ') { - str[i] = '\0'; - printf(" %s\n", p); - p = &str[i+1]; - } - } - - if (p) - printf(" %s\n", p); -} - -static void status_daemon(int fd GNUC_UNUSED, struct sanlk_state *st, char *str, int debug) -{ - printf("daemon\n"); - - if (st->str_len && debug) - print_debug(str, st->str_len); -} - -static void status_lockspace(int fd, struct sanlk_state *st, char *str, int debug) -{ - struct sanlk_lockspace lockspace; - int rv; - - rv = recv(fd, &lockspace, sizeof(lockspace), MSG_WAITALL); - - printf(" lockspace %.48s:%llu:%s:%llu\n", - lockspace.name, - (unsigned long long)lockspace.host_id, - lockspace.host_id_disk.path, - (unsigned long long)lockspace.host_id_disk.offset); - - if (st->str_len && debug) - print_debug(str, st->str_len); -} - -static void status_client(int fd GNUC_UNUSED, struct sanlk_state *st, char *str, int debug) -{ - printf("pid %d ", st->data32); - printf("%.48s\n", st->name); - - if (st->str_len && debug) - print_debug(str, st->str_len); -} - -static void status_resource(int fd, struct sanlk_state *st, char *str, int debug) -{ - struct sanlk_resource resource; - struct sanlk_disk disk; - int i, rv; - - rv = recv(fd, &resource, sizeof(resource), MSG_WAITALL); - - printf(" resource %.48s:%.48s", resource.lockspace_name, resource.name); - - for (i = 0; i < resource.num_disks; i++) { - rv = recv(fd, &disk, sizeof(disk), MSG_WAITALL); - - printf(":%s:%llu", - disk.path, (unsigned long long)disk.offset); - } - printf("\n"); - - if (st->str_len && debug) - print_debug(str, st->str_len); -} - -int sanlock_status(int debug) -{ - struct sm_header h; - struct sanlk_state st; - char str[SANLK_STATE_MAXSTR]; - int fd, rv; - - fd = send_command(SM_CMD_STATUS, 0); - if (fd < 0) - return fd; - - rv = recv(fd, &h, sizeof(h), MSG_WAITALL); - if (rv != sizeof(h)) - return -1; - - - while (1) { - rv = recv(fd, &st, sizeof(st), MSG_WAITALL); - if (!rv) - break; - if (rv != sizeof(st)) - return -1; - - if (st.str_len) { - rv = recv(fd, str, st.str_len, MSG_WAITALL); - if (rv != st.str_len) - return -1; - } - - switch (st.type) { - case SANLK_STATE_DAEMON: - status_daemon(fd, &st, str, debug); - break; - case SANLK_STATE_LOCKSPACE: - status_lockspace(fd, &st, str, debug); - break; - case SANLK_STATE_CLIENT: - status_client(fd, &st, str, debug); - break; - case SANLK_STATE_RESOURCE: - status_resource(fd, &st, str, debug); - break; - } - } - - return 0; -} - static int cmd_lockspace(int cmd, struct sanlk_lockspace *ls, uint32_t flags) { int rv, fd; diff --git a/src/client_cmd.c b/src/client_cmd.c new file mode 100644 index 0000000..a3949d1 --- /dev/null +++ b/src/client_cmd.c @@ -0,0 +1,287 @@ +/* + * Copyright (C) 2010-2011 Red Hat, Inc. All rights reserved. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU General Public License v.2. + */ + +#include <inttypes.h> +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <stddef.h> +#include <fcntl.h> +#include <string.h> +#include <errno.h> +#include <limits.h> +#include <time.h> +#include <syslog.h> +#include <pthread.h> +#include <poll.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <sys/stat.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <sys/un.h> + +#include "sanlock.h" +#include "sanlock_sock.h" + +#include "client_cmd.h" + +#ifndef GNUC_UNUSED +#define GNUC_UNUSED __attribute__((__unused__)) +#endif + +extern int send_command(int cmd, uint32_t data); + +static void print_debug(char *str, int len) +{ + char *p; + int i; + + p = &str[0]; + for (i = 0; i < len-1; i++) { + if (str[i] == ' ') { + str[i] = '\0'; + printf(" %s\n", p); + p = &str[i+1]; + } + } + + if (p) + printf(" %s\n", p); +} + +static void status_daemon(int fd GNUC_UNUSED, struct sanlk_state *st, char *str, int debug) +{ + printf("daemon\n"); + + if (st->str_len && debug) + print_debug(str, st->str_len); +} + +static void status_client(int fd GNUC_UNUSED, struct sanlk_state *st, char *str, int debug) +{ + printf("pid %d ", st->data32); + printf("%.48s\n", st->name); + + if (st->str_len && debug) + print_debug(str, st->str_len); +} + +static void status_lockspace(int fd, struct sanlk_state *st, char *str, int debug) +{ + struct sanlk_lockspace lockspace; + int rv; + + rv = recv(fd, &lockspace, sizeof(lockspace), MSG_WAITALL); + + printf("lockspace %.48s:%llu:%s:%llu\n", + lockspace.name, + (unsigned long long)lockspace.host_id, + lockspace.host_id_disk.path, + (unsigned long long)lockspace.host_id_disk.offset); + + if (st->str_len && debug) + print_debug(str, st->str_len); +} + +static void status_resource(int fd, struct sanlk_state *st, char *str, int debug) +{ + struct sanlk_resource resource; + struct sanlk_disk disk; + int i, rv; + + rv = recv(fd, &resource, sizeof(resource), MSG_WAITALL); + + printf("pid %d resource %.48s:%.48s", st->data32, resource.lockspace_name, resource.name); + + for (i = 0; i < resource.num_disks; i++) { + rv = recv(fd, &disk, sizeof(disk), MSG_WAITALL); + + printf(":%s:%llu", + disk.path, (unsigned long long)disk.offset); + } + printf("\n"); + + if (st->str_len && debug) + print_debug(str, st->str_len); +} + +static void status_host(int fd GNUC_UNUSED, struct sanlk_state *st, char *str, int debug) +{ + printf("%u timestamp %llu\n", st->data32, + (unsigned long long)st->data64); + + if (st->str_len && debug) + print_debug(str, st->str_len); +} + +int sanlock_status(int debug) +{ + struct sm_header h; + struct sanlk_state st; + char str[SANLK_STATE_MAXSTR]; + int fd, rv; + + fd = send_command(SM_CMD_STATUS, 0); + if (fd < 0) + return fd; + + rv = recv(fd, &h, sizeof(h), MSG_WAITALL); + if (rv < 0) { + rv = -errno; + goto out; + } + if (rv != sizeof(h)) { + rv = -1; + goto out; + } + + while (1) { + rv = recv(fd, &st, sizeof(st), MSG_WAITALL); + if (!rv) + break; + if (rv != sizeof(st)) + break; + + if (st.str_len) { + rv = recv(fd, str, st.str_len, MSG_WAITALL); + if (rv != st.str_len) + break; + } + + switch (st.type) { + case SANLK_STATE_DAEMON: + status_daemon(fd, &st, str, debug); + break; + case SANLK_STATE_CLIENT: + status_client(fd, &st, str, debug); + break; + case SANLK_STATE_LOCKSPACE: + status_lockspace(fd, &st, str, debug); + break; + case SANLK_STATE_RESOURCE: + status_resource(fd, &st, str, debug); + break; + } + } + rv = 0; + out: + close(fd); + return rv; +} + +int sanlock_host_status(int debug, char *lockspace_name) +{ + struct sm_header h; + struct sanlk_state st; + struct sanlk_lockspace lockspace; + char str[SANLK_STATE_MAXSTR]; + int fd, rv; + + if (!lockspace_name || !lockspace_name[0]) + return -1; + + fd = send_command(SM_CMD_HOST_STATUS, 0); + if (fd < 0) + return fd; + + memset(&lockspace, 0, sizeof(lockspace)); + snprintf(lockspace.name, SANLK_NAME_LEN, "%s", lockspace_name); + + rv = send(fd, &lockspace, sizeof(lockspace), 0); + if (rv < 0) + goto out; + + rv = recv(fd, &h, sizeof(h), MSG_WAITALL); + if (rv < 0) { + rv = -errno; + goto out; + } + if (rv != sizeof(h)) { + rv = -1; + goto out; + } + + while (1) { + rv = recv(fd, &st, sizeof(st), MSG_WAITALL); + if (!rv) + break; + if (rv != sizeof(st)) + break; + + if (st.str_len) { + rv = recv(fd, str, st.str_len, MSG_WAITALL); + if (rv != st.str_len) + break; + } + + switch (st.type) { + case SANLK_STATE_HOST: + status_host(fd, &st, str, debug); + break; + } + } + + rv = 0; + out: + close(fd); + return rv; +} + +int sanlock_log_dump(void) +{ + struct sm_header h; + char buf[4096]; + int fd, rv; + + fd = send_command(SM_CMD_LOG_DUMP, 0); + if (fd < 0) + return fd; + + memset(&h, 0, sizeof(h)); + + rv = recv(fd, &h, sizeof(h), MSG_WAITALL); + if (rv < 0) { + rv = -errno; + goto out; + } + if (rv != sizeof(h)) { + rv = -1; + goto out; + } + + + while (1) { + memset(buf, 0, sizeof(buf)); + + rv = recv(fd, buf, sizeof(buf) - 1, MSG_WAITALL); + + if (rv > 0) + printf("%s", buf); + else + break; + } + printf("\n"); + out: + close(fd); + return rv; +} + +int sanlock_shutdown(void) +{ + int fd; + + fd = send_command(SM_CMD_SHUTDOWN, 0); + if (fd < 0) + return fd; + + close(fd); + return 0; +} + diff --git a/src/client_cmd.h b/src/client_cmd.h new file mode 100644 index 0000000..3599659 --- /dev/null +++ b/src/client_cmd.h @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2010-2011 Red Hat, Inc. All rights reserved. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU General Public License v.2. + */ + +#ifndef __CLIENT_CMD_H__ +#define __CLIENT_CMD_H__ + +int sanlock_status(int debug); +int sanlock_host_status(int debug, char *lockspace_name); +int sanlock_log_dump(void); +int sanlock_shutdown(void); + +#endif diff --git a/src/direct_lib.c b/src/direct_lib.c index 7d7f9a9..59513ab 100644 --- a/src/direct_lib.c +++ b/src/direct_lib.c @@ -21,11 +21,11 @@ #include "direct.h" #include "task.h"
-void log_level(int space_id GNUC_UNUSED, int token_id GNUC_UNUSED, +void log_level(uint32_t space_id GNUC_UNUSED, uint32_t token_id GNUC_UNUSED, char *name GNUC_UNUSED, int level GNUC_UNUSED, const char *fmt GNUC_UNUSED, ...);
-void log_level(int space_id GNUC_UNUSED, int token_id GNUC_UNUSED, +void log_level(uint32_t space_id GNUC_UNUSED, uint32_t token_id GNUC_UNUSED, char *name GNUC_UNUSED, int level GNUC_UNUSED, const char *fmt GNUC_UNUSED, ...) { diff --git a/src/host_id.c b/src/host_id.c index 86df60b..4d39d82 100644 --- a/src/host_id.c +++ b/src/host_id.c @@ -34,43 +34,7 @@ #include "direct.h" #include "token_manager.h"
-static unsigned int space_id_counter = 1; - -struct list_head spaces; -struct list_head spaces_add; -struct list_head spaces_rem; -pthread_mutex_t spaces_mutex = PTHREAD_MUTEX_INITIALIZER; - -int print_space_state(struct space *sp, char *str) -{ - memset(str, 0, SANLK_STATE_MAXSTR); - - snprintf(str, SANLK_STATE_MAXSTR-1, - "space_id=%u " - "host_generation=%llu " - "space_dead=%d " - "killing_pids=%d " - "corrupt_result=%d " - "acquire_last_result=%d " - "renewal_last_result=%d " - "acquire_last_attempt=%llu " - "acquire_last_success=%llu " - "renewal_last_attempt=%llu " - "renewal_last_success=%llu", - sp->space_id, - (unsigned long long)sp->host_generation, - sp->space_dead, - sp->killing_pids, - sp->lease_status.corrupt_result, - sp->lease_status.acquire_last_result, - sp->lease_status.renewal_last_result, - (unsigned long long)sp->lease_status.acquire_last_attempt, - (unsigned long long)sp->lease_status.acquire_last_success, - (unsigned long long)sp->lease_status.renewal_last_attempt, - (unsigned long long)sp->lease_status.renewal_last_success); - - return strlen(str) + 1; -} +static uint32_t space_id_counter = 1;
static struct space *_search_space(char *name, struct sync_disk *disk, @@ -123,6 +87,11 @@ static struct space *_search_space(char *name, return NULL; }
+struct space *find_lockspace(char *name) +{ + return _search_space(name, NULL, 0, &spaces, &spaces_rem, &spaces_add); +} + int _lockspace_info(char *space_name, struct space *sp_out) { struct space *sp; @@ -290,9 +259,6 @@ void check_other_leases(struct task *task, struct space *sp, char *buf) new = 0;
for (i = 0; i < DEFAULT_MAX_HOSTS; i++) { - if (i+1 == sp->host_id) - continue; - hs = &sp->host_status[i]; hs->last_check = now;
@@ -309,6 +275,9 @@ void check_other_leases(struct task *task, struct space *sp, char *buf) hs->timestamp = leader->timestamp; hs->last_live = now;
+ if (i+1 == sp->host_id) + continue; + bitmap = (char *)leader + HOSTID_BITMAP_OFFSET;
if (!test_id_bit(sp->host_id, bitmap)) @@ -834,10 +803,3 @@ void free_lockspaces(int wait) pthread_mutex_unlock(&spaces_mutex); }
-void setup_spaces(void) -{ - INIT_LIST_HEAD(&spaces); - INIT_LIST_HEAD(&spaces_add); - INIT_LIST_HEAD(&spaces_rem); -} - diff --git a/src/host_id.h b/src/host_id.h index fba2d03..00dbcf7 100644 --- a/src/host_id.h +++ b/src/host_id.h @@ -9,20 +9,17 @@ #ifndef __HOST_ID_H__ #define __HOST_ID__H__
-int print_space_state(struct space *sp, char *str); +struct space *find_lockspace(char *name); int _lockspace_info(char *space_name, struct space *sp_out); int lockspace_info(char *space_name, struct space *sp_out); int lockspace_disk(char *space_name, struct sync_disk *disk); -void block_watchdog_updates(char *space_name); int host_info(char *space_name, uint64_t host_id, struct host_status *hs_out); int host_status_set_bit(char *space_name, uint64_t host_id); -int host_status_clear_bit(char *space_name, uint64_t host_id); int test_id_bit(int host_id, char *bitmap); int check_our_lease(struct task *task, struct space *sp, int *check_all, char *check_buf); void check_other_leases(struct task *task, struct space *sp, char *buf); int add_lockspace(struct sanlk_lockspace *ls); int rem_lockspace(struct sanlk_lockspace *ls); void free_lockspaces(int wait); -void setup_spaces(void);
#endif diff --git a/src/log.c b/src/log.c index 3cb4064..72b424f 100644 --- a/src/log.c +++ b/src/log.c @@ -100,7 +100,7 @@ static void _log_save_ent(int level, int len) * logfile and/or syslog (so callers don't block writing messages to files) */
-void log_level(int space_id, int token_id, char *name_in, int level, const char *fmt, ...) +void log_level(uint32_t space_id, uint32_t token_id, char *name_in, int level, const char *fmt, ...) { va_list ap; char name[NAME_ID_SIZE + 1]; diff --git a/src/log.h b/src/log.h index eacb91b..8661eb0 100644 --- a/src/log.h +++ b/src/log.h @@ -9,7 +9,7 @@ #ifndef __LOG_H__ #define __LOG_H__
-void log_level(int space_id, int token_id, char *name_in, int level, const char *fmt, ...) +void log_level(uint32_t space_id, uint32_t token_id, char *name_in, int level, const char *fmt, ...) __attribute__((format(printf, 5, 6)));
int setup_logging(void); diff --git a/src/main.c b/src/main.c index c249ace..b7cfe91 100644 --- a/src/main.c +++ b/src/main.c @@ -49,6 +49,7 @@ #include "lockfile.h" #include "watchdog.h" #include "task.h" +#include "client_cmd.h"
/* priorities are LOG_* from syslog.h */ int log_logfile_priority = LOG_WARNING; @@ -82,7 +83,7 @@ static struct pollfd *pollfd = NULL; static char command[COMMAND_MAX]; static int cmd_argc; static char **cmd_argv; -static unsigned int token_id_counter = 1; +static uint32_t token_id_counter = 1;
struct cmd_args { struct list_head list; /* thread_pool data */ @@ -106,10 +107,6 @@ struct thread_pool {
static struct thread_pool pool;
-extern struct list_head spaces; -extern struct list_head spaces_rem; -extern pthread_mutex_t spaces_mutex; - static struct random_data rand_data; static char rand_state[32]; static pthread_mutex_t rand_mutex = PTHREAD_MUTEX_INITIALIZER; @@ -1921,7 +1918,27 @@ static int thread_pool_create(int min_workers, int max_workers) return rv; }
-static int print_daemon_state(char *str) +/* + * sanlock client status + * + * 1. send_state_daemon + * + * 2. for each cl in clients + * send_state_client() [sanlk_state + str_len] + * + * 3. for each sp in spaces, spaces_add, spaces_rem + * send_state_lockspace() [sanlk_state + str_len + sanlk_lockspace] + * + * 4. for each r in resources, dispose_resources + * send_state_resource() [sanlk_state + str_len + sanlk_resource + sanlk_disk * num_disks] + * + * sanlock client host_status <lockspace_name> + * + * 1. for each hs in sp->host_status + * send_state_host() + */ + +static int print_state_daemon(char *str) { memset(str, 0, SANLK_STATE_MAXSTR);
@@ -1942,7 +1959,7 @@ static int print_daemon_state(char *str) return strlen(str) + 1; }
-static int print_client_state(struct client *cl, int ci, char *str) +static int print_state_client(struct client *cl, int ci, char *str) { memset(str, 0, SANLK_STATE_MAXSTR);
@@ -1969,180 +1986,295 @@ static int print_client_state(struct client *cl, int ci, char *str) return strlen(str) + 1; }
-static int print_token_state(struct token *t, char *str) +static int print_state_lockspace(struct space *sp, char *str, const char *list_name) { memset(str, 0, SANLK_STATE_MAXSTR);
snprintf(str, SANLK_STATE_MAXSTR-1, - "token_id=%u " - "acquire_result=%d " - "release_result=%d " - "leader.lver=%llu " - "leader.timestamp=%llu " - "leader.owner_id=%llu " - "leader.owner_generation=%llu", - t->token_id, - t->acquire_result, - t->release_result, - (unsigned long long)t->leader.lver, - (unsigned long long)t->leader.timestamp, - (unsigned long long)t->leader.owner_id, - (unsigned long long)t->leader.owner_generation); + "list=%s " + "space_id=%u " + "host_generation=%llu " + "space_dead=%d " + "killing_pids=%d " + "corrupt_result=%d " + "acquire_last_result=%d " + "renewal_last_result=%d " + "acquire_last_attempt=%llu " + "acquire_last_success=%llu " + "renewal_last_attempt=%llu " + "renewal_last_success=%llu", + list_name, + sp->space_id, + (unsigned long long)sp->host_generation, + sp->space_dead, + sp->killing_pids, + sp->lease_status.corrupt_result, + sp->lease_status.acquire_last_result, + sp->lease_status.renewal_last_result, + (unsigned long long)sp->lease_status.acquire_last_attempt, + (unsigned long long)sp->lease_status.acquire_last_success, + (unsigned long long)sp->lease_status.renewal_last_attempt, + (unsigned long long)sp->lease_status.renewal_last_success);
return strlen(str) + 1; }
-/* - * 0. header - * 1. dst (sanlk_state DAEMON) - * 2. dst.str (dst.len) - * 3. lst (sanlk_state LOCKSPACE) - * 4. lst.str (lst.len) print_space_state() - * 5. lockspace (sanlk_lockspace) - * 6. [repeat 3-5 for each space] - * 7. cst (sanlk_state CLIENT) - * 8. cst.str (cst.len) print_client_state() - * 9. rst (sanlk_state RESOURCE) - * 10. rst.str (rst.len) print_token_state() - * 11. resource (sanlk_resource) - * 12. disks (sanlk_disk * resource.num_disks) - * 13. [repeat 9-12 for each token] - * 14. [repeat 7-13 for each client] - */ +static int print_state_resource(struct resource *r, char *str, const char *list_name) +{ + memset(str, 0, SANLK_STATE_MAXSTR);
-/* - * TODO: - * increase max transfer size - * send spaces/spaces_add/spaces_rem instead of just spaces - * use resources/dispose_resources to send resource state instead of cl->tokens - * - * . daemon - * . clients - * . lockspaces from spaces/spaces_add/spaces_rem - * . resources from resources/dispose_resources - * - * in print function, - * for each client pid, go through resources and print any for that pid, clear the res - * print any remaining detached resources (orphan, dispose) - * - * sanlock client host_status <lockspace_name> - * send sp->host_status[] for the named lockspace - */ + snprintf(str, SANLK_STATE_MAXSTR-1, + "list=%s " + "flags=%x " + "lver=%llu " + "token_id=%u ", + list_name, + r->flags, + (unsigned long long)r->lver, + r->token_id);
-static void cmd_status(int fd, struct sm_header *h_recv) + return strlen(str) + 1; +} + +static int print_state_host(struct host_status *hs, char *str) { - struct sm_header h; - struct sanlk_state dst; - struct sanlk_state lst; - struct sanlk_state cst; - struct sanlk_state rst; - struct sanlk_lockspace lockspace; + memset(str, 0, SANLK_STATE_MAXSTR); + + snprintf(str, SANLK_STATE_MAXSTR-1, + "last_check=%llu " + "last_live=%llu " + "last_req=%llu " + "owner_id=%llu " + "owner_generation=%llu " + "timestamp=%llu ", + (unsigned long long)hs->last_check, + (unsigned long long)hs->last_live, + (unsigned long long)hs->last_req, + (unsigned long long)hs->owner_id, + (unsigned long long)hs->owner_generation, + (unsigned long long)hs->timestamp); + + return strlen(str) + 1; +} + +static void send_state_daemon(int fd) +{ + struct sanlk_state st; char str[SANLK_STATE_MAXSTR]; - struct token *token; - struct space *sp; - struct client *cl; - int ci, i, j, str_len; + int str_len;
- /* - * send header: h - */ + memset(&st, 0, sizeof(st));
- memset(&h, 0, sizeof(h)); - memcpy(&h, h_recv, sizeof(struct sm_header)); - h.length = sizeof(h); - h.data = 0; + st.type = SANLK_STATE_DAEMON;
- send(fd, &h, sizeof(h), MSG_NOSIGNAL); + str_len = print_state_daemon(str);
- /* - * send daemon state: dst, dst.str - */ + st.str_len = str_len;
- str_len = print_daemon_state(str); - memset(&dst, 0, sizeof(dst)); - dst.type = SANLK_STATE_DAEMON; - dst.str_len = str_len; + send(fd, &st, sizeof(st), MSG_NOSIGNAL); + if (str_len) + send(fd, str, str_len, MSG_NOSIGNAL); +}
- send(fd, &dst, sizeof(dst), MSG_NOSIGNAL); +static void send_state_client(int fd, struct client *cl, int ci) +{ + struct sanlk_state st; + char str[SANLK_STATE_MAXSTR]; + int str_len; + + memset(&st, 0, sizeof(st)); + + st.type = SANLK_STATE_CLIENT; + st.data32 = cl->pid; + strncpy(st.name, cl->owner_name, NAME_ID_SIZE); + + str_len = print_state_client(cl, ci, str); + + st.str_len = str_len; + + send(fd, &st, sizeof(st), MSG_NOSIGNAL); if (str_len) send(fd, str, str_len, MSG_NOSIGNAL); +}
- if (h_recv->data == SANLK_STATE_DAEMON) - return; +static void send_state_lockspace(int fd, struct space *sp, const char *list_name) +{ + struct sanlk_state st; + struct sanlk_lockspace lockspace; + char str[SANLK_STATE_MAXSTR]; + int str_len;
- /* - * send lockspace state: lst, lst.str, sanlk_lockspace - */ + memset(&st, 0, sizeof(st));
- pthread_mutex_lock(&spaces_mutex); - list_for_each_entry(sp, &spaces, list) { - str_len = print_space_state(sp, str); - memset(&lst, 0, sizeof(lst)); - lst.type = SANLK_STATE_LOCKSPACE; - lst.data64 = sp->host_id; - strncpy(lst.name, sp->space_name, NAME_ID_SIZE); - lst.str_len = str_len; + st.type = SANLK_STATE_LOCKSPACE; + st.data64 = sp->host_id; + strncpy(st.name, sp->space_name, NAME_ID_SIZE); + + str_len = print_state_lockspace(sp, str, list_name); + + st.str_len = str_len; + + send(fd, &st, sizeof(st), MSG_NOSIGNAL); + if (str_len) + send(fd, str, str_len, MSG_NOSIGNAL);
- send(fd, &lst, sizeof(lst), MSG_NOSIGNAL); - if (str_len) - send(fd, str, str_len, MSG_NOSIGNAL); + memset(&lockspace, 0, sizeof(struct sanlk_lockspace)); + strncpy(lockspace.name, sp->space_name, NAME_ID_SIZE); + lockspace.host_id = sp->host_id; + memcpy(&lockspace.host_id_disk, &sp->host_id_disk, sizeof(struct sanlk_disk));
- memset(&lockspace, 0, sizeof(struct sanlk_lockspace)); - strncpy(lockspace.name, sp->space_name, NAME_ID_SIZE); - lockspace.host_id = sp->host_id; - memcpy(&lockspace.host_id_disk, &sp->host_id_disk, sizeof(struct sanlk_disk)); + send(fd, &lockspace, sizeof(lockspace), MSG_NOSIGNAL); +} + +static void send_state_resource(int fd, struct resource *r, const char *list_name) +{ + struct sanlk_state st; + char str[SANLK_STATE_MAXSTR]; + int str_len; + int i;
- send(fd, &lockspace, sizeof(lockspace), MSG_NOSIGNAL); + memset(&st, 0, sizeof(st)); + + st.type = SANLK_STATE_RESOURCE; + st.data32 = r->pid; + strncpy(st.name, r->r.name, NAME_ID_SIZE); + + str_len = print_state_resource(r, str, list_name); + + st.str_len = str_len; + + send(fd, &st, sizeof(st), MSG_NOSIGNAL); + if (str_len) + send(fd, str, str_len, MSG_NOSIGNAL); + + send(fd, &r->r, sizeof(struct sanlk_resource), MSG_NOSIGNAL); + + for (i = 0; i < r->r.num_disks; i++) { + send(fd, &r->r.disks[i], sizeof(struct sanlk_disk), MSG_NOSIGNAL); } - pthread_mutex_unlock(&spaces_mutex); +}
- if (h_recv->data == SANLK_STATE_LOCKSPACE) - return; +static void send_state_host(int fd, struct host_status *hs, int host_id) +{ + struct sanlk_state st; + char str[SANLK_STATE_MAXSTR]; + int str_len;
- /* - * send client and resource state: - * cst, cst.str, (rst, rst.str, resource, disk*N)*M - */ + memset(&st, 0, sizeof(st)); + + st.type = SANLK_STATE_HOST; + st.data32 = host_id; + st.data64 = hs->timestamp; + + str_len = print_state_host(hs, str); + + st.str_len = str_len; + + send(fd, &st, sizeof(st), MSG_NOSIGNAL); + if (str_len) + send(fd, str, str_len, MSG_NOSIGNAL); +} + +static void cmd_status(int fd, struct sm_header *h_recv) +{ + struct sm_header h; + struct client *cl; + struct space *sp; + struct resource *r; + int ci; + + memset(&h, 0, sizeof(h)); + memcpy(&h, h_recv, sizeof(struct sm_header)); + h.length = sizeof(h); + h.data = 0; + + send(fd, &h, sizeof(h), MSG_NOSIGNAL); + + send_state_daemon(fd); + + if (h_recv->data == SANLK_STATE_DAEMON) + return;
for (ci = 0; ci <= client_maxi; ci++) { cl = &client[ci]; - if (!cl->used) continue; + send_state_client(fd, cl, ci); + }
- str_len = print_client_state(cl, ci, str); - memset(&cst, 0, sizeof(cst)); - cst.type = SANLK_STATE_CLIENT; - cst.data32 = cl->pid; - strncpy(cst.name, cl->owner_name, NAME_ID_SIZE); - cst.str_len = str_len; + if (h_recv->data == SANLK_STATE_CLIENT) + return;
- send(fd, &cst, sizeof(cst), MSG_NOSIGNAL); - if (str_len) - send(fd, str, str_len, MSG_NOSIGNAL); + pthread_mutex_lock(&spaces_mutex); + list_for_each_entry(sp, &spaces, list) + send_state_lockspace(fd, sp, "spaces"); + list_for_each_entry(sp, &spaces_rem, list) + send_state_lockspace(fd, sp, "spaces_rem"); + list_for_each_entry(sp, &spaces_rem, list) + send_state_lockspace(fd, sp, "spaces_add"); + pthread_mutex_unlock(&spaces_mutex);
- for (i = 0; i < SANLK_MAX_RESOURCES; i++) { - token = cl->tokens[i]; - if (!token) - continue; + if (h_recv->data == SANLK_STATE_LOCKSPACE) + return; + + pthread_mutex_lock(&resource_mutex); + list_for_each_entry(r, &resources, list) + send_state_resource(fd, r, "resources"); + list_for_each_entry(r, &dispose_resources, list) + send_state_resource(fd, r, "dispose_resources"); + pthread_mutex_unlock(&resource_mutex); +} + +static void cmd_host_status(int fd, struct sm_header *h_recv) +{ + struct sm_header h; + struct sanlk_lockspace lockspace; + struct space *sp; + struct host_status *hs, *status = NULL; + int status_len; + int i, rv;
- str_len = print_token_state(token, str); - memset(&rst, 0, sizeof(rst)); - rst.type = SANLK_STATE_RESOURCE; - strncpy(rst.name, token->r.name, NAME_ID_SIZE); - rst.str_len = str_len; + memset(&h, 0, sizeof(h)); + memcpy(&h, h_recv, sizeof(struct sm_header)); + h.length = sizeof(h); + h.data = 0;
- send(fd, &rst, sizeof(rst), MSG_NOSIGNAL); - if (str_len) - send(fd, str, str_len, MSG_NOSIGNAL); + status_len = sizeof(struct host_status) * DEFAULT_MAX_HOSTS;
- send(fd, &token->r, sizeof(struct sanlk_resource), MSG_NOSIGNAL); + status = malloc(status_len); + if (!status) { + h.data = -ENOMEM; + goto fail; + }
- for (j = 0; j < token->r.num_disks; j++) { - send(fd, &token->disks[j], sizeof(struct sanlk_disk), MSG_NOSIGNAL); - } - } + rv = recv(fd, &lockspace, sizeof(struct sanlk_lockspace), MSG_WAITALL); + if (rv != sizeof(struct sanlk_lockspace)) { + h.data = -ENOTCONN; + goto fail; + } + + send(fd, &h, sizeof(h), MSG_NOSIGNAL); + + pthread_mutex_lock(&spaces_mutex); + sp = find_lockspace(lockspace.name); + memcpy(status, &sp->host_status, status_len); + pthread_mutex_unlock(&spaces_mutex); + + for (i = 0; i < DEFAULT_MAX_HOSTS; i++) { + hs = &status[i]; + if (!hs->last_live && !hs->owner_id) + continue; + send_state_host(fd, hs, i+1); } + + if (status) + free(status); + return; + fail: + send(fd, &h, sizeof(h), MSG_NOSIGNAL); + + if (status) + free(status); }
static void cmd_log_dump(int fd, struct sm_header *h_recv) @@ -2354,6 +2486,10 @@ static void process_cmd_daemon(int ci, struct sm_header *h_recv) strcpy(client[ci].owner_name, "status"); cmd_status(fd, h_recv); break; + case SM_CMD_HOST_STATUS: + strcpy(client[ci].owner_name, "host_status"); + cmd_host_status(fd, h_recv); + break; case SM_CMD_LOG_DUMP: strcpy(client[ci].owner_name, "log_dump"); cmd_log_dump(fd, h_recv); @@ -2401,6 +2537,7 @@ static void process_connection(int ci) case SM_CMD_RESTRICT: case SM_CMD_SHUTDOWN: case SM_CMD_STATUS: + case SM_CMD_HOST_STATUS: case SM_CMD_LOG_DUMP: process_cmd_daemon(ci, &h); break; @@ -2644,8 +2781,6 @@ static int do_daemon(void) if (rv < 0) goto out_threads;
- setup_spaces(); - main_loop();
close_token_manager(); @@ -2871,6 +3006,7 @@ static void print_usage(void) printf("\n"); printf("sanlock client <action> [options]\n"); printf("sanlock client status [-D]\n"); + printf("sanlock client host_status -s LOCKSPACE [-D]\n"); printf("sanlock client log_dump\n"); printf("sanlock client shutdown\n"); printf("sanlock client init -s LOCKSPACE | -r RESOURCE\n"); @@ -2968,6 +3104,8 @@ static int read_command_line(int argc, char *argv[]) case COM_CLIENT: if (!strcmp(act, "status")) com.action = ACT_STATUS; + else if (!strcmp(act, "host_status")) + com.action = ACT_HOST_STATUS; else if (!strcmp(act, "log_dump")) com.action = ACT_LOG_DUMP; else if (!strcmp(act, "shutdown")) @@ -3207,6 +3345,10 @@ static int do_client(void) rv = sanlock_status(com.debug); break;
+ case ACT_HOST_STATUS: + rv = sanlock_host_status(com.debug, com.lockspace.name); + break; + case ACT_LOG_DUMP: rv = sanlock_log_dump(); break; @@ -3468,6 +3610,16 @@ int main(int argc, char *argv[])
BUILD_BUG_ON(sizeof(struct sanlk_disk) != sizeof(struct sync_disk)); BUILD_BUG_ON(sizeof(struct leader_record) > LEADER_RECORD_MAX); + + /* initialize global variables */ + pthread_mutex_init(&spaces_mutex, NULL); + pthread_mutex_init(&resource_mutex, NULL); + pthread_cond_init(&resource_cond, NULL); + INIT_LIST_HEAD(&spaces); + INIT_LIST_HEAD(&spaces_rem); + INIT_LIST_HEAD(&spaces_add); + INIT_LIST_HEAD(&resources); + INIT_LIST_HEAD(&dispose_resources); memset(&com, 0, sizeof(com)); com.use_watchdog = DEFAULT_USE_WATCHDOG; diff --git a/src/sanlock.8 b/src/sanlock.8 index e3196e9..4462280 100644 --- a/src/sanlock.8 +++ b/src/sanlock.8 @@ -248,6 +248,12 @@ io timeout in seconds Print processes, lockspaces, and resources being manged by the sanlock daemon. Add -D to show extra internal daemon status for debugging.
+.BR "sanlock client host_status -s" " LOCKSPACE" + +Print state of host_id delta leases read during the last renewal. +Only lockspace_name is used from the LOCKSPACE argument. +Add -D to show extra internal daemon status for debugging. + .B sanlock client log_dump
Print the sanlock daemon internal debug log. diff --git a/src/sanlock_admin.h b/src/sanlock_admin.h index 3a64a2d..802beee 100644 --- a/src/sanlock_admin.h +++ b/src/sanlock_admin.h @@ -11,14 +11,6 @@ #define __SANLOCK_ADMIN_H__
/* - * daemon admin/managment - */ - -int sanlock_status(int debug); -int sanlock_log_dump(void); -int sanlock_shutdown(void); - -/* * add_lockspace returns: * 0: the lockspace has been added successfully * -EEXIST: the lockspace already exists diff --git a/src/sanlock_internal.h b/src/sanlock_internal.h index 7a26749..2621317 100644 --- a/src/sanlock_internal.h +++ b/src/sanlock_internal.h @@ -79,7 +79,7 @@ struct token { uint64_t host_generation;
/* internal */ - int token_id; /* used to refer to this token instance in log messages */ + uint32_t token_id; /* used to refer to this token instance in log messages */ int space_dead; /* don't bother trying to release if ls is dead */ int acquire_result; int release_result; @@ -89,6 +89,18 @@ struct token { struct sanlk_resource r; };
+#define R_EXAMINE 0x00000001 + +struct resource { + struct list_head list; + struct token *token; + int pid; + uint32_t token_id; + uint32_t flags; + uint64_t lver; + struct sanlk_resource r; +}; + struct lease_status { int corrupt_result; int acquire_last_result; @@ -116,11 +128,11 @@ struct host_status { struct space { struct list_head list; char space_name[NAME_ID_SIZE]; + uint32_t space_id; /* used to refer to this space instance in log messages */ uint64_t host_id; uint64_t host_generation; struct sync_disk host_id_disk; int align_size; - int space_id; /* used to refer to this space instance in log messages */ int space_dead; int killing_pids; int external_remove; @@ -502,6 +514,7 @@ EXTERN struct command_line com;
enum { ACT_STATUS = 1, + ACT_HOST_STATUS, ACT_LOG_DUMP, ACT_SHUTDOWN, ACT_ADD_LOCKSPACE, @@ -527,5 +540,15 @@ enum { EXTERN int external_shutdown; EXTERN char our_host_name_global[SANLK_NAME_LEN+1];
+EXTERN struct list_head spaces; +EXTERN struct list_head spaces_rem; +EXTERN struct list_head spaces_add; +EXTERN pthread_mutex_t spaces_mutex; + +EXTERN struct list_head resources; +EXTERN struct list_head dispose_resources; +EXTERN pthread_mutex_t resource_mutex; +EXTERN pthread_cond_t resource_cond; + #endif
diff --git a/src/sanlock_sock.h b/src/sanlock_sock.h index 5c6a004..8279bd4 100644 --- a/src/sanlock_sock.h +++ b/src/sanlock_sock.h @@ -34,6 +34,7 @@ enum { SM_CMD_INIT_RESOURCE = 14, SM_CMD_EXAMINE_LOCKSPACE = 15, SM_CMD_EXAMINE_RESOURCE = 16, + SM_CMD_HOST_STATUS = 17, };
struct sm_header { @@ -50,9 +51,10 @@ struct sm_header { #define SANLK_STATE_MAXSTR 4096
#define SANLK_STATE_DAEMON 1 -#define SANLK_STATE_LOCKSPACE 2 -#define SANLK_STATE_CLIENT 3 +#define SANLK_STATE_CLIENT 2 +#define SANLK_STATE_LOCKSPACE 3 #define SANLK_STATE_RESOURCE 4 +#define SANLK_STATE_HOST 5
struct sanlk_state { uint32_t type; /* SANLK_STATE_ */ diff --git a/src/token_manager.c b/src/token_manager.c index a701cc3..6568af3 100644 --- a/src/token_manager.c +++ b/src/token_manager.c @@ -31,25 +31,10 @@ #include "task.h" #include "host_id.h"
-static struct list_head resources; -static struct list_head dispose_resources; -static pthread_mutex_t resource_mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t resource_cond = PTHREAD_COND_INITIALIZER; static pthread_t resource_pt; static int resource_thread_stop; static int resource_examine;
-#define R_EXAMINE 0x00000001 - -struct resource { - struct list_head list; - struct token *token; - int pid; - uint32_t flags; - uint64_t lver; - struct sanlk_resource r; -}; - int set_resource_examine(char *space_name, char *res_name) { struct resource *r; @@ -147,6 +132,7 @@ int add_resource(struct token *token, int pid) memset(r, 0, r_len); memcpy(&r->r, &token->r, sizeof(struct sanlk_resource)); memcpy(&r->r.disks, &token->r.disks, disks_len); + r->token_id = token->token_id; r->token = token; r->pid = pid; list_add_tail(&r->list, &resources); @@ -208,10 +194,9 @@ int acquire_token(struct task *task, struct token *token, if (rv < 0) return rv;
- save_resource_lver(token, token->leader.lver); - memcpy(&token->leader, &leader_ret, sizeof(struct leader_record)); token->r.lver = token->leader.lver; + save_resource_lver(token, token->leader.lver); return rv; /* SANLK_OK */ }
@@ -498,9 +483,6 @@ int setup_token_manager(void) { int rv;
- INIT_LIST_HEAD(&resources); - INIT_LIST_HEAD(&dispose_resources); - rv = pthread_create(&resource_pt, NULL, resource_thread, NULL); if (rv) return -1;
sanlock-devel@lists.fedorahosted.org