mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
lvremove
This commit is contained in:
parent
952152fd96
commit
cfd658dab0
@ -295,6 +295,8 @@ struct disk_list *read_pv(struct device *dev, struct pool *mem,
|
|||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log_very_verbose("Found %s in VG %s", name, data->pv.vg_name);
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
|
|
||||||
bad:
|
bad:
|
||||||
|
@ -34,41 +34,6 @@ static char *_create_lv_name(struct pool *mem, const char *full_name)
|
|||||||
return pool_strdup(mem, ptr);
|
return pool_strdup(mem, ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct logical_volume *_find_lv(struct volume_group *vg,
|
|
||||||
const char *name)
|
|
||||||
{
|
|
||||||
struct list_head *tmp;
|
|
||||||
struct logical_volume *lv;
|
|
||||||
struct lv_list *ll;
|
|
||||||
const char *ptr = strrchr(name, '/') + 1;
|
|
||||||
|
|
||||||
list_for_each(tmp, &vg->lvs) {
|
|
||||||
ll = list_entry(tmp, struct lv_list, list);
|
|
||||||
lv = &ll->lv;
|
|
||||||
|
|
||||||
if (!strcmp(ptr, lv->name))
|
|
||||||
return lv;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct physical_volume *_find_pv(struct volume_group *vg,
|
|
||||||
struct device *dev)
|
|
||||||
{
|
|
||||||
struct list_head *tmp;
|
|
||||||
struct physical_volume *pv;
|
|
||||||
struct pv_list *pl;
|
|
||||||
|
|
||||||
list_for_each(tmp, &vg->pvs) {
|
|
||||||
pl = list_entry(tmp, struct pv_list, list);
|
|
||||||
pv = &pl->pv;
|
|
||||||
if (dev == pv->dev)
|
|
||||||
return pv;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _fill_lv_array(struct logical_volume **lvs,
|
static int _fill_lv_array(struct logical_volume **lvs,
|
||||||
struct volume_group *vg, struct disk_list *dl)
|
struct volume_group *vg, struct disk_list *dl)
|
||||||
{
|
{
|
||||||
@ -79,7 +44,7 @@ static int _fill_lv_array(struct logical_volume **lvs,
|
|||||||
list_for_each(tmp, &dl->lvs) {
|
list_for_each(tmp, &dl->lvs) {
|
||||||
struct lvd_list *ll = list_entry(tmp, struct lvd_list, list);
|
struct lvd_list *ll = list_entry(tmp, struct lvd_list, list);
|
||||||
|
|
||||||
if (!(lv = _find_lv(vg, ll->lv.lv_name))) {
|
if (!(lv = find_lv(vg, ll->lv.lv_name))) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -475,7 +440,7 @@ int import_lvs(struct pool *mem, struct volume_group *vg,
|
|||||||
ll = list_entry(tmp2, struct lvd_list, list);
|
ll = list_entry(tmp2, struct lvd_list, list);
|
||||||
lvd = &ll->lv;
|
lvd = &ll->lv;
|
||||||
|
|
||||||
if (!_find_lv(vg, lvd->lv_name) &&
|
if (!find_lv(vg, lvd->lv_name) &&
|
||||||
!_add_lv(mem, vg, lvd)) {
|
!_add_lv(mem, vg, lvd)) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -218,15 +218,71 @@ struct physical_volume *pv_create(struct io_space *ios, const char *name)
|
|||||||
|
|
||||||
struct list_head *find_pv_in_vg(struct volume_group *vg, const char *pv_name)
|
struct list_head *find_pv_in_vg(struct volume_group *vg, const char *pv_name)
|
||||||
{
|
{
|
||||||
struct list_head *tmp;
|
struct list_head *pvh;
|
||||||
struct pv_list *pv;
|
struct pv_list *pv;
|
||||||
|
|
||||||
list_for_each(tmp, &vg->pvs) {
|
list_for_each(pvh, &vg->pvs) {
|
||||||
pv = list_entry(tmp, struct pv_list, list);
|
pv = list_entry(pvh, struct pv_list, list);
|
||||||
|
/* FIXME check dev not name */
|
||||||
if (!strcmp(dev_name(pv->pv.dev), pv_name))
|
if (!strcmp(dev_name(pv->pv.dev), pv_name))
|
||||||
return tmp;
|
return pvh;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct list_head *find_lv_in_vg(struct volume_group *vg, const char *lv_name)
|
||||||
|
{
|
||||||
|
struct list_head *lvh;
|
||||||
|
|
||||||
|
const char *ptr;
|
||||||
|
|
||||||
|
/* Use last component */
|
||||||
|
if ((ptr = strrchr(lv_name, '/')))
|
||||||
|
ptr++;
|
||||||
|
else
|
||||||
|
ptr = lv_name;
|
||||||
|
|
||||||
|
list_for_each(lvh, &vg->lvs)
|
||||||
|
if (!strcmp(list_entry(lvh, struct lv_list, list)->lv.name,
|
||||||
|
ptr))
|
||||||
|
return lvh;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct logical_volume *find_lv(struct volume_group *vg, const char *lv_name)
|
||||||
|
{
|
||||||
|
struct list_head *lvh;
|
||||||
|
|
||||||
|
if ((lvh = find_lv_in_vg(vg, lv_name)))
|
||||||
|
return &list_entry(lvh, struct lv_list, list)->lv;
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct physical_volume *_find_pv(struct volume_group *vg,
|
||||||
|
struct device *dev)
|
||||||
|
{
|
||||||
|
struct list_head *tmp;
|
||||||
|
struct physical_volume *pv;
|
||||||
|
struct pv_list *pl;
|
||||||
|
|
||||||
|
list_for_each(tmp, &vg->pvs) {
|
||||||
|
pl = list_entry(tmp, struct pv_list, list);
|
||||||
|
pv = &pl->pv;
|
||||||
|
if (dev == pv->dev)
|
||||||
|
return pv;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int lv_remove(struct volume_group *vg, struct list_head *lvh)
|
||||||
|
{
|
||||||
|
list_del(lvh);
|
||||||
|
vg->lv_count--;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -232,16 +232,22 @@ struct physical_volume *pv_find(struct volume_group *vg,
|
|||||||
int lv_add(struct volume_group *vg, struct logical_volume *lv);
|
int lv_add(struct volume_group *vg, struct logical_volume *lv);
|
||||||
|
|
||||||
/* Remove an LV from a given VG */
|
/* Remove an LV from a given VG */
|
||||||
int lv_remove(struct volume_group *vg, struct logical_volume *lv);
|
int lv_remove(struct volume_group *vg, struct list_head *lvh);
|
||||||
|
|
||||||
/* ? Return the VG that contains a given LV (based on path given in lv_name) */
|
|
||||||
/* (or environment var?) */
|
|
||||||
struct volume_group *vg_find(const char *lv_name);
|
|
||||||
|
|
||||||
/* Find an LV within a given VG */
|
|
||||||
struct logical_volume *lv_find(struct volume_group *vg, const char *lv_name);
|
|
||||||
|
|
||||||
/* Find a PV within a given VG */
|
/* Find a PV within a given VG */
|
||||||
struct list_head *find_pv_in_vg(struct volume_group *vg, const char *pv_name);
|
struct list_head *find_pv_in_vg(struct volume_group *vg, const char *pv_name);
|
||||||
|
|
||||||
|
/* Find an LV within a given VG */
|
||||||
|
struct list_head *find_lv_in_vg(struct volume_group *vg, const char *lv_name);
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
|
||||||
|
|
||||||
|
/* FIXME Merge these functions with ones above */
|
||||||
|
struct physical_volume *_find_pv(struct volume_group *vg, struct device *dev);
|
||||||
|
struct logical_volume *find_lv(struct volume_group *vg, const char *lv_name);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -51,7 +51,7 @@ SUFFIXES=
|
|||||||
SUFFIXES=.c .d .o
|
SUFFIXES=.c .d .o
|
||||||
|
|
||||||
CFLAGS+=-Wall
|
CFLAGS+=-Wall
|
||||||
CFLAGS+=-O2
|
#CFLAGS+=-O2
|
||||||
CFLAGS+=-g -fno-omit-frame-pointer
|
CFLAGS+=-g -fno-omit-frame-pointer
|
||||||
#CFLAGS+=-pg
|
#CFLAGS+=-pg
|
||||||
CFLAGS+=-DDEBUG_MEM -DDEBUG
|
CFLAGS+=-DDEBUG_MEM -DDEBUG
|
||||||
|
@ -23,6 +23,7 @@ VPATH = @srcdir@
|
|||||||
SOURCES=\
|
SOURCES=\
|
||||||
lvm.c \
|
lvm.c \
|
||||||
lvmchange.c \
|
lvmchange.c \
|
||||||
|
lvremove.c \
|
||||||
pvchange.c \
|
pvchange.c \
|
||||||
pvcreate.c \
|
pvcreate.c \
|
||||||
pvdisplay.c \
|
pvdisplay.c \
|
||||||
@ -33,8 +34,8 @@ SOURCES=\
|
|||||||
vgcreate.c \
|
vgcreate.c \
|
||||||
vgextend.c \
|
vgextend.c \
|
||||||
vgreduce.c \
|
vgreduce.c \
|
||||||
vgrename.c \
|
|
||||||
vgremove.c \
|
vgremove.c \
|
||||||
|
vgrename.c \
|
||||||
vgscan.c
|
vgscan.c
|
||||||
|
|
||||||
TARGETS=\
|
TARGETS=\
|
||||||
|
@ -26,19 +26,15 @@ int lvremove(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
int opt;
|
int opt;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
char *lv_name;
|
|
||||||
|
|
||||||
if (argc == 0) {
|
if (!argc) {
|
||||||
log_error("please enter a logical volume path");
|
log_error("Please enter one or more logical volume paths");
|
||||||
return EINVALID_CMD_LINE;
|
return EINVALID_CMD_LINE;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (opt = 0; opt < argc; opt++) {
|
for (opt = 0; opt < argc; opt++) {
|
||||||
lv_name = argv[opt];
|
if ((ret = lvremove_single(argv[opt])))
|
||||||
|
|
||||||
if ((ret = lvremove_single(lv_name)))
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -46,38 +42,39 @@ int lvremove(int argc, char **argv)
|
|||||||
|
|
||||||
int lvremove_single(char *lv_name)
|
int lvremove_single(char *lv_name)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
|
||||||
char *vg_name = NULL;
|
char *vg_name = NULL;
|
||||||
char buffer[NAME_LEN];
|
|
||||||
|
|
||||||
struct volume_group *vg;
|
struct volume_group *vg;
|
||||||
|
struct list_head *lvh;
|
||||||
struct logical_volume *lv;
|
struct logical_volume *lv;
|
||||||
|
|
||||||
|
|
||||||
lv_name = lvm_check_default_vg_name(lv_name, buffer, sizeof (buffer));
|
|
||||||
/* does VG exist? */
|
/* does VG exist? */
|
||||||
vg_name = vg_name_of_lv(lv_name);
|
if (!(vg_name = extract_vgname(ios, lv_name))) {
|
||||||
|
return ECMD_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
log_verbose("Finding volume group %s", vg_name);
|
log_verbose("Finding volume group %s", vg_name);
|
||||||
if (!(vg = ios->vg_read(ios, vg_name))) {
|
if (!(vg = ios->vg_read(ios, vg_name))) {
|
||||||
log_error("volume group %s doesn't exist", vg_name);
|
log_error("Volume group %s doesn't exist", vg_name);
|
||||||
return ECMD_FAILED;
|
return ECMD_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(vg->status & ACTIVE)) {
|
if (!(vg->status & ACTIVE)) {
|
||||||
log_error("volume group %s must be active before removing "
|
log_error("Volume group %s must be active before removing a "
|
||||||
"logical volume", vg_name);
|
"logical volume", vg_name);
|
||||||
return ECMD_FAILED;
|
return ECMD_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(lv = lv_find(vg, lv_name))) {
|
if (!(lvh = find_lv_in_vg(vg, lv_name))) {
|
||||||
log_error("can't find logical volume %s in volume group %s",
|
log_error("Can't find logical volume %s in volume group %s",
|
||||||
lv_name, vg_name);
|
lv_name, vg_name);
|
||||||
return ECMD_FAILED;
|
return ECMD_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lv = &list_entry(lvh, struct lv_list, list)->lv;
|
||||||
|
|
||||||
if (lv->status & SNAPSHOT_ORG) {
|
if (lv->status & SNAPSHOT_ORG) {
|
||||||
log_error("can't remove logical volume %s under snapshot",
|
log_error("Can't remove logical volume %s under snapshot",
|
||||||
lv_name);
|
lv_name);
|
||||||
return ECMD_FAILED;
|
return ECMD_FAILED;
|
||||||
}
|
}
|
||||||
@ -95,28 +92,33 @@ int lvremove_single(char *lv_name)
|
|||||||
if (yes_no_prompt
|
if (yes_no_prompt
|
||||||
("Do you really want to remove %s? [y/n]: ",
|
("Do you really want to remove %s? [y/n]: ",
|
||||||
lv_name) == 'n') {
|
lv_name) == 'n') {
|
||||||
log_print("logical volume %s not removed", lv_name);
|
log_print("Logical volume %s not removed", lv_name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log_verbose("releasing logical volume %s", lv_name);
|
log_verbose("Releasing logical volume %s", lv_name);
|
||||||
if (lv_remove(vg, lv)) {
|
if (lv_remove(vg, lvh)) {
|
||||||
log_error("Error releasing logical volume %s", lv_name);
|
log_error("Error releasing logical volume %s", lv_name);
|
||||||
return ECMD_FAILED;
|
return ECMD_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
log_verbose("unlinking special file %s", lv_name);
|
/********* FIXME
|
||||||
|
log_verbose("Unlinking special file %s", lv_name);
|
||||||
if (!lvm_check_devfs() && unlink(lv_name) == -1)
|
if (!lvm_check_devfs() && unlink(lv_name) == -1)
|
||||||
log_error("Error unlinking special file %s", lv_name);
|
log_error("Error unlinking special file %s", lv_name);
|
||||||
|
**********/
|
||||||
|
|
||||||
/* store it on disks */
|
/* store it on disks */
|
||||||
if (ios->vg_write(vg))
|
if (ios->vg_write(ios, vg))
|
||||||
return ECMD_FAILED;
|
return ECMD_FAILED;
|
||||||
|
|
||||||
|
/******** FIXME
|
||||||
if ((ret = do_autobackup(vg_name, vg)))
|
if ((ret = do_autobackup(vg_name, vg)))
|
||||||
return ret;
|
return ret;
|
||||||
|
**********/
|
||||||
|
|
||||||
log_print("logical volume %s successfully removed", lv_name);
|
log_print("logical volume %s successfully removed", lv_name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,7 +27,6 @@ int lvmdiskscan(int argc, char **argv) {return 1;}
|
|||||||
int lvmsadc(int argc, char **argv) {return 1;}
|
int lvmsadc(int argc, char **argv) {return 1;}
|
||||||
int lvmsar(int argc, char **argv) {return 1;}
|
int lvmsar(int argc, char **argv) {return 1;}
|
||||||
int lvreduce(int argc, char **argv) {return 1;}
|
int lvreduce(int argc, char **argv) {return 1;}
|
||||||
int lvremove(int argc, char **argv) {return 1;}
|
|
||||||
int lvrename(int argc, char **argv) {return 1;}
|
int lvrename(int argc, char **argv) {return 1;}
|
||||||
int lvscan(int argc, char **argv) {return 1;}
|
int lvscan(int argc, char **argv) {return 1;}
|
||||||
int pvdata(int argc, char **argv) {return 1;}
|
int pvdata(int argc, char **argv) {return 1;}
|
||||||
|
@ -166,3 +166,51 @@ int is_valid_chars(char *n)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *extract_vgname(struct io_space *ios, char *lv_name)
|
||||||
|
{
|
||||||
|
char *vg_name = lv_name;
|
||||||
|
char *vg_path, *st;
|
||||||
|
|
||||||
|
/* Path supplied? */
|
||||||
|
if (strchr(vg_name, '/')) {
|
||||||
|
/* Strip prefix (optional) */
|
||||||
|
if (!strncmp(vg_name, ios->prefix, strlen(ios->prefix)))
|
||||||
|
vg_name += strlen(ios->prefix);
|
||||||
|
|
||||||
|
/* Require exactly one slash */
|
||||||
|
if (!(st = strchr(vg_name, '/')) || (strchr(st + 1, '/'))) {
|
||||||
|
log_error("%s: Invalid path for Logical Volume", lv_name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
vg_name = pool_strdup(ios->mem, vg_name);
|
||||||
|
if (!vg_name) {
|
||||||
|
log_error("Allocation of vg_name failed");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
*strchr(vg_name, '/') = '\0';
|
||||||
|
return vg_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Take default VG from environment? */
|
||||||
|
vg_path = getenv("LVM_VG_NAME");
|
||||||
|
if (!vg_path) {
|
||||||
|
log_error("Path required for Logical Volume %s", lv_name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Strip prefix (optional) */
|
||||||
|
if (!strncmp(vg_path, ios->prefix, strlen(ios->prefix)))
|
||||||
|
vg_path += strlen(ios->prefix);
|
||||||
|
|
||||||
|
if (strchr(vg_path, '/')) {
|
||||||
|
log_error("Environment Volume Group in LVM_VG_NAME invalid: %s",
|
||||||
|
vg_path);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pool_strdup(ios->mem, vg_path);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -34,4 +34,6 @@ int process_each_pv(int argc, char **argv, struct volume_group *vg,
|
|||||||
|
|
||||||
int is_valid_chars(char *n);
|
int is_valid_chars(char *n);
|
||||||
|
|
||||||
|
char *extract_vgname(struct io_space *ios, char *lv_name);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user