stack; // FIXME: What should we do?
}
+static int _check_mda_in_use(struct metadata_area *mda, void *_in_use)
+{
+ int *in_use = _in_use;
+ if (!mda_is_ignored(mda))
+ *in_use = 1;
+ return 1;
+}
+
struct _vg_read_orphan_baton {
+ struct cmd_context *cmd;
struct volume_group *vg;
uint32_t warn_flags;
+ int consistent;
+ int repair;
};
+static int _check_or_repair_orphan_pv_ext(struct physical_volume *pv,
+ struct lvmcache_info *info,
+ struct _vg_read_orphan_baton *b)
+{
+ uint32_t ext_flags = lvmcache_ext_flags(info);
+ int at_least_one_mda_used;
+
+ if (ext_flags & PV_EXT_USED) {
+ if (lvmcache_mda_count(info)) {
+ at_least_one_mda_used = 0;
+ lvmcache_foreach_mda(info, _check_mda_in_use, &at_least_one_mda_used);
+
+ /*
+ * We've found a PV that is marked as used with PV_EXT_USED flag
+ * and it's orphan at the same time while it contains MDAs.
+ * This is incorrect state and it needs to be fixed.
+ * The PV_EXT_USED flag needs to be dropped!
+ */
+ if (b->repair) {
+ if (at_least_one_mda_used) {
+ log_warn("WARNING: Repairing flag incorrectly marking "
+ "Physical Volume %s as used.", pv_dev_name(pv));
+
+ /* pv_write will set correct ext_flags */
+ if (!pv_write(b->cmd, pv, 0)) {
+ b->consistent = 0;
+ log_error("Failed to repair physical volume \"%s\".",
+ pv_dev_name(pv));
+ return 0;
+ }
+ }
+ b->consistent = 1;
+ } else if (at_least_one_mda_used) {
+ /* mark as inconsistent only if there's at least 1 MDA used */
+ b->consistent = 0;
+ }
+ }
+ }
+
+ return 1;
+}
+
static int _vg_read_orphan_pv(struct lvmcache_info *info, void *baton)
{
struct _vg_read_orphan_baton *b = baton;
}
pvl->pv = pv;
add_pvl_to_vgs(b->vg, pvl);
+
+ if (!_check_or_repair_orphan_pv_ext(pv, info, baton)) {
+ stack;
+ return 0;
+ }
+
return 1;
}
/* Make orphan PVs look like a VG. */
static struct volume_group *_vg_read_orphans(struct cmd_context *cmd,
uint32_t warn_flags,
- const char *orphan_vgname)
+ const char *orphan_vgname,
+ int *consistent)
{
const struct format_type *fmt;
struct lvmcache_vginfo *vginfo;
vg->extent_count = 0;
vg->free_count = 0;
+ baton.cmd = cmd;
baton.warn_flags = warn_flags;
baton.vg = vg;
+ baton.consistent = 1;
+ baton.repair = *consistent;
while ((pvl = (struct pv_list *) dm_list_first(&head.list))) {
dm_list_del(&pvl->list);
if (!lvmcache_foreach_pv(vginfo, _vg_read_orphan_pv, &baton))
return_NULL;
+ *consistent = baton.consistent;
return vg;
}
return 1;
}
-static int _check_mda_in_use(struct metadata_area *mda, void *_in_use)
-{
- int *in_use = _in_use;
- if (!mda_is_ignored(mda))
- *in_use = 1;
- return 1;
-}
-
static int _wipe_outdated_pvs(struct cmd_context *cmd, struct volume_group *vg, struct dm_list *to_check)
{
struct pv_list *pvl, *pvl2;
"with pre-commit.");
return NULL;
}
- *consistent = 1;
- return _vg_read_orphans(cmd, warn_flags, vgname);
+ return _vg_read_orphans(cmd, warn_flags, vgname, consistent);
}
if (lvmetad_active() && !use_precommitted) {
}
out:
- if (!*consistent && (warn_flags & WARN_INCONSISTENT))
- log_warn("WARNING: Volume Group %s is not consistent.", vgname);
+ if (!*consistent && (warn_flags & WARN_INCONSISTENT)) {
+ if (is_orphan_vg(vgname))
+ log_warn("WARNING: Found inconsistent standalone Physical Volumes.");
+ else
+ log_warn("WARNING: Volume Group %s is not consistent.", vgname);
+ }
return vg;
}
if (!consistent && !failure) {
release_vg(vg);
if (!(vg = _recover_vg(cmd, vg_name, vgid))) {
- log_error("Recovery of volume group \"%s\" failed.",
- vg_name);
+ if (is_orphan_vg(vg_name))
+ log_error("Recovery of standalone physical volumes failed.");
+ else
+ log_error("Recovery of volume group \"%s\" failed.",
+ vg_name);
failure |= FAILED_RECOVERY;
goto bad_no_unlock;
}