* [PATCH 1/3] multipath-tools: Remove the limitation of IPC command reply length.
@ 2017-08-16 12:34 Gris Ge
2017-08-16 12:34 ` [PATCH 2/3] multipath-tools: libdmmp: Improve timeout mechanism Gris Ge
0 siblings, 1 reply; 5+ messages in thread
From: Gris Ge @ 2017-08-16 12:34 UTC (permalink / raw)
To: dm-devel; +Cc: Gris Ge
Issue:
libmpathcmd will reply error 22(Invalid argument) when having 1000
mpath.
Root cause:
libmpathcmd return error when reply string length exceeded the 65535.
Fix:
Remove the limitation on reply data length.
Extra:
Initially this limitation was removed and improved by commit
bb219efb131aef61c331f181193bf1d80e6b2a99
but then was added back via commit
7381c3f2b19903cc56d1ddafb13e8ad3afc08580
Signed-off-by: Gris Ge <fge@redhat.com>
---
libmpathcmd/mpath_cmd.c | 4 ----
libmpathcmd/mpath_cmd.h | 1 -
2 files changed, 5 deletions(-)
diff --git a/libmpathcmd/mpath_cmd.c b/libmpathcmd/mpath_cmd.c
index 1496b682..af618cff 100644
--- a/libmpathcmd/mpath_cmd.c
+++ b/libmpathcmd/mpath_cmd.c
@@ -142,10 +142,6 @@ int mpath_recv_reply(int fd, char **reply, unsigned int timeout)
len = mpath_recv_reply_len(fd, timeout);
if (len <= 0)
return len;
- if (len > MAX_REPLY_LEN) {
- errno = EINVAL;
- return -1;
- }
*reply = malloc(len);
if (!*reply)
return -1;
diff --git a/libmpathcmd/mpath_cmd.h b/libmpathcmd/mpath_cmd.h
index 6534474c..b57b708b 100644
--- a/libmpathcmd/mpath_cmd.h
+++ b/libmpathcmd/mpath_cmd.h
@@ -26,7 +26,6 @@ extern "C" {
#define DEFAULT_SOCKET "/org/kernel/linux/storage/multipathd"
#define DEFAULT_REPLY_TIMEOUT 4000
-#define MAX_REPLY_LEN 65536
/*
--
2.14.1
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH 2/3] multipath-tools: libdmmp: Improve timeout mechanism 2017-08-16 12:34 [PATCH 1/3] multipath-tools: Remove the limitation of IPC command reply length Gris Ge @ 2017-08-16 12:34 ` Gris Ge 2017-08-16 12:34 ` [PATCH 3/3] multipath-tools: libdmmp: New function to flush and reconfig Gris Ge 2017-08-17 21:29 ` [PATCH 2/3] multipath-tools: libdmmp: Improve timeout mechanism Martin Wilck 0 siblings, 2 replies; 5+ messages in thread From: Gris Ge @ 2017-08-16 12:34 UTC (permalink / raw) To: dm-devel; +Cc: Gris Ge Issue: libdmmp return error of timeout before user requested timeout was met. This happens when multipathd daemon is starting with a lot(1k+) mpaths. Root cause: The multipath has two timeout settings: 1. 'uxsock_timeout' in multipath.conf 2. libmpathcmd timeout argument. And the first is not controllable in current libdmmp code. Fix: * Only keep 1 timeout setting in libdmmp: dmmp_context_timeout_set()/dmmp_context_timeout_get(). * libdmmp will keep reply until meet user requested timeout. * Allow user to set timeout as 0 which mean infinite, only return when error or pass. * Updated libdmmp.h document to to indicate timeout 0 as infinite. * Increase timeout setting in libdmmp test case to test this mechanism. Signed-off-by: Gris Ge <fge@redhat.com> --- libdmmp/libdmmp.c | 136 ++++++++++++++++++++++++++++++++++++-------- libdmmp/libdmmp/libdmmp.h | 1 + libdmmp/test/libdmmp_test.c | 2 +- 3 files changed, 114 insertions(+), 25 deletions(-) diff --git a/libdmmp/libdmmp.c b/libdmmp/libdmmp.c index 3906335a..6db348b4 100644 --- a/libdmmp/libdmmp.c +++ b/libdmmp/libdmmp.c @@ -29,6 +29,7 @@ #include <unistd.h> #include <assert.h> #include <json.h> +#include <time.h> #include <mpath_cmd.h> #include "libdmmp/libdmmp.h" @@ -54,6 +55,17 @@ struct dmmp_context { unsigned int tmo; }; +/* + * The multipathd daemon are using "uxsock_timeout" to define timeout value, + * if timeout at daemon side, we will get message "timeout\n". + * To unify this timeout with `dmmp_context_timeout_set()`, this function + * will keep retry mpath_process_cmd() tile meet the time of + * dmmp_context_timeout_get(). + * Need to free `*output` string manually. + */ +static int _process_cmd(struct dmmp_context *ctx, int fd, const char *cmd, + char **output); + _dmmp_getter_func_gen(dmmp_context_log_priority_get, struct dmmp_context, ctx, log_priority, int); @@ -169,32 +181,11 @@ int dmmp_mpath_array_get(struct dmmp_context *ctx, goto out; } - if (mpath_process_cmd(socket_fd, _DMMP_IPC_SHOW_JSON_CMD, - &j_str, ctx->tmo) != 0) { - errno_save = errno; - memset(errno_str_buff, 0, _ERRNO_STR_BUFF_SIZE); - strerror_r(errno_save, errno_str_buff, _ERRNO_STR_BUFF_SIZE); - if (errno_save == ETIMEDOUT) { - rc = DMMP_ERR_IPC_TIMEOUT; - _error(ctx, "IPC communication timeout, try to " - "increase it via dmmp_context_timeout_set()"); - goto out; - } - _error(ctx, "IPC failed when process command '%s' with " - "error %d(%s)", _DMMP_IPC_SHOW_JSON_CMD, errno_save, - errno_str_buff); - rc = DMMP_ERR_IPC_ERROR; - goto out; - } - - if ((j_str == NULL) || (strlen(j_str) == 0)) { - _error(ctx, "IPC return empty reply for command %s", - _DMMP_IPC_SHOW_JSON_CMD); - rc = DMMP_ERR_IPC_ERROR; - goto out; - } + _good(_process_cmd(ctx, socket_fd, _DMMP_IPC_SHOW_JSON_CMD, &j_str), + rc, out); _debug(ctx, "Got json output from multipathd: '%s'", j_str); + j_token = json_tokener_new(); if (j_token == NULL) { rc = DMMP_ERR_BUG; @@ -283,3 +274,100 @@ out: return rc; } + +static int _process_cmd(struct dmmp_context *ctx, int fd, const char *cmd, + char **output) +{ + int errno_save = 0; + int rc = DMMP_OK; + char errno_str_buff[_ERRNO_STR_BUFF_SIZE]; + struct timespec start_ts; + struct timespec cur_ts; + unsigned int ipc_tmo = 0; + bool flag_check_tmo = false; + unsigned int elapsed = 0; + + assert(output != NULL); + assert(ctx != NULL); + assert(cmd != NULL); + + *output = NULL; + + if (clock_gettime(CLOCK_MONOTONIC, &start_ts) != 0) { + _error(ctx, "BUG: Failed to get CLOCK_MONOTONIC time " + "via clock_gettime(), error %d", errno); + return DMMP_ERR_BUG; + } + + ipc_tmo = ctx->tmo; + if (ctx->tmo == 0) + ipc_tmo = _DEFAULT_UXSOCK_TIMEOUT; + +invoke: + _debug(ctx, "Invoking IPC command '%s' with IPC tmo %u miliseconds", + cmd, ipc_tmo); + flag_check_tmo = false; + if (mpath_process_cmd(fd, cmd, output, ipc_tmo) != 0) { + errno_save = errno; + memset(errno_str_buff, 0, _ERRNO_STR_BUFF_SIZE); + strerror_r(errno_save, errno_str_buff, _ERRNO_STR_BUFF_SIZE); + if (errno_save == ETIMEDOUT) { + flag_check_tmo = true; + } else { + _error(ctx, "IPC failed when process command '%s' with " + "error %d(%s)", cmd, errno_save, errno_str_buff); + _debug(ctx, "%s", *output); + rc = DMMP_ERR_IPC_ERROR; + goto out; + } + } + if ((*output != NULL) && + (strncmp(*output, "timeout", strlen("timeout")) == 0)) + flag_check_tmo = true; + + if (flag_check_tmo == true) { + free(*output); + *output = NULL; + if (ctx->tmo == 0) { + _debug(ctx, "IPC timeout, but user requested infinite " + "timeout"); + goto invoke; + } + + if (clock_gettime(CLOCK_MONOTONIC, &cur_ts) != 0) { + _error(ctx, "BUG: Failed to get CLOCK_MONOTONIC time " + "via clock_gettime(), error %d", errno); + rc = DMMP_ERR_BUG; + goto out; + } + elapsed = (cur_ts.tv_sec - start_ts.tv_sec) * 1000 + + (cur_ts.tv_nsec - start_ts.tv_nsec) / 1000000; + + if (elapsed >= ctx->tmo) { + rc = DMMP_ERR_IPC_TIMEOUT; + _error(ctx, "Timeout, try to increase it via " + "dmmp_context_timeout_set()"); + goto out; + } + if (ctx->tmo != 0) + ipc_tmo = ctx->tmo - elapsed; + + _debug(ctx, "IPC timeout, but user requested timeout has not " + "reached yet, still have %u milliseconds", ipc_tmo); + goto invoke; + } else { + if ((*output == NULL) || (strlen(*output) == 0)) { + _error(ctx, "IPC return empty reply for command %s", + cmd); + rc = DMMP_ERR_IPC_ERROR; + goto out; + } + } + +out: + if (rc != DMMP_OK) { + free(*output); + *output = NULL; + } + return rc; +} diff --git a/libdmmp/libdmmp/libdmmp.h b/libdmmp/libdmmp/libdmmp.h index 06791586..3f3fd017 100644 --- a/libdmmp/libdmmp/libdmmp.h +++ b/libdmmp/libdmmp/libdmmp.h @@ -171,6 +171,7 @@ DMMP_DLL_EXPORT void dmmp_context_free(struct dmmp_context *ctx); * * @tmo: * Timeout in milliseconds(1 seconds equal 1000 milliseconds). + * 0 means infinite, function only return when error or pass. * * Return: * void diff --git a/libdmmp/test/libdmmp_test.c b/libdmmp/test/libdmmp_test.c index 00b40e90..dad0e280 100644 --- a/libdmmp/test/libdmmp_test.c +++ b/libdmmp/test/libdmmp_test.c @@ -35,7 +35,7 @@ } while(0) #define PASS(...) fprintf(stdout, "PASS: "__VA_ARGS__ ); #define FILE_NAME_SIZE 256 -#define TMO 10000 /* Forcing timeout to 10 seconds */ +#define TMO 60000 /* Forcing timeout to 60 seconds */ int test_paths(struct dmmp_path_group *mp_pg) { -- 2.14.1 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 3/3] multipath-tools: libdmmp: New function to flush and reconfig 2017-08-16 12:34 ` [PATCH 2/3] multipath-tools: libdmmp: Improve timeout mechanism Gris Ge @ 2017-08-16 12:34 ` Gris Ge 2017-08-17 21:29 ` [PATCH 2/3] multipath-tools: libdmmp: Improve timeout mechanism Martin Wilck 1 sibling, 0 replies; 5+ messages in thread From: Gris Ge @ 2017-08-16 12:34 UTC (permalink / raw) To: dm-devel; +Cc: Gris Ge New functions: * dmmp_reconfig() to invoke reconfiguration of multipathd daemon. * dmmp_flush_mpath() to flush/del unused mpath. Signed-off-by: Gris Ge <fge@redhat.com> --- libdmmp/libdmmp.c | 143 +++++++++++++++++++++++++++++++++++++------- libdmmp/libdmmp/libdmmp.h | 60 +++++++++++++++++++ libdmmp/libdmmp_misc.c | 5 +- libdmmp/test/libdmmp_test.c | 47 ++++++++++++++- 4 files changed, 229 insertions(+), 26 deletions(-) diff --git a/libdmmp/libdmmp.c b/libdmmp/libdmmp.c index 6db348b4..b4e7f08f 100644 --- a/libdmmp/libdmmp.c +++ b/libdmmp/libdmmp.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 - 2016 Red Hat, Inc. + * Copyright (C) 2015 - 2017 Red Hat, Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,6 +19,7 @@ */ #include <stdint.h> +#include <stdbool.h> #include <string.h> #include <sys/time.h> #include <sys/resource.h> @@ -45,6 +46,8 @@ #define _DMMP_JSON_MAJOR_VERSION 0 #define _DMMP_JSON_MAPS_KEY "maps" #define _ERRNO_STR_BUFF_SIZE 256 +#define _IPC_MAX_CMD_LEN 512 +/* ^ Was _MAX_CMD_LEN in ./libmultipath/uxsock.h */ struct dmmp_context { void (*log_func)(struct dmmp_context *ctx, int priority, @@ -66,6 +69,8 @@ struct dmmp_context { static int _process_cmd(struct dmmp_context *ctx, int fd, const char *cmd, char **output); +static int _ipc_connect(struct dmmp_context *ctx, int *fd); + _dmmp_getter_func_gen(dmmp_context_log_priority_get, struct dmmp_context, ctx, log_priority, int); @@ -153,9 +158,7 @@ int dmmp_mpath_array_get(struct dmmp_context *ctx, uint32_t i = 0; int cur_json_major_version = -1; int ar_maps_len = -1; - int socket_fd = -1; - int errno_save = 0; - char errno_str_buff[_ERRNO_STR_BUFF_SIZE]; + int ipc_fd = -1; assert(ctx != NULL); assert(dmmp_mps != NULL); @@ -164,24 +167,9 @@ int dmmp_mpath_array_get(struct dmmp_context *ctx, *dmmp_mps = NULL; *dmmp_mp_count = 0; - socket_fd = mpath_connect(); - if (socket_fd == -1) { - errno_save = errno; - memset(errno_str_buff, 0, _ERRNO_STR_BUFF_SIZE); - strerror_r(errno_save, errno_str_buff, _ERRNO_STR_BUFF_SIZE); - if (errno_save == ECONNREFUSED) { - rc = DMMP_ERR_NO_DAEMON; - _error(ctx, "Socket connection refuse. " - "Maybe multipathd daemon is not running"); - } else { - _error(ctx, "IPC failed with error %d(%s)", errno_save, - errno_str_buff); - rc = DMMP_ERR_IPC_ERROR; - } - goto out; - } + _good(_ipc_connect(ctx, &ipc_fd), rc, out); - _good(_process_cmd(ctx, socket_fd, _DMMP_IPC_SHOW_JSON_CMD, &j_str), + _good(_process_cmd(ctx, ipc_fd, _DMMP_IPC_SHOW_JSON_CMD, &j_str), rc, out); _debug(ctx, "Got json output from multipathd: '%s'", j_str); @@ -258,8 +246,8 @@ int dmmp_mpath_array_get(struct dmmp_context *ctx, } out: - if (socket_fd >= 0) - mpath_disconnect(socket_fd); + if (ipc_fd >= 0) + mpath_disconnect(ipc_fd); free(j_str); if (j_token != NULL) json_tokener_free(j_token); @@ -371,3 +359,112 @@ out: } return rc; } + +static int _ipc_connect(struct dmmp_context *ctx, int *fd) +{ + int rc = DMMP_OK; + int errno_save = 0; + char errno_str_buff[_ERRNO_STR_BUFF_SIZE]; + + assert(ctx != NULL); + assert(fd != NULL); + + *fd = -1; + + *fd = mpath_connect(); + if (*fd == -1) { + errno_save = errno; + memset(errno_str_buff, 0, _ERRNO_STR_BUFF_SIZE); + strerror_r(errno_save, errno_str_buff, _ERRNO_STR_BUFF_SIZE); + if (errno_save == ECONNREFUSED) { + rc = DMMP_ERR_NO_DAEMON; + _error(ctx, "Socket connection refuse. " + "Maybe multipathd daemon is not running"); + } else { + _error(ctx, "IPC failed with error %d(%s)", errno_save, + errno_str_buff); + rc = DMMP_ERR_IPC_ERROR; + } + } + return rc; +} + +int dmmp_flush_mpath(struct dmmp_context *ctx, const char *mpath_name) +{ + int rc = DMMP_OK; + struct dmmp_mpath **dmmp_mps = NULL; + uint32_t dmmp_mp_count = 0; + uint32_t i = 0; + bool found = false; + int ipc_fd = -1; + char cmd[_IPC_MAX_CMD_LEN]; + char *output = NULL; + + assert(ctx != NULL); + assert(mpath_name != NULL); + + snprintf(cmd, _IPC_MAX_CMD_LEN, "del map %s", mpath_name); + if (strlen(cmd) == _IPC_MAX_CMD_LEN - 1) { + rc = DMMP_ERR_INVALID_ARGUMENT; + _error(ctx, "Invalid mpath name %s", mpath_name); + goto out; + } + + _good(_ipc_connect(ctx, &ipc_fd), rc, out); + _good(_process_cmd(ctx, ipc_fd, cmd, &output), rc, out); + + /* _process_cmd() already make sure output is not NULL */ + + if (strncmp(output, "fail", strlen("fail")) == 0) { + /* Check whether specified mpath exits */ + _good(dmmp_mpath_array_get(ctx, &dmmp_mps, &dmmp_mp_count), + rc, out); + + for (i = 0; i < dmmp_mp_count; ++i) { + if (strcmp(dmmp_mpath_name_get(dmmp_mps[i]), + mpath_name) == 0) { + found = true; + break; + } + } + + if (found == false) { + rc = DMMP_ERR_MPATH_NOT_FOUND; + _error(ctx, "Specified mpath %s not found", mpath_name); + goto out; + } + + rc = DMMP_ERR_MPATH_BUSY; + _error(ctx, "Specified mpath is in use"); + } else if (strncmp(output, "ok", strlen("ok")) != 0) { + rc = DMMP_ERR_BUG; + _error(ctx, "Got unexpected output for cmd '%s': '%s'", + cmd, output); + } + +out: + if (ipc_fd >= 0) + mpath_disconnect(ipc_fd); + dmmp_mpath_array_free(dmmp_mps, dmmp_mp_count); + free(output); + return rc; +} + +int dmmp_reconfig(struct dmmp_context *ctx) +{ + int rc = DMMP_OK; + int ipc_fd = -1; + char *output = NULL; + char cmd[_IPC_MAX_CMD_LEN]; + + snprintf(cmd, _IPC_MAX_CMD_LEN, "%s", "reconfigure"); + + _good(_ipc_connect(ctx, &ipc_fd), rc, out); + _good(_process_cmd(ctx, ipc_fd, cmd, &output), rc, out); + +out: + if (ipc_fd >= 0) + mpath_disconnect(ipc_fd); + free(output); + return rc; +} diff --git a/libdmmp/libdmmp/libdmmp.h b/libdmmp/libdmmp/libdmmp.h index 3f3fd017..72b79b97 100644 --- a/libdmmp/libdmmp/libdmmp.h +++ b/libdmmp/libdmmp/libdmmp.h @@ -39,6 +39,9 @@ extern "C" { #define DMMP_ERR_IPC_ERROR 4 #define DMMP_ERR_NO_DAEMON 5 #define DMMP_ERR_INCOMPATIBLE 6 +#define DMMP_ERR_MPATH_BUSY 7 +#define DMMP_ERR_MPATH_NOT_FOUND 8 +#define DMMP_ERR_INVALID_ARGUMENT 9 /* * Use the syslog severity level as log priority @@ -647,6 +650,63 @@ DMMP_DLL_EXPORT uint32_t dmmp_path_status_get(struct dmmp_path *dmmp_p); */ DMMP_DLL_EXPORT const char *dmmp_path_status_str(uint32_t path_status); +/** + * dmmp_flush_mpath() - Flush specified multipath device map if unused. + * + * Flush a multipath device map specified as parameter, if unused. + * + * @ctx: + * Pointer of 'struct dmmp_context'. + * If this pointer is NULL, your program will be terminated by assert. + * @mpath_name: + * const char *. The name of multipath device map. + * + * Return: + * int. Valid error codes are: + * + * * DMMP_OK + * + * * DMMP_ERR_BUG + * + * * DMMP_ERR_NO_MEMORY + * + * * DMMP_ERR_NO_DAEMON + * + * * DMMP_ERR_MPATH_BUSY + * + * * DMMP_ERR_MPATH_NOT_FOUND + * + * * DMMP_ERR_INVALID_ARGUMENT + * + * Error number could be converted to string by dmmp_strerror(). + */ +DMMP_DLL_EXPORT int dmmp_flush_mpath(struct dmmp_context *ctx, + const char *mpath_name); + +/** + * dmmp_reconfig() - Instruct multipathd daemon to do reconfiguration. + * + * Instruct multipathd daemon to do reconfiguration. + * + * @ctx: + * Pointer of 'struct dmmp_context'. + * If this pointer is NULL, your program will be terminated by assert. + * + * Return: + * int. Valid error codes are: + * + * * DMMP_OK + * + * * DMMP_ERR_BUG + * + * * DMMP_ERR_NO_MEMORY + * + * * DMMP_ERR_NO_DAEMON + * + * Error number could be converted to string by dmmp_strerror(). + */ +DMMP_DLL_EXPORT int dmmp_reconfig(struct dmmp_context *ctx); + #ifdef __cplusplus } /* End of extern "C" */ #endif diff --git a/libdmmp/libdmmp_misc.c b/libdmmp/libdmmp_misc.c index 27f1161a..435ddfa5 100644 --- a/libdmmp/libdmmp_misc.c +++ b/libdmmp/libdmmp_misc.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 - 2016 Red Hat, Inc. + * Copyright (C) 2015 - 2017 Red Hat, Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -46,6 +46,9 @@ static const struct _num_str_conv _DMMP_RC_MSG_CONV[] = { {DMMP_ERR_IPC_ERROR, "Error when communicate with multipathd daemon"}, {DMMP_ERR_NO_DAEMON, "The multipathd daemon not started"}, {DMMP_ERR_INCOMPATIBLE, "Incompatible multipathd daemon version"}, + {DMMP_ERR_MPATH_BUSY, "Specified multipath device map is in use"}, + {DMMP_ERR_MPATH_NOT_FOUND, "Specified multipath not found"}, + {DMMP_ERR_INVALID_ARGUMENT, "Invalid argument"}, }; _dmmp_str_func_gen(dmmp_strerror, int, rc, _DMMP_RC_MSG_CONV); diff --git a/libdmmp/test/libdmmp_test.c b/libdmmp/test/libdmmp_test.c index dad0e280..56bd03e7 100644 --- a/libdmmp/test/libdmmp_test.c +++ b/libdmmp/test/libdmmp_test.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2016 Red Hat, Inc. + * Copyright (C) 2015-2017 Red Hat, Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,6 +24,7 @@ #include <string.h> #include <pthread.h> #include <unistd.h> +#include <stdbool.h> #include <libdmmp/libdmmp.h> @@ -106,11 +107,14 @@ int main(int argc, char *argv[]) struct dmmp_context *ctx = NULL; struct dmmp_mpath **dmmp_mps = NULL; uint32_t dmmp_mp_count = 0; + uint32_t old_dmmp_mp_count = 0; const char *name = NULL; const char *wwid = NULL; const char *kdev = NULL; uint32_t i = 0; int rc = EXIT_SUCCESS; + const char *old_name = NULL; + bool found = false; ctx = dmmp_context_new(); dmmp_context_log_priority_set(ctx, DMMP_LOG_PRIORITY_DEBUG); @@ -119,7 +123,7 @@ int main(int argc, char *argv[]) dmmp_context_timeout_set(ctx, TMO); if (dmmp_context_timeout_get(ctx) != TMO) FAIL(rc, out, "dmmp_context_timeout_set(): Failed to set " - "timeout to %u", TMO); + "timeout to %u\n", TMO); if (dmmp_mpath_array_get(ctx, &dmmp_mps, &dmmp_mp_count) != 0) FAIL(rc, out, "dmmp_mpath_array_get(): rc != 0\n"); @@ -140,7 +144,46 @@ int main(int argc, char *argv[]) if (rc != 0) goto out; } + + old_name = strdup(name); + if (old_name == NULL) + FAIL(rc, out, "strdup(): no memory\n"); + + old_dmmp_mp_count = dmmp_mp_count; + dmmp_mpath_array_free(dmmp_mps, dmmp_mp_count); + + if (dmmp_flush_mpath(ctx, old_name) != DMMP_OK) + FAIL(rc, out, "dmmp_flush_mpath(): Failed\n"); + + PASS("dmmp_flush_mpath(): OK\n"); + + if (dmmp_reconfig(ctx) != DMMP_OK) + FAIL(rc, out, "dmmp_reconfig(): Failed\n"); + + PASS("dmmp_reconfig(): OK\n"); + + if (dmmp_mpath_array_get(ctx, &dmmp_mps, &dmmp_mp_count) != 0) + FAIL(rc, out, "dmmp_mpath_array_get(): rc != 0\n"); + if (dmmp_mp_count == 0) + FAIL(rc, out, "dmmp_mpath_array_get(): " + "Got no multipath devices\n"); + + if (dmmp_mp_count != old_dmmp_mp_count) + FAIL(rc, out, "Got different mpath count after reconfig: " + "old %" PRIu32 ", new %" PRIu32 "\n", old_dmmp_mp_count, + dmmp_mp_count); + + for (i = 0; i < dmmp_mp_count; ++i) { + if (strcmp(old_name, dmmp_mpath_name_get(dmmp_mps[i])) == 0) { + found = true; + break; + } + } + if (found == false) + FAIL(rc, out, "dmmp_reconfig() does not recreate deleted " + "mpath %s\n", old_name); + out: dmmp_context_free(ctx); exit(rc); -- 2.14.1 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 2/3] multipath-tools: libdmmp: Improve timeout mechanism 2017-08-16 12:34 ` [PATCH 2/3] multipath-tools: libdmmp: Improve timeout mechanism Gris Ge 2017-08-16 12:34 ` [PATCH 3/3] multipath-tools: libdmmp: New function to flush and reconfig Gris Ge @ 2017-08-17 21:29 ` Martin Wilck 2017-08-28 12:58 ` Gris Ge 1 sibling, 1 reply; 5+ messages in thread From: Martin Wilck @ 2017-08-17 21:29 UTC (permalink / raw) To: dm-devel On Wed, 2017-08-16 at 20:34 +0800, Gris Ge wrote: > Issue: > libdmmp return error of timeout before user requested timeout was > met. > This happens when multipathd daemon is starting with a lot(1k+) > mpaths. > > Root cause: > The multipath has two timeout settings: > 1. 'uxsock_timeout' in multipath.conf > 2. libmpathcmd timeout argument. > And the first is not controllable in current libdmmp code. > > Fix: > * Only keep 1 timeout setting in libdmmp: > dmmp_context_timeout_set()/dmmp_context_timeout_get(). > * libdmmp will keep reply until meet user requested timeout. Maybe I'm missing something here, but if you just retry the timed-out command, isn't it likely that you'll hit the uxsock_timeout again and again? Best, Martin -- Dr. Martin Wilck <mwilck@suse.com>, Tel. +49 (0)911 74053 2107 SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton HRB 21284 (AG Nürnberg) -- dm-devel mailing list dm-devel@redhat.com https://www.redhat.com/mailman/listinfo/dm-devel ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 2/3] multipath-tools: libdmmp: Improve timeout mechanism 2017-08-17 21:29 ` [PATCH 2/3] multipath-tools: libdmmp: Improve timeout mechanism Martin Wilck @ 2017-08-28 12:58 ` Gris Ge 0 siblings, 0 replies; 5+ messages in thread From: Gris Ge @ 2017-08-28 12:58 UTC (permalink / raw) To: Martin Wilck; +Cc: dm-devel [-- Attachment #1.1: Type: text/plain, Size: 623 bytes --] On Thu, Aug 17, 2017 at 11:29:56PM +0200, Martin Wilck wrote: > On Wed, 2017-08-16 at 20:34 +0800, Gris Ge wrote: > > Issue: > > libdmmp return error of timeout before user requested timeout was > > met. > > Maybe I'm missing something here, but if you just retry the timed-out > command, isn't it likely that you'll hit the uxsock_timeout again and > again? > > Best, > Martin Hi Martin, You will get timeout again after `uxsock_timeout` seconds if the daemon/multipathd haven't finish its work on dm tables and invoking path checker. But eventually, you will the requested data. -- Gris Ge [-- Attachment #1.2: signature.asc --] [-- Type: application/pgp-signature, Size: 833 bytes --] [-- Attachment #2: Type: text/plain, Size: 0 bytes --] ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2017-08-28 12:58 UTC | newest] Thread overview: 5+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2017-08-16 12:34 [PATCH 1/3] multipath-tools: Remove the limitation of IPC command reply length Gris Ge 2017-08-16 12:34 ` [PATCH 2/3] multipath-tools: libdmmp: Improve timeout mechanism Gris Ge 2017-08-16 12:34 ` [PATCH 3/3] multipath-tools: libdmmp: New function to flush and reconfig Gris Ge 2017-08-17 21:29 ` [PATCH 2/3] multipath-tools: libdmmp: Improve timeout mechanism Martin Wilck 2017-08-28 12:58 ` Gris Ge
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.