diff --git a/daemons/clvmd/lvm-functions.c b/daemons/clvmd/lvm-functions.c index 3bb00d35f..34da66df9 100644 --- a/daemons/clvmd/lvm-functions.c +++ b/daemons/clvmd/lvm-functions.c @@ -903,7 +903,6 @@ int init_clvm(struct dm_hash_table *excl_uuid) return 0; } - cmd->is_clvmd = 1; cmd->cmd_line = "clvmd"; /* Check lvm.conf is setup for cluster-LVM */ diff --git a/lib/activate/activate.c b/lib/activate/activate.c index 2d00dc6d1..985215afb 100644 --- a/lib/activate/activate.c +++ b/lib/activate/activate.c @@ -2161,36 +2161,40 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s, if (lv && lv_pre) goto skip_read; - vg = lvmcache_get_saved_vg(vgid, 0); - vg_pre = lvmcache_get_saved_vg(vgid, 1); - - if (!vg || !vg_pre) { - log_debug("lv_suspend dropping both saved vgs and rereading"); - - lvmcache_drop_saved_vgid(vgid); - - vg = vg_read_by_vgid(cmd, vgid, 0); - vg_pre = vg_read_by_vgid(cmd, vgid, 1); - - if (!vg || !vg_pre) { - log_error("lv_suspend could not find vgid %.8s vg %p vg_pre %p", - vgid, vg, vg_pre); + if (!(vg = lvmcache_get_saved_vg(vgid, 0))) { + log_debug("lv_suspend did not find saved_vg %.8s so reading", vgid); + if (!(vg = vg_read_by_vgid(cmd, vgid, 0))) { + log_error("lv_suspend could not read vgid %.8s", vgid); goto out; } + log_debug("lv_suspend using read vg %s %d %p", vg->name, vg->seqno, vg); + } else { + log_debug("lv_suspend using saved_vg %s %d %p", vg->name, vg->seqno, vg); + } - /* - * Note that vg and vg_pre returned by vg_read_by_vgid will - * not be the same as saved_vg_old/saved_vg_new that would - * be returned by lvmcache_get_saved_vg() because the saved_vg's - * are copies of the vg struct that is created by _vg_read. - * (Should we grab and use the saved_vg to use here instead of - * the vg returned by vg_read_by_vgid?) - */ - - if ((vg->status & EXPORTED_VG) || (vg_pre->status & EXPORTED_VG)) { - log_error("Volume group \"%s\" is exported", vg->name); + if (!(vg_pre = lvmcache_get_saved_vg(vgid, 1))) { + log_debug("lv_suspend did not find pre saved_vg %.8s so reading", vgid); + if (!(vg_pre = vg_read_by_vgid(cmd, vgid, 1))) { + log_error("lv_suspend could not read pre vgid %.8s", vgid); goto out; } + log_debug("lv_suspend using pre read vg %s %d %p", vg_pre->name, vg_pre->seqno, vg_pre); + } else { + log_debug("lv_suspend using pre saved_vg %s %d %p", vg_pre->name, vg_pre->seqno, vg_pre); + } + + /* + * Note that vg and vg_pre returned by vg_read_by_vgid will + * not be the same as saved_vg_old/saved_vg_new that would + * be returned by lvmcache_get_saved_vg() because the saved_vg's + * are copies of the vg struct that is created by _vg_read. + * (Should we grab and use the saved_vg to use here instead of + * the vg returned by vg_read_by_vgid?) + */ + + if ((vg->status & EXPORTED_VG) || (vg_pre->status & EXPORTED_VG)) { + log_error("Volume group \"%s\" is exported", vg->name); + goto out; } lv = lv_to_free = find_lv_in_vg_by_lvid(vg, lvid); diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c index 9023bccc1..745e2196e 100644 --- a/lib/cache/lvmcache.c +++ b/lib/cache/lvmcache.c @@ -63,11 +63,12 @@ struct lvmcache_vginfo { int seqno; int independent_metadata_location; /* metadata read from independent areas */ int scan_summary_mismatch; /* vgsummary from devs had mismatching seqno or checksum */ +}; +struct saved_vg { /* - * The following are not related to lvmcache or vginfo, - * but are borrowing the vginfo to store the data. * saved_vg_* are used only by clvmd. + * It is not related to lvmcache or vginfo. * * For activation/deactivation, these are used to avoid * clvmd rereading a VG for each LV that is activated. @@ -83,26 +84,19 @@ struct lvmcache_vginfo { * * saved_vg_committed is set to 1 when clvmd gets * LCK_VG_COMMIT from vg_commit(). - * - * This data does not really belong in lvmcache, it's unrelated - * to lvmcache or vginfo, but it's just a convenient place - * for clvmd to stash the VG (since the same caller isn't - * present to pass the VG to both suspend and resume in the - * case of clvmd.) */ + char vgid[ID_LEN + 1]; int saved_vg_committed; - char *saved_vg_old_buf; - struct dm_config_tree *saved_vg_old_cft; struct volume_group *saved_vg_old; - char *saved_vg_new_buf; - struct dm_config_tree *saved_vg_new_cft; struct volume_group *saved_vg_new; + struct dm_list saved_vg_to_free; }; static struct dm_hash_table *_pvid_hash = NULL; static struct dm_hash_table *_vgid_hash = NULL; static struct dm_hash_table *_vgname_hash = NULL; static struct dm_hash_table *_lock_hash = NULL; +static struct dm_hash_table *_saved_vg_hash = NULL; static DM_LIST_INIT(_vginfos); static DM_LIST_INIT(_found_duplicate_devs); static DM_LIST_INIT(_unused_duplicate_devs); @@ -113,7 +107,7 @@ static int _vg_global_lock_held = 0; /* Global lock held when cache wiped? */ static int _found_duplicate_pvs = 0; /* If we never see a duplicate PV we can skip checking for them later. */ static int _suppress_lock_ordering = 0; -int lvmcache_init(void) +int lvmcache_init(struct cmd_context *cmd) { /* * FIXME add a proper lvmcache_locking_reset() that @@ -137,6 +131,11 @@ int lvmcache_init(void) if (!(_lock_hash = dm_hash_create(128))) return 0; + if (cmd->is_clvmd) { + if (!(_saved_vg_hash = dm_hash_create(128))) + return 0; + } + /* * Reinitialising the cache clears the internal record of * which locks are held. The global lock can be held during @@ -192,136 +191,205 @@ static void _update_cache_lock_state(const char *vgname, int locked) _update_cache_vginfo_lock_state(vginfo, locked); } -static void _saved_vg_free(struct lvmcache_vginfo *vginfo, int free_old, int free_new) +static struct saved_vg *_saved_vg_from_vgid(const char *vgid) { - if (free_old) { - if (vginfo->saved_vg_old) { - log_debug_cache("lvmcache: free saved_vg %s old %p", - vginfo->saved_vg_old->name, - vginfo->saved_vg_old); + struct saved_vg *svg; + char id[ID_LEN + 1] __attribute__((aligned(8))); - vginfo->saved_vg_old->saved_in_clvmd = 0; + /* vgid not necessarily NULL-terminated */ + (void) dm_strncpy(id, vgid, sizeof(id)); + + if (!(svg = dm_hash_lookup(_saved_vg_hash, id))) { + log_debug_cache("lvmcache: no saved_vg for vgid \"%s\"", id); + return NULL; + } + + return svg; +} + +static void _saved_vg_inval(struct saved_vg *svg, int inval_old, int inval_new) +{ + struct vg_list *vgl; + + /* + * In practice there appears to only ever be a single invalidated vg, + * so making saved_vg_to_free a list instead of a pointer is overkill. + * But, without proof otherwise, safer to keep the list. + */ + + if (inval_old && svg->saved_vg_old) { + log_debug_cache("lvmcache: inval saved_vg %s old %p", + svg->saved_vg_old->name, svg->saved_vg_old); + + if ((vgl = dm_zalloc(sizeof(*vgl)))) { + vgl->vg = svg->saved_vg_old; + dm_list_add(&svg->saved_vg_to_free, &vgl->list); } - if (vginfo->saved_vg_old_buf) - dm_free(vginfo->saved_vg_old_buf); - if (vginfo->saved_vg_old_cft) - dm_config_destroy(vginfo->saved_vg_old_cft); - if (vginfo->saved_vg_old) - release_vg(vginfo->saved_vg_old); + svg->saved_vg_old = NULL; + } - vginfo->saved_vg_old_buf = NULL; - vginfo->saved_vg_old_cft = NULL; - vginfo->saved_vg_old = NULL; + if (inval_new && svg->saved_vg_new) { + log_debug_cache("lvmcache: inval saved_vg %s new pre %p", + svg->saved_vg_new->name, svg->saved_vg_new); + + if ((vgl = dm_zalloc(sizeof(*vgl)))) { + vgl->vg = svg->saved_vg_new; + dm_list_add(&svg->saved_vg_to_free, &vgl->list); + } + svg->saved_vg_new = NULL; + } +} + +static void _saved_vg_free(struct saved_vg *svg, int free_old, int free_new) +{ + struct vg_list *vgl, *vgl2; + struct volume_group *vg; + + if (free_old) { + if ((vg = svg->saved_vg_old)) { + log_debug_cache("lvmcache: free saved_vg old %s %.8s %d old %p", + vg->name, (char *)&vg->id, vg->seqno, vg); + + vg->saved_in_clvmd = 0; + release_vg(vg); + svg->saved_vg_old = NULL; + vg = NULL; + } + + dm_list_iterate_items_safe(vgl, vgl2, &svg->saved_vg_to_free) { + log_debug_cache("lvmcache: free saved_vg_to_free %s %.8s %d %p", + vgl->vg->name, (char *)&vgl->vg->id, vgl->vg->seqno, vgl->vg); + + dm_list_del(&vgl->list); + vgl->vg->saved_in_clvmd = 0; + release_vg(vgl->vg); + } } if (free_new) { - if (vginfo->saved_vg_new) { - log_debug_cache("lvmcache: free saved_vg %s new pre %p", - vginfo->saved_vg_new->name, - vginfo->saved_vg_new); + if ((vg = svg->saved_vg_new)) { + log_debug_cache("lvmcache: free saved_vg pre %s %.8s %d %p", + vg->name, (char *)&vg->id, vg->seqno, vg); - vginfo->saved_vg_new->saved_in_clvmd = 0; + vg->saved_in_clvmd = 0; + release_vg(vg); + svg->saved_vg_new = NULL; + vg = NULL; } - - if (vginfo->saved_vg_new_buf) - dm_free(vginfo->saved_vg_new_buf); - if (vginfo->saved_vg_new_cft) - dm_config_destroy(vginfo->saved_vg_new_cft); - if (vginfo->saved_vg_new) - release_vg(vginfo->saved_vg_new); - - vginfo->saved_vg_new_buf = NULL; - vginfo->saved_vg_new_cft = NULL; - vginfo->saved_vg_new = NULL; } } static void _drop_metadata(const char *vgname, int drop_precommitted) { struct lvmcache_vginfo *vginfo; + struct saved_vg *svg; if (!(vginfo = lvmcache_vginfo_from_vgname(vgname, NULL))) return; + if (!(svg = _saved_vg_from_vgid(vginfo->vgid))) + return; + if (drop_precommitted) - _saved_vg_free(vginfo, 0, 1); + _saved_vg_free(svg, 0, 1); else - _saved_vg_free(vginfo, 1, 1); + _saved_vg_free(svg, 1, 1); } void lvmcache_save_vg(struct volume_group *vg, int precommitted) { - struct lvmcache_vginfo *vginfo; + struct saved_vg *svg; struct format_instance *fid; struct format_instance_ctx fic; struct volume_group *save_vg = NULL; - struct dm_config_tree *susp_cft = NULL; - char *susp_buf = NULL; + struct dm_config_tree *save_cft = NULL; + const struct format_type *fmt; + char *save_buf = NULL; size_t size; int new = precommitted; int old = !precommitted; - if (!(vginfo = lvmcache_vginfo_from_vgid((const char *)&vg->id))) - goto_bad; - - /* already saved */ - if (old && vginfo->saved_vg_old && - (vginfo->saved_vg_old->seqno == vg->seqno)) - return; - - /* already saved */ - if (new && vginfo->saved_vg_new && - (vginfo->saved_vg_new->seqno == vg->seqno)) - return; - - _saved_vg_free(vginfo, old, new); - - if (!(size = export_vg_to_buffer(vg, &susp_buf))) + if (!(svg = _saved_vg_from_vgid((const char *)&vg->id))) { + /* Nothing is saved yet for this vg */ + + if (!(svg = dm_zalloc(sizeof(*svg)))) + return; + + dm_list_init(&svg->saved_vg_to_free); + + dm_strncpy(svg->vgid, (const char *)vg->id.uuid, sizeof(svg->vgid)); + + if (!dm_hash_insert(_saved_vg_hash, svg->vgid, svg)) { + log_error("lvmcache: failed to insert saved_vg %s", svg->vgid); + return; + } + } else { + /* Nothing to do if we've already saved this seqno */ + + if (old && svg->saved_vg_old && (svg->saved_vg_old->seqno == vg->seqno)) + return; + + if (new && svg->saved_vg_new && (svg->saved_vg_new->seqno == vg->seqno)) + return; + + /* Invalidate the existing saved_vg that will be replaced */ + + _saved_vg_inval(svg, old, new); + } + + + if (!(size = export_vg_to_buffer(vg, &save_buf))) goto_bad; + fmt = vg->fid->fmt; fic.type = FMT_INSTANCE_MDAS | FMT_INSTANCE_AUX_MDAS; - fic.context.vg_ref.vg_name = vginfo->vgname; - fic.context.vg_ref.vg_id = vginfo->vgid; - if (!(fid = vginfo->fmt->ops->create_instance(vginfo->fmt, &fic))) + fic.context.vg_ref.vg_name = vg->name; + fic.context.vg_ref.vg_id = svg->vgid; + + if (!(fid = fmt->ops->create_instance(fmt, &fic))) goto_bad; - if (!(susp_cft = config_tree_from_string_without_dup_node_check(susp_buf))) + if (!(save_cft = config_tree_from_string_without_dup_node_check(save_buf))) goto_bad; - if (!(save_vg = import_vg_from_config_tree(susp_cft, fid))) + if (!(save_vg = import_vg_from_config_tree(save_cft, fid))) goto_bad; + dm_free(save_buf); + dm_config_destroy(save_cft); + save_vg->saved_in_clvmd = 1; if (old) { - vginfo->saved_vg_old_buf = susp_buf; - vginfo->saved_vg_old_cft = susp_cft; - vginfo->saved_vg_old = save_vg; - log_debug_cache("lvmcache saved old vg %s seqno %d %p", + svg->saved_vg_old = save_vg; + log_debug_cache("lvmcache: saved old vg %s seqno %d %p", save_vg->name, save_vg->seqno, save_vg); } else { - vginfo->saved_vg_new_buf = susp_buf; - vginfo->saved_vg_new_cft = susp_cft; - vginfo->saved_vg_new = save_vg; - log_debug_cache("lvmcache saved pre vg %s seqno %d %p", + svg->saved_vg_new = save_vg; + log_debug_cache("lvmcache: saved pre vg %s seqno %d %p", save_vg->name, save_vg->seqno, save_vg); } return; bad: - _saved_vg_free(vginfo, old, new); - log_debug_cache("lvmcache failed to save pre %d vg %s", precommitted, vg->name); + if (save_buf) + dm_free(save_buf); + if (save_cft) + dm_config_destroy(save_cft); + + _saved_vg_inval(svg, old, new); + log_debug_cache("lvmcache: failed to save pre %d vg %s", precommitted, vg->name); } struct volume_group *lvmcache_get_saved_vg(const char *vgid, int precommitted) { - struct lvmcache_vginfo *vginfo; + struct saved_vg *svg; struct volume_group *vg = NULL; int new = precommitted; int old = !precommitted; - if (!(vginfo = lvmcache_vginfo_from_vgid(vgid))) + if (!(svg = _saved_vg_from_vgid(vgid))) goto out; /* @@ -330,130 +398,116 @@ struct volume_group *lvmcache_get_saved_vg(const char *vgid, int precommitted) */ if (new) - vg = vginfo->saved_vg_new; + vg = svg->saved_vg_new; else if (old) - vg = vginfo->saved_vg_old; + vg = svg->saved_vg_old; if (vg && old) { - if (!vginfo->saved_vg_new) + if (!svg->saved_vg_new) log_debug_cache("lvmcache: get old saved_vg %d %s %p", vg->seqno, vg->name, vg); else log_debug_cache("lvmcache: get old saved_vg %d %s %p new is %d %p", vg->seqno, vg->name, vg, - vginfo->saved_vg_new->seqno, - vginfo->saved_vg_new); + svg->saved_vg_new->seqno, + svg->saved_vg_new); } if (vg && new) { - if (!vginfo->saved_vg_old) - log_debug_cache("lvmcache: get new (pre) saved_vg %d %s %p", + if (!svg->saved_vg_old) + log_debug_cache("lvmcache: get new saved_vg %d %s %p", vg->seqno, vg->name, vg); else - log_debug_cache("lvmcache: get new (pre) saved_vg %d %s %p old is %d %p", + log_debug_cache("lvmcache: get new saved_vg %d %s %p old is %d %p", vg->seqno, vg->name, vg, - vginfo->saved_vg_old->seqno, - vginfo->saved_vg_old); + svg->saved_vg_old->seqno, + svg->saved_vg_old); - /* Do we need to actually set saved_vg_old to match saved_vg_new? - * By just dropping old, we force a subsequent request for old to - * reread it rather than just using new. */ + if (svg->saved_vg_old && (svg->saved_vg_old->seqno < vg->seqno)) { + log_debug_cache("lvmcache: inval saved_vg_old %d %p for new %d %p %s", + svg->saved_vg_old->seqno, svg->saved_vg_old, + vg->seqno, vg, vg->name); - if (vginfo->saved_vg_old && (vginfo->saved_vg_old->seqno < vg->seqno)) { - log_debug_cache("lvmcache: drop saved_vg_old because new invalidates"); - _saved_vg_free(vginfo, 1, 0); + _saved_vg_inval(svg, 1, 0); } } - if (!vg && new && vginfo->saved_vg_old) + if (!vg && new && svg->saved_vg_old) log_warn("lvmcache_get_saved_vg pre %d wanted new but only have old %d %s", precommitted, - vginfo->saved_vg_old->seqno, - vginfo->saved_vg_old->name); + svg->saved_vg_old->seqno, + svg->saved_vg_old->name); - if (!vg && old && vginfo->saved_vg_new) + if (!vg && old && svg->saved_vg_new) log_warn("lvmcache_get_saved_vg pre %d wanted old but only have new %d %s", precommitted, - vginfo->saved_vg_new->seqno, - vginfo->saved_vg_new->name); + svg->saved_vg_new->seqno, + svg->saved_vg_new->name); out: if (!vg) - log_debug_cache("lvmcache no saved vg %s pre %d", vgid, precommitted); + log_debug_cache("lvmcache: no saved pre %d %s", precommitted, vgid); return vg; } struct volume_group *lvmcache_get_saved_vg_latest(const char *vgid) { - struct lvmcache_vginfo *vginfo; + struct saved_vg *svg; struct volume_group *vg = NULL; int old = 0; int new = 0; - if (!(vginfo = lvmcache_vginfo_from_vgid(vgid))) + if (!(svg = _saved_vg_from_vgid(vgid))) goto out; - if (vginfo->saved_vg_committed) { - vg = vginfo->saved_vg_new; + if (svg->saved_vg_committed) { + vg = svg->saved_vg_new; new = 1; } else { - vg = vginfo->saved_vg_old; + vg = svg->saved_vg_old; old = 1; } if (vg && old) { - if (!vginfo->saved_vg_new) + if (!svg->saved_vg_new) log_debug_cache("lvmcache: get_latest old saved_vg %d %s %p", vg->seqno, vg->name, vg); else log_debug_cache("lvmcache: get_latest old saved_vg %d %s %p new is %d %p", vg->seqno, vg->name, vg, - vginfo->saved_vg_new->seqno, - vginfo->saved_vg_new); + svg->saved_vg_new->seqno, + svg->saved_vg_new); } if (vg && new) { - if (!vginfo->saved_vg_old) - log_debug_cache("lvmcache: get_latest new (pre) saved_vg %d %s %p", + if (!svg->saved_vg_old) + log_debug_cache("lvmcache: get_latest new saved_vg %d %s %p", vg->seqno, vg->name, vg); else - log_debug_cache("lvmcache: get_latest new (pre) saved_vg %d %s %p old is %d %p", + log_debug_cache("lvmcache: get_latest new saved_vg %d %s %p old is %d %p", vg->seqno, vg->name, vg, - vginfo->saved_vg_old->seqno, - vginfo->saved_vg_old); + svg->saved_vg_old->seqno, + svg->saved_vg_old); - /* Do we need to actually set saved_vg_old to match saved_vg_new? - * By just dropping old, we force a subsequent request for old to - * reread it rather than just using new. */ + if (svg->saved_vg_old && (svg->saved_vg_old->seqno < vg->seqno)) { + log_debug_cache("lvmcache: inval saved_vg_old %d %p for new %d %p %s", + svg->saved_vg_old->seqno, svg->saved_vg_old, + vg->seqno, vg, vg->name); - if (vginfo->saved_vg_old && (vginfo->saved_vg_old->seqno < vg->seqno)) { - log_debug_cache("lvmcache: drop saved_vg_old because new invalidates"); - _saved_vg_free(vginfo, 1, 0); + _saved_vg_inval(svg, 1, 0); } } out: if (!vg) - log_debug_cache("lvmcache no saved vg %s", vgid); + log_debug_cache("lvmcache: no saved vg latest %s", vgid); return vg; } -void lvmcache_drop_saved_vg(struct volume_group *vg) -{ - struct lvmcache_vginfo *vginfo; - - if (!(vginfo = lvmcache_vginfo_from_vgid((const char *)&vg->id))) - return; - - _saved_vg_free(vginfo, 1, 1); -} - void lvmcache_drop_saved_vgid(const char *vgid) { - struct lvmcache_vginfo *vginfo; + struct saved_vg *svg; - if (!(vginfo = lvmcache_vginfo_from_vgid(vgid))) - return; - - _saved_vg_free(vginfo, 1, 1); + if ((svg = _saved_vg_from_vgid(vgid))) + _saved_vg_inval(svg, 1, 1); } /* @@ -464,15 +518,20 @@ void lvmcache_drop_saved_vgid(const char *vgid) void lvmcache_commit_metadata(const char *vgname) { struct lvmcache_vginfo *vginfo; + struct saved_vg *svg; if (!(vginfo = lvmcache_vginfo_from_vgname(vgname, NULL))) return; - vginfo->saved_vg_committed = 1; + if ((svg = _saved_vg_from_vgid(vginfo->vgid))) + svg->saved_vg_committed = 1; } void lvmcache_drop_metadata(const char *vgname, int drop_precommitted) { + if (!_saved_vg_hash) + return; + if (lvmcache_vgname_is_locked(VG_GLOBAL)) return; @@ -550,11 +609,6 @@ int lvmcache_verify_lock_order(const char *vgname) void lvmcache_lock_vgname(const char *vgname, int read_only __attribute__((unused))) { - if (!_lock_hash && !lvmcache_init()) { - log_error("Internal cache initialisation failed"); - return; - } - if (dm_hash_lookup(_lock_hash, vgname)) log_error(INTERNAL_ERROR "Nested locking attempted on VG %s.", vgname); @@ -1268,6 +1322,11 @@ int lvmcache_label_rescan_vg(struct cmd_context *cmd, const char *vgname, const label_scan_devs(cmd, &devs); + if (!(vginfo = lvmcache_vginfo_from_vgname(vgname, vgid))) { + log_warn("VG info not found after rescan of %s", vgname); + return 0; + } + return 1; } @@ -1321,11 +1380,6 @@ int lvmcache_label_scan(struct cmd_context *cmd) _scanning_in_progress = 1; - if (!_vgname_hash && !lvmcache_init()) { - log_error("Internal cache initialisation failed"); - goto out; - } - /* FIXME: can this happen? */ if (!cmd->full_filter) { log_error("label scan is missing full filter"); @@ -1620,7 +1674,6 @@ static int _free_vginfo(struct lvmcache_vginfo *vginfo) dm_free(vginfo->system_id); dm_free(vginfo->vgname); dm_free(vginfo->creation_host); - _saved_vg_free(vginfo, 1, 1); if (*vginfo->vgid && _vgid_hash && lvmcache_vginfo_from_vgid(vginfo->vgid) == vginfo) @@ -1956,11 +2009,6 @@ out: int lvmcache_add_orphan_vginfo(const char *vgname, struct format_type *fmt) { - if (!_lock_hash && !lvmcache_init()) { - log_error("Internal cache initialisation failed"); - return 0; - } - return _lvmcache_update_vgname(NULL, vgname, vgname, 0, "", fmt); } @@ -2330,6 +2378,11 @@ static void _lvmcache_destroy_lockname(struct dm_hash_node *n) dm_hash_get_key(_lock_hash, n)); } +static void _destroy_saved_vg(struct saved_vg *svg) +{ + _saved_vg_free(svg, 1, 1); +} + void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans, int reset) { struct dm_hash_node *n; @@ -2366,6 +2419,12 @@ void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans, int reset) _lock_hash = NULL; } + if (_saved_vg_hash) { + dm_hash_iter(_saved_vg_hash, (dm_hash_iterate_fn) _destroy_saved_vg); + dm_hash_destroy(_saved_vg_hash); + _saved_vg_hash = NULL; + } + if (!dm_list_empty(&_vginfos)) log_error(INTERNAL_ERROR "_vginfos list should be empty"); dm_list_init(&_vginfos); @@ -2386,9 +2445,16 @@ void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans, int reset) _destroy_duplicate_device_list(&_found_duplicate_devs); /* should be empty anyway */ _found_duplicate_pvs = 0; - if (retain_orphans) - if (!init_lvmcache_orphans(cmd)) - stack; + if (retain_orphans) { + struct format_type *fmt; + + lvmcache_init(cmd); + + dm_list_iterate_items(fmt, &cmd->formats) { + if (!lvmcache_add_orphan_vginfo(fmt->orphan_vg_name, fmt)) + stack; + } + } } int lvmcache_pvid_is_locked(const char *pvid) { diff --git a/lib/cache/lvmcache.h b/lib/cache/lvmcache.h index 7cdda431a..797ff21a2 100644 --- a/lib/cache/lvmcache.h +++ b/lib/cache/lvmcache.h @@ -63,7 +63,7 @@ struct lvmcache_vgsummary { int seqno; }; -int lvmcache_init(void); +int lvmcache_init(struct cmd_context *cmd); void lvmcache_allow_reads_with_lvmetad(void); void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans, int reset); @@ -213,12 +213,15 @@ int lvmcache_get_vg_devs(struct cmd_context *cmd, struct dm_list *devs); void lvmcache_set_independent_location(const char *vgname); +int lvmcache_scan_mismatch(struct cmd_context *cmd, const char *vgname, const char *vgid); + +/* + * These are clvmd-specific functions and are not related to lvmcache. + * FIXME: rename these with a clvm_ prefix in place of lvmcache_ + */ void lvmcache_save_vg(struct volume_group *vg, int precommitted); struct volume_group *lvmcache_get_saved_vg(const char *vgid, int precommitted); struct volume_group *lvmcache_get_saved_vg_latest(const char *vgid); -void lvmcache_drop_saved_vg(struct volume_group *vg); void lvmcache_drop_saved_vgid(const char *vgid); -int lvmcache_scan_mismatch(struct cmd_context *cmd, const char *vgname, const char *vgid); - #endif diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c index 76e15e06e..4fdd62fa1 100644 --- a/lib/commands/toolcontext.c +++ b/lib/commands/toolcontext.c @@ -1814,7 +1814,7 @@ out: } /* Entry point */ -struct cmd_context *create_toolcontext(unsigned is_long_lived, +struct cmd_context *create_toolcontext(unsigned is_clvmd, const char *system_dir, unsigned set_buffering, unsigned threaded, @@ -1841,7 +1841,8 @@ struct cmd_context *create_toolcontext(unsigned is_long_lived, log_error("Failed to allocate command context"); return NULL; } - cmd->is_long_lived = is_long_lived; + cmd->is_long_lived = is_clvmd; + cmd->is_clvmd = is_clvmd; cmd->threaded = threaded ? 1 : 0; cmd->handles_missing_pvs = 0; cmd->handles_unknown_segments = 0; @@ -1970,6 +1971,10 @@ struct cmd_context *create_toolcontext(unsigned is_long_lived, if (!_init_formats(cmd)) goto_out; + if (!lvmcache_init(cmd)) + goto_out; + + /* FIXME: move into lvmcache_init */ if (!init_lvmcache_orphans(cmd)) goto_out; @@ -2191,6 +2196,9 @@ int refresh_toolcontext(struct cmd_context *cmd) if (!_init_formats(cmd)) return_0; + if (!lvmcache_init(cmd)) + return_0; + if (!init_lvmcache_orphans(cmd)) return_0; diff --git a/lib/commands/toolcontext.h b/lib/commands/toolcontext.h index 1d9de0a7a..34222ee95 100644 --- a/lib/commands/toolcontext.h +++ b/lib/commands/toolcontext.h @@ -236,7 +236,7 @@ struct cmd_context { * system_dir may be NULL to use the default value. * The environment variable LVM_SYSTEM_DIR always takes precedence. */ -struct cmd_context *create_toolcontext(unsigned is_long_lived, +struct cmd_context *create_toolcontext(unsigned is_clvmd, const char *system_dir, unsigned set_buffering, unsigned threaded, diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c index d65daafec..16fd6fa71 100644 --- a/lib/metadata/metadata.c +++ b/lib/metadata/metadata.c @@ -4599,7 +4599,7 @@ struct volume_group *vg_read_by_vgid(struct cmd_context *cmd, if (!(vgname = lvmcache_vgname_from_vgid(cmd->mem, vgid))) { log_debug_metadata("Reading VG by vgid %.8s no VG name found, retrying.", vgid); - lvmcache_destroy(cmd, 0, 0); + lvmcache_destroy(cmd, 1, 0); label_scan_destroy(cmd); lvmcache_label_scan(cmd); warn_flags |= SKIP_RESCAN; @@ -4630,7 +4630,7 @@ struct volume_group *vg_read_by_vgid(struct cmd_context *cmd, return vg; scan: - lvmcache_destroy(cmd, 0, 0); + lvmcache_destroy(cmd, 1, 0); label_scan_destroy(cmd); lvmcache_label_scan(cmd); warn_flags |= SKIP_RESCAN; diff --git a/lib/metadata/raid_manip.c b/lib/metadata/raid_manip.c index 1b9ebcf94..703f28547 100644 --- a/lib/metadata/raid_manip.c +++ b/lib/metadata/raid_manip.c @@ -6789,10 +6789,8 @@ static int _lv_raid_rebuild_or_replace(struct logical_volume *lv, return 0; } - if (lv_is_virtual(seg_lv(raid_seg, s)) || - lv_is_virtual(seg_metalv(raid_seg, s)) || - lv_is_partial(seg_lv(raid_seg, s)) || - lv_is_partial(seg_metalv(raid_seg, s)) || + if (_sublv_is_degraded(seg_lv(raid_seg, s)) || + _sublv_is_degraded(seg_metalv(raid_seg, s)) || lv_is_on_pvs(seg_lv(raid_seg, s), remove_pvs) || lv_is_on_pvs(seg_metalv(raid_seg, s), remove_pvs)) { match_count++; @@ -7122,10 +7120,8 @@ static int _partial_raid_lv_is_redundant(const struct logical_volume *lv) if (!(i % copies)) rebuilds_per_group = 0; - if (lv_is_partial(seg_lv(raid_seg, s)) || - lv_is_partial(seg_metalv(raid_seg, s)) || - lv_is_virtual(seg_lv(raid_seg, s)) || - lv_is_virtual(seg_metalv(raid_seg, s))) + if (_sublv_is_degraded(seg_lv(raid_seg, s)) || + _sublv_is_degraded(seg_metalv(raid_seg, s))) rebuilds_per_group++; if (rebuilds_per_group >= copies) { @@ -7138,14 +7134,7 @@ static int _partial_raid_lv_is_redundant(const struct logical_volume *lv) return 1; /* Redundant */ } - for (s = 0; s < raid_seg->area_count; s++) { - if (lv_is_partial(seg_lv(raid_seg, s)) || - lv_is_partial(seg_metalv(raid_seg, s)) || - lv_is_virtual(seg_lv(raid_seg, s)) || - lv_is_virtual(seg_metalv(raid_seg, s))) - failed_components++; - } - + failed_components = _lv_get_nr_failed_components(lv); if (failed_components == raid_seg->area_count) { log_verbose("All components of raid LV %s have failed.", display_lvname(lv)); diff --git a/tools/toollib.c b/tools/toollib.c index 53e7f9ae4..e633cddb1 100644 --- a/tools/toollib.c +++ b/tools/toollib.c @@ -111,7 +111,7 @@ int become_daemon(struct cmd_context *cmd, int skip_lvm) if (!skip_lvm) { reset_locking(); lvmcache_destroy(cmd, 1, 1); - if (!lvmcache_init()) + if (!lvmcache_init(cmd)) /* FIXME Clean up properly here */ _exit(ECMD_FAILED); } @@ -4622,7 +4622,7 @@ int process_each_pv(struct cmd_context *cmd, log_verbose("Some PVs were not found in first search, retrying."); lvmcache_destroy(cmd, 0, 0); - if (!lvmcache_init()) { + if (!lvmcache_init(cmd)) { log_error("Failed to initalize lvm cache."); ret_max = ECMD_FAILED; goto out;