summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2015-12-15 12:55:48 -0600
committerDavid Teigland <teigland@redhat.com>2015-12-15 13:49:29 -0600
commit5ee14eb0f200b7a8e8fd04c782c8d4177f054677 (patch)
tree82819d34a4b404fcbce3916833398da8c82efb43
parent796461a9125a8324a63be154fc998245617e5990 (diff)
downloadlvm2-dev-dct-pvcreate-1.tar.gz
pvcreate: restructuring to use toollibdev-dct-pvcreate-1
- Pull out the hidden equivalent of process_each_pv into an actual top level process_each_pv. - Pull the prompts to the top level, and out from under the VG locks. Previously, pvcreate_vol() was the shared function for creating a PV for pvcreate, vgcreate, vgextend. Now, it will be toollib function pvcreate_each_device(). pvcreate_vol() was called effectively as a helper, from within vgcreate and vgextend code paths. pvcreate_each_device() will be called at the same level as other process_each functions. One of the main problems with pvcreate_vol() is that it included a hidden equivalent of process_each_pv for each device being created: pvcreate_vol() -> _pvcreate_check() -> find_pv_by_name() -> get_pvs() -> get_pvs_internal() -> _get_pvs() -> get_vgids() -> /* equivalent to process_each_pv */ dm_list_iterate_items(vgids) vg = vg_read_internal() dm_list_iterate_items(&vg->pvs) pvcreate_each_device() reorganizes the code so that each-VG-each-PV loop is done once, and uses the standard process_each_pv function at the top level of the function.
-rw-r--r--lib/metadata/pv_manip.c20
-rw-r--r--tools/pvcreate.c30
-rw-r--r--tools/toollib.c148
3 files changed, 159 insertions, 39 deletions
diff --git a/lib/metadata/pv_manip.c b/lib/metadata/pv_manip.c
index e48fe42a1..09000ecde 100644
--- a/lib/metadata/pv_manip.c
+++ b/lib/metadata/pv_manip.c
@@ -852,23 +852,3 @@ out:
return ret;
}
-int pvcreate_single(struct cmd_context *cmd, const char *pv_name,
- struct pvcreate_params *pp)
-{
- int r = 0;
-
- if (!lock_vol(cmd, VG_ORPHANS, LCK_VG_WRITE, NULL)) {
- log_error("Can't get lock for orphan PVs");
- return 0;
- }
-
- if (!(pvcreate_vol(cmd, pv_name, pp, 1)))
- goto_out;
-
- r = 1;
-
-out:
- unlock_vg(cmd, VG_ORPHANS);
-
- return r;
-}
diff --git a/tools/pvcreate.c b/tools/pvcreate.c
index 1f45ad91d..e3fe61435 100644
--- a/tools/pvcreate.c
+++ b/tools/pvcreate.c
@@ -92,32 +92,26 @@ static int pvcreate_restore_params_validate(struct cmd_context *cmd,
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;
+ int ret;
+
+ /* TODO: set pep fields from args */
+
+ pep->pv_count = argc;
+ pep->pv_names = argv;
/* Needed to change the set of orphan PVs. */
if (!lockd_gl(cmd, "ex", 0))
return_ECMD_FAILED;
- pvcreate_params_set_defaults(&pp);
-
- if (!pvcreate_restore_params_validate(cmd, argc, argv, &pp)) {
- return EINVALID_CMD_LINE;
- }
- if (!pvcreate_params_validate(cmd, argc, &pp)) {
- return EINVALID_CMD_LINE;
+ if (!lock_vol(cmd, VG_ORPHANS, LCK_VG_WRITE, NULL)) {
+ log_error("Can't get lock for orphan PVs");
+ return 0;
}
- for (i = 0; i < argc; i++) {
- if (sigint_caught())
- return_ECMD_FAILED;
-
- dm_unescape_colons_and_at_signs(argv[i], NULL, NULL);
+ ret = pvcreate_each_device(cmd, &pep);
- if (!pvcreate_single(cmd, argv[i], &pp))
- ret = ECMD_FAILED;
- }
+ unlock_vg(cmd, VG_ORPHANS);
return ret;
}
diff --git a/tools/toollib.c b/tools/toollib.c
index 728e61d4d..3a70de25c 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -3289,6 +3289,7 @@ int process_each_pv(struct cmd_context *cmd,
int argc, char **argv,
const char *only_this_vgname,
uint32_t read_flags,
+ uint32_t each_flags,
struct processing_handle *handle,
process_single_pv_fn_t process_single_pv)
{
@@ -3343,7 +3344,7 @@ int process_each_pv(struct cmd_context *cmd,
process_all_pvs = dm_list_empty(&arg_pvnames) && dm_list_empty(&arg_tags);
process_all_devices = process_all_pvs && (cmd->command->flags & ENABLE_ALL_DEVS) &&
- arg_count(cmd, all_ARG);
+ (each_flags & EACH_ALL);
/* Needed for a current listing of the global VG namespace. */
if (!only_this_vgname && !lockd_gl(cmd, "sh", 0))
@@ -3498,3 +3499,148 @@ int lvremove_single(struct cmd_context *cmd, struct logical_volume *lv,
return ECMD_PROCESSED;
}
+
+struct pvcreate_device {
+ struct dm_list list;
+ const char *name;
+ struct device *dev;
+};
+
+struct prompt_device {
+ struct dm_list list;
+ const char *name;
+ struct device *dev;
+ pvcreate_prompt_fn_t pvcreate_prompt;
+};
+
+struct pvcreate_each_params {
+ char **pv_names; /* argv */
+ uint32_t pv_count; /* argc */
+ uint32_t create_count;
+ struct dm_list prompt_devices; /* struct prompt_device */
+ struct dm_list create_devices; /* struct pvcreate_device */
+};
+
+static int _pvcreate_check_single(struct cmd_context *cmd,
+ struct volume_group *vg,
+ struct physical_volume *pv,
+ struct processing_handle *handle)
+{
+
+ /*
+ * Check if pv uuid matches a new uuid specified by command.
+ * (was in pvcreate_vol, see pp->rp.idp)
+ */
+
+ /*
+ * If pv->dev matches nothing in pep->pv_names, then return.
+ */
+
+ /*
+ * If pv->dev matches something in pep->pv_names, then pvcreate
+ * is being run on this device.
+ *
+ * If vg is not NULL, then this is running pvcreate over
+ * an existing PV:
+ * . Add a prompt to pep->prompt_devices to confirm this
+ * after process_each is done.
+ * . Add an entry for pv->dev to pep->create_devices.
+ * (Will be removed if prompt is negative.)
+ *
+ * If vg is NULL, then this dev is not an existing PV:
+ * . Add an etry for pv->dev to pep->create_devices.
+ */
+
+}
+
+/*
+ * This can be used by pvcreate, vgcreate and vgextend to create PVs.
+ * The callers need to set up the pvcreate_each_params structure based
+ * on command line args. This includes the pv_names field which specifies
+ * the devices to create PVs on.
+ *
+ * This function is a specialized instance of process_each_pv() and
+ * should be called from a high level in the command.
+ */
+
+int pvcreate_each_device(struct cmd_context *cmd, struct pvcreate_each_params *pep)
+{
+
+ if (!_validate_pvcreate_each_params(pep))
+ return EINVALID_CMD_LINE;
+
+ for (i = 0; i < pep->pv_count; i++)
+ dm_unescape_colons_and_at_signs(pep->pv_names[i], NULL, NULL);
+
+ /*
+ * process all *existing* PVs and devices - this checks if pv_names
+ * entries are already PVs, and matches a known dev to each pv_names
+ * entry. A create_devices entry is added for each pv_names entry
+ * for which a matching device is found.
+ *
+ * This creates lists pep->create_devices and pep->prompt_devices.
+ * This does not modify any of the devices specified for pvcreate.
+ */
+
+ cmd->command->flags |= ENABLE_ALL_DEVS;
+
+ process_each_pv(cmd, 0, NULL, NULL, 0, EACH_ALL, handle, _pvcreate_check_single);
+
+ /*
+ * check if all pep->pv_names were found by process_each.
+ */
+
+ if (pep->create_count != pep->pv_count) {
+ }
+
+ /*
+ * process any prompts that were gathered during the process_each_pv checks
+ * (was in _pvcreate_check)
+ */
+
+ dm_list_iterate_items(prompt, &pep->prompt_devices) {
+ /* TODO: call prompt->pvcreate_prompt(prompt) */
+ }
+
+ /*
+ * wipe signatures on devices being created (was in _pvcreate_check)
+ * (pvcreate_vol also has some code to re-get the dev after the wipe.)
+ */
+
+ dm_list_iterate_items(pd, &pep->create_devices) {
+ if (!wipe_known_signatures(cmd, pd->dev, pd->name, TYPE_LVM1_MEMBER | TYPE_LVM2_MEMBER,
+ 0, pep->yes, pep->force, wiped)) {
+ }
+
+ }
+
+ /*
+ * create pvs on devices
+ */
+ dm_list_iterate_items(pd, &pep->create_devices) {
+
+ if (!(pv = pv_create(cmd, pd->dev, pp->size, pp->data_alignment,
+ pp->data_alignment_offset, pp->labelsector,
+ pp->pvmetadatacopies, pp->pvmetadatasize,
+ pp->metadataignore, &pp->rp))) {
+ }
+
+ pv->status |= UNLABELLED_PV;
+
+ /* wipe existing label (was in _pvcreate_write) */
+
+ if (!label_remove(pd->dev)) {
+ }
+
+ /* zero start of device (was in _pvcreate_write) */
+
+ if (zero) {
+ }
+
+ /* write the pv (was in _pvcreate_write) */
+
+ if (!pv_write(cmd, pv, 1)) {
+ }
+ }
+}
+