1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-03-10 16:58:47 +03:00

lvdisplay & lvreduce

This commit is contained in:
Alasdair Kergon 2001-11-08 16:15:58 +00:00
parent f90fc5faf0
commit 94b8220f6a
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; 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; struct dm_task *dmt;
if (!(dmt = _info(lv))) { if (!(dmt = _info(lv))) {
stack; stack;
return 0; return r;
} }
if (!dm_task_exists(dmt, result)) { if (!dm_task_exists(dmt, &r)) {
stack; stack;
goto out; goto out;
} }
r = 1;
out: out:
dm_task_destroy(dmt); dm_task_destroy(dmt);
return r; 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; struct dm_task *dmt;
if (!(dmt = _info(lv))) { if (!(dmt = _info(lv))) {
stack; stack;
return 0; return r;
} }
if (!dm_task_open_count(dmt, result)) { if (!dm_task_open_count(dmt, &r)) {
stack; stack;
goto out; goto out;
} }
r = 1;
out: out:
dm_task_destroy(dmt); dm_task_destroy(dmt);
return r; return r;
@ -230,15 +226,12 @@ int activate_lvs_in_vg(struct volume_group *vg)
{ {
struct list *lvh; struct list *lvh;
struct logical_volume *lv; struct logical_volume *lv;
int count = 0, exists; int count = 0;
list_iterate(lvh, &vg->lvs) { list_iterate(lvh, &vg->lvs) {
lv = &(list_item(lvh, struct lv_list)->lv); lv = &(list_item(lvh, struct lv_list)->lv);
if (!lv_active(lv, &exists) || exists) count += (!lv_active(lv) && lv_activate(lv));
continue;
count += lv_activate(lv);
} }
return count; return count;
@ -253,15 +246,12 @@ int deactivate_lvs_in_vg(struct volume_group *vg)
{ {
struct list *lvh; struct list *lvh;
struct logical_volume *lv; struct logical_volume *lv;
int count = 0, exists; int count = 0;
list_iterate(lvh, &vg->lvs) { list_iterate(lvh, &vg->lvs) {
lv = &(list_item(lvh, struct lv_list)->lv); lv = &(list_item(lvh, struct lv_list)->lv);
if (!lv_active(lv, &exists) || !exists) count += ((lv_active(lv) == 1) && lv_deactivate(lv));
continue;
count += lv_activate(lv);
} }
return count; return count;
@ -271,17 +261,12 @@ int lvs_in_vg_activated(struct volume_group *vg)
{ {
struct list *lvh; struct list *lvh;
struct logical_volume *lv; struct logical_volume *lv;
int exists, count = 0; int count = 0;
list_iterate(lvh, &vg->lvs) { list_iterate(lvh, &vg->lvs) {
lv = &(list_item(lvh, struct lv_list)->lv); lv = &(list_item(lvh, struct lv_list)->lv);
if (!lv_active(lv, &exists)) { count += (lv_active(lv) == 1);
stack;
continue; /* FIXME: what is the right thing here ? */
}
count += exists ? 1 : 0;
} }
return count; return count;
@ -291,17 +276,12 @@ int lvs_in_vg_opened(struct volume_group *vg)
{ {
struct list *lvh; struct list *lvh;
struct logical_volume *lv; struct logical_volume *lv;
int open, count = 0; int count = 0;
list_iterate(lvh, &vg->lvs) { list_iterate(lvh, &vg->lvs) {
lv = &(list_item(lvh, struct lv_list)->lv); lv = &(list_item(lvh, struct lv_list)->lv);
if (!lv_open_count(lv, &open)) { count += (lv_open_count(lv) == 1);
stack;
continue; /* FIXME: what is the right thing here ? */
}
count += open ? 1 : 0;
} }
return count; return count;

View File

@ -9,8 +9,8 @@
/* FIXME Snapshot handling? */ /* FIXME Snapshot handling? */
int lv_active(struct logical_volume *lv, int *result); int lv_active(struct logical_volume *lv);
int lv_open_count(struct logical_volume *lv, int *result); int lv_open_count(struct logical_volume *lv);
int lv_activate(struct logical_volume *lv); int lv_activate(struct logical_volume *lv);
int lv_reactivate(struct logical_volume *lv); int lv_reactivate(struct logical_volume *lv);

View File

@ -24,6 +24,7 @@
#include "dbg_malloc.h" #include "dbg_malloc.h"
#include "log.h" #include "log.h"
#include "display.h" #include "display.h"
#include "activate.h"
#define SIZE_BUF 128 #define SIZE_BUF 128
@ -205,141 +206,199 @@ void pv_display_short(struct physical_volume *pv)
return; return;
} }
#if 0 void lvdisplay_colons(struct logical_volume *lv)
/******** FIXME
void pv_display_pe(pv_t * pv, pe_disk_t * pe)
{ {
int p; log_print("%s/%s:%s:%d:%d:-1:%d:%llu:%d:-1:%d:%d:-1:-1",
/* FIXME Prefix - attach to struct volume_group? */
for (p = 0; p < pv->pe_total; p++) lv->vg->name,
printf("pe#: %4d vg: %s lv: %d le: %d\n", lv->name,
p, pv->vg_name, pe[p].lv_num, pe[p].le_num); 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; 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; return;
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;
if ((pe_this = dbg_malloc(pv->pe_total * sizeof (pe_disk_t))) == NULL) { void lvdisplay_full(struct logical_volume *lv)
log_error("pe_this allocation failed"); {
goto pv_display_pe_text_out; 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;
} }
printf("LV snapshot status ");
if ((pe_this_count = dbg_malloc(pv->pe_total * sizeof (int))) == NULL) { if (vg_check_active(vg_name) == TRUE) {
log_error("pe_this_count allocation failed"); vg_t *vg_core;
goto pv_display_pe_text_out; if ((ret = vg_status_with_pv_and_lv(vg_name, &vg_core)) == 0) {
} lv_t *lv_ptr =
vg_core->
memset(pe_this, 0, pv->pe_total * sizeof (pe_disk_t)); lv[lv_get_index_by_name(vg_core, lv->lv_name)];
memset(pe_this_count, 0, pv->pe_total * sizeof (int)); if (lv_ptr->lv_access & LV_SNAPSHOT) {
if (lv_ptr->lv_status & LV_ACTIVE)
/* get PE and LE summaries */ printf("active ");
pt_count = 0; else
for (p = pt_count; p < pv->pe_total; p++) { printf("INACTIVE ");
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++;
}
} }
} if (lv_ptr->lv_access & LV_SNAPSHOT_ORG) {
printf("source of\n");
lv = lvs; while (lv_ptr->lv_snapshot_next != NULL) {
printf(" --- Distribution of physical volume ---\n" lv_ptr = lv_ptr->lv_snapshot_next;
" LV Name LE of LV PE for LV\n"); printf(" %s [%s]\n",
for (pt = 0; pt < pt_count; pt++) { lv_ptr->lv_name,
printf(" %-25s ", lv->lv_name); (lv_ptr->
if (strlen(lv->lv_name) > 25) lv_status & LV_ACTIVE) ? "active" :
printf("\n "); "INACTIVE");
printf("%-8u %-8d\n", }
lv->lv_allocated_le, vg_free(vg_core, TRUE);
pe_this_count[pt]); } else {
if (pe_this[pt].lv_num > lv_num_last) { printf("destination for %s\n",
lv_num_last = pe_this[pt].lv_num; lv_ptr->lv_snapshot_org->lv_name);
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;
} }
strcpy(&lv_names[(pe_this[pt].lv_num - 1) * NAME_LEN], }
lv->lv_name); } else {
lv++; printf("INACTIVE ");
if (lv->lv_access & LV_SNAPSHOT_ORG)
printf("original\n");
else
printf("snapshot\n");
} }
}
***********/
printf("\n --- Physical extents ---\n" log_print("LV Status %savailable",
" PE LV LE Disk sector\n"); (lv->status & ACTIVE) ? "" : "NOT ");
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));
} else if (pe_free == -1) /********* FIXME lv_number
pe_free = p; log_print("LV # %u", lv->lv_number + 1);
} ************/
if (pe_free > 0) /********* FIXME lv_open
pv_display_pe_free(pe_free, p); log_print("# open %u\n", lv->lv_open);
**********/
pv_display_pe_text_out: /********
if (lv_names != NULL) #ifdef LVM_FUTURE
dbg_free(lv_names); printf("Mirror copies %u\n", lv->lv_mirror_copies);
else if (lv_names_sav != NULL) printf("Consistency recovery ");
dbg_free(lv_names_sav); if (lv->lv_recovery | LV_BADBLOCK_ON)
if (pe_this != NULL) printf("bad blocks\n");
dbg_free(pe_this); else
if (pe_this_count != NULL) printf("none\n");
dbg_free(pe_this_count); printf("Schedule %u\n", lv->lv_schedule);
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;
}
#endif #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_err(x...) plog(_LOG_ERR, x)
#define log_fatal(x...) plog(_LOG_FATAL, 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_error(fmt, args...) log_err(fmt , ## args)
#define log_print(fmt, args...) log_warn(fmt , ## args) #define log_print(fmt, args...) log_warn(fmt , ## args)

View File

@ -23,8 +23,10 @@ VPATH = @srcdir@
SOURCES=\ SOURCES=\
lvchange.c \ lvchange.c \
lvcreate.c \ lvcreate.c \
lvdisplay.c \
lvm.c \ lvm.c \
lvmchange.c \ lvmchange.c \
lvreduce.c \
lvremove.c \ lvremove.c \
lvscan.c \ lvscan.c \
pvchange.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 e2fsadm(int argc, char **argv) {return 1;}
int lvdisplay(int argc, char **argv) {return 1;}
int lvextend(int argc, char **argv) {return 1;} int lvextend(int argc, char **argv) {return 1;}
int lvmdiskscan(int argc, char **argv) {return 1;} 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 lvrename(int argc, char **argv) {return 1;} int lvrename(int argc, char **argv) {return 1;}
int pvdata(int argc, char **argv) {return 1;} int pvdata(int argc, char **argv) {return 1;}
int vgcfgbackup(int argc, char **argv) {return 1;} int vgcfgbackup(int argc, char **argv) {return 1;}