summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOndrej Kozina <okozina@redhat.com>2015-02-27 14:08:53 +0100
committerOndrej Kozina <okozina@redhat.com>2015-04-01 11:01:22 +0200
commit84092da2cf2847f1600a7a64ab2a83fb5b0ef586 (patch)
tree2a9e629196e54022953e1df36df1d9a98b95281d
parent3f4ce8e68d9f0a24d598d73f77b669e35bedfd73 (diff)
downloadlvm2-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.in2
-rw-r--r--daemons/lvmpolld/lvmpolld-cmd-utils.c139
-rw-r--r--daemons/lvmpolld/lvmpolld-cmd-utils.h25
-rw-r--r--daemons/lvmpolld/lvmpolld-core.c236
-rw-r--r--daemons/lvmpolld/lvmpolld-data-utils.c88
-rw-r--r--daemons/lvmpolld/lvmpolld-data-utils.h12
-rw-r--r--daemons/lvmpolld/lvmpolld-protocol.h3
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"