summaryrefslogtreecommitdiffstats
path: root/daemons/lvmetad/lvmetad-core.c
diff options
context:
space:
mode:
authorPetr Rockai <prockai@redhat.com>2012-02-15 17:30:07 +0000
committerPetr Rockai <prockai@redhat.com>2012-02-15 17:30:07 +0000
commitff455b1806009a3e8f9254354daddff9c60825cb (patch)
treed1eefa7230b6a03b1d3ff00dbf2f3c6d7967bea5 /daemons/lvmetad/lvmetad-core.c
parentd81498a824e66acca994807643e9df1e452fd61c (diff)
downloadlvm2-ff455b1806009a3e8f9254354daddff9c60825cb.tar.gz
lvm2-ff455b1806009a3e8f9254354daddff9c60825cb.tar.xz
lvm2-ff455b1806009a3e8f9254354daddff9c60825cb.zip
Update lvmetad: use device major/minor pair to track devices. Keep a pvmeta
config tree per PV which is mostly provided by the client, so it can be used to keep track of things like label_sector, PV format, mda count / offsets and so on.
Diffstat (limited to 'daemons/lvmetad/lvmetad-core.c')
-rw-r--r--daemons/lvmetad/lvmetad-core.c197
1 files changed, 118 insertions, 79 deletions
diff --git a/daemons/lvmetad/lvmetad-core.c b/daemons/lvmetad/lvmetad-core.c
index 4573db62..f54a711b 100644
--- a/daemons/lvmetad/lvmetad-core.c
+++ b/daemons/lvmetad/lvmetad-core.c
@@ -12,14 +12,10 @@
#include "daemon-server.h"
typedef struct {
- const char *path;
- dev_t number;
-} device; /* TODO */
-
-typedef struct {
struct dm_hash_table *pvid_to_status;
- struct dm_hash_table *pvid_to_device; /* shares locks with status */
+ struct dm_hash_table *pvid_to_pvmeta; /* shares locks with status */
struct dm_hash_table *device_to_pvid; /* shares locks with status */
+
struct dm_hash_table *vgid_to_metadata;
struct dm_hash_table *vgid_to_vgname;
struct dm_hash_table *vgname_to_vgid;
@@ -164,6 +160,56 @@ static int set_flag(struct dm_config_tree *cft, struct dm_config_node *parent,
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 = dm_config_create_node(cft, key);
+ 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 = make_config_node(cft, key, parent, pre_sib);
+ cn->v = dm_config_create_value(cft);
+ cn->v->type = DM_CFG_STRING;
+ cn->v->v.str = value;
+ return cn;
+}
+
+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 = make_config_node(cft, key, parent, pre_sib);
+ cn->v = dm_config_create_value(cft);
+ cn->v->type = DM_CFG_INT;
+ cn->v->v.i = value;
+ return cn;
+}
+
static void filter_metadata(struct dm_config_node *vg) {
struct dm_config_node *pv = pvs(vg);
while (pv) {
@@ -195,16 +241,12 @@ static int update_pv_status(lvmetad_state *s,
int found = uuid ? (dm_hash_lookup(s->pvid_to_status, uuid) ? 1 : 0) : 0;
if (act) {
set_flag(cft, pv, "status", "MISSING", !found);
- const char *devpath = dm_hash_lookup(s->pvid_to_device, uuid);
- // debug("setting device of %s to %s\n", uuid, devpath);
- if (devpath) {
- struct dm_config_node *dev = dm_config_create_node(cft, "device");
- dev->sib = pv->child;
- dev->v = dm_config_create_value(cft);
- dev->v->type = DM_CFG_STRING;
- dev->v->v.str = dm_hash_lookup(s->pvid_to_device, uuid);
- dev->parent = pv;
- pv->child = dev;
+ struct dm_config_tree *pvmeta = dm_hash_lookup(s->pvid_to_pvmeta, uuid);
+ if (pvmeta) {
+ // debug_cft("PV META", pvmeta->root);
+ make_int_node(cft, "device",
+ dm_config_find_int(pvmeta->root, "pvmeta/device", 0),
+ pv, NULL);
}
}
if (!found) {
@@ -221,46 +263,16 @@ static int update_pv_status(lvmetad_state *s,
return complete;
}
-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 = dm_config_create_node(cft, key);
- cn->parent = parent;
- cn->sib = NULL;
- cn->v = NULL;
- cn->child = NULL;
-
- 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 = make_config_node(cft, key, parent, pre_sib);
- cn->v = dm_config_create_value(cft);
- cn->v->type = DM_CFG_STRING;
- cn->v->v.str = value;
- return cn;
-}
-
static struct dm_config_node *make_pv_node(lvmetad_state *s, const char *pvid,
struct dm_config_tree *cft,
struct dm_config_node *parent,
struct dm_config_node *pre_sib)
{
- const char *path = dm_hash_lookup(s->pvid_to_device, pvid),
- *vgid = dm_hash_lookup(s->pvid_to_vgid, pvid),
- *vgname = NULL;
+ struct dm_config_tree *pvmeta = dm_hash_lookup(s->pvid_to_pvmeta, pvid);
+ const char *vgid = dm_hash_lookup(s->pvid_to_vgid, pvid), *vgname = NULL;
+
+ if (!pvmeta)
+ return NULL;
if (vgid) {
lock_vgid_to_metadata(s); // XXX
@@ -268,11 +280,17 @@ static struct dm_config_node *make_pv_node(lvmetad_state *s, const char *pvid,
unlock_vgid_to_metadata(s);
}
- struct dm_config_node *pv = make_config_node(cft, pvid, parent, pre_sib), *cn = NULL;
+ /* Nick the pvmeta config tree. */
+ struct dm_config_node *pv = dm_config_clone_node(cft, pvmeta->root, 0);
+ if (pre_sib)
+ pre_sib->sib = pv;
+ if (parent && !parent->child)
+ parent->child = pv;
+ pv->parent = parent;
+
+ /* Add the "variable" bits to it. */
+ struct dm_config_node *cn = NULL;
- cn = make_text_node(cft, "id", pvid, pv, cn);
- if (path)
- cn = make_text_node(cft, "path", path, pv, cn);
if (vgid && strcmp(vgid, "#orphan"))
cn = make_text_node(cft, "vgid", vgid, pv, cn);
if (vgname)
@@ -293,16 +311,16 @@ static response pv_list(lvmetad_state *s, request r)
lock_pvid_to_status(s);
- struct dm_hash_node *n = dm_hash_get_first(s->pvid_to_device);
+ struct dm_hash_node *n = dm_hash_get_first(s->pvid_to_pvmeta);
while (n) {
- const char *id = dm_hash_get_key(s->pvid_to_device, n);
+ const char *id = dm_hash_get_key(s->pvid_to_pvmeta, n);
cn = make_pv_node(s, id, res.cft, cn_pvs, cn);
- n = dm_hash_get_next(s->pvid_to_device, n);
+ n = dm_hash_get_next(s->pvid_to_pvmeta, n);
}
unlock_pvid_to_status(s);
- debug_cft("PV LIST", res.cft->root);
+ // debug_cft("PV LIST", res.cft->root);
return res;
}
@@ -321,6 +339,11 @@ static response pv_lookup(lvmetad_state *s, request r)
lock_pvid_to_status(s);
pv = make_pv_node(s, pvid, res.cft, NULL, res.cft->root);
+ if (!pv) {
+ unlock_pvid_to_status(s);
+ return daemon_reply_simple("failed", "reason = %s", "PV not found", NULL);
+ }
+
pv->key = "physical_volume";
unlock_pvid_to_status(s);
@@ -672,54 +695,70 @@ out:
static response pv_gone(lvmetad_state *s, request r)
{
int found = 0;
- const char *pvid = daemon_request_str(r, "uuid", NULL),
- *dev = daemon_request_str(r, "device", NULL);
+ const char *pvid = daemon_request_str(r, "uuid", NULL);
+ int64_t device = daemon_request_int(r, "device", 0);
- debug("pv_gone: %s / %s\n", pvid, dev);
+ debug("pv_gone: %s / %lld\n", pvid, device);
+ debug_cft("PV_GONE", r.cft->root);
lock_pvid_to_status(s);
- if (!pvid && dev)
- pvid = dm_hash_lookup(s->device_to_pvid, dev);
+ if (!pvid && device > 0)
+ pvid = dm_hash_lookup_binary(s->device_to_pvid, &device, sizeof(device));
if (!pvid) {
unlock_pvid_to_status(s);
return daemon_reply_simple("failed", "reason = %s", "device not in cache", NULL);
}
- debug("pv_gone (updated): %s / %s\n", pvid, dev);
+ debug("pv_gone (updated): %s / %lld\n", pvid, device);
- found = dm_hash_lookup(s->pvid_to_status, pvid) ? 1 : 0;
+ struct dm_config_tree *pvmeta = dm_hash_lookup(s->pvid_to_pvmeta, pvid);
+ dm_hash_remove_binary(s->device_to_pvid, &device, sizeof(device));
dm_hash_remove(s->pvid_to_status, pvid);
- dm_hash_remove(s->pvid_to_device, pvid);
-
+ dm_hash_remove(s->pvid_to_pvmeta, pvid);
vg_remove_if_missing(s, dm_hash_lookup(s->pvid_to_vgid, pvid));
unlock_pvid_to_status(s);
- if (found)
+ if (pvmeta) {
+ dm_config_destroy(pvmeta);
return daemon_reply_simple("OK", NULL);
- else
+ } else
return daemon_reply_simple("failed", "reason = %s", "PVID does not exist", NULL);
}
static response pv_found(lvmetad_state *s, request r)
{
struct dm_config_node *metadata = dm_config_find_node(r.cft->root, "metadata");
- const char *pvid = daemon_request_str(r, "uuid", NULL);
+ const char *pvid = daemon_request_str(r, "pvmeta/id", NULL);
const char *vgname = daemon_request_str(r, "vgname", NULL);
- const char *devpath = dm_strdup(daemon_request_str(r, "device", NULL));
const char *vgid = daemon_request_str(r, "metadata/id", NULL);
+ struct dm_config_node *pvmeta = dm_config_find_node(r.cft->root, "pvmeta");
+ uint64_t device;
+
int complete = 0, orphan = 0;
+ // debug_cft("INCOMING PV", r.cft->root);
+
if (!pvid)
return daemon_reply_simple("failed", "reason = %s", "need PV UUID", NULL);
- if (!devpath)
- return daemon_reply_simple("failed", "reason = %s", "need PV device", NULL);
+ if (!pvmeta)
+ return daemon_reply_simple("failed", "reason = %s", "need PV metadata", NULL);
+
+ if (!dm_config_get_uint64(pvmeta, "pvmeta/device", &device))
+ return daemon_reply_simple("failed", "reason = %s", "need PV device number", NULL);
- debug("pv_found %s, vgid = %s, device = %s\n", pvid, vgid, devpath);
+ debug("pv_found %s, vgid = %s, device = %lld\n", pvid, vgid, device);
lock_pvid_to_status(s);
dm_hash_insert(s->pvid_to_status, pvid, (void*)1);
- dm_hash_insert(s->pvid_to_device, pvid, (void*)devpath);
- dm_hash_insert(s->device_to_pvid, devpath, (void*)dm_strdup(pvid));
+
+ {
+ struct dm_config_tree *cft = dm_config_create();
+ cft->root = dm_config_clone_node(cft, pvmeta, 0);
+ const char *pvid_dup = dm_config_find_str(cft->root, "pvmeta/id", NULL);
+ 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_status(s);
if (metadata) {
@@ -842,7 +881,7 @@ static int init(daemon_state *s)
lvmetad_state *ls = s->private;
ls->pvid_to_status = dm_hash_create(32);
- ls->pvid_to_device = dm_hash_create(32);
+ 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);
@@ -885,7 +924,7 @@ static int fini(daemon_state *s)
dm_hash_destroy(ls->lock.vg);
dm_hash_destroy(ls->pvid_to_status);
- dm_hash_destroy(ls->pvid_to_device);
+ 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->pvid_to_vgid);