Skip to contentSkip to conversation

Replicator 100428

PATCH New Zdenek Kabelac 2 participants 35 messages Apr 28, 2010 – May 6, 2010 Library code

lore
Share & tools
lore
#0 lore raw

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
#1 lore raw

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
index 393c529..eac63e0 100644
@@ -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
#4 lore raw

PATCH 2/23 Add dm_list_splice() for list join.

In reply to Zdenek Kabelac

Introduce 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
index 73ee5bd..32f664d 100644
@@ -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
index 3d9ca8b..c7a052f 100644
@@ -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
index 0ee23fb..781db12 100644
@@ -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
#6 lore raw

PATCH 3/23 API change for args of process_each_lv_in_vg()

In reply to Zdenek Kabelac

Patch 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
index eac63e0..9aaaa61 100644
@@ -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
index 23ccd86..daab95a 100644
@@ -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
index 29bc7f1..954e456 100644
@@ -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
#9 lore raw

PATCH 4/23 Replicator: libdm support

In reply to Zdenek Kabelac

Introducing 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
index 32f664d..090e633 100644
@@ -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
index 781db12..02f4be0 100644
@@ -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
#10 lore raw

PATCH 5/23 Replicator: suspend/deactivate replicator

In reply to Zdenek Kabelac

Introducing 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
index 090e633..84c216e 100644
@@ -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
index 02f4be0..c1945b3 100644
@@ -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
#17 lore raw

PATCH 6/23 Replicator: lvm2 support

In reply to Zdenek Kabelac

Adding 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
index ed9e631..c6b6a31 100644
@@ -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
index 3498141..ae81040 100644
@@ -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
index 818e452..388c559 100644
@@ -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
index a41dc1a..994adf2 100644
@@ -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
index de97341..5e4a674 100644
@@ -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
index df90743..66ff57b 100644
@@ -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
index 7b31c1d..d352928 100644
@@ -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
new file mode 100644
index 0000000..1c92c6a
@@ -0,0 +1 @@
+init_segtype
lib/replicator/Makefile.in new file +25 -0
new file mode 100644
index 0000000..ac42730
@@ -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
#18 lore raw

PATCH 7/23 Replicator: check replicator segment

In reply to Zdenek Kabelac

Check 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
index 66ff57b..3b8895c 100644
@@ -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
index 782d300..7177070 100644
@@ -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
#19 lore raw

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
index 16d80a2..fb829d5 100644
@@ -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
#20 lore raw

PATCH 9/23 Replicator: extend volume_group with list of VGs

In reply to Zdenek Kabelac

Add 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
index 37588aa..da1a230 100644
@@ -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
#21 lore raw

PATCH 10/23 Replicator: add sorted cmd_vg list

In reply to Zdenek Kabelac

Introduce 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
index da1a230..c5a31d6 100644
@@ -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
#22 lore raw

PATCH 11/23 Replicator: add find_replicator_vgs

In reply to Zdenek Kabelac

Adding 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
index c5a31d6..4c70626 100644
@@ -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
index 82ce23c..abd34b3 100644
@@ -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
#23 lore raw

PATCH 12/23 Replicator: add read and release VGs for rsites

In reply to Zdenek Kabelac

Add 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
index 4c70626..09c83a4 100644
@@ -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
#24 lore raw

PATCH 13/23 Replicator: use cmd_vg list for _process_one_vg()

In reply to Zdenek Kabelac

Patch 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
index 9aaaa61..d5d7fc6 100644
@@ -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
#25 lore raw

PATCH 14/23 Replicator: use cmd_vg for process_each_lv_in_vg()

In reply to Zdenek Kabelac

As 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
index d5d7fc6..83cca3b 100644
@@ -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
#26 lore raw

PATCH 15/23 Replicator: lock_vol() finds missing VGs

In reply to Zdenek Kabelac

Find 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
index e7f25b9..8f6f52b 100644
@@ -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
#27 lore raw

PATCH 16/23 Replicator: activate checks for missing vgs

In reply to Zdenek Kabelac

Activation 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
index 1844cea..c6c6af7 100644
@@ -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
#28 lore raw

PATCH 17/23 Replicator: update _create_partial_dtree()

In reply to Zdenek Kabelac

Adding 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
index d52d46f..9913aae 100644
@@ -869,6 +869,76 @@ static int _add_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree, struc
 	return 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
#29 lore raw

PATCH 18/23 Replicator: vg with cmd_missing_vgs does not print

In reply to Zdenek Kabelac

If 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
index 81c95d1..ff2cdd8 100644
@@ -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
#30 lore raw

PATCH 19/23 Replicator: add replicator to dtree

In reply to Zdenek Kabelac

Adding 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
index 9913aae..81578ff 100644
@@ -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
#31 lore raw

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
index 5e4a674..d50ce53 100644
@@ -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
#32 lore raw

PATCH 21/23 Replicator: activate change for vgchange

In reply to Zdenek Kabelac

Activate 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
index ff2cdd8..9f360d3 100644
@@ -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
#33 lore raw

PATCH 22/23 Replicator: add new options for replicator

In reply to Zdenek Kabelac

New 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
index 22a085d..4ef94ff 100644
@@ -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
index 09c83a4..4198a87 100644
@@ -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
index 88d0d05..7907082 100644
@@ -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
index 7d0185b..39cd5be 100644
@@ -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
index d9ea0c7..367e8ee 100644
@@ -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
index 75575e7..8dbabbc 100644
@@ -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
#34 lore raw

PATCH 23/23 Replicator: man pages for lvcreate, lvchange

In reply to Zdenek Kabelac

Update 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
index c3cb3b2..8ae1230 100644
@@ -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
#2 lore raw

PATCH 1/23 Return ECMD_FAILED for break

In reply to Zdenek Kabelac
Quoted 1 line · Zdenek Kabelac

Return ECMD_FAILED when 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

#7 lore raw

PATCH 3/23 API change for args of process_each_lv_in_vg()

In reply to Zdenek Kabelac
Quoted 3 lines · Zdenek Kabelac

Patch 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.

Ack.

Quoted 10 lines

+++ b/tools/toollib.c

tools/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

#11 lore raw

PATCH 5/23 Replicator: suspend/deactivate replicator

In reply to Zdenek Kabelac

libdm/libdm-deptree.c struct dm_tree_node { · line 165

Quoted 2 lines · Zdenek Kabelac
libdm/libdm-deptree.c +1 -0
 	int 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

#13 lore raw

PATCH 5/23 Replicator: suspend/deactivate replicator

In reply to Zdenek Kabelac
Quoted 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

#3 lore raw

PATCH 1/23 Return ECMD_FAILED for break

In reply to Alasdair G Kergon

Dne 6.5.2010 03:10, Alasdair G Kergon napsal(a):

Quoted 7 lines · Zdenek Kabelac
Quoted 1 line

Return ECMD_FAILED when 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

#8 lore raw

PATCH 3/23 API change for args of process_each_lv_in_vg()

In reply to Alasdair G Kergon

Dne 6.5.2010 03:39, Alasdair G Kergon napsal(a):

Quoted 18 lines · Zdenek Kabelac
Quoted 3 lines

Patch 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.

Ack.

Quoted 11 lines

+++ b/tools/toollib.c

tools/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 -0
 	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.

Ok

Zdenek

#12 lore raw

PATCH 5/23 Replicator: suspend/deactivate replicator

In reply to Alasdair G Kergon

Dne 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 -0
 	int 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

#14 lore raw

PATCH 5/23 Replicator: suspend/deactivate replicator

In reply to Alasdair G Kergon

Dne 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

#15 lore raw

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

#16 lore raw

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