1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-21 13:34:40 +03:00

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.
This commit is contained in:
David Teigland 2017-04-27 12:13:09 -05:00
parent 5cf51fb2f7
commit 4f9ff14508
6 changed files with 116 additions and 35 deletions

View File

@ -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

View File

@ -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"

View File

@ -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")

View File

@ -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;

View File

@ -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;

View File

@ -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;