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:
parent
ef3ab801e8
commit
e33ac7b1ed
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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)
|
||||
{
|
||||
|
133
tools/pvremove.c
133
tools/pvremove.c
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user