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

Introduce percent_range_t and centralise snapshot full/mirror in-sync checks.

This commit is contained in:
Alasdair Kergon 2009-10-01 00:35:29 +00:00
parent 4b12fa1377
commit 78ad1549a5
14 changed files with 154 additions and 62 deletions

View File

@ -1,5 +1,6 @@
Version 2.02.54 - Version 2.02.54 -
===================================== =====================================
Introduce percent_range_t and centralise snapshot full/mirror in-sync checks.
Factor out poll_mirror_progress and introduce progress_t. Factor out poll_mirror_progress and introduce progress_t.
Distinguish between powers of 1000 and powers of 1024 in unit suffixes. Distinguish between powers of 1000 and powers of 1024 in unit suffixes.
Restart lvconverts in vgchange by sharing lv_spawn_background_polling. Restart lvconverts in vgchange by sharing lv_spawn_background_polling.

View File

@ -156,12 +156,14 @@ int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
{ {
return 0; return 0;
} }
int lv_snapshot_percent(const struct logical_volume *lv, float *percent) int lv_snapshot_percent(const struct logical_volume *lv, float *percent,
percent_range_t *percent_range)
{ {
return 0; return 0;
} }
int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv, int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv,
int wait, float *percent, uint32_t *event_nr) int wait, float *percent, percent_range_t *percent_range,
uint32_t *event_nr)
{ {
return 0; return 0;
} }
@ -495,7 +497,8 @@ int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
/* /*
* Returns 1 if percent set, else 0 on failure. * Returns 1 if percent set, else 0 on failure.
*/ */
int lv_snapshot_percent(const struct logical_volume *lv, float *percent) int lv_snapshot_percent(const struct logical_volume *lv, float *percent,
percent_range_t *percent_range)
{ {
int r; int r;
struct dev_manager *dm; struct dev_manager *dm;
@ -506,7 +509,7 @@ int lv_snapshot_percent(const struct logical_volume *lv, float *percent)
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name)))
return_0; return_0;
if (!(r = dev_manager_snapshot_percent(dm, lv, percent))) if (!(r = dev_manager_snapshot_percent(dm, lv, percent, percent_range)))
stack; stack;
dev_manager_destroy(dm); dev_manager_destroy(dm);
@ -516,7 +519,8 @@ int lv_snapshot_percent(const struct logical_volume *lv, float *percent)
/* FIXME Merge with snapshot_percent */ /* FIXME Merge with snapshot_percent */
int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv, int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv,
int wait, float *percent, uint32_t *event_nr) int wait, float *percent, percent_range_t *percent_range,
uint32_t *event_nr)
{ {
int r; int r;
struct dev_manager *dm; struct dev_manager *dm;
@ -541,7 +545,8 @@ int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv,
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name)))
return_0; return_0;
if (!(r = dev_manager_mirror_percent(dm, lv, wait, percent, event_nr))) if (!(r = dev_manager_mirror_percent(dm, lv, wait, percent,
percent_range, event_nr)))
stack; stack;
dev_manager_destroy(dm); dev_manager_destroy(dm);

View File

