mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-22 17:35:59 +03:00
lvdisplay & lvreduce
This commit is contained in:
parent
039bd945e2
commit
87e201460a
@ -52,45 +52,41 @@ static struct dm_task *_info(struct logical_volume *lv)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int lv_active(struct logical_volume *lv, int *result)
|
||||
int lv_active(struct logical_volume *lv)
|
||||
{
|
||||
int r = 0;
|
||||
int r = -1;
|
||||
struct dm_task *dmt;
|
||||
|
||||
if (!(dmt = _info(lv))) {
|
||||
stack;
|
||||
return 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
if (!dm_task_exists(dmt, result)) {
|
||||
if (!dm_task_exists(dmt, &r)) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
|
||||
r = 1;
|
||||
|
||||
out:
|
||||
dm_task_destroy(dmt);
|
||||
return r;
|
||||
}
|
||||
|
||||
int lv_open_count(struct logical_volume *lv, int *result)
|
||||
int lv_open_count(struct logical_volume *lv)
|
||||
{
|
||||
int r = 0;
|
||||
int r = -1;
|
||||
struct dm_task *dmt;
|
||||
|
||||
if (!(dmt = _info(lv))) {
|
||||
stack;
|
||||
return 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
if (!dm_task_open_count(dmt, result)) {
|
||||
if (!dm_task_open_count(dmt, &r)) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
|
||||
r = 1;
|
||||
|
||||
out:
|
||||
dm_task_destroy(dmt);
|
||||
return r;
|
||||
@ -230,15 +226,12 @@ int activate_lvs_in_vg(struct volume_group *vg)
|
||||
{
|
||||
struct list *lvh;
|
||||
struct logical_volume *lv;
|
||||
int count = 0, exists;
|
||||
int count = 0;
|
||||
|
||||
list_iterate(lvh, &vg->lvs) {
|
||||
lv = &(list_item(lvh, struct lv_list)->lv);
|
||||
|
||||
if (!lv_active(lv, &exists) || exists)
|
||||
continue;
|
||||
|
||||
count += lv_activate(lv);
|
||||
count += (!lv_active(lv) && lv_activate(lv));
|
||||
}
|
||||
|
||||
return count;
|
||||
@ -253,15 +246,12 @@ int deactivate_lvs_in_vg(struct volume_group *vg)
|
||||
{
|
||||
struct list *lvh;
|
||||
struct logical_volume *lv;
|
||||
int count = 0, exists;
|
||||
int count = 0;
|
||||
|
||||
list_iterate(lvh, &vg->lvs) {
|
||||
lv = &(list_item(lvh, struct lv_list)->lv);
|
||||
|
||||
if (!lv_active(lv, &exists) || !exists)
|
||||
continue;
|
||||
|
||||
count += lv_activate(lv);
|
||||
count += ((lv_active(lv) == 1) && lv_deactivate(lv));
|
||||
}
|
||||
|
||||
return count;
|
||||
@ -271,17 +261,12 @@ int lvs_in_vg_activated(struct volume_group *vg)
|
||||
{
|
||||
struct list *lvh;
|
||||
struct logical_volume *lv;
|
||||
int exists, count = 0;
|
||||
int count = 0;
|
||||
|
||||
list_iterate(lvh, &vg->lvs) {
|
||||
lv = &(list_item(lvh, struct lv_list)->lv);
|
||||
|
||||
if (!lv_active(lv, &exists)) {
|
||||
stack;
|
||||
continue; /* FIXME: what is the right thing here ? */
|
||||
}
|
||||
|
||||
count += exists ? 1 : 0;
|
||||
count += (lv_active(lv) == 1);
|
||||
}
|
||||
|
||||
return count;
|
||||
@ -291,17 +276,12 @@ int lvs_in_vg_opened(struct volume_group *vg)
|
||||
{
|
||||
struct list *lvh;
|
||||
struct logical_volume *lv;
|
||||
int open, count = 0;
|
||||
int count = 0;
|
||||
|
||||
list_iterate(lvh, &vg->lvs) {
|
||||
lv = &(list_item(lvh, struct lv_list)->lv);
|
||||
|
||||
if (!lv_open_count(lv, &open)) {
|
||||
stack;
|
||||
continue; /* FIXME: what is the right thing here ? */
|
||||
}
|
||||
|
||||
count += open ? 1 : 0;
|
||||
count += (lv_open_count(lv) == 1);
|
||||
}
|
||||
|
||||
return count;
|
||||
|
@ -9,8 +9,8 @@
|
||||
|
||||
/* FIXME Snapshot handling? */
|
||||
|
||||
int lv_active(struct logical_volume *lv, int *result);
|
||||
int lv_open_count(struct logical_volume *lv, int *result);
|
||||
int lv_active(struct logical_volume *lv);
|
||||
int lv_open_count(struct logical_volume *lv);
|
||||
|
||||
int lv_activate(struct logical_volume *lv);
|
||||
int lv_reactivate(struct logical_volume *lv);
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "dbg_malloc.h"
|
||||
#include "log.h"
|
||||
#include "display.h"
|
||||
#include "activate.h"
|
||||
|
||||
#define SIZE_BUF 128
|
||||
|
||||
@ -205,141 +206,199 @@ void pv_display_short(struct physical_volume *pv)
|
||||
return;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/******** FIXME
|
||||
void pv_display_pe(pv_t * pv, pe_disk_t * pe)
|
||||
void lvdisplay_colons(struct logical_volume *lv)
|
||||
{
|
||||
int p;
|
||||
|
||||
for (p = 0; p < pv->pe_total; p++)
|
||||
printf("pe#: %4d vg: %s lv: %d le: %d\n",
|
||||
p, pv->vg_name, pe[p].lv_num, pe[p].le_num);
|
||||
|
||||
log_print("%s/%s:%s:%d:%d:-1:%d:%llu:%d:-1:%d:%d:-1:-1",
|
||||
/* FIXME Prefix - attach to struct volume_group? */
|
||||
lv->vg->name,
|
||||
lv->name,
|
||||
lv->vg->name,
|
||||
(lv->status & (LVM_READ | LVM_WRITE)) >> 8,
|
||||
lv->status & ACTIVE,
|
||||
/* FIXME lv->lv_number, */
|
||||
lvs_in_vg_opened(lv->vg),
|
||||
lv->size,
|
||||
lv->le_count,
|
||||
/* FIXME num allocated? */
|
||||
(lv->status & (ALLOC_STRICT | ALLOC_CONTIGUOUS)) >> 12,
|
||||
lv->read_ahead
|
||||
/* FIXME device num MAJOR(lv->lv_dev), MINOR(lv->lv_dev) */
|
||||
);
|
||||
return;
|
||||
}
|
||||
*******/
|
||||
|
||||
void pv_display_pe_text(pv_t * pv, pe_disk_t * pe, lv_disk_t * lvs)
|
||||
void lvdisplay_extents(struct logical_volume *lv)
|
||||
{
|
||||
int flag = 0;
|
||||
int lv_num_last = 0;
|
||||
int p = 0;
|
||||
int pe_free = 0;
|
||||
int *pe_this_count = NULL;
|
||||
int pt = 0;
|
||||
int pt_count = 0;
|
||||
lv_disk_t *lv;
|
||||
char *lv_name_this = NULL;
|
||||
char *lv_names = NULL;
|
||||
char *lv_names_sav = NULL;
|
||||
pe_disk_t *pe_this = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((pe_this = dbg_malloc(pv->pe_total * sizeof (pe_disk_t))) == NULL) {
|
||||
log_error("pe_this allocation failed");
|
||||
goto pv_display_pe_text_out;
|
||||
void lvdisplay_full(struct logical_volume *lv)
|
||||
{
|
||||
char *size;
|
||||
uint32_t alloc;
|
||||
|
||||
log_print("--- Logical volume ---");
|
||||
|
||||
/* FIXME prefix */
|
||||
log_print("LV Name %s/%s", lv->vg->name, lv->name);
|
||||
log_print("VG Name %s", lv->vg->name);
|
||||
|
||||
log_print("LV Write Access %s",
|
||||
(lv->status & LVM_WRITE) ? "read/write" : "read only");
|
||||
|
||||
/******* FIXME Snapshot
|
||||
if (lv->status & (LVM_SNAPSHOT_ORG | LVM_SNAPSHOT)) {
|
||||
if (lvm_tab_vg_read_with_pv_and_lv(vg_name, &vg) < 0) {
|
||||
ret = -LVM_ELV_SHOW_VG_READ_WITH_PV_AND_LV;
|
||||
goto lv_show_end;
|
||||
}
|
||||
|
||||
if ((pe_this_count = dbg_malloc(pv->pe_total * sizeof (int))) == NULL) {
|
||||
log_error("pe_this_count allocation failed");
|
||||
goto pv_display_pe_text_out;
|
||||
}
|
||||
|
||||
memset(pe_this, 0, pv->pe_total * sizeof (pe_disk_t));
|
||||
memset(pe_this_count, 0, pv->pe_total * sizeof (int));
|
||||
|
||||
/* get PE and LE summaries */
|
||||
pt_count = 0;
|
||||
for (p = pt_count; p < pv->pe_total; p++) {
|
||||
if (pe[p].lv_num != 0) {
|
||||
flag = 0;
|
||||
for (pt = 0; pt < pt_count; pt++) {
|
||||
if (pe_this[pt].lv_num == pe[p].lv_num) {
|
||||
flag = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (flag == 0) {
|
||||
pe_this[pt_count].lv_num = pe[p].lv_num;
|
||||
for (pt = 0; pt < pv->pe_total; pt++)
|
||||
if (pe_this[pt_count].lv_num ==
|
||||
pe[pt].lv_num)
|
||||
pe_this_count[pt_count]++;
|
||||
pt_count++;
|
||||
}
|
||||
printf("LV snapshot status ");
|
||||
if (vg_check_active(vg_name) == TRUE) {
|
||||
vg_t *vg_core;
|
||||
if ((ret = vg_status_with_pv_and_lv(vg_name, &vg_core)) == 0) {
|
||||
lv_t *lv_ptr =
|
||||
vg_core->
|
||||
lv[lv_get_index_by_name(vg_core, lv->lv_name)];
|
||||
if (lv_ptr->lv_access & LV_SNAPSHOT) {
|
||||
if (lv_ptr->lv_status & LV_ACTIVE)
|
||||
printf("active ");
|
||||
else
|
||||
printf("INACTIVE ");
|
||||
}
|
||||
}
|
||||
|
||||
lv = lvs;
|
||||
printf(" --- Distribution of physical volume ---\n"
|
||||
" LV Name LE of LV PE for LV\n");
|
||||
for (pt = 0; pt < pt_count; pt++) {
|
||||
printf(" %-25s ", lv->lv_name);
|
||||
if (strlen(lv->lv_name) > 25)
|
||||
printf("\n ");
|
||||
printf("%-8u %-8d\n",
|
||||
lv->lv_allocated_le,
|
||||
pe_this_count[pt]);
|
||||
if (pe_this[pt].lv_num > lv_num_last) {
|
||||
lv_num_last = pe_this[pt].lv_num;
|
||||
lv_names_sav = lv_names;
|
||||
if ((lv_names = dbg_realloc(lv_names,
|
||||
lv_num_last * NAME_LEN)) ==
|
||||
NULL) {
|
||||
log_error("realloc error in %s [line %d]",
|
||||
__FILE__, __LINE__);
|
||||
goto pv_display_pe_text_out;
|
||||
} else
|
||||
lv_names_sav = NULL;
|
||||
if (lv_ptr->lv_access & LV_SNAPSHOT_ORG) {
|
||||
printf("source of\n");
|
||||
while (lv_ptr->lv_snapshot_next != NULL) {
|
||||
lv_ptr = lv_ptr->lv_snapshot_next;
|
||||
printf(" %s [%s]\n",
|
||||
lv_ptr->lv_name,
|
||||
(lv_ptr->
|
||||
lv_status & LV_ACTIVE) ? "active" :
|
||||
"INACTIVE");
|
||||
}
|
||||
vg_free(vg_core, TRUE);
|
||||
} else {
|
||||
printf("destination for %s\n",
|
||||
lv_ptr->lv_snapshot_org->lv_name);
|
||||
}
|
||||
strcpy(&lv_names[(pe_this[pt].lv_num - 1) * NAME_LEN],
|
||||
lv->lv_name);
|
||||
lv++;
|
||||
}
|
||||
} else {
|
||||
printf("INACTIVE ");
|
||||
if (lv->lv_access & LV_SNAPSHOT_ORG)
|
||||
printf("original\n");
|
||||
else
|
||||
printf("snapshot\n");
|
||||
}
|
||||
}
|
||||
***********/
|
||||
|
||||
printf("\n --- Physical extents ---\n"
|
||||
" PE LV LE Disk sector\n");
|
||||
pe_free = -1;
|
||||
for (p = 0; p < pv->pe_total; p++) {
|
||||
if (pe[p].lv_num != 0) {
|
||||
if (pe_free > -1) {
|
||||
pv_display_pe_free(pe_free, p);
|
||||
pe_free = -1;
|
||||
}
|
||||
lv_name_this = &lv_names[(pe[p].lv_num - 1) * NAME_LEN];
|
||||
printf(" %05d %-25s ", p, lv_name_this);
|
||||
if (strlen(lv_name_this) > 25)
|
||||
printf("\n ");
|
||||
printf("%05d %ld\n", pe[p].le_num,
|
||||
get_pe_offset(p, pv));
|
||||
log_print("LV Status %savailable",
|
||||
(lv->status & ACTIVE) ? "" : "NOT ");
|
||||
|
||||
} else if (pe_free == -1)
|
||||
pe_free = p;
|
||||
}
|
||||
/********* FIXME lv_number
|
||||
log_print("LV # %u", lv->lv_number + 1);
|
||||
************/
|
||||
|
||||
if (pe_free > 0)
|
||||
pv_display_pe_free(pe_free, p);
|
||||
|
||||
pv_display_pe_text_out:
|
||||
if (lv_names != NULL)
|
||||
dbg_free(lv_names);
|
||||
else if (lv_names_sav != NULL)
|
||||
dbg_free(lv_names_sav);
|
||||
if (pe_this != NULL)
|
||||
dbg_free(pe_this);
|
||||
if (pe_this_count != NULL)
|
||||
dbg_free(pe_this_count);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void pv_display_pe_free(int pe_free, int p)
|
||||
{
|
||||
printf(" %05d free\n", pe_free);
|
||||
|
||||
if (p - pe_free > 1)
|
||||
printf(" .....\n %05d free\n", p - 1);
|
||||
|
||||
return;
|
||||
}
|
||||
/********* FIXME lv_open
|
||||
log_print("# open %u\n", lv->lv_open);
|
||||
**********/
|
||||
/********
|
||||
#ifdef LVM_FUTURE
|
||||
printf("Mirror copies %u\n", lv->lv_mirror_copies);
|
||||
printf("Consistency recovery ");
|
||||
if (lv->lv_recovery | LV_BADBLOCK_ON)
|
||||
printf("bad blocks\n");
|
||||
else
|
||||
printf("none\n");
|
||||
printf("Schedule %u\n", lv->lv_schedule);
|
||||
#endif
|
||||
********/
|
||||
|
||||
|
||||
size = display_size(lv->size / 2, SIZE_SHORT);
|
||||
log_print("LV Size %s", size);
|
||||
dbg_free(size);
|
||||
|
||||
log_print("Current LE %u", lv->le_count);
|
||||
|
||||
/********** FIXME allocation
|
||||
log_print("Allocated LE %u", lv->allocated_le);
|
||||
**********/
|
||||
|
||||
/********** FIXME Snapshot
|
||||
if (lv->lv_access & LV_SNAPSHOT) {
|
||||
printf("snapshot chunk size %s\n",
|
||||
(dummy = lvm_show_size(lv->lv_chunk_size / 2, SHORT)));
|
||||
dbg_free(dummy);
|
||||
dummy = NULL;
|
||||
if (lv->lv_remap_end > 0) {
|
||||
lv_remap_ptr = lv->lv_remap_ptr;
|
||||
if (lv_remap_ptr > lv->lv_remap_end)
|
||||
lv_remap_ptr = lv->lv_remap_end;
|
||||
dummy = lvm_show_size(lv_remap_ptr *
|
||||
lv->lv_chunk_size / 2, SHORT);
|
||||
dummy1 = lvm_show_size(lv->lv_remap_end *
|
||||
lv->lv_chunk_size / 2, SHORT);
|
||||
printf("Allocated to snapshot %.2f%% [%s/%s]\n",
|
||||
(float) lv_remap_ptr * 100 / lv->lv_remap_end,
|
||||
dummy, dummy1);
|
||||
dbg_free(dummy);
|
||||
dbg_free(dummy1);
|
||||
dummy =
|
||||
lvm_show_size((vg->
|
||||
lv[lv_get_index_by_number
|
||||
(vg,
|
||||
lv->lv_number)]->lv_size -
|
||||
lv->lv_remap_end * lv->lv_chunk_size) / 2,
|
||||
SHORT);
|
||||
printf("Allocated to COW-table %s\n", dummy);
|
||||
dbg_free(dummy);
|
||||
}
|
||||
}
|
||||
******************/
|
||||
|
||||
if (lv->stripes > 1) {
|
||||
log_print("Stripes %u", lv->stripes);
|
||||
/*********** FIXME stripesize
|
||||
log_print("Stripe size (KByte) %u", lv->stripesize / 2);
|
||||
***********/
|
||||
}
|
||||
|
||||
|
||||
/**************
|
||||
#ifdef LVM_FUTURE
|
||||
printf("Bad block ");
|
||||
if (lv->lv_badblock == LV_BADBLOCK_ON)
|
||||
printf("on\n");
|
||||
else
|
||||
printf("off\n");
|
||||
#endif
|
||||
***************/
|
||||
|
||||
alloc = lv->status & (ALLOC_STRICT | ALLOC_CONTIGUOUS);
|
||||
log_print("Allocation %s%s%s%s",
|
||||
!(alloc & (ALLOC_STRICT | ALLOC_CONTIGUOUS)) ? "next free" : "",
|
||||
(alloc == ALLOC_STRICT) ? "strict" : "",
|
||||
(alloc == ALLOC_CONTIGUOUS) ? "contiguous" : "",
|
||||
(alloc == (ALLOC_STRICT | ALLOC_CONTIGUOUS)) ? "strict/contiguous" : ""
|
||||
);
|
||||
|
||||
log_print("Read ahead sectors %u\n", lv->read_ahead);
|
||||
|
||||
/****************
|
||||
#ifdef LVM_FUTURE
|
||||
printf("IO Timeout (seconds) ");
|
||||
if (lv->lv_io_timeout == 0)
|
||||
printf("default\n\n");
|
||||
else
|
||||
printf("%lu\n\n", lv->lv_io_timeout);
|
||||
#endif
|
||||
*************/
|
||||
|
||||
/********* FIXME blockdev
|
||||
printf("Block device %d:%d\n",
|
||||
MAJOR(lv->lv_dev), MINOR(lv->lv_dev));
|
||||
*************/
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -65,7 +65,7 @@ void print_log(int level, const char *file, int line, const char *format, ...)
|
||||
#define log_err(x...) plog(_LOG_ERR, x)
|
||||
#define log_fatal(x...) plog(_LOG_FATAL, x)
|
||||
|
||||
#define stack log_debug("stack")
|
||||
#define stack log_debug( "s" )
|
||||
|
||||
#define log_error(fmt, args...) log_err(fmt , ## args)
|
||||
#define log_print(fmt, args...) log_warn(fmt , ## args)
|
||||
|
@ -23,8 +23,10 @@ VPATH = @srcdir@
|
||||
SOURCES=\
|
||||
lvchange.c \
|
||||
lvcreate.c \
|
||||
lvdisplay.c \
|
||||
lvm.c \
|
||||
lvmchange.c \
|
||||
lvreduce.c \
|
||||
lvremove.c \
|
||||
lvscan.c \
|
||||
pvchange.c \
|
||||
|
86
tools/lvdisplay.c
Normal file
86
tools/lvdisplay.c
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
int lvdisplay_single(char *lv_name);
|
||||
int lvdisplay(int argc, char **argv)
|
||||
{
|
||||
int ret = 0;
|
||||
int ret_max = 0;
|
||||
int opt = 0;
|
||||
|
||||
/* FIXME Allow VG / all arguments via a process_each? */
|
||||
if (!argc) {
|
||||
log_error("Please enter one or more logical volume paths");
|
||||
return EINVALID_CMD_LINE;
|
||||
}
|
||||
|
||||
if (arg_count(colon_ARG) && arg_count(verbose_ARG)) {
|
||||
log_error("Options -v and -c are incompatible");
|
||||
return EINVALID_CMD_LINE;
|
||||
}
|
||||
|
||||
for (opt = 0; opt < argc; opt++) {
|
||||
ret = lvdisplay_single(argv[opt]);
|
||||
if (ret > ret_max)
|
||||
ret_max = ret;
|
||||
}
|
||||
|
||||
return ret_max;
|
||||
}
|
||||
|
||||
int lvdisplay_single(char *lv_name)
|
||||
{
|
||||
char *vg_name = NULL;
|
||||
|
||||
struct volume_group *vg;
|
||||
struct list *lvh;
|
||||
struct logical_volume *lv;
|
||||
|
||||
/* does VG exist? */
|
||||
if (!(vg_name = extract_vgname(ios, lv_name))) {
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
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 (!(lvh = find_lv_in_vg(vg, lv_name))) {
|
||||
log_error("Can't find logical volume %s in volume group %s",
|
||||
lv_name, vg_name);
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
lv = &list_item(lvh, struct lv_list)->lv;
|
||||
|
||||
if (arg_count(colon_ARG))
|
||||
lvdisplay_colons(lv);
|
||||
else {
|
||||
lvdisplay_full(lv);
|
||||
if (arg_count(verbose_ARG))
|
||||
lvdisplay_extents(lv);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
183
tools/lvreduce.c
Normal file
183
tools/lvreduce.c
Normal file
@ -0,0 +1,183 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
int lvreduce(int argc, char **argv)
|
||||
{
|
||||
struct volume_group *vg;
|
||||
struct logical_volume *lv;
|
||||
struct list *lvh;
|
||||
int32_t extents = 0;
|
||||
int32_t size = 0;
|
||||
char *lv_name, *vg_name;
|
||||
char *st;
|
||||
|
||||
if (arg_count(extents_ARG) + arg_count(size_ARG) != 1) {
|
||||
log_error("Please specify either size or extents (not both)");
|
||||
return EINVALID_CMD_LINE;
|
||||
}
|
||||
|
||||
/* FIXME signed use throughout halves the maximum... */
|
||||
if (arg_count(extents_ARG))
|
||||
extents = arg_int_value(extents_ARG, 0);
|
||||
|
||||
if (arg_count(size_ARG))
|
||||
size = arg_int_value(size_ARG, 0);
|
||||
|
||||
if (!argc) {
|
||||
log_error("Please provide the logical volume name");
|
||||
return EINVALID_CMD_LINE;
|
||||
}
|
||||
|
||||
lv_name = argv[0];
|
||||
argv++;
|
||||
argc--;
|
||||
|
||||
if (!(vg_name = extract_vgname(ios, lv_name))) {
|
||||
log_error("Please provide a volume group name");
|
||||
return EINVALID_CMD_LINE;
|
||||
}
|
||||
|
||||
if ((st = strrchr(lv_name, '/')))
|
||||
lv_name = st + 1;
|
||||
|
||||
/* does VG exist? */
|
||||
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 must be active before changing a "
|
||||
"logical volume", vg_name);
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
/* does LV exist? */
|
||||
if (!(lvh = find_lv_in_vg(vg, lv_name))) {
|
||||
log_error("Logical volume %s not found in volume group %s",
|
||||
lv_name, vg_name);
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
lv = &list_item(lvh, struct lv_list)->lv;
|
||||
|
||||
if (!(lv->status & ACTIVE)) {
|
||||
log_error("Logical volume %s must be active before reduction",
|
||||
lv_name);
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
if (size) {
|
||||
/* No of 512-byte sectors */
|
||||
extents = size * 2;
|
||||
|
||||
if (extents % vg->extent_size) {
|
||||
char *s1;
|
||||
|
||||
extents += (signed) vg->extent_size -
|
||||
(signed) (extents % vg->extent_size);
|
||||
log_print("Rounding up size to full physical extent %s",
|
||||
(s1 =
|
||||
display_size(abs(extents) / 2, SIZE_SHORT)));
|
||||
dbg_free(s1);
|
||||
}
|
||||
|
||||
extents /= (signed) vg->extent_size;
|
||||
}
|
||||
|
||||
if (!extents) {
|
||||
log_error("New size of 0 not permitted");
|
||||
return EINVALID_CMD_LINE;
|
||||
}
|
||||
|
||||
if (extents < 0) {
|
||||
if (1 - extents > lv->le_count) {
|
||||
log_error("Unable to reduce %s below 1 extent",
|
||||
lv_name);
|
||||
return EINVALID_CMD_LINE;
|
||||
}
|
||||
|
||||
lv->le_count += extents;
|
||||
} else {
|
||||
if (extents >= lv->le_count) {
|
||||
log_error("New size given (%d extents) not less than "
|
||||
"existing size (%d extents)", extents,
|
||||
lv->le_count);
|
||||
return EINVALID_CMD_LINE;
|
||||
}
|
||||
lv->le_count = extents;
|
||||
}
|
||||
|
||||
/************ FIXME Stripes
|
||||
size_rest = new_size % (vg->lv[l]->lv_stripes * vg->pe_size);
|
||||
if (size_rest != 0) {
|
||||
log_print
|
||||
("rounding size %ld KB to stripe boundary size ",
|
||||
new_size / 2);
|
||||
new_size = new_size - size_rest;
|
||||
printf("%ld KB\n", new_size / 2);
|
||||
}
|
||||
***********************/
|
||||
|
||||
if (lv->status & ACTIVE || lv_active(lv) > 0) {
|
||||
char *dummy;
|
||||
log_print("WARNING: Reducing active%s logical volume to %s",
|
||||
(lv_open_count(lv) > 0) ? " and open" : "",
|
||||
(dummy =
|
||||
display_size(lv->le_count * vg->extent_size / 2,
|
||||
SIZE_SHORT)));
|
||||
log_print("THIS MAY DESTROY YOUR DATA (filesystem etc.)");
|
||||
dbg_free(dummy);
|
||||
}
|
||||
|
||||
if (!arg_count(force_ARG)) {
|
||||
if (yes_no_prompt
|
||||
("Do you really want to reduce %s? [y/n]: ", lv_name)
|
||||
== 'n') {
|
||||
log_print("Logical volume %s NOT reduced", lv_name);
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
/********* FIXME Suspend lv ***********/
|
||||
|
||||
/* store vg on disk(s) */
|
||||
if (!ios->vg_write(ios, vg))
|
||||
return ECMD_FAILED;
|
||||
|
||||
/* FIXME Ensure it always displays errors? */
|
||||
if (!lv_reactivate(lv))
|
||||
return ECMD_FAILED;
|
||||
|
||||
/********* FIXME Resume *********/
|
||||
|
||||
/********* FIXME Backup
|
||||
if ((ret = do_autobackup(vg_name, vg)))
|
||||
return ret;
|
||||
************/
|
||||
|
||||
log_print("Logical volume %s reduced", lv_name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -19,12 +19,10 @@
|
||||
*/
|
||||
|
||||
int e2fsadm(int argc, char **argv) {return 1;}
|
||||
int lvdisplay(int argc, char **argv) {return 1;}
|
||||
int lvextend(int argc, char **argv) {return 1;}
|
||||
int lvmdiskscan(int argc, char **argv) {return 1;}
|
||||
int lvmsadc(int argc, char **argv) {return 1;}
|
||||
int lvmsar(int argc, char **argv) {return 1;}
|
||||
int lvreduce(int argc, char **argv) {return 1;}
|
||||
int lvrename(int argc, char **argv) {return 1;}
|
||||
int pvdata(int argc, char **argv) {return 1;}
|
||||
int vgcfgbackup(int argc, char **argv) {return 1;}
|
||||
|
Loading…
Reference in New Issue
Block a user