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

lvm2app: Implement lvm_pv_remove V2

Code move and changes to support calling code from
command line and from library interface.

V2 Change lock_vol call

Signed-off-by: Tony Asleson <tasleson@redhat.com>
This commit is contained in:
Tony Asleson 2013-04-02 16:10:18 -04:00
parent ef3ab801e8
commit e33ac7b1ed
5 changed files with 163 additions and 128 deletions

View File

@ -341,6 +341,10 @@ int vg_validate(struct volume_group *vg);
int pv_write_orphan(struct cmd_context *cmd, struct physical_volume *pv);
int pvremove_single(struct cmd_context *cmd, const char *pv_name,
void *handle __attribute__((unused)), unsigned force_count,
unsigned prompt);
/* 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);

View File

@ -19,6 +19,7 @@
#include "toolcontext.h"
#include "locking.h"
#include "defaults.h"
#include "lvmetad.h"
static struct pv_segment *_alloc_pv_segment(struct dm_pool *mem,
struct physical_volume *pv,
@ -542,3 +543,132 @@ int pv_resize(struct physical_volume *pv,
return 1;
}
const char _really_wipe[] =
"Really WIPE LABELS from physical volume \"%s\" of volume group \"%s\" [y/n]? ";
/*
* 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 physical_volume *pv;
/* FIXME Check partition type is LVM unless --force is given */
/* Is there a pv here already? */
/* If not, this is an error unless you used -f. */
if (!(pv = pv_read(cmd, name, 1, 0))) {
if (force_count)
return 1;
log_error("Physical Volume %s not found", name);
return 0;
}
/*
* If a PV has no MDAs it may appear to be an
* orphan until the metadata is read off
* another PV in the same VG. Detecting this
* means checking every VG by scanning every
* PV on the system.
*/
if (is_orphan(pv) && !dm_list_size(&pv->fid->metadata_areas_in_use) &&
!dm_list_size(&pv->fid->metadata_areas_ignored)) {
if (!scan_vgs_for_pvs(cmd, 0)) {
log_error("Rescan for PVs without metadata areas "
"failed.");
goto bad;
}
free_pv_fid(pv);
if (!(pv = pv_read(cmd, name, 1, 0))) {
log_error("Failed to read physical volume %s", name);
goto bad;
}
}
/* orphan ? */
if (is_orphan(pv)) {
free_pv_fid(pv);
return 1;
}
/* Allow partial & exported VGs to be destroyed. */
/* we must have -ff to overwrite a non orphan */
if (force_count < 2) {
log_error("PV %s belongs to Volume Group %s so please use vgreduce first.", name, pv_vg_name(pv));
log_error("(If you are certain you need pvremove, then confirm by using --force twice.)");
goto bad;
}
/* prompt */
if (!prompt &&
yes_no_prompt(_really_wipe, name, pv_vg_name(pv)) == 'n') {
log_error("%s: physical volume label not removed", name);
goto bad;
}
if (force_count) {
log_warn("WARNING: Wiping physical volume label from "
"%s%s%s%s", name,
!is_orphan(pv) ? " of volume group \"" : "",
!is_orphan(pv) ? pv_vg_name(pv) : "",
!is_orphan(pv) ? "\"" : "");
}
free_pv_fid(pv);
return 1;
bad:
free_pv_fid(pv);
return 0;
}
int pvremove_single(struct cmd_context *cmd, const char *pv_name,
void *handle __attribute__((unused)), unsigned force_count,
unsigned prompt)
{
struct device *dev;
int ret = ECMD_FAILED;
if (!lock_vol(cmd, VG_ORPHANS, LCK_VG_WRITE, NULL)) {
log_error("Can't get lock for orphan PVs");
return ECMD_FAILED;
}
if (!pvremove_check(cmd, pv_name, force_count, prompt))
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;
}
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 (!lvmetad_pv_gone_by_dev(dev, NULL))
goto_out;
log_print_unless_silent("Labels on physical volume \"%s\" successfully wiped",
pv_name);
ret = ECMD_PROCESSED;
out:
unlock_vg(cmd, VG_ORPHANS);
return ret;
}

View File

