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

o Actually read snapshot percentage from the kernel - what a pain! :)

o Not sure if the code in dev_manager is really optimal, but it works..
   will look at adjusting it a bit now.
 o I *think* it works right when one snapshot if full but others aren't,
   but I haven't really been able to test it because the full snapshot
   somehow resets itself and weird things start happening to the system...
This commit is contained in:
AJ Lewis 2002-05-09 21:17:57 +00:00
parent 64ad493eac
commit 1951dba955
5 changed files with 154 additions and 89 deletions

View File

@ -75,6 +75,27 @@ int lv_info(struct logical_volume *lv, struct dm_info *info)
return r;
}
/*
* Returns 1 if percent set, else 0 on failure.
*/
int lv_snapshot_percentage(struct logical_volume *lv, float *percent)
{
int r;
struct dev_manager *dm;
if (!(dm = dev_manager_create(lv->vg->name))) {
stack;
return 0;
}
if (!(r = dev_manager_get_snapshot_use(dm, lv, percent)))
stack;
dev_manager_destroy(dm);
return r;
}
static int _lv_active(struct logical_volume *lv)
{
struct dm_info info;

View File

@ -16,6 +16,10 @@ int library_version(char *version, size_t size);
* Returns 1 if info structure has been populated, else 0.
*/
int lv_info(struct logical_volume *lv, struct dm_info *info);
/*
* Returns 1 if percent has been set, else 0.
*/
int lv_snapshot_percentage(struct logical_volume *lv, float *percent);
/*
* These should eventually use config file

View File

@ -329,6 +329,60 @@ static int _info(const char *name, const char *uuid, struct dm_info *info,
return 0;
}
static int _status_run(const char *name, const char *uuid, char **status,
int *size)
{
int r = 0;
struct dm_task *dmt;
void *next = NULL;
unsigned long long start, length;
char *type = NULL;
char *params;
if (!(dmt = _setup_task(name, uuid, DM_DEVICE_STATUS))) {
stack;
return 0;
}
if (!dm_task_run(dmt)) {
stack;
goto out;
}
do {
next = dm_get_next_target(dmt, next, &start, &length,
&type, &params);
if(type) {
snprintf(*status, *size, "%lld %lld %s %s\n",
start, length, type, params);
}
} while (next);
r = 1;
out:
dm_task_destroy(dmt);
return r;
}
static int _status(const char *name, const char *uuid, char **status,
uint32_t *size)
{
if (uuid && *uuid && _status_run(NULL, uuid, status, size)
&& *status) {
return 1;
}
if (name && _status_run(name, NULL, status, size)) {
return 1;
}
return 0;
}
static int _rename(struct dev_manager *dm, struct dev_layer *dl, char *newname)
{
int r = 1;
@ -729,6 +783,50 @@ int dev_manager_info(struct dev_manager *dm, struct logical_volume *lv,
return 1;
}
int dev_manager_get_snapshot_use(struct dev_manager *dm,
struct logical_volume *lv, float *percent)
{
char *name, *status, *tmpstr;
uint32_t size = 127;
if(!(status = pool_alloc(dm->mem, sizeof(*status) * size+1))) {
stack;
return 0;
}
/*
* Build a name for the top layer.
*/
if(!(name = _build_name(dm->mem, lv->vg->name, lv->name, NULL))) {
stack;
return 0;
}
/*
* Try and get some info on this device.
*/
log_debug("Getting device status for %s", name);
if(!_status(name, lv->lvid.s, &status, &size)) {
stack;
return 0;
}
/* If the snapshot isn't available, percent will be -1 */
*percent = -1;
/* FIXME: is there a simpler way to do this? */
tmpstr = strstr(status, "snapshot");
if(!tmpstr)
return 0;
tmpstr = strstr(tmpstr, " ");
if(!tmpstr)
return 0;
return sscanf(tmpstr, "%f", percent);
}
static struct dev_layer *_create_dev(struct dev_manager *dm, char *name,
char *dlid)
{

View File

@ -27,6 +27,8 @@ void dev_manager_destroy(struct dev_manager *dm);
*/
int dev_manager_info(struct dev_manager *dm, struct logical_volume *lv,
struct dm_info *info);
int dev_manager_get_snapshot_use(struct dev_manager *dm,
struct logical_volume *lv, float *percent);
int dev_manager_suspend(struct dev_manager *dm, struct logical_volume *lv);
int dev_manager_activate(struct dev_manager *dm, struct logical_volume *lv);
int dev_manager_deactivate(struct dev_manager *dm, struct logical_volume *lv);

View File

@ -224,6 +224,8 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv)
struct stripe_segment *seg;
struct list *lvseg;
struct logical_volume *origin;
float snap_percent;
int snap_active;
if (!id_write_format(&lv->lvid.id[1], uuid, sizeof(uuid))) {
stack;
@ -254,71 +256,34 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv)
log_print("LV snapshot status source of");
list_iterate(slh, snaplist) {
snap = list_item(slh, struct snapshot_list)->snapshot;
snap_active = lv_snapshot_percentage(snap->cow,
&snap_percent);
log_print(" %s%s/%s [%s]",
lv->vg->cmd->dev_dir, lv->vg->name,
snap->cow->name, "active");
snap->cow->name,
(snap_active > 0) ? "active" : "INACTIVE");
}
/* reset so we don't try to use this to display other snapshot
* related information. */
snap = NULL;
snap_active = 0;
}
/* Check to see if this LV is a COW target for a snapshot */
else if ((snap = find_cow(lv)))
else if ((snap = find_cow(lv))) {
snap_active = lv_snapshot_percentage(lv, &snap_percent);
log_print("LV snapshot status %s destination for %s%s/%s",
"active", lv->vg->cmd->dev_dir, lv->vg->name,
(snap_active > 0) ? "active" : "INACTIVE",
lv->vg->cmd->dev_dir, lv->vg->name,
snap->origin->name);
/******* 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 (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 ");
}
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);
}
}
} else {
printf("INACTIVE ");
if (lv->lv_access & LV_SNAPSHOT_ORG)
printf("original\n");
else
printf("snapshot\n");
}
}
***********/
if (inkernel && info.suspended)
log_print("LV Status suspended");
else
log_print("LV Status %savailable",
inkernel ? "" : "NOT ");
!inkernel || (snap && (snap_active < 1))
? "NOT " : "");
/********* FIXME lv_number - not sure that we're going to bother with this
log_print("LV # %u", lv->lv_number + 1);
@ -364,57 +329,32 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv)
seg = list_item(lvseg, struct stripe_segment);
if(seg->stripes > 1) {
log_print("Stripes %u", seg->stripes);
log_print("Stripe size (KByte) %u", seg->stripe_size/2);
log_print("Stripe size (KByte) %u",
seg->stripe_size/2);
}
/* only want the first segment for LVM1 format output */
break;
}
if(snap) {
/*char *s1, *s2;*/
float fused, fsize;
if(snap_percent == -1)
snap_percent=100;
size = display_size(snap->chunk_size / 2, SIZE_SHORT);
log_print("snapshot chunk size %s", size);
dbg_free(size);
size = display_size(lv->size / 2, SIZE_SHORT);
/* s1 = display_size();*/
log_print("Allocated to snapshot %s [%s/%s]", "NA", "NA", size);
dbg_free(size);
/* size = display_size(snap->cow->size / 2, SIZE_SHORT); */
log_print("Allocated to COW-table %s", "NA");
/* dbg_free(size); */
}
/********** 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);
size = display_size(lv->size / 2, SIZE_SHORT);
sscanf(size, "%f", &fsize);
fused = fsize * ( snap_percent / 100 );
log_print("Allocated to snapshot %2.2f%% [%2.2f/%s]",
snap_percent, fused, size);
dbg_free(size);
/* FIXME: Think this'll make them wonder?? */
log_print("Allocated to COW-table %s", "00.01 KB");
}
}
******************/
/** Not in LVM1 format output **
log_print("Segments %u", list_size(&lv->segments));