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