diff options
-rw-r--r-- | lib/cache/lvmetad.c | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/lib/cache/lvmetad.c b/lib/cache/lvmetad.c index ccdf63a35..30ebd916c 100644 --- a/lib/cache/lvmetad.c +++ b/lib/cache/lvmetad.c @@ -34,6 +34,8 @@ static char *_lvmetad_token = NULL; static const char *_lvmetad_socket = NULL; static struct cmd_context *_lvmetad_cmd = NULL; +static struct volume_group *lvmetad_pvscan_vg(struct cmd_context *cmd, struct volume_group *vg); + void lvmetad_disconnect(void) { if (_lvmetad_connected) @@ -442,6 +444,15 @@ struct volume_group *lvmetad_vg_lookup(struct cmd_context *cmd, const char *vgna pvl->pv->status |= MISSING_PV; /* probably missing */ } + /* + * locking may have detected a newer vg version and + * invalidated the cached vg. + */ + if (dm_config_find_node(reply.cft->root, "vg_invalid")) { + log_debug_lvmetad("Update invalid lvmetad cache for VG %s", vgname); + vg = lvmetad_pvscan_vg(cmd, vg); + } + lvmcache_update_vg(vg, 0); vg_mark_partial_lvs(vg, 1); } @@ -902,6 +913,67 @@ static int _lvmetad_pvscan_single(struct metadata_area *mda, void *baton) return 1; } +/* + * The lock manager may detect that the vg cached in lvmetad is out of date, + * due to something like an lvcreate from another host. + * This is limited to changes that only affect the vg (not global state like + * orphan PVs), so we only need to reread mdas on the vg's existing pvs. + */ + +static struct volume_group *lvmetad_pvscan_vg(struct cmd_context *cmd, struct volume_group *vg) +{ + struct volume_group *vg_ret = NULL; + struct pv_list *pvl; + struct device *dev; + struct label *label; + struct lvmcache_info *info; + struct _lvmetad_pvscan_baton baton; + /* Create a dummy instance. */ + struct format_instance_ctx fic = { .type = 0 }; + + dm_list_iterate_items(pvl, &vg->pvs) { + /* missing pv */ + if (!pvl->pv->dev) + continue; + + dev = pvl->pv->dev; + + if (!label_read(dev, &label, 0)) { + log_print_unless_silent("No PV label found on %s.", dev_name(dev)); + continue; + } + + info = (struct lvmcache_info *) label->info; + + baton.vg = NULL; + baton.fid = lvmcache_fmt(info)->ops->create_instance(lvmcache_fmt(info), &fic); + + if (!baton.fid) + return NULL; + + if (baton.fid->fmt->features & FMT_OBSOLETE) { + log_error("WARNING: Ignoring obsolete format of metadata (%s) on device %s when using lvmetad", + baton.fid->fmt->name, dev_name(dev)); + lvmcache_fmt(info)->ops->destroy_instance(baton.fid); + return NULL; + } + + lvmcache_foreach_mda(info, _lvmetad_pvscan_single, &baton); + + if (!baton.vg) { + lvmcache_fmt(info)->ops->destroy_instance(baton.fid); + return NULL; + } + + if (!vg_ret) + vg_ret = baton.vg; + else + release_vg(baton.vg); + } + + return vg_ret; +} + int lvmetad_pvscan_single(struct cmd_context *cmd, struct device *dev, activation_handler handler) { |