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 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 */
|
/* Manipulate PV structures */
|
||||||
int pv_add(struct volume_group *vg, struct physical_volume *pv);
|
int pv_add(struct volume_group *vg, struct physical_volume *pv);
|
||||||
int pv_remove(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 "toolcontext.h"
|
||||||
#include "locking.h"
|
#include "locking.h"
|
||||||
#include "defaults.h"
|
#include "defaults.h"
|
||||||
|
#include "lvmetad.h"
|
||||||
|
|
||||||
static struct pv_segment *_alloc_pv_segment(struct dm_pool *mem,
|
static struct pv_segment *_alloc_pv_segment(struct dm_pool *mem,
|
||||||
struct physical_volume *pv,
|
struct physical_volume *pv,
|
||||||
@ -542,3 +543,132 @@ int pv_resize(struct physical_volume *pv,
|
|||||||
|
|
||||||
return 1;
|
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
|
* \return
|
||||||
* A list of lvm_pv_list structures containing pv handles for all physical
|
* 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
|
* 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);
|
struct dm_list *lvm_list_pvs(lvm_t libh);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Free the resources used by acquiring the pvlist. This should be called as
|
* 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
|
* 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
|
* \param pvlist
|
||||||
* PV list to be freed
|
* 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);
|
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.
|
* Return a list of PV handles for a given VG handle.
|
||||||
*
|
*
|
||||||
|
@ -75,6 +75,14 @@ struct lvm_list_wrapper
|
|||||||
struct dm_list vgslist;
|
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)
|
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 "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 pvremove(struct cmd_context *cmd, int argc, char **argv)
|
||||||
{
|
{
|
||||||
int i, r;
|
int i, r;
|
||||||
int ret = ECMD_PROCESSED;
|
int ret = ECMD_PROCESSED;
|
||||||
|
unsigned force_count;
|
||||||
|
unsigned prompt;
|
||||||
|
|
||||||
if (!argc) {
|
if (!argc) {
|
||||||
log_error("Please enter a physical volume path");
|
log_error("Please enter a physical volume path");
|
||||||
return EINVALID_CMD_LINE;
|
return EINVALID_CMD_LINE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
force_count = arg_count(cmd, force_ARG);
|
||||||
|
prompt = arg_count(cmd, yes_ARG);
|
||||||
|
|
||||||
for (i = 0; i < argc; i++) {
|
for (i = 0; i < argc; i++) {
|
||||||
dm_unescape_colons_and_at_signs(argv[i], NULL, NULL);
|
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)
|
if (r > ret)
|
||||||
ret = r;
|
ret = r;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user