Gitweb:
https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=4f9ff14508084789c73...
Commit: 4f9ff14508084789c731e99d8921c052da694319
Parent: 5cf51fb2f74ad43a2555bc391cf069caa1d99775
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Thu Apr 27 12:13:09 2017 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Thu Apr 27 13:25:41 2017 -0500
pvcreate: add prompt when setting dev size
If the device size does not match the size requested
by --setphysicalvolumesize, then prompt the user.
Make the pvcreate checking/prompting code handle
multiple prompts for the same device, since the
new prompt can be in addition to the existing
prompt when the PV is in a VG.
---
test/shell/pv-check-dev-size.sh | 4 +-
test/shell/snapshot-usage.sh | 2 +-
tools/args.h | 2 +-
tools/pvcreate.c | 4 +-
tools/pvresize.c | 4 +-
tools/toollib.c | 133 +++++++++++++++++++++++++++++++--------
6 files changed, 115 insertions(+), 34 deletions(-)
diff --git a/test/shell/pv-check-dev-size.sh b/test/shell/pv-check-dev-size.sh
index d3d1b53..76618ad 100644
--- a/test/shell/pv-check-dev-size.sh
+++ b/test/shell/pv-check-dev-size.sh
@@ -27,7 +27,7 @@ not grep "$CHECK_MSG" err
vgremove -ff $vg
# set PV size to 2x dev size
-pvcreate --setphysicalvolumesize 16m $dev1
+pvcreate --yes --setphysicalvolumesize 16m $dev1
vgcreate $vg $dev1 2>err
grep "$CHECK_MSG" err
pvs 2>err
@@ -36,7 +36,7 @@ vgremove -ff $vg
# should be quiet if requested
aux lvmconf 'metadata/check_pv_device_sizes = 0'
-pvcreate --setphysicalvolumesize 16m $dev1
+pvcreate --yes --setphysicalvolumesize 16m $dev1
vgcreate $vg $dev1 2>err
not grep "$CHECK_MSG" err
pvs 2>err
diff --git a/test/shell/snapshot-usage.sh b/test/shell/snapshot-usage.sh
index a780664..a751f1a 100644
--- a/test/shell/snapshot-usage.sh
+++ b/test/shell/snapshot-usage.sh
@@ -78,7 +78,7 @@ aux lvmconf "activation/snapshot_autoextend_percent = 20" \
"activation/snapshot_autoextend_threshold = 50"
# Check usability with smallest (1k) extent size ($lv has 15P)
-pvcreate --setphysicalvolumesize 4T "$DM_DEV_DIR/$vg/$lv"
+pvcreate --yes --setphysicalvolumesize 4T "$DM_DEV_DIR/$vg/$lv"
trap 'cleanup_tail' EXIT
vgcreate -s 1K $vg1 "$DM_DEV_DIR/$vg/$lv"
diff --git a/tools/args.h b/tools/args.h
index be1711b..87b33e7 100644
--- a/tools/args.h
+++ b/tools/args.h
@@ -402,7 +402,7 @@ arg(originname_ARG, '\0', "originname", lv_VAL, 0,
0,
"to a thin LV. The LV being converted becomes a read-only external
origin\n"
"with this name.\n")
-arg(physicalvolumesize_ARG, '\0', "setphysicalvolumesize", sizemb_VAL,
0, 0,
+arg(setphysicalvolumesize_ARG, '\0', "setphysicalvolumesize",
sizemb_VAL, 0, 0,
"Overrides the automatically detected size of the PV.\n"
"Use with care, or prior to reducing the physical size of the device.\n")
diff --git a/tools/pvcreate.c b/tools/pvcreate.c
index e69eed4..0fe5ad5 100644
--- a/tools/pvcreate.c
+++ b/tools/pvcreate.c
@@ -52,11 +52,11 @@ static int pvcreate_restore_params_from_args(struct cmd_context *cmd,
int argc,
pp->pva.idp = &pp->pva.id;
}
- if (arg_sign_value(cmd, physicalvolumesize_ARG, SIGN_NONE) == SIGN_MINUS) {
+ if (arg_sign_value(cmd, setphysicalvolumesize_ARG, SIGN_NONE) == SIGN_MINUS) {
log_error("Physical volume size may not be negative");
return 0;
}
- pp->pva.size = arg_uint64_value(cmd, physicalvolumesize_ARG, UINT64_C(0));
+ pp->pva.size = arg_uint64_value(cmd, setphysicalvolumesize_ARG, UINT64_C(0));
if (arg_is_set(cmd, restorefile_ARG) || arg_is_set(cmd, uuidstr_ARG))
pp->zero = 0;
diff --git a/tools/pvresize.c b/tools/pvresize.c
index 1de1709..8a65952 100644
--- a/tools/pvresize.c
+++ b/tools/pvresize.c
@@ -72,13 +72,13 @@ int pvresize(struct cmd_context *cmd, int argc, char **argv)
goto out;
}
- if (arg_sign_value(cmd, physicalvolumesize_ARG, SIGN_NONE) == SIGN_MINUS) {
+ if (arg_sign_value(cmd, setphysicalvolumesize_ARG, SIGN_NONE) == SIGN_MINUS) {
log_error("Physical volume size may not be negative");
ret = EINVALID_CMD_LINE;
goto out;
}
- params.new_size = arg_uint64_value(cmd, physicalvolumesize_ARG,
+ params.new_size = arg_uint64_value(cmd, setphysicalvolumesize_ARG,
UINT64_C(0));
params.done = 0;
diff --git a/tools/toollib.c b/tools/toollib.c
index 838765b..f3cf4ca 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -4751,6 +4751,7 @@ int pvcreate_params_from_args(struct cmd_context *cmd, struct
pvcreate_params *p
enum {
PROMPT_PVCREATE_PV_IN_VG = 1,
PROMPT_PVREMOVE_PV_IN_VG = 2,
+ PROMPT_PVCREATE_DEV_SIZE = 4,
};
enum {
@@ -4767,6 +4768,8 @@ enum {
struct pvcreate_prompt {
struct dm_list list;
uint32_t type;
+ uint64_t size;
+ uint64_t new_size;
const char *pv_name;
const char *vg_name;
struct device *dev;
@@ -4808,12 +4811,14 @@ static void _check_pvcreate_prompt(struct cmd_context *cmd,
{
const char *vgname = prompt->vg_name ? prompt->vg_name :
"<unknown>";
const char *pvname = prompt->pv_name;
+ int answer_yes = 0;
+ int answer_no = 0;
/* The VG name can be unknown when the PV is used but metadata is not available */
- if (prompt->type == PROMPT_PVCREATE_PV_IN_VG) {
+ if (prompt->type & PROMPT_PVCREATE_PV_IN_VG) {
if (pp->force != DONT_PROMPT_OVERRIDE) {
- prompt->answer = PROMPT_ANSWER_NO;
+ answer_no = 1;
if (prompt->vg_name_unknown) {
log_error("PV %s is used by a VG but its metadata is missing.", pvname);
@@ -4825,20 +4830,39 @@ static void _check_pvcreate_prompt(struct cmd_context *cmd,
log_error("Unable to add physical volume '%s' to volume group
'%s'", pvname, vgname);
}
} else if (pp->yes) {
- prompt->answer = PROMPT_ANSWER_YES;
+ answer_yes = 1;
} else if (ask) {
if (yes_no_prompt("Really INITIALIZE physical volume \"%s\" of volume
group \"%s\" [y/n]? ", pvname, vgname) == 'n') {
- prompt->answer = PROMPT_ANSWER_NO;
- log_error("%s: physical volume not initialized", pvname);
+ answer_no = 1;
} else {
- prompt->answer = PROMPT_ANSWER_YES;
+ answer_yes = 1;
log_warn("WARNING: Forcing physical volume creation on %s of volume group
\"%s\"", pvname, vgname);
}
}
- } else if (prompt->type == PROMPT_PVREMOVE_PV_IN_VG) {
+ }
+
+ if (prompt->type & PROMPT_PVCREATE_DEV_SIZE) {
+ if (pp->yes) {
+ log_warn("WARNING: Faking size of PV %s. Don't write outside real
device.", pvname);
+ answer_yes = 1;
+ } else if (ask) {
+ if (prompt->new_size != prompt->size) {
+ if (yes_no_prompt("WARNING: %s: device size %s does not match requested size %s.
Proceed? [y/n]: ", pvname,
+ display_size(cmd, (uint64_t)prompt->size),
+ display_size(cmd, (uint64_t)prompt->new_size)) == 'n') {
+ answer_no = 1;
+ } else {
+ answer_yes = 1;
+ log_warn("WARNING: Faking size of PV %s. Don't write outside real
device.", pvname);
+ }
+ }
+ }
+ }
+
+ if (prompt->type & PROMPT_PVREMOVE_PV_IN_VG) {
if (pp->force != DONT_PROMPT_OVERRIDE) {
- prompt->answer = PROMPT_ANSWER_NO;
+ answer_no = 1;
if (prompt->vg_name_unknown)
log_error("PV %s is used by a VG but its metadata is missing.", pvname);
@@ -4847,20 +4871,51 @@ static void _check_pvcreate_prompt(struct cmd_context *cmd,
log_error("(If you are certain you need pvremove, then confirm by using --force
twice.)");
} else if (pp->yes) {
log_warn("WARNING: PV %s is used by VG %s", pvname, vgname);
- prompt->answer = PROMPT_ANSWER_YES;
+ answer_yes = 1;
} else if (ask) {
log_warn("WARNING: PV %s is used by VG %s", pvname, vgname);
- if (yes_no_prompt("Really WIPE LABELS from physical volume \"%s\" of
volume group \"%s\" [y/n]? ", pvname, vgname) == 'n') {
- prompt->answer = PROMPT_ANSWER_NO;
- log_error("%s: physical volume label not removed", pvname);
- } else {
- prompt->answer = PROMPT_ANSWER_YES;
- }
+ if (yes_no_prompt("Really WIPE LABELS from physical volume \"%s\" of
volume group \"%s\" [y/n]? ", pvname, vgname) == 'n')
+ answer_no = 1;
+ else
+ answer_yes = 1;
}
+ }
- if ((prompt->answer == PROMPT_ANSWER_YES) && (pp->force ==
DONT_PROMPT_OVERRIDE))
- log_warn("WARNING: Wiping physical volume label from %s of volume group
\"%s\"", pvname, vgname);
+ if (answer_yes && answer_no) {
+ log_warn("WARNING: prompt answer yes is overriden by prompt answer no.");
+ answer_yes = 0;
}
+
+ /*
+ * no answer is valid when not asking the user.
+ * the caller uses this to check if all the prompts
+ * can be answered automatically without prompts.
+ */
+ if (!ask && !answer_yes && !answer_no)
+ return;
+
+ if (answer_no)
+ prompt->answer = PROMPT_ANSWER_NO;
+ else if (answer_yes)
+ prompt->answer = PROMPT_ANSWER_YES;
+
+ /*
+ * Mostly historical messages. Other messages above could be moved
+ * here to separate the answer logic from the messages.
+ */
+
+ if ((prompt->type & (PROMPT_PVCREATE_DEV_SIZE | PROMPT_PVCREATE_PV_IN_VG))
&&
+ (prompt->answer == PROMPT_ANSWER_NO))
+ log_error("%s: physical volume not initialized.", pvname);
+
+ if ((prompt->type & PROMPT_PVREMOVE_PV_IN_VG) &&
+ (prompt->answer == PROMPT_ANSWER_NO))
+ log_error("%s: physical volume label not removed.", pvname);
+
+ if ((prompt->type & PROMPT_PVREMOVE_PV_IN_VG) &&
+ (prompt->answer == PROMPT_ANSWER_YES) &&
+ (pp->force == DONT_PROMPT_OVERRIDE))
+ log_warn("WARNING: Wiping physical volume label from %s of volume group
\"%s\".", pvname, vgname);
}
static struct pvcreate_device *_pvcreate_list_find_dev(struct dm_list *devices, struct
device *dev)
@@ -4912,6 +4967,10 @@ static int _pvcreate_check_single(struct cmd_context *cmd,
struct pvcreate_params *pp = (struct pvcreate_params *) handle->custom_handle;
struct pvcreate_device *pd;
struct pvcreate_prompt *prompt;
+ uint64_t size = 0;
+ uint64_t new_size = 0;
+ int need_size_prompt = 0;
+ int need_vg_prompt = 0;
int found = 0;
if (!pv->dev)
@@ -4996,35 +5055,57 @@ static int _pvcreate_check_single(struct cmd_context *cmd,
pd->is_not_pv = 1;
}
+ if (arg_is_set(cmd, setphysicalvolumesize_ARG)) {
+ new_size = arg_uint64_value(cmd, setphysicalvolumesize_ARG, UINT64_C(0));
+
+ if (!dev_get_size(pv->dev, &size)) {
+ log_error("Can't get device size of %s.", pv_dev_name(pv));
+ dm_list_move(&pp->arg_fail, &pd->list);
+ return 1;
+ } else if (new_size != size)
+ need_size_prompt = 1;
+ }
+
/*
* pvcreate is being run on this device, and it's not a PV,
* or is an orphan PV. Neither case requires a prompt.
+ * Or, pvcreate is being run on this device, but the device
+ * is already a PV in a VG. A prompt or force option is required
+ * to use it.
*/
- if (pd->is_orphan_pv || pd->is_not_pv) {
+ if (pd->is_orphan_pv || pd->is_not_pv)
+ need_vg_prompt = 0;
+ else
+ need_vg_prompt = 1;
+
+ if (!need_size_prompt && !need_vg_prompt) {
pd->dev = pv->dev;
dm_list_move(&pp->arg_process, &pd->list);
return 1;
}
- /*
- * pvcreate is being run on this device, but the device is already
- * a PV in a VG. A prompt or force option is required to use it.
- */
if (!(prompt = dm_pool_zalloc(cmd->mem, sizeof(*prompt)))) {
log_error("prompt alloc failed.");
pp->check_failed = 1;
return 0;
}
prompt->dev = pd->dev;
- prompt->type = PROMPT_PVCREATE_PV_IN_VG;
prompt->pv_name = dm_pool_strdup(cmd->mem, pd->name);
+ prompt->size = size;
+ prompt->new_size = new_size;
if (pd->is_used_unknown_pv)
prompt->vg_name_unknown = 1;
- else
+ else if (need_vg_prompt)
prompt->vg_name = dm_pool_strdup(cmd->mem, vg->name);
- dm_list_add(&pp->prompts, &prompt->list);
+ if (need_size_prompt)
+ prompt->type |= PROMPT_PVCREATE_DEV_SIZE;
+
+ if (need_vg_prompt)
+ prompt->type |= PROMPT_PVCREATE_PV_IN_VG;
+
+ dm_list_add(&pp->prompts, &prompt->list);
pd->dev = pv->dev;
dm_list_move(&pp->arg_process, &pd->list);
@@ -5254,7 +5335,7 @@ static int _pvremove_check_single(struct cmd_context *cmd,
prompt->vg_name_unknown = 1;
else
prompt->vg_name = dm_pool_strdup(cmd->mem, vg->name);
- prompt->type = PROMPT_PVREMOVE_PV_IN_VG;
+ prompt->type |= PROMPT_PVREMOVE_PV_IN_VG;
dm_list_add(&pp->prompts, &prompt->list);
pd->dev = pv->dev;