@ -81,9 +81,11 @@ int lv_activation_filter(struct cmd_context *cmd, const char *lvid_s,
/* /*
* Returns 1 if percent has been set, else 0. * Returns 1 if percent has been set, else 0.
*/ */
int lv_snapshot_percent(const struct logical_volume *lv, float *percent); int lv_snapshot_percent(const struct logical_volume *lv, float *percent,
percent_range_t *percent_range);
int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv, int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv,
int wait, float *percent, uint32_t *event_nr); int wait, float *percent, percent_range_t *percent_range,
uint32_t *event_nr);
/* /*
* Return number of LVs in the VG that are active. * Return number of LVs in the VG that are active.

View File

@ -327,10 +327,26 @@ static int _status(const char *name, const char *uuid,
return 0; return 0;
} }
static percent_range_t _combine_percent_ranges(percent_range_t a,
percent_range_t b)
{
if (a == PERCENT_INVALID || b == PERCENT_INVALID)
return PERCENT_INVALID;
if (a == PERCENT_100 && b == PERCENT_100)
return PERCENT_100;
if (a == PERCENT_0 && b == PERCENT_0)
return PERCENT_0;
return PERCENT_0_TO_100;
}
static int _percent_run(struct dev_manager *dm, const char *name, static int _percent_run(struct dev_manager *dm, const char *name,
const char *dlid, const char *dlid,
const char *target_type, int wait, const char *target_type, int wait,
struct logical_volume *lv, float *percent, struct logical_volume *lv, float *percent,
percent_range_t *overall_percent_range,
uint32_t *event_nr) uint32_t *event_nr)
{ {
int r = 0; int r = 0;
@ -343,10 +359,13 @@ static int _percent_run(struct dev_manager *dm, const char *name,
struct dm_list *segh = &lv->segments; struct dm_list *segh = &lv->segments;
struct lv_segment *seg = NULL; struct lv_segment *seg = NULL;
struct segment_type *segtype; struct segment_type *segtype;
percent_range_t percent_range, combined_percent_range;
int first_time = 1;
uint64_t total_numerator = 0, total_denominator = 0; uint64_t total_numerator = 0, total_denominator = 0;
*percent = -1; *percent = -1;
*overall_percent_range = PERCENT_INVALID;
if (!(dmt = _setup_task(name, dlid, event_nr, if (!(dmt = _setup_task(name, dlid, event_nr,
wait ? DM_DEVICE_WAITEVENT : DM_DEVICE_STATUS, 0, 0))) wait ? DM_DEVICE_WAITEVENT : DM_DEVICE_STATUS, 0, 0)))
@ -383,12 +402,20 @@ static int _percent_run(struct dev_manager *dm, const char *name,
continue; continue;
if (segtype->ops->target_percent && if (segtype->ops->target_percent &&
!segtype->ops->target_percent(&dm->target_state, dm->mem, !segtype->ops->target_percent(&dm->target_state,
&percent_range, dm->mem,
dm->cmd, seg, params, dm->cmd, seg, params,
&total_numerator, &total_numerator,
&total_denominator)) &total_denominator))
goto_out; goto_out;
if (first_time) {
combined_percent_range = percent_range;
first_time = 0;
} else
combined_percent_range =
_combine_percent_ranges(combined_percent_range,
percent_range);
} while (next); } while (next);
if (lv && (segh = dm_list_next(&lv->segments, segh))) { if (lv && (segh = dm_list_next(&lv->segments, segh))) {
@ -397,10 +424,16 @@ static int _percent_run(struct dev_manager *dm, const char *name,
goto out; goto out;
} }
if (total_denominator) if (total_denominator) {
*percent = (float) total_numerator *100 / total_denominator; *percent = (float) total_numerator *100 / total_denominator;
else *overall_percent_range = combined_percent_range;
} else {
*percent = 100; *percent = 100;
if (first_time)
*overall_percent_range = PERCENT_100;
else
*overall_percent_range = combined_percent_range;
}
log_debug("LV percent: %f", *percent); log_debug("LV percent: %f", *percent);
r = 1; r = 1;
@ -413,20 +446,20 @@ static int _percent_run(struct dev_manager *dm, const char *name,
static int _percent(struct dev_manager *dm, const char *name, const char *dlid, static int _percent(struct dev_manager *dm, const char *name, const char *dlid,
const char *target_type, int wait, const char *target_type, int wait,
struct logical_volume *lv, float *percent, struct logical_volume *lv, float *percent,
uint32_t *event_nr) percent_range_t *overall_percent_range, uint32_t *event_nr)
{ {
if (dlid && *dlid) { if (dlid && *dlid) {
if (_percent_run(dm, NULL, dlid, target_type, wait, lv, percent, if (_percent_run(dm, NULL, dlid, target_type, wait, lv, percent,
event_nr)) overall_percent_range, event_nr))
return 1; return 1;
else if (_percent_run(dm, NULL, dlid + sizeof(UUID_PREFIX) - 1, else if (_percent_run(dm, NULL, dlid + sizeof(UUID_PREFIX) - 1,
target_type, wait, lv, percent, target_type, wait, lv, percent,
event_nr)) overall_percent_range, event_nr))
return 1; return 1;
} }
if (name && _percent_run(dm, name, NULL, target_type, wait, lv, percent, if (name && _percent_run(dm, name, NULL, target_type, wait, lv, percent,
event_nr)) overall_percent_range, event_nr))
return 1; return 1;
return 0; return 0;
@ -481,7 +514,7 @@ void dev_manager_exit(void)
int dev_manager_snapshot_percent(struct dev_manager *dm, int dev_manager_snapshot_percent(struct dev_manager *dm,
const struct logical_volume *lv, const struct logical_volume *lv,
float *percent) float *percent, percent_range_t *percent_range)
{ {
char *name; char *name;
const char *dlid; const char *dlid;
@ -500,7 +533,7 @@ int dev_manager_snapshot_percent(struct dev_manager *dm,
*/ */
log_debug("Getting device status percentage for %s", name); log_debug("Getting device status percentage for %s", name);
if (!(_percent(dm, name, dlid, "snapshot", 0, NULL, percent, if (!(_percent(dm, name, dlid, "snapshot", 0, NULL, percent,
NULL))) percent_range, NULL)))
return_0; return_0;
/* FIXME dm_pool_free ? */ /* FIXME dm_pool_free ? */
@ -513,7 +546,8 @@ int dev_manager_snapshot_percent(struct dev_manager *dm,
/* FIXME Cope with more than one target */ /* FIXME Cope with more than one target */
int dev_manager_mirror_percent(struct dev_manager *dm, int dev_manager_mirror_percent(struct dev_manager *dm,
struct logical_volume *lv, int wait, struct logical_volume *lv, int wait,
float *percent, uint32_t *event_nr) float *percent, percent_range_t *percent_range,
uint32_t *event_nr)
{ {
char *name; char *name;
const char *dlid; const char *dlid;
@ -533,7 +567,7 @@ int dev_manager_mirror_percent(struct dev_manager *dm,
log_debug("Getting device mirror status percentage for %s", name); log_debug("Getting device mirror status percentage for %s", name);
if (!(_percent(dm, name, dlid, "mirror", wait, lv, percent, if (!(_percent(dm, name, dlid, "mirror", wait, lv, percent,
event_nr))) percent_range, event_nr)))
return_0; return_0;
return 1; return 1;

View File

@ -16,6 +16,8 @@
#ifndef _LVM_DEV_MANAGER_H #ifndef _LVM_DEV_MANAGER_H
#define _LVM_DEV_MANAGER_H #define _LVM_DEV_MANAGER_H
#include "metadata-exported.h"
struct logical_volume; struct logical_volume;
struct volume_group; struct volume_group;
struct cmd_context; struct cmd_context;
@ -44,10 +46,12 @@ int dev_manager_info(struct dm_pool *mem, const char *name,
struct dm_info *info, uint32_t *read_ahead); struct dm_info *info, uint32_t *read_ahead);
int dev_manager_snapshot_percent(struct dev_manager *dm, int dev_manager_snapshot_percent(struct dev_manager *dm,
const struct logical_volume *lv, const struct logical_volume *lv,
float *percent); float *percent,
percent_range_t *percent_range);
int dev_manager_mirror_percent(struct dev_manager *dm, int dev_manager_mirror_percent(struct dev_manager *dm,
struct logical_volume *lv, int wait, struct logical_volume *lv, int wait,
float *percent, uint32_t *event_nr); float *percent, percent_range_t *percent_range,
uint32_t *event_nr);
int dev_manager_suspend(struct dev_manager *dm, struct logical_volume *lv, int dev_manager_suspend(struct dev_manager *dm, struct logical_volume *lv,
int lockfs, int flush_required); int lockfs, int flush_required);
int dev_manager_activate(struct dev_manager *dm, struct logical_volume *lv); int dev_manager_activate(struct dev_manager *dm, struct logical_volume *lv);

View File

@ -482,6 +482,7 @@ int lvdisplay_full(struct cmd_context *cmd,
char uuid[64] __attribute((aligned(8))); char uuid[64] __attribute((aligned(8)));
struct lv_segment *snap_seg = NULL; struct lv_segment *snap_seg = NULL;
float snap_percent; /* fused, fsize; */ float snap_percent; /* fused, fsize; */
percent_range_t percent_range;
if (!id_write_format(&lv->lvid.id[1], uuid, sizeof(uuid))) if (!id_write_format(&lv->lvid.id[1], uuid, sizeof(uuid)))
return_0; return_0;
@ -506,24 +507,26 @@ int lvdisplay_full(struct cmd_context *cmd,
origin_list) { origin_list) {
if (inkernel && if (inkernel &&
(snap_active = lv_snapshot_percent(snap_seg->cow, (snap_active = lv_snapshot_percent(snap_seg->cow,
&snap_percent))) &snap_percent,
if (snap_percent < 0 || snap_percent >= 100) &percent_range)))
if (percent_range == PERCENT_INVALID)
snap_active = 0; snap_active = 0;
log_print(" %s%s/%s [%s]", log_print(" %s%s/%s [%s]",
lv->vg->cmd->dev_dir, lv->vg->name, lv->vg->cmd->dev_dir, lv->vg->name,
snap_seg->cow->name, snap_seg->cow->name,
(snap_active > 0) ? "active" : "INACTIVE"); snap_active ? "active" : "INACTIVE");
} }
snap_seg = NULL; snap_seg = NULL;
} else if ((snap_seg = find_cow(lv))) { } else if ((snap_seg = find_cow(lv))) {
if (inkernel && if (inkernel &&
(snap_active = lv_snapshot_percent(snap_seg->cow, (snap_active = lv_snapshot_percent(snap_seg->cow,
&snap_percent))) &snap_percent,
if (snap_percent < 0 || snap_percent >= 100) &percent_range)))
if (percent_range == PERCENT_INVALID)
snap_active = 0; snap_active = 0;
log_print("LV snapshot status %s destination for %s%s/%s", log_print("LV snapshot status %s destination for %s%s/%s",
(snap_active > 0) ? "active" : "INACTIVE", snap_active ? "active" : "INACTIVE",
lv->vg->cmd->dev_dir, lv->vg->name, lv->vg->cmd->dev_dir, lv->vg->name,
snap_seg->origin->name); snap_seg->origin->name);
} }

View File

@ -136,6 +136,13 @@ typedef enum {
DONT_PROMPT_OVERRIDE = 2 /* Skip prompt + override a second condition */ DONT_PROMPT_OVERRIDE = 2 /* Skip prompt + override a second condition */
} force_t; } force_t;
typedef enum {
PERCENT_0 = 0,
PERCENT_0_TO_100 = 1,
PERCENT_100 = 2,
PERCENT_INVALID = 3
} percent_range_t;
struct cmd_context; struct cmd_context;
struct format_handler; struct format_handler;
struct labeller; struct labeller;

