Index: tools/polldaemon.c =================================================================== RCS file: /cvs/lvm2/LVM2/tools/polldaemon.c,v retrieving revision 1.5 diff -u -p -r1.5 polldaemon.c --- tools/polldaemon.c 17 Oct 2005 17:56:27 -0000 1.5 +++ tools/polldaemon.c 2 May 2006 15:29:12 -0000 @@ -18,6 +18,15 @@ #include #include +struct daemon_parms { + struct poll_functions *poll_fns; + unsigned interval; + unsigned aborting; + unsigned background; + unsigned outstanding_count; + unsigned progress_display; +}; + static void _sigchld_handler(int sig) { while (wait4(-1, NULL, WNOHANG | WUNTRACED, NULL) > 0) ; @@ -62,76 +71,31 @@ static int _become_daemon(struct cmd_con return 1; } -static int _check_mirror_status(struct cmd_context *cmd, - struct volume_group *vg, - struct logical_volume *lv_mirr, - const char *name, struct daemon_parms *parms, - int *finished) -{ - struct list *lvs_changed; - float segment_percent = 0.0, overall_percent = 0.0; - uint32_t event_nr = 0; - +static int _check_lv_status(struct cmd_context *cmd, struct volume_group *vg, + struct logical_volume *lv, + struct daemon_parms *parms, int *finished) +{ /* By default, caller should not retry */ *finished = 1; - if (parms->aborting) { - if (!(lvs_changed = lvs_using_lv(cmd, vg, lv_mirr))) { - log_error("Failed to generate list of copied LVs: " - "can't abort."); - return 0; - } - parms->poll_fns->finish_copy(cmd, vg, lv_mirr, lvs_changed); - return 0; - } - - if (!lv_mirror_percent(cmd, lv_mirr, !parms->interval, &segment_percent, - &event_nr)) { - log_error("ABORTING: Mirror percentage check failed."); - return 0; - } - - overall_percent = copy_percent(lv_mirr); - if (parms->progress_display) - log_print("%s: Moved: %.1f%%", name, overall_percent); - else - log_verbose("%s: Moved: %.1f%%", name, overall_percent); - - if (segment_percent < 100.0) { - /* The only case the caller *should* try again later */ - *finished = 0; - return 1; - } + if (parms->aborting) + return parms->poll_fns->finish(cmd, vg, lv); - if (!(lvs_changed = lvs_using_lv(cmd, vg, lv_mirr))) { - log_error("ABORTING: Failed to generate list of copied LVs"); + if (!parms->poll_fns->poll_lv(cmd, vg, lv, !parms->interval, + parms->progress_display, finished)) return 0; - } - /* Finished? Or progress to next segment? */ - if (overall_percent >= 100.0) { - if (!parms->poll_fns->finish_copy(cmd, vg, lv_mirr, - lvs_changed)) - return 0; - } else { - if (!parms->poll_fns->update_metadata(cmd, vg, lv_mirr, - lvs_changed, 0)) { - log_error("ABORTING: Segment progression failed."); - parms->poll_fns->finish_copy(cmd, vg, lv_mirr, - lvs_changed); - return 0; - } - *finished = 0; /* Another segment */ - } + if (!*finished) + return 1; /* The caller *should* try again later */ - return 1; + return parms->poll_fns->finish(cmd, vg, lv); } -static int _wait_for_single_mirror(struct cmd_context *cmd, const char *name, - struct daemon_parms *parms) +static int _poll_for_single_lv(struct cmd_context *cmd, const char *name, + struct daemon_parms *parms) { struct volume_group *vg; - struct logical_volume *lv_mirr; + struct logical_volume *lv; int finished = 0; /* Poll for mirror completion */ @@ -144,23 +108,12 @@ static int _wait_for_single_mirror(struc init_full_scan_done(0); } - /* Locks the (possibly renamed) VG again */ - if (!(vg = parms->poll_fns->get_copy_vg(cmd, name))) { - log_error("ABORTING: Can't reread VG for %s", name); - /* What more could we do here? */ - return 0; - } - - if (!(lv_mirr = parms->poll_fns->get_copy_lv(cmd, vg, name, - parms->lv_type))) { - log_error("ABORTING: Can't find mirror LV in %s for %s", - vg->name, name); - unlock_vg(cmd, vg->name); + if (!parms->poll_fns->get_vg_and_lv(cmd, name, &vg, &lv)) { + log_error("ABORTING: Can't find VG and LV for %s", name); return 0; } - if (!_check_mirror_status(cmd, vg, lv_mirr, name, parms, - &finished)) { + if (!_check_lv_status(cmd, vg, lv, parms, &finished)) { unlock_vg(cmd, vg->name); return 0; } @@ -176,8 +129,6 @@ static int _poll_vg(struct cmd_context * { struct daemon_parms *parms = (struct daemon_parms *) handle; struct lv_list *lvl; - struct logical_volume *lv_mirr; - const char *name; int finished; if (!vg) { @@ -196,18 +147,10 @@ static int _poll_vg(struct cmd_context * return ECMD_FAILED; } - list_iterate_items(lvl, &vg->lvs) { - lv_mirr = lvl->lv; - if (!(lv_mirr->status & parms->lv_type)) - continue; - if (!(name = parms->poll_fns->get_copy_name_from_lv(lv_mirr))) - continue; - /* FIXME Need to do the activation from _set_up_pvmove here - * if it's not running and we're not aborting */ - if (_check_mirror_status(cmd, vg, lv_mirr, name, - parms, &finished) && !finished) + list_iterate_items(lvl, &vg->lvs) + if (_check_lv_status(cmd, vg, lvl->lv, parms, &finished) && + !finished) parms->outstanding_count++; - } return ECMD_PROCESSED; @@ -225,16 +168,16 @@ static void _poll_for_all_vgs(struct cmd } } -int poll_daemon(struct cmd_context *cmd, const char *name, unsigned background, - uint32_t lv_type, struct poll_functions *poll_fns) +int poll_daemon(struct cmd_context *cmd, struct poll_functions *poll_fns, + const char *name, unsigned interval, + unsigned aborting, unsigned background) { struct daemon_parms parms; - parms.aborting = arg_count(cmd, abort_ARG) ? 1 : 0; + parms.interval = interval; + parms.aborting = aborting; parms.background = background; - parms.interval = arg_uint_value(cmd, interval_ARG, DEFAULT_INTERVAL); parms.progress_display = 1; - parms.lv_type = lv_type; parms.poll_fns = poll_fns; if (parms.interval && !parms.aborting) @@ -258,7 +201,7 @@ int poll_daemon(struct cmd_context *cmd, } if (name) { - if (!_wait_for_single_mirror(cmd, name, &parms)) + if (!_poll_for_single_lv(cmd, name, &parms)) return ECMD_FAILED; } else _poll_for_all_vgs(cmd, &parms); Index: tools/polldaemon.h =================================================================== RCS file: /cvs/lvm2/LVM2/tools/polldaemon.h,v retrieving revision 1.1 diff -u -p -r1.1 polldaemon.h --- tools/polldaemon.h 5 May 2004 17:56:20 -0000 1.1 +++ tools/polldaemon.h 2 May 2006 15:29:12 -0000 @@ -19,34 +19,23 @@ #include "metadata.h" struct poll_functions { - const char *(*get_copy_name_from_lv) (struct logical_volume * lv_mirr); - struct volume_group *(*get_copy_vg) (struct cmd_context * cmd, - const char *name); - struct logical_volume *(*get_copy_lv) (struct cmd_context * cmd, - struct volume_group * vg, - const char *name, - uint32_t lv_type); - int (*update_metadata) (struct cmd_context * cmd, - struct volume_group * vg, - struct logical_volume * lv_mirr, - struct list * lvs_changed, int first_time); - int (*finish_copy) (struct cmd_context * cmd, - struct volume_group * vg, - struct logical_volume * lv_mirr, - struct list * lvs_changed); + int (*get_vg_and_lv) (struct cmd_context *cmd, + const char *name, + struct volume_group **vg, + struct logical_volume **lv); + int (*poll_lv) (struct cmd_context *cmd, + struct volume_group *vg, + struct logical_volume *lv, + int wait, + int display_progress, + int *finished); + int (*finish) (struct cmd_context *cmd, + struct volume_group *vg, + struct logical_volume *lv); }; -struct daemon_parms { - unsigned interval; - unsigned aborting; - unsigned background; - unsigned outstanding_count; - unsigned progress_display; - uint32_t lv_type; - struct poll_functions *poll_fns; -}; - -int poll_daemon(struct cmd_context *cmd, const char *name, unsigned background, - uint32_t lv_type, struct poll_functions *poll_fns); +int poll_daemon(struct cmd_context *cmd, struct poll_functions *poll_fns, + const char *name, unsigned interval, + unsigned aborting, unsigned background); #endif Index: tools/pvmove.c =================================================================== RCS file: /cvs/lvm2/LVM2/tools/pvmove.c,v retrieving revision 1.29 diff -u -p -r1.29 pvmove.c --- tools/pvmove.c 12 Apr 2006 21:23:04 -0000 1.29 +++ tools/pvmove.c 2 May 2006 15:29:12 -0000 @@ -389,12 +389,17 @@ static int _set_up_pvmove(struct cmd_con return ECMD_PROCESSED; } -static int _finish_pvmove(struct cmd_context *cmd, struct volume_group *vg, - struct logical_volume *lv_mirr, - struct list *lvs_changed) +static int _pvmove_finish_copy(struct cmd_context *cmd, struct volume_group *vg, + struct logical_volume *lv_mirr) { + struct list *lvs_changed; int r = 1; + if (!(lvs_changed = lvs_using_lv(cmd, vg, lv_mirr))) { + log_error("ABORTING: Failed to generate list of copied LVs"); + return 0; + } + /* Update metadata to remove mirror segments and break dependencies */ if (!remove_pvmove_mirrors(vg, lv_mirr)) { log_error("ABORTING: Removal of temporary mirror failed"); @@ -467,33 +472,99 @@ static int _finish_pvmove(struct cmd_con return r; } -static struct volume_group *_get_move_vg(struct cmd_context *cmd, - const char *name) +static int _pvmove_poll_lv(struct cmd_context *cmd, struct volume_group *vg, + struct logical_volume *lv, int wait, + int display_progress, int *finished) +{ + struct list *lvs_changed; + float segment_percent = 0.0, overall_percent = 0.0; + uint32_t event_nr = 0; + const char *name; + + *finished = 1; + + if (!(lv->status & PVMOVE)) + return 0; + + if (!lv_mirror_percent(cmd, lv, wait, &segment_percent, &event_nr)) { + log_error("ABORTING: Mirror percentage check failed."); + return 0; + } + + overall_percent = copy_percent(lv); + name = get_pvmove_pvname_from_lv_mirr(lv); + if (display_progress) + log_print("%s: Moved: %.1f%%", name, overall_percent); + else + log_verbose("%s: Moved: %.1f%%", name, overall_percent); + + if (segment_percent < 100.0) { + *finished = 0; + return 1; + } + + if (!(lvs_changed = lvs_using_lv(cmd, vg, lv))) { + log_error("ABORTING: Failed to generate list of copied LVs"); + return 0; + } + + if (overall_percent < 100.0) { + if (!_update_metadata(cmd, vg, lv, lvs_changed, 0)) { + log_error("ABORTING: Segment progression failed."); + _pvmove_finish_copy(cmd, vg, lv); + return 0; + } + *finished = 0; /* Another segment */ + } + + return 1; +} + +static int _pvmove_get_vg_and_lv(struct cmd_context *cmd, const char *name, + struct volume_group **vg_ret, + struct logical_volume **lv_ret) { struct physical_volume *pv; + struct volume_group *vg; + struct logical_volume *lv; /* Reread all metadata in case it got changed */ if (!(pv = find_pv_by_name(cmd, name))) { log_error("ABORTING: Can't reread PV %s", name); /* What more could we do here? */ - return NULL; + return 0; } - return _get_vg(cmd, pv->vg_name); + if (!(vg = _get_vg(cmd, pv->vg_name))) + return 0; + + if (!(lv = find_pvmove_lv_from_pvname(cmd, vg, name, PVMOVE))) { + unlock_vg(cmd, vg->name); + return 0; + } + + *vg_ret = vg; + *lv_ret = lv; + + return 1; } static struct poll_functions _pvmove_fns = { - get_copy_name_from_lv:get_pvmove_pvname_from_lv_mirr, - get_copy_vg:_get_move_vg, - get_copy_lv:find_pvmove_lv_from_pvname, - update_metadata:_update_metadata, - finish_copy:_finish_pvmove, + get_vg_and_lv : _pvmove_get_vg_and_lv, + poll_lv : _pvmove_poll_lv, + finish : _pvmove_finish_copy, }; int pvmove_poll(struct cmd_context *cmd, const char *pv_name, unsigned background) { - return poll_daemon(cmd, pv_name, background, PVMOVE, &_pvmove_fns); + unsigned interval, aborting; + + interval = arg_uint_value(cmd, interval_ARG, DEFAULT_INTERVAL); + aborting = arg_count(cmd, abort_ARG) ? 1 : 0; + + return poll_daemon(cmd, &_pvmove_fns, pv_name, + interval, aborting, background); } int pvmove(struct cmd_context *cmd, int argc, char **argv)