diff options
author | Petr Rockai <prockai@redhat.com> | 2012-02-15 17:30:07 +0000 |
---|---|---|
committer | Petr Rockai <prockai@redhat.com> | 2012-02-15 17:30:07 +0000 |
commit | ff455b1806009a3e8f9254354daddff9c60825cb (patch) | |
tree | d1eefa7230b6a03b1d3ff00dbf2f3c6d7967bea5 /daemons/lvmetad/lvmetad-core.c | |
parent | d81498a824e66acca994807643e9df1e452fd61c (diff) | |
download | lvm2-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.c | 197 |
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); |