diff options
author | Ondrej Kozina <okozina@redhat.com> | 2015-02-27 14:08:53 +0100 |
---|---|---|
committer | Ondrej Kozina <okozina@redhat.com> | 2015-04-01 11:01:22 +0200 |
commit | 84092da2cf2847f1600a7a64ab2a83fb5b0ef586 (patch) | |
tree | 2a9e629196e54022953e1df36df1d9a98b95281d | |
parent | 3f4ce8e68d9f0a24d598d73f77b669e35bedfd73 (diff) | |
download | lvm2-84092da2cf2847f1600a7a64ab2a83fb5b0ef586.tar.gz |
lvmpolld: monitor LVs per LVM_SYSTEM_DIR and lvid
lvmpolld is now able to monitor more than one equal lvids at once
assuming each request for monitoring LVID=X is also filled with
different LVM_SYSTEM_DIR env. variable value.
In other words lvmpolld replaced lvid as an unique identifier with
couple: <LVM_SYSTEM_DIR value>+lvid.
-rw-r--r-- | daemons/lvmpolld/Makefile.in | 2 | ||||
-rw-r--r-- | daemons/lvmpolld/lvmpolld-cmd-utils.c | 139 | ||||
-rw-r--r-- | daemons/lvmpolld/lvmpolld-cmd-utils.h | 25 | ||||
-rw-r--r-- | daemons/lvmpolld/lvmpolld-core.c | 236 | ||||
-rw-r--r-- | daemons/lvmpolld/lvmpolld-data-utils.c | 88 | ||||
-rw-r--r-- | daemons/lvmpolld/lvmpolld-data-utils.h | 12 | ||||
-rw-r--r-- | daemons/lvmpolld/lvmpolld-protocol.h | 3 |
7 files changed, 351 insertions, 154 deletions
diff --git a/daemons/lvmpolld/Makefile.in b/daemons/lvmpolld/Makefile.in index dc8821395..e007b5e03 100644 --- a/daemons/lvmpolld/Makefile.in +++ b/daemons/lvmpolld/Makefile.in @@ -15,7 +15,7 @@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ -SOURCES = lvmpolld-core.c lvmpolld-data-utils.c +SOURCES = lvmpolld-core.c lvmpolld-data-utils.c lvmpolld-cmd-utils.c #SOURCES2 = testdaemon-testclient.c TARGETS = lvmpolld diff --git a/daemons/lvmpolld/lvmpolld-cmd-utils.c b/daemons/lvmpolld/lvmpolld-cmd-utils.c new file mode 100644 index 000000000..e33d147de --- /dev/null +++ b/daemons/lvmpolld/lvmpolld-cmd-utils.c @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2015 Red Hat, Inc. + * + * This file is part of LVM2. + * + * 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 Lesser General Public License v.2.1. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <unistd.h> + +#include "libdevmapper.h" +#include "lvmpolld-cmd-utils.h" +#include "lvmpolld-protocol.h" + +/* extract this info from autoconf/automake files */ +#define LVPOLL_CMD "lvpoll" + +extern char **environ; + +static const char *const const polling_ops[] = { [PVMOVE] = LVMPD_REQ_PVMOVE, + [CONVERT] = LVMPD_REQ_CONVERT, + [MERGE] = LVMPD_REQ_MERGE, + [MERGE_THIN] = LVMPD_REQ_MERGE_THIN }; + +static int add_to_cmd_arr(const char ***cmdargv, const char *str, unsigned *index, unsigned renameme) +{ + const char **newargv = *cmdargv; + + if (*index && !(*index % renameme)) { + newargv = dm_realloc(*cmdargv, (*index / renameme + 1) * renameme * sizeof(char *)); + if (!newargv) + return 0; + *cmdargv = newargv; + } + + *(*cmdargv + (*index)++) = str; + + return 1; +} + +const char **cmdargv_ctr(const lvmpolld_lv_t *pdlv, const char *lvm_binary, unsigned abort, unsigned handle_missing_pvs) +{ + unsigned i = 0; + const char **cmd_argv = dm_malloc(MIN_ARGV_SIZE * sizeof(char *)); + + if (!cmd_argv) + return NULL; + + /* path to lvm2 binary */ + if (!add_to_cmd_arr(&cmd_argv, lvm_binary, &i, MIN_ARGV_SIZE)) + goto err; + + /* cmd to execute */ + if (!add_to_cmd_arr(&cmd_argv, LVPOLL_CMD, &i, MIN_ARGV_SIZE)) + goto err; + + /* transfer internal polling interval */ + if (pdlv->sinterval && + (!add_to_cmd_arr(&cmd_argv, "--interval", &i, MIN_ARGV_SIZE) || + !add_to_cmd_arr(&cmd_argv, pdlv->sinterval, &i, MIN_ARGV_SIZE))) + goto err; + + /* pass abort param */ + if (abort && + !add_to_cmd_arr(&cmd_argv, "--abort", &i, MIN_ARGV_SIZE)) + goto err; + + /* pass handle-missing-pvs. used by mirror polling operation */ + if (handle_missing_pvs && + !add_to_cmd_arr(&cmd_argv, "--handle-missing-pvs", &i, MIN_ARGV_SIZE)) + goto err; + + /* one of: "convert", "pvmove", "merge", "merge_thin" */ + if (!add_to_cmd_arr(&cmd_argv, "--poll-operation", &i, MIN_ARGV_SIZE) || + !add_to_cmd_arr(&cmd_argv, polling_ops[pdlv->type], &i, MIN_ARGV_SIZE)) + goto err; + + /* vg/lv name */ + if (!add_to_cmd_arr(&cmd_argv, pdlv->lvname, &i, MIN_ARGV_SIZE)) + goto err; + + /* terminating NULL */ + if (!add_to_cmd_arr(&cmd_argv, NULL, &i, MIN_ARGV_SIZE)) + goto err; + + return cmd_argv; +err: + dm_free(cmd_argv); + return NULL; +} + +/* FIXME: in fact exclude should be va list */ +static int copy_env(const char ***cmd_envp, unsigned *i, unsigned renameme, const char *exclude) +{ + const char * const* tmp = environ; + + if (!tmp) + return 0; + + while (*tmp) { + if (strncmp(*tmp, exclude, strlen(exclude)) && !add_to_cmd_arr(cmd_envp, *tmp, i, renameme)) + return 0; + tmp++; + } + + return 1; +} + +const char **cmdenvp_ctr(const lvmpolld_lv_t *pdlv) +{ + unsigned i = 0; + const char **cmd_envp = dm_malloc(MIN_ARGV_SIZE * sizeof(char *)); + + if (!cmd_envp) + return NULL; + + /* copy whole environment from lvmpolld, exclude LVM_SYSTEM_DIR if set */ + if (!copy_env(&cmd_envp, &i, MIN_ARGV_SIZE, "LVM_SYSTEM_DIR=")) + goto err; + + /* Add per client LVM_SYSTEM_DIR variable if set */ + if (*pdlv->lvm_system_dir_env && !add_to_cmd_arr(&cmd_envp, pdlv->lvm_system_dir_env, &i, MIN_ARGV_SIZE)) + goto err; + + /* terminating NULL */ + if (!add_to_cmd_arr(&cmd_envp, NULL, &i, MIN_ARGV_SIZE)) + goto err; + + return cmd_envp; +err: + dm_free(cmd_envp); + return NULL; +} diff --git a/daemons/lvmpolld/lvmpolld-cmd-utils.h b/daemons/lvmpolld/lvmpolld-cmd-utils.h new file mode 100644 index 000000000..ada794db9 --- /dev/null +++ b/daemons/lvmpolld/lvmpolld-cmd-utils.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2015 Red Hat, Inc. + * + * This file is part of LVM2. + * + * 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 Lesser General Public License v.2.1. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _LVM_LVMPOLLD_CMD_UTILS_H +#define _LVM_LVMPOLLD_CMD_UTILS_H + +#include "lvmpolld-data-utils.h" + +#define MIN_ARGV_SIZE 8 + +const char **cmdargv_ctr(const lvmpolld_lv_t *pdlv, const char *lvm_binary, unsigned abort, unsigned handle_missing_pvs); +const char **cmdenvp_ctr(const lvmpolld_lv_t *pdlv); + +#endif /* _LVM_LVMPOLLD_CMD_UTILS_H */ diff --git a/daemons/lvmpolld/lvmpolld-core.c b/daemons/lvmpolld/lvmpolld-core.c index c9a90ca16..bdf131758 100644 --- a/daemons/lvmpolld/lvmpolld-core.c +++ b/daemons/lvmpolld/lvmpolld-core.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 Red Hat, Inc. + * Copyright (C) 2015 Red Hat, Inc. * * This file is part of LVM2. * @@ -23,12 +23,13 @@ #include <wait.h> #include <sys/types.h> +#include "config-util.h" #include "configure.h" #include "daemon-server.h" #include "daemon-log.h" -#include "config-util.h" -#include "lvmpolld-protocol.h" +#include "lvmpolld-cmd-utils.h" #include "lvmpolld-data-utils.h" +#include "lvmpolld-protocol.h" #include "lvm-version.h" /* ??? */ #define LVMPOLLD_SOCKET DEFAULT_RUN_DIR "/lvmpolld.socket" @@ -42,7 +43,6 @@ */ /* extract this info from autoconf/automake files */ -#define LVPOLL_CMD "lvpoll" #define LVM2_BIN_PATH "/usr/sbin/lvm" /* predefined reason for response = "failed" case */ @@ -62,15 +62,10 @@ typedef struct lvmpolld_state { const char *log_config; const char *lvm_binary; - lvmpolld_store_t lvid_to_pdlv_abort; - lvmpolld_store_t lvid_to_pdlv_poll; + lvmpolld_store_t id_to_pdlv_abort; + lvmpolld_store_t id_to_pdlv_poll; } lvmpolld_state_t; -static const char *const const polling_ops[] = { [PVMOVE] = LVMPD_REQ_PVMOVE, - [CONVERT] = LVMPD_REQ_CONVERT, - [MERGE] = LVMPD_REQ_MERGE, - [MERGE_THIN] = LVMPD_REQ_MERGE_THIN }; - static void usage(const char *prog, FILE *file) { fprintf(file, "Usage:\n" @@ -94,8 +89,8 @@ static int init(struct daemon_state *s) if (!daemon_log_parse(ls->log, DAEMON_LOG_OUTLET_STDERR, ls->log_config, 1)) return 0; - pdst_init(&ls->lvid_to_pdlv_poll, "polling"); - pdst_init(&ls->lvid_to_pdlv_abort, "abort"); + pdst_init(&ls->id_to_pdlv_poll, "polling"); + pdst_init(&ls->id_to_pdlv_abort, "abort"); DEBUGLOG(ls, "%s: LVM_SYSTEM_DIR=%s", PD_LOG_PREFIX, getenv("LVM_SYSTEM_DIR") ?: "<not set>"); @@ -113,8 +108,8 @@ static int fini(struct daemon_state *s) { lvmpolld_state_t *ls = s->private; - pdst_destroy(&ls->lvid_to_pdlv_poll); - pdst_destroy(&ls->lvid_to_pdlv_abort); + pdst_destroy(&ls->id_to_pdlv_poll); + pdst_destroy(&ls->id_to_pdlv_abort); return 1; } @@ -139,14 +134,14 @@ static void update_active_state(lvmpolld_state_t *ls) if (!ls->idle) return; - pdst_lock(&ls->lvid_to_pdlv_poll); - pdst_lock(&ls->lvid_to_pdlv_abort); + pdst_lock(&ls->id_to_pdlv_poll); + pdst_lock(&ls->id_to_pdlv_abort); - ls->idle->is_idle = !ls->lvid_to_pdlv_poll.active_polling_count && - !ls->lvid_to_pdlv_abort.active_polling_count; + ls->idle->is_idle = !ls->id_to_pdlv_poll.active_polling_count && + !ls->id_to_pdlv_abort.active_polling_count; - pdst_unlock(&ls->lvid_to_pdlv_abort); - pdst_unlock(&ls->lvid_to_pdlv_poll); + pdst_unlock(&ls->id_to_pdlv_abort); + pdst_unlock(&ls->id_to_pdlv_poll); } /* make this configurable */ @@ -206,9 +201,6 @@ static int poll_for_output(lvmpolld_lv_t *pdlv, int outfd, int errfd) assert(read_single_line(&line, &lsize, fout)); /* may block indef. anyway */ INFO(pdlv->ls, "%s: PID %d: %s: '%s'", LVM2_LOG_PREFIX, pdlv->cmd_pid, "STDOUT", line); - - if (pdlv->parse_output_fn) - pdlv->parse_output_fn(pdlv, line); } else if (fds[0].revents) { if (fds[0].revents & POLLHUP) DEBUGLOG(pdlv->ls, "%s: %s", PD_LOG_PREFIX, "caught POLLHUP"); @@ -263,8 +255,6 @@ static int poll_for_output(lvmpolld_lv_t *pdlv, int outfd, int errfd) while (read_single_line(&line, &lsize, fout)) { assert(r > 0); INFO(pdlv->ls, "%s: PID %d: %s: %s", LVM2_LOG_PREFIX, pdlv->cmd_pid, "STDOUT", line); - if (pdlv->parse_output_fn) - pdlv->parse_output_fn(pdlv, line); } if (fds[1].fd >= 0) while (read_single_line(&line, &lsize, ferr)) { @@ -297,87 +287,24 @@ out: return err; } -#define MIN_SIZE 16 - -static int add_to_cmdargv(const char ***cmdargv, const char *str, int *index, int renameme) +static void debug_print(lvmpolld_state_t *ls, const char * const* ptr) { - const char **newargv = *cmdargv; - - if (*index && !(*index % renameme)) { - newargv = dm_realloc(*cmdargv, (*index / renameme + 1) * renameme * sizeof(char *)); - if (!newargv) - return 0; - *cmdargv = newargv; - } - - *(*cmdargv + (*index)++) = str; - - return 1; -} + const char * const* tmp = ptr; -static const char **cmdargv_ctr(lvmpolld_lv_t *pdlv, unsigned abort, unsigned handle_missing_pvs) -{ - int i = 0; - const char **cmd_argv = dm_malloc(MIN_SIZE * sizeof(char *)); + if (!tmp) + return; - if (!cmd_argv) { - ERROR(pdlv->ls, "%s: %s", PD_LOG_PREFIX, "construct_cmdargv: malloc failed"); - return NULL; + while (*tmp) { + DEBUGLOG(ls, "%s: %s", PD_LOG_PREFIX, *tmp); + tmp++; } - - /* path to lvm2 binary */ - if (!add_to_cmdargv(&cmd_argv, pdlv->ls->lvm_binary, &i, MIN_SIZE)) - goto err; - - /* cmd to execute */ - if (!add_to_cmdargv(&cmd_argv, LVPOLL_CMD, &i, MIN_SIZE)) - goto err; - - /* by default run under global filter */ - if (!add_to_cmdargv(&cmd_argv, "--config", &i, MIN_SIZE) || - !add_to_cmdargv(&cmd_argv, "devices { filter = [ \"a/.*/\" ] }", &i, MIN_SIZE)) - goto err; - - /* transfer internal polling interval */ - if (pdlv->sinterval && - (!add_to_cmdargv(&cmd_argv, "--interval", &i, MIN_SIZE) || - !add_to_cmdargv(&cmd_argv, pdlv->sinterval, &i, MIN_SIZE))) - goto err; - - /* pass abort param */ - if (abort && - !add_to_cmdargv(&cmd_argv, "--abort", &i, MIN_SIZE)) - goto err; - - /* pass handle-missing-pvs. used by mirror polling operation */ - if (handle_missing_pvs && - !add_to_cmdargv(&cmd_argv, "--handle-missing-pvs", &i, MIN_SIZE)) - goto err; - - /* one of: "convert", "pvmove", "merge", "merge_thin" */ - if (!add_to_cmdargv(&cmd_argv, "--poll-operation", &i, MIN_SIZE) || - !add_to_cmdargv(&cmd_argv, polling_ops[pdlv->type], &i, MIN_SIZE)) - goto err; - - /* vg/lv name */ - if (!add_to_cmdargv(&cmd_argv, pdlv->lvname, &i, MIN_SIZE)) - goto err; - - /* terminating NULL */ - if (!add_to_cmdargv(&cmd_argv, NULL, &i, MIN_SIZE)) - goto err; - - return cmd_argv; -err: - ERROR(pdlv->ls, "%s: %s", PD_LOG_PREFIX, "construct_cmdargv: realloc failed"); - dm_free(cmd_argv); - return NULL; } static void *fork_and_poll(void *args) { lvmpolld_store_t *pdst; pid_t r; + char buf[128]; int error = 1; lvmpolld_lv_t *pdlv = (lvmpolld_lv_t *) args; @@ -401,6 +328,14 @@ static void *fork_and_poll(void *args) if (fcntl(errpipe[1], F_SETFD, FD_CLOEXEC)) WARN(ls, "%s: %s", PD_LOG_PREFIX, "failed to set FD_CLOEXEC on write end of err pipe"); + DEBUGLOG(ls, "%s: %s", PD_LOG_PREFIX, "cmd line arguments:"); + debug_print(ls, pdlv->cmdargv); + DEBUGLOG(ls, "%s: %s", PD_LOG_PREFIX, "---end---"); + + DEBUGLOG(ls, "%s: %s", PD_LOG_PREFIX, "cmd environment variables:"); + debug_print(ls, pdlv->cmdenvp); + DEBUGLOG(ls, "%s: %s", PD_LOG_PREFIX, "---end---"); + r = fork(); if (!r) { /* child */ @@ -410,7 +345,12 @@ static void *fork_and_poll(void *args) (dup2(errpipe[1], STDERR_FILENO ) != STDERR_FILENO)) _exit(100); - execv(*(pdlv->cmdargv), (char *const *)pdlv->cmdargv); + execve(*(pdlv->cmdargv), (char *const *)pdlv->cmdargv, (char *const *)pdlv->cmdenvp); + + /* FIXME: This is illegal remove it (thread aware syscall) */ + strerror_r(errno, buf, sizeof(buf)); + + ERROR(ls, "%s: %s: %s", PD_LOG_PREFIX, "Failed to exec command", buf); _exit(101); } else { @@ -481,24 +421,56 @@ err: return NULL; } +static char *construct_id(const char *sysdir, const char *uuid) +{ + char *id; + int r; + size_t l; + + l = strlen(uuid) + (sysdir ? strlen(sysdir) : 0) + 1; + id = (char *) dm_malloc(l * sizeof(char)); + if (!id) + return NULL; + + r = sysdir ? dm_snprintf(id, l, "%s%s", sysdir, uuid) : + dm_snprintf(id, l, "%s", uuid); + + if (!r) { + dm_free(id); + id = NULL; + } + + return id; +} + static response progress_info(client_handle h, lvmpolld_state_t *ls, request req) { + char *id; lvmpolld_lv_t *pdlv; lvmpolld_store_t *pdst; lvmpolld_lv_state_t st; response r; const char *lvid = daemon_request_str(req, LVMPD_PARM_LVID, NULL); + const char *sysdir = daemon_request_str(req, LVMPD_PARM_SYSDIR, NULL); unsigned abort = daemon_request_int(req, LVMPD_PARM_ABORT, 0); if (!lvid) return reply_fail(REASON_MISSING_LVID); - pdst = abort ? &ls->lvid_to_pdlv_abort : &ls->lvid_to_pdlv_poll; + id = construct_id(sysdir, lvid); + if (!id) { + ERROR(ls, "%s: %s", PD_LOG_PREFIX, "failed to construct id"); + return reply_fail(REASON_INTERNAL_ERROR); + } + + DEBUGLOG(ls, "%s: %s: %s", PD_LOG_PREFIX, "ID", id); + + pdst = abort ? &ls->id_to_pdlv_abort : &ls->id_to_pdlv_poll; pdst_lock(pdst); /* store locked */ - pdlv = pdst_locked_lookup(pdst, lvid); + pdlv = pdst_locked_lookup(pdst, id); if (pdlv) { /* * with store lock held, I'm the only reader accessing the pdlv @@ -509,7 +481,7 @@ static response progress_info(client_handle h, lvmpolld_state_t *ls, request req INFO(ls, "%s: %s %s", PD_LOG_PREFIX, "Polling finished. Removing related data structure for LV", lvid); - pdst_locked_remove(pdst, lvid); + pdst_locked_remove(pdst, id); pdlv_destroy(pdlv); } } @@ -518,6 +490,8 @@ static response progress_info(client_handle h, lvmpolld_state_t *ls, request req pdst_unlock(pdst); /* store unlocked */ + dm_free(id); + if (pdlv) { if (st.internal_error) return reply_fail(REASON_POLLING_FAILED); @@ -539,30 +513,39 @@ static response progress_info(client_handle h, lvmpolld_state_t *ls, request req static lvmpolld_lv_t *construct_pdlv(request req, lvmpolld_state_t *ls, lvmpolld_store_t *pdst, - const char *interval, const char *lvid, - const char *lvname, enum poll_type type, + const char *interval, const char *id, + const char *vgname, const char *lvname, + const char *sysdir, enum poll_type type, unsigned abort, unsigned uinterval) { - const char **cmdargv; + const char **cmdargv, **cmdenvp; lvmpolld_lv_t *pdlv; unsigned handle_missing_pvs = daemon_request_int(req, LVMPD_PARM_HANDLE_MISSING_PVS, 0); - pdlv = pdlv_create(ls, lvid, lvname, type, interval, 2 * uinterval, - pdst, NULL); + pdlv = pdlv_create(ls, id, vgname, lvname, sysdir, type, + interval, 2 * uinterval, pdst); if (!pdlv) { ERROR(ls, "%s: %s", PD_LOG_PREFIX, "Failed to create pdlv"); return NULL; } - cmdargv = cmdargv_ctr(pdlv, abort, handle_missing_pvs); + cmdargv = cmdargv_ctr(pdlv, pdlv->ls->lvm_binary, abort, handle_missing_pvs); if (!cmdargv) { pdlv_destroy(pdlv); ERROR(ls, "%s: %s", PD_LOG_PREFIX, "failed to construct cmd arguments for lvpoll command"); return NULL; } + cmdenvp = cmdenvp_ctr(pdlv); + if (!cmdenvp) { + pdlv_destroy(pdlv); + ERROR(ls, "%s: %s", PD_LOG_PREFIX, "failed to construct cmd environment for lvpoll command"); + return NULL; + } + pdlv->cmdargv = cmdargv; + pdlv->cmdenvp = cmdenvp; return pdlv; } @@ -584,16 +567,16 @@ static int spawn_detached_thread(lvmpolld_lv_t *pdlv) static response poll_init(client_handle h, lvmpolld_state_t *ls, request req, enum poll_type type) { - char *full_lvname; + char *id; lvmpolld_lv_t *pdlv; lvmpolld_store_t *pdst; - size_t len; unsigned uinterval; const char *interval = daemon_request_str(req, LVMPD_PARM_INTERVAL, NULL); const char *lvid = daemon_request_str(req, LVMPD_PARM_LVID, NULL); const char *lvname = daemon_request_str(req, LVMPD_PARM_LVNAME, NULL); const char *vgname = daemon_request_str(req, LVMPD_PARM_VGNAME, NULL); + const char *sysdir = daemon_request_str(req, LVMPD_PARM_SYSDIR, NULL); unsigned abort = daemon_request_int(req, LVMPD_PARM_ABORT, 0); assert(type < POLL_TYPE_MAX); @@ -613,19 +596,19 @@ static response poll_init(client_handle h, lvmpolld_state_t *ls, request req, en if (!vgname) return reply_fail(REASON_MISSING_VGNAME); - len = strlen(lvname) + strlen(vgname) + 2; /* vg/lv and \0 */ - full_lvname = dm_malloc(len); - if (!full_lvname || dm_snprintf(full_lvname, len, "%s/%s", vgname, lvname) < 0) { - ERROR(ls, "%s: %s", PD_LOG_PREFIX, "Failed to clone vg/lv name"); - dm_free(full_lvname); + id = construct_id(sysdir, lvid); + if (!id) { + ERROR(ls, "%s: %s", PD_LOG_PREFIX, "failed to construct id"); return reply_fail(REASON_INTERNAL_ERROR); } - pdst = abort ? &ls->lvid_to_pdlv_abort : &ls->lvid_to_pdlv_poll; + DEBUGLOG(ls, "%s: %s=%s", PD_LOG_PREFIX, "ID", id); + + pdst = abort ? &ls->id_to_pdlv_abort : &ls->id_to_pdlv_poll; pdst_lock(pdst); - pdlv = pdst_locked_lookup(pdst, lvid); + pdlv = pdst_locked_lookup(pdst, id); if (pdlv && pdlv_get_polling_finished(pdlv)) { WARN(ls, "%s: %s %s", PD_LOG_PREFIX, "Force removal of uncollected info for LV", lvid); @@ -634,7 +617,7 @@ static response poll_init(client_handle h, lvmpolld_state_t *ls, request req, en * otherwise it would have to refuse request for new polling * lv with same id. */ - pdst_locked_remove(pdst, lvid); + pdst_locked_remove(pdst, id); pdlv_destroy(pdlv); pdlv = NULL; } @@ -642,29 +625,29 @@ static response poll_init(client_handle h, lvmpolld_state_t *ls, request req, en if (pdlv) { if (!pdlv_is_type(pdlv, type)) { pdst_unlock(pdst); - dm_free(full_lvname); + dm_free(id); return reply_fail(REASON_DIFFERENT_OPERATION_IN_PROGRESS); } } else { - pdlv = construct_pdlv(req, ls, pdst, interval, lvid, full_lvname, - type, abort, uinterval); + pdlv = construct_pdlv(req, ls, pdst, interval, id, vgname, + lvname, sysdir, type, abort, uinterval); if (!pdlv) { pdst_unlock(pdst); - dm_free(full_lvname); + dm_free(id); return reply_fail(REASON_INTERNAL_ERROR); } - if (!pdst_locked_insert(pdst, lvid, pdlv)) { + if (!pdst_locked_insert(pdst, id, pdlv)) { pdlv_destroy(pdlv); pdst_unlock(pdst); - dm_free(full_lvname); + dm_free(id); return reply_fail(REASON_INTERNAL_ERROR); } if (!spawn_detached_thread(pdlv)) { ERROR(ls, "%s: %s", PD_LOG_PREFIX, "failed to spawn detached thread"); - pdst_locked_remove(pdst, lvid); + pdst_locked_remove(pdst, id); pdlv_destroy(pdlv); pdst_unlock(pdst); - dm_free(full_lvname); + dm_free(id); return reply_fail(REASON_INTERNAL_ERROR); } @@ -675,12 +658,11 @@ static response poll_init(client_handle h, lvmpolld_state_t *ls, request req, en pdst_unlock(pdst); - dm_free(full_lvname); + dm_free(id); return daemon_reply_simple(LVMPD_RESP_OK, NULL); } - static response handler(struct daemon_state s, client_handle h, request r) { lvmpolld_state_t *ls = s.private; diff --git a/daemons/lvmpolld/lvmpolld-data-utils.c b/daemons/lvmpolld/lvmpolld-data-utils.c index faf251aca..4719e5d88 100644 --- a/daemons/lvmpolld/lvmpolld-data-utils.c +++ b/daemons/lvmpolld/lvmpolld-data-utils.c @@ -15,30 +15,77 @@ #include "libdevmapper.h" #include "lvmpolld-data-utils.h" -lvmpolld_lv_t *pdlv_create(lvmpolld_state_t *ls, const char *lvid, - const char *lvname, enum poll_type type, +static char *_construct_full_lvname(const char *vgname, const char *lvname) +{ + char *name; + size_t l; + + l = strlen(vgname) + strlen(lvname) + 2; /* vg/lv and \0 */ + name = (char *) dm_malloc(l * sizeof(char)); + if (!name) + return NULL; + + if (dm_snprintf(name, l, "%s/%s", vgname, lvname) < 0) { + dm_free(name); + name = NULL; + } + + return name; +} + +static char *_construct_lvm_system_dir_env(const char *sysdir) +{ + /* + * Store either "LVM_SYSTEM_DIR=/path/to..." + * - or - + * just single char to store NULL byte + */ + size_t l = sysdir ? strlen(sysdir) + 16 : 1; + char *env = (char *) dm_malloc(l * sizeof(char)); + + if (!env) + return NULL; + + *env = '\0'; + + if (sysdir && dm_snprintf(env, l, "LVM_SYSTEM_DIR=%s", sysdir) < 0) { + dm_free(env); + env = NULL; + } + + return env; +} + +static inline const char *_get_lvid(const char *lvmpolld_id, const char *sysdir) +{ + return lvmpolld_id ? (lvmpolld_id + (sysdir ? strlen(sysdir) : 0)) : NULL; +} + +lvmpolld_lv_t *pdlv_create(lvmpolld_state_t *ls, const char *id, + const char *vgname, const char *lvname, + const char *sysdir, enum poll_type type, const char *sinterval, unsigned pdtimeout, - lvmpolld_store_t *pdst, - lvmpolld_parse_output_fn_t parse_fn) + lvmpolld_store_t *pdst) { + char *lvmpolld_id = dm_strdup(id), /* copy */ + *full_lvname = _construct_full_lvname(vgname, lvname), /* copy */ + *lvm_system_dir_env = _construct_lvm_system_dir_env(sysdir); /* copy */ + lvmpolld_lv_t tmp = { .ls = ls, .type = type, - .lvid = dm_strdup(lvid), - .lvname = dm_strdup(lvname), - .sinterval = dm_strdup(sinterval), + .lvmpolld_id = lvmpolld_id, + .lvid = _get_lvid(lvmpolld_id, sysdir), + .lvname = full_lvname, + .lvm_system_dir_env = lvm_system_dir_env, + .sinterval = dm_strdup(sinterval), /* copy */ .pdtimeout = pdtimeout ?: PDTIMEOUT_DEF, .cmd_state = { .retcode = -1, .signal = 0 }, - .pdst = pdst, - .parse_output_fn = parse_fn + .pdst = pdst }, *pdlv = (lvmpolld_lv_t *) dm_malloc(sizeof(lvmpolld_lv_t)); - if (!pdlv || !tmp.lvid || !tmp.lvname || !tmp.sinterval) { - dm_free((void *)tmp.lvid); - dm_free((void *)tmp.lvname); - dm_free((void *)tmp.sinterval); - return NULL; - } + if (!pdlv || !tmp.lvid || !tmp.lvname || !tmp.lvm_system_dir_env || !tmp.sinterval) + goto err; memcpy(pdlv, &tmp, sizeof(*pdlv)); @@ -48,9 +95,10 @@ lvmpolld_lv_t *pdlv_create(lvmpolld_state_t *ls, const char *lvid, return pdlv; err: - dm_free((void *)pdlv->sinterval); - dm_free((void *)pdlv->lvid); - dm_free((void *)pdlv->lvname); + dm_free((void *)lvmpolld_id); + dm_free((void *)full_lvname); + dm_free((void *)lvm_system_dir_env); + dm_free((void *)tmp.sinterval); dm_free((void *)pdlv); return NULL; @@ -58,10 +106,12 @@ err: void pdlv_destroy(lvmpolld_lv_t *pdlv) { - dm_free((void *)pdlv->lvid); + dm_free((void *)pdlv->lvmpolld_id); dm_free((void *)pdlv->lvname); dm_free((void *)pdlv->sinterval); + dm_free((void *)pdlv->lvm_system_dir_env); dm_free((void *)pdlv->cmdargv); + dm_free((void *)pdlv->cmdenvp); pthread_mutex_destroy(&pdlv->lock); diff --git a/daemons/lvmpolld/lvmpolld-data-utils.h b/daemons/lvmpolld/lvmpolld-data-utils.h index fc4261c67..7fe0d1927 100644 --- a/daemons/lvmpolld/lvmpolld-data-utils.h +++ b/daemons/lvmpolld/lvmpolld-data-utils.h @@ -59,12 +59,14 @@ typedef struct lvmpolld_lv { struct lvmpolld_state *const ls; const enum poll_type type; const char *const lvid; + const char *const lvmpolld_id; const char *const lvname; /* full vg/lv name */ const unsigned pdtimeout; /* in seconds */ const char *const sinterval; + const char *const lvm_system_dir_env; lvmpolld_store_t *const pdst; - lvmpolld_parse_output_fn_t parse_output_fn; const char *const *cmdargv; + const char *const *cmdenvp; /* only used by write */ pid_t cmd_pid; @@ -81,11 +83,11 @@ typedef struct lvmpolld_lv { /* LVMPOLLD_LV_T section */ /* only call with appropriate lvmpolld_store_t lock held */ -lvmpolld_lv_t *pdlv_create(struct lvmpolld_state *ls, const char *lvid, - const char *lvname, const enum poll_type type, +lvmpolld_lv_t *pdlv_create(lvmpolld_state_t *ls, const char *id, + const char *vgname, const char *lvname, + const char *sysdir, enum poll_type type, const char *sinterval, unsigned pdtimeout, - lvmpolld_store_t *pdst, - lvmpolld_parse_output_fn_t parse_fn); + lvmpolld_store_t *pdst); /* only call with appropriate lvmpolld_store_t lock held */ void pdlv_destroy(lvmpolld_lv_t *pdlv); diff --git a/daemons/lvmpolld/lvmpolld-protocol.h b/daemons/lvmpolld/lvmpolld-protocol.h index a215f14f8..e1e7080a7 100644 --- a/daemons/lvmpolld/lvmpolld-protocol.h +++ b/daemons/lvmpolld/lvmpolld-protocol.h @@ -27,12 +27,11 @@ #define LVMPD_REQ_PVMOVE PVMOVE_POLL #define LVMPD_PARM_ABORT "abort" -#define LVMPD_PARM_BACKGROUND "background" -#define LVMPD_PARM_DATA "data" /* progress data */ #define LVMPD_PARM_HANDLE_MISSING_PVS "handle_missing_pvs" #define LVMPD_PARM_INTERVAL "interval" #define LVMPD_PARM_LVID "lvid" #define LVMPD_PARM_LVNAME "lvname" +#define LVMPD_PARM_SYSDIR "sysdir" #define LVMPD_PARM_VALUE "value" /* either retcode or signal value */ #define LVMPD_PARM_VGNAME "vgname" |