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

liblvm: Move lib code used exclusively into metadata-liblvm.c

Also remove some redundant function definitions from metadata.h.
This commit is contained in:
Alasdair G Kergon 2017-10-18 19:29:32 +01:00
parent f1cc5b12fd
commit f3ae99dcc0
9 changed files with 727 additions and 673 deletions

View File

@ -1,5 +1,6 @@
Version 2.02.176 - Version 2.02.176 -
=================================== ===================================
Move lib code used only by liblvm into metadata-liblvm.c.
Distinguish between device not found and excluded by filter. Distinguish between device not found and excluded by filter.
Monitor external origin LVs. Monitor external origin LVs.
Remove the replicator code, including configure --with-replicators. Remove the replicator code, including configure --with-replicators.

View File

@ -96,6 +96,7 @@ SOURCES =\
metadata/lv_manip.c \ metadata/lv_manip.c \
metadata/merge.c \ metadata/merge.c \
metadata/metadata.c \ metadata/metadata.c \
metadata/metadata-liblvm.c \
metadata/mirror.c \ metadata/mirror.c \
metadata/pool_manip.c \ metadata/pool_manip.c \
metadata/pv.c \ metadata/pv.c \

View File

@ -688,9 +688,9 @@ uint32_t vg_read_error(struct volume_group *vg_handle);
struct physical_volume *pv_create(const struct cmd_context *cmd, struct physical_volume *pv_create(const struct cmd_context *cmd,
struct device *dev, struct pv_create_args *pva); struct device *dev, struct pv_create_args *pva);
int pvremove_single(struct cmd_context *cmd, const char *pv_name, struct physical_volume *pvcreate_vol(struct cmd_context *cmd, const char *pv_name,
void *handle __attribute__((unused)), unsigned force_count, struct pvcreate_params *pp, int write_now);
unsigned prompt, struct dm_list *pvslist);
int pvremove_many(struct cmd_context *cmd, struct dm_list *pv_names, int pvremove_many(struct cmd_context *cmd, struct dm_list *pv_names,
unsigned force_count, unsigned prompt); unsigned force_count, unsigned prompt);

View File