@ -553,14 +553,15 @@ struct dm_list *lvm_vg_list_lvs(vg_t vg);
* \return
* A list of lvm_pv_list structures containing pv handles for all physical
* volumes. If no PVs exist or a global lock was unable to be obtained a
* NULL is returned.
* NULL is returned. Do not attempt to remove one of the PVs until after the
* call to lvm_list_pvs_free has been made.
*/
struct dm_list *lvm_list_pvs(lvm_t libh);
/**
* Free the resources used by acquiring the pvlist. This should be called as
* soon as possible after processing the needed information from the pv list as
* a global locks are held.
* a global lock is held.
*
* \param pvlist
* PV list to be freed
@ -570,6 +571,17 @@ struct dm_list *lvm_list_pvs(lvm_t libh);
*/
int lvm_list_pvs_free(struct dm_list *pvlist);
/**
* Remove a physical volume.
* Note: You cannot remove a PV while iterating through the list of PVs as
* locks are held for the PV list.
* \param libh Library handle
* \param pv_name The physical volume name
* \return
* 0 on success, else -1 with library errno and text set.
*/
int lvm_pv_remove(lvm_t libh, const char *pv_name);
/**
* Return a list of PV handles for a given VG handle.
*

View File

@ -75,6 +75,14 @@ struct lvm_list_wrapper
struct dm_list vgslist;
};
int lvm_pv_remove(lvm_t libh, const char *pv_name)
{
struct cmd_context *cmd = (struct cmd_context *)libh;
if ( 1 != pvremove_single(cmd, pv_name, NULL, 0, 0)) {
return -1;
}
return 0;
}
struct dm_list *lvm_list_pvs(lvm_t libh)
{

View File

@ -14,146 +14,27 @@
*/
#include "tools.h"
#include "metadata.h"
/*
* 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)
{
struct physical_volume *pv;
/* FIXME Check partition type is LVM unless --force is given */
/* Is there a pv here already? */
/* If not, this is an error unless you used -f. */
if (!(pv = pv_read(cmd, name, 1, 0))) {
if (arg_count(cmd, force_ARG))
return 1;
log_error("Physical Volume %s not found", name);
return 0;
}
/*
* If a PV has no MDAs it may appear to be an
* orphan until the metadata is read off
* another PV in the same VG. Detecting this
* means checking every VG by scanning every
* PV on the system.
*/
if (is_orphan(pv) && !dm_list_size(&pv->fid->metadata_areas_in_use) &&
!dm_list_size(&pv->fid->metadata_areas_ignored)) {
if (!scan_vgs_for_pvs(cmd, 0)) {
log_error("Rescan for PVs without metadata areas "
"failed.");
goto bad;
}
free_pv_fid(pv);
if (!(pv = pv_read(cmd, name, 1, 0))) {
log_error("Failed to read physical volume %s", name);
goto bad;
}
}
/* orphan ? */
if (is_orphan(pv)) {
free_pv_fid(pv);
return 1;
}
/* Allow partial & exported VGs to be destroyed. */
/* we must have -ff to overwrite a non orphan */
if (arg_count(cmd, force_ARG) < 2) {
log_error("PV %s belongs to Volume Group %s so please use vgreduce first.", name, pv_vg_name(pv));
log_error("(If you are certain you need pvremove, then confirm by using --force twice.)");
goto bad;
}
/* prompt */
if (!arg_count(cmd, yes_ARG) &&
yes_no_prompt("Really WIPE LABELS from physical volume \"%s\" "
"of volume group \"%s\" [y/n]? ",
name, pv_vg_name(pv)) == 'n') {
log_error("%s: physical volume label not removed", name);
goto bad;
}
if (arg_count(cmd, force_ARG)) {
log_warn("WARNING: Wiping physical volume label from "
"%s%s%s%s", name,
!is_orphan(pv) ? " of volume group \"" : "",
!is_orphan(pv) ? pv_vg_name(pv) : "",
!is_orphan(pv) ? "\"" : "");
}
free_pv_fid(pv);
return 1;
bad:
free_pv_fid(pv);
return 0;
}
static int pvremove_single(struct cmd_context *cmd, const char *pv_name,
void *handle __attribute__((unused)))
{
struct device *dev;
int ret = ECMD_FAILED;
if (!lock_vol(cmd, VG_ORPHANS, LCK_VG_WRITE, NULL)) {
log_error("Can't get lock for orphan PVs");
return ECMD_FAILED;
}
if (!pvremove_check(cmd, pv_name))
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;
}
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 (!lvmetad_pv_gone_by_dev(dev, NULL))
goto_out;
log_print_unless_silent("Labels on physical volume \"%s\" successfully wiped",
pv_name);
ret = ECMD_PROCESSED;
out:
unlock_vg(cmd, VG_ORPHANS);
return ret;
}
int pvremove(struct cmd_context *cmd, int argc, char **argv)
{
int i, r;
int ret = ECMD_PROCESSED;
unsigned force_count;
unsigned prompt;
if (!argc) {
log_error("Please enter a physical volume path");
return EINVALID_CMD_LINE;
}
force_count = arg_count(cmd, force_ARG);
prompt = arg_count(cmd, yes_ARG);
for (i = 0; i < argc; i++) {
dm_unescape_colons_and_at_signs(argv[i], NULL, NULL);
r = pvremove_single(cmd, argv[i], NULL);
r = pvremove_single(cmd, argv[i], NULL, force_count, prompt);
if (r > ret)
ret = r;
}