Replicator 100428
cover Replicator 100428
Rebased set of replicator patches.
Log creation code is still kept separately as many changes are still on going in this code.
Updated parts:
* Updated dm_splice_list() API.
* Removed old code from dm_tree_preload_children().
* Renamed failed_lvs -> failed_lvnames.
* Switched vgs_list to cmd_vg and updated API slightly
* Extracted nonrelated change in front of patchset (return ECMD_FAILED)
* Previous set had wrong month number.
* Converted Makefiles.
* Renamed some functions (removed lvm_ prefix).
* Renamed vg_name_list -> vgs_list.
* Roved code from validation to segment checking.
* Added dm_list_splice
* Changed API for process_each_lv_in_vg()
* lock_lv_vol() detects missing VGs before calling lock_vol().
* Using common typedef between dm and lvm part for operation mode.
* Minor code reoganization based on review
* Extended validation code.
* Added manpages updates to patches to document API
still this is ongoing task to make all the options working.
* API around vg_name_list which is now autonomous entity.
* Processed VG contains list of opened VGs and flag for missing VGs.
Zdenek Kabelac (23):
Return ECMD_FAILED for break
Add dm_list_splice() for list join.
API change for args of process_each_lv_in_vg()
Replicator: libdm support
Replicator: suspend/deactivate replicator
Replicator: lvm2 support
Replicator: check replicator segment
Replicator: extend _lv_each_dependency() rep. deps
Replicator: extend volume_group with list of VGs
Replicator: add sorted cmd_vg list
Replicator: add find_replicator_vgs
Replicator: add read and release VGs for rsites
Replicator: use cmd_vg list for _process_one_vg()
Replicator: use cmd_vg for process_each_lv_in_vg()
Replicator: lock_vol() finds missing VGs
Replicator: activate checks for missing vgs
Replicator: update _create_partial_dtree()
Replicator: vg with cmd_missing_vgs does not print
Replicator: add replicator to dtree
Replicator: do not remove of replicators' LVs
Replicator: activate change for vgchange
Replicator: add new options for replicator
Replicator: man pages for lvcreate, lvchange
configure.in | 17 + lib/Makefile.in | 10 + lib/activate/activate.c | 21 +- lib/activate/dev_manager.c | 136 +++++++- lib/commands/toolcontext.c | 5 + lib/config/defaults.h | 1 + lib/format_text/flags.c | 2 + lib/locking/locking.h | 4 +- lib/metadata/lv_manip.c | 10 + lib/metadata/merge.c | 17 + lib/metadata/metadata-exported.h | 98 +++++- lib/metadata/metadata.c | 4 + lib/metadata/metadata.h | 6 + lib/metadata/replicator_manip.c | 692 +++++++++++++++++++++++++++++++++ lib/metadata/segtype.h | 8 + lib/replicator/.exported_symbols | 1 + lib/replicator/Makefile.in | 25 ++ lib/replicator/replicator.c | 790 ++++++++++++++++++++++++++++++++++++++ libdm/.exported_symbols | 4 + libdm/datastruct/list.c | 24 ++- libdm/libdevmapper.h | 42 ++ libdm/libdm-deptree.c | 358 +++++++++++++++++- man/lvchange.8.in | 56 +++ man/lvcreate.8.in | 63 +++- tools/args.h | 13 + tools/commands.h | 7 + tools/lvcreate.c | 58 +++- tools/lvmcmdline.c | 9 + tools/toollib.c | 114 ++++-- tools/toollib.h | 1 + tools/tools.h | 1 + tools/vgchange.c | 9 +- tools/vgdisplay.c | 2 +- 33 files changed, 2558 insertions(+), 50 deletions(-) create mode 100644 lib/metadata/replicator_manip.c create mode 100644 lib/replicator/.exported_symbols create mode 100644 lib/replicator/Makefile.in create mode 100644 lib/replicator/replicator.c
PATCH 1/23 Return ECMD_FAILED for break
Return ECMD_FAILED when sigint has been caught.
--- tools/toollib.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
tools/toollib.c +1 -1
@@ -330,7 +330,7 @@ int process_each_lv(struct cmd_context *cmd, int argc, char **argv,if (ret > ret_max) ret_max = ret;if (sigint_caught ()) -break ; +return ECMD_FAILED ; }return ret_max;
Signature · 1 line
1.7.0.1
PATCH 2/23 Add dm_list_splice() for list join.
In reply to Zdenek KabelacIntroduce dm_list_splice() to join two lists.
--- libdm/.exported_symbols | 1 + libdm/datastruct/list.c | 24 +++++++++++++++++++++++- libdm/libdevmapper.h | 5 +++++ 3 files changed, 29 insertions(+), 1 deletions(-)
libdm/.exported_symbols +1 -0
@@ -155,6 +155,7 @@ dm_list_add dm_list_add_h dm_list_del dm_list_move +dm_list_splice dm_list_empty dm_list_start dm_list_end
libdm/datastruct/list.c +23 -1
@@ -1,6 +1,6 @@/* * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. -* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. +* Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved. * * This file is part of LVM2. *
@@ -144,3 +144,25 @@ unsigned int dm_list_size(const struct dm_list *head)return s; } + +/* +* Join two lists together. +* This moves all the elements of the list 'head1' to the end of the list +* 'head', leaving 'head1' empty. +*/ +void dm_list_splice (struct dm_list *head,struct dm_list *head1) +{ +assert (head->n); +assert (head1->n); + +if (dm_list_empty (head1)) +return ; + + head1->p->n = head; + head1->n->p = head->p; + + head->p->n = head1->n; + head->p = head1->p; + +dm_list_init (head1); +}
libdm/libdevmapper.h +5 -0
@@ -718,6 +718,11 @@ void dm_list_del(struct dm_list *elem);void dm_list_move (struct dm_list *head,struct dm_list *elem);/* +* Join 'head1' to the of 'head'. +*/ +void dm_list_splice (struct dm_list *head,struct dm_list *head1); + +/* * Is the list empty? */ int dm_list_empty (const struct dm_list *head);
Signature · 1 line
1.7.0.1
PATCH 3/23 API change for args of process_each_lv_in_vg()
In reply to Zdenek KabelacPatch adds failed_lvnames to the list of parameters for process_each_lv_in_vg(). If the list is not NULL it will be filled with LV names of failing LVs during function execution.
Application could later reiterate only on failed LVs.
--- tools/toollib.c | 14 +++++++++++++- tools/toollib.h | 1 + tools/vgdisplay.c | 2 +- 3 files changed, 15 insertions(+), 2 deletions(-)
tools/toollib.c +13 -1
@@ -86,6 +86,7 @@ int process_each_lv_in_vg(struct cmd_context *cmd,struct volume_group *vg, const struct dm_list *arg_lvnames, const struct dm_list *tags, + struct dm_list *failed_lvnames, void *handle, process_single_lv_fn_t process_single_lv) {
@@ -99,6 +100,9 @@ int process_each_lv_in_vg(struct cmd_context *cmd,struct lv_list *lvl; +if (failed_lvnames) +dm_list_init (failed_lvnames); +if (!vg_check_status (vg,EXPORTED_VG ))return ECMD_FAILED ;
@@ -155,6 +159,14 @@ int process_each_lv_in_vg(struct cmd_context *cmd,continue ; ret =process_single_lv (cmd, lvl->lv, handle); +if (ret !=ECMD_PROCESSED && failed_lvnames) { +if (!str_list_add (cmd->mem, failed_lvnames, +dm_pool_strdup (cmd->mem, + lvl->lv->name))) { +log_error ("Allocation failed for str_list." ); +return ECMD_FAILED ; + } + }if (ret > ret_max) ret_max = ret;if (sigint_caught ())
@@ -325,7 +337,7 @@ int process_each_lv(struct cmd_context *cmd, int argc, char **argv, } ret =process_each_lv_in_vg (cmd, vg, &lvnames, tags_arg, - handle, process_single_lv); +NULL , handle, process_single_lv);unlock_and_release_vg (cmd, vg, vgname);if (ret > ret_max) ret_max = ret;
tools/toollib.h +1 -0
@@ -78,6 +78,7 @@ int process_each_lv_in_vg(struct cmd_context *cmd,struct volume_group *vg, const struct dm_list *arg_lvnames, const struct dm_list *tags, + struct dm_list *failed_lvnames, void *handle, process_single_lv_fn_t process_single_lv);
tools/vgdisplay.c +1 -1
@@ -37,7 +37,7 @@ static int vgdisplay_single(struct cmd_context *cmd, const char *vg_name,if (arg_count (cmd, verbose_ARG)) {vgdisplay_extents (vg); -process_each_lv_in_vg (cmd, vg,NULL ,NULL ,NULL , +process_each_lv_in_vg (cmd, vg,NULL ,NULL ,NULL ,NULL , (process_single_lv_fn_t )lvdisplay_full);log_print ("--- Physical volumes ---" );
Signature · 1 line
1.7.0.1
PATCH 4/23 Replicator: libdm support
In reply to Zdenek KabelacIntroducing new API calls:dm_tree_node_add_replicator_target()dm_tree_node_add_replicator_dev_target().
Define new typedef dm_replicator_mode_t.
--- libdm/.exported_symbols | 2 + libdm/libdevmapper.h | 35 ++++++ libdm/libdm-deptree.c | 296 ++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 328 insertions(+), 5 deletions(-)
libdm/.exported_symbols +2 -0
@@ -80,6 +80,8 @@ dm_tree_node_add_crypt_target dm_tree_node_add_mirror_target dm_tree_node_add_mirror_target_log dm_tree_node_add_target_area +dm_tree_node_add_replicator_target +dm_tree_node_add_replicator_dev_target dm_tree_node_set_read_ahead dm_tree_skip_lockfs dm_tree_use_no_flush_suspend
libdm/libdevmapper.h +35 -0
@@ -439,6 +439,41 @@ int dm_tree_node_add_mirror_target_log(struct dm_tree_node *node,const char *log_uuid, unsigned area_count, uint32_t flags); + +/* +* Replicator operation mode +* Note: API for Replicator is not yet stable +*/ +typedef enum { +DM_REPLICATOR_SYNC ,/* Synchronous replication */ +DM_REPLICATOR_ASYNC_WARN ,/* Warn if async replicator is slow */ +DM_REPLICATOR_ASYNC_STALL ,/* Stall replicator if not fast enough */ +DM_REPLICATOR_ASYNC_DROP ,/* Drop sites out of sync */ +DM_REPLICATOR_ASYNC_FAIL ,/* Fail replicator if slow */ +NUM_DM_REPLICATOR_MODES +}dm_replicator_mode_t ; + +int dm_tree_node_add_replicator_target (struct dm_tree_node *node, +uint64_t size, +const char *rlog_uuid, +const char *rlog_type, +unsigned rsite_index, +dm_replicator_mode_t mode, +uint32_t async_timeout, +uint64_t fall_behind_data, +uint32_t fall_behind_ios); + +int dm_tree_node_add_replicator_dev_target (struct dm_tree_node *node, +uint64_t size, +const char *replicator_uuid,/* Replicator control device */ +uint64_t rdevice_index, +const char *rdev_uuid,/* Rimage device name/uuid */ +unsigned rsite_index, +const char *slog_uuid, +uint32_t slog_flags,/* Mirror log flags */ +uint32_t slog_region_size); +/* End of Replicator API */ + int dm_tree_node_add_target_area(struct dm_tree_node *node, const char *dev_name, const char *dlid,
libdm/libdm-deptree.c +291 -5
379 lines not on this page · raw message
Signature · 1 line
1.7.0.1
PATCH 5/23 Replicator: suspend/deactivate replicator
In reply to Zdenek KabelacIntroducing dm_tree_set_suspend_priority() for suspending replicator control target before deactivation of replicator-dev target.
This patch presents no functional change to current dtree - only replicator target currently sets higher suspend priority for some of its nodes.
--- libdm/.exported_symbols | 1 + libdm/libdevmapper.h | 2 + libdm/libdm-deptree.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 0 deletions(-)
libdm/.exported_symbols +1 -0
@@ -82,6 +82,7 @@ dm_tree_node_add_mirror_target_log dm_tree_node_add_target_area dm_tree_node_add_replicator_target dm_tree_node_add_replicator_dev_target +dm_tree_set_suspend_priority dm_tree_node_set_read_ahead dm_tree_skip_lockfs dm_tree_use_no_flush_suspend
libdm/libdevmapper.h +2 -0
@@ -474,6 +474,8 @@ int dm_tree_node_add_replicator_dev_target(struct dm_tree_node *node, uint32_t slog_region_size);/* End of Replicator API */ +int dm_tree_set_suspend_priority (struct dm_tree *dtree,const char *uuid,int priority); + int dm_tree_node_add_target_area(struct dm_tree_node *node, const char *dev_name, const char *dlid,
libdm/libdm-deptree.c +62 -0
86 lines not on this page · raw message
Signature · 1 line
1.7.0.1
PATCH 6/23 Replicator: lvm2 support
In reply to Zdenek KabelacAdding configure.in support for Replicators. Adding basic lib lvm support for Replicators. Adding flags REPLICATOR and REPLICATOR_LOG. Adding segments SEG_REPLICATOR and SEG_REPLICATOR_DEV. Adding basic methods for handling replicator metadata.
--- configure.in | 17 + lib/Makefile.in | 10 + lib/commands/toolcontext.c | 5 + lib/format_text/flags.c | 2 + lib/metadata/lv_manip.c | 1 + lib/metadata/merge.c | 14 + lib/metadata/metadata-exported.h | 74 ++++- lib/metadata/replicator_manip.c | 327 ++++++++++++++++ lib/metadata/segtype.h | 8 + lib/replicator/.exported_symbols | 1 + lib/replicator/Makefile.in | 25 ++ lib/replicator/replicator.c | 790 ++++++++++++++++++++++++++++++++++++++ 12 files changed, 1273 insertions(+), 1 deletions(-) create mode 100644 lib/metadata/replicator_manip.c create mode 100644 lib/replicator/.exported_symbols create mode 100644 lib/replicator/Makefile.in create mode 100644 lib/replicator/replicator.c
configure.in +17 -0
@@ -303,6 +303,21 @@ if test x$MIRRORS = xinternal; then fi ################################################################################ +dnl -- asynchronous volume replicator inclusion type +AC_MSG_CHECKING(whether to include replicators) +AC_ARG_WITH(replicators, AC_HELP_STRING([--with-replicators=TYPE], + [Replicator support: internal/shared/none [TYPE=none] ]), + [REPLICATORS=$withval], [REPLICATORS="none"]) +AC_MSG_RESULT($REPLICATORS) + +case "$REPLICATORS" in + none|shared) ;; + internal) AC_DEFINE([REPLICATOR_INTERNAL], 1, + [Define to 1 to include built-in support for replicators.]) ;; + *) AC_MSG_ERROR([--with-replicators parameter invalid ($REPLICATORS)]) ;; +esac + +################################################################################ dnl -- Disable readline AC_MSG_CHECKING(whether to enable readline) AC_ARG_ENABLE([readline],
@@ -1104,6 +1119,7 @@ AC_SUBST(LVM_PATCHLEVEL) AC_SUBST(LVM_RELEASE) AC_SUBST(LVM_RELEASE_DATE) AC_SUBST(MIRRORS) +AC_SUBST(REPLICATORS) AC_SUBST(MSGFMT) AC_SUBST(PKGCONFIG) AC_SUBST(POOL)
@@ -1156,6 +1172,7 @@ lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile +lib/replicator/Makefile lib/misc/lvm-version.h lib/snapshot/Makefile libdm/Makefile
lib/Makefile.in +10 -0
@@ -32,6 +32,10 @@ ifeq ("@MIRRORS@", "shared") SUBDIRS += mirror endif +ifeq ("@REPLICATORS@", "shared") + SUBDIRS += replicator +endif + SOURCES =\ activate/activate.c \ cache/lvmcache.c \
@@ -74,6 +78,7 @@ SOURCES =\ metadata/mirror.c \ metadata/pv_manip.c \ metadata/pv_map.c \ + metadata/replicator_manip.c \ metadata/segtype.c \ metadata/snapshot_manip.c \ misc/crc.c \
@@ -129,6 +134,10 @@ ifeq ("@MIRRORS@", "internal") SOURCES += mirror/mirrored.c endif +ifeq ("@REPLICATORS@", "internal") + SOURCES += replicator/replicator.c +endif + ifeq ("@DEVMAPPER@", "yes") SOURCES +=\ activate/dev_manager.c \
@@ -155,6 +164,7 @@ ifeq ($(MAKECMDGOALS),distclean) format_pool \ snapshot \ mirror \ + replicator \ locking endif
lib/commands/toolcontext.c +5 -0
@@ -917,6 +917,11 @@ static int _init_segtypes(struct cmd_context *cmd)dm_list_add (&cmd->segtypes, &segtype->list);#endif +#ifdef REPLICATOR_INTERNAL +if (!init_replicator_segtype (&seglib)) +return 0 ; +#endif +#ifdef HAVE_LIBDL /* Load any formats in shared libs unless static */ if (!is_static() &&
lib/format_text/flags.c +2 -0
@@ -67,6 +67,8 @@ static const struct flag _lv_flags[] = { {PARTIAL_LV, NULL, 0}, {POSTORDER_FLAG, NULL, 0}, {VIRTUAL_ORIGIN, NULL, 0}, + {REPLICATOR, NULL, 0}, + {REPLICATOR_LOG, NULL, 0}, {0, NULL, 0} };
lib/metadata/lv_manip.c +1 -0
@@ -2008,6 +2008,7 @@ struct logical_volume *alloc_lv(struct dm_pool *mem)dm_list_init (&lv->segments);dm_list_init (&lv->tags);dm_list_init (&lv->segs_using_this_lv); +dm_list_init (&lv->rsites);return lv; }
lib/metadata/merge.c +14 -0
@@ -72,6 +72,8 @@ int check_lv_segments(struct logical_volume *lv, int complete_vg)uint32_t area_multiplier, s;struct seg_list *sl;int error_count =0 ; +struct replicator_site *rsite; +struct replicator_device *rdev; dm_list_iterate_items(seg, &lv->segments) { seg_count++;
@@ -213,6 +215,18 @@ int check_lv_segments(struct logical_volume *lv, int complete_vg)if (lv ==seg_lv (seg, s)) seg_found++; } +if (seg_is_replicator_dev (seg)) { + dm_list_iterate_items(rsite, &seg->replicator->rsites) { + dm_list_iterate_items(rdev, &rsite->rdevices) { +if (lv == rdev->lv || lv == rdev->slog) + seg_found++; + } + } +if (lv == seg->replicator) + seg_found++; + } +if (seg_is_replicator (seg) && lv == seg->rlog_lv) + seg_found++;if (seg->log_lv == lv) seg_found++;if (!seg_found) {
lib/metadata/metadata-exported.h +73 -1
110 lines not on this page · raw message
lib/metadata/replicator_manip.c new file +327 -0
327 lines not on this page · raw message
lib/metadata/segtype.h +8 -0
@@ -35,9 +35,13 @@ struct dev_manager;#define SEG_VIRTUAL 0x00000020U#define SEG_CANNOT_BE_ZEROED 0x00000040U#define SEG_MONITORED 0x00000080U +#define SEG_REPLICATOR 0x00000100U +#define SEG_REPLICATOR_DEV 0x00000200U#define SEG_UNKNOWN 0x80000000U#define seg_is_mirrored (seg) ((seg)->segtype->flags & SEG_AREAS_MIRRORED ? 1 : 0) +#define seg_is_replicator (seg) ((seg)->segtype->flags & SEG_REPLICATOR ? 1 : 0) +#define seg_is_replicator_dev (seg) ((seg)->segtype->flags & SEG_REPLICATOR_DEV ? 1 : 0)#define seg_is_striped (seg) ((seg)->segtype->flags & SEG_AREAS_STRIPED ? 1 : 0)#define seg_is_snapshot (seg) ((seg)->segtype->flags & SEG_SNAPSHOT ? 1 : 0)#define seg_is_virtual (seg) ((seg)->segtype->flags & SEG_VIRTUAL ? 1 : 0)
@@ -110,6 +114,10 @@ struct segment_type *init_error_segtype(struct cmd_context *cmd);struct segment_type *init_free_segtype (struct cmd_context *cmd);struct segment_type *init_unknown_segtype (struct cmd_context *cmd,const char *name); +#ifdef REPLICATOR_INTERNAL +int init_replicator_segtype (struct segtype_library *seglib); +#endif +#ifdef SNAPSHOT_INTERNAL struct segment_type *init_snapshot_segtype (struct cmd_context *cmd);#endif
lib/replicator/.exported_symbols new file +1 -0
@@ -0,0 +1 @@ +init_segtype
lib/replicator/Makefile.in new file +25 -0
@@ -0,0 +1,25 @@ +# +# Copyright (C) 2009-2010 Red Hat, Inc. All rights reserved. +# +# This file is part of LVM2. +# +# This copyrighted material is made available to anyone wishing to use, +# modify, copy, or redistribute it subject to the terms and conditions +# of the GNU General Public License v.2. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +top_builddir = @top_builddir@ + +SOURCES = replicator.c + +LIB_SHARED = liblvm2replicator.$(LIB_SUFFIX) +LIB_VERSION = $(LIB_VERSION_LVM) + +include $(top_builddir)/make.tmpl + +install: install_lib_shared_plugin
lib/replicator/replicator.c new file +790 -0
790 lines not on this page · raw message
Signature · 1 line
1.7.0.1
PATCH 7/23 Replicator: check replicator segment
In reply to Zdenek KabelacCheck for possible problems within replicator structures. Used also by vg_validate.
--- lib/metadata/merge.c | 3 + lib/metadata/metadata.h | 6 ++ lib/metadata/replicator_manip.c | 152 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 161 insertions(+), 0 deletions(-)
lib/metadata/merge.c +3 -0
@@ -137,6 +137,9 @@ int check_lv_segments(struct logical_volume *lv, int complete_vg) } } +if (seg_is_replicator (seg) && !check_replicator_segment (seg)) + inc_error_count; +for (s =0 ; s < seg->area_count; s++) {if (seg_type (seg, s) ==AREA_UNASSIGNED ) { log_error("LV %s: segment %u has unassigned "
lib/metadata/metadata.h +6 -0
@@ -321,6 +321,12 @@ struct logical_volume *alloc_lv(struct dm_pool *mem);*/ int check_lv_segments (struct logical_volume *lv,int complete_vg); + +/* +* Checks that a replicator segment is correct. +*/ +int check_replicator_segment (const struct lv_segment *replicator_seg); +/* * Sometimes (eg, after an lvextend), it is possible to merge two * adjacent segments into a single segment. This function trys
lib/metadata/replicator_manip.c +152 -0
158 lines not on this page · raw message
Signature · 1 line
1.7.0.1
PATCH 8/23 Replicator: extend _lv_each_dependency() rep. deps
In reply to Zdenek Kabelac--- lib/metadata/metadata.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-)
lib/metadata/metadata.c +4 -0
@@ -1983,6 +1983,8 @@ static int _lv_each_dependency(struct logical_volume *lv,struct lv_segment *lvseg;struct logical_volume *deps[] = { + (lv->rdevice && lv != lv->rdevice->lv) ? lv->rdevice->lv :0 , + (lv->rdevice && lv != lv->rdevice->slog) ? lv->rdevice->slog :0 , lv->snapshot ? lv->snapshot->origin :0 , lv->snapshot ? lv->snapshot->cow :0 };for (i =0 ; i <sizeof (deps) /sizeof (*deps); ++i) {
@@ -1993,6 +1995,8 @@ static int _lv_each_dependency(struct logical_volume *lv, dm_list_iterate_items(lvseg, &lv->segments) {if (lvseg->log_lv && !fn (lvseg->log_lv, data)) return_0; +if (lvseg->rlog_lv && !fn (lvseg->rlog_lv, data)) + return_0;for (s =0 ; s < lvseg->area_count; ++s) {if (seg_type (lvseg, s) ==AREA_LV && !fn (seg_lv (lvseg,s), data)) return_0;
Signature · 1 line
1.7.0.1
PATCH 9/23 Replicator: extend volume_group with list of VGs
In reply to Zdenek KabelacAdd pointer to linked list of opened VGs. List temporarily keeps the information about needed or locked and opened VGs for replicator target. Also add cmd_missing_vgs status information for quick check and also for possible continuos process_each_lv() where we need
to detect whether failure has been caused by missing VG or
some other reason.
--- lib/metadata/metadata-exported.h | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)
lib/metadata/metadata-exported.h +2 -0
@@ -223,6 +223,8 @@ struct volume_group {struct cmd_context *cmd;struct dm_pool *vgmem;struct format_instance *fid; +struct dm_list *cmd_vgs;/* List of wanted/locked and opened VGs */ +uint32_t cmd_missing_vgs;uint32_t seqno;/* Metadata sequence number */ alloc_policy_t alloc;
Signature · 1 line
1.7.0.1
PATCH 10/23 Replicator: add sorted cmd_vg list
In reply to Zdenek KabelacIntroduce struct cmd_vg to store information about needed volume group name, vgid, flags and the pointer to opened VG.
Keep VGs list in alphabetical order for locking order.
Introduce functions:cmd_vg_add() add new cmd_vg entry.cmd_vg_lookup() search cmd_vgs for vg_name.cmd_vg_read() open VGs in cmd_vgs list.cmd_vg_release() close VGs in reversed order.
--- lib/metadata/metadata-exported.h | 16 +++++ lib/metadata/replicator_manip.c | 125 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 141 insertions(+), 0 deletions(-)
lib/metadata/metadata-exported.h +16 -0
@@ -298,6 +298,15 @@ struct lv_segment_area {struct segment_type ; +/* List with vg_name, vgid and flags */ +struct cmd_vg { +struct dm_list list; +const char *vg_name; +const char *vgid; +uint32_t flags; +struct volume_group *vg; +}; +/* ++ Replicator datatypes */ typedef enum { REPLICATOR_STATE_PASSIVE,
@@ -792,6 +801,13 @@ int lv_is_rlog(const struct logical_volume *lv);int lv_is_slog (const struct logical_volume *lv);struct logical_volume *first_replicator_dev (const struct logical_volume *lv);/* -- metadata/replicator_manip.c */ +struct cmd_vg *cmd_vg_add (struct dm_pool *mem,struct dm_list *cmd_vgs, +const char *vg_name,const char *vgid, +uint32_t flags); +struct cmd_vg *cmd_vg_lookup (struct dm_list *cmd_vgs, +const char *vg_name,const char *vgid); +int cmd_vg_read (struct cmd_context *cmd,struct dm_list *cmd_vgs); +void cmd_vg_release (struct dm_list *cmd_vgs);struct logical_volume *find_pvmove_lv (struct volume_group *vg,struct device *dev,uint32_t lv_type);
lib/metadata/replicator_manip.c +125 -0
134 lines not on this page · raw message
Signature · 1 line
1.7.0.1
PATCH 11/23 Replicator: add find_replicator_vgs
In reply to Zdenek KabelacAdding function find_replicator_vgs() to find all needed VGs for replicator.
This function is later called before taking lock_vol().
--- lib/metadata/metadata-exported.h | 2 ++ lib/metadata/replicator_manip.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 0 deletions(-)
lib/metadata/metadata-exported.h +2 -0
@@ -809,6 +809,8 @@ struct cmd_vg *cmd_vg_lookup(struct dm_list *cmd_vgs,int cmd_vg_read (struct cmd_context *cmd,struct dm_list *cmd_vgs);void cmd_vg_release (struct dm_list *cmd_vgs); +int find_replicator_vgs (struct logical_volume *lv); +struct logical_volume *find_pvmove_lv (struct volume_group *vg,struct device *dev,uint32_t lv_type); struct logical_volume *find_pvmove_lv_from_pvname(struct cmd_context *cmd,
lib/metadata/replicator_manip.c +32 -0
@@ -602,3 +602,35 @@ void cmd_vg_release(struct dm_list *cmd_vgs) cvl->vg =NULL ; } } + +/** +* Find all needed remote VGs for processing given LV. +* Missing VGs are added to VG's vgs list. +*/ +int find_replicator_vgs (struct logical_volume *lv) +{ +struct replicator_site *rsite; +int ret =1 ; + +if (!lv_is_replicator_dev (lv)) +return 1 ; + + dm_list_iterate_items(rsite, &first_seg(lv)->replicator->rsites) { +if (!rsite->vg_name || !lv->vg->cmd_vgs || +cmd_vg_lookup (lv->vg->cmd_vgs, rsite->vg_name,NULL )) +continue ; + ret =0 ; +/* Using cmd memory pool for cmd_vg list allocation */ +if (!cmd_vg_add (lv->vg->cmd->mem, lv->vg->cmd_vgs, + rsite->vg_name,NULL ,0 )) { + lv->vg->cmd_missing_vgs =0 ;/* do not retry */ + stack; +break ; + } + +log_debug ("VG: %s added as missing." , rsite->vg_name); + lv->vg->cmd_missing_vgs++; + } + +return ret; +}
Signature · 1 line
1.7.0.1
PATCH 12/23 Replicator: add read and release VGs for rsites
In reply to Zdenek KabelacAdd function to read and release remote VGs for replicator sites in activation context.
--- lib/metadata/metadata-exported.h | 3 ++ lib/metadata/replicator_manip.c | 56 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 0 deletions(-)
lib/metadata/metadata-exported.h +3 -0
@@ -811,6 +811,9 @@ void cmd_vg_release(struct dm_list *cmd_vgs);int find_replicator_vgs (struct logical_volume *lv); +int lv_read_replicator_vgs (struct logical_volume *lv); +void lv_release_replicator_vgs (struct logical_volume *lv); +struct logical_volume *find_pvmove_lv (struct volume_group *vg,struct device *dev,uint32_t lv_type); struct logical_volume *find_pvmove_lv_from_pvname(struct cmd_context *cmd,
lib/metadata/replicator_manip.c +56 -0
59 lines not on this page · raw message
Signature · 1 line
1.7.0.1
PATCH 13/23 Replicator: use cmd_vg list for _process_one_vg()
In reply to Zdenek KabelacPatch modifes behavior of _process_one_vg().
In the first pass vg_read() collect for replicator sorted list of additional VGs during lock_vol().
If any VG needed by a replicator is not yet opened then next iteration loop is taken with all collected VGs.
Flag vg->cmd_missing_vgs detects missing VGs.
--- tools/toollib.c | 55 ++++++++++++++++++++++++++++++++----------------------- 1 files changed, 32 insertions(+), 23 deletions(-)
tools/toollib.c +32 -23
@@ -433,37 +433,46 @@ static int _process_one_vg(struct cmd_context *cmd, const char *vg_name, uint32_t flags, void *handle, int ret_max, process_single_vg_fn_t process_single_vg) { - struct volume_group *vg; + struct dm_list cmd_vgs; +struct cmd_vg *cvl_vg;int ret =0 ;log_verbose ("Finding volume group \"%s\"" , vg_name); - vg =vg_read (cmd, vg_name, vgid, flags); -/* Allow FAILED_INCONSISTENT through only for vgcfgrestore */ -if (vg_read_error (vg) && - !((vg_read_error (vg) ==FAILED_INCONSISTENT ) && - (flags &READ_ALLOW_INCONSISTENT ))) { - ret_max =ECMD_FAILED ; - goto_out; - } +dm_list_init (&cmd_vgs); +if (!(cvl_vg =cmd_vg_add (cmd->mem, &cmd_vgs, vg_name, vgid, flags))) + return_0; + +while (!sigint_caught ()) { +if (!cmd_vg_read (cmd, &cmd_vgs)) +/* Allow FAILED_INCONSISTENT through only for vgcfgrestore */ +if (vg_read_error (cvl_vg->vg) && + (!((flags &READ_ALLOW_INCONSISTENT ) && + (vg_read_error (cvl_vg->vg) ==FAILED_INCONSISTENT )))) { + ret =ECMD_FAILED ; +break ; + } + +if (!dm_list_empty (tags) && +/* Only process if a tag matches or it's on arg_vgnames */ + !str_list_match_item (arg_vgnames, vg_name) && + !str_list_match_list (tags, &cvl_vg->vg->tags)) +break ; -if (!dm_list_empty (tags)) { -/* Only process if a tag matches or it's on arg_vgnames */ -if (!str_list_match_item (arg_vgnames, vg_name) && - !str_list_match_list (tags, &vg->tags)) - goto out; + ret =process_single_vg (cmd, vg_name, cvl_vg->vg, handle); + +if (vg_read_error (cvl_vg->vg))/* FAILED_INCONSISTENT */ +break ; + +if (!cvl_vg->vg->cmd_missing_vgs) +break ; + +cmd_vg_release (&cmd_vgs); } -if ((ret =process_single_vg (cmd, vg_name, vg, - handle)) > ret_max) - ret_max = ret; +cmd_vg_release (&cmd_vgs); -out: -if (vg_read_error (vg)) -vg_release (vg); -else -unlock_and_release_vg (cmd, vg, vg_name); -return ret_max; +return (ret > ret_max) ? ret : ret_max; } int process_each_vg(struct cmd_context *cmd, int argc, char **argv,
Signature · 1 line
1.7.0.1
PATCH 14/23 Replicator: use cmd_vg for process_each_lv_in_vg()
In reply to Zdenek KabelacAs for _process_one_vg() we need similar retry loop for process_each_lv_in_vg(). This patch retries to process failed LVs with reopened VGs.
Patch does not add any extra repeated invocations if there is not found any missing VG during LV processing.
--- tools/toollib.c | 45 ++++++++++++++++++++++++++++++++++++--------- 1 files changed, 36 insertions(+), 9 deletions(-)
tools/toollib.c +36 -9
@@ -158,6 +158,7 @@ int process_each_lv_in_vg(struct cmd_context *cmd,if (!process_lv)continue ; + lvl->lv->vg->cmd_missing_vgs =0 ; ret =process_single_lv (cmd, lvl->lv, handle); if (ret != ECMD_PROCESSED && failed_lvnames) { if (!str_list_add(cmd->mem, failed_lvnames,
@@ -166,6 +167,8 @@ int process_each_lv_in_vg(struct cmd_context *cmd,log_error ("Allocation failed for str_list." );return ECMD_FAILED ; } +if (lvl->lv->vg->cmd_missing_vgs) + ret =ECMD_PROCESSED ; }if (ret > ret_max) ret_max = ret;
@@ -193,7 +196,9 @@ int process_each_lv(struct cmd_context *cmd, int argc, char **argv,struct dm_list *tags_arg;struct dm_list *vgnames;/* VGs to process */ struct str_list *sll, *strl; -struct volume_group *vg; +struct cmd_vg *cvl_vg; +struct dm_list cmd_vgs; +struct dm_list failed_lvnames;struct dm_list tags, lvnames;struct dm_list arg_lvnames;/* Cmdline vgname or vgname/lvname */ char *vglv;
@@ -203,6 +208,7 @@ int process_each_lv(struct cmd_context *cmd, int argc, char **argv,dm_list_init (&tags);dm_list_init (&arg_lvnames); +dm_list_init (&failed_lvnames);if (argc) {struct dm_list arg_vgnames;
@@ -298,13 +304,17 @@ int process_each_lv(struct cmd_context *cmd, int argc, char **argv, } } - vg =NULL ; dm_list_iterate_items(strl, vgnames) { vgname = strl->str; - vg =vg_read (cmd, vgname,NULL , flags); +dm_list_init (&cmd_vgs); +if (!(cvl_vg =cmd_vg_add (cmd->mem, &cmd_vgs, + vgname,NULL , flags))) { + stack; +return ECMD_FAILED ; + } -if (vg_read_error (vg)) { -vg_release (vg); +if (!cmd_vg_read (cmd, &cmd_vgs)) { +cmd_vg_release (&cmd_vgs);if (ret_max <ECMD_FAILED ) {log_error ("Skipping volume group %s" , vgname); ret_max =ECMD_FAILED ;
@@ -330,17 +340,34 @@ int process_each_lv(struct cmd_context *cmd, int argc, char **argv, dm_pool_strdup(cmd->mem, lv_name + 1))) {log_error ("strlist allocation failed" ); -unlock_and_release_vg (cmd, vg, vgname); +cmd_vg_release (&cmd_vgs);return ECMD_FAILED ; } } } - ret =process_each_lv_in_vg (cmd, vg, &lvnames, tags_arg, -NULL , handle, process_single_lv); -unlock_and_release_vg (cmd, vg, vgname); +while (!sigint_caught ()) { + ret =process_each_lv_in_vg (cmd, cvl_vg->vg, &lvnames, + tags_arg, &failed_lvnames, + handle, process_single_lv); +if (ret !=ECMD_PROCESSED || +dm_list_empty (&failed_lvnames)) +break ; + +/* Try again with failed LVs in this VG */ +dm_list_init (&lvnames); +dm_list_splice (&lvnames, &failed_lvnames); + +cmd_vg_release (&cmd_vgs); +if (!cmd_vg_read (cmd, &cmd_vgs)) { + ret =ECMD_FAILED ;/* break */ +break ; + } + }if (ret > ret_max) ret_max = ret; + +cmd_vg_release (&cmd_vgs);if (sigint_caught ())return ECMD_FAILED ; }
Signature · 1 line
1.7.0.1
PATCH 15/23 Replicator: lock_vol() finds missing VGs
In reply to Zdenek KabelacFind and check for all needed VGs before calling lock_vol().
--- lib/locking/locking.h | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-)
lib/locking/locking.h +3 -1
@@ -129,7 +129,9 @@ int check_lvm1_vg_inactive(struct cmd_context *cmd, const char *vgname); (vg_is_clustered((lv)->vg) ? LCK_CLUSTER_VG : 0)#define lock_lv_vol (cmd, lv, flags) \ - lock_vol(cmd, (lv)->lvid.s, flags | LCK_LV_CLUSTERED(lv)) + (find_replicator_vgs((lv)) ? \ + lock_vol(cmd, (lv)->lvid.s, flags | LCK_LV_CLUSTERED(lv)) : \ + 0)#define unlock_vg (cmd, vol) lock_vol(cmd, vol, LCK_VG_UNLOCK)#define unlock_and_release_vg (cmd, vg, vol) \
Signature · 1 line
1.7.0.1
PATCH 16/23 Replicator: activate checks for missing vgs
In reply to Zdenek KabelacActivation needs to have all remote VGs locked to pass for replicator.
--- lib/activate/activate.c | 21 ++++++++++++++++++--- 1 files changed, 18 insertions(+), 3 deletions(-)
lib/activate/activate.c +18 -3
@@ -865,6 +865,9 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s, goto out; } +if (!lv_read_replicator_vgs (lv)) + goto_out; +lv_calculate_readahead (lv,NULL );/* If VG was precommitted, preload devices for the LV */
@@ -894,8 +897,10 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s, out:if (lv_pre)vg_release (lv_pre->vg); -if (lv) +if (lv) { +lv_release_replicator_vgs (lv);vg_release (lv->vg); + }return r; }
@@ -1025,6 +1030,9 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s) goto_out; } +if (!lv_read_replicator_vgs (lv)) + goto_out; +lv_calculate_readahead (lv,NULL );if (!monitor_dev_for_events (cmd, lv,0 ))
@@ -1038,8 +1046,10 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)if (!lv_info (cmd, lv, &info,1 ,0 ) || info.exists) r =0 ; out: -if (lv) +if (lv) { +lv_release_replicator_vgs (lv);vg_release (lv->vg); + }return r; }
@@ -1118,6 +1128,9 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s, goto out; } +if (!lv_read_replicator_vgs (lv)) + goto_out; +lv_calculate_readahead (lv,NULL );if (exclusive)
@@ -1133,8 +1146,10 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s, stack; out: -if (lv) +if (lv) { +lv_release_replicator_vgs (lv);vg_release (lv->vg); + }return r; }
Signature · 1 line
1.7.0.1
PATCH 17/23 Replicator: update _create_partial_dtree()
In reply to Zdenek KabelacAdding function _create_partial_replicator() to create partial tree for Replicator target.
Using dm_tree_set_suspend_priority() for Replicator.
--- lib/activate/dev_manager.c | 76 ++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 76 insertions(+), 0 deletions(-)
lib/activate/dev_manager.c +76 -0
@@ -869,6 +869,76 @@ static int _add_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree, strucreturn 1 ; } +/* +* Add replicator devices +* +* Using _add_dev_to_dtree() directly instead of _add_lv_to_dtree() +* to avoid checks with extensions. +*/ +static int _create_partial_replicator (struct dev_manager *dm, +struct dm_tree *dtree, +struct lv_segment *seg) +{ +struct replicator_device *rdev; +struct replicator_site *rsite; +const char *replicator_dlid; + +if (!lv_is_active_replicator_dev (seg->lv)) { +if (!_add_dev_to_dtree (dm, dtree, seg->lv->rdevice->lv, +NULL )) + return_0; +return 1 ; + } + +/* Add all related devs for replicator */ + dm_list_iterate_items(rsite, &seg->replicator->rsites) { + dm_list_iterate_items(rdev, &rsite->rdevices) { +if (rsite->state ==REPLICATOR_STATE_ACTIVE ) { +/* Add _rimage LV */ +if (rdev->lv && + !_add_dev_to_dtree (dm, dtree, + rdev->lv,NULL )) + return_0; + +/* Add replicator-dev LV */ +if (seg->lv != rdev->replicator_dev->lv && + !_add_dev_to_dtree (dm, dtree, + rdev->replicator_dev->lv, +NULL )) + return_0; + } + +if (!rdev->rsite->vg_name) +continue ; + +if (rdev->lv && + !_add_dev_to_dtree (dm, dtree, rdev->lv,NULL )) + return_0; + +if (rdev->slog && + !_add_dev_to_dtree (dm, dtree, rdev->slog,NULL )) + return_0; + + } + } + +/* Add rlog and replicator devices */ +if (first_seg (seg->replicator)->rlog_lv && + !_add_dev_to_dtree (dm, dtree, +first_seg (seg->replicator)->rlog_lv,NULL )) + return_0; +if (!_add_dev_to_dtree (dm, dtree, seg->replicator,NULL )) + return_0; + +/* Set suspend priority for replicator device */ +if (!(replicator_dlid =build_dm_uuid (dm->mem, seg->replicator->lvid.s,NULL ))) + return_0; +if (!dm_tree_set_suspend_priority (dtree, replicator_dlid,1 )) + return_0; + +return 1 ; +} +static struct dm_tree *_create_partial_dtree (struct dev_manager *dm,struct logical_volume *lv) {struct dm_tree *dtree;
@@ -889,6 +959,12 @@ static struct dm_tree *_create_partial_dtree(struct dev_manager *dm, struct logi if (!_add_lv_to_dtree(dm, dtree, dm_list_struct_base(snh, struct lv_segment, origin_list)->cow)) goto_bad; +/* Add any replicator-dev LVs of this LV */ + dm_list_iterate_items(seg, &lv->segments) +if (seg_is_replicator_dev (seg) && + !_create_partial_replicator (dm, dtree, seg)) + goto_bad; +/* Add any LVs used by segments in this LV */ dm_list_iterate_items(seg, &lv->segments)for (s =0 ; s < seg->area_count; s++)
Signature · 1 line
1.7.0.1
PATCH 18/23 Replicator: vg with cmd_missing_vgs does not print
In reply to Zdenek KabelacIf missed VGs do not print message and wait for retry.
--- tools/vgchange.c | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-)
tools/vgchange.c +3 -2
@@ -224,8 +224,9 @@ static int _vgchange_available(struct cmd_context *cmd, struct volume_group *vg) ret =_activate_lvs_in_vg (cmd, vg, available); -log_print ("%d logical volume(s) in volume group \"%s\" now active" , -lvs_in_vg_activated (vg), vg->name); +if (!vg->cmd_missing_vgs) +log_print ("%d logical volume(s) in volume group \"%s\" now active" , +lvs_in_vg_activated (vg), vg->name);return ret; }
Signature · 1 line
1.7.0.1
PATCH 19/23 Replicator: add replicator to dtree
In reply to Zdenek KabelacAdding all replicator related LVs to dtree.
Start of one replicator_dev initiate start of all other related.
--- lib/activate/dev_manager.c | 60 +++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 59 insertions(+), 1 deletions(-)
lib/activate/dev_manager.c +59 -1
@@ -1176,6 +1176,61 @@ static int _add_target_to_dtree(struct dev_manager *dm,static int _add_new_lv_to_dtree (struct dev_manager *dm,struct dm_tree *dtree,struct logical_volume *lv,const char *layer); +/* Add all replicators' LVs from active segment */ +static int _add_replicator_dev_target_to_dtree (struct dev_manager *dm, +struct dm_tree *dtree, +struct lv_segment *seg) +{ +struct replicator_device *rdev; +struct replicator_site *rsite; + +/* Only active replicator */ +if (!lv_is_active_replicator_dev (seg->lv)) { +if (!_add_new_lv_to_dtree (dm, dtree, seg->lv->rdevice->lv,NULL )) + return_0; +return 1 ; + } + +/* Add rlog and replicator nodes */ +if (!seg->replicator || + !first_seg (seg->replicator)->rlog_lv || + !_add_new_lv_to_dtree (dm, dtree, +first_seg (seg->replicator)->rlog_lv,NULL ) || + !_add_new_lv_to_dtree (dm, dtree, seg->replicator,NULL )) + return_0; + +/* Activation of one replicator_dev node activates all other nodes */ + dm_list_iterate_items(rsite, &seg->replicator->rsites) { + dm_list_iterate_items(rdev, &rsite->rdevices) { +if (rdev->lv && + !_add_new_lv_to_dtree (dm, dtree, rdev->lv,NULL )) + return_0; + +if (rdev->slog && + !_add_new_lv_to_dtree (dm, dtree, + rdev->slog,NULL )) + return_0; + } + } +/* Add remaining replicator-dev nodes in the second loop +* to avoid multiple retries for inserting all elements */ + dm_list_iterate_items(rsite, &seg->replicator->rsites) { +if (rsite->state !=REPLICATOR_STATE_ACTIVE ) +continue ; + dm_list_iterate_items(rdev, &rsite->rdevices) { +if (rdev->replicator_dev->lv == seg->lv) +continue ; +if (!rdev->replicator_dev->lv || + !_add_new_lv_to_dtree (dm, dtree, + rdev->replicator_dev->lv, +NULL )) + return_0; + } + } + +return 1 ; +} + static int _add_segment_to_dtree(struct dev_manager *dm, struct dm_tree *dtree, struct dm_tree_node *dnode,
@@ -1206,9 +1261,12 @@ static int _add_segment_to_dtree(struct dev_manager *dm, !_add_new_lv_to_dtree(dm, dtree, seg->log_lv, NULL)) return_0; +if (seg_is_replicator_dev (seg)) { +if (!_add_replicator_dev_target_to_dtree (dm, dtree, seg)) + return_0;/* If this is a snapshot origin, add real LV */ /* If this is a snapshot origin + merging snapshot, add cow + real LV */ -if (lv_is_origin (seg->lv) && !layer) { + }else if (lv_is_origin (seg->lv) && !layer) {if (vg_is_clustered (seg->lv->vg)) {log_error ("Clustered snapshots are not yet supported" );return 0 ;
Signature · 1 line
1.7.0.1
PATCH 20/23 Replicator: do not remove of replicators' LVs
In reply to Zdenek Kabelac--- lib/metadata/lv_manip.c | 9 +++++++++ 1 files changed, 9 insertions(+), 0 deletions(-)
lib/metadata/lv_manip.c +9 -0
@@ -2230,6 +2230,15 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,return 0 ; } +if (lv_is_replicator_dev (lv) || +lv_is_rimage (lv) || +lv_is_rlog (lv) || +lv_is_slog (lv)) { +log_error ("Can't remove logical volume %s used by a " +"replicator." , lv->name); +return 0 ; + } +if (lv->status &LOCKED ) {log_error ("Can't remove locked LV %s" , lv->name);return 0 ;
Signature · 1 line
1.7.0.1
PATCH 21/23 Replicator: activate change for vgchange
In reply to Zdenek KabelacActivate only the first replicator-dev LV, that activates all other related LVs from Replicator.
--- tools/vgchange.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-)
tools/vgchange.c +4 -0
@@ -104,6 +104,10 @@ static int _activate_lvs_in_vg(struct cmd_context *cmd,if ((lv->status &MIRROR_IMAGE ) || (lv->status &MIRROR_LOG ))continue ; +/* Only request activation of the first replicator-dev LV */ +if (lv_is_replicator_dev (lv) && (lv !=first_replicator_dev (lv))) +continue ; +/* Can't deactivate a pvmove LV */ /* FIXME There needs to be a controlled way of doing this */ if (((activate == CHANGE_AN) || (activate == CHANGE_ALN)) &&
Signature · 1 line
1.7.0.1
PATCH 22/23 Replicator: add new options for replicator
In reply to Zdenek KabelacNew options: addsite, delsite, replicator,
replicatorlog, replicatorlogtype.
--- lib/config/defaults.h | 1 + lib/metadata/metadata-exported.h | 1 + tools/args.h | 13 ++++++++ tools/commands.h | 7 ++++ tools/lvcreate.c | 58 +++++++++++++++++++++++++++++++++++++- tools/lvmcmdline.c | 9 ++++++ tools/tools.h | 1 + 7 files changed, 89 insertions(+), 1 deletions(-)
lib/config/defaults.h +1 -0
@@ -108,6 +108,7 @@#define DEFAULT_STRIPE_FILLER "error"#define DEFAULT_MIRROR_REGION_SIZE 512/* KB */ +#define DEFAULT_REPLICATOR_REGION_SIZE 512/* KB */ #define DEFAULT_INTERVAL 15#ifdef READLINE_SUPPORT
lib/metadata/metadata-exported.h +1 -0
@@ -608,6 +608,7 @@ uint64_t extents_from_size(struct cmd_context *cmd, uint64_t size,struct lvcreate_params {/* flags */ int snapshot;/* snap */ +int replicator;/* replicator */ int zero;/* all */ int major;/* all */ int minor;/* all */
tools/args.h +13 -0
@@ -66,6 +66,19 @@ arg(virtualsize_ARG, '\0', "virtualsize", size_mb_arg, 0) arg(noudevsync_ARG, '\0', "noudevsync", NULL, 0) arg(poll_ARG, '\0', "poll", yes_no_arg, 0) arg(stripes_long_ARG, '\0', "stripes", int_arg, 0) +arg(replicator_ARG, '\0', "replicator", NULL, 0) +arg(replicatordev_ARG, '\0', "replicatordev", NULL, 0) +arg(replicatorlog_ARG, '\0', "replicatorlog", NULL, 0) +arg(replicatorlogtype_ARG, '\0', "replicatorlogtype", NULL, 0) +arg(addsite_ARG, '\0', "addsite", site_arg, 0) +arg(delsite_ARG, '\0', "delsite", site_arg, 0) +arg(fallbehinddata_ARG, '\0', "fallbehinddata", size_mb_arg, 0) +arg(fallbehindios_ARG, '\0', "fallbehindios", int_arg, 0) +arg(fallbehindtimeout_ARG, '\0', "fallbehindtimeout", int_arg, 0) +arg(sitemode_ARG, '\0', "sitemode", string_arg, 0) +arg(activesite_ARG, '\0', "activesite", string_arg, 0) +arg(passivesite_ARG, '\0', "passivesite", string_arg, 0) +arg (remotevolumegroup_ARG,'\0' ,"remotevolumegroup" , string_arg,0 ) /* Allow some variations */arg (resizable_ARG,'\0' ,"resizable" , yes_no_arg,0 )
tools/commands.h +7 -0
@@ -62,10 +62,12 @@ xx(lvchange,"lvchange\n" "\t[-A|--autobackup y|n]\n" "\t[-a|--available [e|l]y|n]\n" +"\t[--addsite Site]\n" "\t[--addtag Tag]\n" "\t[--alloc AllocationPolicy]\n" "\t[-C|--contiguous y|n]\n" "\t[-d|--debug]\n" +"\t[--delsite Site]\n" "\t[--deltag Tag]\n" "\t[-f|--force]\n" "\t[-h|--help]\n"
@@ -90,6 +92,7 @@ xx(lvchange, ignorelockingfailure_ARG, ignoremonitoring_ARG, major_ARG, minor_ARG, monitor_ARG, noudevsync_ARG, partial_ARG, permission_ARG, persistent_ARG, poll_ARG, readahead_ARG, resync_ARG, refresh_ARG, addtag_ARG, deltag_ARG, + addsite_ARG, delsite_ARG, test_ARG, yes_ARG) xx(lvconvert,
@@ -164,6 +167,9 @@ xx(lvcreate,"\t[-p|--permission {r|rw}]\n" "\t[-r|--readahead ReadAheadSectors|auto|none]\n" "\t[-R|--regionsize MirrorLogRegionSize]\n" +"\t[--replicator]\n" +"\t[--replicatorlog LogicalVolumeName]\n" +"\t[--replicatorlogtype ringbuffer]\n" "\t[-t|--test]\n" "\t[--type VolumeType]\n" "\t[-v|--verbose]\n"
@@ -202,6 +208,7 @@ xx(lvcreate, mirrorlog_ARG, mirrors_ARG, monitor_ARG, name_ARG, nosync_ARG, noudevsync_ARG, permission_ARG, persistent_ARG, readahead_ARG, regionsize_ARG, size_ARG, snapshot_ARG, stripes_ARG, stripesize_ARG, test_ARG, type_ARG, + replicator_ARG, replicatorlog_ARG, replicatorlogtype_ARG, virtualoriginsize_ARG, virtualsize_ARG, zero_ARG) xx(lvdisplay,
tools/lvcreate.c +57 -1
94 lines not on this page · raw message
tools/lvmcmdline.c +9 -0
@@ -488,6 +488,15 @@ int readahead_arg(struct cmd_context *cmd __attribute((unused)), struct arg *a)return 1 ; } +int site_arg (struct cmd_context *cmd __attribute((unused)),struct arg *a) +{ +char *pos = a->value; +if (!validate_name (pos)) +return 0 ; + +return 1 ; +} +static void __alloc (int size) {if (!(_cmdline.commands =dm_realloc (_cmdline.commands,sizeof (*_cmdline.commands) * size))) {
tools/tools.h +1 -0
@@ -152,6 +152,7 @@ int units_arg(struct cmd_context *cmd, struct arg *a);int segtype_arg (struct cmd_context *cmd,struct arg *a);int alloc_arg (struct cmd_context *cmd,struct arg *a);int readahead_arg (struct cmd_context *cmd,struct arg *a); +int site_arg (struct cmd_context *cmd,struct arg *a);/* we use the enums to access the switches */ unsigned arg_count (const struct cmd_context *cmd,int a);
Signature · 1 line
1.7.0.1
PATCH 23/23 Replicator: man pages for lvcreate, lvchange
In reply to Zdenek KabelacUpdate man pages to cover basic usage of lvcreate and lvchange utility to handle basic replicator funtionality.
Current desriptions shows how to create replicator, add site, add replicated device.
--- man/lvchange.8.in | 56 +++++++++++++++++++++++++++++++++++++++++++++++ man/lvcreate.8.in | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 118 insertions(+), 1 deletions(-)
man/lvchange.8.in +56 -0
@@ -3,10 +3,17 @@ lvchange \- change attributes of a logical volume .SH SYNOPSIS .B lvchange +[\-\-addsite Site] [\-\-addtag Tag] [\-A|\-\-autobackup y|n] [\-a|\-\-available y|n|ey|en|ly|ln] [\-\-alloc AllocationPolicy] [\-C|\-\-contiguous y|n] [\-d|\-\-debug] [\-\-deltag Tag] +[\-\-delsite Site] +[[\-\-fallbehinddata Size[bBsSkKmMgGtTpPeE]] | +[\-\-fallbehindios IOS] | +[\-\-fallbehindtimeout sec]] +[\-\-sitemode [sync|warn|stall|drop|fail] +[[\-\-activesite Site] | [\-\-passivesite Site]] [\-\-resync] [\-h|\-?|\-\-help] [\-\-ignorelockingfailure]
@@ -19,6 +26,7 @@ lvchange \- change attributes of a logical volume [\-p|\-\-permission r|rw] [\-r/\-\-readahead ReadAheadSectors|auto|none] [\-\-refresh] [\-t|\-\-test] +[\-\-remotevolumegroup VolumeGroupName] [\-v|\-\-verbose] LogicalVolumePath [LogicalVolumePath...] .SH DESCRIPTION lvchange allows you to change the attributes of a logical volume
@@ -102,10 +110,58 @@ If the logical volume is active, reload its metadata. This is not necessary in normal operation, but may be useful if something has gone wrong or if you're doing clustering manually without a clustered lock manager. +.TP +.I \-\-addsite +Add new site to given replicator LV. +.TP +.I \-\-delsite +Remove given site from replicator LV. +.TP +.I \-\-fallbehinddata +How many data could get replicator behind. Cannot be mixed +with --fallbehindios or --fallbehindtimeout. +.TP +.I \-\-fallbehindios +How many io operation could be queued in replicator backing store device. +Cannot be mixed with --fallbehinddata or --fallbehindtimeout. +.TP +.I \-\-fallbehindtimeout +How many seconds could be replicator behind actual data. Cannot be mixed +with --fallbehinddata or --fallbehindios. +.TP +.I \-\-sitemode +Select replication mode. Default is Warn. +Sync is synchronous mode. Warn,Stall,Drop,Fail are asynchronous modes. +Warn issues warning when remote site is switched to sync log. +Stall stalls replicator until remote site is back in range. +Drop drops whole remote site, if it get too behind. +Fail whole replicator fails is remote sites gets too behind. +Local site works usually in stall mode. There is no synclog for local +replicated volumes. +.TP +.I \-\-activesite +Marks site as active. Note: Only one site from replicator could be +marked active with actual implementation and this site must be +local site. +.TP +.I \-\-passivesite +Marks site as passive which is default. +.TP +.I \-\-remotevolumegroup +Selects remote volume group for remote site that contains logical volumes +with same names for replication as the volume group for site. Local site +for replicator is assumed if remotevolumegroup is not specified. +.TP .SH Examples "lvchange -pr vg00/lvol1" changes the permission on volume lvol1 in volume group vg00 to be read-only. +"lvchange --addsite NewYork vg00/replicator0" +adds new local site NewYork in replicator vg00/replicator0. + +"lvchange --activesite NewYork vg00/replicator0" +marks site NewYork in replicator vg00/replicator0 as active. + .SH SEE ALSO .BR lvm (8), .BR lvcreate (8),
man/lvcreate.8.in +62 -1
97 lines not on this page · raw message
Signature · 1 line
1.7.0.1
PATCH 1/23 Return ECMD_FAILED for break
In reply to Zdenek KabelacQuoted 1 line · Zdenek Kabelac
Return
ECMD_FAILEDwhen sigint has been caught.
Might seem reasonable, but this condition is also checked in many other places. If we're going to override the return code when a command might have been interrupted before it completed, shouldn't we do it consistently everywhere?
Alasdair
PATCH 2/23 Add dm_list_splice() for list join.
In reply to Zdenek KabelacQuoted 1 line · Zdenek Kabelac
Introduce
dm_list_splice()to join two lists.
Ack.
Alasdair
PATCH 3/23 API change for args of process_each_lv_in_vg()
In reply to Zdenek KabelacQuoted 3 lines · Zdenek Kabelac
Patch adds
failed_lvnamesto the list of parameters forprocess_each_lv_in_vg(). If the list is not NULL it will be filled with LV names of failing LVs during function execution.
Ack.
Quoted 10 lines
+++
b/tools/toollib.ctools/toollib.c +1
-0@@ -86,6 +86,7 @@ int process_each_lv_in_vg(struct cmd_context *cmd,struct volume_group *vg, const struct dm_list *arg_lvnames, const struct dm_list *tags, + struct dm_list *failed_lvnames, void *handle, process_single_lv_fn_t process_single_lv) {
tools/toollib.c int process_each_lv_in_vg(struct cmd_context *cmd, · line 104
Quoted 5 lines
tools/toollib.c +2
-0@@ -99,6 +100,9 @@ int process_each_lv_in_vg(struct cmd_context *cmd,struct lv_list *lvl; +if (failed_lvnames) +dm_list_init (failed_lvnames);
I'd prefer the caller to initialise it, which is what we tend to do elsewhere, so that we don't pass 'undefined' values into functions.
Alasdair
PATCH 5/23 Replicator: suspend/deactivate replicator
In reply to Zdenek Kabelaclibdm/libdm-deptree.c struct dm_tree_node { · line 165
Quoted 2 lines · Zdenek Kabelac
libdm/libdm-deptree.c +1
-0int activation_priority;/* 0 gets activated first */ +int suspend_priority;/* 1 gets suspend first */
Can we make those two work in similar, not opposite, ways?
Alasdair
PATCH 5/23 Replicator: suspend/deactivate replicator
In reply to Zdenek KabelacQuoted 2 lines · Zdenek Kabelac
Introducing
dm_tree_set_suspend_priority()for suspending replicator control target before deactivation of replicator-dev target.
Not keen on this one - need a bit more information as to why we need this, and then why the existing function dm_tree_suspend_children() - perhaps extended with an 'inverted' parameter - is insufficient.
libdm/libdm-deptree.c static int _suspend_node(const char *name, uint32_t major, uint32_t minor, · line 1070
Quoted 4 lines
libdm/libdm-deptree.c +3
-0+static int _suspend_parent (struct dm_tree_node *dnode,const char *uuid_prefix, + if (!dlink->node->suspend_priority) + continue;
Why is this hard-coded only to cope with one value of suspend_priority?
Alasdair
PATCH 1/23 Return ECMD_FAILED for break
In reply to Alasdair G KergonDne 6.5.2010 03:10, Alasdair G Kergon napsal(a):
Quoted 7 lines · Zdenek Kabelac
Quoted 1 line
Return
ECMD_FAILEDwhen sigint has been caught.Might seem reasonable, but this condition is also checked in many other places. If we're going to override the return code when a command might have been interrupted before it completed, shouldn't we do it consistently everywhere?
Yes there are more inconsitencies like this through the code - but in my replicator case I've added 'extra' loop around this interrupt check - thus I've added this fix at this place.
The problem with interrupt check may be possibly bigger - as the semantic is not really clear - should we always return 'error' when Ctrl+C is hit by the user? - maybe we should check for sigint before we actually want to iterate next loop - thus if the 'break' was noticed after processing last loop - we return 'OK' like no break was seen ?
Zdenek
PATCH 3/23 API change for args of process_each_lv_in_vg()
In reply to Alasdair G KergonDne 6.5.2010 03:39, Alasdair G Kergon napsal(a):
Quoted 18 lines · Zdenek Kabelac
Quoted 3 lines
Patch adds
failed_lvnamesto the list of parameters forprocess_each_lv_in_vg(). If the list is not NULL it will be filled with LV names of failing LVs during function execution.Ack.
Quoted 11 lines
+++
b/tools/toollib.ctools/toollib.c +1
-0@@ -86,6 +86,7 @@ int process_each_lv_in_vg(struct cmd_context *cmd,struct volume_group *vg, const struct dm_list *arg_lvnames, const struct dm_list *tags, + struct dm_list *failed_lvnames, void *handle, process_single_lv_fn_t process_single_lv) {@@ -99,6 +100,9 @@ int process_each_lv_in_vg(struct cmd_context *cmd,
Quoted 8 lines
tools/toollib.c int process_each_lv_in_vg(struct cmd_context *cmd, · line 104
Quoted 4 lines
tools/toollib.c +2
-0struct lv_list *lvl; +if (failed_lvnames) +dm_list_init (failed_lvnames);I'd prefer the caller to initialise it, which is what we tend to do elsewhere, so that we don't pass 'undefined' values into functions.
Ok
Zdenek
PATCH 5/23 Replicator: suspend/deactivate replicator
In reply to Alasdair G KergonDne 6.5.2010 03:45, Alasdair G Kergon napsal(a):
Quoted 5 lines · Zdenek Kabelac
libdm/libdm-deptree.c struct dm_tree_node { · line 165
Quoted 2 lines
libdm/libdm-deptree.c +1
-0int activation_priority;/* 0 gets activated first */ +int suspend_priority;/* 1 gets suspend first */ Can we make those two work in similar, not opposite, ways?
Idea behind 'suspend_priority' is not meant as a generic concept - it's rather designed for needs of Replicator target (also that's why original reject name had the replicator in it and after your suggestion a more generic name is used here) - if there will be some future target with similar logic - we could try to figure out probably better logic.
Meanwhile - the difference from activation_priority is there are no levels, it's rather boolean 'true/false' logic (which could go to comment probably) - when false==0 means default - no priority for parent suspend - thus unless explicitly set by dm user (which currently is made only by the Replicator target) the function _suspend_parent() will have no effect on processing.
Zdenek
PATCH 5/23 Replicator: suspend/deactivate replicator
In reply to Alasdair G KergonDne 6.5.2010 03:55, Alasdair G Kergon napsal(a):
Quoted 8 lines · Zdenek Kabelac
Quoted 2 lines
Introducing
dm_tree_set_suspend_priority()for suspending replicator control target before deactivation of replicator-dev target.Not keen on this one - need a bit more information as to why we need this, and then why the existing function
dm_tree_suspend_children()- perhaps extended with an 'inverted' parameter - is insufficient.
With the Replicator we have the logic, which has the use case for both variants (and no other target so far needed this) - thus we need to distinguish between them somehow.
master replicator node (replicator0)
replicator-dev node (lv1)
replicator-dev node (lv2)We may want to either 'remove/suspend' the whole replicator - or just one leg. Thus cutting the leg without suspending master node is valid and supported operation here. So to differentiate between cutting leg or replicator the parent suspend flag is used. That way we may atomically freeze the whole replicator and avoid damage in the ordering of rlogged data.
Quoted 7 lines
libdm/libdm-deptree.c static int _suspend_node(const char *name, uint32_t major, uint32_t minor, · line 1070
Quoted 4 lines
libdm/libdm-deptree.c +3
-0+static int _suspend_parent (struct dm_tree_node *dnode,const char *uuid_prefix, + if (!dlink->node->suspend_priority) + continue;Why is this hard-coded only to cope with one value of
suspend_priority?
As mentioned in previous response - it's rather true/false value - so maybe we could use different name here to avoid confusion with activation_priority which takes numbers ?
Zdenek
PATCH 5/23 Replicator: suspend/deactivate replicator
Quoted 8 lines · Zdenek Kabelac
With the Replicator we have the logic, which has the use case for both variants (and no other target so far needed this) - thus we need to distinguish between them somehow.
master replicator node (replicator0) replicator-dev node (lv1) replicator-dev node (lv2)
Quoted 5 lines
We may want to either 'remove/suspend' the whole replicator - or just one leg. Thus cutting the leg without suspending master node is valid and supported operation here. So to differentiate between cutting leg or replicator the parent suspend flag is used. That way we may atomically freeze the whole replicator and avoid damage in the ordering of rlogged data.
Elsewhere we issue the suspend at the top part of the tree that we wish to suspend. So distinguish the two cases by suspend(replicator0) vs suspend(lv1).
So I'm still not seeing the complete picture/problem here.
Alasdair
PATCH 5/23 Replicator: suspend/deactivate replicator
Dne 6.5.2010 12:14, Alasdair G Kergon napsal(a):
Quoted 15 lines · Zdenek Kabelac
Quoted 8 lines
With the Replicator we have the logic, which has the use case for both variants (and no other target so far needed this) - thus we need to distinguish between them somehow.
master replicator node (replicator0) replicator-dev node (lv1) replicator-dev node (lv2)Quoted 5 lines
We may want to either 'remove/suspend' the whole replicator - or just one leg. Thus cutting the leg without suspending master node is valid and supported operation here. So to differentiate between cutting leg or replicator the parent suspend flag is used. That way we may atomically freeze the whole replicator and avoid damage in the ordering of rlogged data.
Quoted 4 lines
Elsewhere we issue the suspend at the top part of the tree that we wish to suspend. So distinguish the two cases by suspend(replicator0) vs suspend(lv1).
So I'm still not seeing the complete picture/problem here.
IMHO that would mean, that every tool which would need to suspend LV1 would need to know that it must build first the tree for replicator and make this as a two stage function.
i.e. mirror over replicator - I'm not saying it's supported feature at this moment, but from the logic how the dm_tree operates this 'one-pass' solution seems to be a more complex solution.
Of course it could be probably overwritten to use multiple trees generated for each leg separately after the main part of replicator is suspend - but it looks far more complicated compared with this bool suspend_priority flag.
Zdenek