master - lvmetad: Clear metadata/PV cache before a token-triggered rescan.
by Petr Rockai
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=d2d66634282459...
Commit: d2d66634282459438210f1f9ba7e2e4c910e13ba
Parent: e7d3553906f15b9117d0152844f69de33564ab46
Author: Petr Rockai <prockai(a)redhat.com>
AuthorDate: Wed Sep 19 23:18:28 2012 +0200
Committer: Petr Rockai <prockai(a)redhat.com>
CommitterDate: Wed Sep 26 17:26:23 2012 +0200
lvmetad: Clear metadata/PV cache before a token-triggered rescan.
---
daemons/lvmetad/lvmetad-core.c | 82 ++++++++++++++++++++++++++++-----------
lib/cache/lvmetad.c | 6 +++
2 files changed, 65 insertions(+), 23 deletions(-)
diff --git a/daemons/lvmetad/lvmetad-core.c b/daemons/lvmetad/lvmetad-core.c
index 09ba20d..c6cc3d9 100644
--- a/daemons/lvmetad/lvmetad-core.c
+++ b/daemons/lvmetad/lvmetad-core.c
@@ -45,6 +45,38 @@ typedef struct {
pthread_mutex_t token_lock;
} lvmetad_state;
+static void destroy_metadata_hashes(lvmetad_state *s)
+{
+ struct dm_hash_node *n = NULL;
+
+ while (n) {
+ dm_config_destroy(dm_hash_get_data(s->vgid_to_metadata, n));
+ n = dm_hash_get_next(s->vgid_to_metadata, n);
+ }
+
+ n = dm_hash_get_first(s->pvid_to_pvmeta);
+ while (n) {
+ dm_config_destroy(dm_hash_get_data(s->pvid_to_pvmeta, n));
+ n = dm_hash_get_next(s->pvid_to_pvmeta, n);
+ }
+ dm_hash_destroy(s->pvid_to_pvmeta);
+ dm_hash_destroy(s->vgid_to_metadata);
+ dm_hash_destroy(s->vgid_to_vgname);
+ dm_hash_destroy(s->vgname_to_vgid);
+ dm_hash_destroy(s->device_to_pvid);
+ dm_hash_destroy(s->pvid_to_vgid);
+}
+
+static void create_metadata_hashes(lvmetad_state *s)
+{
+ s->pvid_to_pvmeta = dm_hash_create(32);
+ s->device_to_pvid = dm_hash_create(32);
+ s->vgid_to_metadata = dm_hash_create(32);
+ s->vgid_to_vgname = dm_hash_create(32);
+ s->pvid_to_vgid = dm_hash_create(32);
+ s->vgname_to_vgid = dm_hash_create(32);
+}
+
static void lock_pvid_to_pvmeta(lvmetad_state *s) {
pthread_mutex_lock(&s->lock.pvid_to_pvmeta); }
static void unlock_pvid_to_pvmeta(lvmetad_state *s) {
@@ -724,6 +756,24 @@ static response pv_gone(lvmetad_state *s, request r)
return reply_unknown("PVID does not exist");
}
+static response pv_clear_all(lvmetad_state *s, request r)
+{
+ DEBUG(s, "pv_clear_all");
+
+ lock_pvid_to_pvmeta(s);
+ lock_vgid_to_metadata(s);
+ lock_pvid_to_vgid(s);
+
+ destroy_metadata_hashes(s);
+ create_metadata_hashes(s);
+
+ unlock_pvid_to_vgid(s);
+ unlock_vgid_to_metadata(s);
+ unlock_pvid_to_pvmeta(s);
+
+ return daemon_reply_simple("OK", NULL);
+}
+
static response pv_found(lvmetad_state *s, request r)
{
struct dm_config_node *metadata = dm_config_find_node(r.cft->root, "metadata");
@@ -877,6 +927,9 @@ static response handler(daemon_state s, client_handle h, request r)
if (!strcmp(rq, "pv_gone"))
return pv_gone(state, r);
+ if (!strcmp(rq, "pv_clear_all"))
+ return pv_clear_all(state, r);
+
if (!strcmp(rq, "pv_lookup"))
return pv_lookup(state, r);
@@ -905,20 +958,16 @@ static int init(daemon_state *s)
lvmetad_state *ls = s->private;
ls->log = s->log;
- ls->pvid_to_pvmeta = dm_hash_create(32);
- ls->device_to_pvid = dm_hash_create(32);
- ls->vgid_to_metadata = dm_hash_create(32);
- ls->vgid_to_vgname = dm_hash_create(32);
- ls->pvid_to_vgid = dm_hash_create(32);
- ls->vgname_to_vgid = dm_hash_create(32);
- ls->lock.vg = dm_hash_create(32);
- ls->token[0] = 0;
pthread_mutexattr_init(&rec);
pthread_mutexattr_settype(&rec, PTHREAD_MUTEX_RECURSIVE_NP);
pthread_mutex_init(&ls->lock.pvid_to_pvmeta, &rec);
pthread_mutex_init(&ls->lock.vgid_to_metadata, &rec);
pthread_mutex_init(&ls->lock.pvid_to_vgid, NULL);
pthread_mutex_init(&ls->token_lock, NULL);
+ create_metadata_hashes(ls);
+
+ ls->lock.vg = dm_hash_create(32);
+ ls->token[0] = 0;
/* Set up stderr logging depending on the -d option. */
daemon_log_parse(ls->log, DAEMON_LOG_OUTLET_STDERR, ls->debug_config, 1);
@@ -939,17 +988,10 @@ static int fini(daemon_state *s)
struct dm_hash_node *n = dm_hash_get_first(ls->vgid_to_metadata);
DEBUG(s, "fini");
- while (n) {
- dm_config_destroy(dm_hash_get_data(ls->vgid_to_metadata, n));
- n = dm_hash_get_next(ls->vgid_to_metadata, n);
- }
- n = dm_hash_get_first(ls->pvid_to_pvmeta);
- while (n) {
- dm_config_destroy(dm_hash_get_data(ls->pvid_to_pvmeta, n));
- n = dm_hash_get_next(ls->pvid_to_pvmeta, n);
- }
+ destroy_metadata_hashes(ls);
+ /* Destroy the lock hashes now. */
n = dm_hash_get_first(ls->lock.vg);
while (n) {
pthread_mutex_destroy(dm_hash_get_data(ls->lock.vg, n));
@@ -958,12 +1000,6 @@ static int fini(daemon_state *s)
}
dm_hash_destroy(ls->lock.vg);
- dm_hash_destroy(ls->pvid_to_pvmeta);
- dm_hash_destroy(ls->device_to_pvid);
- dm_hash_destroy(ls->vgid_to_metadata);
- dm_hash_destroy(ls->vgid_to_vgname);
- dm_hash_destroy(ls->vgname_to_vgid);
- dm_hash_destroy(ls->pvid_to_vgid);
return 1;
}
diff --git a/lib/cache/lvmetad.c b/lib/cache/lvmetad.c
index 237fec6..a7e3cd3 100644
--- a/lib/cache/lvmetad.c
+++ b/lib/cache/lvmetad.c
@@ -851,6 +851,7 @@ int lvmetad_pvscan_all_devs(struct cmd_context *cmd, activation_handler handler)
{
struct dev_iter *iter;
struct device *dev;
+ daemon_reply reply;
int r = 1;
if (!(iter = dev_iter_create(cmd->lvmetad_filter, 1))) {
@@ -858,6 +859,11 @@ int lvmetad_pvscan_all_devs(struct cmd_context *cmd, activation_handler handler)
return 0;
}
+ reply = _lvmetad_send("pv_clear_all", NULL);
+ if (!_lvmetad_handle_reply(reply, "clear status on all PVs", "", NULL))
+ r = 0;
+ daemon_reply_destroy(reply);
+
while ((dev = dev_iter_get(iter))) {
if (!lvmetad_pvscan_single(cmd, dev, handler)) {
r = 0;
11 years, 6 months
master - lvmetad: Make vgscan --cache an alias to pvscan --cache.
by Petr Rockai
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=e7d3553906f15b...
Commit: e7d3553906f15b9117d0152844f69de33564ab46
Parent: 2d7a8b453196893186ae3eb61dc31c1df8b1cf6f
Author: Petr Rockai <prockai(a)redhat.com>
AuthorDate: Mon Sep 10 16:35:43 2012 +0200
Committer: Petr Rockai <prockai(a)redhat.com>
CommitterDate: Wed Sep 26 17:26:23 2012 +0200
lvmetad: Make vgscan --cache an alias to pvscan --cache.
---
tools/vgscan.c | 16 ++++------------
1 files changed, 4 insertions(+), 12 deletions(-)
diff --git a/tools/vgscan.c b/tools/vgscan.c
index 8deafb6..99124ef 100644
--- a/tools/vgscan.c
+++ b/tools/vgscan.c
@@ -15,8 +15,6 @@
#include "tools.h"
-static int _lvmetad;
-
static int vgscan_single(struct cmd_context *cmd, const char *vg_name,
struct volume_group *vg,
void *handle __attribute__((unused)))
@@ -27,12 +25,6 @@ static int vgscan_single(struct cmd_context *cmd, const char *vg_name,
check_current_backup(vg);
- /* keep lvmetad up to date, restore the "active" state temporarily */
- lvmetad_set_active(_lvmetad);
- if (!lvmetad_vg_update(vg))
- stack;
- lvmetad_set_active(0);
-
return ECMD_PROCESSED;
}
@@ -54,10 +46,11 @@ int vgscan(struct cmd_context *cmd, int argc, char **argv)
cmd->filter->wipe(cmd->filter);
lvmcache_destroy(cmd, 1);
- _lvmetad = lvmetad_active();
if (arg_count(cmd, cache_ARG)) {
- if (_lvmetad)
- lvmetad_set_active(0); /* do not rely on lvmetad info */
+ if (lvmetad_active()) {
+ if (!lvmetad_pvscan_all_devs(cmd, NULL))
+ return ECMD_FAILED;
+ }
else {
log_error("Cannot proceed since lvmetad is not active.");
unlock_vg(cmd, VG_GLOBAL);
@@ -76,7 +69,6 @@ int vgscan(struct cmd_context *cmd, int argc, char **argv)
maxret = ret;
}
- lvmetad_set_active(_lvmetad); /* restore */
unlock_vg(cmd, VG_GLOBAL);
return maxret;
}
11 years, 6 months
master - TEST: Add LVM_VALGRIND_LVMETAD to testing options.
by Petr Rockai
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=2d7a8b45319689...
Commit: 2d7a8b453196893186ae3eb61dc31c1df8b1cf6f
Parent: 0a87fed794f2886047298bbc7b21919e9fc04951
Author: Petr Rockai <prockai(a)redhat.com>
AuthorDate: Mon Sep 10 07:42:39 2012 +0200
Committer: Petr Rockai <prockai(a)redhat.com>
CommitterDate: Wed Sep 26 17:26:23 2012 +0200
TEST: Add LVM_VALGRIND_LVMETAD to testing options.
---
test/lib/aux.sh | 5 ++++-
1 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/test/lib/aux.sh b/test/lib/aux.sh
index d6a2008..d1d5e10 100644
--- a/test/lib/aux.sh
+++ b/test/lib/aux.sh
@@ -73,8 +73,11 @@ prepare_lvmetad() {
lvmconf "global/use_lvmetad = 1"
lvmconf "devices/md_component_detection = 0"
+ local run_valgrind=
+ test -z "$LVM_VALGRIND_LVMETAD" || run_valgrind="run_valgrind"
+
echo "preparing lvmetad..."
- lvmetad -f "$@" -s "$TESTDIR/lvmetad.socket" -d wire,debug &
+ $run_valgrind lvmetad -f "$@" -s "$TESTDIR/lvmetad.socket" -d wire,debug &
echo $! > LOCAL_LVMETAD
sleep .3
11 years, 6 months
master - Makefiles: Build libdaemonclient unconditionally.
by Petr Rockai
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=0a87fed794f288...
Commit: 0a87fed794f2886047298bbc7b21919e9fc04951
Parent: ca0c8673b2064ceb840ee7f4cb5804b33e55f3c7
Author: Petr Rockai <prockai(a)redhat.com>
AuthorDate: Mon Sep 10 07:40:00 2012 +0200
Committer: Petr Rockai <prockai(a)redhat.com>
CommitterDate: Wed Sep 26 17:26:23 2012 +0200
Makefiles: Build libdaemonclient unconditionally.
---
Makefile.in | 6 +-----
libdaemon/Makefile.in | 4 +++-
make.tmpl.in | 8 +++-----
3 files changed, 7 insertions(+), 11 deletions(-)
diff --git a/Makefile.in b/Makefile.in
index 4316190..6b153d3 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -26,16 +26,12 @@ ifeq ("@INTL@", "yes")
SUBDIRS += po
endif
-SUBDIRS += lib tools daemons libdm
+SUBDIRS += lib tools daemons libdm libdaemon
ifeq ("@APPLIB@", "yes")
SUBDIRS += liblvm
endif
-ifeq ("@BUILD_LVMETAD@", "yes")
- SUBDIRS += libdaemon
-endif
-
SUBDIRS += scripts
# FIXME Should use intermediate Makefiles here!
diff --git a/libdaemon/Makefile.in b/libdaemon/Makefile.in
index fbe5a08..dbe6516 100644
--- a/libdaemon/Makefile.in
+++ b/libdaemon/Makefile.in
@@ -17,8 +17,10 @@ top_builddir = @top_builddir@
.PHONY: client server
+SUBDIRS += client
+
ifeq ("@BUILD_LVMETAD@", "yes")
- SUBDIRS += client server
+ SUBDIRS += server
server: client
endif
diff --git a/make.tmpl.in b/make.tmpl.in
index b8b127f..21fd415 100644
--- a/make.tmpl.in
+++ b/make.tmpl.in
@@ -144,11 +144,9 @@ endif
LDFLAGS += -L$(top_builddir)/libdm -L$(top_builddir)/lib
CLDFLAGS += -L$(top_builddir)/libdm -L$(top_builddir)/lib
-ifeq ("@BUILD_LVMETAD@", "yes")
- DAEMON_LIBS = -ldaemonclient
- LDFLAGS += -L$(top_builddir)/libdaemon/client
- CLDFLAGS += -L$(top_builddir)/libdaemon/client
-endif
+DAEMON_LIBS = -ldaemonclient
+LDFLAGS += -L$(top_builddir)/libdaemon/client
+CLDFLAGS += -L$(top_builddir)/libdaemon/client
ifeq ("@DMEVENTD@", "yes")
LDFLAGS += -L$(top_builddir)/daemons/dmeventd
11 years, 6 months
master - lib/cache/lvmetad: s/pvscan_lvmetad/lvmetad_pvscan/ in the API
by Petr Rockai
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=ca0c8673b2064c...
Commit: ca0c8673b2064ceb840ee7f4cb5804b33e55f3c7
Parent: c9f56d639b6c6ddfae7749c64eba64a776ecc7d9
Author: Petr Rockai <prockai(a)redhat.com>
AuthorDate: Sun Sep 9 22:05:59 2012 +0200
Committer: Petr Rockai <prockai(a)redhat.com>
CommitterDate: Wed Sep 26 17:26:23 2012 +0200
lib/cache/lvmetad: s/pvscan_lvmetad/lvmetad_pvscan/ in the API
---
lib/cache/lvmetad.c | 18 +++++++++---------
lib/cache/lvmetad.h | 8 ++++----
tools/pvscan.c | 6 +++---
3 files changed, 16 insertions(+), 16 deletions(-)
diff --git a/lib/cache/lvmetad.c b/lib/cache/lvmetad.c
index 1e185da..237fec6 100644
--- a/lib/cache/lvmetad.c
+++ b/lib/cache/lvmetad.c
@@ -123,7 +123,7 @@ retry:
_lvmetad_token = (char *) "update in progress";
if (!_token_update()) goto out;
- if (pvscan_lvmetad_all_devs(_lvmetad_cmd, NULL)) {
+ if (lvmetad_pvscan_all_devs(_lvmetad_cmd, NULL)) {
_lvmetad_token = future_token;
if (!_token_update()) goto out;
}
@@ -773,14 +773,14 @@ int lvmetad_pv_gone_by_dev(struct device *dev, activation_handler handler)
* The following code implements pvscan --cache.
*/
-struct _pvscan_lvmetad_baton {
+struct _lvmetad_pvscan_baton {
struct volume_group *vg;
struct format_instance *fid;
};
-static int _pvscan_lvmetad_single(struct metadata_area *mda, void *baton)
+static int _lvmetad_pvscan_single(struct metadata_area *mda, void *baton)
{
- struct _pvscan_lvmetad_baton *b = baton;
+ struct _lvmetad_pvscan_baton *b = baton;
struct volume_group *this = mda->ops->vg_read(b->fid, "", mda, 1);
/* FIXME Also ensure contents match etc. */
@@ -792,12 +792,12 @@ static int _pvscan_lvmetad_single(struct metadata_area *mda, void *baton)
return 1;
}
-int pvscan_lvmetad_single(struct cmd_context *cmd, struct device *dev,
+int lvmetad_pvscan_single(struct cmd_context *cmd, struct device *dev,
activation_handler handler)
{
struct label *label;
struct lvmcache_info *info;
- struct _pvscan_lvmetad_baton baton;
+ struct _lvmetad_pvscan_baton baton;
/* Create a dummy instance. */
struct format_instance_ctx fic = { .type = 0 };
@@ -822,7 +822,7 @@ int pvscan_lvmetad_single(struct cmd_context *cmd, struct device *dev,
if (!baton.fid)
goto_bad;
- lvmcache_foreach_mda(info, _pvscan_lvmetad_single, &baton);
+ lvmcache_foreach_mda(info, _lvmetad_pvscan_single, &baton);
if (!baton.vg)
lvmcache_fmt(info)->ops->destroy_instance(baton.fid);
@@ -847,7 +847,7 @@ bad:
return 0;
}
-int pvscan_lvmetad_all_devs(struct cmd_context *cmd, activation_handler handler)
+int lvmetad_pvscan_all_devs(struct cmd_context *cmd, activation_handler handler)
{
struct dev_iter *iter;
struct device *dev;
@@ -859,7 +859,7 @@ int pvscan_lvmetad_all_devs(struct cmd_context *cmd, activation_handler handler)
}
while ((dev = dev_iter_get(iter))) {
- if (!pvscan_lvmetad_single(cmd, dev, handler)) {
+ if (!lvmetad_pvscan_single(cmd, dev, handler)) {
r = 0;
break;
}
diff --git a/lib/cache/lvmetad.h b/lib/cache/lvmetad.h
index cb85929..60110a0 100644
--- a/lib/cache/lvmetad.h
+++ b/lib/cache/lvmetad.h
@@ -125,10 +125,10 @@ struct volume_group *lvmetad_vg_lookup(struct cmd_context *cmd,
/*
* Scan a single device and update lvmetad with the result(s).
*/
-int pvscan_lvmetad_single(struct cmd_context *cmd, struct device *dev,
+int lvmetad_pvscan_single(struct cmd_context *cmd, struct device *dev,
activation_handler handler);
-int pvscan_lvmetad_all_devs(struct cmd_context *cmd, activation_handler handler);
+int lvmetad_pvscan_all_devs(struct cmd_context *cmd, activation_handler handler);
# else /* LVMETAD_SUPPORT */
@@ -148,8 +148,8 @@ int pvscan_lvmetad_all_devs(struct cmd_context *cmd, activation_handler handler)
# define lvmetad_pv_lookup_by_dev(cmd, dev, found) (0)
# define lvmetad_vg_list_to_lvmcache(cmd) (1)
# define lvmetad_vg_lookup(cmd, vgname, vgid) (NULL)
-# define pvscan_lvmetad_single(cmd, dev, handler) (0)
-# define pvscan_lvmetad_all_devs(cmd, handler) (0)
+# define lvmetad_pvscan_single(cmd, dev, handler) (0)
+# define lvmetad_pvscan_all_devs(cmd, handler) (0)
# endif /* LVMETAD_SUPPORT */
diff --git a/tools/pvscan.c b/tools/pvscan.c
index 239ce97..3d5ddef 100644
--- a/tools/pvscan.c
+++ b/tools/pvscan.c
@@ -142,7 +142,7 @@ static int _pvscan_lvmetad(struct cmd_context *cmd, int argc, char **argv)
/* Scan everything? */
if (!argc && !devno_args) {
- if (!pvscan_lvmetad_all_devs(cmd, handler))
+ if (!lvmetad_pvscan_all_devs(cmd, handler))
ret = ECMD_FAILED;
goto out;
}
@@ -159,7 +159,7 @@ static int _pvscan_lvmetad(struct cmd_context *cmd, int argc, char **argv)
continue;
}
- if (!pvscan_lvmetad_single(cmd, dev, handler)) {
+ if (!lvmetad_pvscan_single(cmd, dev, handler)) {
ret = ECMD_FAILED;
break;
}
@@ -198,7 +198,7 @@ static int _pvscan_lvmetad(struct cmd_context *cmd, int argc, char **argv)
continue;
}
- if (!pvscan_lvmetad_single(cmd, dev, handler)) {
+ if (!lvmetad_pvscan_single(cmd, dev, handler)) {
ret = ECMD_FAILED;
break;
}
11 years, 6 months
master - lvmetad: Use "%" PRId64 in place of "%d" for extra clarity.
by Petr Rockai
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=c9f56d639b6c6d...
Commit: c9f56d639b6c6ddfae7749c64eba64a776ecc7d9
Parent: c7b17836ea139ba7448f5a5c1d2fbe93676baa36
Author: Petr Rockai <prockai(a)redhat.com>
AuthorDate: Sun Sep 9 21:57:59 2012 +0200
Committer: Petr Rockai <prockai(a)redhat.com>
CommitterDate: Wed Sep 26 17:26:16 2012 +0200
lvmetad: Use "%" PRId64 in place of "%d" for extra clarity.
---
lib/cache/lvmetad.c | 15 +++++++++------
lib/format_text/format-text.c | 8 ++++----
libdaemon/client/daemon-shared.c | 8 ++++----
libdaemon/server/daemon-server.c | 2 +-
4 files changed, 18 insertions(+), 15 deletions(-)
diff --git a/lib/cache/lvmetad.c b/lib/cache/lvmetad.c
index 90d43dd..1e185da 100644
--- a/lib/cache/lvmetad.c
+++ b/lib/cache/lvmetad.c
@@ -508,7 +508,7 @@ int lvmetad_pv_lookup_by_dev(struct cmd_context *cmd, struct device *dev, int *f
if (!lvmetad_active())
return_0;
- reply = _lvmetad_send("pv_lookup", "device = %d", dev->dev, NULL);
+ reply = _lvmetad_send("pv_lookup", "device = %" PRId64, (int64_t) dev->dev, NULL);
if (!_lvmetad_handle_reply(reply, "lookup PV", dev_name(dev), found))
goto_out;
@@ -624,7 +624,10 @@ static int _extract_da(struct disk_locn *da, void *baton)
dm_snprintf(id, 32, "da%d", b->i);
if (!(cn = make_config_node(b->cft, id, b->cft->root, b->pre_sib)))
return 0;
- if (!config_make_nodes(b->cft, cn, NULL, "offset = %d", da->offset, "size = %d", da->size, NULL))
+ if (!config_make_nodes(b->cft, cn, NULL,
+ "offset = %"PRId64, (int64_t) da->offset,
+ "size = %"PRId64, (int64_t) da->size,
+ NULL))
return 0;
b->i ++;
@@ -676,10 +679,10 @@ int lvmetad_pv_found(struct id pvid, struct device *device, const struct format_
}
if (!config_make_nodes(pvmeta, pvmeta->root, NULL,
- "device = %d", device->dev,
- "dev_size = %d", info ? lvmcache_device_size(info) : 0,
+ "device = %"PRId64, (int64_t) device->dev,
+ "dev_size = %"PRId64, (int64_t) (info ? lvmcache_device_size(info) : 0),
"format = %s", fmt->name,
- "label_sector = %d", label_sector,
+ "label_sector = %"PRId64, (int64_t) label_sector,
"id = %s", uuid,
NULL))
{
@@ -751,7 +754,7 @@ int lvmetad_pv_gone(dev_t device, const char *pv_name, activation_handler handle
* the whole stack from top to bottom (not yet upstream).
*/
- reply = _lvmetad_send("pv_gone", "device = %d", device, NULL);
+ reply = _lvmetad_send("pv_gone", "device = %" PRId64, (int64_t) device, NULL);
result = _lvmetad_handle_reply(reply, "drop PV", pv_name, &found);
/* We don't care whether or not the daemon had the PV cached. */
diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c
index ff8757f..b562cfa 100644
--- a/lib/format_text/format-text.c
+++ b/lib/format_text/format-text.c
@@ -1617,10 +1617,10 @@ static int _mda_export_text_raw(struct metadata_area *mda,
struct mda_context *mdc = (struct mda_context *) mda->metadata_locn;
return config_make_nodes(cft, parent, NULL,
- "ignore = %d", mda_is_ignored(mda),
- "start = %d", mdc->area.start,
- "size = %d", mdc->area.size,
- "free_sectors = %d", mdc->free_sectors,
+ "ignore = %" PRId64, (int64_t) mda_is_ignored(mda),
+ "start = %" PRId64, (int64_t) mdc->area.start,
+ "size = %" PRId64, (int64_t) mdc->area.size,
+ "free_sectors = %" PRId64, (int64_t) mdc->free_sectors,
NULL) ? 1 : 0;
}
diff --git a/libdaemon/client/daemon-shared.c b/libdaemon/client/daemon-shared.c
index 4b98f51..6a1cf05 100644
--- a/libdaemon/client/daemon-shared.c
+++ b/libdaemon/client/daemon-shared.c
@@ -115,9 +115,9 @@ char *format_buffer_v(const char *head, va_list ap)
goto fail;
}
keylen = strchr(next, '=') - next;
- if (strstr(next, "%d")) {
- int value = va_arg(ap, int);
- dm_asprintf(&buffer, "%s%.*s= %d\n", buffer, keylen, next, value);
+ if (strstr(next, "%d") || strstr(next, "%" PRId64)) {
+ int64_t value = va_arg(ap, int64_t);
+ dm_asprintf(&buffer, "%s%.*s= %" PRId64 "\n", buffer, keylen, next, value);
dm_free(old);
} else if (strstr(next, "%s")) {
char *value = va_arg(ap, char *);
@@ -301,7 +301,7 @@ struct dm_config_node *config_make_nodes_v(struct dm_config_tree *cft,
char *key = dm_pool_strdup(cft->mem, next);
*strchr(key, '=') = 0;
- if (!strcmp(fmt, "%d")) {
+ if (!strcmp(fmt, "%d") || !strcmp(fmt, "%" PRId64)) {
int64_t value = va_arg(ap, int64_t);
if (!(cn = make_int_node(cft, key, value, parent, pre_sib)))
return 0;
diff --git a/libdaemon/server/daemon-server.c b/libdaemon/server/daemon-server.c
index 76627c0..50bf065 100644
--- a/libdaemon/server/daemon-server.c
+++ b/libdaemon/server/daemon-server.c
@@ -360,7 +360,7 @@ static response builtin_handler(daemon_state s, client_handle h, request r)
if (!strcmp(rq, "hello")) {
return daemon_reply_simple("OK", "protocol = %s", s.protocol ?: "default",
- "version = %d", s.protocol_version, NULL);
+ "version = %" PRId64, (int64_t) s.protocol_version, NULL);
}
response res = { .buffer = NULL, .error = EPROTO };
11 years, 6 months
master - Implement devices/global_filter.
by Petr Rockai
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=c7b17836ea139b...
Commit: c7b17836ea139ba7448f5a5c1d2fbe93676baa36
Parent: ceb79c9a500f38ac31c8d79904c3730805feb3dc
Author: Petr Rockai <prockai(a)redhat.com>
AuthorDate: Mon Aug 13 19:44:10 2012 +0200
Committer: Petr Rockai <prockai(a)redhat.com>
CommitterDate: Wed Sep 26 14:49:15 2012 +0200
Implement devices/global_filter.
The global filter is applied first, and is also applied in pvscan --cache (which
is called from udev rules to keep lvmetad updated). Cf. example.conf.
---
daemons/lvmetad/lvmetad-core.c | 87 +++++++++++++-------
doc/example.conf.in | 8 ++
lib/cache/lvmcache.c | 2 -
lib/cache/lvmetad.c | 167 ++++++++++++++++++++++++++++++--------
lib/cache/lvmetad.h | 27 ++++++-
lib/commands/toolcontext.c | 45 +++++++++--
lib/commands/toolcontext.h | 1 +
lib/device/dev-cache.c | 4 +-
lib/device/dev-cache.h | 1 +
lib/filters/filter-persistent.c | 5 +-
lib/filters/filter-persistent.h | 1 -
libdaemon/client/daemon-shared.c | 4 +-
test/lib/aux.sh | 2 +-
tools/pvscan.c | 31 +-------
tools/vgrename.c | 3 +-
tools/vgscan.c | 3 +-
16 files changed, 279 insertions(+), 112 deletions(-)
diff --git a/daemons/lvmetad/lvmetad-core.c b/daemons/lvmetad/lvmetad-core.c
index c96e285..09ba20d 100644
--- a/daemons/lvmetad/lvmetad-core.c
+++ b/daemons/lvmetad/lvmetad-core.c
@@ -41,6 +41,8 @@ typedef struct {
pthread_mutex_t vgid_to_metadata;
pthread_mutex_t pvid_to_vgid;
} lock;
+ char token[128];
+ pthread_mutex_t token_lock;
} lvmetad_state;
static void lock_pvid_to_pvmeta(lvmetad_state *s) {
@@ -58,6 +60,16 @@ static void lock_pvid_to_vgid(lvmetad_state *s) {
static void unlock_pvid_to_vgid(lvmetad_state *s) {
pthread_mutex_unlock(&s->lock.pvid_to_vgid); }
+static response reply_fail(const char *reason)
+{
+ return daemon_reply_simple("failed", "reason = %s", reason, NULL);
+}
+
+static response reply_unknown(const char *reason)
+{
+ return daemon_reply_simple("unknown", "reason = %s", reason, NULL);
+}
+
/*
* TODO: It may be beneficial to clean up the vg lock hash from time to time,
* since if we have many "rogue" requests for nonexistent things, we will keep
@@ -257,13 +269,13 @@ static response pv_lookup(lvmetad_state *s, request r)
struct dm_config_node *pv;
if (!pvid && !devt)
- return daemon_reply_simple("failed", "reason = %s", "need PVID or device", NULL);
+ return reply_fail("need PVID or device");
if (!(res.cft = dm_config_create()))
- return daemon_reply_simple("failed", "reason = %s", "out of memory", NULL);
+ return reply_fail("out of memory");
if (!(res.cft->root = make_text_node(res.cft, "response", "OK", NULL, NULL)))
- return daemon_reply_simple("failed", "reason = %s", "out of memory", NULL);
+ return reply_fail("out of memory");
lock_pvid_to_pvmeta(s);
if (!pvid && devt)
@@ -273,14 +285,14 @@ static response pv_lookup(lvmetad_state *s, request r)
WARN(s, "pv_lookup: could not find device %" PRIu64, devt);
unlock_pvid_to_pvmeta(s);
dm_config_destroy(res.cft);
- return daemon_reply_simple("unknown", "reason = %s", "device not found", NULL);
+ return reply_unknown("device not found");
}
pv = make_pv_node(s, pvid, res.cft, NULL, res.cft->root);
if (!pv) {
unlock_pvid_to_pvmeta(s);
dm_config_destroy(res.cft);
- return daemon_reply_simple("unknown", "reason = %s", "PV not found", NULL);
+ return reply_unknown("PV not found");
}
pv->key = "physical_volume";
@@ -381,12 +393,12 @@ static response vg_lookup(lvmetad_state *s, request r)
DEBUG(s, "vg_lookup: updated uuid = %s, name = %s", uuid, name);
if (!uuid)
- return daemon_reply_simple("unknown", "reason = %s", "VG not found", NULL);
+ return reply_unknown("VG not found");
cft = lock_vg(s, uuid);
if (!cft || !cft->root) {
unlock_vg(s, uuid);
- return daemon_reply_simple("unknown", "reason = %s", "UUID not found", NULL);
+ return reply_unknown("UUID not found");
}
metadata = cft->root;
@@ -426,7 +438,7 @@ static response vg_lookup(lvmetad_state *s, request r)
return res;
bad:
unlock_vg(s, uuid);
- return daemon_reply_simple("failed", "reason = %s", "Out of memory", NULL);
+ return reply_fail("out of memory");
}
static int compare_value(struct dm_config_value *a, struct dm_config_value *b)
@@ -694,7 +706,7 @@ static response pv_gone(lvmetad_state *s, request r)
pvid = dm_hash_lookup_binary(s->device_to_pvid, &device, sizeof(device));
if (!pvid) {
unlock_pvid_to_pvmeta(s);
- return daemon_reply_simple("unknown", "reason = %s", "device not in cache", NULL);
+ return reply_unknown("device not in cache");
}
DEBUG(s, "pv_gone (updated): %s / %" PRIu64, pvid, device);
@@ -709,7 +721,7 @@ static response pv_gone(lvmetad_state *s, request r)
dm_config_destroy(pvmeta);
return daemon_reply_simple("OK", NULL);
} else
- return daemon_reply_simple("unknown", "reason = %s", "PVID does not exist", NULL);
+ return reply_unknown("PVID does not exist");
}
static response pv_found(lvmetad_state *s, request r)
@@ -726,12 +738,12 @@ static response pv_found(lvmetad_state *s, request r)
int complete = 0, orphan = 0;
if (!pvid)
- return daemon_reply_simple("failed", "reason = %s", "need PV UUID", NULL);
+ return reply_fail("need PV UUID");
if (!pvmeta)
- return daemon_reply_simple("failed", "reason = %s", "need PV metadata", NULL);
+ return reply_fail("need PV metadata");
if (!dm_config_get_uint64(pvmeta, "pvmeta/device", &device))
- return daemon_reply_simple("failed", "reason = %s", "need PV device number", NULL);
+ return reply_fail("need PV device number");
DEBUG(s, "pv_found %s, vgid = %s, device = %" PRIu64, pvid, vgid, device);
@@ -745,14 +757,14 @@ static response pv_found(lvmetad_state *s, request r)
if (!(cft = dm_config_create()) ||
!(cft->root = dm_config_clone_node(cft, pvmeta, 0))) {
unlock_pvid_to_pvmeta(s);
- return daemon_reply_simple("failed", "reason = %s", "out of memory", NULL);
+ return reply_fail("out of memory");
}
pvid_dup = dm_config_find_str(cft->root, "pvmeta/id", NULL);
if (!dm_hash_insert(s->pvid_to_pvmeta, pvid, cft) ||
!dm_hash_insert_binary(s->device_to_pvid, &device, sizeof(device), (void*)pvid_dup)) {
unlock_pvid_to_pvmeta(s);
- return daemon_reply_simple("failed", "reason = %s", "out of memory", NULL);
+ return reply_fail("out of memory");
}
if (pvmeta_old)
dm_config_destroy(pvmeta_old);
@@ -761,16 +773,15 @@ static response pv_found(lvmetad_state *s, request r)
if (metadata) {
if (!vgid)
- return daemon_reply_simple("failed", "reason = %s", "need VG UUID", NULL);
+ return reply_fail("need VG UUID");
DEBUG(s, "obtained vgid = %s, vgname = %s", vgid, vgname);
if (!vgname)
- return daemon_reply_simple("failed", "reason = %s", "need VG name", NULL);
+ return reply_fail("need VG name");
if (daemon_request_int(r, "metadata/seqno", -1) < 0)
- return daemon_reply_simple("failed", "reason = %s", "need VG seqno", NULL);
+ return reply_fail("need VG seqno");
if (!update_metadata(s, vgname, vgid, metadata))
- return daemon_reply_simple("failed", "reason = %s",
- "metadata update failed", NULL);
+ return reply_fail("metadata update failed");
} else {
lock_pvid_to_vgid(s);
vgid = dm_hash_lookup(s->pvid_to_vgid, pvid);
@@ -784,8 +795,7 @@ static response pv_found(lvmetad_state *s, request r)
orphan = 1;
else {
unlock_vg(s, vgid);
- return daemon_reply_simple("failed", "reason = %s",
- "non-orphan VG without metadata encountered", NULL);
+ return reply_fail("non-orphan VG without metadata encountered");
}
unlock_vg(s, vgid);
}
@@ -804,17 +814,16 @@ static response vg_update(lvmetad_state *s, request r)
const char *vgname = daemon_request_str(r, "vgname", NULL);
if (metadata) {
if (!vgid)
- return daemon_reply_simple("failed", "reason = %s", "need VG UUID", NULL);
+ return reply_fail("need VG UUID");
if (!vgname)
- return daemon_reply_simple("failed", "reason = %s", "need VG name", NULL);
+ return reply_fail("need VG name");
if (daemon_request_int(r, "metadata/seqno", -1) < 0)
- return daemon_reply_simple("failed", "reason = %s", "need VG seqno", NULL);
+ return reply_fail("need VG seqno");
/* TODO defer metadata update here; add a separate vg_commit
* call; if client does not commit, die */
if (!update_metadata(s, vgname, vgid, metadata))
- return daemon_reply_simple("failed", "reason = %s",
- "metadata update failed", NULL);
+ return reply_fail("metadata update failed");
}
return daemon_reply_simple("OK", NULL);
}
@@ -824,7 +833,7 @@ static response vg_remove(lvmetad_state *s, request r)
const char *vgid = daemon_request_str(r, "uuid", NULL);
if (!vgid)
- return daemon_reply_simple("failed", "reason = %s", "need VG UUID", NULL);
+ return reply_fail("need VG UUID");
DEBUG(s, "vg_remove: %s", vgid);
@@ -839,6 +848,24 @@ static response handler(daemon_state s, client_handle h, request r)
{
lvmetad_state *state = s.private;
const char *rq = daemon_request_str(r, "request", "NONE");
+ const char *token = daemon_request_str(r, "token", "NONE");
+
+ pthread_mutex_lock(&state->token_lock);
+ if (!strcmp(rq, "token_update")) {
+ strncpy(state->token, token, 128);
+ state->token[127] = 0;
+ pthread_mutex_unlock(&state->token_lock);
+ return daemon_reply_simple("OK", NULL);
+ }
+
+ if (strcmp(token, state->token)) {
+ pthread_mutex_unlock(&state->token_lock);
+ return daemon_reply_simple("token_mismatch",
+ "expected = %s", state->token,
+ "received = %s", token,
+ "reason = %s", "token mismatch", NULL);
+ }
+ pthread_mutex_unlock(&state->token_lock);
/*
* TODO Add a stats call, with transaction count/rate, time since last
@@ -869,7 +896,7 @@ static response handler(daemon_state s, client_handle h, request r)
if (!strcmp(rq, "vg_list"))
return vg_list(state, r);
- return daemon_reply_simple("failed", "reason = %s", "no such request", NULL);
+ return reply_fail("request not implemented");
}
static int init(daemon_state *s)
@@ -885,11 +912,13 @@ static int init(daemon_state *s)
ls->pvid_to_vgid = dm_hash_create(32);
ls->vgname_to_vgid = dm_hash_create(32);
ls->lock.vg = dm_hash_create(32);
+ ls->token[0] = 0;
pthread_mutexattr_init(&rec);
pthread_mutexattr_settype(&rec, PTHREAD_MUTEX_RECURSIVE_NP);
pthread_mutex_init(&ls->lock.pvid_to_pvmeta, &rec);
pthread_mutex_init(&ls->lock.vgid_to_metadata, &rec);
pthread_mutex_init(&ls->lock.pvid_to_vgid, NULL);
+ pthread_mutex_init(&ls->token_lock, NULL);
/* Set up stderr logging depending on the -d option. */
daemon_log_parse(ls->log, DAEMON_LOG_OUTLET_STDERR, ls->debug_config, 1);
diff --git a/doc/example.conf.in b/doc/example.conf.in
index 7b26bdc..b4cda6f 100644
--- a/doc/example.conf.in
+++ b/doc/example.conf.in
@@ -79,6 +79,14 @@ devices {
# Use anchors if you want to be really specific
# filter = [ "a|^/dev/hda8$|", "r/.*/" ]
+ # Since "filter" is often overriden from command line, it is not suitable
+ # for system-wide device filtering (udev rules, lvmetad). To hide devices
+ # from LVM-specific udev processing and/or from lvmetad, you need to set
+ # global_filter. The syntax is the same as for normal "filter"
+ # above. Devices that fail the global_filter are not even opened by LVM.
+
+ # global_filter = []
+
# The results of the filtering are cached on disk to avoid
# rescanning dud devices (which can take a very long time).
# By default this cache is stored in the @DEFAULT_SYS_DIR@/@DEFAULT_CACHE_SUBDIR@ directory
diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c
index 6f9cfad..2c431b1 100644
--- a/lib/cache/lvmcache.c
+++ b/lib/cache/lvmcache.c
@@ -109,8 +109,6 @@ int lvmcache_init(void)
_vg_global_lock_held = 0;
}
- lvmetad_init();
-
return 1;
}
diff --git a/lib/cache/lvmetad.c b/lib/cache/lvmetad.c
index 53dbab0..90d43dd 100644
--- a/lib/cache/lvmetad.c
+++ b/lib/cache/lvmetad.c
@@ -20,38 +20,120 @@
#include "lvmcache.h"
#include "lvmetad-client.h"
#include "format-text.h" // TODO for disk_locn, used as a DA representation
+#include "filter.h"
+#include "assert.h"
+#include "crc.h"
-static int _using_lvmetad = 0;
static daemon_handle _lvmetad;
-static const char *_lvmetad_token;
+static int _lvmetad_use = 0;
+static int _lvmetad_connected = 0;
-void lvmetad_init(void)
+static char *_lvmetad_token = NULL;
+static const char *_lvmetad_socket = NULL;
+static struct cmd_context *_lvmetad_cmd = NULL;
+
+void lvmetad_disconnect(void)
+{
+ daemon_close(_lvmetad);
+ _lvmetad_connected = 0;
+ _lvmetad_cmd = NULL;
+}
+
+void lvmetad_init(struct cmd_context *cmd)
{
- const char *socket = getenv("LVM_LVMETAD_SOCKET");
- if (_using_lvmetad) { /* configured by the toolcontext */
- _lvmetad = lvmetad_open(socket ?: DEFAULT_RUN_DIR "/lvmetad.socket");
- if (_lvmetad.socket_fd < 0 || _lvmetad.error) {
+ if (_lvmetad_use && _lvmetad_socket && !_lvmetad_connected) {
+ assert(_lvmetad_socket);
+ _lvmetad = lvmetad_open(_lvmetad_socket);
+ if (_lvmetad.socket_fd >= 0 && !_lvmetad.error) {
+ _lvmetad_connected = 1;
+ _lvmetad_cmd = cmd;
+ } else
log_warn("WARNING: Failed to connect to lvmetad: %s. Falling back to internal scanning.", strerror(_lvmetad.error));
- _using_lvmetad = 0;
- }
}
}
+int lvmetad_active(void)
+{
+ return _lvmetad_use && _lvmetad_connected;
+}
+
+void lvmetad_set_active(int active)
+{
+ _lvmetad_use = active;
+}
+
+void lvmetad_set_token(const struct dm_config_value *filter)
+{
+ if (_lvmetad_token)
+ dm_free(_lvmetad_token);
+ int ft = 0;
+ while (filter && filter->type == DM_CFG_STRING) {
+ ft = calc_crc(ft, (const uint8_t *) filter->v.str, strlen(filter->v.str));
+ filter = filter->next;
+ }
+ if (!dm_asprintf(&_lvmetad_token, "filter:%u", ft))
+ log_warn("WARNING: Failed to set lvmetad token. Out of memory?");
+}
+
+void lvmetad_set_socket(const char *sock)
+{
+ _lvmetad_socket = sock;
+}
+
+static daemon_reply _lvmetad_send(const char *id, ...);
+
+static int _token_update()
+{
+ daemon_reply repl = _lvmetad_send("token_update", NULL);
+
+ if (strcmp(daemon_reply_str(repl, "response", ""), "OK")) {
+ daemon_reply_destroy(repl);
+ return 0;
+ }
+
+ daemon_reply_destroy(repl);
+ return 1;
+}
+
+
static daemon_reply _lvmetad_send(const char *id, ...)
{
va_list ap;
- va_start(ap, id);
- daemon_reply repl;
- daemon_request req = daemon_request_make(id);
+ daemon_reply repl, token_set;
+ daemon_request req;
+ int try = 0;
+ char *future_token;
- // daemon_request_extend(req, "token", _lvmetad_token, NULL);
+retry:
+ req = daemon_request_make(id);
+
+ if (_lvmetad_token)
+ daemon_request_extend(req, "token = %s", _lvmetad_token, NULL);
+
+ va_start(ap, id);
daemon_request_extend_v(req, ap);
+ va_end(ap);
repl = daemon_send(_lvmetad, req);
daemon_request_destroy(req);
- va_end(ap);
+ if (!strcmp(daemon_reply_str(repl, "response", ""), "token_mismatch") && try < 2 && !test_mode()) {
+ future_token = _lvmetad_token;
+ _lvmetad_token = (char *) "update in progress";
+ if (!_token_update()) goto out;
+
+ if (pvscan_lvmetad_all_devs(_lvmetad_cmd, NULL)) {
+ _lvmetad_token = future_token;
+ if (!_token_update()) goto out;
+ }
+ _lvmetad_token = future_token;
+ ++ try;
+ daemon_reply_destroy(repl);
+ goto retry;
+ }
+
+out:
return repl;
}
@@ -203,7 +285,7 @@ struct volume_group *lvmetad_vg_lookup(struct cmd_context *cmd, const char *vgna
struct pv_list *pvl;
struct lvmcache_info *info;
- if (!_using_lvmetad)
+ if (!lvmetad_active())
return NULL;
if (vgid) {
@@ -317,7 +399,7 @@ int lvmetad_vg_update(struct volume_group *vg)
if (!vg)
return 0;
- if (!_using_lvmetad || test_mode())
+ if (!lvmetad_active() || test_mode())
return 1; /* fake it */
if (!(vgmeta = _export_vg_to_config_tree(vg)))
@@ -369,7 +451,7 @@ int lvmetad_vg_remove(struct volume_group *vg)
daemon_reply reply;
int result;
- if (!_using_lvmetad || test_mode())
+ if (!lvmetad_active() || test_mode())
return 1; /* just fake it */
if (!id_write_format(&vg->id, uuid, sizeof(uuid)))
@@ -390,7 +472,7 @@ int lvmetad_pv_lookup(struct cmd_context *cmd, struct id pvid, int *found)
int result = 0;
struct dm_config_node *cn;
- if (!_using_lvmetad)
+ if (!lvmetad_active())
return_0;
if (!id_write_format(&pvid, uuid, sizeof(uuid)))
@@ -423,7 +505,7 @@ int lvmetad_pv_lookup_by_dev(struct cmd_context *cmd, struct device *dev, int *f
daemon_reply reply;
struct dm_config_node *cn;
- if (!_using_lvmetad)
+ if (!lvmetad_active())
return_0;
reply = _lvmetad_send("pv_lookup", "device = %d", dev->dev, NULL);
@@ -450,7 +532,7 @@ int lvmetad_pv_list_to_lvmcache(struct cmd_context *cmd)
daemon_reply reply;
struct dm_config_node *cn;
- if (!_using_lvmetad)
+ if (!lvmetad_active())
return 1;
reply = _lvmetad_send("pv_list", NULL);
@@ -476,7 +558,7 @@ int lvmetad_vg_list_to_lvmcache(struct cmd_context *cmd)
daemon_reply reply;
struct dm_config_node *cn;
- if (!_using_lvmetad)
+ if (!lvmetad_active())
return 1;
reply = _lvmetad_send("vg_list", NULL);
@@ -576,7 +658,7 @@ int lvmetad_pv_found(struct id pvid, struct device *device, const struct format_
const char *status;
int result;
- if (!_using_lvmetad || test_mode())
+ if (!lvmetad_active() || test_mode())
return 1;
if (!id_write_format(&pvid, uuid, sizeof(uuid)))
@@ -659,7 +741,7 @@ int lvmetad_pv_gone(dev_t device, const char *pv_name, activation_handler handle
int result;
int found;
- if (!_using_lvmetad || test_mode())
+ if (!lvmetad_active() || test_mode())
return 1;
/*
@@ -669,7 +751,7 @@ int lvmetad_pv_gone(dev_t device, const char *pv_name, activation_handler handle
* the whole stack from top to bottom (not yet upstream).
*/
- reply = daemon_send_simple(_lvmetad, "pv_gone", "device = %d", device, NULL);
+ reply = _lvmetad_send("pv_gone", "device = %d", device, NULL);
result = _lvmetad_handle_reply(reply, "drop PV", pv_name, &found);
/* We don't care whether or not the daemon had the PV cached. */
@@ -684,16 +766,6 @@ int lvmetad_pv_gone_by_dev(struct device *dev, activation_handler handler)
return lvmetad_pv_gone(dev->dev, dev_name(dev), handler);
}
-int lvmetad_active(void)
-{
- return _using_lvmetad;
-}
-
-void lvmetad_set_active(int active)
-{
- _using_lvmetad = active;
-}
-
/*
* The following code implements pvscan --cache.
*/
@@ -771,3 +843,30 @@ bad:
"It is strongly recommended that you restart lvmetad immediately.");
return 0;
}
+
+int pvscan_lvmetad_all_devs(struct cmd_context *cmd, activation_handler handler)
+{
+ struct dev_iter *iter;
+ struct device *dev;
+ int r = 1;
+
+ if (!(iter = dev_iter_create(cmd->lvmetad_filter, 1))) {
+ log_error("dev_iter creation failed");
+ return 0;
+ }
+
+ while ((dev = dev_iter_get(iter))) {
+ if (!pvscan_lvmetad_single(cmd, dev, handler)) {
+ r = 0;
+ break;
+ }
+
+ if (sigint_caught())
+ break;
+ }
+
+ dev_iter_destroy(iter);
+
+ return r;
+}
+
diff --git a/lib/cache/lvmetad.h b/lib/cache/lvmetad.h
index 7a6fe0b..cb85929 100644
--- a/lib/cache/lvmetad.h
+++ b/lib/cache/lvmetad.h
@@ -30,7 +30,7 @@ typedef int (*activation_handler) (struct volume_group *vg, int partial,
* Initialise the communication with lvmetad. Normally called by
* lvmcache_init. Sets up a global handle for our process.
*/
-void lvmetad_init(void);
+void lvmetad_init(struct cmd_context *);
/*
* Override the use of lvmetad for retrieving scan results and metadata.
@@ -38,12 +38,29 @@ void lvmetad_init(void);
void lvmetad_set_active(int);
/*
+ * Configure the socket that lvmetad_init will use to connect to the daemon.
+ */
+void lvmetad_set_socket(const char *);
+
+/*
* Check whether lvmetad is active (where active means both that it is running
* and that we have a working connection with it).
*/
int lvmetad_active(void);
/*
+ * Drop connection to lvmetad. A subsequent lvmetad_init() will re-establish
+ * the connection (possibly at a different socket path).
+ */
+void lvmetad_disconnect(void);
+
+/*
+ * Set the "lvmetad validity token" (currently only consists of the lvmetad
+ * filter. See lvm.conf.
+ */
+void lvmetad_set_token(const struct dm_config_value *filter);
+
+/*
* Send a new version of VG metadata to lvmetad. This is normally called after
* vg_write but before vg_commit. After vg_commit, lvmetad_vg_commit is called
* to seal the transaction. The result of lvmetad_vg_update is that the new
@@ -111,11 +128,16 @@ struct volume_group *lvmetad_vg_lookup(struct cmd_context *cmd,
int pvscan_lvmetad_single(struct cmd_context *cmd, struct device *dev,
activation_handler handler);
+int pvscan_lvmetad_all_devs(struct cmd_context *cmd, activation_handler handler);
+
# else /* LVMETAD_SUPPORT */
-# define lvmetad_init() do { } while (0)
+# define lvmetad_init(cmd) do { } while (0)
+# define lvmetad_disconnect() do { } while (0)
# define lvmetad_set_active(a) do { } while (0)
+# define lvmetad_set_socket(a) do { } while (0)
# define lvmetad_active() (0)
+# define lvmetad_set_token(a) do { } while (0)
# define lvmetad_vg_update(vg) (1)
# define lvmetad_vg_remove(vg) (1)
# define lvmetad_pv_found(pvid, device, fmt, label_sector, vg, handler) (1)
@@ -127,6 +149,7 @@ int pvscan_lvmetad_single(struct cmd_context *cmd, struct device *dev,
# define lvmetad_vg_list_to_lvmcache(cmd) (1)
# define lvmetad_vg_lookup(cmd, vgname, vgid) (NULL)
# define pvscan_lvmetad_single(cmd, dev, handler) (0)
+# define pvscan_lvmetad_all_devs(cmd, handler) (0)
# endif /* LVMETAD_SUPPORT */
diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c
index 9c2404f..c5e0ee3 100644
--- a/lib/commands/toolcontext.c
+++ b/lib/commands/toolcontext.c
@@ -399,7 +399,20 @@ static int _process_config(struct cmd_context *cmd)
(find_config_tree_int(cmd, "global/detect_internal_vg_cache_corruption",
DEFAULT_DETECT_INTERNAL_VG_CACHE_CORRUPTION));
+ lvmetad_disconnect();
+ const char *lvmetad_socket = getenv("LVM_LVMETAD_SOCKET");
+ if (!lvmetad_socket)
+ lvmetad_socket = DEFAULT_RUN_DIR "/lvmetad.socket";
+
+ /* TODO?
+ lvmetad_socket = find_config_tree_str(cmd, "lvmetad/socket_path",
+ DEFAULT_RUN_DIR "/lvmetad.socket");
+ */
+ lvmetad_set_socket(lvmetad_socket);
+ cn = find_config_tree_node(cmd, "devices/global_filter");
+ lvmetad_set_token(cn ? cn->v : NULL);
lvmetad_set_active(find_config_tree_int(cmd, "global/use_lvmetad", 0));
+ lvmetad_init(cmd);
return 1;
}
@@ -818,13 +831,14 @@ static int _init_filters(struct cmd_context *cmd, unsigned load_persistent_cache
{
static char cache_file[PATH_MAX];
const char *dev_cache = NULL, *cache_dir, *cache_file_prefix;
- struct dev_filter *f3, *f4;
+ struct dev_filter *f3 = NULL, *f4 = NULL, *toplevel_components[2] = { 0 };
struct stat st;
+ const struct dm_config_node *cn;
cmd->dump_filter = 0;
if (!(f3 = _init_filter_components(cmd)))
- return_0;
+ goto_bad;
init_ignore_suspended_devices(find_config_tree_int(cmd,
"devices/ignore_suspended_devices", DEFAULT_IGNORE_SUSPENDED_DEVICES));
@@ -843,8 +857,7 @@ static int _init_filters(struct cmd_context *cmd, unsigned load_persistent_cache
cache_dir ? : DEFAULT_CACHE_SUBDIR,
cache_file_prefix ? : DEFAULT_CACHE_FILE_PREFIX) < 0) {
log_error("Persistent cache filename too long.");
- f3->destroy(f3);
- return 0;
+ goto bad;
}
} else if (!(dev_cache = find_config_tree_str(cmd, "devices/cache", NULL)) &&
(dm_snprintf(cache_file, sizeof(cache_file),
@@ -852,8 +865,7 @@ static int _init_filters(struct cmd_context *cmd, unsigned load_persistent_cache
cmd->system_dir, DEFAULT_CACHE_SUBDIR,
DEFAULT_CACHE_FILE_PREFIX) < 0)) {
log_error("Persistent cache filename too long.");
- f3->destroy(f3);
- return 0;
+ goto bad;
}
if (!dev_cache)
@@ -883,9 +895,26 @@ static int _init_filters(struct cmd_context *cmd, unsigned load_persistent_cache
log_verbose("Failed to load existing device cache from %s",
dev_cache);
- cmd->filter = f4;
+ if (!(cn = find_config_tree_node(cmd, "devices/global_filter"))) {
+ cmd->filter = f4;
+ } else if (!(cmd->lvmetad_filter = regex_filter_create(cn->v)))
+ goto_bad;
+ else {
+ toplevel_components[0] = cmd->lvmetad_filter;
+ toplevel_components[1] = f4;
+ if (!(cmd->filter = composite_filter_create(2, toplevel_components)))
+ goto_bad;
+ }
return 1;
+bad:
+ if (f3)
+ f3->destroy(f3);
+ if (f4)
+ f4->destroy(f4);
+ if (toplevel_components[0])
+ toplevel_components[0]->destroy(toplevel_components[0]);
+ return 0;
}
struct format_type *get_format_by_name(struct cmd_context *cmd, const char *format)
@@ -1495,6 +1524,8 @@ int refresh_filters(struct cmd_context *cmd)
cmd->filter = NULL;
}
+ cmd->lvmetad_filter = NULL;
+
if (!(r = _init_filters(cmd, 0)))
stack;
diff --git a/lib/commands/toolcontext.h b/lib/commands/toolcontext.h
index e0ef041..6e5803f 100644
--- a/lib/commands/toolcontext.h
+++ b/lib/commands/toolcontext.h
@@ -91,6 +91,7 @@ struct cmd_context {
unsigned independent_metadata_areas:1; /* Active formats have MDAs outside PVs */
struct dev_filter *filter;
+ struct dev_filter *lvmetad_filter;
int dump_filter; /* Dump filter when exiting? */
struct dm_list config_files;
diff --git a/lib/device/dev-cache.c b/lib/device/dev-cache.c
index 1da9a77..79b3028 100644
--- a/lib/device/dev-cache.c
+++ b/lib/device/dev-cache.c
@@ -971,8 +971,8 @@ struct dev_iter *dev_iter_create(struct dev_filter *f, int dev_scan)
if (dev_scan && !trust_cache()) {
/* Flag gets reset between each command */
- if (!full_scan_done() && f)
- persistent_filter_wipe(f); /* Calls _full_scan(1) */
+ if (!full_scan_done() && f && f->wipe)
+ f->wipe(f); /* Calls _full_scan(1) */
} else
_full_scan(0);
diff --git a/lib/device/dev-cache.h b/lib/device/dev-cache.h
index f3511cc..3267c9d 100644
--- a/lib/device/dev-cache.h
+++ b/lib/device/dev-cache.h
@@ -25,6 +25,7 @@
struct dev_filter {
int (*passes_filter) (struct dev_filter * f, struct device * dev);
void (*destroy) (struct dev_filter * f);
+ void (*wipe) (struct dev_filter * f);
void *private;
unsigned use_count;
};
diff --git a/lib/filters/filter-persistent.c b/lib/filters/filter-persistent.c
index 79e40b8..d00a99a 100644
--- a/lib/filters/filter-persistent.c
+++ b/lib/filters/filter-persistent.c
@@ -51,7 +51,7 @@ static int _init_hash(struct pfilter *pf)
return 1;
}
-int persistent_filter_wipe(struct dev_filter *f)
+static void _persistent_filter_wipe(struct dev_filter *f)
{
struct pfilter *pf = (struct pfilter *) f->private;
@@ -60,8 +60,6 @@ int persistent_filter_wipe(struct dev_filter *f)
/* Trigger complete device scan */
dev_cache_scan(1);
-
- return 1;
}
static int _read_array(struct pfilter *pf, struct dm_config_tree *cft,
@@ -368,6 +366,7 @@ struct dev_filter *persistent_filter_create(struct dev_filter *real,
f->destroy = _persistent_destroy;
f->use_count = 0;
f->private = pf;
+ f->wipe = _persistent_filter_wipe;
return f;
diff --git a/lib/filters/filter-persistent.h b/lib/filters/filter-persistent.h
index ad56a62..c2eee30 100644
--- a/lib/filters/filter-persistent.h
+++ b/lib/filters/filter-persistent.h
@@ -21,7 +21,6 @@
struct dev_filter *persistent_filter_create(struct dev_filter *f,
const char *file);
-int persistent_filter_wipe(struct dev_filter *f);
int persistent_filter_load(struct dev_filter *f, struct dm_config_tree **cft_out);
int persistent_filter_dump(struct dev_filter *f, int merge_existing);
diff --git a/libdaemon/client/daemon-shared.c b/libdaemon/client/daemon-shared.c
index 40c02b0..4b98f51 100644
--- a/libdaemon/client/daemon-shared.c
+++ b/libdaemon/client/daemon-shared.c
@@ -221,8 +221,10 @@ static void chain_node(struct dm_config_node *cn,
if (parent && !parent->child)
parent->child = cn;
- if (pre_sib)
+ if (pre_sib) {
+ cn->sib = pre_sib->sib;
pre_sib->sib = cn;
+ }
}
diff --git a/test/lib/aux.sh b/test/lib/aux.sh
index 0b46c79..d6a2008 100644
--- a/test/lib/aux.sh
+++ b/test/lib/aux.sh
@@ -527,5 +527,5 @@ target_at_least()
test -f DEVICES && devs=$(cat DEVICES)
-unset LVM_VALGRIND
+#unset LVM_VALGRIND
"$@"
diff --git a/tools/pvscan.c b/tools/pvscan.c
index 9287388..239ce97 100644
--- a/tools/pvscan.c
+++ b/tools/pvscan.c
@@ -106,32 +106,6 @@ static int _auto_activation_handler(struct volume_group *vg, int partial,
return 1;
}
-static int _pvscan_lvmetad_all_devs(struct cmd_context *cmd, activation_handler handler)
-{
- struct dev_iter *iter;
- struct device *dev;
- int r = 1;
-
- if (!(iter = dev_iter_create(cmd->filter, 1))) {
- log_error("dev_iter creation failed");
- return 0;
- }
-
- while ((dev = dev_iter_get(iter))) {
- if (!pvscan_lvmetad_single(cmd, dev, handler)) {
- r = 0;
- break;
- }
-
- if (sigint_caught())
- break;
- }
-
- dev_iter_destroy(iter);
-
- return r;
-}
-
static int _pvscan_lvmetad(struct cmd_context *cmd, int argc, char **argv)
{
int ret = ECMD_PROCESSED;
@@ -168,7 +142,7 @@ static int _pvscan_lvmetad(struct cmd_context *cmd, int argc, char **argv)
/* Scan everything? */
if (!argc && !devno_args) {
- if (!_pvscan_lvmetad_all_devs(cmd, handler))
+ if (!pvscan_lvmetad_all_devs(cmd, handler))
ret = ECMD_FAILED;
goto out;
}
@@ -283,7 +257,8 @@ int pvscan(struct cmd_context *cmd, int argc, char **argv)
return ECMD_FAILED;
}
- persistent_filter_wipe(cmd->filter);
+ if (cmd->filter->wipe)
+ cmd->filter->wipe(cmd->filter);
lvmcache_destroy(cmd, 1);
/* populate lvmcache */
diff --git a/tools/vgrename.c b/tools/vgrename.c
index 451d085..b476602 100644
--- a/tools/vgrename.c
+++ b/tools/vgrename.c
@@ -181,7 +181,8 @@ static int vg_rename_path(struct cmd_context *cmd, const char *old_vg_path,
vg_name_old, vg_name_new);
/* FIXME lvmcache corruption - vginfo duplicated instead of renamed */
- persistent_filter_wipe(cmd->filter);
+ if (cmd->filter->wipe)
+ cmd->filter->wipe(cmd->filter);
lvmcache_destroy(cmd, 1);
return 1;
diff --git a/tools/vgscan.c b/tools/vgscan.c
index a34f3ba..8deafb6 100644
--- a/tools/vgscan.c
+++ b/tools/vgscan.c
@@ -50,7 +50,8 @@ int vgscan(struct cmd_context *cmd, int argc, char **argv)
return ECMD_FAILED;
}
- persistent_filter_wipe(cmd->filter);
+ if (cmd->filter->wipe)
+ cmd->filter->wipe(cmd->filter);
lvmcache_destroy(cmd, 1);
_lvmetad = lvmetad_active();
11 years, 6 months
master - example.conf.in: The command to refresh lvmetad is pvscan --cache.
by Petr Rockai
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=ceb79c9a500f38...
Commit: ceb79c9a500f38ac31c8d79904c3730805feb3dc
Parent: 2276379a71ec9d790241633b013a707a07c5046b
Author: Petr Rockai <prockai(a)redhat.com>
AuthorDate: Mon Aug 13 14:41:57 2012 +0200
Committer: Petr Rockai <prockai(a)redhat.com>
CommitterDate: Wed Sep 26 14:49:15 2012 +0200
example.conf.in: The command to refresh lvmetad is pvscan --cache.
---
doc/example.conf.in | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/doc/example.conf.in b/doc/example.conf.in
index 8cec63c..7b26bdc 100644
--- a/doc/example.conf.in
+++ b/doc/example.conf.in
@@ -479,7 +479,7 @@ global {
# scanning is done by the individual commands. In a setup with lvmetad,
# lvmetad udev rules *must* be set up for LVM to work correctly. Without
# proper udev rules, all changes in block device configuration will be
- # *ignored* until a manual 'vgscan' is performed.
+ # *ignored* until a manual 'pvscan --cache' is performed.
use_lvmetad = 0
# Full path of the utility called to check that a thin metadata device
11 years, 6 months
master - lib/cache/lvmetad: Refactor to use dm_config_tree in requests.
by Petr Rockai
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=2276379a71ec9d...
Commit: 2276379a71ec9d790241633b013a707a07c5046b
Parent: ea14d5159cd3a196c0754f4e37539dee1eb2d169
Author: Petr Rockai <prockai(a)redhat.com>
AuthorDate: Sat Aug 11 10:37:28 2012 +0200
Committer: Petr Rockai <prockai(a)redhat.com>
CommitterDate: Wed Sep 26 14:49:15 2012 +0200
lib/cache/lvmetad: Refactor to use dm_config_tree in requests.
We were using daemon_send_simple until now, but it is no longer adequate, since
we need to manipulate requests in a generic way (adding a validity token to each
request), and the tree-based request interface is much more suitable for this.
---
lib/cache/lvmetad.c | 220 ++++++++++++++++++++++------------------
lib/cache/lvmetad.h | 2 +
lib/format_text/format-text.c | 23 +++--
lib/metadata/metadata.h | 3 +-
4 files changed, 137 insertions(+), 111 deletions(-)
diff --git a/lib/cache/lvmetad.c b/lib/cache/lvmetad.c
index feab361..53dbab0 100644
--- a/lib/cache/lvmetad.c
+++ b/lib/cache/lvmetad.c
@@ -23,6 +23,7 @@
static int _using_lvmetad = 0;
static daemon_handle _lvmetad;
+static const char *_lvmetad_token;
void lvmetad_init(void)
{
@@ -36,6 +37,24 @@ void lvmetad_init(void)
}
}
+static daemon_reply _lvmetad_send(const char *id, ...)
+{
+ va_list ap;
+ va_start(ap, id);
+ daemon_reply repl;
+ daemon_request req = daemon_request_make(id);
+
+ // daemon_request_extend(req, "token", _lvmetad_token, NULL);
+ daemon_request_extend_v(req, ap);
+
+ repl = daemon_send(_lvmetad, req);
+
+ daemon_request_destroy(req);
+
+ va_end(ap);
+ return repl;
+}
+
/*
* Helper; evaluate the reply from lvmetad, check for errors, print diagnostics
* and return a summary success/failure exit code.
@@ -190,11 +209,11 @@ struct volume_group *lvmetad_vg_lookup(struct cmd_context *cmd, const char *vgna
if (vgid) {
if (!id_write_format((const struct id*)vgid, uuid, sizeof(uuid)))
return_NULL;
- reply = daemon_send_simple(_lvmetad, "vg_lookup", "uuid = %s", uuid, NULL);
+ reply = _lvmetad_send("vg_lookup", "uuid = %s", uuid, NULL);
} else {
if (!vgname)
log_error(INTERNAL_ERROR "VG name required (VGID not available)");
- reply = daemon_send_simple(_lvmetad, "vg_lookup", "name = %s", vgname, NULL);
+ reply = _lvmetad_send("vg_lookup", "name = %s", vgname, NULL);
}
if (!strcmp(daemon_reply_str(reply, "response", ""), "OK")) {
@@ -264,9 +283,28 @@ static int _fixup_ignored(struct metadata_area *mda, void *baton) {
return 1;
}
-int lvmetad_vg_update(struct volume_group *vg)
+static struct dm_config_tree *_export_vg_to_config_tree(struct volume_group *vg)
{
char *buf = NULL;
+ struct dm_config_tree *vgmeta;
+
+ if (!export_vg_to_buffer(vg, &buf)) {
+ log_error("Could not format VG metadata.");
+ return 0;
+ }
+
+ if (!(vgmeta = dm_config_from_string(buf))) {
+ log_error("Error parsing VG metadata.");
+ dm_free(buf);
+ return 0;
+ }
+
+ dm_free(buf);
+ return vgmeta;
+}
+
+int lvmetad_vg_update(struct volume_group *vg)
+{
daemon_reply reply;
struct dm_hash_node *n;
struct metadata_area *mda;
@@ -274,6 +312,7 @@ int lvmetad_vg_update(struct volume_group *vg)
struct pv_list *pvl;
struct lvmcache_info *info;
struct _fixup_baton baton;
+ struct dm_config_tree *vgmeta;
if (!vg)
return 0;
@@ -281,20 +320,12 @@ int lvmetad_vg_update(struct volume_group *vg)
if (!_using_lvmetad || test_mode())
return 1; /* fake it */
- /* TODO. This is not entirely correct, since export_vg_to_buffer
- * adds trailing nodes to the buffer. We may need to use
- * export_vg_to_config_tree and format the buffer ourselves. It
- * does, however, work for now, since the garbage is well
- * formatted and has no conflicting keys with the rest of the
- * request. */
- if (!export_vg_to_buffer(vg, &buf)) {
- log_error("Could not format VG metadata.");
- return 0;
- }
+ if (!(vgmeta = _export_vg_to_config_tree(vg)))
+ return_0;
- reply = daemon_send_simple(_lvmetad, "vg_update", "vgname = %s", vg->name,
- "metadata = %b", strchr(buf, '{'), NULL);
- dm_free(buf);
+ reply = _lvmetad_send("vg_update", "vgname = %s", vg->name,
+ "metadata = %t", vgmeta, NULL);
+ dm_config_destroy(vgmeta);
if (!_lvmetad_handle_reply(reply, "update VG", vg->name, NULL)) {
daemon_reply_destroy(reply);
@@ -344,8 +375,7 @@ int lvmetad_vg_remove(struct volume_group *vg)
if (!id_write_format(&vg->id, uuid, sizeof(uuid)))
return_0;
- reply = daemon_send_simple(_lvmetad, "vg_remove", "uuid = %s", uuid, NULL);
-
+ reply = _lvmetad_send("vg_remove", "uuid = %s", uuid, NULL);
result = _lvmetad_handle_reply(reply, "remove VG", vg->name, NULL);
daemon_reply_destroy(reply);
@@ -366,8 +396,7 @@ int lvmetad_pv_lookup(struct cmd_context *cmd, struct id pvid, int *found)
if (!id_write_format(&pvid, uuid, sizeof(uuid)))
return_0;
- reply = daemon_send_simple(_lvmetad, "pv_lookup", "uuid = %s", uuid, NULL);
-
+ reply = _lvmetad_send("pv_lookup", "uuid = %s", uuid, NULL);
if (!_lvmetad_handle_reply(reply, "lookup PV", "", found))
goto_out;
@@ -397,8 +426,7 @@ int lvmetad_pv_lookup_by_dev(struct cmd_context *cmd, struct device *dev, int *f
if (!_using_lvmetad)
return_0;
- reply = daemon_send_simple(_lvmetad, "pv_lookup", "device = %d", dev->dev, NULL);
-
+ reply = _lvmetad_send("pv_lookup", "device = %d", dev->dev, NULL);
if (!_lvmetad_handle_reply(reply, "lookup PV", dev_name(dev), found))
goto_out;
@@ -425,8 +453,7 @@ int lvmetad_pv_list_to_lvmcache(struct cmd_context *cmd)
if (!_using_lvmetad)
return 1;
- reply = daemon_send_simple(_lvmetad, "pv_list", NULL);
-
+ reply = _lvmetad_send("pv_list", NULL);
if (!_lvmetad_handle_reply(reply, "list PVs", "", NULL)) {
daemon_reply_destroy(reply);
return_0;
@@ -452,8 +479,7 @@ int lvmetad_vg_list_to_lvmcache(struct cmd_context *cmd)
if (!_using_lvmetad)
return 1;
- reply = daemon_send_simple(_lvmetad, "vg_list", NULL);
-
+ reply = _lvmetad_send("vg_list", NULL);
if (!_lvmetad_handle_reply(reply, "list VGs", "", NULL)) {
daemon_reply_destroy(reply);
return_0;
@@ -476,66 +502,67 @@ int lvmetad_vg_list_to_lvmcache(struct cmd_context *cmd)
return 1;
}
-struct _print_mda_baton {
+struct _extract_mda_baton {
int i;
- char *buffer;
+ struct dm_config_tree *cft;
+ struct dm_config_node *pre_sib;
};
-static int _print_mda(struct metadata_area *mda, void *baton)
+static int _extract_mda(struct metadata_area *mda, void *baton)
{
+ struct _extract_mda_baton *b = baton;
+ struct dm_config_node *cn;
int result = 0;
- struct _print_mda_baton *b = baton;
- char *buf, *mda_txt;
+ char id[32];
if (!mda->ops->mda_export_text) /* do nothing */
return 1;
- buf = b->buffer;
- mda_txt = mda->ops->mda_export_text(mda);
- if (!dm_asprintf(&b->buffer, "%s mda%i { %s }", b->buffer ?: "", b->i, mda_txt))
- goto_out;
+ dm_snprintf(id, 32, "mda%d", b->i);
+ if (!(cn = make_config_node(b->cft, id, b->cft->root, b->pre_sib)))
+ return 0;
+ if (!mda->ops->mda_export_text(mda, b->cft, cn))
+ return 0;
+
b->i ++;
- result = 1;
-out:
- dm_free(mda_txt);
- dm_free(buf);
- return result;
+ b->pre_sib = cn; /* for efficiency */
+
+ return 1;
}
-static int _print_da(struct disk_locn *da, void *baton)
+static int _extract_da(struct disk_locn *da, void *baton)
{
- struct _print_mda_baton *b;
- char *buf;
+ struct _extract_mda_baton *b = baton;
+ struct dm_config_node *cn;
+ char id[32];
if (!da)
return 1;
- b = baton;
- buf = b->buffer;
- if (!dm_asprintf(&b->buffer, "%s da%i { offset = %" PRIu64
- " size = %" PRIu64 " }",
- b->buffer ?: "", b->i, da->offset, da->size))
- {
- dm_free(buf);
- return_0;
- }
+ dm_snprintf(id, 32, "da%d", b->i);
+ if (!(cn = make_config_node(b->cft, id, b->cft->root, b->pre_sib)))
+ return 0;
+ if (!config_make_nodes(b->cft, cn, NULL, "offset = %d", da->offset, "size = %d", da->size, NULL))
+ return 0;
+
b->i ++;
- dm_free(buf);
+ b->pre_sib = cn; /* for efficiency */
return 1;
}
-static const char *_print_mdas(struct lvmcache_info *info)
+static int _extract_mdas(struct lvmcache_info *info, struct dm_config_tree *cft,
+ struct dm_config_node *pre_sib)
{
- struct _print_mda_baton baton = { .i = 0, .buffer = NULL };
+ struct _extract_mda_baton baton = { .i = 0, .cft = cft, .pre_sib = NULL };
- if (!lvmcache_foreach_mda(info, &_print_mda, &baton))
- return NULL;
+ if (!lvmcache_foreach_mda(info, &_extract_mda, &baton))
+ return 0;
baton.i = 0;
- if (!lvmcache_foreach_da(info, &_print_da, &baton))
- return NULL;
+ if (!lvmcache_foreach_da(info, &_extract_da, &baton))
+ return 0;
- return baton.buffer;
+ return 1;
}
int lvmetad_pv_found(struct id pvid, struct device *device, const struct format_type *fmt,
@@ -545,8 +572,7 @@ int lvmetad_pv_found(struct id pvid, struct device *device, const struct format_
daemon_reply reply;
struct lvmcache_info *info;
const char *mdas = NULL;
- char *pvmeta;
- char *buf = NULL;
+ struct dm_config_tree *pvmeta, *vgmeta;
const char *status;
int result;
@@ -556,46 +582,45 @@ int lvmetad_pv_found(struct id pvid, struct device *device, const struct format_
if (!id_write_format(&pvid, uuid, sizeof(uuid)))
return_0;
- /* FIXME A more direct route would be much preferable. */
- if ((info = lvmcache_info_from_pvid((const char *)&pvid, 0)))
- mdas = _print_mdas(info);
-
- if (!dm_asprintf(&pvmeta,
- "{ device = %" PRIu64 "\n"
- " dev_size = %" PRIu64 "\n"
- " format = \"%s\"\n"
- " label_sector = %" PRIu64 "\n"
- " id = \"%s\"\n"
- " %s"
- "}", device->dev,
- info ? lvmcache_device_size(info) : 0,
- fmt->name, label_sector, uuid, mdas ?: "")) {
- dm_free((char *)mdas);
+ pvmeta = dm_config_create();
+ if (!pvmeta)
+ return_0;
+
+ info = lvmcache_info_from_pvid((const char *)&pvid, 0);
+
+ if (!(pvmeta->root = make_config_node(pvmeta, "pv", NULL, NULL))) {
+ dm_config_destroy(pvmeta);
+ return_0;
+ }
+
+ if (!config_make_nodes(pvmeta, pvmeta->root, NULL,
+ "device = %d", device->dev,
+ "dev_size = %d", info ? lvmcache_device_size(info) : 0,
+ "format = %s", fmt->name,
+ "label_sector = %d", label_sector,
+ "id = %s", uuid,
+ NULL))
+ {
+ dm_config_destroy(pvmeta);
return_0;
}
- dm_free((char *)mdas);
+ if (info)
+ /* FIXME A more direct route would be much preferable. */
+ _extract_mdas(info, pvmeta, pvmeta->root);
if (vg) {
- /*
- * TODO. This is not entirely correct, since export_vg_to_buffer
- * adds trailing garbage to the buffer. We may need to use
- * export_vg_to_config_tree and format the buffer ourselves. It
- * does, however, work for now, since the garbage is well
- * formatted and has no conflicting keys with the rest of the
- * request.
- */
- if (!export_vg_to_buffer(vg, &buf)) {
- dm_free(pvmeta);
+ if (!(vgmeta = _export_vg_to_config_tree(vg))) {
+ dm_config_destroy(pvmeta);
return_0;
}
- reply = daemon_send_simple(_lvmetad,
- "pv_found",
- "pvmeta = %b", pvmeta,
- "vgname = %s", vg->name,
- "metadata = %b", strchr(buf, '{'),
- NULL);
+ reply = _lvmetad_send("pv_found",
+ "pvmeta = %t", pvmeta,
+ "vgname = %s", vg->name,
+ "metadata = %t", vgmeta,
+ NULL);
+ dm_config_destroy(vgmeta);
} else {
if (handler) {
log_error(INTERNAL_ERROR "Handler needs existing VG.");
@@ -603,13 +628,10 @@ int lvmetad_pv_found(struct id pvid, struct device *device, const struct format_
return 0;
}
/* There are no MDAs on this PV. */
- reply = daemon_send_simple(_lvmetad,
- "pv_found",
- "pvmeta = %b", pvmeta,
- NULL);
+ reply = _lvmetad_send("pv_found", "pvmeta = %t", pvmeta, NULL);
}
- dm_free(pvmeta);
+ dm_config_destroy(pvmeta);
result = _lvmetad_handle_reply(reply, "update PV", uuid, NULL);
diff --git a/lib/cache/lvmetad.h b/lib/cache/lvmetad.h
index 9c49440..7a6fe0b 100644
--- a/lib/cache/lvmetad.h
+++ b/lib/cache/lvmetad.h
@@ -15,6 +15,8 @@
#ifndef _LVM_METAD_H
#define _LVM_METAD_H
+#include "daemon-shared.h" // XXX
+
struct volume_group;
struct cmd_context;
struct dm_config_tree;
diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c
index d706c2b..ff8757f 100644
--- a/lib/format_text/format-text.c
+++ b/lib/format_text/format-text.c
@@ -1584,7 +1584,9 @@ static struct metadata_area_ops _metadata_text_file_backup_ops = {
.vg_commit = _vg_commit_file_backup
};
-static char *_mda_export_text_raw(struct metadata_area *mda);
+static int _mda_export_text_raw(struct metadata_area *mda,
+ struct dm_config_tree *cft,
+ struct dm_config_node *parent);
static int _mda_import_text_raw(struct lvmcache_info *info, const struct dm_config_node *cn);
static struct metadata_area_ops _metadata_text_raw_ops = {
@@ -1608,19 +1610,18 @@ static struct metadata_area_ops _metadata_text_raw_ops = {
.mda_import_text = _mda_import_text_raw
};
-static char *_mda_export_text_raw(struct metadata_area *mda)
+static int _mda_export_text_raw(struct metadata_area *mda,
+ struct dm_config_tree *cft,
+ struct dm_config_node *parent)
{
struct mda_context *mdc = (struct mda_context *) mda->metadata_locn;
- char *result;
- dm_asprintf(&result,
- "ignore = %d "
- "start = %" PRIu64" "
- "size = %" PRIu64 " "
- "free_sectors = %" PRIu64,
- mda_is_ignored(mda), mdc->area.start, mdc->area.size, mdc->free_sectors);
-
- return result;
+ return config_make_nodes(cft, parent, NULL,
+ "ignore = %d", mda_is_ignored(mda),
+ "start = %d", mdc->area.start,
+ "size = %d", mdc->area.size,
+ "free_sectors = %d", mdc->free_sectors,
+ NULL) ? 1 : 0;
}
static int _mda_import_text_raw(struct lvmcache_info *info, const struct dm_config_node *cn)
diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h
index 6227a33..7bc7eaf 100644
--- a/lib/metadata/metadata.h
+++ b/lib/metadata/metadata.h
@@ -148,7 +148,8 @@ struct metadata_area_ops {
struct metadata_area *mda2);
struct device *(*mda_get_device)(struct metadata_area *mda);
- char *(*mda_export_text)(struct metadata_area *mda);
+ int (*mda_export_text)(struct metadata_area *mda, struct dm_config_tree *cft,
+ struct dm_config_node *parent);
int (*mda_import_text)(struct lvmcache_info *info, const struct dm_config_node *cn);
};
11 years, 6 months
master - libdaemon: Extend and refactor APIs.
by Petr Rockai
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=ea14d5159cd3a1...
Commit: ea14d5159cd3a196c0754f4e37539dee1eb2d169
Parent: 72d82e21d44c48a3823156afa900eb071b3eb144
Author: Petr Rockai <prockai(a)redhat.com>
AuthorDate: Sat Aug 11 10:33:53 2012 +0200
Committer: Petr Rockai <prockai(a)redhat.com>
CommitterDate: Wed Sep 26 14:49:09 2012 +0200
libdaemon: Extend and refactor APIs.
- move common dm_config_tree manipulation functions from lvmetad-core to
daemon-shared
- add config-tree-based request manipulation APIs to daemon-client
- factor out _v (va_list) variants of most variadic functions in libdaemon
---
daemons/lvmetad/lvmetad-core.c | 123 --------------------
lib/config/config.c | 1 +
libdaemon/client/daemon-client.c | 74 +++++++++++--
libdaemon/client/daemon-client.h | 6 +
libdaemon/client/daemon-shared.c | 232 +++++++++++++++++++++++++++++++++++++-
libdaemon/client/daemon-shared.h | 38 ++++++-
libdaemon/server/daemon-server.c | 45 +++-----
7 files changed, 354 insertions(+), 165 deletions(-)
diff --git a/daemons/lvmetad/lvmetad-core.c b/daemons/lvmetad/lvmetad-core.c
index 146ee69..c96e285 100644
--- a/daemons/lvmetad/lvmetad-core.c
+++ b/daemons/lvmetad/lvmetad-core.c
@@ -107,129 +107,6 @@ static struct dm_config_node *pvs(struct dm_config_node *vg)
return pv;
}
-/*
- * TODO: This set_flag function is pretty generic and might make sense in a
- * library here or there.
- */
-static int set_flag(struct dm_config_tree *cft, struct dm_config_node *parent,
- const char *field, const char *flag, int want) {
- struct dm_config_value *value = NULL, *pred = NULL;
- struct dm_config_node *node = dm_config_find_node(parent->child, field);
- struct dm_config_value *new;
-
- if (node)
- value = node->v;
-
- while (value && value->type != DM_CFG_EMPTY_ARRAY && strcmp(value->v.str, flag)) {
- pred = value;
- value = value->next;
- }
-
- if (value && want)
- return 1;
-
- if (!value && !want)
- return 1;
-
- if (value && !want) {
- if (pred) {
- pred->next = value->next;
- } else if (value == node->v && value->next) {
- node->v = value->next;
- } else {
- node->v->type = DM_CFG_EMPTY_ARRAY;
- }
- }
-
- if (!value && want) {
- if (!node) {
- if (!(node = dm_config_create_node(cft, field)))
- return 0;
- node->sib = parent->child;
- if (!(node->v = dm_config_create_value(cft)))
- return 0;
- node->v->type = DM_CFG_EMPTY_ARRAY;
- node->parent = parent;
- parent->child = node;
- }
- if (!(new = dm_config_create_value(cft))) {
- /* FIXME error reporting */
- return 0;
- }
- new->type = DM_CFG_STRING;
- new->v.str = flag;
- new->next = node->v;
- node->v = new;
- }
-
- return 1;
-}
-
-static struct dm_config_node *make_config_node(struct dm_config_tree *cft,
- const char *key,
- struct dm_config_node *parent,
- struct dm_config_node *pre_sib)
-{
- struct dm_config_node *cn;
-
- if (!(cn = dm_config_create_node(cft, key)))
- return NULL;
-
- cn->parent = parent;
- cn->sib = NULL;
- cn->v = NULL;
- cn->child = NULL;
-
- if (parent && parent->child && !pre_sib) { /* find the last one */
- pre_sib = parent->child;
- while (pre_sib && pre_sib->sib)
- pre_sib = pre_sib->sib;
- }
-
- if (parent && !parent->child)
- parent->child = cn;
- if (pre_sib)
- pre_sib->sib = cn;
-
- return cn;
-}
-
-static struct dm_config_node *make_text_node(struct dm_config_tree *cft,
- const char *key,
- const char *value,
- struct dm_config_node *parent,
- struct dm_config_node *pre_sib)
-{
- struct dm_config_node *cn;
-
- if (!(cn = make_config_node(cft, key, parent, pre_sib)) ||
- !(cn->v = dm_config_create_value(cft)))
- return NULL;
-
- cn->v->type = DM_CFG_STRING;
- cn->v->v.str = value;
- return cn;
-}
-
-#if 0
-static struct dm_config_node *make_int_node(struct dm_config_tree *cft,
- const char *key,
- int64_t value,
- struct dm_config_node *parent,
- struct dm_config_node *pre_sib)
-{
- struct dm_config_node *cn;
-
- if (!(cn = make_config_node(cft, key, parent, pre_sib)) ||
- !(cn->v = dm_config_create_value(cft)))
- return NULL;
-
- cn->v->type = DM_CFG_INT;
- cn->v->v.i = value;
- return cn;
-}
-#endif
-
static void filter_metadata(struct dm_config_node *vg) {
struct dm_config_node *pv = pvs(vg);
while (pv) {
diff --git a/lib/config/config.c b/lib/config/config.c
index a7bda97..00bfcab 100644
--- a/lib/config/config.c
+++ b/lib/config/config.c
@@ -489,3 +489,4 @@ int config_write(struct dm_config_tree *cft, const char *file,
return r;
}
+
diff --git a/libdaemon/client/daemon-client.c b/libdaemon/client/daemon-client.c
index 6aad75c..0ade329 100644
--- a/libdaemon/client/daemon-client.c
+++ b/libdaemon/client/daemon-client.c
@@ -72,9 +72,8 @@ daemon_reply daemon_send(daemon_handle h, daemon_request rq)
daemon_reply reply = { .cft = NULL, .error = 0 };
assert(h.socket_fd >= 0);
- if (!rq.buffer) {
- /* TODO: build the buffer from rq.cft */
- }
+ if (!rq.buffer)
+ dm_config_write_node(rq.cft->root, buffer_line, &rq.buffer);
assert(rq.buffer);
if (!write_buffer(h.socket_fd, rq.buffer, strlen(rq.buffer)))
@@ -94,16 +93,19 @@ void daemon_reply_destroy(daemon_reply r) {
dm_free(r.buffer);
}
-daemon_reply daemon_send_simple(daemon_handle h, const char *id, ...)
+daemon_reply daemon_send_simple_v(daemon_handle h, const char *id, va_list ap)
{
static const daemon_reply err = { .error = ENOMEM, .buffer = NULL, .cft = NULL };
daemon_request rq = { .cft = NULL };
daemon_reply repl;
- va_list ap;
+ char *rq_line;
- va_start(ap, id);
- rq.buffer = format_buffer("request", id, ap);
- va_end(ap);
+ rq_line = format_buffer("", "request = %s", id, NULL);
+ if (!rq_line)
+ return err;
+
+ rq.buffer = format_buffer_v(rq_line, ap);
+ dm_free(rq_line);
if (!rq.buffer)
return err;
@@ -114,7 +116,63 @@ daemon_reply daemon_send_simple(daemon_handle h, const char *id, ...)
return repl;
}
+daemon_reply daemon_send_simple(daemon_handle h, const char *id, ...)
+{
+ va_list ap;
+ va_start(ap, id);
+ daemon_reply r = daemon_send_simple_v(h, id, ap);
+ va_end(ap);
+ return r;
+}
+
void daemon_close(daemon_handle h)
{
dm_free((char *)h.protocol);
}
+
+daemon_request daemon_request_make(const char *id)
+{
+ daemon_request r;
+ r.cft = NULL;
+ r.buffer = NULL;
+
+ if (!(r.cft = dm_config_create()))
+ goto bad;
+
+ if (!(r.cft->root = make_text_node(r.cft, "request", id, NULL, NULL)))
+ goto bad;
+
+ return r;
+bad:
+ if (r.cft)
+ dm_config_destroy(r.cft);
+ r.cft = NULL;
+ return r;
+}
+
+int daemon_request_extend_v(daemon_request r, va_list ap)
+{
+ if (!r.cft)
+ return 0;
+
+ if (!config_make_nodes_v(r.cft, NULL, r.cft->root, ap))
+ return 0;
+
+ return 1;
+}
+
+int daemon_request_extend(daemon_request r, ...)
+{
+ va_list ap;
+ va_start(ap, r);
+ int res = daemon_request_extend_v(r, ap);
+ va_end(ap);
+ return res;
+}
+
+void daemon_request_destroy(daemon_request r) {
+ if (r.cft)
+ dm_config_destroy(r.cft);
+ dm_free(r.buffer);
+}
+
diff --git a/libdaemon/client/daemon-client.h b/libdaemon/client/daemon-client.h
index 15fef70..2863d03 100644
--- a/libdaemon/client/daemon-client.h
+++ b/libdaemon/client/daemon-client.h
@@ -87,6 +87,12 @@ daemon_reply daemon_send(daemon_handle h, daemon_request r);
* for ? in %?: d for integer, s for string.
*/
daemon_reply daemon_send_simple(daemon_handle h, const char *id, ...);
+daemon_reply daemon_send_simple_v(daemon_handle h, const char *id, va_list ap);
+
+daemon_request daemon_request_make(const char *id);
+int daemon_request_extend(daemon_request r, ...);
+int daemon_request_extend_v(daemon_request r, va_list ap);
+void daemon_request_destroy(daemon_request r);
void daemon_reply_destroy(daemon_reply r);
diff --git a/libdaemon/client/daemon-shared.c b/libdaemon/client/daemon-shared.c
index b767794..40c02b0 100644
--- a/libdaemon/client/daemon-shared.c
+++ b/libdaemon/client/daemon-shared.c
@@ -17,8 +17,8 @@
#include <malloc.h>
#include <string.h>
#include <unistd.h>
-#include <assert.h>
+#include "dm-logging.h"
#include "daemon-shared.h"
#include "libdevmapper.h"
@@ -99,18 +99,21 @@ write:
goto write;
}
-char *format_buffer(const char *what, const char *id, va_list ap)
+char *format_buffer_v(const char *head, va_list ap)
{
char *buffer, *old;
char *next;
int keylen;
- dm_asprintf(&buffer, "%s = \"%s\"\n", what, id);
+ dm_asprintf(&buffer, "%s", head);
if (!buffer) goto fail;
while ((next = va_arg(ap, char *))) {
old = buffer;
- assert(strchr(next, '='));
+ if (!strchr(next, '=')) {
+ log_error(INTERNAL_ERROR "Bad format string at '%s'", next);
+ goto fail;
+ }
keylen = strchr(next, '=') - next;
if (strstr(next, "%d")) {
int value = va_arg(ap, int);
@@ -138,3 +141,224 @@ fail:
dm_free(buffer);
return NULL;
}
+
+char *format_buffer(const char *head, ...)
+{
+ va_list ap;
+ va_start(ap, head);
+ char *res = format_buffer_v(head, ap);
+ va_end(ap);
+ return res;
+}
+
+int set_flag(struct dm_config_tree *cft, struct dm_config_node *parent,
+ const char *field, const char *flag, int want)
+{
+ struct dm_config_value *value = NULL, *pred = NULL;
+ struct dm_config_node *node = dm_config_find_node(parent->child, field);
+ struct dm_config_value *new;
+
+ if (node)
+ value = node->v;
+
+ while (value && value->type != DM_CFG_EMPTY_ARRAY && strcmp(value->v.str, flag)) {
+ pred = value;
+ value = value->next;
+ }
+
+ if (value && want)
+ return 1;
+
+ if (!value && !want)
+ return 1;
+
+ if (value && !want) {
+ if (pred) {
+ pred->next = value->next;
+ } else if (value == node->v && value->next) {
+ node->v = value->next;
+ } else {
+ node->v->type = DM_CFG_EMPTY_ARRAY;
+ }
+ }
+
+ if (!value && want) {
+ if (!node) {
+ if (!(node = dm_config_create_node(cft, field)))
+ return 0;
+ node->sib = parent->child;
+ if (!(node->v = dm_config_create_value(cft)))
+ return 0;
+ node->v->type = DM_CFG_EMPTY_ARRAY;
+ node->parent = parent;
+ parent->child = node;
+ }
+ if (!(new = dm_config_create_value(cft))) {
+ /* FIXME error reporting */
+ return 0;
+ }
+ new->type = DM_CFG_STRING;
+ new->v.str = flag;
+ new->next = node->v;
+ node->v = new;
+ }
+
+ return 1;
+}
+
+static void chain_node(struct dm_config_node *cn,
+ struct dm_config_node *parent,
+ struct dm_config_node *pre_sib)
+{
+ cn->parent = parent;
+ cn->sib = NULL;
+
+ if (parent && parent->child && !pre_sib) { /* find the last one */
+ pre_sib = parent->child;
+ while (pre_sib && pre_sib->sib)
+ pre_sib = pre_sib->sib;
+ }
+
+ if (parent && !parent->child)
+ parent->child = cn;
+ if (pre_sib)
+ pre_sib->sib = cn;
+
+}
+
+struct dm_config_node *make_config_node(struct dm_config_tree *cft,
+ const char *key,
+ struct dm_config_node *parent,
+ struct dm_config_node *pre_sib)
+{
+ struct dm_config_node *cn;
+
+ if (!(cn = dm_config_create_node(cft, key)))
+ return NULL;
+
+ cn->v = NULL;
+ cn->child = NULL;
+
+ chain_node(cn, parent, pre_sib);
+
+ return cn;
+}
+
+struct dm_config_node *make_text_node(struct dm_config_tree *cft,
+ const char *key,
+ const char *value,
+ struct dm_config_node *parent,
+ struct dm_config_node *pre_sib)
+{
+ struct dm_config_node *cn;
+
+ if (!(cn = make_config_node(cft, key, parent, pre_sib)) ||
+ !(cn->v = dm_config_create_value(cft)))
+ return NULL;
+
+ cn->v->type = DM_CFG_STRING;
+ cn->v->v.str = value;
+ return cn;
+}
+
+struct dm_config_node *make_int_node(struct dm_config_tree *cft,
+ const char *key,
+ int64_t value,
+ struct dm_config_node *parent,
+ struct dm_config_node *pre_sib)
+{
+ struct dm_config_node *cn;
+
+ if (!(cn = make_config_node(cft, key, parent, pre_sib)) ||
+ !(cn->v = dm_config_create_value(cft)))
+ return NULL;
+
+ cn->v->type = DM_CFG_INT;
+ cn->v->v.i = value;
+ return cn;
+}
+
+struct dm_config_node *config_make_nodes_v(struct dm_config_tree *cft,
+ struct dm_config_node *parent,
+ struct dm_config_node *pre_sib,
+ va_list ap)
+{
+ const char *next;
+ struct dm_config_node *first = NULL;
+
+ while ((next = va_arg(ap, char *))) {
+ struct dm_config_node *cn = NULL;
+ const char *fmt = strchr(next, '=');
+
+ if (!fmt) {
+ log_error(INTERNAL_ERROR "Bad format string '%s'", fmt);
+ return_NULL;
+ }
+ fmt += 2;
+
+ char *key = dm_pool_strdup(cft->mem, next);
+ *strchr(key, '=') = 0;
+
+ if (!strcmp(fmt, "%d")) {
+ int64_t value = va_arg(ap, int64_t);
+ if (!(cn = make_int_node(cft, key, value, parent, pre_sib)))
+ return 0;
+ } else if (!strcmp(fmt, "%s")) {
+ char *value = va_arg(ap, char *);
+ if (!(cn = make_text_node(cft, key, value, parent, pre_sib)))
+ return 0;
+ } else if (!strcmp(fmt, "%t")) {
+ struct dm_config_tree *tree = va_arg(ap, struct dm_config_tree *);
+ cn = dm_config_clone_node(cft, tree->root, 1);
+ if (!cn)
+ return 0;
+ cn->key = key;
+ chain_node(cn, parent, pre_sib);
+ } else {
+ log_error(INTERNAL_ERROR "Bad format string '%s'", fmt);
+ return_NULL;
+ }
+ if (!first)
+ first = cn;
+ if (cn)
+ pre_sib = cn;
+ }
+
+ return first;
+}
+
+struct dm_config_node *config_make_nodes(struct dm_config_tree *cft,
+ struct dm_config_node *parent,
+ struct dm_config_node *pre_sib,
+ ...)
+{
+ va_list ap;
+ va_start(ap, pre_sib);
+ struct dm_config_node *res = config_make_nodes_v(cft, parent, pre_sib, ap);
+ va_end(ap);
+ return res;
+}
+
+int buffer_rewrite(char **buf, const char *format, const char *string)
+{
+ char *old = *buf;
+ int r = dm_asprintf(buf, format, *buf, string);
+
+ dm_free(old);
+
+ return (r < 0) ? 0 : 1;
+}
+
+int buffer_line(const char *line, void *baton)
+{
+ char **buffer = baton;
+
+ if (*buffer) {
+ if (!buffer_rewrite(buffer, "%s\n%s", line))
+ return 0;
+ } else if (dm_asprintf(buffer, "%s\n", line) < 0)
+ return 0;
+
+ return 1;
+}
+
diff --git a/libdaemon/client/daemon-shared.h b/libdaemon/client/daemon-shared.h
index 3e5fa9c..acb71c6 100644
--- a/libdaemon/client/daemon-shared.h
+++ b/libdaemon/client/daemon-shared.h
@@ -16,15 +16,51 @@
#define _LVM_DAEMON_SHARED_H
#include "configure.h"
+#include "libdevmapper.h"
#define _REENTRANT
#define _GNU_SOURCE
#define _FILE_OFFSET_BITS 64
+/* TODO function names */
+
#include <stdarg.h>
int read_buffer(int fd, char **buffer);
int write_buffer(int fd, const char *buffer, int length);
-char *format_buffer(const char *what, const char *id, va_list ap);
+char *format_buffer_v(const char *head, va_list ap);
+char *format_buffer(const char *head, ...);
+
+int buffer_line(const char *line, void *baton);
+int buffer_rewrite(char **buf, const char *format, const char *string);
+
+int set_flag(struct dm_config_tree *cft, struct dm_config_node *parent,
+ const char *field, const char *flag, int want);
+
+struct dm_config_node *make_config_node(struct dm_config_tree *cft,
+ const char *key,
+ struct dm_config_node *parent,
+ struct dm_config_node *pre_sib);
+
+struct dm_config_node *make_text_node(struct dm_config_tree *cft,
+ const char *key,
+ const char *value,
+ struct dm_config_node *parent,
+ struct dm_config_node *pre_sib);
+
+struct dm_config_node *make_int_node(struct dm_config_tree *cft,
+ const char *key,
+ int64_t value,
+ struct dm_config_node *parent,
+ struct dm_config_node *pre_sib);
+
+struct dm_config_node *config_make_nodes_v(struct dm_config_tree *cft,
+ struct dm_config_node *parent,
+ struct dm_config_node *pre_sib,
+ va_list ap);
+struct dm_config_node *config_make_nodes(struct dm_config_tree *cft,
+ struct dm_config_node *parent,
+ struct dm_config_node *pre_sib,
+ ...);
#endif /* _LVM_DAEMON_SHARED_H */
diff --git a/libdaemon/server/daemon-server.c b/libdaemon/server/daemon-server.c
index ef26cbc..76627c0 100644
--- a/libdaemon/server/daemon-server.c
+++ b/libdaemon/server/daemon-server.c
@@ -329,14 +329,23 @@ response daemon_reply_simple(const char *id, ...)
{
va_list ap;
response res = { .cft = NULL };
+ char *res_line = NULL;
va_start(ap, id);
- if (!(res.buffer = format_buffer("response", id, ap)))
+ if (!(res_line = format_buffer("", "response = %s", id, NULL))) {
res.error = ENOMEM;
+ goto end;
+ }
- va_end(ap);
+ if (!(res.buffer = format_buffer_v(res_line, ap))) {
+ res.error = ENOMEM;
+ goto end;
+ }
+end:
+ dm_free(res_line);
+ va_end(ap);
return res;
}
@@ -345,27 +354,6 @@ struct thread_baton {
client_handle client;
};
-static int buffer_rewrite(char **buf, const char *format, const char *string) {
- char *old = *buf;
- int r = dm_asprintf(buf, format, *buf, string);
-
- dm_free(old);
-
- return (r < 0) ? 0 : 1;
-}
-
-static int buffer_line(const char *line, void *baton) {
- response *r = baton;
-
- if (r->buffer) {
- if (!buffer_rewrite(&r->buffer, "%s\n%s", line))
- return 0;
- } else if (dm_asprintf(&r->buffer, "%s\n", line) < 0)
- return 0;
-
- return 1;
-}
-
static response builtin_handler(daemon_state s, client_handle h, request r)
{
const char *rq = daemon_request_str(r, "request", "NONE");
@@ -382,7 +370,7 @@ static response builtin_handler(daemon_state s, client_handle h, request r)
static void *client_thread(void *baton)
{
struct thread_baton *b = baton;
- request req;
+ request req = { .buffer = NULL };
response res;
while (1) {
@@ -402,11 +390,9 @@ static void *client_thread(void *baton)
res = b->s.handler(b->s, b->client, req);
if (!res.buffer) {
- dm_config_write_node(res.cft->root, buffer_line, &res);
- if (!buffer_rewrite(&res.buffer, "%s\n\n", NULL)) {
- dm_free(req.buffer);
+ dm_config_write_node(res.cft->root, buffer_line, &res.buffer);
+ if (!buffer_rewrite(&res.buffer, "%s\n\n", NULL))
goto fail;
- }
dm_config_destroy(res.cft);
}
@@ -423,7 +409,8 @@ fail:
/* TODO what should we really do here? */
if (close(b->client.socket_fd))
perror("close");
- free(baton);
+ dm_free(req.buffer);
+ dm_free(baton);
return NULL;
}
11 years, 6 months