1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-21 13:34:40 +03:00

vgreduce, vgremove, vgrename & vgscan

This commit is contained in:
Alasdair Kergon 2001-10-11 21:35:55 +00:00
parent c4bf9638e3
commit 6e91eeef13
10 changed files with 285 additions and 25 deletions

View File

@ -91,6 +91,10 @@ static struct volume_group *_vg_read(struct io_space *is, const char *vg_name)
return NULL; return NULL;
} }
/* Strip prefix if present */
if (!strncmp(vg_name, is->prefix, strlen(is->prefix)))
vg_name += strlen(is->prefix);
if (!read_pvs_in_vg(vg_name, is->filter, mem, &pvs)) { if (!read_pvs_in_vg(vg_name, is->filter, mem, &pvs)) {
stack; stack;
return NULL; return NULL;
@ -295,7 +299,8 @@ static struct list_head *_get_vgs(struct io_space *is)
list_for_each(tmp, pvs) { list_for_each(tmp, pvs) {
struct pv_list *pvl = list_entry(tmp, struct pv_list, list); struct pv_list *pvl = list_entry(tmp, struct pv_list, list);
if (_find_vg_name(names, pvl->pv.vg_name)) if (!(*pvl->pv.vg_name) ||
_find_vg_name(names, pvl->pv.vg_name))
continue; continue;
if (!(nl = pool_alloc(is->mem, sizeof(*nl)))) { if (!(nl = pool_alloc(is->mem, sizeof(*nl)))) {
@ -358,8 +363,9 @@ static int _pv_write(struct io_space *is, struct physical_volume *pv)
INIT_LIST_HEAD(&pvs); INIT_LIST_HEAD(&pvs);
if (pv->vg_name) { if (*pv->vg_name) {
log_info("pv_write should only be called for an orphan pv"); log_error("Assertion failed: can't _pv_write non-orphan PV "
"(in VG %s)", pv->vg_name);
return 0; return 0;
} }

View File

@ -25,8 +25,10 @@ SOURCES=\
lvmchange.c\ lvmchange.c\
toollib.c\ toollib.c\
vgck.c\ vgck.c\
vgreduce.c\
vgrename.c\ vgrename.c\
vgremove.c vgremove.c\
vgscan.c
TARGETS=\ TARGETS=\
lvm lvm

View File

@ -19,7 +19,7 @@
*/ */
xx(available_ARG, 'a', "available", yes_no_arg) xx(available_ARG, 'a', "available", yes_no_arg)
xx(all_ARG, 'a', "all", yes_no_arg) xx(all_ARG, 'a', "all", NULL)
xx(autobackup_ARG, 'A', "autobackup", yes_no_arg) xx(autobackup_ARG, 'A', "autobackup", yes_no_arg)
xx(activevolumegroups_ARG, 'A', "activevolumegroups", NULL) xx(activevolumegroups_ARG, 'A', "activevolumegroups", NULL)
xx(blockdevice_ARG, 'b', "blockdevice", NULL) xx(blockdevice_ARG, 'b', "blockdevice", NULL)

View File

@ -45,7 +45,5 @@ int vgextend(int argc, char **argv) {return 1;}
int vgimport(int argc, char **argv) {return 1;} int vgimport(int argc, char **argv) {return 1;}
int vgmerge(int argc, char **argv) {return 1;} int vgmerge(int argc, char **argv) {return 1;}
int vgmknodes(int argc, char **argv) {return 1;} int vgmknodes(int argc, char **argv) {return 1;}
int vgreduce(int argc, char **argv) {return 1;}
int vgscan(int argc, char **argv) {return 1;}
int vgsplit(int argc, char **argv) {return 1;} int vgsplit(int argc, char **argv) {return 1;}

View File

@ -120,13 +120,60 @@ int process_each_vg(int argc, char **argv,
return ret_max; return ret_max;
} }
int process_each_pv(int argc, char **argv, struct volume_group *vg,
int (*process_single) (struct volume_group * vg,
struct physical_volume * pv))
{
int opt = 0;
int ret_max = 0;
int ret = 0;
struct list_head *pvh;
if (argc) {
log_verbose("Using physical volume(s) on command line");
for (; opt < argc; opt++) {
if (!(pvh = find_pv_in_vg(vg, argv[opt]))) {
log_error("Physical Volume %s not found in "
"Volume Group %s", argv[opt],
vg->name);
continue;
}
ret = process_single(vg, &list_entry
(pvh, struct pv_list, list)->pv);
if (ret > ret_max)
ret_max = ret;
}
} else {
log_verbose("Using all physical volume(s) in volume group");
list_for_each(pvh, &vg->pvs) {
ret = process_single(vg, &list_entry
(pvh, struct pv_list, list)->pv);
if (ret > ret_max)
ret_max = ret;
}
}
return ret_max;
}
int is_valid_chars(char *n) int is_valid_chars(char *n)
{ {
register char c; register char c;
while ((c = *n++)) while ((c = *n++))
if (!isalnum(c) && c != '.' && c != '_' && c != '-' && if (!isalnum(c) && c != '.' && c != '_' && c != '-' && c != '+')
c != '+')
return 0; return 0;
return 1; return 1;
} }
struct list_head *find_pv_in_vg(struct volume_group *vg, const char *pv_name)
{
struct list_head *pvh;
list_for_each(pvh, &vg->pvs) {
if (!strcmp(list_entry(pvh, struct pv_list, list)->pv.dev->name,
pv_name)) return pvh;
}
return NULL;
}

View File

@ -28,6 +28,12 @@ int do_autobackup(struct volume_group *vg);
int process_each_vg(int argc, char **argv, int process_each_vg(int argc, char **argv,
int (*process_single) (const char *vg_name)); int (*process_single) (const char *vg_name));
int process_each_pv(int argc, char **argv, struct volume_group *vg,
int (*process_single) (struct volume_group * vg,
struct physical_volume * pv));
int is_valid_chars(char *n); int is_valid_chars(char *n);
struct list_head *find_pv_in_vg(struct volume_group *vg, const char *pv_name);
#endif #endif

132
tools/vgreduce.c Normal file
View File

@ -0,0 +1,132 @@
/*
* Copyright (C) 2001 Sistina Software
*
* LVM is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* LVM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LVM; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
*/
#include "tools.h"
static int vgreduce_single(struct volume_group *vg, struct physical_volume *pv);
int vgreduce(int argc, char **argv)
{
struct volume_group *vg;
char *vg_name;
if (!argc) {
log_error("Please give volume group name and "
"physical volume paths");
return EINVALID_CMD_LINE;
}
if (argc == 1 && !arg_count(all_ARG)) {
log_error("Please enter physical volume paths or option -a");
return EINVALID_CMD_LINE;
}
if (argc > 1 && arg_count(all_ARG)) {
log_error("Option -a and physical volume paths mutually "
"exclusive");
return EINVALID_CMD_LINE;
}
vg_name = argv[0];
argv++;
argc--;
log_verbose("Finding volume group %s", vg_name);
if (!(vg = ios->vg_read(ios, vg_name))) {
log_error("Volume group %s doesn't exist", vg_name);
return ECMD_FAILED;
}
if (!(vg->status & ACTIVE)) {
log_error("Volume group %s is not active", vg_name);
return ECMD_FAILED;
}
if (!(vg->status & EXTENDABLE_VG)) {
log_error("Volume group %s is not reducable", vg_name);
return ECMD_FAILED;
}
/* FIXME: Pass private structure through to all these functions */
/* and update in batch here? */
return process_each_pv(argc, argv, vg, vgreduce_single);
/******* FIXME
log_error ("no empty physical volumes found in volume group \"%s\"", vg_name);
log_verbose
("volume group \"%s\" will be reduced by %d physical volume%s",
vg_name, np, np > 1 ? "s" : "");
log_verbose ("reducing volume group \"%s\" by physical volume \"%s\"", vg_name, pv_names[p]);
log_print
("volume group \"%s\" %ssuccessfully reduced by physical volume%s:",
vg_name, error > 0 ? "NOT " : "", p > 1 ? "s" : "");
log_print("%s", pv_this[p]->pv_name);
********/
}
/* Or take pv_name instead? */
static int vgreduce_single(struct volume_group *vg, struct physical_volume *pv)
{
struct list_head *pvh;
if (pv->pe_allocated) {
log_error("Physical volume %s still in use", pv->dev->name);
return ECMD_FAILED;
}
/********* FIXME: Is this unnecessary after checking pe_allocated?
if (pv->lv_cur > 0) {
log_error ("can't reduce volume group \"%s\" by used physical volume \"%s\"", vg_name, error_pv_name);
}
*********/
if (vg->pv_count == 1) {
log_error("Can't remove final physical volume %s from "
"volume group %s", pv->dev->name, vg->name);
return ECMD_FAILED;
}
pvh = find_pv_in_vg(vg, pv->dev->name);
log_verbose("Removing %s from volume group %s", pv->dev->name,
vg->name);
list_del(pvh);
*pv->vg_name = '\0';
vg->pv_count--;
if (!(ios->vg_write(ios, vg))) {
log_error("Removal of physical volume %s from %s failed",
pv->dev->name, vg->name);
return ECMD_FAILED;
}
if (!ios->pv_write(ios, pv)) {
log_error("Failed to clear metadata from physical volume %s "
"after removal from %s", pv->dev->name, vg->name);
return ECMD_FAILED;
}
log_print("Removed %s from volume group %s", pv->dev->name, vg->name);
return 0;
}

View File

@ -32,13 +32,13 @@ static int vgremove_single(const char *vg_name)
struct volume_group *vg; struct volume_group *vg;
struct physical_volume *pv; struct physical_volume *pv;
struct list_head *pvh; struct list_head *pvh;
int ret = 0;
log_verbose("Checking for volume group %s", vg_name); log_verbose("Checking for 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 is still active", vg_name); log_error("Volume group %s is still active", vg_name);
@ -47,7 +47,7 @@ static int vgremove_single(const char *vg_name)
if (vg->lv_count) { if (vg->lv_count) {
log_error("Volume group %s still contains %d logical volume(s)", log_error("Volume group %s still contains %d logical volume(s)",
vg_name, vg->lv_count); vg_name, vg->lv_count);
return ECMD_FAILED; return ECMD_FAILED;
} }
@ -58,19 +58,23 @@ static int vgremove_single(const char *vg_name)
} }
*************/ *************/
/* init physical volumes */ /* init physical volumes */
list_for_each(pvh, &vg->pvs) { list_for_each(pvh, &vg->pvs) {
pv = &list_entry(pvh, struct pv_list, list)->pv; pv = &list_entry(pvh, struct pv_list, list)->pv;
log_verbose("Removing physical volume %s from volume group %s", log_verbose("Removing physical volume %s from volume group %s",
pv->dev->name, vg_name); pv->dev->name, vg_name);
pv->vg_name = '\0'; *pv->vg_name = '\0';
if (!(ios->pv_write(ios, pv))) if (!(ios->pv_write(ios, pv))) {
log_error("Failed to remove physical volume %s from " log_error("Failed to remove physical volume %s from "
"volume group %s", pv->dev->name, vg_name); "volume group %s", pv->dev->name, vg_name);
ret = ECMD_FAILED;
}
} }
log_print("Volume group %s successfully removed", vg_name); if (!ret)
log_print("Volume group %s successfully removed", vg_name);
else
log_error("Volume group %s not properly removed", vg_name);
return 0; return ret;
} }

View File

@ -92,8 +92,8 @@ int vgrename(int argc, char **argv)
/* FIXME Should vg_write fix these implicitly? It has to check them. */ /* FIXME Should vg_write fix these implicitly? It has to check them. */
list_for_each(pvh, &vg_old->pvs) { list_for_each(pvh, &vg_old->pvs) {
strcpy(list_entry(pvh, struct pv_list, list)->pv.vg_name, strcpy(list_entry(pvh, struct pv_list, list)->pv.vg_name,
vg_name_new); vg_name_new);
} }
/********** FIXME: Check within vg_write now /********** FIXME: Check within vg_write now
@ -147,4 +147,3 @@ char *lv_change_vgname(char *vg_name, char *lv_name)
strncpy(lv_name_buf, lv_name, NAME_LEN - 1); return lv_name_buf;} strncpy(lv_name_buf, lv_name, NAME_LEN - 1); return lv_name_buf;}
**********************/ **********************/

66
tools/vgscan.c Normal file
View File

@ -0,0 +1,66 @@
/*
* Copyright (C) 2001 Sistina Software
*
* LVM is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* LVM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LVM; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
*/
#include "tools.h"
static int vgscan_single(const char *vg_name);
int vgscan(int argc, char **argv)
{
if (argc) {
log_error("Too many parameters on command line");
return EINVALID_CMD_LINE;
}
log_print("Reading all physical volumes (this may take a while...)");
return process_each_vg(argc, argv, &vgscan_single);
}
static int vgscan_single(const char *vg_name)
{
struct volume_group *vg;
log_verbose("Checking for volume group %s", vg_name);
if (!(vg = ios->vg_read(ios, vg_name))) {
log_error("Volume group %s not found", vg_name);
return ECMD_FAILED;
}
log_print("Found %sactive volume group %s",
(vg->status & ACTIVE) ? "" : "in", vg_name);
/* FIXME: Now try to activate any inactive logical volumes */
/* activate_lvs(vg) ? */
if (!(vg->status & ACTIVE)) {
vg->status |= ACTIVE;
if (!(ios->vg_write(ios, vg))) {
log_error("Failed to activate volume group %s",
vg_name);
return ECMD_FAILED;
}
/* FIXME: Create /dev/vg entries? */
log_print("Volume Group %s activated", vg_name);
}
return 0;
}