@ -0,0 +1,701 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* This file contains functions now used only by liblvm.
* Ideally this file should be empty as liblvm and toollib should be doing identical things.
* FIXME Merge all the code into different parts of the tree.
*/
#include "lib.h"
#include "toolcontext.h"
#include "lvm-string.h"
#include "metadata.h"
#include "label.h"
#include "lvm-signal.h"
#include "lvmcache.h"
#include "lvmetad.h"
int vg_reduce(struct volume_group *vg, const char *pv_name)
{
struct physical_volume *pv;
struct pv_list *pvl;
if (!(pvl = find_pv_in_vg(vg, pv_name))) {
log_error("Physical volume %s not in volume group %s.",
pv_name, vg->name);
return 0;
}
pv = pvl->pv;
if (vgreduce_single(vg->cmd, vg, pv, 0)) {
dm_list_add(&vg->removed_pvs, &pvl->list);
return 1;
}
log_error("Unable to remove physical volume '%s' from "
"volume group '%s'.", pv_name, vg->name);
return 0;
}
static int _pvcreate_write(struct cmd_context *cmd, struct pv_to_write *pvw)
{
struct physical_volume *pv = pvw->pv;
struct device *dev = pv->dev;
const char *pv_name = dev_name(dev);
if (pvw->new_pv) {
/* Wipe existing label first */
if (!label_remove(pv_dev(pv))) {
log_error("Failed to wipe existing label on %s", pv_name);
return 0;
}
if (pvw->pp->zero) {
log_verbose("Zeroing start of device %s", pv_name);
if (!dev_open_quiet(dev)) {
log_error("%s not opened: device not zeroed", pv_name);
return 0;
}
if (!dev_set(dev, UINT64_C(0), (size_t) 2048, 0)) {
log_error("%s not wiped: aborting", pv_name);
if (!dev_close(dev))
stack;
return 0;
}
if (!dev_close(dev))
stack;
}
}
log_verbose("Writing physical volume data to disk \"%s\"",
pv_name);
if (!(pv_write(cmd, pv, 1))) {
log_error("Failed to write physical volume \"%s\"", pv_name);
return 0;
}
if (pvw->new_pv)
log_print_unless_silent("Physical volume \"%s\" successfully created", pv_name);
else
log_verbose("Physical volume \"%s\" successfully written", pv_name);
return 1;
}
static int _verify_pv_create_params(struct pvcreate_params *pp)
{
/*
* FIXME: Some of these checks are duplicates in pvcreate_params_validate.
*/
if (pp->pva.pvmetadatacopies > 2) {
log_error("Metadatacopies may only be 0, 1 or 2");
return 0;
}
if (pp->pva.data_alignment > UINT32_MAX) {
log_error("Physical volume data alignment is too big.");
return 0;
}
if (pp->pva.data_alignment_offset > UINT32_MAX) {
log_error("Physical volume data alignment offset is too big.");
return 0;
}
return 1;
}
/*
* See if we may pvcreate on this device.
* 0 indicates we may not.
*/
static int _pvcreate_check(struct cmd_context *cmd, const char *name,
struct pvcreate_params *pp, int *wiped)
{
static const char really_init_msg[] = "Really INITIALIZE physical volume";
static const char not_init_msg[] = "physical volume not initialized";
struct physical_volume *pv;
struct device *dev;
int r = 0;
int scan_needed = 0;
int filter_refresh_needed = 0;
int used;
/* FIXME Check partition type is LVM unless --force is given */
*wiped = 0;
/* Is there a pv here already? */
pv = find_pv_by_name(cmd, name, 1, 1);
/* Allow partial & exported VGs to be destroyed. */
/* We must have -ff to overwrite a non orphan */
if (pv) {
if (!is_orphan(pv) && pp->force != DONT_PROMPT_OVERRIDE) {
log_error("Can't initialize physical volume \"%s\" of "
"volume group \"%s\" without -ff.", name, pv_vg_name(pv));
goto out;
}
if ((used = is_used_pv(pv)) < 0)
goto_out;
if (used && pp->force != DONT_PROMPT_OVERRIDE) {
log_error("PV %s is used by a VG but its metadata is missing.", name);
log_error("Can't initialize PV '%s' without -ff.", name);
goto out;
}
}
/* prompt */
if (pv && !pp->yes) {
if (is_orphan(pv)) {
if (used) {
if (yes_no_prompt("%s \"%s\" that is marked as belonging to a VG [y/n]? ",
really_init_msg, name) == 'n') {
log_error("%s: %s", name, not_init_msg);
goto out;
}
}
} else {
if (yes_no_prompt("%s \"%s\" of volume group \"%s\" [y/n]? ",
really_init_msg, name, pv_vg_name(pv)) == 'n') {
log_error("%s: %s", name, not_init_msg);
goto out;
}
}
}
if (sigint_caught())
goto_out;
dev = dev_cache_get(name, cmd->full_filter);
/*
* Refresh+rescan at the end is needed if:
* - we don't obtain device list from udev,
* hence persistent cache file is used
* and we need to trash it and reevaluate
* for any changes done outside - adding
* any new foreign signature which may affect
* filtering - before we do pvcreate, we
* need to be sure that we have up-to-date
* view for filters
*
* - we have wiped existing foreign signatures
* from dev as this may affect what's filtered
* as well
*
*
* Only rescan at the end is needed if:
* - we've just checked whether dev is fileterd
* by MD filter. We do the refresh in-situ,
* so no need to require the refresh at the
* end of this fn. This is to allow for
* wiping MD signature during pvcreate for
* the dev - the dev would normally be
* filtered because of MD filter.
* This is an exception.
*/
/* Is there an md superblock here? */
if (!dev && md_filtering()) {
if (!refresh_filters(cmd))
goto_out;
init_md_filtering(0);
dev = dev_cache_get(name, cmd->full_filter);
init_md_filtering(1);
scan_needed = 1;
} else if (!obtain_device_list_from_udev())
filter_refresh_needed = scan_needed = 1;
if (!dev) {
log_error("Device %s not found (or ignored by filtering).", name);
goto out;
}
/*
* This test will fail if the device belongs to an MD array.
*/
if (!dev_test_excl(dev)) {
/* FIXME Detect whether device-mapper itself is still using it */
log_error("Can't open %s exclusively. Mounted filesystem?",
name);
goto out;
}
if (!wipe_known_signatures(cmd, dev, name,
TYPE_LVM1_MEMBER | TYPE_LVM2_MEMBER,
0, pp->yes, pp->force, wiped)) {
log_error("Aborting pvcreate on %s.", name);
goto out;
}
if (*wiped)
filter_refresh_needed = scan_needed = 1;
if (sigint_caught())
goto_out;
if (pv && !is_orphan(pv) && pp->force)
log_warn("WARNING: Forcing physical volume creation on "
"%s%s%s%s", name,
!is_orphan(pv) ? " of volume group \"" : "",
pv_vg_name(pv),
!is_orphan(pv) ? "\"" : "");
r = 1;
out:
if (filter_refresh_needed)
if (!refresh_filters(cmd)) {
stack;
r = 0;
}
if (scan_needed) {
lvmcache_force_next_label_scan();
if (!lvmcache_label_scan(cmd)) {
stack;
r = 0;
}
}
free_pv_fid(pv);
return r;
}
/*
* pvcreate_vol() - initialize a device with PV label and metadata area
*
* Parameters:
* - pv_name: device path to initialize
* - pp: parameters to pass to pv_create; if NULL, use default values
*
* Returns:
* NULL: error
* struct physical_volume * (non-NULL): handle to physical volume created
*/
struct physical_volume *pvcreate_vol(struct cmd_context *cmd, const char *pv_name,
struct pvcreate_params *pp, int write_now)
{
struct physical_volume *pv = NULL;
struct device *dev;
int wiped = 0;
struct dm_list mdas;
struct pvcreate_params default_pp;
char buffer[64] __attribute__((aligned(8)));
dev_ext_t dev_ext_src;
pvcreate_params_set_defaults(&default_pp);
if (!pp)
pp = &default_pp;
if (!_verify_pv_create_params(pp)) {
goto bad;
}
if (pp->pva.idp) {
if ((dev = lvmcache_device_from_pvid(cmd, pp->pva.idp, NULL, NULL)) &&
(dev != dev_cache_get(pv_name, cmd->full_filter))) {
if (!id_write_format((const struct id*)&pp->pva.idp->uuid,
buffer, sizeof(buffer)))
goto_bad;
log_error("uuid %s already in use on \"%s\"", buffer,
dev_name(dev));
goto bad;
}
}
if (!_pvcreate_check(cmd, pv_name, pp, &wiped))
goto_bad;
if (sigint_caught())
goto_bad;
/*
* wipe_known_signatures called in _pvcreate_check fires
* WATCH event to update udev database. But at the moment,
* we have no way to synchronize with such event - we may
* end up still seeing the old info in udev db and pvcreate
* can fail to proceed because of the device still being
* filtered (because of the stale info in udev db).
* Disable udev dev-ext source temporarily here for
* this reason and rescan with DEV_EXT_NONE dev-ext
* source (so filters use DEV_EXT_NONE source).
*/
dev_ext_src = external_device_info_source();
if (wiped && (dev_ext_src == DEV_EXT_UDEV))
init_external_device_info_source(DEV_EXT_NONE);
dev = dev_cache_get(pv_name, cmd->full_filter);
init_external_device_info_source(dev_ext_src);
if (!dev) {
log_error("%s: Couldn't find device. Check your filters?",
pv_name);
goto bad;
}
dm_list_init(&mdas);
if (!(pv = pv_create(cmd, dev, &pp->pva))) {
log_error("Failed to setup physical volume \"%s\"", pv_name);
goto bad;
}
log_verbose("Set up physical volume for \"%s\" with %" PRIu64
" available sectors", pv_name, pv_size(pv));
pv->status |= UNLABELLED_PV;
if (write_now) {
struct pv_to_write pvw;
pvw.pp = pp;
pvw.pv = pv;
pvw.new_pv = 1;
if (!_pvcreate_write(cmd, &pvw))
goto bad;
}
return pv;
bad:
return NULL;
}
/*
* Extend a VG by a single PV / device path
*
* Parameters:
* - vg: handle of volume group to extend by 'pv_name'
* - pv_name: device path of PV to add to VG
* - pp: parameters to pass to implicit pvcreate; if NULL, do not pvcreate
* - max_phys_block_size: largest physical block size found amongst PVs in a VG
*
*/
static int _vg_extend_single_pv(struct volume_group *vg, char *pv_name,
struct pvcreate_params *pp,
unsigned int *max_phys_block_size)
{
struct physical_volume *pv;
struct pv_to_write *pvw;
int new_pv = 0;
pv = find_pv_by_name(vg->cmd, pv_name, 1, 1);
if (!pv && !pp) {
log_error("%s not identified as an existing "
"physical volume", pv_name);
return 0;
}
if (!pv && pp) {
if (!(pv = pvcreate_vol(vg->cmd, pv_name, pp, 0)))
return_0;
new_pv = 1;
}
if (!(check_dev_block_size_for_vg(pv->dev, (const struct volume_group *) vg,
max_phys_block_size)))
goto_bad;
if (!add_pv_to_vg(vg, pv_name, pv, new_pv))
goto_bad;
if ((pv->fmt->features & FMT_PV_FLAGS) ||
(pv->status & UNLABELLED_PV)) {
if (!(pvw = dm_pool_zalloc(vg->vgmem, sizeof(*pvw)))) {
log_error("pv_to_write allocation for '%s' failed", pv_name);
return 0;
}
pvw->pv = pv;
pvw->pp = new_pv ? pp : NULL;
pvw->new_pv = new_pv;
dm_list_add(&vg->pvs_to_write, &pvw->list);
}
return 1;
bad:
free_pv_fid(pv);
return 0;
}
/*
* Extend a VG by a single PV / device path
*
* Parameters:
* - vg: handle of volume group to extend by 'pv_name'
* - pv_count: count of device paths of PVs
* - pv_names: device paths of PVs to add to VG
* - pp: parameters to pass to implicit pvcreate; if NULL, do not pvcreate
*
*/
int vg_extend(struct volume_group *vg, int pv_count, const char *const *pv_names,
struct pvcreate_params *pp)
{
int i;
char *pv_name;
unsigned int max_phys_block_size = 0;
if (vg_bad_status_bits(vg, RESIZEABLE_VG))
return_0;
/* attach each pv */
for (i = 0; i < pv_count; i++) {
if (!(pv_name = dm_strdup(pv_names[i]))) {
log_error("Failed to duplicate pv name %s.", pv_names[i]);
return 0;
}
dm_unescape_colons_and_at_signs(pv_name, NULL, NULL);
if (!_vg_extend_single_pv(vg, pv_name, pp, &max_phys_block_size)) {
log_error("Unable to add physical volume '%s' to "
"volume group '%s'.", pv_name, vg->name);
dm_free(pv_name);
return 0;
}
dm_free(pv_name);
}
(void) check_pv_dev_sizes(vg);
/* FIXME Decide whether to initialise and add new mdahs to format instance */
return 1;
}
/*
* Decide whether it is "safe" to wipe the labels on this device.
* 0 indicates we may not.
*/
static int _pvremove_check(struct cmd_context *cmd, const char *name,
unsigned force_count, unsigned prompt, struct dm_list *pvslist)
{
static const char really_wipe_msg[] = "Really WIPE LABELS from physical volume";
struct device *dev;
struct label *label;
struct pv_list *pvl;
struct physical_volume *pv = NULL;
int used;
int r = 0;
/* FIXME Check partition type is LVM unless --force is given */
if (!(dev = dev_cache_get(name, cmd->filter))) {
log_error("Device %s not found.", name);
return 0;
}
/* Is there a pv here already? */
/* If not, this is an error unless you used -f. */
if (!label_read(dev, &label, 0)) {
if (force_count)
return 1;
log_error("No PV label found on %s.", name);
return 0;
}
dm_list_iterate_items(pvl, pvslist)
if (pvl->pv->dev == dev)
pv = pvl->pv;
if (!pv) {
log_error(INTERNAL_ERROR "Physical Volume %s has a label, "
"but is neither in a VG nor orphan.", name);
goto out; /* better safe than sorry */
}
if (is_orphan(pv)) {
if ((used = is_used_pv(pv)) < 0)
goto_out;
if (used) {
log_warn("WARNING: PV %s is used by a VG but its metadata is missing.", name);
if (force_count < 2)
goto_bad;
if (!prompt &&
yes_no_prompt("%s \"%s\" that is marked as belonging to a VG [y/n]? ",
really_wipe_msg, name) == 'n')
goto_bad;
}
} else {
log_warn("WARNING: PV %s is used by VG %s (consider using vgreduce).", name, pv_vg_name(pv));
if (force_count < 2)
goto_bad;
if (!prompt &&
yes_no_prompt("%s \"%s\" of volume group \"%s\" [y/n]? ",
really_wipe_msg, name, pv_vg_name(pv)) == 'n')
goto_bad;
}
if (force_count)
log_warn("WARNING: Wiping physical volume label from "
"%s%s%s%s", name,
!is_orphan(pv) ? " of volume group \"" : "",
pv_vg_name(pv),
!is_orphan(pv) ? "\"" : "");
r = 1;
bad:
if (!r) {
log_error("%s: physical volume label not removed.", name);
if (force_count < 2) /* Show hint as log_error() */
log_error("(If you are certain you need pvremove, "
"then confirm by using --force twice.)");
}
out:
return r;
}
static int _pvremove_single(struct cmd_context *cmd, const char *pv_name,
void *handle __attribute__((unused)), unsigned force_count,
unsigned prompt, struct dm_list *pvslist)
{
struct device *dev;
struct lvmcache_info *info;
int r = 0;
if (!_pvremove_check(cmd, pv_name, force_count, prompt, pvslist))
goto out;
if (!(dev = dev_cache_get(pv_name, cmd->filter))) {
log_error("%s: Couldn't find device. Check your filters?",
pv_name);
goto out;
}
info = lvmcache_info_from_pvid(dev->pvid, dev, 0);
if (!dev_test_excl(dev)) {
/* FIXME Detect whether device-mapper is still using the device */
log_error("Can't open %s exclusively - not removing. "
"Mounted filesystem?", dev_name(dev));
goto out;
}
/* Wipe existing label(s) */
if (!label_remove(dev)) {
log_error("Failed to wipe existing label(s) on %s", pv_name);
goto out;
}
if (info)
lvmcache_del(info);
if (!lvmetad_pv_gone_by_dev(dev))
goto_out;
log_print_unless_silent("Labels on physical volume \"%s\" successfully wiped",
pv_name);
r = 1;
out:
return r;
}
int pvremove_many(struct cmd_context *cmd, struct dm_list *pv_names,
unsigned force_count, unsigned prompt)
{
int ret = 1;
struct dm_list *pvslist = NULL;
struct pv_list *pvl;
const struct dm_str_list *pv_name;
if (!lock_vol(cmd, VG_ORPHANS, LCK_VG_WRITE, NULL)) {
log_error("Can't get lock for orphan PVs");
return 0;
}
lvmcache_seed_infos_from_lvmetad(cmd);
if (!(pvslist = get_pvs(cmd))) {
ret = 0;
goto_out;
}
dm_list_iterate_items(pv_name, pv_names) {
if (!_pvremove_single(cmd, pv_name->str, NULL, force_count, prompt, pvslist)) {
stack;
ret = 0;
}
if (sigint_caught()) {
ret = 0;
goto_out;
}
}
out:
unlock_vg(cmd, NULL, VG_ORPHANS);
if (pvslist)
dm_list_iterate_items(pvl, pvslist)
free_pv_fid(pvl->pv);
return ret;
}
/* FIXME: liblvm todo - make into function that returns handle */
struct physical_volume *find_pv_by_name(struct cmd_context *cmd,
const char *pv_name,
int allow_orphan, int allow_unformatted)
{
struct device *dev;
struct pv_list *pvl;
struct dm_list *pvslist;
struct physical_volume *pv = NULL;
lvmcache_seed_infos_from_lvmetad(cmd);
if (!(dev = dev_cache_get(pv_name, cmd->filter))) {
if (!allow_unformatted)
log_error("Physical volume %s not found", pv_name);
return_NULL;
}
if (!(pvslist = get_pvs(cmd)))
return_NULL;
dm_list_iterate_items(pvl, pvslist)
if (pvl->pv->dev == dev)
pv = pvl->pv;
else
free_pv_fid(pvl->pv);
if (!pv && !allow_unformatted)
log_error("Physical volume %s not found", pv_name);
if (pv && !allow_orphan && is_orphan_vg(pv->vg_name)) {
log_error("Physical volume %s not in a volume group", pv_name);
goto bad;
}
return pv;
bad:
free_pv_fid(pv);
return NULL;
}