View File

@ -701,17 +701,16 @@ int remove_mirror_images(struct logical_volume *lv, uint32_t num_mirrors,
static int _mirrored_lv_in_sync(struct logical_volume *lv) static int _mirrored_lv_in_sync(struct logical_volume *lv)
{ {
float sync_percent; float sync_percent;
percent_range_t percent_range;
if (!lv_mirror_percent(lv->vg->cmd, lv, 0, &sync_percent, NULL)) { if (!lv_mirror_percent(lv->vg->cmd, lv, 0, &sync_percent,
&percent_range, NULL)) {
log_error("Unable to determine mirror sync status of %s/%s.", log_error("Unable to determine mirror sync status of %s/%s.",
lv->vg->name, lv->name); lv->vg->name, lv->name);
return 0; return 0;
} }
if (sync_percent >= 100.0) return (percent_range == PERCENT_100) ? 1 : 0;
return 1;
return 0;
} }
/* /*
@ -1203,6 +1202,7 @@ int remove_mirror_log(struct cmd_context *cmd,
struct dm_list *removable_pvs) struct dm_list *removable_pvs)
{ {
float sync_percent; float sync_percent;
percent_range_t percent_range = PERCENT_0;
struct lvinfo info; struct lvinfo info;
struct volume_group *vg = lv->vg; struct volume_group *vg = lv->vg;
@ -1214,7 +1214,8 @@ int remove_mirror_log(struct cmd_context *cmd,
/* Had disk log, switch to core. */ /* Had disk log, switch to core. */
if (lv_info(cmd, lv, &info, 0, 0) && info.exists) { if (lv_info(cmd, lv, &info, 0, 0) && info.exists) {
if (!lv_mirror_percent(cmd, lv, 0, &sync_percent, NULL)) { if (!lv_mirror_percent(cmd, lv, 0, &sync_percent,
&percent_range, NULL)) {
log_error("Unable to determine mirror sync status."); log_error("Unable to determine mirror sync status.");
return 0; return 0;
} }
@ -1229,7 +1230,7 @@ int remove_mirror_log(struct cmd_context *cmd,
else else
return 0; return 0;
if (sync_percent >= 100.0) if (percent_range == PERCENT_100)
init_mirror_in_sync(1); init_mirror_in_sync(1);
else { else {
/* A full resync will take place */ /* A full resync will take place */
@ -1353,6 +1354,7 @@ int add_mirror_log(struct cmd_context *cmd, struct logical_volume *lv,
const struct segment_type *segtype; const struct segment_type *segtype;
struct dm_list *parallel_areas; struct dm_list *parallel_areas;
float sync_percent; float sync_percent;
percent_range_t percent_range;
int in_sync; int in_sync;
struct logical_volume *log_lv; struct logical_volume *log_lv;
struct lvinfo info; struct lvinfo info;
@ -1404,8 +1406,9 @@ int add_mirror_log(struct cmd_context *cmd, struct logical_volume *lv,
} }
/* check sync status */ /* check sync status */
if (lv_mirror_percent(cmd, lv, 0, &sync_percent, NULL) && if (lv_mirror_percent(cmd, lv, 0, &sync_percent, &percent_range,
sync_percent >= 100.0) NULL) &&
(percent_range == PERCENT_100))
in_sync = 1; in_sync = 1;
else else
in_sync = 0; in_sync = 0;

View File

@ -16,6 +16,8 @@
#ifndef _SEGTYPES_H #ifndef _SEGTYPES_H
#define _SEGTYPES_H #define _SEGTYPES_H
#include "metadata-exported.h"
struct segtype_handler; struct segtype_handler;
struct cmd_context; struct cmd_context;
struct config_tree; struct config_tree;
@ -73,7 +75,9 @@ struct segtype_handler {
struct lv_segment *seg, struct lv_segment *seg,
struct dm_tree_node *node, uint64_t len, struct dm_tree_node *node, uint64_t len,
uint32_t *pvmove_mirror_count); uint32_t *pvmove_mirror_count);
int (*target_percent) (void **target_state, struct dm_pool * mem, int (*target_percent) (void **target_state,
percent_range_t *percent_range,
struct dm_pool * mem,
struct cmd_context *cmd, struct cmd_context *cmd,
struct lv_segment *seg, char *params, struct lv_segment *seg, char *params,
uint64_t *total_numerator, uint64_t *total_numerator,

View File

@ -178,10 +178,13 @@ static struct mirror_state *_mirrored_init_target(struct dm_pool *mem,
return mirr_state; return mirr_state;
} }
static int _mirrored_target_percent(void **target_state, struct dm_pool *mem, static int _mirrored_target_percent(void **target_state,
struct cmd_context *cmd, struct lv_segment *seg, percent_range_t *percent_range,
char *params, uint64_t *total_numerator, struct dm_pool *mem,
uint64_t *total_denominator) struct cmd_context *cmd,
struct lv_segment *seg, char *params,
uint64_t *total_numerator,
uint64_t *total_denominator)
{ {
struct mirror_state *mirr_state; struct mirror_state *mirr_state;
uint64_t numerator, denominator; uint64_t numerator, denominator;
@ -226,6 +229,13 @@ static int _mirrored_target_percent(void **target_state, struct dm_pool *mem,
if (seg) if (seg)
seg->extents_copied = seg->area_len * numerator / denominator; seg->extents_copied = seg->area_len * numerator / denominator;
if (numerator == denominator)
*percent_range = PERCENT_100;
else if (numerator == 0)
*percent_range = PERCENT_0;
else
*percent_range = PERCENT_0_TO_100;
return 1; return 1;
} }

View File

@ -275,18 +275,17 @@ static int _lvkmin_disp(struct dm_report *rh, struct dm_pool *mem __attribute((u
static int _lv_mimage_in_sync(const struct logical_volume *lv) static int _lv_mimage_in_sync(const struct logical_volume *lv)
{ {
float percent; float percent;
percent_range_t percent_range;
struct lv_segment *mirror_seg = find_mirror_seg(first_seg(lv)); struct lv_segment *mirror_seg = find_mirror_seg(first_seg(lv));
if (!(lv->status & MIRROR_IMAGE) || !mirror_seg) if (!(lv->status & MIRROR_IMAGE) || !mirror_seg)
return_0; return_0;
if (!lv_mirror_percent(lv->vg->cmd, mirror_seg->lv, 0, &percent, NULL)) if (!lv_mirror_percent(lv->vg->cmd, mirror_seg->lv, 0, &percent,
&percent_range, NULL))
return_0; return_0;
if (percent >= 100.0) return (percent_range == PERCENT_100) ? 1 : 0;
return 1;
return 0;
} }
static int _lvstatus_disp(struct dm_report *rh __attribute((unused)), struct dm_pool *mem, static int _lvstatus_disp(struct dm_report *rh __attribute((unused)), struct dm_pool *mem,
@ -297,6 +296,7 @@ static int _lvstatus_disp(struct dm_report *rh __attribute((unused)), struct dm_
struct lvinfo info; struct lvinfo info;
char *repstr; char *repstr;
float snap_percent; float snap_percent;
percent_range_t percent_range;
if (!(repstr = dm_pool_zalloc(mem, 7))) { if (!(repstr = dm_pool_zalloc(mem, 7))) {
log_error("dm_pool_alloc failed"); log_error("dm_pool_alloc failed");
@ -363,8 +363,8 @@ static int _lvstatus_disp(struct dm_report *rh __attribute((unused)), struct dm_
/* Snapshot dropped? */ /* Snapshot dropped? */
if (info.live_table && lv_is_cow(lv) && if (info.live_table && lv_is_cow(lv) &&
(!lv_snapshot_percent(lv, &snap_percent) || (!lv_snapshot_percent(lv, &snap_percent, &percent_range) ||
snap_percent < 0 || snap_percent >= 100)) { percent_range == PERCENT_INVALID)) {
repstr[0] = toupper(repstr[0]); repstr[0] = toupper(repstr[0]);
if (info.suspended) if (info.suspended)
repstr[4] = 'S'; /* Susp Inv snapshot */ repstr[4] = 'S'; /* Susp Inv snapshot */
@ -1009,6 +1009,7 @@ static int _snpercent_disp(struct dm_report *rh __attribute((unused)), struct dm
const struct logical_volume *lv = (const struct logical_volume *) data; const struct logical_volume *lv = (const struct logical_volume *) data;
struct lvinfo info; struct lvinfo info;
float snap_percent; float snap_percent;
percent_range_t percent_range;
uint64_t *sortval; uint64_t *sortval;
char *repstr; char *repstr;
@ -1030,7 +1031,8 @@ static int _snpercent_disp(struct dm_report *rh __attribute((unused)), struct dm
return 1; return 1;
} }
if (!lv_snapshot_percent(lv, &snap_percent) || snap_percent < 0) { if (!lv_snapshot_percent(lv, &snap_percent, &percent_range) ||
(percent_range == PERCENT_INVALID)) {
*sortval = UINT64_C(100); *sortval = UINT64_C(100);
dm_report_field_set_value(field, "100.00", sortval); dm_report_field_set_value(field, "100.00", sortval);
return 1; return 1;
@ -1058,6 +1060,7 @@ static int _copypercent_disp(struct dm_report *rh __attribute((unused)), struct
{ {
struct logical_volume *lv = (struct logical_volume *) data; struct logical_volume *lv = (struct logical_volume *) data;
float percent; float percent;
percent_range_t percent_range;
uint64_t *sortval; uint64_t *sortval;
char *repstr; char *repstr;
@ -1067,7 +1070,8 @@ static int _copypercent_disp(struct dm_report *rh __attribute((unused)), struct
} }
if ((!(lv->status & PVMOVE) && !(lv->status & MIRRORED)) || if ((!(lv->status & PVMOVE) && !(lv->status & MIRRORED)) ||
!lv_mirror_percent(lv->vg->cmd, lv, 0, &percent, NULL)) { !lv_mirror_percent(lv->vg->cmd, lv, 0, &percent, &percent_range,
NULL) || (percent_range == PERCENT_INVALID)) {
*sortval = UINT64_C(0); *sortval = UINT64_C(0);
dm_report_field_set_value(field, "", sortval); dm_report_field_set_value(field, "", sortval);
return 1; return 1;

View File

@ -88,11 +88,12 @@ static int _snap_text_export(const struct lv_segment *seg, struct formatter *f)
#ifdef DEVMAPPER_SUPPORT #ifdef DEVMAPPER_SUPPORT
static int _snap_target_percent(void **target_state __attribute((unused)), static int _snap_target_percent(void **target_state __attribute((unused)),
struct dm_pool *mem __attribute((unused)), percent_range_t *percent_range,
struct cmd_context *cmd __attribute((unused)), struct dm_pool *mem __attribute((unused)),
struct lv_segment *seg __attribute((unused)), struct cmd_context *cmd __attribute((unused)),
char *params, uint64_t *total_numerator, struct lv_segment *seg __attribute((unused)),
uint64_t *total_denominator) char *params, uint64_t *total_numerator,
uint64_t *total_denominator)
{ {
uint64_t numerator, denominator; uint64_t numerator, denominator;
@ -100,7 +101,16 @@ static int _snap_target_percent(void **target_state __attribute((unused)),
&numerator, &denominator) == 2) { &numerator, &denominator) == 2) {
*total_numerator += numerator; *total_numerator += numerator;
*total_denominator += denominator; *total_denominator += denominator;
} if (!numerator)
*percent_range = PERCENT_0;
else if (numerator == denominator)
*percent_range = PERCENT_100;
else
*percent_range = PERCENT_0_TO_100;
} else if (!strcmp(params, "Invalid"))
*percent_range = PERCENT_INVALID;
else
return 0;
return 1; return 1;
} }

View File

@ -24,6 +24,7 @@ static int lvscan_single(struct cmd_context *cmd, struct logical_volume *lv,
int inkernel, snap_active = 1; int inkernel, snap_active = 1;
struct lv_segment *snap_seg = NULL; struct lv_segment *snap_seg = NULL;
float snap_percent; /* fused, fsize; */ float snap_percent; /* fused, fsize; */
percent_range_t percent_range;
const char *active_str, *snapshot_str; const char *active_str, *snapshot_str;
@ -36,15 +37,17 @@ static int lvscan_single(struct cmd_context *cmd, struct logical_volume *lv,
origin_list) { origin_list) {
if (inkernel && if (inkernel &&
(snap_active = lv_snapshot_percent(snap_seg->cow, (snap_active = lv_snapshot_percent(snap_seg->cow,
&snap_percent))) &snap_percent,
if (snap_percent < 0 || snap_percent >= 100) &percent_range)))
if (percent_range == PERCENT_INVALID)
snap_active = 0; snap_active = 0;
} }
snap_seg = NULL; snap_seg = NULL;
} else if (lv_is_cow(lv)) { } else if (lv_is_cow(lv)) {
if (inkernel && if (inkernel &&
(snap_active = lv_snapshot_percent(lv, &snap_percent))) (snap_active = lv_snapshot_percent(lv, &snap_percent,
if (snap_percent < 0 || snap_percent >= 100) &percent_range)))
if (percent_range == PERCENT_INVALID)
snap_active = 0; snap_active = 0;
} }

View File

@ -68,10 +68,12 @@ progress_t poll_mirror_progress(struct cmd_context *cmd,
struct daemon_parms *parms) struct daemon_parms *parms)
{ {
float segment_percent = 0.0, overall_percent = 0.0; float segment_percent = 0.0, overall_percent = 0.0;
percent_range_t percent_range;
uint32_t event_nr = 0; uint32_t event_nr = 0;
if (!lv_mirror_percent(cmd, lv, !parms->interval, &segment_percent, if (!lv_mirror_percent(cmd, lv, !parms->interval, &segment_percent,
&event_nr)) { &percent_range, &event_nr) ||
(percent_range == PERCENT_INVALID)) {
log_error("ABORTING: Mirror percentage check failed."); log_error("ABORTING: Mirror percentage check failed.");
return PROGRESS_CHECK_FAILED; return PROGRESS_CHECK_FAILED;
} }
@ -84,7 +86,7 @@ progress_t poll_mirror_progress(struct cmd_context *cmd,
log_verbose("%s: %s: %.1f%%", name, parms->progress_title, log_verbose("%s: %s: %.1f%%", name, parms->progress_title,
overall_percent); overall_percent);
if (segment_percent < 100.0) if (percent_range != PERCENT_100)
return PROGRESS_UNFINISHED; return PROGRESS_UNFINISHED;
if (overall_percent >= 100.0) if (overall_percent >= 100.0)