mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
lvmetad: Maintain info about outdated PVs.
This commit is contained in:
parent
f3c7bd4004
commit
925268794f
@ -40,6 +40,7 @@ typedef struct {
|
||||
|
||||
struct dm_hash_table *vgid_to_metadata;
|
||||
struct dm_hash_table *vgid_to_vgname;
|
||||
struct dm_hash_table *vgid_to_outdated_pvs;
|
||||
struct dm_hash_table *vgname_to_vgid;
|
||||
struct dm_hash_table *pvid_to_vgid;
|
||||
struct {
|
||||
@ -66,6 +67,7 @@ static void destroy_metadata_hashes(lvmetad_state *s)
|
||||
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->vgid_to_outdated_pvs);
|
||||
dm_hash_destroy(s->vgname_to_vgid);
|
||||
|
||||
dm_hash_destroy(s->device_to_pvid);
|
||||
@ -78,6 +80,7 @@ static void create_metadata_hashes(lvmetad_state *s)
|
||||
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->vgid_to_outdated_pvs = dm_hash_create(32);
|
||||
s->pvid_to_vgid = dm_hash_create(32);
|
||||
s->vgname_to_vgid = dm_hash_create(32);
|
||||
}
|
||||
@ -420,6 +423,54 @@ bad:
|
||||
return res;
|
||||
}
|
||||
|
||||
static void mark_outdated_pv(lvmetad_state *s, const char *vgid, const char *pvid)
|
||||
{
|
||||
struct dm_config_tree *pvmeta, *outdated_pvs;
|
||||
struct dm_config_node *list, *cft_vgid;
|
||||
struct dm_config_value *v;
|
||||
|
||||
lock_pvid_to_pvmeta(s);
|
||||
pvmeta = dm_hash_lookup(s->pvid_to_pvmeta, pvid);
|
||||
unlock_pvid_to_pvmeta(s);
|
||||
|
||||
/* if the MDA exists and is used, it will have ignore=0 set */
|
||||
if (!pvmeta ||
|
||||
(dm_config_find_int64(pvmeta->root, "pvmeta/mda0/ignore", 1) &&
|
||||
dm_config_find_int64(pvmeta->root, "pvmeta/mda1/ignore", 1)))
|
||||
return;
|
||||
|
||||
WARN(s, "PV %s has outdated metadata", pvid);
|
||||
|
||||
outdated_pvs = dm_hash_lookup(s->vgid_to_outdated_pvs, vgid);
|
||||
if (!outdated_pvs) {
|
||||
if (!(outdated_pvs = dm_config_from_string("outdated_pvs/pv_list = []")) ||
|
||||
!(cft_vgid = make_text_node(outdated_pvs, "vgid", dm_pool_strdup(outdated_pvs->mem, vgid),
|
||||
outdated_pvs->root, NULL)))
|
||||
abort();
|
||||
if(!dm_hash_insert(s->vgid_to_outdated_pvs, cft_vgid->v->v.str, outdated_pvs))
|
||||
abort();
|
||||
DEBUGLOG(s, "created outdated_pvs list for VG %s", vgid);
|
||||
}
|
||||
|
||||
list = dm_config_find_node(outdated_pvs->root, "outdated_pvs/pv_list");
|
||||
v = list->v;
|
||||
while (v) {
|
||||
if (v->type != DM_CFG_EMPTY_ARRAY && !strcmp(v->v.str, pvid))
|
||||
return;
|
||||
v = v->next;
|
||||
}
|
||||
if (!(v = dm_config_create_value(outdated_pvs)))
|
||||
abort();
|
||||
v->type = DM_CFG_STRING;
|
||||
v->v.str = dm_pool_strdup(outdated_pvs->mem, pvid);
|
||||
v->next = list->v;
|
||||
list->v = v;
|
||||
}
|
||||
|
||||
static void chain_outdated_pvs(lvmetad_state *s, const char *vgid, struct dm_config_tree *metadata)
|
||||
{
|
||||
}
|
||||
|
||||
static response vg_lookup(lvmetad_state *s, request r)
|
||||
{
|
||||
struct dm_config_tree *cft;
|
||||
@ -486,6 +537,7 @@ static response vg_lookup(lvmetad_state *s, request r)
|
||||
unlock_vg(s, uuid);
|
||||
|
||||
update_pv_status(s, res.cft, n, 1); /* FIXME report errors */
|
||||
chain_outdated_pvs(s, uuid, res.cft);
|
||||
|
||||
return res;
|
||||
bad:
|
||||
@ -549,9 +601,11 @@ static int compare_config(struct dm_config_node *a, struct dm_config_node *b)
|
||||
|
||||
static int vg_remove_if_missing(lvmetad_state *s, const char *vgid, int update_pvids);
|
||||
|
||||
enum update_pvid_mode { UPDATE_ONLY, REMOVE_EMPTY, MARK_OUTDATED };
|
||||
|
||||
/* You need to be holding the pvid_to_vgid lock already to call this. */
|
||||
static int update_pvid_to_vgid(lvmetad_state *s, struct dm_config_tree *vg,
|
||||
const char *vgid, int nuke_empty)
|
||||
const char *vgid, int mode)
|
||||
{
|
||||
struct dm_config_node *pv;
|
||||
struct dm_hash_table *to_check;
|
||||
@ -571,11 +625,14 @@ static int update_pvid_to_vgid(lvmetad_state *s, struct dm_config_tree *vg,
|
||||
if (!(pvid = dm_config_find_str(pv->child, "id", NULL)))
|
||||
continue;
|
||||
|
||||
if (nuke_empty &&
|
||||
if (mode == REMOVE_EMPTY &&
|
||||
(vgid_old = dm_hash_lookup(s->pvid_to_vgid, pvid)) &&
|
||||
!dm_hash_insert(to_check, vgid_old, (void*) 1))
|
||||
goto out;
|
||||
|
||||
if (mode == MARK_OUTDATED)
|
||||
mark_outdated_pv(s, vgid, pvid);
|
||||
|
||||
if (!dm_hash_insert(s->pvid_to_vgid, pvid, (void*) vgid))
|
||||
goto out;
|
||||
|
||||
@ -599,10 +656,11 @@ static int update_pvid_to_vgid(lvmetad_state *s, struct dm_config_tree *vg,
|
||||
/* A pvid map lock needs to be held if update_pvids = 1. */
|
||||
static int remove_metadata(lvmetad_state *s, const char *vgid, int update_pvids)
|
||||
{
|
||||
struct dm_config_tree *old;
|
||||
struct dm_config_tree *old, *outdated_pvs;
|
||||
const char *oldname;
|
||||
lock_vgid_to_metadata(s);
|
||||
old = dm_hash_lookup(s->vgid_to_metadata, vgid);
|
||||
outdated_pvs = dm_hash_lookup(s->vgid_to_outdated_pvs, vgid);
|
||||
oldname = dm_hash_lookup(s->vgid_to_vgname, vgid);
|
||||
|
||||
if (!old) {
|
||||
@ -616,12 +674,15 @@ static int remove_metadata(lvmetad_state *s, const char *vgid, int update_pvids)
|
||||
dm_hash_remove(s->vgid_to_metadata, vgid);
|
||||
dm_hash_remove(s->vgid_to_vgname, vgid);
|
||||
dm_hash_remove(s->vgname_to_vgid, oldname);
|
||||
dm_hash_remove(s->vgid_to_outdated_pvs, vgid);
|
||||
unlock_vgid_to_metadata(s);
|
||||
|
||||
if (update_pvids)
|
||||
/* FIXME: What should happen when update fails */
|
||||
update_pvid_to_vgid(s, old, "#orphan", 0);
|
||||
dm_config_destroy(old);
|
||||
if (outdated_pvs)
|
||||
dm_config_destroy(outdated_pvs);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -665,7 +726,7 @@ static int vg_remove_if_missing(lvmetad_state *s, const char *vgid, int update_p
|
||||
* this function, so they can be safely destroyed after update_metadata returns
|
||||
* (anything that might have been retained is copied). */
|
||||
static int update_metadata(lvmetad_state *s, const char *name, const char *_vgid,
|
||||
struct dm_config_node *metadata, int64_t *oldseq)
|
||||
struct dm_config_node *metadata, int64_t *oldseq, const char *pvid)
|
||||
{
|
||||
struct dm_config_tree *cft = NULL;
|
||||
struct dm_config_tree *old;
|
||||
@ -714,6 +775,10 @@ static int update_metadata(lvmetad_state *s, const char *name, const char *_vgid
|
||||
|
||||
if (seq < haveseq) {
|
||||
DEBUGLOG(s, "Refusing to update metadata for %s (at %d) to %d", _vgid, haveseq, seq);
|
||||
|
||||
if (pvid)
|
||||
mark_outdated_pv(s, dm_config_find_str(old->root, "metadata/id", NULL), pvid);
|
||||
|
||||
/* TODO: notify the client that their metadata is out of date? */
|
||||
retval = 1;
|
||||
goto out;
|
||||
@ -736,6 +801,8 @@ static int update_metadata(lvmetad_state *s, const char *name, const char *_vgid
|
||||
|
||||
if (haveseq >= 0 && haveseq < seq) {
|
||||
INFO(s, "Updating metadata for %s at %d to %d", _vgid, haveseq, seq);
|
||||
if (oldseq)
|
||||
update_pvid_to_vgid(s, old, vgid, MARK_OUTDATED);
|
||||
/* temporarily orphan all of our PVs */
|
||||
update_pvid_to_vgid(s, old, "#orphan", 0);
|
||||
}
|
||||
@ -992,7 +1059,7 @@ out_of_mem:
|
||||
if (daemon_request_int(r, "metadata/seqno", -1) < 0)
|
||||
return reply_fail("need VG seqno");
|
||||
|
||||
if (!update_metadata(s, vgname, vgid, metadata, &seqno_old))
|
||||
if (!update_metadata(s, vgname, vgid, metadata, &seqno_old, pvid))
|
||||
return reply_fail("metadata update failed");
|
||||
changed |= (seqno_old != dm_config_find_int(metadata, "metadata/seqno", -1));
|
||||
} else {
|
||||
@ -1055,7 +1122,7 @@ static response vg_update(lvmetad_state *s, request r)
|
||||
|
||||
/* TODO defer metadata update here; add a separate vg_commit
|
||||
* call; if client does not commit, die */
|
||||
if (!update_metadata(s, vgname, vgid, metadata, NULL))
|
||||
if (!update_metadata(s, vgname, vgid, metadata, NULL, NULL))
|
||||
return reply_fail("metadata update failed");
|
||||
}
|
||||
return daemon_reply_simple("OK", NULL);
|
||||
@ -1136,6 +1203,9 @@ static response dump(lvmetad_state *s)
|
||||
buffer_append(b, "\n# VGID to VGNAME mapping\n\n");
|
||||
_dump_pairs(b, s->vgid_to_vgname, "vgid_to_vgname", 0);
|
||||
|
||||
buffer_append(b, "\n# VGID to outdated PVs mapping\n\n");
|
||||
_dump_cft(b, s->vgid_to_outdated_pvs, "outdated_pvs/vgid");
|
||||
|
||||
buffer_append(b, "\n# VGNAME to VGID mapping\n\n");
|
||||
_dump_pairs(b, s->vgname_to_vgid, "vgname_to_vgid", 0);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user