View File

@ -44,9 +44,6 @@ static struct physical_volume *_pv_read(struct cmd_context *cmd,
struct format_instance *fid, struct format_instance *fid,
uint32_t warn_flags, int scan_label_only); uint32_t warn_flags, int scan_label_only);
static uint32_t _vg_bad_status_bits(const struct volume_group *vg,
uint64_t status);
static int _alignment_overrides_default(unsigned long data_alignment, static int _alignment_overrides_default(unsigned long data_alignment,
unsigned long default_pe_align) unsigned long default_pe_align)
{ {
@ -177,8 +174,8 @@ void del_pvl_from_vgs(struct volume_group *vg, struct pv_list *pvl)
* 1 - success * 1 - success
* FIXME: remove pv_name - obtain safely from pv * FIXME: remove pv_name - obtain safely from pv
*/ */
static int _add_pv_to_vg(struct volume_group *vg, const char *pv_name, int add_pv_to_vg(struct volume_group *vg, const char *pv_name,
struct physical_volume *pv, int new_pv) struct physical_volume *pv, int new_pv)
{ {
struct pv_list *pvl; struct pv_list *pvl;
struct format_instance *fid = vg->fid; struct format_instance *fid = vg->fid;
@ -387,8 +384,8 @@ static int _move_pv(struct volume_group *vg_from, struct volume_group *vg_to,
return 0; return 0;
} }
if (_vg_bad_status_bits(vg_from, RESIZEABLE_VG) || if (vg_bad_status_bits(vg_from, RESIZEABLE_VG) ||
_vg_bad_status_bits(vg_to, RESIZEABLE_VG)) vg_bad_status_bits(vg_to, RESIZEABLE_VG))
return 0; return 0;
del_pvl_from_vgs(vg_from, pvl); del_pvl_from_vgs(vg_from, pvl);
@ -427,8 +424,8 @@ int move_pvs_used_by_lv(struct volume_group *vg_from,
return 0; return 0;
} }
if (_vg_bad_status_bits(vg_from, RESIZEABLE_VG) || if (vg_bad_status_bits(vg_from, RESIZEABLE_VG) ||
_vg_bad_status_bits(vg_to, RESIZEABLE_VG)) vg_bad_status_bits(vg_to, RESIZEABLE_VG))
return 0; return 0;
dm_list_iterate_items(lvseg, &lvl->lv->segments) { dm_list_iterate_items(lvseg, &lvl->lv->segments) {
@ -675,7 +672,7 @@ int vg_check_pv_dev_block_sizes(const struct volume_group *vg)
return 1; return 1;
} }
static int _check_pv_dev_sizes(struct volume_group *vg) int check_pv_dev_sizes(struct volume_group *vg)
{ {
struct pv_list *pvl; struct pv_list *pvl;
uint64_t dev_size, size; uint64_t dev_size, size;
@ -710,125 +707,16 @@ static int _check_pv_dev_sizes(struct volume_group *vg)
return r; return r;
} }
/*
* Extend a VG by a single PV / device path
*
* Parameters:
* - vg: handle of volume group to extend by 'pv_name'
* - pv_name: device path of PV to add to VG
* - pp: parameters to pass to implicit pvcreate; if NULL, do not pvcreate
* - max_phys_block_size: largest physical block size found amongst PVs in a VG
*
*/
static int _vg_extend_single_pv(struct volume_group *vg, char *pv_name,
struct pvcreate_params *pp,
unsigned int *max_phys_block_size)
{
struct physical_volume *pv;
struct pv_to_write *pvw;
int new_pv = 0;
pv = find_pv_by_name(vg->cmd, pv_name, 1, 1);
if (!pv && !pp) {
log_error("%s not identified as an existing "
"physical volume", pv_name);
return 0;
}
if (!pv && pp) {
if (!(pv = pvcreate_vol(vg->cmd, pv_name, pp, 0)))
return_0;
new_pv = 1;
}
if (!(check_dev_block_size_for_vg(pv->dev, (const struct volume_group *) vg,
max_phys_block_size)))
goto_bad;
if (!_add_pv_to_vg(vg, pv_name, pv, new_pv))
goto_bad;
if ((pv->fmt->features & FMT_PV_FLAGS) ||
(pv->status & UNLABELLED_PV)) {
if (!(pvw = dm_pool_zalloc(vg->vgmem, sizeof(*pvw)))) {
log_error("pv_to_write allocation for '%s' failed", pv_name);
return 0;
}
pvw->pv = pv;
pvw->pp = new_pv ? pp : NULL;
pvw->new_pv = new_pv;
dm_list_add(&vg->pvs_to_write, &pvw->list);
}
return 1;
bad:
free_pv_fid(pv);
return 0;
}
/* /*
* FIXME: commands shifting to common code in toollib have left a large * FIXME: commands shifting to common code in toollib have left a large
* amount of code only used by liblvm. Either remove this by shifting * amount of code only used by liblvm. Either remove this by shifting
* liblvm to use toollib, or isolate all this code into a liblvm-specific * liblvm to use toollib, or isolate all this code into a liblvm-specific
* source file. All the following and more are only used by liblvm: * source file. All the following and more are only used by liblvm:
* *
* . vg_extend()
* . _vg_extend_single_pv()
* . pvcreate_vol()
* . _pvcreate_check()
* . _pvcreate_write()
* . pvremove_many()
* . pvremove_single()
* . find_pv_by_name()
* . get_pvs() * . get_pvs()
* . the vg->pvs_to_write list and pv_to_write struct * . the vg->pvs_to_write list and pv_to_write struct
* . vg_reduce()
*/ */
/*
* Extend a VG by a single PV / device path
*
* Parameters:
* - vg: handle of volume group to extend by 'pv_name'
* - pv_count: count of device paths of PVs
* - pv_names: device paths of PVs to add to VG
* - pp: parameters to pass to implicit pvcreate; if NULL, do not pvcreate
*
*/
int vg_extend(struct volume_group *vg, int pv_count, const char *const *pv_names,
struct pvcreate_params *pp)
{
int i;
char *pv_name;
unsigned int max_phys_block_size = 0;
if (_vg_bad_status_bits(vg, RESIZEABLE_VG))
return_0;
/* attach each pv */
for (i = 0; i < pv_count; i++) {
if (!(pv_name = dm_strdup(pv_names[i]))) {
log_error("Failed to duplicate pv name %s.", pv_names[i]);
return 0;
}
dm_unescape_colons_and_at_signs(pv_name, NULL, NULL);
if (!_vg_extend_single_pv(vg, pv_name, pp, &max_phys_block_size)) {
log_error("Unable to add physical volume '%s' to "
"volume group '%s'.", pv_name, vg->name);
dm_free(pv_name);
return 0;
}
dm_free(pv_name);
}
(void) _check_pv_dev_sizes(vg);
/* FIXME Decide whether to initialise and add new mdahs to format instance */
return 1;
}
int vg_extend_each_pv(struct volume_group *vg, struct pvcreate_params *pp) int vg_extend_each_pv(struct volume_group *vg, struct pvcreate_params *pp)
{ {
struct pv_list *pvl; struct pv_list *pvl;
@ -836,7 +724,7 @@ int vg_extend_each_pv(struct volume_group *vg, struct pvcreate_params *pp)
log_debug_metadata("Adding PVs to VG %s.", vg->name); log_debug_metadata("Adding PVs to VG %s.", vg->name);
if (_vg_bad_status_bits(vg, RESIZEABLE_VG)) if (vg_bad_status_bits(vg, RESIZEABLE_VG))
return_0; return_0;
dm_list_iterate_items(pvl, &pp->pvs) { dm_list_iterate_items(pvl, &pp->pvs) {
@ -849,44 +737,20 @@ int vg_extend_each_pv(struct volume_group *vg, struct pvcreate_params *pp)
return 0; return 0;
} }
if (!_add_pv_to_vg(vg, pv_dev_name(pvl->pv), pvl->pv, 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.", log_error("PV %s cannot be added to VG %s.",
pv_dev_name(pvl->pv), vg->name); pv_dev_name(pvl->pv), vg->name);
return 0; return 0;
} }
} }
(void) _check_pv_dev_sizes(vg); (void) check_pv_dev_sizes(vg);
dm_list_splice(&vg->pv_write_list, &pp->pvs); dm_list_splice(&vg->pv_write_list, &pp->pvs);
return 1; return 1;
} }
int vg_reduce(struct volume_group *vg, const char *pv_name)
{
struct physical_volume *pv;
struct pv_list *pvl;
if (!(pvl = find_pv_in_vg(vg, pv_name))) {
log_error("Physical volume %s not in volume group %s.",
pv_name, vg->name);
return 0;
}
pv = pvl->pv;
if (vgreduce_single(vg->cmd, vg, pv, 0)) {
dm_list_add(&vg->removed_pvs, &pvl->list);
return 1;
}
log_error("Unable to remove physical volume '%s' from "
"volume group '%s'.", pv_name, vg->name);
return 0;
}
int lv_change_tag(struct logical_volume *lv, const char *tag, int add_tag) int lv_change_tag(struct logical_volume *lv, const char *tag, int add_tag)
{ {
char *tag_new; char *tag_new;
@ -1573,168 +1437,6 @@ void pvcreate_params_set_defaults(struct pvcreate_params *pp)
dm_list_init(&pp->pvs); dm_list_init(&pp->pvs);
} }
/*
* See if we may pvcreate on this device.
* 0 indicates we may not.
*/
static int _pvcreate_check(struct cmd_context *cmd, const char *name,
struct pvcreate_params *pp, int *wiped)
{
static const char really_init_msg[] = "Really INITIALIZE physical volume";
static const char not_init_msg[] = "physical volume not initialized";
struct physical_volume *pv;
struct device *dev;
int r = 0;
int scan_needed = 0;
int filter_refresh_needed = 0;
int used;
/* FIXME Check partition type is LVM unless --force is given */
*wiped = 0;
/* Is there a pv here already? */
pv = find_pv_by_name(cmd, name, 1, 1);
/* Allow partial & exported VGs to be destroyed. */
/* We must have -ff to overwrite a non orphan */
if (pv) {
if (!is_orphan(pv) && pp->force != DONT_PROMPT_OVERRIDE) {
log_error("Can't initialize physical volume \"%s\" of "
"volume group \"%s\" without -ff.", name, pv_vg_name(pv));
goto out;
}
if ((used = is_used_pv(pv)) < 0)
goto_out;
if (used && pp->force != DONT_PROMPT_OVERRIDE) {
log_error("PV %s is used by a VG but its metadata is missing.", name);
log_error("Can't initialize PV '%s' without -ff.", name);
goto out;
}
}
/* prompt */
if (pv && !pp->yes) {
if (is_orphan(pv)) {
if (used) {
if (yes_no_prompt("%s \"%s\" that is marked as belonging to a VG [y/n]? ",
really_init_msg, name) == 'n') {
log_error("%s: %s", name, not_init_msg);
goto out;
}
}
} else {
if (yes_no_prompt("%s \"%s\" of volume group \"%s\" [y/n]? ",
really_init_msg, name, pv_vg_name(pv)) == 'n') {
log_error("%s: %s", name, not_init_msg);
goto out;
}
}
}
if (sigint_caught())
goto_out;
dev = dev_cache_get(name, cmd->full_filter);
/*
* Refresh+rescan at the end is needed if:
* - we don't obtain device list from udev,
* hence persistent cache file is used
* and we need to trash it and reevaluate
* for any changes done outside - adding
* any new foreign signature which may affect
* filtering - before we do pvcreate, we
* need to be sure that we have up-to-date
* view for filters
*
* - we have wiped existing foreign signatures
* from dev as this may affect what's filtered
* as well
*
*
* Only rescan at the end is needed if:
* - we've just checked whether dev is fileterd
* by MD filter. We do the refresh in-situ,
* so no need to require the refresh at the
* end of this fn. This is to allow for
* wiping MD signature during pvcreate for
* the dev - the dev would normally be
* filtered because of MD filter.
* This is an exception.
*/
/* Is there an md superblock here? */
if (!dev && md_filtering()) {
if (!refresh_filters(cmd))
goto_out;
init_md_filtering(0);
dev = dev_cache_get(name, cmd->full_filter);
init_md_filtering(1);
scan_needed = 1;
} else if (!obtain_device_list_from_udev())
filter_refresh_needed = scan_needed = 1;
if (!dev) {
log_error("Device %s not found (or ignored by filtering).", name);
goto out;
}
/*
* This test will fail if the device belongs to an MD array.
*/
if (!dev_test_excl(dev)) {
/* FIXME Detect whether device-mapper itself is still using it */
log_error("Can't open %s exclusively. Mounted filesystem?",
name);
goto out;
}
if (!wipe_known_signatures(cmd, dev, name,
TYPE_LVM1_MEMBER | TYPE_LVM2_MEMBER,
0, pp->yes, pp->force, wiped)) {
log_error("Aborting pvcreate on %s.", name);
goto out;
}
if (*wiped)
filter_refresh_needed = scan_needed = 1;
if (sigint_caught())
goto_out;
if (pv && !is_orphan(pv) && pp->force)
log_warn("WARNING: Forcing physical volume creation on "
"%s%s%s%s", name,
!is_orphan(pv) ? " of volume group \"" : "",
pv_vg_name(pv),
!is_orphan(pv) ? "\"" : "");
r = 1;
out:
if (filter_refresh_needed)
if (!refresh_filters(cmd)) {
stack;
r = 0;
}
if (scan_needed) {
lvmcache_force_next_label_scan();
if (!lvmcache_label_scan(cmd)) {
stack;
r = 0;
}
}
free_pv_fid(pv);
return r;
}
static int _pvcreate_write(struct cmd_context *cmd, struct pv_to_write *pvw) static int _pvcreate_write(struct cmd_context *cmd, struct pv_to_write *pvw)
{ {
struct physical_volume *pv = pvw->pv; struct physical_volume *pv = pvw->pv;
@ -1782,129 +1484,6 @@ static int _pvcreate_write(struct cmd_context *cmd, struct pv_to_write *pvw)
return 1; return 1;
} }
static int _verify_pv_create_params(struct pvcreate_params *pp)
{
/*
* FIXME: Some of these checks are duplicates in pvcreate_params_validate.
*/
if (pp->pva.pvmetadatacopies > 2) {
log_error("Metadatacopies may only be 0, 1 or 2");
return 0;
}
if (pp->pva.data_alignment > UINT32_MAX) {
log_error("Physical volume data alignment is too big.");
return 0;
}
if (pp->pva.data_alignment_offset > UINT32_MAX) {
log_error("Physical volume data alignment offset is too big.");
return 0;
}
return 1;
}
/*
* pvcreate_vol() - initialize a device with PV label and metadata area
*
* Parameters:
* - pv_name: device path to initialize
* - pp: parameters to pass to pv_create; if NULL, use default values
*
* Returns:
* NULL: error
* struct physical_volume * (non-NULL): handle to physical volume created
*/
struct physical_volume *pvcreate_vol(struct cmd_context *cmd, const char *pv_name,
struct pvcreate_params *pp, int write_now)
{
struct physical_volume *pv = NULL;
struct device *dev;
int wiped = 0;
struct dm_list mdas;
struct pvcreate_params default_pp;
char buffer[64] __attribute__((aligned(8)));
dev_ext_t dev_ext_src;
pvcreate_params_set_defaults(&default_pp);
if (!pp)
pp = &default_pp;
if (!_verify_pv_create_params(pp)) {
goto bad;
}
if (pp->pva.idp) {
if ((dev = lvmcache_device_from_pvid(cmd, pp->pva.idp, NULL, NULL)) &&
(dev != dev_cache_get(pv_name, cmd->full_filter))) {
if (!id_write_format((const struct id*)&pp->pva.idp->uuid,
buffer, sizeof(buffer)))
goto_bad;
log_error("uuid %s already in use on \"%s\"", buffer,
dev_name(dev));
goto bad;
}
}
if (!_pvcreate_check(cmd, pv_name, pp, &wiped))
goto_bad;
if (sigint_caught())
goto_bad;
/*
* wipe_known_signatures called in _pvcreate_check fires
* WATCH event to update udev database. But at the moment,
* we have no way to synchronize with such event - we may
* end up still seeing the old info in udev db and pvcreate
* can fail to proceed because of the device still being
* filtered (because of the stale info in udev db).
* Disable udev dev-ext source temporarily here for
* this reason and rescan with DEV_EXT_NONE dev-ext
* source (so filters use DEV_EXT_NONE source).
*/
dev_ext_src = external_device_info_source();
if (wiped && (dev_ext_src == DEV_EXT_UDEV))
init_external_device_info_source(DEV_EXT_NONE);
dev = dev_cache_get(pv_name, cmd->full_filter);
init_external_device_info_source(dev_ext_src);
if (!dev) {
log_error("%s: Couldn't find device. Check your filters?",
pv_name);
goto bad;
}
dm_list_init(&mdas);
if (!(pv = pv_create(cmd, dev, &pp->pva))) {
log_error("Failed to setup physical volume \"%s\"", pv_name);
goto bad;
}
log_verbose("Set up physical volume for \"%s\" with %" PRIu64
" available sectors", pv_name, pv_size(pv));
pv->status |= UNLABELLED_PV;
if (write_now) {
struct pv_to_write pvw;
pvw.pp = pp;
pvw.pv = pv;
pvw.new_pv = 1;
if (!_pvcreate_write(cmd, &pvw))
goto bad;
}
return pv;
bad:
return NULL;
}
static struct physical_volume *_alloc_pv(struct dm_pool *mem, struct device *dev) static struct physical_volume *_alloc_pv(struct dm_pool *mem, struct device *dev)
{ {
struct physical_volume *pv; struct physical_volume *pv;
@ -2203,48 +1782,6 @@ struct physical_volume *find_pv(struct volume_group *vg, struct device *dev)
return NULL; return NULL;
} }
/* FIXME: liblvm todo - make into function that returns handle */
struct physical_volume *find_pv_by_name(struct cmd_context *cmd,
const char *pv_name,
int allow_orphan, int allow_unformatted)
{
struct device *dev;
struct pv_list *pvl;
struct dm_list *pvslist;
struct physical_volume *pv = NULL;
lvmcache_seed_infos_from_lvmetad(cmd);
if (!(dev = dev_cache_get(pv_name, cmd->filter))) {
if (!allow_unformatted)
log_error("Physical volume %s not found", pv_name);
return_NULL;
}
if (!(pvslist = get_pvs(cmd)))
return_NULL;
dm_list_iterate_items(pvl, pvslist)
if (pvl->pv->dev == dev)
pv = pvl->pv;
else
free_pv_fid(pvl->pv);
if (!pv && !allow_unformatted)
log_error("Physical volume %s not found", pv_name);
if (pv && !allow_orphan && is_orphan_vg(pv->vg_name)) {
log_error("Physical volume %s not in a volume group", pv_name);
goto bad;
}
return pv;
bad:
free_pv_fid(pv);
return NULL;
}
/* Find segment at a given logical extent in an LV */ /* Find segment at a given logical extent in an LV */
struct lv_segment *find_seg_by_le(const struct logical_volume *lv, uint32_t le) struct lv_segment *find_seg_by_le(const struct logical_volume *lv, uint32_t le)
{ {
@ -4899,7 +4436,7 @@ struct volume_group *vg_read_internal(struct cmd_context *cmd, const char *vgnam
if (!(vg = _vg_read(cmd, vgname, vgid, warn_flags, consistent, 0))) if (!(vg = _vg_read(cmd, vgname, vgid, warn_flags, consistent, 0)))
goto_out; goto_out;
if (!_check_pv_dev_sizes(vg)) if (!check_pv_dev_sizes(vg))
log_warn("One or more devices used as PVs in VG %s " log_warn("One or more devices used as PVs in VG %s "
"have changed sizes.", vg->name); "have changed sizes.", vg->name);
@ -5573,8 +5110,7 @@ static int _access_vg_clustered(struct cmd_context *cmd, const struct volume_gro
* *
* FIXME Remove the unnecessary duplicate definitions and return bits directly. * FIXME Remove the unnecessary duplicate definitions and return bits directly.
*/ */
static uint32_t _vg_bad_status_bits(const struct volume_group *vg, uint32_t vg_bad_status_bits(const struct volume_group *vg, uint64_t status)
uint64_t status)
{ {
uint32_t failure = 0; uint32_t failure = 0;
@ -5610,7 +5146,7 @@ static uint32_t _vg_bad_status_bits(const struct volume_group *vg,
*/ */
int vg_check_status(const struct volume_group *vg, uint64_t status) int vg_check_status(const struct volume_group *vg, uint64_t status)
{ {
return !_vg_bad_status_bits(vg, status); return !vg_bad_status_bits(vg, status);
} }
/* /*
@ -5830,7 +5366,7 @@ static int _access_vg_systemid(struct cmd_context *cmd, struct volume_group *vg)
} }
/* /*
* FIXME: move _vg_bad_status_bits() checks in here. * FIXME: move vg_bad_status_bits() checks in here.
*/ */
static int _vg_access_permitted(struct cmd_context *cmd, struct volume_group *vg, static int _vg_access_permitted(struct cmd_context *cmd, struct volume_group *vg,
uint32_t lockd_state, uint32_t *failure) uint32_t lockd_state, uint32_t *failure)
@ -5966,7 +5502,7 @@ static struct volume_group *_vg_lock_and_read(struct cmd_context *cmd, const cha
goto bad; goto bad;
} }
failure |= _vg_bad_status_bits(vg, status_flags); failure |= vg_bad_status_bits(vg, status_flags);
if (failure) if (failure)
goto_bad; goto_bad;

View File

@ -353,16 +353,13 @@ unsigned long set_pe_align_offset(struct physical_volume *pv,
int pv_write_orphan(struct cmd_context *cmd, struct physical_volume *pv); int pv_write_orphan(struct cmd_context *cmd, struct physical_volume *pv);
struct physical_volume *pvcreate_vol(struct cmd_context *cmd, const char *pv_name,
struct pvcreate_params *pp, int write_now);
int check_dev_block_size_for_vg(struct device *dev, const struct volume_group *vg, int check_dev_block_size_for_vg(struct device *dev, const struct volume_group *vg,
unsigned int *max_phys_block_size_found); unsigned int *max_phys_block_size_found);
int check_pv_dev_sizes(struct volume_group *vg);
uint32_t vg_bad_status_bits(const struct volume_group *vg, uint64_t status);
int add_pv_to_vg(struct volume_group *vg, const char *pv_name,
struct physical_volume *pv, int new_pv);
/* Manipulate PV structures */
int pv_add(struct volume_group *vg, struct physical_volume *pv);
int pv_remove(struct volume_group *vg, struct physical_volume *pv);
struct physical_volume *pv_find(struct volume_group *vg, const char *pv_name);
/* Find a PV within a given VG */ /* Find a PV within a given VG */
int get_pv_from_vg_by_id(const struct format_type *fmt, const char *vg_name, int get_pv_from_vg_by_id(const struct format_type *fmt, const char *vg_name,
@ -375,10 +372,6 @@ struct logical_volume *find_lv_in_vg_by_lvid(struct volume_group *vg,
struct lv_list *find_lv_in_lv_list(const struct dm_list *ll, struct lv_list *find_lv_in_lv_list(const struct dm_list *ll,
const struct logical_volume *lv); const struct logical_volume *lv);
/* Return the VG that contains a given LV (based on path given in lv_name) */
/* or environment var */
struct volume_group *find_vg_with_lv(const char *lv_name);
/* Find LV with given lvid (used during activation) */ /* Find LV with given lvid (used during activation) */
struct logical_volume *lv_from_lvid(struct cmd_context *cmd, struct logical_volume *lv_from_lvid(struct cmd_context *cmd,
const char *lvid_s, const char *lvid_s,
@ -466,8 +459,6 @@ void lv_calculate_readahead(const struct logical_volume *lv, uint32_t *read_ahea
*/ */
size_t export_vg_to_buffer(struct volume_group *vg, char **buf); size_t export_vg_to_buffer(struct volume_group *vg, char **buf);
struct dm_config_tree *export_vg_to_config_tree(struct volume_group *vg); struct dm_config_tree *export_vg_to_config_tree(struct volume_group *vg);
struct volume_group *import_vg_from_buffer(const char *buf,
struct format_instance *fid);
struct volume_group *import_vg_from_config_tree(const struct dm_config_tree *cft, struct volume_group *import_vg_from_config_tree(const struct dm_config_tree *cft,
struct format_instance *fid); struct format_instance *fid);
struct volume_group *import_vg_from_lvmetad_config_tree(const struct dm_config_tree *cft, struct volume_group *import_vg_from_lvmetad_config_tree(const struct dm_config_tree *cft,

View File

@ -705,179 +705,3 @@ out:
"to repair from archived metadata."); "to repair from archived metadata.");
return r; return r;
} }
/*
* Decide whether it is "safe" to wipe the labels on this device.
* 0 indicates we may not.
*/
static int _pvremove_check(struct cmd_context *cmd, const char *name,
unsigned force_count, unsigned prompt, struct dm_list *pvslist)
{
static const char really_wipe_msg[] = "Really WIPE LABELS from physical volume";
struct device *dev;
struct label *label;
struct pv_list *pvl;
struct physical_volume *pv = NULL;
int used;
int r = 0;
/* FIXME Check partition type is LVM unless --force is given */
if (!(dev = dev_cache_get(name, cmd->filter))) {
log_error("Device %s not found.", name);
return 0;
}
/* Is there a pv here already? */
/* If not, this is an error unless you used -f. */
if (!label_read(dev, &label, 0)) {
if (force_count)
return 1;
log_error("No PV label found on %s.", name);
return 0;
}
dm_list_iterate_items(pvl, pvslist)
if (pvl->pv->dev == dev)
pv = pvl->pv;
if (!pv) {
log_error(INTERNAL_ERROR "Physical Volume %s has a label, "
"but is neither in a VG nor orphan.", name);
goto out; /* better safe than sorry */
}
if (is_orphan(pv)) {
if ((used = is_used_pv(pv)) < 0)
goto_out;
if (used) {
log_warn("WARNING: PV %s is used by a VG but its metadata is missing.", name);
if (force_count < 2)
goto_bad;
if (!prompt &&
yes_no_prompt("%s \"%s\" that is marked as belonging to a VG [y/n]? ",
really_wipe_msg, name) == 'n')
goto_bad;
}
} else {
log_warn("WARNING: PV %s is used by VG %s (consider using vgreduce).", name, pv_vg_name(pv));
if (force_count < 2)
goto_bad;
if (!prompt &&
yes_no_prompt("%s \"%s\" of volume group \"%s\" [y/n]? ",
really_wipe_msg, name, pv_vg_name(pv)) == 'n')
goto_bad;
}
if (force_count)
log_warn("WARNING: Wiping physical volume label from "
"%s%s%s%s", name,
!is_orphan(pv) ? " of volume group \"" : "",
pv_vg_name(pv),
!is_orphan(pv) ? "\"" : "");
r = 1;
bad:
if (!r) {
log_error("%s: physical volume label not removed.", name);
if (force_count < 2) /* Show hint as log_error() */
log_error("(If you are certain you need pvremove, "
"then confirm by using --force twice.)");
}
out:
return r;
}
int pvremove_single(struct cmd_context *cmd, const char *pv_name,
void *handle __attribute__((unused)), unsigned force_count,
unsigned prompt, struct dm_list *pvslist)
{
struct device *dev;
struct lvmcache_info *info;
int r = 0;
if (!_pvremove_check(cmd, pv_name, force_count, prompt, pvslist))
goto out;
if (!(dev = dev_cache_get(pv_name, cmd->filter))) {
log_error("%s: Couldn't find device. Check your filters?",
pv_name);
goto out;
}
info = lvmcache_info_from_pvid(dev->pvid, dev, 0);
if (!dev_test_excl(dev)) {
/* FIXME Detect whether device-mapper is still using the device */
log_error("Can't open %s exclusively - not removing. "
"Mounted filesystem?", dev_name(dev));
goto out;
}
/* Wipe existing label(s) */
if (!label_remove(dev)) {
log_error("Failed to wipe existing label(s) on %s", pv_name);
goto out;
}
if (info)
lvmcache_del(info);
if (!lvmetad_pv_gone_by_dev(dev))
goto_out;
log_print_unless_silent("Labels on physical volume \"%s\" successfully wiped",
pv_name);
r = 1;
out:
return r;
}
int pvremove_many(struct cmd_context *cmd, struct dm_list *pv_names,
unsigned force_count, unsigned prompt)
{
int ret = 1;
struct dm_list *pvslist = NULL;
struct pv_list *pvl;
const struct dm_str_list *pv_name;
if (!lock_vol(cmd, VG_ORPHANS, LCK_VG_WRITE, NULL)) {
log_error("Can't get lock for orphan PVs");
return 0;
}
lvmcache_seed_infos_from_lvmetad(cmd);
if (!(pvslist = get_pvs(cmd))) {
ret = 0;
goto_out;
}
dm_list_iterate_items(pv_name, pv_names) {
if (!pvremove_single(cmd, pv_name->str, NULL, force_count, prompt, pvslist)) {
stack;
ret = 0;
}
if (sigint_caught()) {
ret = 0;
goto_out;
}
}
out:
unlock_vg(cmd, NULL, VG_ORPHANS);
if (pvslist)
dm_list_iterate_items(pvl, pvslist)
free_pv_fid(pvl->pv);
return ret;
}

View File

@ -13,7 +13,7 @@
*/ */
#include "lib.h" #include "lib.h"
#include "metadata.h" #include "metadata-exported.h"
#include "lvm-string.h" #include "lvm-string.h"
#include "defaults.h" #include "defaults.h"
#include "segtype.h" #include "segtype.h"

View File

@ -14,7 +14,7 @@
#include <stddef.h> #include <stddef.h>
#include "lib.h" #include "lib.h"
#include "metadata.h" #include "metadata-exported.h"
#include "lvm-string.h" #include "lvm-string.h"
#include "str_list.h" #include "str_list.h"
#include "lvm_misc.h" #include "lvm_misc.h"