From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 28710 invoked by alias); 10 Jan 2008 18:35:53 -0000 Received: (qmail 28695 invoked by uid 9447); 10 Jan 2008 18:35:52 -0000 Date: Thu, 10 Jan 2008 18:35:00 -0000 Message-ID: <20080110183552.28693.qmail@sourceware.org> From: agk@sourceware.org To: lvm-devel@redhat.com, lvm2-cvs@sourceware.org Subject: LVM2 lib/format_text/flags.c lib/format_text/i ... Mailing-List: contact lvm2-cvs-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Post: List-Help: , Sender: lvm2-cvs-owner@sourceware.org X-SW-Source: 2008-01/txt/msg00012.txt.bz2 CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: agk@sourceware.org 2008-01-10 18:35:51 Modified files: lib/format_text: flags.c import_vsn1.c lib/metadata : metadata-exported.h mirror.c lib/report : columns.h report.c man : lvs.8 pvs.8 vgs.8 tools : lvchange.c lvconvert.c tools.h Log message: Various lvconvert/polldaemon-related fixes from NEC. See lvm-devel for original patches & explanations. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/format_text/flags.c.diff?cvsroot=lvm2&r1=1.30&r2=1.31 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/format_text/import_vsn1.c.diff?cvsroot=lvm2&r1=1.45&r2=1.46 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/metadata-exported.h.diff?cvsroot=lvm2&r1=1.30&r2=1.31 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/mirror.c.diff?cvsroot=lvm2&r1=1.51&r2=1.52 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/report/columns.h.diff?cvsroot=lvm2&r1=1.26&r2=1.27 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/report/report.c.diff?cvsroot=lvm2&r1=1.70&r2=1.71 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/man/lvs.8.diff?cvsroot=lvm2&r1=1.7&r2=1.8 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/man/pvs.8.diff?cvsroot=lvm2&r1=1.3&r2=1.4 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/man/vgs.8.diff?cvsroot=lvm2&r1=1.5&r2=1.6 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/lvchange.c.diff?cvsroot=lvm2&r1=1.84&r2=1.85 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/lvconvert.c.diff?cvsroot=lvm2&r1=1.52&r2=1.53 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/tools.h.diff?cvsroot=lvm2&r1=1.59&r2=1.60 --- LVM2/lib/format_text/flags.c 2007/08/20 20:55:26 1.30 +++ LVM2/lib/format_text/flags.c 2008/01/10 18:35:50 1.31 @@ -60,6 +60,7 @@ {VIRTUAL, NULL}, {SNAPSHOT, NULL}, {ACTIVATE_EXCL, NULL}, + {CONVERTING, NULL}, {0, NULL} }; --- LVM2/lib/format_text/import_vsn1.c 2007/11/09 16:51:53 1.45 +++ LVM2/lib/format_text/import_vsn1.c 2008/01/10 18:35:50 1.46 @@ -86,6 +86,22 @@ return 1; } +static int _is_converting(struct logical_volume *lv) +{ + struct lv_segment *seg; + + if (lv->status & MIRRORED) { + seg = first_seg(lv); + /* Can't use is_temporary_mirror() because the metadata for + * seg_lv may not be read in and flags may not be set yet. */ + if (seg_type(seg, 0) == AREA_LV && + strstr(seg_lv(seg, 0)->name, MIRROR_SYNC_LAYER)) + return 1; + } + + return 0; +} + static int _read_id(struct id *id, struct config_node *cn, const char *path) { struct config_value *cv; @@ -343,6 +359,9 @@ if (seg_is_virtual(seg)) lv->status |= VIRTUAL; + if (_is_converting(lv)) + lv->status |= CONVERTING; + return 1; } --- LVM2/lib/metadata/metadata-exported.h 2008/01/07 20:42:57 1.30 +++ LVM2/lib/metadata/metadata-exported.h 2008/01/10 18:35:50 1.31 @@ -69,6 +69,7 @@ #define MIRROR_NOTSYNCED 0x00080000U /* LV */ //#define ACTIVATE_EXCL 0x00100000U /* LV - internal use only */ //#define PRECOMMITTED 0x00200000U /* VG - internal use only */ +#define CONVERTING 0x00400000U /* LV */ #define LVM_READ 0x00000100U /* LV VG */ #define LVM_WRITE 0x00000200U /* LV VG */ --- LVM2/lib/metadata/mirror.c 2007/12/22 12:13:29 1.51 +++ LVM2/lib/metadata/mirror.c 2008/01/10 18:35:50 1.52 @@ -134,13 +134,34 @@ return 1; } +static int _merge_mirror_images(struct logical_volume *lv, + const struct list *mimages) +{ + uint32_t addition = list_size(mimages); + struct logical_volume **img_lvs; + struct lv_list *lvl; + int i = 0; + + if (!addition) + return 1; + + if (!(img_lvs = alloca(sizeof(*img_lvs) * addition))) + return_0; + + list_iterate_items(lvl, mimages) + img_lvs[i++] = lvl->lv; + + return lv_add_mirror_lvs(lv, img_lvs, addition, + MIRROR_IMAGE, first_seg(lv)->region_size); +} + /* * Remove num_removed images from mirrored_seg */ static int _remove_mirror_images(struct logical_volume *lv, uint32_t num_removed, struct list *removable_pvs, - unsigned remove_log, struct list *orphan_lvs) + unsigned remove_log, unsigned collapse) { uint32_t m; uint32_t s, s1; @@ -162,9 +183,16 @@ old_area_count, old_area_count - num_removed, remove_log ? " and no log volume" : ""); + if (collapse && + (removable_pvs || (old_area_count - num_removed != 1))) { + log_error("Incompatible parameters to _remove_mirror_images"); + return 0; + } + /* Move removable_pvs to end of array */ if (removable_pvs) { - for (s = 0; s < mirrored_seg->area_count; s++) { + for (s = 0; s < mirrored_seg->area_count && + old_area_count - new_area_count < num_removed; s++) { all_pvs_removable = 1; sub_lv = seg_lv(mirrored_seg, s); list_iterate_items(seg, &sub_lv->segments) { @@ -197,11 +225,8 @@ mirrored_seg->areas[new_area_count] = mirrored_seg->areas[s]; mirrored_seg->areas[s] = area; } - /* Found enough matches? */ - if (old_area_count - new_area_count == num_removed) - break; } - if (old_area_count == new_area_count) { + if (num_removed && old_area_count == new_area_count) { log_error("No mirror images found using specified PVs."); return 0; } @@ -235,7 +260,12 @@ lv->status &= ~MIRRORED; lv->status &= ~MIRROR_NOTSYNCED; remove_log = 1; - } + if (collapse && !_merge_mirror_images(lv, &tmp_orphan_lvs)) { + log_error("Failed to add mirror images"); + return 0; + } + } else if (remove_log) + mirrored_seg->log_lv = NULL; if (remove_log && log_lv) { log_lv->status &= ~MIRROR_LOG; @@ -272,11 +302,7 @@ } /* Save or delete the 'orphan' LVs */ - if (orphan_lvs) { - *orphan_lvs = tmp_orphan_lvs; - orphan_lvs->n->p = orphan_lvs; - orphan_lvs->p->n = orphan_lvs; - } else { + if (!collapse) { list_iterate_items(lvl, &tmp_orphan_lvs) if (!_delete_lv(lv, lvl->lv)) return 0; @@ -302,18 +328,19 @@ num_removed = existing_mirrors - num_mirrors; - while (num_removed) { + /* num_removed can be 0 if the function is called just to remove log */ + do { if (num_removed < first_seg(lv)->area_count) removed_once = num_removed; else removed_once = first_seg(lv)->area_count - 1; if (!_remove_mirror_images(lv, removed_once, - removable_pvs, remove_log, NULL)) + removable_pvs, remove_log, 0)) return_0; num_removed -= removed_once; - } + } while (num_removed); return 1; } @@ -334,27 +361,6 @@ return 0; } -static int _merge_mirror_images(struct logical_volume *lv, - const struct list *mimages) -{ - uint32_t addition = list_size(mimages); - struct logical_volume **img_lvs; - struct lv_list *lvl; - int i = 0; - - if (!addition) - return 1; - - if (!(img_lvs = alloca(sizeof(*img_lvs) * addition))) - return_0; - - list_iterate_items(lvl, mimages) - img_lvs[i++] = lvl->lv; - - return lv_add_mirror_lvs(lv, img_lvs, addition, - MIRROR_IMAGE, first_seg(lv)->region_size); -} - /* * Return a temporary LV for resyncing added mirror image. * Add other mirror legs to lvs list. @@ -390,7 +396,6 @@ int collapse_mirrored_lv(struct logical_volume *lv) { struct logical_volume *tmp_lv, *parent_lv; - struct list lvlist; while ((tmp_lv = _find_tmp_mirror(lv))) { parent_lv = find_parent_for_layer(lv, tmp_lv); @@ -400,18 +405,12 @@ return 1; } - list_init(&lvlist); if (!_remove_mirror_images(parent_lv, first_seg(parent_lv)->area_count - 1, - NULL, 1, &lvlist)) { + NULL, 1, 1)) { log_error("Failed to release mirror images"); return 0; } - - if (!_merge_mirror_images(parent_lv, &lvlist)) { - log_error("Failed to add mirror images"); - return 0; - } } return 1; @@ -1277,6 +1276,13 @@ return 0; } + /* For corelog mirror, activation code depends on + * the global mirror_in_sync status. As we are adding + * a new mirror, it should be set as 'out-of-sync' + * so that the sync starts. */ + if (!log_count) + init_mirror_in_sync(0); + if (flags & MIRROR_BY_SEG) { if (log_count) { log_error("Persistent log is not supported on " --- LVM2/lib/report/columns.h 2007/12/14 21:53:02 1.26 +++ LVM2/lib/report/columns.h 2008/01/10 18:35:51 1.27 @@ -33,6 +33,7 @@ FIELD(LVS, lv, NUM, "Snap%", lvid, 6, snpercent, "snap_percent", "For snapshots, the percentage full if LV is active.") FIELD(LVS, lv, NUM, "Copy%", lvid, 6, copypercent, "copy_percent", "For mirrors and pvmove, current percentage in-sync.") FIELD(LVS, lv, STR, "Move", lvid, 4, movepv, "move_pv", "For pvmove, Source PV of temporary LV created by pvmove") +FIELD(LVS, lv, STR, "Convert", lvid, 7, convertlv, "convert_lv", "For lvconvert, Name of temporary LV created by lvconvert") FIELD(LVS, lv, STR, "LV Tags", tags, 7, tags, "lv_tags", "Tags, if any.") FIELD(LVS, lv, STR, "Log", lvid, 3, loglv, "mirror_log", "For mirrors, the LV holding the synchronisation log.") FIELD(LVS, lv, STR, "Modules", lvid, 7, modules, "modules", "Kernel device-mapper modules required for this LV.") --- LVM2/lib/report/report.c 2007/12/22 02:12:59 1.70 +++ LVM2/lib/report/report.c 2008/01/10 18:35:51 1.71 @@ -272,7 +272,7 @@ return dm_report_field_uint64(rh, field, &_minusone); } -static int _lv_mimage_in_sync(struct logical_volume *lv) +static int _lv_mimage_in_sync(const struct logical_volume *lv) { float percent; struct lv_segment *seg = first_seg(lv); @@ -306,6 +306,8 @@ if (lv->status & PVMOVE) repstr[0] = 'p'; + else if (lv->status & CONVERTING) + repstr[0] = 'c'; else if (lv->status & MIRRORED) { if (lv->status & MIRROR_NOTSYNCED) repstr[0] = 'M'; @@ -548,6 +550,32 @@ return 1; } +static int _convertlv_disp(struct dm_report *rh, struct dm_pool *mem __attribute((unused)), + struct dm_report_field *field, + const void *data, void *private __attribute((unused))) +{ + const struct logical_volume *lv = (const struct logical_volume *) data; + const char *name = NULL; + struct lv_segment *seg; + + if (lv->status & CONVERTING) { + if (lv->status & MIRRORED) { + seg = first_seg(lv); + + /* Temporary mirror is always area_num == 0 */ + if (seg_type(seg, 0) == AREA_LV && + is_temporary_mirror_layer(seg_lv(seg, 0))) + name = seg_lv(seg, 0)->name; + } + } + + if (name) + return dm_report_field_string(rh, field, &name); + + dm_report_field_set_value(field, "", NULL); + return 1; +} + static int _size32_disp(struct dm_report *rh __attribute((unused)), struct dm_pool *mem, struct dm_report_field *field, const void *data, void *private) --- LVM2/man/lvs.8 2007/12/22 02:12:59 1.7 +++ LVM2/man/lvs.8 2008/01/10 18:35:51 1.8 @@ -47,7 +47,8 @@ .RS .IP 1 3 Volume type: (m)irrored, (M)irrored without initial sync, (o)rigin, (p)vmove, (s)napshot, -invalid (S)napshot, (v)irtual, mirror (i)mage, mirror (I)mage out-of-sync +invalid (S)napshot, (v)irtual, mirror (i)mage, mirror (I)mage out-of-sync, +under (c)onversion .IP 2 3 Permissions: (w)riteable, (r)ead-only .IP 3 3 @@ -82,6 +83,7 @@ of 1000 (S.I.) instead of 1024. Can also specify custom (u)nits e.g. \-\-units 3M .SH SEE ALSO +.BR lvm (8), .BR lvdisplay (8), .BR pvs (8), .BR vgs (8) --- LVM2/man/pvs.8 2007/01/18 22:33:24 1.3 +++ LVM2/man/pvs.8 2008/01/10 18:35:51 1.4 @@ -58,6 +58,7 @@ of 1000 (S.I.) instead of 1024. Can also specify custom (u)nits e.g. \-\-units 3M .SH SEE ALSO +.BR lvm (8), .BR pvdisplay (8), .BR lvs (8), .BR vgs (8) --- LVM2/man/vgs.8 2007/03/27 13:35:33 1.5 +++ LVM2/man/vgs.8 2008/01/10 18:35:51 1.6 @@ -71,6 +71,7 @@ of 1000 (S.I.) instead of 1024. Can also specify custom (u)nits e.g. \-\-units 3M .SH SEE ALSO +.BR lvm (8), .BR vgdisplay (8), .BR pvs (8), .BR lvs (8) --- LVM2/tools/lvchange.c 2007/12/05 19:24:32 1.84 +++ LVM2/tools/lvchange.c 2008/01/10 18:35:51 1.85 @@ -106,6 +106,8 @@ { int activate; const char *pvname; + char *lv_full_name; + uint32_t len; activate = arg_uint_value(cmd, available_ARG, 0); @@ -158,6 +160,18 @@ pvname); pvmove_poll(cmd, pvname, 1); } + + if (lv->status & CONVERTING) { + len = strlen(lv->vg->name) + strlen(lv->name) + 2; + if (!(lv_full_name = alloca(len))) + return_0; + if (!dm_snprintf(lv_full_name, len, "%s/%s", + lv->vg->name, lv->name)) + return_0; + log_verbose("Spawning background lvconvert process for %s", + lv->name); + lvconvert_poll(cmd, lv_full_name, 1); + } } return 1; --- LVM2/tools/lvconvert.c 2007/12/22 12:13:29 1.52 +++ LVM2/tools/lvconvert.c 2008/01/10 18:35:51 1.53 @@ -270,6 +270,8 @@ return 0; } + lv->status &= ~CONVERTING; + log_very_verbose("Updating logical volume \"%s\" on disk(s)", lv->name); if (!vg_write(vg)) @@ -307,8 +309,8 @@ .finish_copy = _finish_lvconvert_mirror, }; -static int _lvconvert_poll(struct cmd_context *cmd, const char *lv_name, - unsigned background) +int lvconvert_poll(struct cmd_context *cmd, const char *lv_name, + unsigned background) { return poll_daemon(cmd, lv_name, background, 0, &_lvconvert_mirror_fns, "Converted"); @@ -370,7 +372,8 @@ existing_mirrors = lv_mirror_count(lv); /* If called with no argument, try collapsing the resync layers */ - if (!arg_count(cmd, mirrors_ARG) && !arg_count(cmd, mirrorlog_ARG)) { + if (!arg_count(cmd, mirrors_ARG) && !arg_count(cmd, mirrorlog_ARG) && + !arg_count(cmd, corelog_ARG)) { lp->wait_daemon = 1; return 1; } @@ -496,7 +499,8 @@ lp->pvh, lp->alloc)) return_0; } else if (seg->log_lv && corelog) { - if (!remove_mirror_log(cmd, lv, lp->pvh)) + if (!remove_mirror_log(cmd, lv, + lp->pv_count ? lp->pvh : NULL)) return_0; } else { /* No change */ @@ -511,25 +515,46 @@ "without initial resync"); return 0; } - /* FIXME: can't have multiple mlogs. force corelog. */ - corelog = 1; - if (!_insert_lvconvert_layer(cmd, lv)) { + /* + * Log addition/removal should be done before the layer + * insertion to make the end result consistent with + * linear-to-mirror conversion. + */ + if (!seg->log_lv && !corelog) { + if (!add_mirror_log(cmd, lv, 1, + adjusted_mirror_region_size( + lv->vg->extent_size, + lv->le_count, + lp->region_size), + lp->pvh, lp->alloc)) + return_0; + } else if (seg->log_lv && corelog) { + if (!remove_mirror_log(cmd, lv, + lp->pv_count ? lp->pvh : NULL)) + return_0; + } + /* Insert a temporary layer for syncing, + * only if the original lv is using disk log. */ + if (seg->log_lv && !_insert_lvconvert_layer(cmd, lv)) { log_error("Failed to insert resync layer"); return 0; } + /* FIXME: can't have multiple mlogs. force corelog. */ if (!lv_add_mirrors(cmd, lv, lp->mirrors - existing_mirrors, 1, adjusted_mirror_region_size( lv->vg->extent_size, lv->le_count, lp->region_size), - corelog ? 0U : 1U, lp->pvh, lp->alloc, + 0U, lp->pvh, lp->alloc, MIRROR_BY_LV)) return_0; + lv->status |= CONVERTING; lp->wait_daemon = 1; } else { /* Reduce number of mirrors */ if (!lv_remove_mirrors(cmd, lv, existing_mirrors - lp->mirrors, - 0, lp->pv_count ? lp->pvh : NULL, 0)) + corelog ? 1U : 0U, + lp->pv_count ? lp->pvh : NULL, 0)) return_0; } @@ -681,6 +706,7 @@ struct lv_list *lvl; struct lvconvert_params lp; int ret = ECMD_FAILED; + struct lvinfo info; if (!_read_params(&lp, cmd, argc, argv)) { stack; @@ -714,8 +740,14 @@ error: unlock_vg(cmd, lp.vg_name); - if (lp.wait_daemon) - ret = _lvconvert_poll(cmd, lp.lv_name_full, - arg_count(cmd, background_ARG) ? 1U : 0); + if (ret == ECMD_PROCESSED && lp.wait_daemon) { + if (!lv_info(cmd, lvl->lv, &info, 1, 0) || !info.exists) { + log_print("Conversion starts after activation"); + return ret; + } + ret = lvconvert_poll(cmd, lp.lv_name_full, + arg_count(cmd, background_ARG) ? 1U : 0); + } + return ret; } --- LVM2/tools/tools.h 2007/11/09 16:51:54 1.59 +++ LVM2/tools/tools.h 2008/01/10 18:35:51 1.60 @@ -165,5 +165,6 @@ const char *command_name(struct cmd_context *cmd); int pvmove_poll(struct cmd_context *cmd, const char *pv, unsigned background); +int lvconvert_poll(struct cmd_context *cmd, const char *lv_name, unsigned background); #endif