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:
parent
5cf51fb2f7
commit
4f9ff14508
@ -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
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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")
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
135
tools/toollib.c
135
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;
|
||||
|
Loading…
Reference in New Issue
Block a user