1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-22 17:35:59 +03:00

lvdisplay & lvreduce

This commit is contained in:
Alasdair Kergon 2001-11-08 16:15:58 +00:00
parent 039bd945e2
commit 87e201460a
8 changed files with 472 additions and 164 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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;
}

View File

@ -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)

View File

@ -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
View 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
View 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;
}

View File

@ -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;}