1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-01-03 05:18:29 +03:00

toollib: add two phase pv processing code

This is common code for handling PV create/remove
that can be shared by pvcreate/vgcreate/vgextend/pvremove.
This does not change any commands to use the new code.

- 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 do not
  run any prompts while locks are held.
  The orphan lock is reacquired after any prompts are
  done, and the devices being created are checked for
  any change made while the lock was not held.

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.
This commit is contained in:
David Teigland 2016-02-16 14:15:24 -06:00
parent ff2267012a
commit 71671778ab
13 changed files with 1097 additions and 32 deletions

View File

@ -542,6 +542,62 @@ struct pvcreate_params {
struct pvcreate_restorable_params rp;
};
/*
* FIXME: rename this pvcreate_params once the old pvcreate_params is unused.
* This can probably be put in toollib.h.
*/
struct pvcreate_each_params {
/*
* From argc and argv.
*/
char **pv_names;
uint32_t pv_count;
/*
* From command line args.
*/
int zero;
uint64_t size;
uint64_t data_alignment;
uint64_t data_alignment_offset;
int pvmetadatacopies;
uint64_t pvmetadatasize;
int64_t labelsector;
force_t force;
unsigned yes;
unsigned metadataignore;
/*
* From recovery-specific command line args.
*/
const char *restorefile; /* NULL if no --restorefile option */
const char *uuid_str; /* id in printable format, NULL if no id */
struct id id;
/*
* From reading VG backup file.
*/
uint64_t ba_start;
uint64_t ba_size;
uint64_t pe_start;
uint32_t extent_count;
uint32_t extent_size;
/*
* Used for command processing.
*/
struct dm_list prompts; /* pvcreate_prompt */
struct dm_list arg_devices; /* pvcreate_device, one for each pv_name */
struct dm_list arg_process; /* pvcreate_device, used for processing */
struct dm_list arg_confirm; /* pvcreate_device, used for processing */
struct dm_list arg_create; /* pvcreate_device, used for pvcreate */
struct dm_list arg_fail; /* pvcreate_device, failed to create */
struct dm_list pvs; /* pv_list, created and usable for vgcreate/vgextend */
const char *orphan_vg_name;
unsigned preserve_existing : 1;
unsigned check_failed : 1;
};
struct lvresize_params {
const char *vg_name; /* only-used when VG is not yet opened (in /tools) */
const char *lv_name;
@ -705,6 +761,7 @@ int vg_rename(struct cmd_context *cmd, struct volume_group *vg,
const char *new_name);
int vg_extend(struct volume_group *vg, int pv_count, const char *const *pv_names,
struct pvcreate_params *pp);
int vg_extend_each_pv(struct volume_group *vg, struct pvcreate_each_params *pp);
int vg_reduce(struct volume_group *vg, const char *pv_name);
int vgreduce_single(struct cmd_context *cmd, struct volume_group *vg,

View File

@ -791,6 +791,40 @@ int vg_extend(struct volume_group *vg, int pv_count, const char *const *pv_names
return 1;
}
int vg_extend_each_pv(struct volume_group *vg, struct pvcreate_each_params *pp)
{
struct pv_list *pvl;
unsigned int max_phys_block_size = 0;
log_debug_metadata("Adding PVs to VG %s", vg->name);
if (_vg_bad_status_bits(vg, RESIZEABLE_VG))
return_0;
dm_list_iterate_items(pvl, &pp->pvs) {
log_debug_metadata("Adding PV %s to VG %s", pv_dev_name(pvl->pv), vg->name);
if (!(check_dev_block_size_for_vg(pvl->pv->dev,
(const struct volume_group *) vg,
&max_phys_block_size))) {
log_error("PV %s has wrong block size", pv_dev_name(pvl->pv));
return_0;
}
if (!add_pv_to_vg(vg, pv_dev_name(pvl->pv), pvl->pv, 0)) {
log_error("PV %s cannot be added to VG %s.",
pv_dev_name(pvl->pv), vg->name);
return_0;
}
}
(void) _check_pv_dev_sizes(vg);
dm_list_splice(&vg->pv_write_list, &pp->pvs);
return 1;
}
int vg_reduce(struct volume_group *vg, const char *pv_name)
{
struct physical_volume *pv;
@ -3839,6 +3873,8 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
struct cached_vg_fmtdata *vg_fmtdata = NULL; /* Additional format-specific data about the vg */
unsigned use_previous_vg;
log_very_verbose("Reading VG %s %.32s", vgname ?: "<no name>", vgid ?: "<no vgid>");
if (is_orphan_vg(vgname)) {
if (use_precommitted) {
log_error(INTERNAL_ERROR "vg_read_internal requires vgname "
@ -5322,6 +5358,9 @@ static struct volume_group *_vg_lock_and_read(struct cmd_context *cmd, const cha
return _vg_make_handle(cmd, vg, FAILED_LOCKING);
}
if (already_locked)
log_very_verbose("Locking %s already done", vg_name);
if (is_orphan_vg(vg_name))
status_flags &= ~LVM_WRITE;

View File

@ -766,7 +766,7 @@ xx(pvck,
xx(pvcreate,
"Initialize physical volume(s) for use by LVM",
0,
ENABLE_ALL_DEVS,
"pvcreate\n"
"\t[--norestorefile]\n"
"\t[--restorefile file]\n"
@ -1119,7 +1119,7 @@ xx(vgconvert,
xx(vgcreate,
"Create a volume group",
0,
MUST_USE_ALL_ARGS | ENABLE_ALL_DEVS,
"vgcreate\n"
"\t[-A|--autobackup {y|n}]\n"
"\t[--addtag Tag]\n"
@ -1214,7 +1214,7 @@ xx(vgexport,
xx(vgextend,
"Add physical volumes to a volume group",
0,
MUST_USE_ALL_ARGS | ENABLE_ALL_DEVS,
"vgextend\n"
"\t[-A|--autobackup y|n]\n"
"\t[--restoremissing]\n"

View File

@ -228,7 +228,7 @@ int pvchange(struct cmd_context *cmd, int argc, char **argv)
}
}
ret = process_each_pv(cmd, argc, argv, NULL, READ_FOR_UPDATE, handle, _pvchange_single);
ret = process_each_pv(cmd, argc, argv, NULL, 0, READ_FOR_UPDATE, handle, _pvchange_single);
if (!argc)
unlock_vg(cmd, VG_GLOBAL);

View File

@ -107,8 +107,9 @@ int pvdisplay(struct cmd_context *cmd, int argc, char **argv)
}
}
ret = process_each_pv(cmd, argc, argv, NULL, 0, NULL,
_pvdisplay_single);
ret = process_each_pv(cmd, argc, argv, NULL,
arg_is_set(cmd, all_ARG), 0,
NULL, _pvdisplay_single);
if (lock_global)
unlock_vg(cmd, VG_GLOBAL);

View File

@ -895,7 +895,7 @@ int pvmove(struct cmd_context *cmd, int argc, char **argv)
handle->custom_handle = &pp;
process_each_pv(cmd, 1, &pv_name, NULL,
process_each_pv(cmd, 1, &pv_name, NULL, 0,
is_abort ? 0 : READ_FOR_UPDATE,
handle,
is_abort ? &_pvmove_read_single : &_pvmove_setup_single);

View File

@ -87,7 +87,7 @@ int pvresize(struct cmd_context *cmd, int argc, char **argv)
handle->custom_handle = &params;
ret = process_each_pv(cmd, argc, argv, NULL, READ_FOR_UPDATE, handle,
ret = process_each_pv(cmd, argc, argv, NULL, 0, READ_FOR_UPDATE, handle,
_pvresize_single);
log_print_unless_silent("%d physical volume(s) resized / %d physical volume(s) "

View File

@ -422,7 +422,7 @@ int pvscan(struct cmd_context *cmd, int argc, char **argv)
handle->custom_handle = &params;
ret = process_each_pv(cmd, argc, argv, NULL, 0, handle, _pvscan_single);
ret = process_each_pv(cmd, argc, argv, NULL, 0, 0, handle, _pvscan_single);
if (!params.pvs_found)
log_print_unless_silent("No matching physical volumes found");

View File

@ -893,7 +893,8 @@ static int _report(struct cmd_context *cmd, int argc, char **argv,
break;
case PVS:
if (args_are_pvs)
r = process_each_pv(cmd, argc, argv, NULL, 0,
r = process_each_pv(cmd, argc, argv, NULL,
arg_is_set(cmd, all_ARG), 0,
&handle, &_pvs_single);
else
r = process_each_vg(cmd, argc, argv, NULL, 0,
@ -910,7 +911,8 @@ static int _report(struct cmd_context *cmd, int argc, char **argv,
break;
case PVSEGS:
if (args_are_pvs)
r = process_each_pv(cmd, argc, argv, NULL, 0,
r = process_each_pv(cmd, argc, argv, NULL,
arg_is_set(cmd, all_ARG), 0,
&handle,
lv_info_needed && !lv_segment_status_needed ? &_pvsegs_with_lv_info_single :
!lv_info_needed && lv_segment_status_needed ? &_pvsegs_with_lv_status_single :

File diff suppressed because it is too large Load Diff

View File

@ -101,8 +101,8 @@ int process_each_vg(struct cmd_context *cmd, int argc, char **argv,
struct processing_handle *handle,
process_single_vg_fn_t process_single_vg);
int process_each_pv(struct cmd_context *cmd, int argc, char **argv,
const char *vg_name, uint32_t read_flags,
int process_each_pv(struct cmd_context *cmd, int argc, char **argv, const char *vg_name,
int all_is_set, uint32_t read_flags,
struct processing_handle *handle,
process_single_pv_fn_t process_single_pv);
@ -152,6 +152,10 @@ const char *extract_vgname(struct cmd_context *cmd, const char *lv_name);
const char *skip_dev_dir(struct cmd_context *cmd, const char *vg_name,
unsigned *dev_dir_found);
void pvcreate_each_params_set_defaults(struct pvcreate_each_params *pp);
int pvcreate_each_params_from_args(struct cmd_context *cmd, struct pvcreate_each_params *pp);
int pvcreate_each_device(struct cmd_context *cmd, struct processing_handle *handle, struct pvcreate_each_params *pp);
/*
* Builds a list of pv's from the names in argv. Used in
* lvcreate/extend.

View File

@ -107,6 +107,8 @@ struct arg_value_group_list {
#define NO_METADATA_PROCESSING 0x00000040
/* Command wants to scan for new devices and force labels to be read from them all. */
#define REQUIRES_FULL_LABEL_SCAN 0x00000080
/* Command must use all specified arg names and fail if all cannot be used. */
#define MUST_USE_ALL_ARGS 0x00000100
/* a register of the lvm commands */
struct command {

View File

@ -188,7 +188,7 @@ int vgreduce(struct cmd_context *cmd, int argc, char **argv)
/* FIXME: Pass private struct through to all these functions */
/* and update in batch afterwards? */
return process_each_pv(cmd, argc, argv, vg_name,
READ_FOR_UPDATE, NULL,
0, READ_FOR_UPDATE, NULL,
_vgreduce_single);
log_verbose("Finding volume group \"%s\"", vg_name);