Gitweb:
http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=384e46fb762e84...
Commit: 384e46fb762e843a145616ff1558e6b7b70a0495
Parent: 82a1c6ccc141de84f3450d97f8049c5f2d08863c
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Tue Mar 10 11:25:14 2015 +0100
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Fri Aug 21 11:15:53 2015 +0200
pv: check for the PV_EXT_USED flag and deny pvcreate/pvchange/pvremove/vgcreate on such PV
(unless forced)
Make sure we won't use a PV that is already marked as used. Normally,
VG metadata would stop us from doing that, but we can run into a
situation where such metadata is missing because PVs with MDAs
are missing and the PVs left are the ones with 0 MDAs.
(/dev/sda in this example has 0 MDAs and it belongs to a VG,
but other PVs with MDA are missing)
$ pvs -o pv_name,pv_mda_count /dev/sda
PV #PMda
/dev/sda 0
$ pvcreate /dev/sda
Can't initialize physical volume "/dev/sda" that is marked as used without
-ff.
$ pvchange -u /dev/sda
Can't change PV "/dev/sda" that is marked as used without -ff.
Physical volume /dev/sda not changed
0 physical volumes changed / 1 physical volume not changed
$ pvremove /dev/sda
PV /dev/sda is marked as used.
(If you are certain you need pvremove, then confirm by using --force twice.)
$ vgcreate vg /dev/sda
Physical volume '/dev/sda' is marked as used.
Unable to add physical volume '/dev/sda' to volume group 'vg'.
---
lib/metadata/metadata.c | 37 +++++++++++++++++++++++++++++++++----
lib/metadata/pv_manip.c | 18 ++++++++++++++++--
tools/pvchange.c | 23 +++++++++++++++++++----
3 files changed, 68 insertions(+), 10 deletions(-)
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index cf54f58..55f5840 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -185,6 +185,8 @@ int add_pv_to_vg(struct volume_group *vg, const char *pv_name,
struct format_instance *fid = vg->fid;
struct dm_pool *mem = vg->vgmem;
char uuid[64] __attribute__((aligned(8)));
+ struct lvmcache_info *info;
+ uint32_t ext_flags;
log_verbose("Adding physical volume '%s' to volume group
'%s'",
pv_name, vg->name);
@@ -198,6 +200,17 @@ int add_pv_to_vg(struct volume_group *vg, const char *pv_name,
log_error("Physical volume '%s' is already in volume group "
"'%s'", pv_name, pv->vg_name);
return 0;
+ } else if (!new_pv) {
+ if (!(info = lvmcache_info_from_pvid((const char *)&pv->id, 0))) {
+ log_error("Failed to find cached info for PV %s.", pv_name);
+ return 0;
+ }
+
+ ext_flags = lvmcache_ext_flags(info);
+ if (ext_flags & PV_EXT_USED) {
+ log_error("Physical volume '%s' is marked as used.", pv_name);
+ return 0;
+ }
}
if (pv->fmt != fid->fmt) {
@@ -1421,6 +1434,8 @@ static int _pvcreate_check(struct cmd_context *cmd, const char
*name,
struct pvcreate_params *pp, int *wiped)
{
struct physical_volume *pv;
+ struct lvmcache_info *info;
+ uint32_t ext_flags;
struct device *dev;
int r = 0;
int scan_needed = 0;
@@ -1435,10 +1450,24 @@ static int _pvcreate_check(struct cmd_context *cmd, const char
*name,
/* Allow partial & exported VGs to be destroyed. */
/* We must have -ff to overwrite a non orphan */
- if (pv && !is_orphan(pv) && pp->force != DONT_PROMPT_OVERRIDE) {
- log_error("Can't initialize physical volume \"%s\" of "
- "volume group \"%s\" without -ff", name, pv_vg_name(pv));
- goto out;
+ if (pv) {
+ if (!is_orphan(pv) && pp->force != DONT_PROMPT_OVERRIDE) {
+ log_error("Can't initialize physical volume \"%s\" of "
+ "volume group \"%s\" without -ff.", name, pv_vg_name(pv));
+ goto out;
+ }
+
+ if (!(info = lvmcache_info_from_pvid((const char *)&pv->id, 0))) {
+ log_error("Failed to find cached info for PV %s.", name);
+ goto out;
+ }
+
+ ext_flags = lvmcache_ext_flags(info);
+ if (ext_flags & PV_EXT_USED && pp->force != DONT_PROMPT_OVERRIDE) {
+ log_error("Can't initialize physical volume \"%s\" that is marked
as used "
+ "without -ff.", name);
+ goto out;
+ }
}
/* prompt */
diff --git a/lib/metadata/pv_manip.c b/lib/metadata/pv_manip.c
index ce7f661..92e48f8 100644
--- a/lib/metadata/pv_manip.c
+++ b/lib/metadata/pv_manip.c
@@ -697,10 +697,12 @@ const char _really_wipe[] =
static int pvremove_check(struct cmd_context *cmd, const char *name,
unsigned force_count, unsigned prompt, struct dm_list *pvslist)
{
+ static const char pvremove_force_hint_msg[] = "(If you are certain you need
pvremove, then confirm by using --force twice.)";
struct device *dev;
struct label *label;
struct pv_list *pvl;
-
+ struct lvmcache_info *info;
+ uint32_t ext_flags;
struct physical_volume *pv = NULL;
int r = 0;
@@ -731,6 +733,18 @@ static int pvremove_check(struct cmd_context *cmd, const char *name,
}
if (is_orphan(pv)) {
+ if (!(info = lvmcache_info_from_pvid((const char *)&pv->id, 0))) {
+ log_error("Failed to find cached info for PV %s.", name);
+ goto out;
+ }
+
+ ext_flags = lvmcache_ext_flags(info);
+ if (ext_flags & PV_EXT_USED && force_count < 2) {
+ log_error("PV %s is marked as used.", name);
+ log_error("%s", pvremove_force_hint_msg);
+ goto out;
+ }
+
r = 1;
goto out;
}
@@ -738,7 +752,7 @@ static int pvremove_check(struct cmd_context *cmd, const char *name,
/* we must have -ff to overwrite a non orphan */
if (force_count < 2) {
log_error("PV %s belongs to Volume Group %s so please use vgreduce first.",
name, pv_vg_name(pv));
- log_error("(If you are certain you need pvremove, then confirm by using --force
twice.)");
+ log_error("%s", pvremove_force_hint_msg);
goto out;
}
diff --git a/tools/pvchange.c b/tools/pvchange.c
index 91e93c1..409f759 100644
--- a/tools/pvchange.c
+++ b/tools/pvchange.c
@@ -25,6 +25,8 @@ static int _pvchange_single(struct cmd_context *cmd, struct volume_group
*vg,
{
struct pvchange_params *params = (struct pvchange_params *) handle->custom_handle;
const char *pv_name = pv_dev_name(pv);
+ struct lvmcache_info *info;
+ uint32_t ext_flags;
char uuid[64] __attribute__((aligned(8)));
unsigned done = 0;
@@ -48,10 +50,23 @@ static int _pvchange_single(struct cmd_context *cmd, struct
volume_group *vg,
}
if (!archive(vg))
goto_bad;
- } else if (tagargs) {
- log_error("Can't change tag on Physical Volume %s not "
- "in volume group", pv_name);
- goto bad;
+ } else {
+ if (tagargs) {
+ log_error("Can't change tag on Physical Volume %s not "
+ "in volume group", pv_name);
+ goto bad;
+ }
+
+ if (!(info = lvmcache_info_from_pvid((const char *) &pv->id,0))) {
+ log_error("Failed to find cached info for PV %s.", pv_name);
+ goto bad;
+ }
+
+ ext_flags = lvmcache_ext_flags(info);
+ if (ext_flags & PV_EXT_USED && (arg_count(cmd, force_ARG) !=
DONT_PROMPT_OVERRIDE)) {
+ log_error("Can't change PV \"%s\" that is marked as used without
-ff.", pv_name);
+ goto bad;
+ }
}
if (arg_count(cmd, allocatable_ARG)) {