summaryrefslogtreecommitdiff
path: root/tools/pvcreate.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/pvcreate.c')
-rw-r--r--tools/pvcreate.c267
1 files changed, 217 insertions, 50 deletions
diff --git a/tools/pvcreate.c b/tools/pvcreate.c
index 1f45ad91d..711bf7333 100644
--- a/tools/pvcreate.c
+++ b/tools/pvcreate.c
@@ -15,6 +15,114 @@
#include "tools.h"
+int pvcreate_each_params_from_args(struct cmd_context *cmd, struct pvcreate_each_params *pp)
+{
+ pp->yes = arg_count(cmd, yes_ARG);
+ pp->force = (force_t) arg_count(cmd, force_ARG);
+
+ if (arg_int_value(cmd, labelsector_ARG, 0) >= LABEL_SCAN_SECTORS) {
+ log_error("labelsector must be less than %lu.",
+ LABEL_SCAN_SECTORS);
+ return 0;
+ } else {
+ pp->labelsector = arg_int64_value(cmd, labelsector_ARG,
+ DEFAULT_LABELSECTOR);
+ }
+
+ if (!(cmd->fmt->features & FMT_MDAS) &&
+ (arg_count(cmd, pvmetadatacopies_ARG) ||
+ arg_count(cmd, metadatasize_ARG) ||
+ arg_count(cmd, dataalignment_ARG) ||
+ arg_count(cmd, dataalignmentoffset_ARG))) {
+ log_error("Metadata and data alignment parameters only "
+ "apply to text format.");
+ return 0;
+ }
+
+ if (!(cmd->fmt->features & FMT_BAS) &&
+ arg_count(cmd, bootloaderareasize_ARG)) {
+ log_error("Bootloader area parameters only "
+ "apply to text format.");
+ return 0;
+ }
+
+ if (arg_count(cmd, metadataignore_ARG))
+ pp->metadataignore = arg_int_value(cmd, metadataignore_ARG,
+ DEFAULT_PVMETADATAIGNORE);
+ else
+ pp->metadataignore = find_config_tree_bool(cmd, metadata_pvmetadataignore_CFG, NULL);
+
+ if (arg_count(cmd, pvmetadatacopies_ARG) &&
+ !arg_int_value(cmd, pvmetadatacopies_ARG, -1) &&
+ pp->metadataignore) {
+ log_error("metadataignore only applies to metadatacopies > 0");
+ return 0;
+ }
+
+ pp->zero = arg_int_value(cmd, zero_ARG, 1);
+
+ if (arg_sign_value(cmd, dataalignment_ARG, SIGN_NONE) == SIGN_MINUS) {
+ log_error("Physical volume data alignment may not be negative.");
+ return 0;
+ }
+ pp->data_alignment = arg_uint64_value(cmd, dataalignment_ARG, UINT64_C(0));
+
+ if (pp->data_alignment > UINT32_MAX) {
+ log_error("Physical volume data alignment is too big.");
+ return 0;
+ }
+
+ if (arg_sign_value(cmd, dataalignmentoffset_ARG, SIGN_NONE) == SIGN_MINUS) {
+ log_error("Physical volume data alignment offset may not be negative");
+ return 0;
+ }
+ pp->data_alignment_offset = arg_uint64_value(cmd, dataalignmentoffset_ARG, UINT64_C(0));
+
+ if (pp->data_alignment_offset > UINT32_MAX) {
+ log_error("Physical volume data alignment offset is too big.");
+ return 0;
+ }
+
+ if ((pp->data_alignment + pp->data_alignment_offset) &&
+ (pp->pe_start != PV_PE_START_CALC)) {
+ if ((pp->data_alignment ? pp->pe_start % pp->data_alignment : pp->pe_start) != pp->data_alignment_offset) {
+ log_warn("WARNING: Ignoring data alignment %s"
+ " incompatible with restored pe_start value %s)",
+ display_size(cmd, pp->data_alignment + pp->data_alignment_offset),
+ display_size(cmd, pp->pe_start));
+ pp->data_alignment = 0;
+ pp->data_alignment_offset = 0;
+ }
+ }
+
+ if (arg_sign_value(cmd, metadatasize_ARG, SIGN_NONE) == SIGN_MINUS) {
+ log_error("Metadata size may not be negative.");
+ return 0;
+ }
+
+ if (arg_sign_value(cmd, bootloaderareasize_ARG, SIGN_NONE) == SIGN_MINUS) {
+ log_error("Bootloader area size may not be negative.");
+ return 0;
+ }
+
+ pp->pvmetadatasize = arg_uint64_value(cmd, metadatasize_ARG, UINT64_C(0));
+ if (!pp->pvmetadatasize)
+ pp->pvmetadatasize = find_config_tree_int(cmd, metadata_pvmetadatasize_CFG, NULL);
+
+ pp->pvmetadatacopies = arg_int_value(cmd, pvmetadatacopies_ARG, -1);
+ if (pp->pvmetadatacopies < 0)
+ pp->pvmetadatacopies = find_config_tree_int(cmd, metadata_pvmetadatacopies_CFG, NULL);
+
+ if (pp->pvmetadatacopies > 2) {
+ log_error("Metadatacopies may only be 0, 1 or 2");
+ return 0;
+ }
+
+ pp->ba_size = arg_uint64_value(cmd, bootloaderareasize_ARG, pp->ba_size);
+
+ return 1;
+}
+
/*
* Intial sanity checking of recovery-related command-line arguments.
* These args are: --restorefile, --uuid, and --physicalvolumesize
@@ -22,13 +130,12 @@
* Output arguments:
* pp: structure allocated by caller, fields written / validated here
*/
-static int pvcreate_restore_params_validate(struct cmd_context *cmd,
- int argc, char **argv,
- struct pvcreate_params *pp)
+static int pvcreate_each_restore_params_from_args(struct cmd_context *cmd, int argc,
+ struct pvcreate_each_params *pp)
{
const char *uuid = NULL;
- struct volume_group *vg;
- struct pv_list *existing_pvl;
+
+ pp->restorefile = arg_str_value(cmd, restorefile_ARG, NULL);
if (arg_count(cmd, restorefile_ARG) && !arg_count(cmd, uuidstr_ARG)) {
log_error("--uuid is required with --restorefile");
@@ -48,35 +155,10 @@ static int pvcreate_restore_params_validate(struct cmd_context *cmd,
return 0;
}
- if (arg_count(cmd, uuidstr_ARG)) {
- uuid = arg_str_value(cmd, uuidstr_ARG, "");
- if (!id_read_format(&pp->rp.id, uuid))
- return 0;
- pp->rp.idp = &pp->rp.id;
- lvmcache_seed_infos_from_lvmetad(cmd); /* need to check for UUID dups */
- }
-
- if (arg_count(cmd, restorefile_ARG)) {
- pp->rp.restorefile = arg_str_value(cmd, restorefile_ARG, "");
- /* The uuid won't already exist */
- if (!(vg = backup_read_vg(cmd, NULL, pp->rp.restorefile))) {
- log_error("Unable to read volume group from %s",
- pp->rp.restorefile);
- return 0;
- }
- if (!(existing_pvl = find_pv_in_vg_by_uuid(vg, pp->rp.idp))) {
- release_vg(vg);
- log_error("Can't find uuid %s in backup file %s",
- uuid, pp->rp.restorefile);
+ if (arg_count(cmd, uuidstr_ARG)) {
+ pp->uuid_str = arg_str_value(cmd, uuidstr_ARG, "");
+ if (!id_read_format(&pp->id, uuid))
return 0;
- }
- pp->rp.ba_start = pv_ba_start(existing_pvl->pv);
- pp->rp.ba_size = pv_ba_size(existing_pvl->pv);
- pp->rp.pe_start = pv_pe_start(existing_pvl->pv);
- pp->rp.extent_size = pv_pe_size(existing_pvl->pv);
- pp->rp.extent_count = pv_pe_count(existing_pvl->pv);
-
- release_vg(vg);
}
if (arg_sign_value(cmd, physicalvolumesize_ARG, SIGN_NONE) == SIGN_MINUS) {
@@ -90,34 +172,119 @@ static int pvcreate_restore_params_validate(struct cmd_context *cmd,
return 1;
}
+static int pvcreate_each_restore_params_from_backup(struct cmd_context *cmd,
+ struct pvcreate_each_params *pep)
+{
+ struct volume_group *vg;
+ struct pv_list *existing_pvl;
+ const char *uuid;
+
+ /*
+ * When restoring a PV, params need to be read from a backup file.
+ */
+ if (!pep->restorefile)
+ return 1;
+
+ uuid = arg_str_value(cmd, uuidstr_ARG, "");
+
+ if (!(vg = backup_read_vg(cmd, NULL, pep->restorefile))) {
+ log_error("Unable to read volume group from %s", pep->restorefile);
+ return 0;
+ }
+
+ if (!(existing_pvl = find_pv_in_vg_by_uuid(vg, &pep->id))) {
+ release_vg(vg);
+ log_error("Can't find uuid %s in backup file %s",
+ uuid, pep->restorefile);
+ return 0;
+ }
+
+ pep->ba_start = pv_ba_start(existing_pvl->pv);
+ pep->ba_size = pv_ba_size(existing_pvl->pv);
+ pep->pe_start = pv_pe_start(existing_pvl->pv);
+ pep->extent_size = pv_pe_size(existing_pvl->pv);
+ pep->extent_count = pv_pe_count(existing_pvl->pv);
+
+ release_vg(vg);
+ return 1;
+}
+
+void pvcreate_each_params_set_defaults(struct pvcreate_each_params *pep)
+{
+ pep->zero = 1;
+ pep->size = 0;
+ pep->data_alignment = UINT64_C(0);
+ pep->data_alignment_offset = UINT64_C(0);
+ pep->pvmetadatacopies = DEFAULT_PVMETADATACOPIES;
+ pep->pvmetadatasize = DEFAULT_PVMETADATASIZE;
+ pep->labelsector = DEFAULT_LABELSECTOR;
+ pep->force = PROMPT;
+ pep->yes = 0;
+ pep->metadataignore = DEFAULT_PVMETADATAIGNORE;
+ pep->rp.restorefile = 0;
+ pep->rp.idp = 0;
+ pep->rp.ba_start = 0;
+ pep->rp.ba_size = 0;
+ pep->rp.pe_start = PV_PE_START_CALC;
+ pep->rp.extent_count = 0;
+ pep->rp.extent_size = 0;
+
+ dm_list_init(&pep->prompts);
+ dm_list_init(&pep->arg_names);
+ dm_list_init(&pep->arg_create);
+ dm_list_init(&pep->arg_fail);
+}
+
int pvcreate(struct cmd_context *cmd, int argc, char **argv)
{
- int i;
- int ret = ECMD_PROCESSED;
- struct pvcreate_params pp;
+ struct pvcreate_each_params pep = { 0 };
+ int ret;
- /* Needed to change the set of orphan PVs. */
- if (!lockd_gl(cmd, "ex", 0))
- return_ECMD_FAILED;
+ if (!argc) {
+ log_error("Please enter a physical volume path.");
+ return 0;
+ }
- pvcreate_params_set_defaults(&pp);
+ /*
+ * Five kinds of pvcreate param values:
+ * 1. defaults
+ * 2. normal command line args
+ * 3. recovery-related command line args
+ * 4. recovery-related args from backup file
+ * 5. argc/argv free args specifying devices
+ */
- if (!pvcreate_restore_params_validate(cmd, argc, argv, &pp)) {
+ pvcreate_each_params_set_defaults(&pep);
+
+ if (!pvcreate_each_params_from_args(cmd, &pep))
return EINVALID_CMD_LINE;
- }
- if (!pvcreate_params_validate(cmd, argc, &pp)) {
+
+ if (!pvcreate_each_restore_params_from_args(cmd, argc, &pep))
return EINVALID_CMD_LINE;
- }
- for (i = 0; i < argc; i++) {
- if (sigint_caught())
- return_ECMD_FAILED;
+ if (!pvcreate_each_restore_params_from_backup(cmd, &pep))
+ return EINVALID_CMD_LINE;
- dm_unescape_colons_and_at_signs(argv[i], NULL, NULL);
+ pep->pv_count = argc;
+ pep->pv_names = argv;
- if (!pvcreate_single(cmd, argv[i], &pp))
- ret = ECMD_FAILED;
+ /*
+ * Needed to change the set of orphan PVs.
+ * (disable afterward to prevent process_each_pv from doing
+ * a shared global lock since it's already acquired it ex.)
+ */
+ if (!lockd_gl(cmd, "ex", 0))
+ return_ECMD_FAILED;
+ cmd->lockd_gl_disable = 1;
+
+ if (!lock_vol(cmd, VG_ORPHANS, LCK_VG_WRITE, NULL)) {
+ log_error("Can't get lock for orphan PVs");
+ return 0;
}
+ ret = pvcreate_each_device(cmd, &pep);
+
+ unlock_vg(cmd, VG_ORPHANS);
+
return ret;
}