commit 93885cbfc6271ecb5007601369ad29cee3df6b99
Author: David Teigland <teigland(a)redhat.com>
Date: Fri Apr 11 14:10:25 2014 -0500
sanlock: shutdown reply
A wait option (-w 1) can be added to sanlock shutdown.
The shutdown command will wait for a result from the
daemon indicating success (exiting), or failure (not
exiting because lockspaces exist).
This option seems useful for vdsm.
Signed-off-by: David Teigland <teigland(a)redhat.com>
diff --git a/src/client_cmd.c b/src/client_cmd.c
index 7723f88..15c26a1 100644
--- a/src/client_cmd.c
+++ b/src/client_cmd.c
@@ -636,15 +636,40 @@ int sanlock_log_dump(int max_size)
return rv;
}
-int sanlock_shutdown(uint32_t force)
+int sanlock_shutdown(uint32_t force, int wait_result)
{
+ struct sm_header h;
+ int cmd;
int fd;
+ int rv = 0;
+
+ if (wait_result)
+ cmd = SM_CMD_SHUTDOWN_WAIT;
+ else
+ cmd = SM_CMD_SHUTDOWN;
- fd = send_command(SM_CMD_SHUTDOWN, force);
+ fd = send_command(cmd, force);
if (fd < 0)
return fd;
What you mean is return -1 - right?
+ if (cmd != SM_CMD_SHUTDOWN_WAIT)
+ goto out;
+
+ 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;
+ }
+
+ rv = h.data;
+ out:
close(fd);
- return 0;
+ return rv;
}
diff --git a/src/client_cmd.h b/src/client_cmd.h
index 35f82d9..f7c69c1 100644
--- a/src/client_cmd.h
+++ b/src/client_cmd.h
@@ -12,6 +12,6 @@
int sanlock_status(int debug, char sort_arg);
int sanlock_host_status(int debug, char *lockspace_name);
int sanlock_log_dump(int max_size);
-int sanlock_shutdown(uint32_t force);
+int sanlock_shutdown(uint32_t force, int wait_result);
#endif
diff --git a/src/cmd.c b/src/cmd.c
index f19e8fb..a9a1eef 100644
--- a/src/cmd.c
+++ b/src/cmd.c
@@ -1159,6 +1159,74 @@ static void cmd_get_lvb(struct task *task GNUC_UNUSED,
struct cmd_args *ca)
client_resume(ca->ci_in);
}
+static int shutdown_reply_ci = -1;
+static int shutdown_reply_fd = -1;
+
+static int daemon_shutdown_start(int ci, int fd, int force)
+{
+ int rv;
+
+ if (force) {
+ shutdown_reply_ci = ci;
+ shutdown_reply_fd = fd;
+ external_shutdown = 2;
+ return 0;
+ }
+
+ pthread_mutex_lock(&spaces_mutex);
+ if (list_empty(&spaces) &&
+ list_empty(&spaces_rem) &&
+ list_empty(&spaces_add)) {
+ shutdown_reply_ci = ci;
+ shutdown_reply_fd = fd;
+ external_shutdown = 1;
+ rv = 0;
+ } else {
+ rv = -EBUSY;
+ }
+ pthread_mutex_unlock(&spaces_mutex);
+
+ return rv;
+}
+
+static void cmd_shutdown_wait(struct task *task GNUC_UNUSED, struct cmd_args
*ca)
+{
+ int fd, result;
+
+ fd = client[ca->ci_in].fd;
+
+ result = daemon_shutdown_start(ca->ci_in, fd, ca->header.data);
+
+ /*
+ * daemon_shutdown_reply will send the result at the
+ * end of main_loop.
+ */
+ if (!result)
+ return;
It will be more clear to do:
if (result == -EBUSY)
return;
+
+ send_result(fd, &ca->header, result);
+ client_resume(ca->ci_in);
+}
+
+void daemon_shutdown_reply(void)
+{
+ struct sm_header h;
+
+ /* shutdown wait was not used */
+ if (shutdown_reply_fd == -1)
+ return;
+
+ memset(&h, 0, sizeof(h));
+ h.magic = SM_MAGIC;
+ h.version = SM_PROTO;
+ h.length = sizeof(h);
+
+ send(shutdown_reply_fd, &h, sizeof(h), MSG_NOSIGNAL);
+ close(shutdown_reply_fd);
+
+ client_resume(shutdown_reply_ci);
+}
+
static void cmd_add_lockspace(struct cmd_args *ca)
{
struct sanlk_lockspace lockspace;
@@ -1908,6 +1976,9 @@ void call_cmd_thread(struct task *task, struct cmd_args
*ca)
case SM_CMD_GET_LVB:
cmd_get_lvb(task, ca);
break;
+ case SM_CMD_SHUTDOWN_WAIT:
+ cmd_shutdown_wait(task, ca);
+ break;
};
}
diff --git a/src/cmd.h b/src/cmd.h
index 3f31283..30c19e6 100644
--- a/src/cmd.h
+++ b/src/cmd.h
@@ -24,4 +24,6 @@ void call_cmd_thread(struct task *task, struct cmd_args
*ca);
/* cmds processed by main loop */
void call_cmd_daemon(int ci, struct sm_header *h_recv, int client_maxi);
+void daemon_shutdown_reply(void);
+
#endif
diff --git a/src/main.c b/src/main.c
index 5f3c6ed..dbb6da8 100644
--- a/src/main.c
+++ b/src/main.c
@@ -840,6 +840,8 @@ static int main_loop(void)
free_lockspaces(1);
+ daemon_shutdown_reply();
+
return 0;
}
@@ -1194,6 +1196,7 @@ static void process_connection(int ci)
case SM_CMD_READ_RESOURCE_OWNERS:
case SM_CMD_SET_LVB:
case SM_CMD_GET_LVB:
+ case SM_CMD_SHUTDOWN_WAIT:
rv = client_suspend(ci);
if (rv < 0)
return;
@@ -1814,7 +1817,7 @@ static void print_usage(void)
printf("sanlock client gets [-h 0|1]\n");
printf("sanlock client host_status -s LOCKSPACE [-D]\n");
printf("sanlock client log_dump\n");
- printf("sanlock client shutdown [-f 0|1]\n");
+ printf("sanlock client shutdown [-f 0|1] [-w 0|1]\n");
For boolean option, it is more user friendly to use -w without a value:
sanlock client shutdown -w
But it seems that this is already use like this in other commands :-(
printf("sanlock client init -s LOCKSPACE | -r
RESOURCE\n");
printf("sanlock client read -s LOCKSPACE | -r RESOURCE\n");
printf("sanlock client align -s LOCKSPACE\n");
@@ -2047,6 +2050,7 @@ static int read_command_line(int argc, char *argv[])
break;
case 'w':
com.use_watchdog = atoi(optionarg);
+ com.wait = atoi(optionarg);
break;
case 'h':
if (com.action == ACT_GETS || com.action == ACT_CLIENT_READ)
@@ -2399,8 +2403,8 @@ static int do_client(void)
break;
case ACT_SHUTDOWN:
- log_tool("shutdown");
- rv = sanlock_shutdown(com.force_mode);
+ log_tool("shutdown force %d wait %d", com.force_mode, com.wait);
+ rv = sanlock_shutdown(com.force_mode, com.wait);
log_tool("shutdown done %d", rv);
break;
diff --git a/src/sanlock.8 b/src/sanlock.8
index 0d2b63c..7b92329 100644
--- a/src/sanlock.8
+++ b/src/sanlock.8
@@ -273,7 +273,10 @@ Print the sanlock daemon internal debug log.
Ask the sanlock daemon to exit. Without the force option (-f 0), the
command will be ignored if any lockspaces exist. With the force option
(-f 1), any registered processes will be killed, their resource leases
-released, and lockspaces removed.
+released, and lockspaces removed. With the wait option (-w 1), the
+command will wait for a result from the daemon indicating that it has
+shut down and is exiting, or cannot shut down because lockspaces
+exist (command fails).
.BR "sanlock client init -s" " LOCKSPACE"
diff --git a/src/sanlock_internal.h b/src/sanlock_internal.h
index c3fa574..a62135c 100644
--- a/src/sanlock_internal.h
+++ b/src/sanlock_internal.h
@@ -265,6 +265,7 @@ struct command_line {
int debug;
int debug_renew;
int quiet_fail;
+ int wait;
int use_watchdog;
int high_priority; /* -h */
int get_hosts; /* -h */
diff --git a/src/sanlock_sock.h b/src/sanlock_sock.h
index c5c1ec9..8e8f5e2 100644
--- a/src/sanlock_sock.h
+++ b/src/sanlock_sock.h
@@ -47,6 +47,7 @@ enum {
SM_CMD_GET_LVB = 26,
SM_CMD_CONVERT = 27,
SM_CMD_VERSION = 28,
+ SM_CMD_SHUTDOWN_WAIT = 29,
};
struct sm_header {
How much time it takes to get a reply from the daemon?
We certainly like this feature in next release, but it is not a must.
Thanks,
Nir