Avoid depending on comparison of floating-point values. Return 4 values: TARGET_STATUS_ERROR --- error occured TARGET_STATUS_INVALIDATED --- the snapshot is invalidated (there may still exist 100% filled snapshot that is not invalidated) TARGET_STATUS_PROCESSING --- mirror is resynchronizing, snapshot is neither empty nor invalidated. TARGET_STATUS_FINISHED --- finished. For mirrors, it is returned when the mirror resynchronization finished. For snapshots, it is returned when the snapshot contains no exceptions (merging finished). Decisions are made based on these returned values, not on actual floating point number. Signed-off-by: Mikulas Patocka --- lib/activate/dev_manager.c | 54 +++++++++++++++++++++++++-------------------- lib/display/display.c | 16 +++++-------- lib/metadata/mirror.c | 20 ++++++++-------- lib/metadata/segtype.h | 6 +++++ lib/mirror/mirrored.c | 8 +++--- lib/report/report.c | 16 ++++++------- lib/snapshot/snapshot.c | 8 +++++- tools/lvscan.c | 15 +++++------- tools/polldaemon.c | 7 +++-- 9 files changed, 80 insertions(+), 70 deletions(-) Index: LVM2.2.02.39/lib/metadata/segtype.h =================================================================== --- LVM2.2.02.39.orig/lib/metadata/segtype.h 2008-08-04 19:25:00.000000000 +0200 +++ LVM2.2.02.39/lib/metadata/segtype.h 2008-08-04 19:25:00.000000000 +0200 @@ -73,6 +73,12 @@ struct segtype_handler { struct lv_segment *seg, struct dm_tree_node *node, uint64_t len, uint32_t *pvmove_mirror_count); +/* return value of target_percent. The order is important, if multiple targets + return different values, the lowest value wins */ +#define TARGET_STATUS_ERROR 0 +#define TARGET_STATUS_INVALIDATED 1 +#define TARGET_STATUS_PROCESSING 2 +#define TARGET_STATUS_FINISHED 3 int (*target_percent) (void **target_state, struct dm_pool * mem, struct cmd_context *cmd, struct lv_segment *seg, char *params, Index: LVM2.2.02.39/lib/mirror/mirrored.c =================================================================== --- LVM2.2.02.39.orig/lib/mirror/mirrored.c 2008-08-04 19:25:00.000000000 +0200 +++ LVM2.2.02.39/lib/mirror/mirrored.c 2008-08-04 19:25:00.000000000 +0200 @@ -195,7 +195,7 @@ static int _mirrored_target_percent(void if (sscanf(pos, "%u %n", &mirror_count, &used) != 1) { log_error("Failure parsing mirror status mirror count: %s", params); - return 0; + return TARGET_STATUS_ERROR; } pos += used; @@ -203,7 +203,7 @@ static int _mirrored_target_percent(void if (sscanf(pos, "%*x:%*x %n", &used) != 0) { log_error("Failure parsing mirror status devices: %s", params); - return 0; + return TARGET_STATUS_ERROR; } pos += used; } @@ -211,7 +211,7 @@ static int _mirrored_target_percent(void if (sscanf(pos, "%" PRIu64 "/%" PRIu64 "%n", &numerator, &denominator, &used) != 2) { log_error("Failure parsing mirror status fraction: %s", params); - return 0; + return TARGET_STATUS_ERROR; } pos += used; @@ -221,7 +221,7 @@ static int _mirrored_target_percent(void if (seg) seg->extents_copied = seg->area_len * numerator / denominator; - return 1; + return numerator != denominator ? TARGET_STATUS_PROCESSING : TARGET_STATUS_FINISHED; } static int _add_log(struct dev_manager *dm, struct lv_segment *seg, Index: LVM2.2.02.39/lib/snapshot/snapshot.c =================================================================== --- LVM2.2.02.39.orig/lib/snapshot/snapshot.c 2008-08-04 19:25:00.000000000 +0200 +++ LVM2.2.02.39/lib/snapshot/snapshot.c 2008-08-04 19:25:00.000000000 +0200 @@ -103,9 +103,13 @@ static int _snap_target_percent(void **t &numerator, &denominator) == 2) { *total_numerator += numerator; *total_denominator += denominator; + if (!numerator) return TARGET_STATUS_FINISHED; + else return TARGET_STATUS_PROCESSING; + } else if (!strcmp(params, "Invalid")) { + return TARGET_STATUS_INVALIDATED; + } else { + return TARGET_STATUS_ERROR; } - - return 1; } static int _snap_target_present(const struct lv_segment *seg __attribute((unused)), Index: LVM2.2.02.39/lib/activate/dev_manager.c =================================================================== --- LVM2.2.02.39.orig/lib/activate/dev_manager.c 2008-08-04 19:25:00.000000000 +0200 +++ LVM2.2.02.39/lib/activate/dev_manager.c 2008-08-04 19:25:00.000000000 +0200 @@ -326,7 +326,7 @@ static int _percent_run(struct dev_manag struct logical_volume *lv, float *percent, uint32_t *event_nr) { - int r = 0; + int r = TARGET_STATUS_FINISHED; struct dm_task *dmt; struct dm_info info; void *next = NULL; @@ -373,12 +373,16 @@ static int _percent_run(struct dev_manag if (!(segtype = get_segtype_from_string(dm->cmd, type))) continue; - if (segtype->ops->target_percent && - !segtype->ops->target_percent(&dm->target_state, dm->mem, - dm->cmd, seg, params, - &total_numerator, - &total_denominator)) - goto_out; + if (segtype->ops->target_percent) { + int target_status = + segtype->ops->target_percent(&dm->target_state, + dm->mem, dm->cmd, seg, + params, + &total_numerator, + &total_denominator); + if (target_status < r) + r = target_status; + } } while (next); @@ -394,7 +398,6 @@ static int _percent_run(struct dev_manag *percent = 100; log_debug("LV percent: %f", *percent); - r = 1; out: dm_task_destroy(dmt); @@ -406,19 +409,21 @@ static int _percent(struct dev_manager * struct logical_volume *lv, float *percent, uint32_t *event_nr) { + int r; if (dlid && *dlid) { - if (_percent_run(dm, NULL, dlid, target_type, wait, lv, percent, - event_nr)) - return 1; - else if (_percent_run(dm, NULL, dlid + sizeof(UUID_PREFIX) - 1, - target_type, wait, lv, percent, - event_nr)) - return 1; + if ((r = _percent_run(dm, NULL, dlid, target_type, wait, lv, + percent, event_nr))) + return r; + else if ((r = _percent_run(dm, NULL, + dlid + sizeof(UUID_PREFIX) - 1, + target_type, wait, lv, percent, + event_nr))) + return r; } - if (name && _percent_run(dm, name, NULL, target_type, wait, lv, percent, - event_nr)) - return 1; + if (name && ((r = _percent_run(dm, name, NULL, target_type, wait, lv, + percent, event_nr)))) + return r; return 0; } @@ -479,6 +484,7 @@ int dev_manager_snapshot_percent(struct const struct logical_volume *lv, float *percent) { + int r; char *name; const char *dlid; @@ -495,14 +501,13 @@ int dev_manager_snapshot_percent(struct * Try and get some info on this device. */ log_debug("Getting device status percentage for %s", name); - if (!(_percent(dm, name, dlid, "snapshot", 0, NULL, percent, - NULL))) + if (!(r = _percent(dm, name, dlid, "snapshot", 0, NULL, percent, NULL))) return_0; /* FIXME dm_pool_free ? */ /* If the snapshot isn't available, percent will be -1 */ - return 1; + return r; } /* FIXME Merge with snapshot_percent, auto-detecting target type */ @@ -511,6 +516,7 @@ int dev_manager_mirror_percent(struct de struct logical_volume *lv, int wait, float *percent, uint32_t *event_nr) { + int r; char *name; const char *dlid; @@ -528,11 +534,11 @@ int dev_manager_mirror_percent(struct de } log_debug("Getting device mirror status percentage for %s", name); - if (!(_percent(dm, name, dlid, "mirror", wait, lv, percent, - event_nr))) + if (!(r = _percent(dm, name, dlid, "mirror", wait, lv, percent, + event_nr))) return_0; - return 1; + return r; } #if 0 Index: LVM2.2.02.39/lib/display/display.c =================================================================== --- LVM2.2.02.39.orig/lib/display/display.c 2008-08-04 19:23:13.000000000 +0200 +++ LVM2.2.02.39/lib/display/display.c 2008-08-04 19:25:00.000000000 +0200 @@ -427,11 +427,9 @@ int lvdisplay_full(struct cmd_context *c list_iterate_items_gen(snap_seg, &lv->snapshot_segs, origin_list) { - if (inkernel && - (snap_active = lv_snapshot_percent(snap_seg->cow, - &snap_percent))) - if (snap_percent < 0 || snap_percent >= 100) - snap_active = 0; + if (inkernel) + snap_active = lv_snapshot_percent(snap_seg->cow, + &snap_percent) >= TARGET_STATUS_PROCESSING; log_print(" %s%s/%s [%s]", lv->vg->cmd->dev_dir, lv->vg->name, snap_seg->cow->name, @@ -439,11 +437,9 @@ int lvdisplay_full(struct cmd_context *c } snap_seg = NULL; } else if ((snap_seg = find_cow(lv))) { - if (inkernel && - (snap_active = lv_snapshot_percent(snap_seg->cow, - &snap_percent))) - if (snap_percent < 0 || snap_percent >= 100) - snap_active = 0; + if (inkernel) + snap_active = lv_snapshot_percent(snap_seg->cow, + &snap_percent) >= TARGET_STATUS_PROCESSING; log_print("LV snapshot status %s destination for %s%s/%s", (snap_active > 0) ? "active" : "INACTIVE", Index: LVM2.2.02.39/lib/metadata/mirror.c =================================================================== --- LVM2.2.02.39.orig/lib/metadata/mirror.c 2008-08-04 19:23:13.000000000 +0200 +++ LVM2.2.02.39/lib/metadata/mirror.c 2008-08-04 19:25:00.000000000 +0200 @@ -640,18 +640,16 @@ int remove_mirror_images(struct logical_ static int _mirrored_lv_in_sync(struct logical_volume *lv) { + int r; float sync_percent; - if (!lv_mirror_percent(lv->vg->cmd, lv, 0, &sync_percent, NULL)) { + if (!(r = lv_mirror_percent(lv->vg->cmd, lv, 0, &sync_percent, NULL))) { log_error("Unable to determine mirror sync status of %s/%s.", lv->vg->name, lv->name); return 0; } - if (sync_percent >= 100.0) - return 1; - - return 0; + return r == TARGET_STATUS_FINISHED; } /* @@ -1140,6 +1138,7 @@ int remove_mirror_log(struct cmd_context struct list *removable_pvs) { float sync_percent; + int sync_status; struct lvinfo info; struct volume_group *vg = lv->vg; @@ -1151,7 +1150,8 @@ int remove_mirror_log(struct cmd_context /* Had disk log, switch to core. */ if (lv_info(cmd, lv, &info, 0, 0) && info.exists) { - if (!lv_mirror_percent(cmd, lv, 0, &sync_percent, NULL)) { + if (!(sync_status = lv_mirror_percent(cmd, lv, 0, &sync_percent, + NULL))) { log_error("Unable to determine mirror sync status."); return 0; } @@ -1162,11 +1162,11 @@ int remove_mirror_log(struct cmd_context } else if (yes_no_prompt("Full resync required to convert " "inactive mirror %s to core log. " "Proceed? [y/n]: ")) - sync_percent = 0; + sync_status = TARGET_STATUS_PROCESSING; else return 0; - if (sync_percent >= 100.0) + if (sync_status == TARGET_STATUS_FINISHED) init_mirror_in_sync(1); else { /* A full resync will take place */ @@ -1340,8 +1340,8 @@ int add_mirror_log(struct cmd_context *c } /* check sync status */ - if (lv_mirror_percent(cmd, lv, 0, &sync_percent, NULL) && - sync_percent >= 100.0) + if (lv_mirror_percent(cmd, lv, 0, &sync_percent, NULL) + == TARGET_STATUS_FINISHED) in_sync = 1; else in_sync = 0; Index: LVM2.2.02.39/lib/report/report.c =================================================================== --- LVM2.2.02.39.orig/lib/report/report.c 2008-08-04 19:23:13.000000000 +0200 +++ LVM2.2.02.39/lib/report/report.c 2008-08-04 19:25:00.000000000 +0200 @@ -274,19 +274,18 @@ static int _lvkmin_disp(struct dm_report static int _lv_mimage_in_sync(const struct logical_volume *lv) { + int status; float percent; struct lv_segment *mirror_seg = find_mirror_seg(first_seg(lv)); if (!(lv->status & MIRROR_IMAGE) || !mirror_seg) return_0; - if (!lv_mirror_percent(lv->vg->cmd, mirror_seg->lv, 0, &percent, NULL)) + if (!(status = lv_mirror_percent(lv->vg->cmd, mirror_seg->lv, 0, + &percent, NULL))) return_0; - if (percent >= 100.0) - return 1; - - return 0; + return status == TARGET_STATUS_FINISHED; } static int _lvstatus_disp(struct dm_report *rh __attribute((unused)), struct dm_pool *mem, @@ -363,8 +362,8 @@ static int _lvstatus_disp(struct dm_repo /* Snapshot dropped? */ if (info.live_table && lv_is_cow(lv) && - (!lv_snapshot_percent(lv, &snap_percent) || - snap_percent < 0 || snap_percent >= 100)) { + (lv_snapshot_percent(lv, &snap_percent) + <= TARGET_STATUS_INVALIDATED)) { repstr[0] = toupper(repstr[0]); if (info.suspended) repstr[4] = 'S'; /* Susp Inv snapshot */ @@ -961,7 +960,8 @@ static int _snpercent_disp(struct dm_rep return 1; } - if (!lv_snapshot_percent(lv, &snap_percent) || snap_percent < 0) { + if (lv_snapshot_percent(lv, &snap_percent) + < TARGET_STATUS_INVALIDATED) { *sortval = UINT64_C(100); dm_report_field_set_value(field, "100.00", sortval); return 1; Index: LVM2.2.02.39/tools/lvscan.c =================================================================== --- LVM2.2.02.39.orig/tools/lvscan.c 2008-08-04 19:23:13.000000000 +0200 +++ LVM2.2.02.39/tools/lvscan.c 2008-08-04 19:25:00.000000000 +0200 @@ -34,18 +34,15 @@ static int lvscan_single(struct cmd_cont if (lv_is_origin(lv)) { list_iterate_items_gen(snap_seg, &lv->snapshot_segs, origin_list) { - if (inkernel && - (snap_active = lv_snapshot_percent(snap_seg->cow, - &snap_percent))) - if (snap_percent < 0 || snap_percent >= 100) - snap_active = 0; + if (inkernel) + snap_active = lv_snapshot_percent(snap_seg->cow, + &snap_percent) >= TARGET_STATUS_PROCESSING; } snap_seg = NULL; } else if (lv_is_cow(lv)) { - if (inkernel && - (snap_active = lv_snapshot_percent(lv, &snap_percent))) - if (snap_percent < 0 || snap_percent >= 100) - snap_active = 0; + if (inkernel) + snap_active = lv_snapshot_percent(lv, &snap_percent) + >= TARGET_STATUS_PROCESSING; } /* FIXME Add -D arg to skip this! */ Index: LVM2.2.02.39/tools/polldaemon.c =================================================================== --- LVM2.2.02.39.orig/tools/polldaemon.c 2008-08-04 19:34:13.000000000 +0200 +++ LVM2.2.02.39/tools/polldaemon.c 2008-08-04 19:36:34.000000000 +0200 @@ -70,6 +70,7 @@ static int _check_mirror_status(struct c { struct list *lvs_changed; float segment_percent = 0.0, overall_percent = 0.0; + int status; uint32_t event_nr = 0; /* By default, caller should not retry */ @@ -85,8 +86,8 @@ static int _check_mirror_status(struct c return 0; } - if (!lv_mirror_percent(cmd, lv_mirr, !parms->interval, &segment_percent, - &event_nr)) { + if (!(status = lv_mirror_percent(cmd, lv_mirr, !parms->interval, + &segment_percent, &event_nr))) { log_error("ABORTING: Mirror percentage check failed."); return 0; } @@ -99,7 +100,7 @@ static int _check_mirror_status(struct c log_verbose("%s: %s: %.1f%%", name, parms->progress_title, overall_percent); - if (segment_percent < 100.0) { + if (status < TARGET_STATUS_FINISHED) { /* The only case the caller *should* try again later */ *finished = 0; return 1;