From 542d0c4bff23cb46eb156e25f995c563334e8ba2 Mon Sep 17 00:00:00 2001 From: Ondrej Kozina <okozina@redhat.com> Date: Wed, 9 Mar 2016 18:02:30 +0100 Subject: [PATCH] lvmpolld: reinstate internal progress info tracking --- daemons/lvmpolld/lvmpolld-core.c | 62 +++++++++++++++++++++++++- daemons/lvmpolld/lvmpolld-data-utils.c | 13 +++++- daemons/lvmpolld/lvmpolld-data-utils.h | 11 +++-- 3 files changed, 80 insertions(+), 6 deletions(-) diff --git a/daemons/lvmpolld/lvmpolld-core.c b/daemons/lvmpolld/lvmpolld-core.c index fd7327241..c6f02a4de 100644 --- a/daemons/lvmpolld/lvmpolld-core.c +++ b/daemons/lvmpolld/lvmpolld-core.c @@ -203,6 +203,60 @@ static int read_single_line(struct lvmpolld_thread_data *data, int err) return (r > 0); } +static const char *keyword(const enum poll_type type) +{ + switch (type) { + case PVMOVE: + return "Moved"; + case CONVERT: + return "Converted"; + case MERGE: /* fall through */ + case MERGE_THIN: + return "Merged"; + default: + return NULL; + } +} + +static void parse_percents(struct lvmpolld_lv *pdlv, const char *line) +{ + char *endptr, *keyw, *nr; + dm_percent_t perc; + double d; + + if (!(keyw = strstr(line, keyword(pdlv->type))) || keyw == line + || !strchr(keyw, DM_PERCENT_CHAR)) { + DEBUGLOG(pdlv->ls, "%s: %s", PD_LOG_PREFIX, + "parsing percentage from lvm2 command failed"); + return; + } + + nr = strpbrk(keyw, "+-0123456789"); + if (!nr) { + DEBUGLOG(pdlv->ls, "%s: %s", PD_LOG_PREFIX, + "parsing percentage from lvm2 command failed"); + return; + } + + d = strtod(nr, &endptr); + if (nr == endptr) { + DEBUGLOG(pdlv->ls, "%s: %s", PD_LOG_PREFIX, + "parsing percentage from lvm2 command failed"); + return; + } else if (d > 100.0) { + WARN(pdlv->ls, "%s: %s", PD_LOG_PREFIX, + "parsing percentage from lvm2 command returned invalid value"); + return; + } + + perc = dm_make_percent((uint64_t)(d * DM_PERCENT_1), DM_PERCENT_100); + + DEBUGLOG(pdlv->ls, "%s: %s %.1f%%", PD_LOG_PREFIX, + "parsed", dm_percent_to_float(perc)); + + pdlv_set_percents(pdlv, perc); +} + static void update_idle_state(struct lvmpolld_state *ls) { if (!ls->idle) @@ -274,6 +328,9 @@ static int poll_for_output(struct lvmpolld_lv *pdlv, struct lvmpolld_thread_data assert(read_single_line(data, 0)); /* may block indef. anyway */ INFO(pdlv->ls, "%s: PID %d: %s: '%s'", LVM2_LOG_PREFIX, pdlv->cmd_pid, "STDOUT", data->line); + + if (pdlv->parse_output_fn) + pdlv->parse_output_fn(pdlv, data->line); } else if (fds[0].revents) { if (fds[0].revents & POLLHUP) DEBUGLOG(pdlv->ls, "%s: %s", PD_LOG_PREFIX, "caught POLLHUP"); @@ -329,6 +386,8 @@ static int poll_for_output(struct lvmpolld_lv *pdlv, struct lvmpolld_thread_data while (read_single_line(data, 0)) { assert(r > 0); INFO(pdlv->ls, "%s: PID %d: %s: %s", LVM2_LOG_PREFIX, pdlv->cmd_pid, "STDOUT", data->line); + if (pdlv->parse_output_fn) + pdlv->parse_output_fn(pdlv, data->line); } if (fds[1].fd >= 0) while (read_single_line(data, 1)) { @@ -562,7 +621,8 @@ static struct lvmpolld_lv *construct_pdlv(request req, struct lvmpolld_state *ls unsigned handle_missing_pvs = daemon_request_int(req, LVMPD_PARM_HANDLE_MISSING_PVS, 0); pdlv = pdlv_create(ls, id, vgname, lvname, sysdir, type, - interval, uinterval, pdst); + interval, uinterval, pdst, + abort_polling ? NULL : parse_percents); if (!pdlv) { ERROR(ls, "%s: %s", PD_LOG_PREFIX, "failed to create internal LV data structure."); diff --git a/daemons/lvmpolld/lvmpolld-data-utils.c b/daemons/lvmpolld/lvmpolld-data-utils.c index 99883f816..b141f0ace 100644 --- a/daemons/lvmpolld/lvmpolld-data-utils.c +++ b/daemons/lvmpolld/lvmpolld-data-utils.c @@ -91,7 +91,8 @@ struct lvmpolld_lv *pdlv_create(struct lvmpolld_state *ls, const char *id, const char *vgname, const char *lvname, const char *sysdir, enum poll_type type, const char *sinterval, unsigned pdtimeout, - struct lvmpolld_store *pdst) + struct lvmpolld_store *pdst, + lvmpolld_parse_output_fn_t parse_fn) { char *lvmpolld_id = dm_strdup(id), /* copy */ *full_lvname = _construct_full_lvname(vgname, lvname), /* copy */ @@ -108,7 +109,8 @@ struct lvmpolld_lv *pdlv_create(struct lvmpolld_state *ls, const char *id, .pdtimeout = pdtimeout < MIN_POLLING_TIMEOUT ? MIN_POLLING_TIMEOUT : pdtimeout, .cmd_state = { .retcode = -1, .signal = 0 }, .pdst = pdst, - .init_rq_count = 1 + .init_rq_count = 1, + .parse_output_fn = parse_fn }, *pdlv = (struct lvmpolld_lv *) dm_malloc(sizeof(struct lvmpolld_lv)); if (!pdlv || !tmp.lvid || !tmp.lvname || !tmp.lvm_system_dir_env || !tmp.sinterval) @@ -183,6 +185,13 @@ void pdlv_set_error(struct lvmpolld_lv *pdlv, unsigned error) pdlv_unlock(pdlv); } +void pdlv_set_percents(struct lvmpolld_lv *pdlv, dm_percent_t percent) +{ + pdlv_lock(pdlv); + pdlv->percent = percent; + pdlv_unlock(pdlv); +} + void pdlv_set_polling_finished(struct lvmpolld_lv *pdlv, unsigned finished) { pdlv_lock(pdlv); diff --git a/daemons/lvmpolld/lvmpolld-data-utils.h b/daemons/lvmpolld/lvmpolld-data-utils.h index 5bb5c863d..215886516 100644 --- a/daemons/lvmpolld/lvmpolld-data-utils.h +++ b/daemons/lvmpolld/lvmpolld-data-utils.h @@ -19,6 +19,9 @@ struct buffer; struct lvmpolld_state; +struct lvmpolld_lv; + +typedef void (*lvmpolld_parse_output_fn_t) (struct lvmpolld_lv *pdlv, const char *line); enum poll_type { PVMOVE = 0, @@ -54,6 +57,7 @@ struct lvmpolld_lv { const char *const sinterval; const char *const lvm_system_dir_env; struct lvmpolld_store *const pdst; + lvmpolld_parse_output_fn_t parse_output_fn; const char *const *cmdargv; const char *const *cmdenvp; @@ -65,13 +69,12 @@ struct lvmpolld_lv { /* block of shared variables protected by lock */ struct lvmpolld_cmd_stat cmd_state; + dm_percent_t percent; unsigned init_rq_count; /* for debuging purposes only */ unsigned polling_finished:1; /* no more updates */ unsigned error:1; /* unrecoverable error occured in lvmpolld */ }; -typedef void (*lvmpolld_parse_output_fn_t) (struct lvmpolld_lv *pdlv, const char *line); - /* TODO: replace with configuration option */ #define MIN_POLLING_TIMEOUT 60 @@ -101,7 +104,8 @@ struct lvmpolld_lv *pdlv_create(struct lvmpolld_state *ls, const char *id, const char *vgname, const char *lvname, const char *sysdir, enum poll_type type, const char *sinterval, unsigned pdtimeout, - struct lvmpolld_store *pdst); + struct lvmpolld_store *pdst, + lvmpolld_parse_output_fn_t parse_fn); /* only call with appropriate struct lvmpolld_store lock held */ void pdlv_destroy(struct lvmpolld_lv *pdlv); @@ -138,6 +142,7 @@ unsigned pdlv_get_polling_finished(struct lvmpolld_lv *pdlv); struct lvmpolld_lv_state pdlv_get_status(struct lvmpolld_lv *pdlv); void pdlv_set_cmd_state(struct lvmpolld_lv *pdlv, const struct lvmpolld_cmd_stat *cmd_state); void pdlv_set_error(struct lvmpolld_lv *pdlv, unsigned error); +void pdlv_set_percents(struct lvmpolld_lv *pdlv, dm_percent_t percent); void pdlv_set_polling_finished(struct lvmpolld_lv *pdlv, unsigned finished); /*