All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/22] Replicator 100412
@ 2010-04-12 15:21 Zdenek Kabelac
  2010-04-12 15:21 ` [PATCH 01/22] Add dm_list_splice() for list join Zdenek Kabelac
                   ` (21 more replies)
  0 siblings, 22 replies; 42+ messages in thread
From: Zdenek Kabelac @ 2010-04-12 15:21 UTC (permalink / raw)
  To: lvm-devel

Rebased set of replicator patches.
Log creation code is still kept separately as many changes
are still on going in this code.

Updated parts:

* previous set had wrong month number.
* converted Makefiles.
* renamed some functions (removed lvm_ prefix).
* renamed vg_name_list -> vgs_list.
* moved 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 (22):
  Add dm_list_splice() for list join.
  API change for args of process_each_lv_in_vg()
  Replicator: add libdm support
  Replicator: suspend/deactivate replicator
  Replicator: add lvm support
  Replicator: check replicator segment
  Replicator: extend _lv_each_dependency() rep. deps
  Replicator: extend volume_group with list of VGs
  Replicator: add sorted vgs_list
  Replicator: add find_replicator_vgs
  Replicator: add read and release VGs for rsites
  Replicator: use vgs_list for _process_one_vg()
  Replicator: use vgs_list 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 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          |   22 +-
 lib/activate/dev_manager.c       |  135 +++++++-
 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 |  105 +++++-
 lib/metadata/metadata.c          |    4 +
 lib/metadata/replicator_manip.c  |  718 ++++++++++++++++++++++++++++++++++
 lib/metadata/segtype.h           |    8 +
 lib/replicator/.exported_symbols |    1 +
 lib/replicator/Makefile.in       |   25 ++
 lib/replicator/replicator.c      |  794 ++++++++++++++++++++++++++++++++++++++
 libdm/.exported_symbols          |    4 +
 libdm/datastruct/list.c          |   12 +
 libdm/libdevmapper.h             |   38 ++
 libdm/libdm-deptree.c            |  359 +++++++++++++++++-
 man/lvchange.8.in                |   57 +++
 man/lvcreate.8.in                |   55 +++
 tools/args.h                     |   13 +
 tools/commands.h                 |    7 +
 tools/lvcreate.c                 |   55 +++
 tools/lvmcmdline.c               |    9 +
 tools/toollib.c                  |  115 ++++--
 tools/toollib.h                  |    1 +
 tools/tools.h                    |    1 +
 tools/vgchange.c                 |    9 +-
 tools/vgdisplay.c                |    2 +-
 32 files changed, 2567 insertions(+), 48 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



^ permalink raw reply	[flat|nested] 42+ messages in thread

* [PATCH 01/22] Add dm_list_splice() for list join.
  2010-04-12 15:21 [PATCH 00/22] Replicator 100412 Zdenek Kabelac
@ 2010-04-12 15:21 ` Zdenek Kabelac
  2010-04-14 11:38   ` Petr Rockai
  2010-04-26 13:15   ` Alasdair G Kergon
  2010-04-12 15:21 ` [PATCH 02/22] API change for args of process_each_lv_in_vg() Zdenek Kabelac
                   ` (20 subsequent siblings)
  21 siblings, 2 replies; 42+ messages in thread
From: Zdenek Kabelac @ 2010-04-12 15:21 UTC (permalink / raw)
  To: lvm-devel

Introduce dm_list_splice to join two lists.

Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
 libdm/.exported_symbols |    1 +
 libdm/datastruct/list.c |   12 ++++++++++++
 libdm/libdevmapper.h    |    5 +++++
 3 files changed, 18 insertions(+), 0 deletions(-)

diff --git a/libdm/.exported_symbols b/libdm/.exported_symbols
index fd9d0b9..ea65c8b 100644
--- a/libdm/.exported_symbols
+++ b/libdm/.exported_symbols
@@ -153,6 +153,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
diff --git a/libdm/datastruct/list.c b/libdm/datastruct/list.c
index 3d9ca8b..a7f9324 100644
--- a/libdm/datastruct/list.c
+++ b/libdm/datastruct/list.c
@@ -144,3 +144,15 @@ unsigned int dm_list_size(const struct dm_list *head)
 
 	return s;
 }
+
+void dm_list_splice(struct dm_list *list, struct dm_list *head)
+{
+	struct dm_list *first = list->n;
+	struct dm_list *last = list->p;
+	struct dm_list *at = head->n;
+
+	first->p = head;
+	head->n = first;
+	last->n = at;
+	at->p = last;
+}
diff --git a/libdm/libdevmapper.h b/libdm/libdevmapper.h
index 1ae930f..aa8ad5c 100644
--- a/libdm/libdevmapper.h
+++ b/libdm/libdevmapper.h
@@ -715,6 +715,11 @@ void dm_list_del(struct dm_list *elem);
 void dm_list_move(struct dm_list *head, struct dm_list *elem);
 
 /*
+ * Join 'list' to 'head'.
+ */
+void dm_list_splice(struct dm_list *list, struct dm_list *head);
+
+/*
  * Is the list empty?
  */
 int dm_list_empty(const struct dm_list *head);
-- 
1.7.0.1



^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 02/22] API change for args of process_each_lv_in_vg()
  2010-04-12 15:21 [PATCH 00/22] Replicator 100412 Zdenek Kabelac
  2010-04-12 15:21 ` [PATCH 01/22] Add dm_list_splice() for list join Zdenek Kabelac
@ 2010-04-12 15:21 ` Zdenek Kabelac
  2010-04-26 13:34   ` Alasdair G Kergon
  2010-04-26 13:46   ` Mike Snitzer
  2010-04-12 15:21 ` [PATCH 03/22] Replicator: add libdm support Zdenek Kabelac
                   ` (19 subsequent siblings)
  21 siblings, 2 replies; 42+ messages in thread
From: Zdenek Kabelac @ 2010-04-12 15:21 UTC (permalink / raw)
  To: lvm-devel

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

Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
 tools/toollib.c   |   14 +++++++++++++-
 tools/toollib.h   |    1 +
 tools/vgdisplay.c |    2 +-
 3 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/tools/toollib.c b/tools/toollib.c
index 52ea4a6..c31315c 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -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_lvs,
 			  void *handle,
 			  process_single_lv_fn_t process_single)
 {
@@ -99,6 +100,9 @@ int process_each_lv_in_vg(struct cmd_context *cmd,
 
 	struct lv_list *lvl;
 
+	if (failed_lvs)
+		dm_list_init(failed_lvs);
+
 	if (!vg_check_status(vg, EXPORTED_VG))
 		return ECMD_FAILED;
 
@@ -148,6 +152,14 @@ int process_each_lv_in_vg(struct cmd_context *cmd,
 			continue;
 
 		ret = process_single(cmd, lvl->lv, handle);
+		if (ret != ECMD_PROCESSED && failed_lvs) {
+			if (!str_list_add(cmd->mem, failed_lvs,
+					  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())
@@ -320,7 +332,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);
+					    NULL, handle, process_single);
 		unlock_and_release_vg(cmd, vg, vgname);
 		if (ret > ret_max)
 			ret_max = ret;
diff --git a/tools/toollib.h b/tools/toollib.h
index 0ea7eba..8f22cc4 100644
--- a/tools/toollib.h
+++ b/tools/toollib.h
@@ -79,6 +79,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_lvs,
 			  void *handle,
 			  process_single_lv_fn_t process_single);
 
diff --git a/tools/vgdisplay.c b/tools/vgdisplay.c
index 29bc7f1..954e456 100644
--- a/tools/vgdisplay.c
+++ b/tools/vgdisplay.c
@@ -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 ---");
-- 
1.7.0.1



^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 03/22] Replicator: add libdm support
  2010-04-12 15:21 [PATCH 00/22] Replicator 100412 Zdenek Kabelac
  2010-04-12 15:21 ` [PATCH 01/22] Add dm_list_splice() for list join Zdenek Kabelac
  2010-04-12 15:21 ` [PATCH 02/22] API change for args of process_each_lv_in_vg() Zdenek Kabelac
@ 2010-04-12 15:21 ` Zdenek Kabelac
  2010-04-26 13:46   ` Alasdair G Kergon
  2010-04-12 15:21 ` [PATCH 04/22] Replicator: suspend/deactivate replicator Zdenek Kabelac
                   ` (18 subsequent siblings)
  21 siblings, 1 reply; 42+ messages in thread
From: Zdenek Kabelac @ 2010-04-12 15:21 UTC (permalink / raw)
  To: lvm-devel

Introducing dm_tree_node_add_replicator_target() and
dm_tree_node_add_replicator_dev_target().
Define typedef dm_replicator_mode_t

Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
 libdm/.exported_symbols |    2 +
 libdm/libdevmapper.h    |   31 +++++
 libdm/libdm-deptree.c   |  297 ++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 325 insertions(+), 5 deletions(-)

diff --git a/libdm/.exported_symbols b/libdm/.exported_symbols
index ea65c8b..d9ef125 100644
--- a/libdm/.exported_symbols
+++ b/libdm/.exported_symbols
@@ -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
diff --git a/libdm/libdevmapper.h b/libdm/libdevmapper.h
index aa8ad5c..3ab5ea2 100644
--- a/libdm/libdevmapper.h
+++ b/libdm/libdevmapper.h
@@ -439,6 +439,37 @@ 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 */
+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);
+
 int dm_tree_node_add_target_area(struct dm_tree_node *node,
 				    const char *dev_name,
 				    const char *dlid,
diff --git a/libdm/libdm-deptree.c b/libdm/libdm-deptree.c
index eb74340..c9255d5 100644
--- a/libdm/libdm-deptree.c
+++ b/libdm/libdm-deptree.c
@@ -33,6 +33,8 @@ enum {
 	SEG_ERROR,
 	SEG_LINEAR,
 	SEG_MIRRORED,
+	SEG_REPLICATOR,
+	SEG_REPLICATOR_DEV,
 	SEG_SNAPSHOT,
 	SEG_SNAPSHOT_ORIGIN,
 	SEG_SNAPSHOT_MERGE,
@@ -50,6 +52,8 @@ struct {
 	{ SEG_ERROR, "error" },
 	{ SEG_LINEAR, "linear" },
 	{ SEG_MIRRORED, "mirror" },
+	{ SEG_REPLICATOR, "replicator" },
+	{ SEG_REPLICATOR_DEV, "replicator-dev" },
 	{ SEG_SNAPSHOT, "snapshot" },
 	{ SEG_SNAPSHOT_ORIGIN, "snapshot-origin" },
 	{ SEG_SNAPSHOT_MERGE, "snapshot-merge" },
@@ -64,6 +68,23 @@ struct seg_area {
 	struct dm_tree_node *dev_node;
 
 	uint64_t offset;
+
+	unsigned rsite_index;		/* Replicator site index */
+	struct dm_tree_node *slog;	/* Replicator sync log node */
+	uint64_t region_size;		/* Replicator sync log size */
+	uint32_t flags;			/* Replicator sync log flags */
+};
+
+/* Replicator-log has a list of sites */
+/* CHECKME: maybe move to seg_area too? */
+struct replicator_site {
+	struct dm_list list;
+
+	unsigned rsite_index;
+	dm_replicator_mode_t mode;
+	uint32_t async_timeout;
+	uint32_t fall_behind_ios;
+	uint64_t fall_behind_data;
 };
 
 /* Per-segment properties */
@@ -74,8 +95,8 @@ struct load_segment {
 
 	uint64_t size;
 
-	unsigned area_count;		/* Linear + Striped + Mirrored + Crypt */
-	struct dm_list areas;		/* Linear + Striped + Mirrored + Crypt */
+	unsigned area_count;		/* Linear + Striped + Mirrored + Crypt + Replicator */
+	struct dm_list areas;		/* Linear + Striped + Mirrored + Crypt + Replicator */
 
 	uint32_t stripe_size;		/* Striped */
 
@@ -85,7 +106,7 @@ struct load_segment {
 	struct dm_tree_node *origin;	/* Snapshot + Snapshot origin */
 	struct dm_tree_node *merge;	/* Snapshot */
 
-	struct dm_tree_node *log;	/* Mirror */
+	struct dm_tree_node *log;	/* Mirror + Replicator */
 	uint32_t region_size;		/* Mirror */
 	unsigned clustered;		/* Mirror */
 	unsigned mirror_area_count;	/* Mirror */
@@ -97,6 +118,13 @@ struct load_segment {
 	const char *iv;			/* Crypt */
 	uint64_t iv_offset;		/* Crypt */
 	const char *key;		/* Crypt */
+
+	const char *rlog_type;		/* Replicator */
+	struct dm_list rsites;		/* Replicator */
+	unsigned rsite_count;		/* Replicator */
+	unsigned rdevice_count;		/* Replicator */
+	struct dm_tree_node *replicator;/* Replicator-dev */
+	uint64_t rdevice_index;		/* Replicator-dev */
 };
 
 /* Per-device properties */
@@ -1342,13 +1370,51 @@ static int _emit_areas_line(struct dm_task *dmt __attribute((unused)),
 	struct seg_area *area;
 	char devbuf[DM_FORMAT_DEV_BUFSIZE];
 	unsigned first_time = 1;
+	const char *logtype;
+	unsigned log_parm_count;
 
 	dm_list_iterate_items(area, &seg->areas) {
 		if (!_build_dev_string(devbuf, sizeof(devbuf), area->dev_node))
 			return_0;
 
-		EMIT_PARAMS(*pos, "%s%s %" PRIu64, first_time ? "" : " ",
-			    devbuf, area->offset);
+		switch (seg->type) {
+		case SEG_REPLICATOR_DEV:
+			EMIT_PARAMS(*pos, " %d 1 %s", area->rsite_index, devbuf);
+			if (first_time)
+				EMIT_PARAMS(*pos, " nolog 0");
+			else {
+				/* Remote devices */
+				log_parm_count = (area->flags &
+						  (DM_NOSYNC | DM_FORCESYNC)) ? 2 : 1;
+
+				if (!area->slog) {
+					devbuf[0] = 0;		/* Only core log parameters */
+					logtype = "core";
+				} else {
+					devbuf[0] = ' ';	/* Extra space before device name */
+					if (!_build_dev_string(devbuf + 1,
+							       sizeof(devbuf) - 1,
+							       area->slog))
+						return_0;
+					logtype = "disk";
+					log_parm_count++;	/* Extra sync log device name parameter */
+				}
+
+				EMIT_PARAMS(*pos, " %s %u%s %" PRIu64, logtype,
+					    log_parm_count, devbuf, area->region_size);
+
+				logtype = (area->flags & DM_NOSYNC) ?
+					" nosync" : (area->flags & DM_FORCESYNC) ?
+					" sync" : NULL;
+
+				if (logtype)
+					EMIT_PARAMS(*pos, logtype);
+			}
+			break;
+		default:
+			EMIT_PARAMS(*pos, "%s%s %" PRIu64, first_time ? "" : " ",
+				    devbuf, area->offset);
+		}
 
 		first_time = 0;
 	}
@@ -1356,6 +1422,42 @@ static int _emit_areas_line(struct dm_task *dmt __attribute((unused)),
 	return 1;
 }
 
+static int _replicator_emit_segment_line(const struct load_segment *seg, char *params,
+					 size_t paramsize, int *pos)
+{
+	const struct load_segment *rlog_seg;
+	struct replicator_site *rsite;
+	char rlogbuf[DM_FORMAT_DEV_BUFSIZE];
+	unsigned parm_count;
+
+	if (!seg->log || !_build_dev_string(rlogbuf, sizeof(rlogbuf), seg->log))
+		return_0;
+
+	rlog_seg = dm_list_item(dm_list_last(&seg->log->props.segs),
+				struct load_segment);
+
+	EMIT_PARAMS(*pos, "%s 4 %s 0 auto %" PRIu64,
+		    seg->rlog_type, rlogbuf, rlog_seg->size);
+
+	dm_list_iterate_items(rsite, &seg->rsites) {
+		parm_count = (rsite->fall_behind_data
+			      || rsite->fall_behind_ios
+			      || rsite->async_timeout) ? 4 : 2;
+
+		EMIT_PARAMS(*pos, " blockdev %u %u %s", parm_count, rsite->rsite_index,
+			    (rsite->mode == DM_REPLICATOR_SYNC) ? "synchronous" : "asynchronous");
+
+		if (rsite->fall_behind_data)
+			EMIT_PARAMS(*pos, " data %" PRIu64, rsite->fall_behind_data);
+		else if (rsite->fall_behind_ios)
+			EMIT_PARAMS(*pos, " ios %" PRIu32, rsite->fall_behind_ios);
+		else if (rsite->async_timeout)
+			EMIT_PARAMS(*pos, " timeout %" PRIu32, rsite->async_timeout);
+	}
+
+	return 1;
+}
+
 /*
  * Returns: 1 on success, 0 on failure
  */
@@ -1499,6 +1601,21 @@ static int _emit_segment_line(struct dm_task *dmt, uint32_t major,
 		if (!r)
 			return_0;
 		break;
+	case SEG_REPLICATOR:
+		if ((r = _replicator_emit_segment_line(seg, params, paramsize,
+						       &pos)) <= 0) {
+			stack;
+			return r;
+		}
+		break;
+	case SEG_REPLICATOR_DEV:
+		if (!seg->replicator || !_build_dev_string(originbuf,
+							   sizeof(originbuf),
+							   seg->replicator))
+			return_0;
+
+		EMIT_PARAMS(pos, "%s %" PRIu64, originbuf, seg->rdevice_index);
+		break;
 	case SEG_SNAPSHOT:
 	case SEG_SNAPSHOT_MERGE:
 		if (!_build_dev_string(originbuf, sizeof(originbuf), seg->origin))
@@ -1527,6 +1644,7 @@ static int _emit_segment_line(struct dm_task *dmt, uint32_t major,
 
 	switch(seg->type) {
 	case SEG_ERROR:
+	case SEG_REPLICATOR:
 	case SEG_SNAPSHOT:
 	case SEG_SNAPSHOT_ORIGIN:
 	case SEG_SNAPSHOT_MERGE:
@@ -1534,6 +1652,7 @@ static int _emit_segment_line(struct dm_task *dmt, uint32_t major,
 		break;
 	case SEG_CRYPT:
 	case SEG_LINEAR:
+	case SEG_REPLICATOR_DEV:
 	case SEG_STRIPED:
 		if ((r = _emit_areas_line(dmt, seg, params, paramsize, &pos)) <= 0) {
 			stack;
@@ -1688,6 +1807,9 @@ int dm_tree_preload_children(struct dm_tree_node *dnode,
 			}
 		}
 
+		if (child->activation_priority != 0)
+			continue;
+
 		/* Propagate device size change change */
 		if (child->props.size_changed)
 			dnode->props.size_changed = 1;
@@ -1996,6 +2118,171 @@ int dm_tree_node_add_mirror_target(struct dm_tree_node *node,
 	return 1;
 }
 
+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)
+{
+	struct load_segment *rseg;
+	struct replicator_site *rsite;
+
+	/* Local site0 - adds replicator segment and links rlog device */
+	if (rsite_index == 0) {
+		if (node->props.segment_count) {
+			log_error(INTERNAL_ERROR "Attempt to add replicator segment to already used node.");
+			return 0;
+		}
+
+		if (!(rseg = _add_segment(node, SEG_REPLICATOR, size)))
+			return_0;
+
+		if (!(rseg->log = dm_tree_find_node_by_uuid(node->dtree, rlog_uuid))) {
+			log_error("Missing replicator log uuid %s.", rlog_uuid);
+			return 0;
+		}
+
+		if (!_link_tree_nodes(node, rseg->log))
+			return_0;
+
+		if (strcmp(rlog_type, "ringbuffer") != 0) {
+			log_error("Unsupported rlog type %s.", rlog_type);
+			return 0;
+		}
+
+		if (!(rseg->rlog_type = dm_pool_strdup(node->dtree->mem, rlog_type)))
+			return_0;
+
+		dm_list_init(&rseg->rsites);
+		rseg->rdevice_count = 0;
+		node->activation_priority = 1;
+	}
+
+	/* Add site to segment */
+	if (mode == DM_REPLICATOR_SYNC
+	    && (async_timeout || fall_behind_ios || fall_behind_data)) {
+		log_error("Async parameters passed for synchronnous replicator.");
+		return 0;
+	}
+
+	if (node->props.segment_count != 1) {
+		log_error(INTERNAL_ERROR "Attempt to add remote site area before setting replog.");
+		return 0;
+	}
+
+	rseg = dm_list_item(dm_list_last(&node->props.segs), struct load_segment);
+	if (rseg->type != SEG_REPLICATOR) {
+		log_error(INTERNAL_ERROR "Attempt to use non replicator segment %s.",
+			  dm_segtypes[rseg->type].target);
+		return 0;
+	}
+
+	if (!(rsite = dm_pool_zalloc(node->dtree->mem, sizeof(*rsite)))) {
+		log_error("Failed to allocate remote site segment.");
+		return 0;
+	}
+
+	dm_list_add(&rseg->rsites, &rsite->list);
+	rseg->rsite_count++;
+
+	rsite->mode = mode;
+	rsite->async_timeout = async_timeout;
+	rsite->fall_behind_data = fall_behind_data;
+	rsite->fall_behind_ios = fall_behind_ios;
+	rsite->rsite_index = rsite_index;
+
+	return 1;
+}
+
+/* Appends device node to Replicator */
+int dm_tree_node_add_replicator_dev_target(struct dm_tree_node *node,
+					   uint64_t size,
+					   const char *replicator_uuid,
+					   uint64_t rdevice_index,
+					   const char *rdev_uuid,
+					   unsigned rsite_index,
+					   const char *slog_uuid,
+					   uint32_t slog_flags,
+					   uint32_t slog_region_size)
+{
+	struct seg_area *area;
+	struct load_segment *rseg;
+	struct load_segment *rep_seg;
+
+	if (rsite_index == 0) {
+		/* Site index for local target */
+		if (!(rseg = _add_segment(node, SEG_REPLICATOR_DEV, size)))
+			return_0;
+
+		if (!(rseg->replicator = dm_tree_find_node_by_uuid(node->dtree, replicator_uuid))) {
+			log_error("Missing replicator uuid %s.", replicator_uuid);
+			return 0;
+		}
+
+		/* Local slink 0 for replicator must be always initialized first */
+		if (rseg->replicator->props.segment_count != 1) {
+			log_error(INTERNAL_ERROR "Attempt to use non replicator segment.");
+			return 0;
+		}
+
+		rep_seg = dm_list_item(dm_list_last(&rseg->replicator->props.segs), struct load_segment);
+		if (rep_seg->type != SEG_REPLICATOR) {
+			log_error(INTERNAL_ERROR "Attempt to use non replicator segment %s.",
+				  dm_segtypes[rep_seg->type].target);
+			return 0;
+		}
+		rep_seg->rdevice_count++;
+
+		if (!_link_tree_nodes(node, rseg->replicator))
+			return_0;
+
+		rseg->rdevice_index = rdevice_index;
+	} else {
+		if (node->props.segment_count != 1) {
+			/* Local slink 0 for replicator must be always initialized first */
+			log_error(INTERNAL_ERROR "Attempt to use non replicator-dev segment.");
+			return 0;
+		}
+
+		rseg = dm_list_item(dm_list_last(&node->props.segs), struct load_segment);
+		if (rseg->type != SEG_REPLICATOR_DEV) {
+			log_error(INTERNAL_ERROR "Attempt to use non replicator-dev segment %s.",
+				  dm_segtypes[rseg->type].target);
+			return 0;
+		}
+	}
+
+	if (!(slog_flags & DM_CORELOG) && !slog_uuid) {
+		log_error("Unspecified sync log uuid.");
+		return 0;
+	}
+
+	if (!dm_tree_node_add_target_area(node, NULL, rdev_uuid, 0))
+		return_0;
+
+	area = dm_list_item(dm_list_last(&rseg->areas), struct seg_area);
+
+	if (!(slog_flags & DM_CORELOG)) {
+		if (!(area->slog = dm_tree_find_node_by_uuid(node->dtree, slog_uuid))) {
+			log_error("Couldn't find sync log uuid %s.", slog_uuid);
+			return 0;
+		}
+
+		if (!_link_tree_nodes(node, area->slog))
+			return_0;
+	}
+
+	area->flags = slog_flags;
+	area->region_size = slog_region_size;
+	area->rsite_index = rsite_index;
+
+	return 1;
+}
+
 static int _add_area(struct dm_tree_node *node, struct load_segment *seg, struct dm_tree_node *dev_node, uint64_t offset)
 {
 	struct seg_area *area;
-- 
1.7.0.1



^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 04/22] Replicator: suspend/deactivate replicator
  2010-04-12 15:21 [PATCH 00/22] Replicator 100412 Zdenek Kabelac
                   ` (2 preceding siblings ...)
  2010-04-12 15:21 ` [PATCH 03/22] Replicator: add libdm support Zdenek Kabelac
@ 2010-04-12 15:21 ` Zdenek Kabelac
  2010-04-26 13:50   ` Alasdair G Kergon
  2010-04-12 15:21 ` [PATCH 05/22] Replicator: add lvm support Zdenek Kabelac
                   ` (17 subsequent siblings)
  21 siblings, 1 reply; 42+ messages in thread
From: Zdenek Kabelac @ 2010-04-12 15:21 UTC (permalink / raw)
  To: lvm-devel

Introducing dm_tree_set_suspend_priority() for suspending replicator
control target before deactivation of replicator-dev target.

Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
 libdm/.exported_symbols |    1 +
 libdm/libdevmapper.h    |    2 +
 libdm/libdm-deptree.c   |   62 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 65 insertions(+), 0 deletions(-)

diff --git a/libdm/.exported_symbols b/libdm/.exported_symbols
index d9ef125..b977383 100644
--- a/libdm/.exported_symbols
+++ b/libdm/.exported_symbols
@@ -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
diff --git a/libdm/libdevmapper.h b/libdm/libdevmapper.h
index 3ab5ea2..52f594c 100644
--- a/libdm/libdevmapper.h
+++ b/libdm/libdevmapper.h
@@ -470,6 +470,8 @@ int dm_tree_node_add_replicator_dev_target(struct dm_tree_node *node,
 					   uint32_t slog_flags,		/* Mirror log flags */
 					   uint32_t slog_region_size);
 
+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,
diff --git a/libdm/libdm-deptree.c b/libdm/libdm-deptree.c
index c9255d5..477cbcb 100644
--- a/libdm/libdm-deptree.c
+++ b/libdm/libdm-deptree.c
@@ -160,6 +160,7 @@ struct dm_tree_node {
         struct dm_list used_by;    	/* Nodes that use this node */
 
 	int activation_priority;	/* 0 gets activated first */
+	int suspend_priority;		/* 1 gets suspend first */
 
 	uint16_t udev_flags;		/* Udev control flags */
 
@@ -682,6 +683,18 @@ void dm_tree_node_set_read_ahead(struct dm_tree_node *dnode,
 	dnode->props.read_ahead_flags = read_ahead_flags;
 }
 
+int dm_tree_set_suspend_priority(struct dm_tree *dtree, const char *uuid, int priority)
+{
+	struct dm_tree_node *dnode;
+
+	if ((dnode = dm_tree_find_node_by_uuid(dtree, uuid))) {
+		log_verbose("Setting suspend priority for %s.", dnode->name);
+		dnode->suspend_priority = priority;
+	}
+
+	return 1;
+}
+
 int dm_tree_add_dev(struct dm_tree *dtree, uint32_t major, uint32_t minor)
 {
 	return _add_dev(dtree, &dtree->root, major, minor, 0) ? 1 : 0;
@@ -1041,6 +1054,52 @@ static int _suspend_node(const char *name, uint32_t major, uint32_t minor,
 	return r;
 }
 
+static int _suspend_parent(struct dm_tree_node *dnode, const char *uuid_prefix,
+			   size_t uuid_prefix_len)
+{
+	struct dm_info info;
+	const struct dm_info *dinfo;
+	const char *name;
+	const char *uuid;
+	struct dm_tree_link *dlink;
+
+	dm_list_iterate_items(dlink, &dnode->uses) {
+		if (!dlink->node->suspend_priority)
+			continue;
+
+		if (!(uuid = dm_tree_node_get_uuid(dlink->node))) {
+			stack;
+			continue;
+		}
+		/* Ignore if it doesn't belong to this VG */
+		if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))
+			continue;
+
+		if (!(dinfo = dm_tree_node_get_info(dlink->node))) {
+			stack;
+			continue;
+		}
+
+		if (dinfo->suspended)
+			continue;
+
+		if (!(name = dm_tree_node_get_name(dlink->node))) {
+			stack;
+			continue;
+		}
+
+		if (!_suspend_node(name, dinfo->major, dinfo->minor,
+				   1, 1, &info)) {
+			log_error("Unable to suspend %s (%" PRIu32
+				  ":%" PRIu32 ").", name, dinfo->major,
+				  dinfo->minor);
+			return 0;
+		}
+	}
+
+	return 1;
+}
+
 /*
  * FIXME Don't attempt to deactivate known internal dependencies.
  */
@@ -1093,6 +1152,9 @@ static int _dm_tree_deactivate_children(struct dm_tree_node *dnode,
 			continue;
 		}
 
+		if (!_suspend_parent(child, uuid_prefix, uuid_prefix_len))
+			continue;
+
 		if (!_deactivate_node(name, info.major, info.minor,
 				      &child->dtree->cookie, child->udev_flags)) {
 			log_error("Unable to deactivate %s (%" PRIu32
-- 
1.7.0.1



^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 05/22] Replicator: add lvm support
  2010-04-12 15:21 [PATCH 00/22] Replicator 100412 Zdenek Kabelac
                   ` (3 preceding siblings ...)
  2010-04-12 15:21 ` [PATCH 04/22] Replicator: suspend/deactivate replicator Zdenek Kabelac
@ 2010-04-12 15:21 ` Zdenek Kabelac
  2010-04-26 14:10   ` Alasdair G Kergon
  2010-04-12 15:21 ` [PATCH 06/22] Replicator: check replicator segment Zdenek Kabelac
                   ` (16 subsequent siblings)
  21 siblings, 1 reply; 42+ messages in thread
From: Zdenek Kabelac @ 2010-04-12 15:21 UTC (permalink / raw)
  To: lvm-devel

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.

Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
 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  |  340 ++++++++++++++++
 lib/metadata/segtype.h           |    8 +
 lib/replicator/.exported_symbols |    1 +
 lib/replicator/Makefile.in       |   25 ++
 lib/replicator/replicator.c      |  794 ++++++++++++++++++++++++++++++++++++++
 12 files changed, 1290 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

diff --git a/configure.in b/configure.in
index ed9e631..c6b6a31 100644
--- a/configure.in
+++ b/configure.in
@@ -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
diff --git a/lib/Makefile.in b/lib/Makefile.in
index 3498141..ae81040 100644
--- a/lib/Makefile.in
+++ b/lib/Makefile.in
@@ -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
 
diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c
index 818e452..388c559 100644
--- a/lib/commands/toolcontext.c
+++ b/lib/commands/toolcontext.c
@@ -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() &&
diff --git a/lib/format_text/flags.c b/lib/format_text/flags.c
index a41dc1a..994adf2 100644
--- a/lib/format_text/flags.c
+++ b/lib/format_text/flags.c
@@ -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}
 };
 
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index f8bed4b..43ca423 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -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;
 }
diff --git a/lib/metadata/merge.c b/lib/metadata/merge.c
index df90743..66ff57b 100644
--- a/lib/metadata/merge.c
+++ b/lib/metadata/merge.c
@@ -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) {
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index b4967e6..7b6c7fa 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -72,6 +72,9 @@
 
 #define MERGING			0x10000000U	/* LV SEG */
 
+#define REPLICATOR		0x20000000U	/* LV -internal use only for replicator */
+#define REPLICATOR_LOG		0x40000000U	/* LV -internal use only for replicator-dev */
+
 #define LVM_READ              	0x00000100U	/* LV VG */
 #define LVM_WRITE             	0x00000200U	/* LV VG */
 #define CLUSTERED         	0x00000400U	/* VG */
@@ -280,6 +283,45 @@ struct lv_segment_area {
 };
 
 struct segment_type;
+
+/* ++ Replicator datatypes */
+typedef enum {
+	REPLICATOR_STATE_PASSIVE,
+	REPLICATOR_STATE_ACTIVE,
+	NUM_REPLICATOR_STATE
+} replicator_state_t;
+
+struct replicator_site {
+	struct dm_list list;		/* Chained list of sites */
+	struct dm_list rdevices;	/* Device list */
+
+	struct logical_volume *replicator; /* Reference to replicator */
+
+	const char *name;               /* Site name */
+	const char *vg_name;		/* VG name */
+	struct volume_group *vg;        /* resolved vg  (activate/deactive) */
+	unsigned site_index;
+	replicator_state_t state;	/* Active or pasive state of site */
+	dm_replicator_mode_t op_mode;	/* Operation mode sync or async fail|warn|drop|stall */
+	uint64_t fall_behind_data;	/* Bytes */
+	uint32_t fall_behind_ios;	/* IO operations */
+	uint32_t fall_behind_timeout;	/* Seconds */
+};
+
+struct replicator_device {
+	struct dm_list list;		/* Chained list of devices from same site */
+
+	struct lv_segment *replicator_dev; /* Reference to replicator-dev segment */
+	struct replicator_site *rsite;	/* Reference to site parameters */
+
+	uint64_t device_index;
+	const char *name;		/* Device LV name */
+	struct logical_volume *lv;	/* LV from replicator site's VG */
+	struct logical_volume *slog;	/* Synclog lv from VG  */
+	const char *slog_name;		/* Debug - specify size of core synclog */
+};
+/* -- Replicator datatypes */
+
 struct lv_segment {
 	struct dm_list list;
 	struct logical_volume *lv;
@@ -298,7 +340,7 @@ struct lv_segment {
 	struct logical_volume *origin;
 	struct logical_volume *cow;
 	struct dm_list origin_list;
-	uint32_t region_size;	/* For mirrors - in sectors */
+	uint32_t region_size;	/* For mirrors, replicators - in sectors */
 	uint32_t extents_copied;
 	struct logical_volume *log_lv;
 	struct lv_segment *pvmove_source_seg;
@@ -307,6 +349,12 @@ struct lv_segment {
 	struct dm_list tags;
 
 	struct lv_segment_area *areas;
+
+	struct logical_volume *replicator;/* For replicator-devs - link to replicator LV */
+	struct logical_volume *rlog_lv;	/* For replicators */
+	const char *rlog_type;		/* For replicators */
+	uint64_t rdevice_index_highest;	/* For replicators */
+	unsigned rsite_index_highest;	/* For replicators */
 };
 
 #define seg_type(seg, s)	(seg)->areas[(s)].type
@@ -332,6 +380,9 @@ struct logical_volume {
 	struct dm_list snapshot_segs;
 	struct lv_segment *snapshot;
 
+	struct replicator_device *rdevice;/* For replicator-devs, rimages, slogs - reference to rdevice */
+	struct dm_list rsites;	/* For replicators - all sites */
+
 	struct dm_list segments;
 	struct dm_list tags;
 	struct dm_list segs_using_this_lv;
@@ -704,6 +755,27 @@ int reconfigure_mirror_images(struct lv_segment *mirrored_seg, uint32_t num_mirr
 int collapse_mirrored_lv(struct logical_volume *lv);
 int shift_mirror_images(struct lv_segment *mirrored_seg, unsigned mimage);
 
+/* ++  metadata/replicator_manip.c */
+int replicator_add_replicator_dev(struct logical_volume *replicator_lv,
+				  struct lv_segment *rdev_seg);
+struct logical_volume *replicator_remove_replicator_dev(struct lv_segment *rdev_seg);
+int replicator_add_rlog(struct lv_segment *replicator_seg, struct logical_volume *rlog_lv);
+struct logical_volume *replicator_remove_rlog(struct lv_segment *replicator_seg);
+
+int replicator_dev_add_slog(struct replicator_device *rdev, struct logical_volume *slog_lv);
+struct logical_volume *replicator_dev_remove_slog(struct replicator_device *rdev);
+int replicator_dev_add_rimage(struct replicator_device *rdev, struct logical_volume *lv);
+struct logical_volume *replicator_dev_remove_rimage(struct replicator_device *rdev);
+
+int lv_is_active_replicator_dev(const struct logical_volume *lv);
+int lv_is_replicator(const struct logical_volume *lv);
+int lv_is_replicator_dev(const struct logical_volume *lv);
+int lv_is_rimage(const struct logical_volume *lv);
+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 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,
diff --git a/lib/metadata/replicator_manip.c b/lib/metadata/replicator_manip.c
new file mode 100644
index 0000000..02fd49c
--- /dev/null
+++ b/lib/metadata/replicator_manip.c
@@ -0,0 +1,340 @@
+/*
+ * 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 Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ */
+
+#include <inttypes.h>
+#include <sys/types.h>
+#include "libdevmapper.h"
+#include "lvm-types.h"
+
+#include "activate.h"
+#include "archiver.h"
+#include "defaults.h"
+#include "label.h"
+#include "lib.h"
+#include "locking.h"
+#include "lv_alloc.h"
+#include "lvm-string.h"
+#include "metadata.h"
+#include "segtype.h"
+#include "toolcontext.h"
+
+/* Add lv as replicator_dev device */
+int replicator_dev_add_rimage(struct replicator_device *rdev,
+			      struct logical_volume *lv)
+{
+	if (!lv || !rdev)
+		return_0;
+
+	if (lv_is_rimage(lv)) {
+		log_error("Logical volume %s is already part of other "
+			  "replicator.", lv->name);
+		return 0;
+	}
+
+	if (rdev->lv) {
+		log_error("Logical volume %s can not be attached to an "
+			  "already defined replicator_device", lv->name);
+		return 0;
+	}
+
+	lv_set_hidden(lv);
+	lv->rdevice = rdev;
+	rdev->lv = lv;
+
+	return add_seg_to_segs_using_this_lv(lv, rdev->replicator_dev);
+}
+
+/* Remove lv from replicator_dev device */
+struct logical_volume *replicator_dev_remove_rimage(struct replicator_device *rdev)
+{
+	struct logical_volume *lv;
+
+	if (!rdev || !rdev->lv)
+		return_NULL;
+
+	lv = rdev->lv;
+	if (!remove_seg_from_segs_using_this_lv(lv, rdev->replicator_dev))
+		return_NULL;
+
+	/* FIXME: - check for site references */
+	rdev->lv = NULL;
+	lv->rdevice = NULL;
+	lv_set_visible(lv);
+
+	return lv;
+}
+
+int replicator_dev_add_slog(struct replicator_device *rdev,
+			    struct logical_volume *slog)
+{
+	if (!slog || !rdev)
+		return_0;
+
+	if (rdev->slog) {
+		log_error("Replicator device in site %s already has sync log.",
+			  rdev->rsite->name);
+		return 0;
+	}
+
+	if (slog->rdevice) {
+		log_error("Sync log %s is already used by replicator %s.",
+			  slog->name, slog->rdevice->rsite->replicator->name);
+		return 0;
+	}
+
+	lv_set_hidden(slog);
+	slog->rdevice = rdev;
+	rdev->slog = slog;
+
+	return add_seg_to_segs_using_this_lv(slog, rdev->replicator_dev);
+}
+
+struct logical_volume *replicator_dev_remove_slog(struct replicator_device *rdev)
+{
+	struct logical_volume *lv;
+
+	if (!rdev)
+		return_NULL;
+
+	lv = rdev->slog;
+	if (!lv) {
+		log_error("Replicator device in site %s does not have sync log.",
+			  rdev->rsite->name);
+		return NULL;
+	}
+
+	if (!remove_seg_from_segs_using_this_lv(lv, rdev->replicator_dev))
+		return_NULL;
+
+	rdev->slog = NULL;
+	lv->rdevice = NULL;
+	lv_set_visible(lv);
+
+	return lv;
+}
+
+int replicator_add_replicator_dev(struct logical_volume *replicator_lv,
+				  struct lv_segment *replicator_dev_seg)
+{
+	if (!replicator_lv)
+		return_0;
+
+	if (!(replicator_lv->status & REPLICATOR)) {
+		dm_list_init(&replicator_lv->rsites);
+		lv_set_hidden(replicator_lv);
+		replicator_lv->status |= REPLICATOR;
+	}
+
+	if (!replicator_dev_seg)
+		return 1;
+
+	if (replicator_dev_seg->replicator) {
+		log_error("Replicator device %s is already part of replicator.",
+			  replicator_dev_seg->lv->name);
+		return 0;
+	}
+
+	replicator_dev_seg->replicator = replicator_lv;
+
+	return add_seg_to_segs_using_this_lv(replicator_lv, replicator_dev_seg);
+}
+
+/**
+ * Returns rimage ?? lv upon succeful detach of device
+ * entire LV entry should be removed by this crootall ??
+ */
+struct logical_volume *replicator_remove_replicator_dev(struct lv_segment *replicator_dev_seg)
+{
+	struct logical_volume *lv = NULL;
+
+	log_error("FIXME: not implemented.");
+#if 0
+	/* FIXME: - this is going to be complex.... */
+	if (!replicator_dev_seg)
+		return_NULL;
+
+	/* if slog or rimage - exit */
+
+	if (!remove_seg_from_segs_using_this_lv(lv, replicator_seg))
+		return_NULL;
+
+	replicator_seg->rlog_lv = NULL;
+	lv->status &= ~REPLICATOR_LOG;
+	lv_set_visible(lv);
+#endif
+
+	return lv;
+}
+
+int replicator_add_rlog(struct lv_segment *replicator_seg,
+			struct logical_volume *rlog_lv)
+{
+	if (!rlog_lv)
+		return_0;
+
+	if (rlog_lv->status & REPLICATOR_LOG) {
+		log_error("Rlog device %s is already used.", rlog_lv->name);
+		return 0;
+	}
+
+	lv_set_hidden(rlog_lv);
+	rlog_lv->status |= REPLICATOR_LOG;
+	replicator_seg->rlog_lv = rlog_lv;
+
+	return add_seg_to_segs_using_this_lv(rlog_lv, replicator_seg);
+}
+
+struct logical_volume *replicator_remove_rlog(struct lv_segment *replicator_seg)
+{
+	struct logical_volume *lv;
+
+	if (!replicator_seg)
+		return_0;
+
+	if (!(lv = replicator_seg->rlog_lv)) {
+		log_error("Replog segment %s does not have rlog.",
+			  replicator_seg->lv->name);
+		return NULL;
+	}
+
+	if (!remove_seg_from_segs_using_this_lv(lv, replicator_seg))
+		return_NULL;
+
+	replicator_seg->rlog_lv = NULL;
+	lv->status &= ~REPLICATOR_LOG;
+	lv_set_visible(lv);
+
+	return lv;
+}
+
+
+#if 0
+/*
+ * Create new LV to pretend the original LV
+ * this target will have a 'replicator' segment
+ */
+int lv_add_replicator(struct logical_volume *origin, const char *rep_suffix)
+{
+	struct logical_volume *rep_lv;
+	char *name;
+	size_t slen;
+
+	if (!(name = strstr(origin->name, rep_suffix))) {
+		log_error("Failed to find replicator suffix %s in LV name %s",
+			  rep_suffix, origin->name);
+		return 0;
+	}
+	slen = (size_t)(name - origin->name);
+	name = alloca(slen + 1);
+	memcpy(name, origin->name, slen);
+	name[slen] = 0;
+
+	if ((rep_lv = find_lv(origin->vg, name))) {
+		rep_lv->status |= VIRTUAL;
+		return 1;
+	}
+
+	if (!(rep_lv = lv_create_empty(name, &origin->lvid,
+				       LVM_READ | LVM_WRITE | VISIBLE_LV,
+				       ALLOC_INHERIT, origin->vg)))
+		return_0;
+
+	if (!lv_add_virtual_segment(rep_lv, 0, origin->le_count,
+				    get_segtype_from_string(origin->vg->cmd,
+							    "error")))
+		return_0;
+
+	rep_lv->status |= VIRTUAL;
+	return 1;
+}
+
+int lv_remove_replicator(struct logical_volume *lv)
+{
+	return 1;
+}
+#endif
+
+/**
+ * Is this segment part of active replicator
+ */
+int lv_is_active_replicator_dev(const struct logical_volume *lv)
+{
+	return ((lv->status & REPLICATOR) &&
+		lv->rdevice &&
+		lv->rdevice->rsite &&
+		lv->rdevice->rsite->state == REPLICATOR_STATE_ACTIVE);
+}
+
+/**
+ * Is this LV replicator control device
+ */
+int lv_is_replicator(const struct logical_volume *lv)
+{
+	return ((lv->status & REPLICATOR) &&
+		!dm_list_empty(&lv->segments) &&
+		seg_is_replicator(first_seg(lv)));
+}
+
+/**
+ * Is this LV replicator device
+ */
+int lv_is_replicator_dev(const struct logical_volume *lv)
+{
+	return ((lv->status & REPLICATOR) &&
+		!dm_list_empty(&lv->segments) &&
+		seg_is_replicator_dev(first_seg(lv)));
+}
+
+/**
+ * Is this LV replicated origin lv
+ */
+int lv_is_rimage(const struct logical_volume *lv)
+{
+	return (lv->rdevice && lv->rdevice->lv == lv);
+}
+
+/**
+ * Is this LV rlog
+ */
+int lv_is_rlog(const struct logical_volume *lv)
+{
+	return (lv->status & REPLICATOR_LOG);
+}
+
+/**
+ * Is this LV sync log
+ */
+int lv_is_slog(const struct logical_volume *lv)
+{
+	return (lv->rdevice && lv->rdevice->slog == lv);
+}
+
+/**
+ * Returns first replicator-dev in site in case the LV is replicator-dev,
+ * NULL otherwise
+ */
+struct logical_volume *first_replicator_dev(const struct logical_volume *lv)
+{
+	struct replicator_device *rdev;
+	struct replicator_site *rsite;
+
+	if (lv_is_replicator_dev(lv))
+		dm_list_iterate_items(rsite, &first_seg(lv)->replicator->rsites) {
+			dm_list_iterate_items(rdev, &rsite->rdevices)
+				return rdev->replicator_dev->lv;
+			break;
+		}
+
+	return NULL;
+}
diff --git a/lib/metadata/segtype.h b/lib/metadata/segtype.h
index 7b31c1d..d352928 100644
--- a/lib/metadata/segtype.h
+++ b/lib/metadata/segtype.h
@@ -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
diff --git a/lib/replicator/.exported_symbols b/lib/replicator/.exported_symbols
new file mode 100644
index 0000000..1c92c6a
--- /dev/null
+++ b/lib/replicator/.exported_symbols
@@ -0,0 +1 @@
+init_segtype
diff --git a/lib/replicator/Makefile.in b/lib/replicator/Makefile.in
new file mode 100644
index 0000000..ac42730
--- /dev/null
+++ b/lib/replicator/Makefile.in
@@ -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
diff --git a/lib/replicator/replicator.c b/lib/replicator/replicator.c
new file mode 100644
index 0000000..37114bf
--- /dev/null
+++ b/lib/replicator/replicator.c
@@ -0,0 +1,794 @@
+/*
+ * 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 Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ */
+
+#include "lib.h"
+#include "toolcontext.h"
+#include "metadata.h"
+#include "segtype.h"
+#include "text_export.h"
+#include "text_import.h"
+#include "config.h"
+#include "activate.h"
+#include "str_list.h"
+#include "targets.h"  /* build_dlid */
+#ifdef DMEVENTD
+#  include "sharedlib.h"
+#  include "libdevmapper-event.h"
+#endif
+
+/* Dm kernel module name for replicator */
+#define REPLICATOR_MODULE "replicator"
+#define REPLICATOR_DEV_MODULE "replicator-dev"
+
+/*
+ * Macro used as return argument - returns 0.
+ * return is left to be written in the function for better readability.
+ */
+#define SEG_LOG_ERROR(t, p...) \
+	log_error(t " segment %s of logical volume %s.", ## p, \
+		  config_parent_name(sn), seg->lv->name), 0;
+
+
+/*
+ *  Replicator target
+ */
+static const char *_replicator_name(const struct lv_segment *seg)
+{
+	return seg->segtype->name;
+}
+
+/* FIXME: missing implementation */
+static void _replicator_display(const struct lv_segment *seg)
+{
+	//const char *size;
+	//uint32_t s;
+
+	log_print("  Replicator");
+	if (seg->rlog_lv)
+		log_print("  Replicator volume\t%s", seg->rlog_lv->name);
+}
+
+/* Wrapper for get_config_uint32() with default value */
+static uint32_t _get_config_uint32(const struct config_node *cn,
+				   const char *path,
+				   uint32_t def)
+{
+	uint32_t t;
+
+	return get_config_uint32(cn, path, &t) ? t : def;
+}
+
+/* Wrapper for get_config_uint64() with default value */
+static uint64_t _get_config_uint64(const struct config_node *cn,
+				   const char *path,
+				   uint64_t def)
+{
+	uint64_t t;
+
+	return get_config_uint64(cn, path, &t) ? t : def;
+}
+
+
+/* Strings replicator_state_t enum */
+static const char _state_txt[NUM_REPLICATOR_STATE][8] = {
+	"passive",
+	"active"
+};
+
+/* Parse state string */
+static replicator_state_t _get_state(const struct config_node *sn,
+				     const char *path, replicator_state_t def)
+{
+	char *str;
+	unsigned i;
+
+	if (get_config_str(sn, path, &str)) {
+		for (i = 0; i < sizeof(_state_txt)/sizeof(_state_txt[0]); ++i)
+			if (strcasecmp(str, _state_txt[i]) == 0)
+				return (replicator_state_t) i;
+
+		log_warn("%s: unknown value '%s', using default '%s' state",
+			 path, str, _state_txt[def]);
+	}
+
+	return def;
+}
+
+/* Strings for replicator_action_t enum */
+static const char _op_mode_txt[NUM_DM_REPLICATOR_MODES][8] = {
+	"sync",
+	"warn",
+	"stall",
+	"drop",
+	"fail"
+};
+
+
+/* Parse action string */
+static dm_replicator_mode_t _get_op_mode(const struct config_node *sn,
+					 const char *path, dm_replicator_mode_t def)
+{
+	char *str;
+	unsigned i;
+
+	if (get_config_str(sn, path, &str)) {
+		for (i = 0; i < sizeof(_op_mode_txt)/sizeof(_op_mode_txt[0]); ++i)
+			if (strcasecmp(str, _op_mode_txt[i]) == 0) {
+				log_very_verbose("Setting %s to %s",
+						 path, _op_mode_txt[i]);
+				return (dm_replicator_mode_t) i;
+			}
+		log_warn("%s: unknown value '%s', using default '%s' operation mode",
+			 path, str, _op_mode_txt[def]);
+	}
+
+	return def;
+}
+
+static struct replicator_site *_get_site(struct logical_volume *replicator,
+					 const char *key)
+{
+	struct dm_pool *mem = replicator->vg->vgmem;
+	struct replicator_site *rsite;
+
+	dm_list_iterate_items(rsite, &replicator->rsites)
+		if (strcasecmp(rsite->name, key) == 0)
+			return rsite;
+
+	if (!(rsite = dm_pool_zalloc(mem, sizeof(*rsite))))
+		return_NULL;
+
+	if (!(rsite->name = dm_pool_strdup(mem, key)))
+		return_NULL;
+
+	rsite->replicator = replicator;
+	dm_list_init(&rsite->rdevices);
+	dm_list_add(&replicator->rsites, &rsite->list);
+
+	return rsite;
+}
+
+
+/* Parse replicator site element */
+static int _add_site(struct lv_segment *seg,
+		     const char *key,
+		     const struct config_node *sn)
+{
+	struct dm_pool *mem = seg->lv->vg->vgmem;
+	const struct config_node *cn;
+	struct replicator_site *rsite;
+
+	if (!(rsite = _get_site(seg->lv, key)))
+		return_0;
+
+	if (!find_config_node(sn, "site_index"))
+		return SEG_LOG_ERROR("Mandatory site_index is missing for");
+
+	rsite->state = _get_state(sn, "state", REPLICATOR_STATE_PASSIVE);
+	rsite->site_index = _get_config_uint32(sn, "site_index", 0);
+	if (rsite->site_index > seg->rsite_index_highest)
+		return SEG_LOG_ERROR("site_index=%d > highest_site_index=%d for",
+				     rsite->site_index, seg->rsite_index_highest);
+
+	rsite->fall_behind_data = _get_config_uint64(sn, "fall_behind_data", 0);
+	rsite->fall_behind_ios = _get_config_uint32(sn, "fall_behind_ios", 0);
+	rsite->fall_behind_timeout = _get_config_uint32(sn, "fall_behind_timeout", 0);
+	rsite->op_mode = DM_REPLICATOR_SYNC;
+
+	if (rsite->fall_behind_data ||
+	    rsite->fall_behind_ios ||
+	    rsite->fall_behind_timeout) {
+		if (rsite->fall_behind_data && rsite->fall_behind_ios)
+			return SEG_LOG_ERROR("Defined both fall_behind_data "
+					     "and fall_behind_ios in");
+
+		if (rsite->fall_behind_data && rsite->fall_behind_timeout)
+			return SEG_LOG_ERROR("Defined both fall_behind_data "
+					     "and fall_behind_timeout in");
+
+		if (rsite->fall_behind_ios && rsite->fall_behind_timeout)
+			return SEG_LOG_ERROR("Defined both fall_behind_ios "
+					     "and fall_behind_timeout in");
+
+		rsite->op_mode = _get_op_mode(sn, "operation_mode",
+					      rsite->op_mode);
+	}
+
+	if ((cn = find_config_node(sn, "volume_group"))) {
+		if (!cn->v || cn->v->type != CFG_STRING)
+			return SEG_LOG_ERROR("volume_group must be a string in");
+
+		if (!(rsite->vg_name = dm_pool_strdup(mem, cn->v->v.str)))
+			return_0;
+
+	} else if (rsite->site_index != 0)
+		return SEG_LOG_ERROR("volume_group is mandatory for remote site in");
+
+	return 1;
+}
+
+
+/* Import replicator segment */
+static int _replicator_text_import(struct lv_segment *seg,
+				   const struct config_node *sn,
+				   struct dm_hash_table *pv_hash __attribute((unused)))
+{
+	const struct config_node *cn;
+	struct logical_volume *rlog_lv;
+
+	if (!replicator_add_replicator_dev(seg->lv, NULL))
+		return_0;
+
+	if (!(cn = find_config_node(sn, "replicator_log")) ||
+	    !cn->v || cn->v->type != CFG_STRING)
+		return SEG_LOG_ERROR("Replicator log type must be a string in");
+
+	if (!(rlog_lv = find_lv(seg->lv->vg, cn->v->v.str)))
+		return SEG_LOG_ERROR("Unknown replicator log %s in",
+				     cn->v->v.str);
+
+	if (!(cn = find_config_node(sn, "replicator_log_type")) ||
+	    !cn->v || cn->v->type != CFG_STRING)
+		return SEG_LOG_ERROR("Replicator log's type must be a string in");
+	if (strcasecmp(cn->v->v.str, "ringbuffer"))
+		return SEG_LOG_ERROR("Only ringbuffer replicator log type is supported in");
+
+	if (!(seg->rlog_type = dm_pool_strdup(seg->lv->vg->vgmem, cn->v->v.str)))
+		return_0;
+
+
+	log_very_verbose("replicator_log = %s", rlog_lv->name);
+	log_very_verbose("replicator_log_type = %s", seg->rlog_type);
+
+	if (!replicator_add_rlog(seg, rlog_lv))
+		return_0;
+
+	seg->rdevice_index_highest = _get_config_uint64(sn, "highest_device_index", 0);
+	seg->rsite_index_highest = _get_config_uint32(sn, "highest_site_index", 0);
+
+	seg->region_size = _get_config_uint32(sn, "sync_log_size", 0);
+
+	for (; sn; sn = sn->sib)
+		if (!sn->v) {
+			for (cn = sn->sib; cn; cn = cn->sib)
+				if (!cn->v && (strcasecmp(cn->key ,sn->key) == 0))
+					return SEG_LOG_ERROR("Detected duplicate site "
+							     "name %s in", sn->key);
+			if (!_add_site(seg, sn->key, sn->child))
+				return_0;
+		}
+	return 1;
+}
+
+/* Export replicator segment */
+static int _replicator_text_export(const struct lv_segment *seg,
+				   struct formatter *f)
+{
+	struct replicator_site *rsite;
+
+	if (!seg->rlog_lv)
+                return_0;
+
+	outf(f, "replicator_log = \"%s\"", seg->rlog_lv->name);
+	outf(f, "replicator_log_type = \"%s\"", seg->rlog_type);
+	outf(f, "highest_device_index = %" PRIu64, seg->rdevice_index_highest);
+	outf(f, "highest_site_index = %d", seg->rsite_index_highest);
+
+	if (seg->region_size)
+		outsize(f, (uint64_t)seg->region_size,
+			"sync_log_size = %" PRIu32, seg->region_size);
+
+	if (!dm_list_empty(&seg->lv->rsites))
+		outnl(f);
+
+	dm_list_iterate_items(rsite, &seg->lv->rsites) {
+		outf(f, "%s {", rsite->name);
+		out_inc_indent(f);
+
+		outf(f, "state = \"%s\"", _state_txt[rsite->state]);
+		outf(f, "site_index = %d", rsite->site_index);
+
+		/* Only non-default parameters are written */
+		if (rsite->op_mode != DM_REPLICATOR_SYNC)
+			outf(f, "operation_mode = \"%s\"",
+			     _op_mode_txt[rsite->op_mode]);
+		if (rsite->fall_behind_timeout)
+			outfc(f, "# seconds", "fall_behind_timeout = %u",
+			     rsite->fall_behind_timeout);
+		if (rsite->fall_behind_ios)
+			outfc(f, "# io operations", "fall_behind_ios = %u",
+			     rsite->fall_behind_ios);
+		if (rsite->fall_behind_data)
+			outsize(f, rsite->fall_behind_data, "fall_behind_data = %" PRIu64,
+				rsite->fall_behind_data);
+		if (rsite->state != REPLICATOR_STATE_ACTIVE && rsite->vg_name)
+			outf(f, "volume_group = \"%s\"", rsite->vg_name);
+
+		out_dec_indent(f);
+		outf(f, "}");
+	}
+
+	return 1;
+}
+
+#ifdef DEVMAPPER_SUPPORT
+static int _replicator_add_target_line(struct dev_manager *dm,
+				       struct dm_pool *mem,
+				       struct cmd_context *cmd,
+				       void **target_state,
+				       struct lv_segment *seg,
+				       struct dm_tree_node *node,
+				       uint64_t len,
+				       uint32_t *pvmove_mirror_count)
+{
+	const char *rlog_dlid;
+	struct replicator_site *rsite;
+
+	if (!seg->rlog_lv)
+		return_0;
+
+	if (!(rlog_dlid = build_dlid(dm, seg->rlog_lv->lvid.s, NULL)))
+		return_0;
+
+	dm_list_iterate_items(rsite, &seg->lv->rsites) {
+		if (!dm_tree_node_add_replicator_target(node,
+							seg->rlog_lv->size,
+							rlog_dlid,
+							seg->rlog_type,
+							rsite->site_index,
+							rsite->op_mode,
+							rsite->fall_behind_timeout,
+							rsite->fall_behind_data,
+							rsite->fall_behind_ios)) {
+			if (rsite->site_index == 0) {
+				log_error("Failed to add replicator log '%s' "
+					  "to replicator '%s'.",
+					  rlog_dlid, seg->lv->name);
+				return 0;
+			}
+			// FIXME:
+		}
+	}
+
+	return 1;
+}
+
+/* FIXME: write something useful for replicator here */
+static int _replicator_target_percent(void **target_state,
+				      percent_range_t *percent_range,
+				      struct dm_pool *mem,
+				      struct cmd_context *cmd,
+				      struct lv_segment *seg,
+				      char *params, uint64_t *total_numerator,
+				      uint64_t *total_denominator)
+{
+	return 1;
+}
+
+/* Check for module presence */
+static int _replicator_target_present(struct cmd_context *cmd,
+				      const struct lv_segment *seg __attribute((unused)),
+				      unsigned *attributes __attribute((unused)))
+{
+	static int _checked = 0;
+	static int _present = 0;
+
+	if (!_checked) {
+		_present = target_present(cmd, REPLICATOR_MODULE, 1);
+		_checked = 1;
+	}
+
+	return _present;
+}
+
+#endif
+
+static int _replicator_modules_needed(struct dm_pool *mem,
+				      const struct lv_segment *seg __attribute((unused)),
+				      struct dm_list *modules)
+{
+	if (!str_list_add(mem, modules, REPLICATOR_MODULE))
+		return_0;
+
+	if (!str_list_add(mem, modules, REPLICATOR_DEV_MODULE))
+		return_0;
+
+	return 1;
+}
+
+static void _replicator_destroy(const struct segment_type *segtype)
+{
+	dm_free((void *)segtype);
+}
+
+static struct segtype_handler _replicator_ops = {
+	.name = _replicator_name,
+	.display = _replicator_display,
+	.text_import = _replicator_text_import,
+	.text_export = _replicator_text_export,
+#ifdef DEVMAPPER_SUPPORT
+	.add_target_line = _replicator_add_target_line,
+	.target_percent = _replicator_target_percent,
+	.target_present = _replicator_target_present,
+#endif
+	.modules_needed = _replicator_modules_needed,
+	.destroy = _replicator_destroy,
+};
+
+/*
+ *  Replicator-dev  target
+ */
+static void _replicator_dev_display(const struct lv_segment *seg)
+{
+	//const char *size;
+	//uint32_t s;
+	// FIXME: debug test code for now
+	log_print("  Replicator\t\t%u", seg->area_count);
+	log_print("  Mirror size\t\t%u", seg->area_len);
+	if (seg->log_lv)
+		log_print("  Replicator log volume\t%s", seg->rlog_lv->name);
+
+}
+
+static int _add_device(struct lv_segment *seg,
+		       const char *site_name,
+		       const struct config_node *sn,
+		       uint64_t devidx)
+{
+	struct dm_pool *mem = seg->lv->vg->vgmem;
+	struct logical_volume *lv = NULL;
+	struct logical_volume *slog_lv = NULL;
+	struct replicator_site *rsite = _get_site(seg->replicator, site_name);
+	struct replicator_device *rdev;
+	const char *dev_str = NULL;
+	const char *slog_str = NULL;
+	const struct config_node *cn;
+
+	dm_list_iterate_items(rdev, &rsite->rdevices)
+		if (rdev->replicator_dev == seg)
+			return SEG_LOG_ERROR("Duplicate site found in");
+
+	if ((cn = find_config_node(sn, "sync_log"))) {
+		if (!cn->v || !cn->v->v.str)
+			return SEG_LOG_ERROR("Sync log must be a string in");
+		slog_str = cn->v->v.str;
+	}
+
+	if (!(cn = find_config_node(sn, "logical_volume")) ||
+	    !cn->v || !cn->v->v.str)
+		return SEG_LOG_ERROR("Logical volume must be a string in");
+
+	dev_str = cn->v->v.str;
+
+	if (!seg->lv->rdevice) {
+		if (slog_str)
+			return SEG_LOG_ERROR("Sync log %s defined for local "
+					     "device in", slog_str);
+
+		/* Check for device in current VG */
+		if (!(lv = find_lv(seg->lv->vg, dev_str)))
+			return SEG_LOG_ERROR("Logical volume %s not found in",
+					     dev_str);
+	} else {
+		if (!slog_str)
+			return SEG_LOG_ERROR("Sync log is missing for remote "
+					     "device in");
+		/* Check for slog device in current VG */
+		if (!(slog_lv = find_lv(seg->lv->vg, slog_str)))
+			return SEG_LOG_ERROR("Sync log %s not found in",
+					     slog_str);
+	}
+
+	if (!(rdev = dm_pool_zalloc(mem, sizeof(*rdev))))
+		return_0;
+
+	if (!(rdev->name = dm_pool_strdup(mem, dev_str)))
+		return_0;
+
+	rdev->replicator_dev = seg;
+	rdev->rsite = rsite;
+	rdev->device_index = devidx;
+
+	if (!seg->lv->rdevice) {
+		if (!replicator_dev_add_rimage(rdev, lv))
+			return SEG_LOG_ERROR("LV inconsistency found in");
+		seg->lv->rdevice = rdev;
+	} else {
+		if (!slog_str ||
+		    !(rdev->slog_name = dm_pool_strdup(mem, slog_str)))
+			return_0;
+
+		if (!replicator_dev_add_slog(rdev, slog_lv))
+			return SEG_LOG_ERROR("Sync log inconsistency found in");
+	}
+
+	dm_list_add(&rsite->rdevices, &rdev->list);// linked site list
+
+	return 1;
+}
+
+/* Import replicator segment */
+static int _replicator_dev_text_import(struct lv_segment *seg,
+				       const struct config_node *sn,
+				       struct dm_hash_table *pv_hash __attribute((unused)))
+{
+	const struct config_node *cn;
+	struct logical_volume *replicator;
+	uint64_t devidx;
+
+	if (!(cn = find_config_node(sn, "replicator")))
+		return SEG_LOG_ERROR("Replicator is missing for");
+
+	if (!cn->v || !cn->v->v.str)
+		return SEG_LOG_ERROR("Replicator must be a string for");
+
+	if (!(replicator = find_lv(seg->lv->vg, cn->v->v.str)))
+		return SEG_LOG_ERROR("Unknown replicator %s for", cn->v->v.str);
+
+	if (!replicator_add_replicator_dev(replicator, seg))
+		return_0;
+
+	log_very_verbose("replicator=%s", replicator->name);
+
+	/* Mandatory */
+	if (!find_config_node(sn, "device_index") ||
+	    !get_config_uint64(sn, "device_index", &devidx))
+		return SEG_LOG_ERROR("Could not read 'device_index' for");
+
+	/* Read devices from sites */
+	for (; sn; sn = sn->sib)
+		if (!(sn->v) && !_add_device(seg, sn->key, sn->child, devidx))
+			return_0;
+
+	if (!seg->lv->rdevice)
+		return SEG_LOG_ERROR("Replicator device without site in");
+
+	seg->rlog_lv = NULL;
+	seg->lv->status |= REPLICATOR;
+
+	return 1;
+}
+
+/* Export replicator-dev segment */
+static int _replicator_dev_text_export(const struct lv_segment *seg,
+				       struct formatter *f)
+{
+	struct replicator_site *rsite;
+	struct replicator_device *rdev;
+
+	if (!seg->replicator || !seg->lv->rdevice)
+		return_0;
+
+	outf(f, "replicator = \"%s\"", seg->replicator->name);
+	outf(f, "device_index = %" PRId64, seg->lv->rdevice->device_index);
+
+	outnl(f);
+
+	dm_list_iterate_items(rsite, &seg->replicator->rsites) {
+		dm_list_iterate_items(rdev, &rsite->rdevices) {
+			if (rdev->replicator_dev != seg)
+				continue;
+
+			outf(f, "%s {", rdev->rsite->name);
+
+			out_inc_indent(f);
+
+			outf(f, "logical_volume = \"%s\"",
+			     rdev->name ? rdev->name : rdev->lv->name);
+
+			if (rdev->slog)
+				outf(f, "sync_log = \"%s\"", rdev->slog->name);
+			else if (rdev->slog_name)
+				outf(f, "sync_log = \"%s\"", rdev->slog_name);
+
+			out_dec_indent(f);
+
+			outf(f, "}");
+		}
+	}
+
+	return 1;
+}
+
+#ifdef DEVMAPPER_SUPPORT
+/*
+ * Add target for passive site matching the device index
+ */
+static int _replicator_dev_add_target_line(struct dev_manager *dm,
+					   struct dm_pool *mem,
+					   struct cmd_context *cmd,
+					   void **target_state,
+					   struct lv_segment *seg,
+					   struct dm_tree_node *node,
+					   uint64_t len,
+					   uint32_t *pvmove_mirror_count)
+{
+	const char *replicator_dlid, *rdev_dlid, *slog_dlid;
+	struct replicator_device *rdev, *rdev_search;
+	struct replicator_site *rsite;
+	uint32_t slog_size;
+	uint32_t slog_flags;
+
+	if (!lv_is_active_replicator_dev(seg->lv)) {
+		/* Create passive linear mapping */
+		log_very_verbose("Inactive replicator %s using %s.",
+				 seg->lv->name, seg->lv->rdevice->lv->name);
+		if (!dm_tree_node_add_linear_target(node, seg->lv->size))
+			return_0;
+		if (!(rdev_dlid = build_dlid(dm, seg->lv->rdevice->lv->lvid.s, NULL)))
+			return_0;
+		return dm_tree_node_add_target_area(node, NULL, rdev_dlid, 0);
+	} else if (seg->lv->rdevice->rsite->site_index) {
+		log_error("Active site with site_index != 0 (%s, %d)",
+			  seg->lv->rdevice->rsite->name,
+			  seg->lv->rdevice->rsite->site_index);
+		return 0; /* Replicator without any active site */
+	}
+
+	/*
+	 * At this point all devices that have some connection with replicator
+	 * must be present in dm_tree
+	 */
+	if (!seg_is_replicator_dev(seg) ||
+	    !(replicator_dlid = build_dlid(dm, seg->replicator->lvid.s, NULL)))
+		return_0;
+
+	/* Select remote devices with the same device index */
+	dm_list_iterate_items(rsite, &seg->replicator->rsites) {
+		if (rsite->site_index == 0) {
+			/* Local slink0 device */
+			rdev = seg->lv->rdevice;
+		} else {
+			rdev = NULL;
+			dm_list_iterate_items(rdev_search, &rsite->rdevices) {
+				if (rdev_search->replicator_dev == seg) {
+					rdev = rdev_search;
+					break;
+				}
+			}
+
+			if (!rdev) {
+				log_error(INTERNAL_ERROR "rdev list not found.");
+				return 0;
+			}
+		}
+
+		if (!rdev->lv ||
+		    !(rdev_dlid = build_dlid(dm, rdev->lv->lvid.s, NULL)))
+			return_0;
+
+		slog_dlid = NULL;
+
+		/* Using either disk or core (in memory) log */
+		if (rdev->slog) {
+			slog_flags = DM_NOSYNC;
+			slog_size = (uint32_t) rdev->slog->size;
+			/* slog_size = 2048;  FIXME: HACK */
+			if (!(slog_dlid = build_dlid(dm, rdev->slog->lvid.s, NULL)))
+				return_0;
+		} else if (rdev->slog_name &&
+			   sscanf(rdev->slog_name, "%" PRIu32, &slog_size) == 1) {
+			slog_flags = DM_CORELOG | DM_FORCESYNC;
+			if (slog_size == 0) {
+				log_error("Failed to use empty corelog size "
+					  "in replicator '%s'.",
+					  rsite->replicator->name);
+				return 0;
+			}
+		} else  {
+			slog_flags = DM_CORELOG | DM_FORCESYNC;
+			slog_size = 0; /* NOLOG */
+		}
+
+		if (!dm_tree_node_add_replicator_dev_target(node,
+							    seg->lv->size,
+							    replicator_dlid,
+							    seg->lv->rdevice->device_index,
+							    rdev_dlid,
+							    rsite->site_index,
+							    slog_dlid,
+							    slog_flags,
+							    slog_size)) {
+			return_0;
+			/*
+			 * CHECKME: handle 'state = dropped' in future
+			 */
+		}
+	}
+
+	return 1;
+}
+
+/* FIXME: write something useful for replicator-dev here */
+static int _replicator_dev_target_percent(void **target_state,
+					  percent_range_t *percent_range,
+					  struct dm_pool *mem,
+					  struct cmd_context *cmd,
+					  struct lv_segment *seg,
+					  char *params,
+					  uint64_t *total_numerator,
+					  uint64_t *total_denominator)
+{
+	return 1;
+}
+
+/* Check for module presence */
+static int _replicator_dev_target_present(struct cmd_context *cmd,
+					  const struct lv_segment *seg __attribute((unused)),
+					  unsigned *attributes __attribute((unused)))
+{
+	static int _checked = 0;
+	static int _present = 0;
+
+	if (!_checked) {
+		_present = target_present(cmd, REPLICATOR_DEV_MODULE, 1);
+		_checked = 1;
+	}
+
+	return _present;
+}
+
+#endif
+
+static struct segtype_handler _replicator_dev_ops = {
+	.name = _replicator_name,
+	.display = _replicator_dev_display,
+	.text_import = _replicator_dev_text_import,
+	.text_export = _replicator_dev_text_export,
+#ifdef DEVMAPPER_SUPPORT
+	.add_target_line = _replicator_dev_add_target_line,
+	.target_percent = _replicator_dev_target_percent,
+	.target_present = _replicator_dev_target_present,
+#endif
+	.modules_needed = _replicator_modules_needed,
+	.destroy = _replicator_destroy,
+};
+
+#ifdef REPLICATOR_INTERNAL
+int init_replicator_segtype(struct segtype_library *seglib)
+#else /* Shared */
+int init_multiple_segtype(struct segtype_library *seglib);
+int init_multiple_segtype(struct segtype_library *seglib)
+#endif
+{
+	struct segment_type *segtype;
+
+	if (!(segtype = dm_malloc(sizeof(*segtype))))
+		return_0;
+
+	segtype->ops = &_replicator_ops;
+	segtype->name = REPLICATOR_MODULE;
+	segtype->private = NULL;
+	segtype->flags = SEG_REPLICATOR;
+
+	if (!lvm_register_segtype(seglib, segtype))
+		return_0;
+
+	log_very_verbose("Initialised segtype: " REPLICATOR_MODULE);
+
+	if (!(segtype = dm_malloc(sizeof(*segtype))))
+		return_0;
+
+	segtype->ops = &_replicator_dev_ops;
+	segtype->name = REPLICATOR_DEV_MODULE;
+	segtype->private = NULL;
+	segtype->flags = SEG_REPLICATOR_DEV;
+
+	if (!lvm_register_segtype(seglib, segtype))
+		return_0;
+
+	log_very_verbose("Initialised segtype: " REPLICATOR_DEV_MODULE);
+
+	return 1;
+}
-- 
1.7.0.1



^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 06/22] Replicator: check replicator segment
  2010-04-12 15:21 [PATCH 00/22] Replicator 100412 Zdenek Kabelac
                   ` (4 preceding siblings ...)
  2010-04-12 15:21 ` [PATCH 05/22] Replicator: add lvm support Zdenek Kabelac
@ 2010-04-12 15:21 ` Zdenek Kabelac
  2010-04-12 15:21 ` [PATCH 07/22] Replicator: extend _lv_each_dependency() rep. deps Zdenek Kabelac
                   ` (15 subsequent siblings)
  21 siblings, 0 replies; 42+ messages in thread
From: Zdenek Kabelac @ 2010-04-12 15:21 UTC (permalink / raw)
  To: lvm-devel

Check for possible problems within replicator structures.
Used also by vg_validate.

Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
 lib/metadata/merge.c             |    3 +
 lib/metadata/metadata-exported.h |    1 +
 lib/metadata/replicator_manip.c  |  152 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 156 insertions(+), 0 deletions(-)

diff --git a/lib/metadata/merge.c b/lib/metadata/merge.c
index 66ff57b..9a34daf 100644
--- a/lib/metadata/merge.c
+++ b/lib/metadata/merge.c
@@ -137,6 +137,9 @@ int check_lv_segments(struct logical_volume *lv, int complete_vg)
 			}
 		}
 
+		if (seg_is_replicator(seg) && !replicator_check_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 "
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index 7b6c7fa..6d40365 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -767,6 +767,7 @@ struct logical_volume *replicator_dev_remove_slog(struct replicator_device *rdev
 int replicator_dev_add_rimage(struct replicator_device *rdev, struct logical_volume *lv);
 struct logical_volume *replicator_dev_remove_rimage(struct replicator_device *rdev);
 
+int replicator_check_segment(const struct lv_segment *replicator_seg);
 int lv_is_active_replicator_dev(const struct logical_volume *lv);
 int lv_is_replicator(const struct logical_volume *lv);
 int lv_is_replicator_dev(const struct logical_volume *lv);
diff --git a/lib/metadata/replicator_manip.c b/lib/metadata/replicator_manip.c
index 02fd49c..7062a32 100644
--- a/lib/metadata/replicator_manip.c
+++ b/lib/metadata/replicator_manip.c
@@ -265,6 +265,158 @@ int lv_remove_replicator(struct logical_volume *lv)
 }
 #endif
 
+/*
+ * Check all replicator structures:
+ *  only non-clustered vg for replicator
+ *  only one segment in replicator LV
+ *  site has correct combination of operation_mode parameters
+ *  site and devices have correct index numbers
+ *  duplicate site names, site indexes, device names, device indexes
+ */
+int replicator_check_segment(const struct lv_segment *rseg)
+{
+	struct replicator_site *rsite, *rsiteb;
+	struct replicator_device *rdev, *rdevb;
+        struct logical_volume *lv = rseg->lv;
+	int r = 1;
+
+	if (vg_is_clustered(lv->vg)) {
+		log_error("Volume Group %s of replicator %s is clustered",
+			  lv->vg->name, lv->name);
+		return 0;
+	}
+
+	if (dm_list_size(&lv->segments) != 1) {
+		log_error("Replicator %s segment size %d != 1",
+			  lv->name, dm_list_size(&lv->segments));
+		return 0;
+	}
+
+	dm_list_iterate_items(rsite, &lv->rsites) {
+		if (rsite->op_mode == DM_REPLICATOR_SYNC) {
+			if (rsite->fall_behind_timeout) {
+				log_error("Defined fall_behind_timeout="
+					  "%d for sync replicator %s/%s.",
+					  rsite->fall_behind_timeout, lv->name,
+					  rsite->name);
+				r = 0;
+			}
+			if (rsite->fall_behind_ios) {
+				log_error("Defined fall_behind_ios="
+					  "%d for sync replicator %s/%s.",
+					  rsite->fall_behind_ios, lv->name, rsite->name);
+				r = 0;
+			}
+			if (rsite->fall_behind_data) {
+				log_error("Defined fall_behind_data="
+					  "%" PRIu64 " for sync replicator %s/%s.",
+					  rsite->fall_behind_data, lv->name, rsite->name);
+				r = 0;
+			}
+		} else {
+			if (rsite->fall_behind_timeout && rsite->fall_behind_ios) {
+				log_error("Defined fall_behind_timeout and"
+					  " fall_behind_ios for async replicator %s/%s.",
+					  lv->name, rsite->name);
+				r = 0;
+			}
+			if (rsite->fall_behind_timeout && rsite->fall_behind_data) {
+				log_error("Defined fall_behind_timeout and"
+					  " fall_behind_data for async replicator %s/%s.",
+					  lv->name, rsite->name);
+				r = 0;
+			}
+			if (rsite->fall_behind_ios && rsite->fall_behind_data) {
+				log_error("Defined fall_behind_ios and"
+					  " fall_behind_data for async replicator %s/%s.",
+					  lv->name, rsite->name);
+				r = 0;
+			}
+			if (!rsite->fall_behind_ios && !rsite->fall_behind_data &&
+			    !rsite->fall_behind_timeout) {
+				log_error("fall_behind_timeout,"
+					  " fall_behind_ios and fall_behind_data are"
+					  " undefined for async replicator %s/%s.",
+					  lv->name, rsite->name);
+				r = 0;
+			}
+		}
+		dm_list_iterate_items(rsiteb, &lv->rsites) {
+			if (rsite == rsiteb)
+				break;
+			if (strcasecmp(rsite->name, rsiteb->name) == 0) {
+				log_error("Duplicate site name"
+					  " %s detected for replicator %s.",
+					  rsite->name, lv->name);
+				r = 0;
+			}
+			if ((rsite->vg_name && rsiteb->vg_name &&
+			     strcasecmp(rsite->vg_name, rsiteb->vg_name) == 0) ||
+			    (!rsite->vg_name && !rsiteb->vg_name)) {
+				log_error("Duplicate VG name"
+					  " %s detected for replicator %s.",
+					  (rsite->vg_name) ? rsite->vg_name : "<local>",
+					  lv->name);
+				r = 0;
+			}
+			if (rsite->site_index == rsiteb->site_index) {
+				log_error("Duplicate site index"
+					  " %d detected for replicator %s/%s.",
+					  rsite->site_index, lv->name,
+					  rsite->name);
+				r = 0;
+			}
+			if (rsite->site_index > rseg->rsite_index_highest) {
+				log_error("Site index %d > %d"
+					  " (too high) for replicator %s/%s.",
+					  rsite->site_index,
+					  rseg->rsite_index_highest,
+					  lv->name, rsite->name);
+				r = 0;
+			}
+		}
+
+		dm_list_iterate_items(rdev, &rsite->rdevices) {
+			dm_list_iterate_items(rdevb, &rsite->rdevices) {
+				if (rdev == rdevb)
+					break;
+				if (rdev->slog && (rdev->slog == rdevb->slog)) {
+					log_error("Duplicate "
+						  "sync log %s detected for "
+						  "replicator %s.",
+						  rdev->slog->name, lv->name);
+					r = 0;
+				}
+				if (strcasecmp(rdev->name, rdevb->name) == 0) {
+					log_error("Duplicate "
+						  "device name %s detected "
+						  "for replicator %s.",
+						  rdev->name, lv->name);
+					r = 0;
+				}
+				if (rdev->device_index == rdevb->device_index) {
+					log_error("Duplicate "
+						  "device index %" PRId64
+						  " detected for replicator "
+						  "%s/%s.", rdev->device_index,
+						  lv->name, rsite->name);
+					r = 0;
+				}
+				if (rdev->device_index > rseg->rdevice_index_highest) {
+					log_error("Device index %" PRIu64 " > %"
+						  PRIu64 " (too high) for replicator %s/%s.",
+						  rdev->device_index,
+						  rseg->rdevice_index_highest,
+						  lv->name, rsite->name);
+					r = 0;
+				}
+			}
+		}
+	}
+
+	return r;
+}
+
 /**
  * Is this segment part of active replicator
  */
-- 
1.7.0.1



^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 07/22] Replicator: extend _lv_each_dependency() rep. deps
  2010-04-12 15:21 [PATCH 00/22] Replicator 100412 Zdenek Kabelac
                   ` (5 preceding siblings ...)
  2010-04-12 15:21 ` [PATCH 06/22] Replicator: check replicator segment Zdenek Kabelac
@ 2010-04-12 15:21 ` Zdenek Kabelac
  2010-04-12 15:21 ` [PATCH 08/22] Replicator: extend volume_group with list of VGs Zdenek Kabelac
                   ` (14 subsequent siblings)
  21 siblings, 0 replies; 42+ messages in thread
From: Zdenek Kabelac @ 2010-04-12 15:21 UTC (permalink / raw)
  To: lvm-devel

Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
 lib/metadata/metadata.c |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index a4f1948..dcbaeff 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -1976,6 +1976,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) {
@@ -1986,6 +1988,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;
-- 
1.7.0.1



^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 08/22] Replicator: extend volume_group with list of VGs
  2010-04-12 15:21 [PATCH 00/22] Replicator 100412 Zdenek Kabelac
                   ` (6 preceding siblings ...)
  2010-04-12 15:21 ` [PATCH 07/22] Replicator: extend _lv_each_dependency() rep. deps Zdenek Kabelac
@ 2010-04-12 15:21 ` Zdenek Kabelac
  2010-04-26 14:26   ` Alasdair G Kergon
  2010-04-26 14:27   ` Alasdair G Kergon
  2010-04-12 15:21 ` [PATCH 09/22] Replicator: add sorted vgs_list Zdenek Kabelac
                   ` (13 subsequent siblings)
  21 siblings, 2 replies; 42+ messages in thread
From: Zdenek Kabelac @ 2010-04-12 15:21 UTC (permalink / raw)
  To: lvm-devel

Add linked list of opened VGs. List keeps the information
about needed and locked and opened VGs for replicator target.
Also add 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.

Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
 lib/metadata/metadata-exported.h |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index 6d40365..9c73dba 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -250,6 +250,10 @@ struct volume_group {
 
 	struct dm_list tags;
 
+        /* List of wanted/locked and opened VGs */
+	struct dm_list vgs;
+	uint32_t missing_vgs;
+
 	/*
 	 * FIXME: Move the next fields into a different struct?
 	 */
-- 
1.7.0.1



^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 09/22] Replicator: add sorted vgs_list
  2010-04-12 15:21 [PATCH 00/22] Replicator 100412 Zdenek Kabelac
                   ` (7 preceding siblings ...)
  2010-04-12 15:21 ` [PATCH 08/22] Replicator: extend volume_group with list of VGs Zdenek Kabelac
@ 2010-04-12 15:21 ` Zdenek Kabelac
  2010-04-26 14:34   ` Alasdair G Kergon
  2010-04-12 15:21 ` [PATCH 10/22] Replicator: add find_replicator_vgs Zdenek Kabelac
                   ` (12 subsequent siblings)
  21 siblings, 1 reply; 42+ messages in thread
From: Zdenek Kabelac @ 2010-04-12 15:21 UTC (permalink / raw)
  To: lvm-devel

Introduce struct vgs_list 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:
vgs_list_add() add new vgs_list entry.
vgs_list_lookup() search for vgs_list for vg_name.
vgs_list_read() open list of VGs.
vgs_list_release() close VGs in reversed order.

Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
 lib/metadata/metadata-exported.h |   20 ++++++
 lib/metadata/replicator_manip.c  |  138 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 158 insertions(+), 0 deletions(-)

diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index 9c73dba..0f00d7a 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -288,6 +288,15 @@ struct lv_segment_area {
 
 struct segment_type;
 
+/* List with vg_name, vgid and flags */
+struct vgs_list {
+	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,
@@ -780,6 +789,17 @@ 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 vgs_list *vgs_list_add(struct dm_pool *mem,
+			      struct dm_list *vg_nlist,
+			      const char *vg_name, const char *vgid,
+			      uint32_t flags);
+struct vgs_list *vgs_list_lookup(struct dm_list *vg_nlist,
+				 const char *vg_name);
+
+int vgs_list_read(struct cmd_context *cmd, struct dm_list *vgs_list,
+		  struct vgs_list *vnl_vg);
+void vgs_list_release(struct dm_list *vgs_list,
+		      struct vgs_list *vnl_vg);
 
 struct logical_volume *find_pvmove_lv(struct volume_group *vg,
 				      struct device *dev, uint32_t lv_type);
diff --git a/lib/metadata/replicator_manip.c b/lib/metadata/replicator_manip.c
index 7062a32..8b5d8fe 100644
--- a/lib/metadata/replicator_manip.c
+++ b/lib/metadata/replicator_manip.c
@@ -490,3 +490,141 @@ struct logical_volume *first_replicator_dev(const struct logical_volume *lv)
 
 	return NULL;
 }
+
+/**
+ * Add VG to sorted VGs list
+ *
+ * Maintain the alphabeticaly ordered list, avoid duplications.
+ *
+ * \return
+ * Returns newly created or already present vgs_list entry.
+ * Returns NULL in error case.
+ */
+struct vgs_list *vgs_list_add(struct dm_pool *mem,
+			      struct dm_list *list,
+			      const char *vg_name,
+			      const char *vgid,
+			      uint32_t flags)
+{
+	struct vgs_list *vgsl, *ins;
+
+	/* Is already in the list ? */
+	if ((vgsl = vgs_list_lookup(list, vg_name)))
+		return vgsl;
+
+	if (!(vgsl = dm_pool_alloc(mem, sizeof(*vgsl)))) {
+		log_error("Allocation of vgs_list failed.");
+		return NULL;
+	}
+
+	if (!(vgsl->vg_name = dm_pool_strdup(mem, vg_name))) {
+		dm_pool_free(mem, vgsl);
+		log_error("Allocation of vg_name failed.");
+		return NULL;
+	}
+
+	if (vgid &&
+	    !(vgsl->vgid = dm_pool_strdup(mem, vgid))) {
+		dm_pool_free(mem, vgsl);
+		log_error("Allocation of vgid failed.");
+		return NULL;
+	} else
+		vgsl->vgid = NULL;
+
+	vgsl->flags = flags;
+	vgsl->vg = NULL;
+	dm_list_iterate_items(ins, list)
+		if (strcmp(vg_name, ins->vg_name) < 0) {
+			list = &ins->list;
+			break;
+		}
+
+	dm_list_add(list, &vgsl->list);
+
+	return vgsl;
+}
+
+/**
+ * Find vgs_list with given vg_name in VGs list.
+ *
+ * \param list
+ * List of vgs_list elements.
+ * \param vg_name
+ * Name of VG to be found.
+ * \return
+ * Returns vgs_list element with VG if vg_name is found.
+ * Returns NULL if vg_name is not found.
+ */
+struct vgs_list *vgs_list_lookup(struct dm_list *l, const char *vg_name)
+{
+	struct vgs_list *vgsl;
+
+	dm_list_iterate_items(vgsl, l)
+		if (!strcmp(vg_name, vgsl->vg_name))
+			return vgsl;
+
+	return NULL;
+}
+
+/**
+ * Read and lock multiple VGs stored in vgs_list alphabeticaly.
+ * On the success list is spliced to vgs_vg->vg vgs list and left
+ * UNINITIALIZED and shall NOT be used until calling vgs_list_release().
+ *
+ * \param list
+ * Contains list of vgs_list entries.
+ * \param vgs_vg
+ * Contains master VGs list.
+ *
+ * \return
+ * Returns 1 if all VG in vgs_list are correctly openned and locked.
+ * Returns 0 if there is some problem with any VG.
+ * 
+ * (Needed to allow support for FAILED_INCONSISTENT)
+ */
+int vgs_list_read(struct cmd_context *cmd, struct dm_list *list,
+		  struct vgs_list *vgs_vg)
+{
+	struct vgs_list *vgsl;
+
+	/* Iterate through alphabeticaly ordered VGs list */
+	dm_list_iterate_items(vgsl, list) {
+		vgsl->vg = vg_read(cmd, vgsl->vg_name, vgsl->vgid, vgsl->flags);
+		if (vg_read_error(vgsl->vg)) {
+			log_debug("Failed to vg_read %s", vgsl->vg_name);
+			return 0;
+		}
+	}
+
+	dm_list_init(&vgs_vg->vg->vgs);
+	dm_list_splice(list, &vgs_vg->vg->vgs);
+
+	return 1;
+}
+
+/**
+ * Release opened and locked VGs from list.
+ * List is spliced back from vgs_vg to list.
+ *
+ * \param list
+ * Contains list of vgs_list entries.
+ * \param vgs_vg
+ * Contains master VG with vgs list of active VGs.
+ */
+void vgs_list_release(struct dm_list *list, struct vgs_list *vgs_vg)
+{
+	struct vgs_list *vgsl;
+
+	if (!vg_read_error(vgs_vg->vg)) {
+		dm_list_init(list);
+		dm_list_splice(&vgs_vg->vg->vgs, list);
+	}
+
+	dm_list_iterate_back_items(vgsl, list) {
+		if (vg_read_error(vgsl->vg))
+			vg_release(vgsl->vg);
+		else
+			unlock_and_release_vg(vgsl->vg->cmd, vgsl->vg, vgsl->vg_name);
+		vgsl->vg = NULL;
+	}
+}
-- 
1.7.0.1



^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 10/22] Replicator: add find_replicator_vgs
  2010-04-12 15:21 [PATCH 00/22] Replicator 100412 Zdenek Kabelac
                   ` (8 preceding siblings ...)
  2010-04-12 15:21 ` [PATCH 09/22] Replicator: add sorted vgs_list Zdenek Kabelac
@ 2010-04-12 15:21 ` Zdenek Kabelac
  2010-04-12 15:21 ` [PATCH 11/22] Replicator: add read and release VGs for rsites Zdenek Kabelac
                   ` (11 subsequent siblings)
  21 siblings, 0 replies; 42+ messages in thread
From: Zdenek Kabelac @ 2010-04-12 15:21 UTC (permalink / raw)
  To: lvm-devel

Adding function find_replicator_vgs() to find all needed
VGs for replicator.

This function is later called before taking lock_vol().

Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
 lib/metadata/metadata-exported.h |    2 ++
 lib/metadata/replicator_manip.c  |   32 ++++++++++++++++++++++++++++++++
 2 files changed, 34 insertions(+), 0 deletions(-)

diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index 0f00d7a..1ff8986 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -801,6 +801,8 @@ int vgs_list_read(struct cmd_context *cmd, struct dm_list *vgs_list,
 void vgs_list_release(struct dm_list *vgs_list,
 		      struct vgs_list *vnl_vg);
 
+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,
diff --git a/lib/metadata/replicator_manip.c b/lib/metadata/replicator_manip.c
index 8b5d8fe..208efea 100644
--- a/lib/metadata/replicator_manip.c
+++ b/lib/metadata/replicator_manip.c
@@ -628,3 +628,35 @@ void vgs_list_release(struct dm_list *list, struct vgs_list *vgs_vg)
 		vgsl->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 ||
+		    vgs_list_lookup(&lv->vg->vgs, rsite->vg_name))
+			continue;
+		ret = 0;
+		/* Using cmd memory pool for list allocation */
+		if (!vgs_list_add(lv->vg->cmd->mem, &lv->vg->vgs,
+				      rsite->vg_name, NULL, 0)) {
+			lv->vg->missing_vgs = 0; /* do not retry */
+			stack;
+			break;
+		}
+
+		log_debug("VG: %s added as missing.", rsite->vg_name);
+		lv->vg->missing_vgs++;
+	}
+
+	return ret;
+}
-- 
1.7.0.1



^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 11/22] Replicator: add read and release VGs for rsites
  2010-04-12 15:21 [PATCH 00/22] Replicator 100412 Zdenek Kabelac
                   ` (9 preceding siblings ...)
  2010-04-12 15:21 ` [PATCH 10/22] Replicator: add find_replicator_vgs Zdenek Kabelac
@ 2010-04-12 15:21 ` Zdenek Kabelac
  2010-04-12 15:21 ` [PATCH 12/22] Replicator: use vgs_list for _process_one_vg() Zdenek Kabelac
                   ` (10 subsequent siblings)
  21 siblings, 0 replies; 42+ messages in thread
From: Zdenek Kabelac @ 2010-04-12 15:21 UTC (permalink / raw)
  To: lvm-devel

Add function to read and release remote VGs for replicator sites
in activation context.

Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
 lib/metadata/metadata-exported.h |    3 ++
 lib/metadata/replicator_manip.c  |   56 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 59 insertions(+), 0 deletions(-)

diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index 1ff8986..d0c86d9 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -803,6 +803,9 @@ void vgs_list_release(struct dm_list *vgs_list,
 
 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,
diff --git a/lib/metadata/replicator_manip.c b/lib/metadata/replicator_manip.c
index 208efea..9682c14 100644
--- a/lib/metadata/replicator_manip.c
+++ b/lib/metadata/replicator_manip.c
@@ -660,3 +660,59 @@ int find_replicator_vgs(struct logical_volume *lv)
 
 	return ret;
 }
+
+/**
+ * Resolve all remote VGs from replicators' sites
+ * This function is used in activation context and needs all VGs already locked
+ */
+int lv_read_replicator_vgs(struct logical_volume *lv)
+{
+	struct replicator_device *rdev;
+	struct replicator_site *rsite;
+	struct volume_group *vg;
+
+	if (!lv_is_replicator_dev(lv))
+		return 1;
+
+	dm_list_iterate_items(rsite, &first_seg(lv)->replicator->rsites) {
+		if (!rsite->vg_name)
+			continue;
+		vg = vg_read(lv->vg->cmd, rsite->vg_name, 0, 0); // READ_WITHOUT_LOCK
+		if (vg_read_error(vg)) {
+			log_error("Unable to read volume group %s",
+				  rsite->vg_name);
+			goto bad;
+		}
+		rsite->vg = vg;
+		/* CHECKME: handling missing LVs needs to be better */
+		dm_list_iterate_items(rdev, &rsite->rdevices)
+			if (!(rdev->lv = find_lv(vg, rdev->name))) {
+				log_error("Unable to find %s in volume group %s",
+					  rdev->name, rsite->vg_name);
+				goto bad;
+			}
+	}
+
+	return 1;
+bad:
+	lv_release_replicator_vgs(lv);
+	return 0;
+}
+
+/**
+ * Release all VG resources taken by replicators' sites
+ * This function is used in activation context and needs all VGs already locked
+ */
+void lv_release_replicator_vgs(struct logical_volume *lv)
+{
+	struct replicator_site *rsite;
+
+	if (!lv_is_replicator_dev(lv))
+		return;
+
+	dm_list_iterate_back_items(rsite, &first_seg(lv)->replicator->rsites)
+		if (rsite->vg_name && rsite->vg) {
+			vg_release(rsite->vg);
+			rsite->vg = NULL;
+		}
+}
-- 
1.7.0.1



^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 12/22] Replicator: use vgs_list for _process_one_vg()
  2010-04-12 15:21 [PATCH 00/22] Replicator 100412 Zdenek Kabelac
                   ` (10 preceding siblings ...)
  2010-04-12 15:21 ` [PATCH 11/22] Replicator: add read and release VGs for rsites Zdenek Kabelac
@ 2010-04-12 15:21 ` Zdenek Kabelac
  2010-04-12 15:21 ` [PATCH 13/22] Replicator: use vgs_list for process_each_lv_in_vg() Zdenek Kabelac
                   ` (9 subsequent siblings)
  21 siblings, 0 replies; 42+ messages in thread
From: Zdenek Kabelac @ 2010-04-12 15:21 UTC (permalink / raw)
  To: lvm-devel

Patch modifes behavior of _process_one_vg().

In the first pass the plain vg_read() for the given VG is used.
Replicator collects sorted list of additional VGs during lock_vol().
If any VG needed by replicator is not yet opened then next iteration
loop is taken with collected VGs.

Flag vg->missing_vgs detects missing VGs.

Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
 tools/toollib.c |   56 ++++++++++++++++++++++++++++++++----------------------
 1 files changed, 33 insertions(+), 23 deletions(-)

diff --git a/tools/toollib.c b/tools/toollib.c
index c31315c..2c5ba63 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -436,37 +436,47 @@ static int _process_one_vg(struct cmd_context *cmd, const char *vg_name,
 						  struct volume_group * vg,
 						  void *handle))
 {
-	struct volume_group *vg;
+	struct dm_list vgs_list;
+	struct vgs_list *vgs_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(&vgs_list);
+	vgs_vg = vgs_list_add(cmd->mem, &vgs_list, vg_name, vgid, flags);
+	if (!vgs_vg)
+		return_0;
+
+	while (!sigint_caught()) {
+		if (!vgs_list_read(cmd, &vgs_list, vgs_vg))
+			/* Allow FAILED_INCONSISTENT through only for vgcfgrestore */
+			if (vg_read_error(vgs_vg->vg) &&
+			    (!((flags & READ_ALLOW_INCONSISTENT) &&
+			       (vg_read_error(vgs_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, &vgs_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(cmd, vg_name, vgs_vg->vg, handle);
+
+		if (vg_read_error(vgs_vg->vg)) /* FAILED_INCONSISTENT */
+			break;
+
+		if (!vgs_vg->vg->missing_vgs)
+			break;
+
+		vgs_list_release(&vgs_list, vgs_vg);
 	}
 
-	if ((ret = process_single(cmd, vg_name, vg,
-				  handle)) > ret_max)
-		ret_max = ret;
+	vgs_list_release(&vgs_list, vgs_vg);
 
-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,
-- 
1.7.0.1



^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 13/22] Replicator: use vgs_list for process_each_lv_in_vg()
  2010-04-12 15:21 [PATCH 00/22] Replicator 100412 Zdenek Kabelac
                   ` (11 preceding siblings ...)
  2010-04-12 15:21 ` [PATCH 12/22] Replicator: use vgs_list for _process_one_vg() Zdenek Kabelac
@ 2010-04-12 15:21 ` Zdenek Kabelac
  2010-04-12 15:21 ` [PATCH 14/22] Replicator: lock_vol() finds missing VGs Zdenek Kabelac
                   ` (8 subsequent siblings)
  21 siblings, 0 replies; 42+ messages in thread
From: Zdenek Kabelac @ 2010-04-12 15:21 UTC (permalink / raw)
  To: lvm-devel

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
any missing VG during LV processing.

Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
 tools/toollib.c |   47 +++++++++++++++++++++++++++++++++++++----------
 1 files changed, 37 insertions(+), 10 deletions(-)

diff --git a/tools/toollib.c b/tools/toollib.c
index 2c5ba63..598710b 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -151,6 +151,7 @@ int process_each_lv_in_vg(struct cmd_context *cmd,
 		if (!process_lv)
 			continue;
 
+		lvl->lv->vg->missing_vgs = 0;
 		ret = process_single(cmd, lvl->lv, handle);
 		if (ret != ECMD_PROCESSED && failed_lvs) {
 			if (!str_list_add(cmd->mem, failed_lvs,
@@ -159,6 +160,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->missing_vgs)
+				ret = ECMD_PROCESSED;
 		}
 		if (ret > ret_max)
 			ret_max = ret;
@@ -188,7 +191,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 vgs_list *vgs_vg;
+	struct dm_list vgs_list;
+	struct dm_list failed_lvs;
 	struct dm_list tags, lvnames;
 	struct dm_list arg_lvnames;	/* Cmdline vgname or vgname/lvname */
 	char *vglv;
@@ -198,6 +203,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_lvs);
 
 	if (argc) {
 		struct dm_list arg_vgnames;
@@ -293,13 +299,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(&vgs_list);
+		if (!(vgs_vg = vgs_list_add(cmd->mem, &vgs_list,
+					    vgname, NULL, flags))) {
+			stack;
+			return ECMD_FAILED;
+		}
 
-		if (vg_read_error(vg)) {
-			vg_release(vg);
+		if (!vgs_list_read(cmd, &vgs_list, vgs_vg)) {
+			vgs_list_release(&vgs_list, vgs_vg);
 			if (ret_max < ECMD_FAILED) {
 				log_error("Skipping volume group %s", vgname);
 				ret_max = ECMD_FAILED;
@@ -325,19 +335,36 @@ 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);
+					vgs_list_release(&vgs_list,vgs_vg);
 					return ECMD_FAILED;
 				}
 			}
 		}
 
-		ret = process_each_lv_in_vg(cmd, vg, &lvnames, tags_arg,
-					    NULL, handle, process_single);
-		unlock_and_release_vg(cmd, vg, vgname);
+		while (!sigint_caught()) {
+			ret = process_each_lv_in_vg(cmd, vgs_vg->vg, &lvnames,
+						    tags_arg, &failed_lvs,
+						    handle, process_single);
+			if (ret != ECMD_PROCESSED ||
+			    dm_list_empty(&failed_lvs))
+				break;
+
+			/* Try again with failed LVs in this VG */
+			dm_list_init(&lvnames);
+			dm_list_splice(&failed_lvs, &lvnames);
+
+			vgs_list_release(&vgs_list, vgs_vg);
+			if (!vgs_list_read(cmd, &vgs_list, vgs_vg)) {
+				ret = ECMD_FAILED; /* break */
+				break;
+			}
+		}
 		if (ret > ret_max)
 			ret_max = ret;
+
+		vgs_list_release(&vgs_list, vgs_vg);
 		if (sigint_caught())
-			break;
+			return ECMD_FAILED;
 	}
 
 	return ret_max;
-- 
1.7.0.1



^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 14/22] Replicator: lock_vol() finds missing VGs
  2010-04-12 15:21 [PATCH 00/22] Replicator 100412 Zdenek Kabelac
                   ` (12 preceding siblings ...)
  2010-04-12 15:21 ` [PATCH 13/22] Replicator: use vgs_list for process_each_lv_in_vg() Zdenek Kabelac
@ 2010-04-12 15:21 ` Zdenek Kabelac
  2010-04-12 15:21 ` [PATCH 15/22] Replicator: activate checks for missing vgs Zdenek Kabelac
                   ` (7 subsequent siblings)
  21 siblings, 0 replies; 42+ messages in thread
From: Zdenek Kabelac @ 2010-04-12 15:21 UTC (permalink / raw)
  To: lvm-devel

Find and check for all needed VGs before calling lock_vol().

Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
 lib/locking/locking.h |    4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/lib/locking/locking.h b/lib/locking/locking.h
index e7f25b9..8f6f52b 100644
--- a/lib/locking/locking.h
+++ b/lib/locking/locking.h
@@ -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) \
-- 
1.7.0.1



^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 15/22] Replicator: activate checks for missing vgs
  2010-04-12 15:21 [PATCH 00/22] Replicator 100412 Zdenek Kabelac
                   ` (13 preceding siblings ...)
  2010-04-12 15:21 ` [PATCH 14/22] Replicator: lock_vol() finds missing VGs Zdenek Kabelac
@ 2010-04-12 15:21 ` Zdenek Kabelac
  2010-04-26 14:39   ` Alasdair G Kergon
  2010-04-12 15:21 ` [PATCH 16/22] Replicator: update _create_partial_dtree() Zdenek Kabelac
                   ` (6 subsequent siblings)
  21 siblings, 1 reply; 42+ messages in thread
From: Zdenek Kabelac @ 2010-04-12 15:21 UTC (permalink / raw)
  To: lvm-devel

Activation needs to have all remote VGs locked to pass for replicator.

Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
 lib/activate/activate.c |   22 ++++++++++++++++++----
 1 files changed, 18 insertions(+), 4 deletions(-)

diff --git a/lib/activate/activate.c b/lib/activate/activate.c
index 1844cea..4aabc38 100644
--- a/lib/activate/activate.c
+++ b/lib/activate/activate.c
@@ -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,9 +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 +1029,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 +1045,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 +1127,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 +1145,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;
 }
-- 
1.7.0.1



^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 16/22] Replicator: update _create_partial_dtree()
  2010-04-12 15:21 [PATCH 00/22] Replicator 100412 Zdenek Kabelac
                   ` (14 preceding siblings ...)
  2010-04-12 15:21 ` [PATCH 15/22] Replicator: activate checks for missing vgs Zdenek Kabelac
@ 2010-04-12 15:21 ` Zdenek Kabelac
  2010-04-12 15:21 ` [PATCH 17/22] Replicator: vg with missing_vgs does not print Zdenek Kabelac
                   ` (5 subsequent siblings)
  21 siblings, 0 replies; 42+ messages in thread
From: Zdenek Kabelac @ 2010-04-12 15:21 UTC (permalink / raw)
  To: lvm-devel

Adding function _create_partial_replicator() to create
partial tree for Replicator target.

Using dm_tree_set_suspend_priority() for Replicator.

Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
 lib/activate/dev_manager.c |   75 ++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 75 insertions(+), 0 deletions(-)

diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
index dcd5000..c904858 100644
--- a/lib/activate/dev_manager.c
+++ b/lib/activate/dev_manager.c
@@ -867,6 +867,75 @@ static int _add_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree, struc
 	return 1;
 }
 
+/*
+ * Add devices from replicator
+ * use _add_dev_to_dtree() directly instead of _add_lv_to_dtree()
+ * no need to extend its check with  _slog, _rlog, _rimage
+ */
+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_dlid(dm, 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;
@@ -887,6 +956,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++)
-- 
1.7.0.1



^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 17/22] Replicator: vg with missing_vgs does not print
  2010-04-12 15:21 [PATCH 00/22] Replicator 100412 Zdenek Kabelac
                   ` (15 preceding siblings ...)
  2010-04-12 15:21 ` [PATCH 16/22] Replicator: update _create_partial_dtree() Zdenek Kabelac
@ 2010-04-12 15:21 ` Zdenek Kabelac
  2010-04-12 15:21 ` [PATCH 18/22] Replicator: add replicator to dtree Zdenek Kabelac
                   ` (4 subsequent siblings)
  21 siblings, 0 replies; 42+ messages in thread
From: Zdenek Kabelac @ 2010-04-12 15:21 UTC (permalink / raw)
  To: lvm-devel

If missed VGs do not print message and wait for retry.

Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
 tools/vgchange.c |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/tools/vgchange.c b/tools/vgchange.c
index 81c95d1..68fac86 100644
--- a/tools/vgchange.c
+++ b/tools/vgchange.c
@@ -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->missing_vgs)
+		log_print("%d logical volume(s) in volume group \"%s\" now active",
+			  lvs_in_vg_activated(vg), vg->name);
 	return ret;
 }
 
-- 
1.7.0.1



^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 18/22] Replicator: add replicator to dtree
  2010-04-12 15:21 [PATCH 00/22] Replicator 100412 Zdenek Kabelac
                   ` (16 preceding siblings ...)
  2010-04-12 15:21 ` [PATCH 17/22] Replicator: vg with missing_vgs does not print Zdenek Kabelac
@ 2010-04-12 15:21 ` Zdenek Kabelac
  2010-04-12 15:21 ` [PATCH 19/22] Replicator: do not remove of replicators' LVs Zdenek Kabelac
                   ` (3 subsequent siblings)
  21 siblings, 0 replies; 42+ messages in thread
From: Zdenek Kabelac @ 2010-04-12 15:21 UTC (permalink / raw)
  To: lvm-devel

Adding all replicator related LVs to dtree.
Start of one replicator_dev initiate start of all other related.

Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
 lib/activate/dev_manager.c |   60 +++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 59 insertions(+), 1 deletions(-)

diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
index c904858..cf39c58 100644
--- a/lib/activate/dev_manager.c
+++ b/lib/activate/dev_manager.c
@@ -1173,6 +1173,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,
@@ -1203,9 +1258,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;
-- 
1.7.0.1



^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 19/22] Replicator: do not remove of replicators' LVs
  2010-04-12 15:21 [PATCH 00/22] Replicator 100412 Zdenek Kabelac
                   ` (17 preceding siblings ...)
  2010-04-12 15:21 ` [PATCH 18/22] Replicator: add replicator to dtree Zdenek Kabelac
@ 2010-04-12 15:21 ` Zdenek Kabelac
  2010-04-12 15:21 ` [PATCH 20/22] Replicator: activate change for vgchange Zdenek Kabelac
                   ` (2 subsequent siblings)
  21 siblings, 0 replies; 42+ messages in thread
From: Zdenek Kabelac @ 2010-04-12 15:21 UTC (permalink / raw)
  To: lvm-devel

Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
 lib/metadata/lv_manip.c |    9 +++++++++
 1 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 43ca423..55040cc 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -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;
-- 
1.7.0.1



^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 20/22] Replicator: activate change for vgchange
  2010-04-12 15:21 [PATCH 00/22] Replicator 100412 Zdenek Kabelac
                   ` (18 preceding siblings ...)
  2010-04-12 15:21 ` [PATCH 19/22] Replicator: do not remove of replicators' LVs Zdenek Kabelac
@ 2010-04-12 15:21 ` Zdenek Kabelac
  2010-04-12 15:21 ` [PATCH 21/22] Replicator: add new options for replicator Zdenek Kabelac
  2010-04-12 15:21 ` [PATCH 22/22] Replicator: man pages for lvcreate, lvchange Zdenek Kabelac
  21 siblings, 0 replies; 42+ messages in thread
From: Zdenek Kabelac @ 2010-04-12 15:21 UTC (permalink / raw)
  To: lvm-devel

Activate only the first replicator-dev LV, that activates all other
related LVs from Replicator.

Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
 tools/vgchange.c |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/tools/vgchange.c b/tools/vgchange.c
index 68fac86..139a1a5 100644
--- a/tools/vgchange.c
+++ b/tools/vgchange.c
@@ -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)) &&
-- 
1.7.0.1



^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 21/22] Replicator: add new options for replicator
  2010-04-12 15:21 [PATCH 00/22] Replicator 100412 Zdenek Kabelac
                   ` (19 preceding siblings ...)
  2010-04-12 15:21 ` [PATCH 20/22] Replicator: activate change for vgchange Zdenek Kabelac
@ 2010-04-12 15:21 ` Zdenek Kabelac
  2010-04-12 15:21 ` [PATCH 22/22] Replicator: man pages for lvcreate, lvchange Zdenek Kabelac
  21 siblings, 0 replies; 42+ messages in thread
From: Zdenek Kabelac @ 2010-04-12 15:21 UTC (permalink / raw)
  To: lvm-devel

New options: addsite, delsite, replicator,
replicatorlog, replicatorlogtype.

Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
 lib/config/defaults.h            |    1 +
 lib/metadata/metadata-exported.h |    1 +
 tools/args.h                     |   13 +++++++++
 tools/commands.h                 |    7 +++++
 tools/lvcreate.c                 |   55 ++++++++++++++++++++++++++++++++++++++
 tools/lvmcmdline.c               |    9 ++++++
 tools/tools.h                    |    1 +
 7 files changed, 87 insertions(+), 0 deletions(-)

diff --git a/lib/config/defaults.h b/lib/config/defaults.h
index 22a085d..4ef94ff 100644
--- a/lib/config/defaults.h
+++ b/lib/config/defaults.h
@@ -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
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index d0c86d9..fee76d1 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -595,6 +595,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 */
diff --git a/tools/args.h b/tools/args.h
index 981f45f..4623ff6 100644
--- a/tools/args.h
+++ b/tools/args.h
@@ -66,6 +66,19 @@ arg(virtualoriginsize_ARG, '\0', "virtualoriginsize", size_mb_arg, 0)
 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(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)
diff --git a/tools/commands.h b/tools/commands.h
index 9b611de..6b43d94 100644
--- a/tools/commands.h
+++ b/tools/commands.h
@@ -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,
@@ -162,6 +165,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"
@@ -200,6 +206,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,
diff --git a/tools/lvcreate.c b/tools/lvcreate.c
index 83dda32..48f3099 100644
--- a/tools/lvcreate.c
+++ b/tools/lvcreate.c
@@ -381,6 +381,36 @@ static int _read_mirror_params(struct lvcreate_params *lp,
 	return 1;
 }
 
+static int _read_replicator_params(struct lvcreate_params *lp,
+				   struct cmd_context *cmd)
+{
+	int region_size;
+	const char *mirrorlog;
+
+	if (arg_count(cmd, regionsize_ARG)) {
+		if (arg_sign_value(cmd, regionsize_ARG, 0) == SIGN_MINUS) {
+			log_error("Negative regionsize is invalid.");
+			return 0;
+		}
+		lp->region_size = arg_uint_value(cmd, regionsize_ARG, 0);
+	} else {
+		region_size = 2 * find_config_tree_int(cmd,
+						       "activation/replicator_region_size",
+						       DEFAULT_REPLICATOR_REGION_SIZE);
+		if (region_size < 0) {
+			log_error("Negative replicator_region_size in configuration "
+				  "file is invalid.");
+			return 0;
+		}
+		lp->region_size = region_size;
+	}
+
+	if (!_validate_mirror_params(cmd, lp)) /* reuse ? */
+		return 0;
+
+	return 1;
+}
+
 static int _lvcreate_params(struct lvcreate_params *lp,
 			    struct lvcreate_cmdline_params *lcp,
 			    struct cmd_context *cmd,
@@ -388,6 +418,7 @@ static int _lvcreate_params(struct lvcreate_params *lp,
 {
 	int contiguous;
 	unsigned pagesize;
+	int i;
 
 	memset(lp, 0, sizeof(*lp));
 	memset(lcp, 0, sizeof(*lcp));
@@ -413,6 +444,9 @@ static int _lvcreate_params(struct lvcreate_params *lp,
 	if (seg_is_mirrored(lp))
 		lp->mirrors = 2;
 
+	if (seg_is_replicator(lp) || arg_count(cmd, replicator_ARG))
+		lp->replicator = 1;
+
 	if (arg_count(cmd, mirrors_ARG)) {
 		lp->mirrors = arg_uint_value(cmd, mirrors_ARG, 0) + 1;
 		if (lp->mirrors == 1)
@@ -471,6 +505,26 @@ static int _lvcreate_params(struct lvcreate_params *lp,
 		}
 	}
 
+	if (lp->replicator) {
+		log_error("--replicator for replicators");
+	} else {
+		static const struct {
+			const char *str;
+			int argname;
+		} repargs[] = {
+			{ "replicatorlog", replicatorlog_ARG },
+			{ "replicatorlog", replicatorlog_ARG },
+			{ "remotevolumegroup", remotevolumegroup_ARG }
+		};
+
+		for (i = 0; i < sizeof(repargs)/sizeof(repargs[0]); ++i)
+			if (arg_count(cmd, repargs[i].argname)) {
+			log_error("--%s is only available "
+				  "with replicators.", repargs[i].str);
+			return 0;
+		}
+	}
+
 	if (activation() && lp->segtype->ops->target_present &&
 	    !lp->segtype->ops->target_present(cmd, NULL, NULL)) {
 		log_error("%s: Required device-mapper target(s) not "
@@ -485,6 +539,7 @@ static int _lvcreate_params(struct lvcreate_params *lp,
 	if (!_lvcreate_name_params(lp, cmd, &argc, &argv) ||
 	    !_read_size_params(lp, lcp, cmd) ||
 	    !_read_stripe_params(lp, cmd) ||
+	    !_read_replicator_params(lp, cmd) ||
 	    !_read_mirror_params(lp, cmd))
 		return_0;
 
diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c
index d9ea0c7..367e8ee 100644
--- a/tools/lvmcmdline.c
+++ b/tools/lvmcmdline.c
@@ -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))) {
diff --git a/tools/tools.h b/tools/tools.h
index 75575e7..8dbabbc 100644
--- a/tools/tools.h
+++ b/tools/tools.h
@@ -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);
-- 
1.7.0.1



^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 22/22] Replicator: man pages for lvcreate, lvchange
  2010-04-12 15:21 [PATCH 00/22] Replicator 100412 Zdenek Kabelac
                   ` (20 preceding siblings ...)
  2010-04-12 15:21 ` [PATCH 21/22] Replicator: add new options for replicator Zdenek Kabelac
@ 2010-04-12 15:21 ` Zdenek Kabelac
  2010-04-26 14:49   ` Alasdair G Kergon
  21 siblings, 1 reply; 42+ messages in thread
From: Zdenek Kabelac @ 2010-04-12 15:21 UTC (permalink / raw)
  To: lvm-devel

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.

Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
 man/lvchange.8.in |   57 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 man/lvcreate.8.in |   55 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 112 insertions(+), 0 deletions(-)

diff --git a/man/lvchange.8.in b/man/lvchange.8.in
index c3cb3b2..280e6d6 100644
--- a/man/lvchange.8.in
+++ b/man/lvchange.8.in
@@ -3,10 +3,18 @@
 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 +27,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 +111,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),
diff --git a/man/lvcreate.8.in b/man/lvcreate.8.in
index 3c36b97..bc162d3 100644
--- a/man/lvcreate.8.in
+++ b/man/lvcreate.8.in
@@ -15,6 +15,8 @@ lvcreate \- create a logical volume in an existing volume group
 [\-M|\-\-persistent y|n] [\-\-minor minor]
 [\-m|\-\-mirrors Mirrors [\-\-nosync] [\-\-mirrorlog {disk|core|mirrored}] [\-\-corelog]
 [\-R|\-\-regionsize MirrorLogRegionSize]]
+[[\-\-replicatordev ReplicatedLogicalVolumeName] [\-\-site Site]]
+[\-R|\-\-regionsize ReplicatorSyncLogRegionSize]]
 [\-n|\-\-name LogicalVolumeName]
 [\-p|\-\-permission r|rw] [\-r|\-\-readahead ReadAheadSectors|auto|none]
 [\-t|\-\-test]
@@ -35,6 +37,22 @@ VolumeGroupName [PhysicalVolumePath[:PE[-PE]]...]
 OriginalLogicalVolumePath | 
 [\-s|\-\-snapshot]
 VolumeGroupName \-\-virtualsize VirtualSize}
+.br
+
+.br
+.B lvcreate
+{\-l|\-\-extents LogicalExtentsNumber[%{VG|FREE|ORIGIN}] |
+ \-L|\-\-size LogicalVolumeSize[bBsSkKmMgGtTpPeE] |
+ \-\-replicatorlog ReplicatorLogLV}
+[\-\-replicatorlogtype ReplicatorLogType]
+[\-\-replicatorsynclog {disk|core}]
+[\-R|\-\-regionsize ReplicatorSyncLogRegionSize]]
+[\-\-nosync]
+\-n|\-\-name ReplicatorLogicalVolumeName
+\-\-replicator
+VolumeGroupName
+.br
+
 .SH DESCRIPTION
 lvcreate creates a new logical volume in a volume group ( see
 .B vgcreate(8), vgchange(8)
@@ -119,6 +137,38 @@ device is activated, for example, after every reboot.  Using "mirrored"
 will create a persistent log that is itself mirrored.
 
 The optional argument --corelog is equivalent to --mirrorlog core.
+.TP
+.I \-\-replicator
+Creates empty replicator logical volume. ( see
+.B lvchange(8)
+) for options, how to customize created replicator LV.
+
+Specifying optional argument --nosync will cause the creation
+of the replicator to skip the initial resynchronization. Any data written
+afterwards will be replicator, but the original contents will not be
+copied.  This is useful for skipping a potentially long and resource
+intensive initial sync of an empty device.
+
+The optional argument --replicatorsynclog specifies the type of synclog to be
+used. The default is disk, which is persistent and requires a small amount of
+storage space, usually on a separate device from the data being replicated.
+Using core means the replicator is regenerated by copying the data from the
+first device again each time the device is activated, for example, after every
+reboot.
+
+The optional argument --replicatorlog specifies the LogicalVolumeName of the
+LV to be used as the main backing store device for keeping replicator master
+log. If not specified, log is allocated with given -L|--size. Note: This
+backing store device should be very fast and reliable and storage (i.e. raid1),
+so should be selected with special care.
+
+The optional argument --replicatorlogtype specifies type of the backing store
+log. The default and currently the only valid and supported type is ringbuffer.
+
+.TP
+.I \-\-replicatordev
+Creates empty replicated logical volume. If the --site is not specified, local
+site is found inside replicator LV.
 
 .TP
 .I \-n, \-\-name LogicalVolumeName
@@ -237,10 +287,15 @@ under 100MB of actual data on it.
 creates a linear logical volume "vg00/lvol1" using physical extents
 /dev/sda:0-7 and /dev/sdb:0-7 for allocation of extents.
 
+"lvcreate -L 1G -n replicator0 vg00"
+.br
+creates an empty replicator logical volume "vg00/replicator0" and hidden backing
+store volume vg00/replicator0_rlog of size 1G.
 
 .SH SEE ALSO
 .BR lvm (8), 
 .BR vgcreate (8), 
+.BR lvchange (8)
 .BR lvremove (8), 
 .BR lvrename (8)
 .BR lvextend (8), 
-- 
1.7.0.1



^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 01/22] Add dm_list_splice() for list join.
  2010-04-12 15:21 ` [PATCH 01/22] Add dm_list_splice() for list join Zdenek Kabelac
@ 2010-04-14 11:38   ` Petr Rockai
  2010-04-26 13:15   ` Alasdair G Kergon
  1 sibling, 0 replies; 42+ messages in thread
From: Petr Rockai @ 2010-04-14 11:38 UTC (permalink / raw)
  To: lvm-devel

Zdenek Kabelac <zkabelac@redhat.com> writes:
> --- a/libdm/datastruct/list.c
> +++ b/libdm/datastruct/list.c
> @@ -144,3 +144,15 @@ unsigned int dm_list_size(const struct dm_list *head)
>  
>  	return s;
>  }
> +
> +void dm_list_splice(struct dm_list *list, struct dm_list *head)
> +{
> +	struct dm_list *first = list->n;
> +	struct dm_list *last = list->p;
> +	struct dm_list *at = head->n;
> +
> +	first->p = head;
> +	head->n = first;
> +	last->n = at;
> +	at->p = last;
> +}

> --- a/libdm/libdevmapper.h
> +++ b/libdm/libdevmapper.h
> @@ -715,6 +715,11 @@ void dm_list_del(struct dm_list *elem);
>  void dm_list_move(struct dm_list *head, struct dm_list *elem);
>  
>  /*
> + * Join 'list' to 'head'.
> + */
> +void dm_list_splice(struct dm_list *list, struct dm_list *head);
> +
> +/*
>   * Is the list empty?
>   */
>  int dm_list_empty(const struct dm_list *head);

Ack. Please check in.

Yours,
   Petr.



^ permalink raw reply	[flat|nested] 42+ messages in thread

* [PATCH 01/22] Add dm_list_splice() for list join.
  2010-04-12 15:21 ` [PATCH 01/22] Add dm_list_splice() for list join Zdenek Kabelac
  2010-04-14 11:38   ` Petr Rockai
@ 2010-04-26 13:15   ` Alasdair G Kergon
  2010-04-26 13:23     ` Alasdair G Kergon
  1 sibling, 1 reply; 42+ messages in thread
From: Alasdair G Kergon @ 2010-04-26 13:15 UTC (permalink / raw)
  To: lvm-devel

On Mon, Apr 12, 2010 at 05:21:29PM +0200, Zdenek Kabelac wrote:
> Introduce dm_list_splice to join two lists.

OK, but do please retain the style and conventions of the existing functions.

> +void dm_list_splice(struct dm_list *list, struct dm_list *head)

Based on existing conventions, the code appears to implement:
  dm_list_splice_h(struct dm_list *head, struct dm_list *list)

Try the following (untested) instead:

/*
 * 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);

	head1->p->n = head;
	head1->n->p = head->p;

	head->p->n = head1->n;
	head->p = head1->p;

	dm_list_init(head1);
}

Of if you genuinely require the _h version (i.e. the elements are ordered and
you can't choose to retain 'head1' for the combined list instead of 'head.)

/*
 * Join two lists together.
 * This moves all the elements of the list 'head1' to the front of the list
 * 'head', leaving 'head1' empty.
 */
void dm_list_splice_h(struct dm_list *head, struct dm_list *head1)
{
	assert(head->n);
	assert(head1->n);

	head1->n->p = head;
	head1->p->n = head->n;

	head->n->p = head1->p;
	head->n = head1->n;

	dm_list_init(head1);
}

Alasdair



^ permalink raw reply	[flat|nested] 42+ messages in thread

* [PATCH 01/22] Add dm_list_splice() for list join.
  2010-04-26 13:15   ` Alasdair G Kergon
@ 2010-04-26 13:23     ` Alasdair G Kergon
  0 siblings, 0 replies; 42+ messages in thread
From: Alasdair G Kergon @ 2010-04-26 13:23 UTC (permalink / raw)
  To: lvm-devel

Need to check for empty lists too.

Alasdair



^ permalink raw reply	[flat|nested] 42+ messages in thread

* [PATCH 02/22] API change for args of process_each_lv_in_vg()
  2010-04-12 15:21 ` [PATCH 02/22] API change for args of process_each_lv_in_vg() Zdenek Kabelac
@ 2010-04-26 13:34   ` Alasdair G Kergon
  2010-04-26 13:46   ` Mike Snitzer
  1 sibling, 0 replies; 42+ messages in thread
From: Alasdair G Kergon @ 2010-04-26 13:34 UTC (permalink / raw)
  To: lvm-devel

On Mon, Apr 12, 2010 at 05:21:30PM +0200, Zdenek Kabelac wrote:
> Patch adds failed_lvs 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.
 
OK.

Alasdair



^ permalink raw reply	[flat|nested] 42+ messages in thread

* [PATCH 02/22] API change for args of process_each_lv_in_vg()
  2010-04-12 15:21 ` [PATCH 02/22] API change for args of process_each_lv_in_vg() Zdenek Kabelac
  2010-04-26 13:34   ` Alasdair G Kergon
@ 2010-04-26 13:46   ` Mike Snitzer
  1 sibling, 0 replies; 42+ messages in thread
From: Mike Snitzer @ 2010-04-26 13:46 UTC (permalink / raw)
  To: lvm-devel

On Mon, Apr 12 2010 at 11:21am -0400,
Zdenek Kabelac <zkabelac@redhat.com> wrote:

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

Alasdair's recent comment highlighted this change.  Minor nit, maybe
rename the 'failed_lvs' to 'failed_lvnames'?

Mike



^ permalink raw reply	[flat|nested] 42+ messages in thread

* [PATCH 03/22] Replicator: add libdm support
  2010-04-12 15:21 ` [PATCH 03/22] Replicator: add libdm support Zdenek Kabelac
@ 2010-04-26 13:46   ` Alasdair G Kergon
  2010-04-26 14:12     ` Zdenek Kabelac
  0 siblings, 1 reply; 42+ messages in thread
From: Alasdair G Kergon @ 2010-04-26 13:46 UTC (permalink / raw)
  To: lvm-devel

On Mon, Apr 12, 2010 at 05:21:31PM +0200, Zdenek Kabelac wrote:
> index aa8ad5c..3ab5ea2 100644
> --- a/libdm/libdevmapper.h
> +++ b/libdm/libdevmapper.h
> @@ -439,6 +439,37 @@ int dm_tree_node_add_mirror_target_log(struct dm_tree_node *node,
>  					  const char *log_uuid,
>  					  unsigned area_count,
>  					  uint32_t flags);

Add comment lines that clearly separate out this section of the header file,
indicating that the functionality and API are not yet frozen.

> +
> +/* Replicator operation mode */
> +typedef enum {

> +/* Replicator-log has a list of sites */
> +/* CHECKME: maybe move to seg_area too? */

Stick with 'FIXME' for anything like that.

> @@ -1688,6 +1807,9 @@ int dm_tree_preload_children(struct dm_tree_node *dnode,
>  			}
>  		}
>  
> +		if (child->activation_priority != 0)
> +			continue;
> +

That change could affect non-replicator code: please separate it out and
explain the reasoning.

> +	if (rsite_index == 0) {

Stick with !rsite_index.  (Or if '0' has a special meaning use #define.)

Alasdair



^ permalink raw reply	[flat|nested] 42+ messages in thread

* [PATCH 04/22] Replicator: suspend/deactivate replicator
  2010-04-12 15:21 ` [PATCH 04/22] Replicator: suspend/deactivate replicator Zdenek Kabelac
@ 2010-04-26 13:50   ` Alasdair G Kergon
  0 siblings, 0 replies; 42+ messages in thread
From: Alasdair G Kergon @ 2010-04-26 13:50 UTC (permalink / raw)
  To: lvm-devel

On Mon, Apr 12, 2010 at 05:21:32PM +0200, Zdenek Kabelac wrote:
> Introducing dm_tree_set_suspend_priority() for suspending replicator
> control target before deactivation of replicator-dev target.
 
Existing code paths are affected by this.

Again, please provide a more-detailed explanation of the new logic and
why it will not break any existing code.

Alasdair



^ permalink raw reply	[flat|nested] 42+ messages in thread

* [PATCH 05/22] Replicator: add lvm support
  2010-04-12 15:21 ` [PATCH 05/22] Replicator: add lvm support Zdenek Kabelac
@ 2010-04-26 14:10   ` Alasdair G Kergon
  0 siblings, 0 replies; 42+ messages in thread
From: Alasdair G Kergon @ 2010-04-26 14:10 UTC (permalink / raw)
  To: lvm-devel

On Mon, Apr 12, 2010 at 05:21:33PM +0200, Zdenek Kabelac wrote:
> 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.
 
> +++ b/lib/metadata/replicator_manip.c

> +#include <inttypes.h>
> +#include <sys/types.h>
> +#include "libdevmapper.h"
> +#include "lvm-types.h"
> +
> +#include "activate.h"
> +#include "archiver.h"
> +#include "defaults.h"
> +#include "label.h"
> +#include "lib.h"
> +#include "locking.h"
> +#include "lv_alloc.h"
> +#include "lvm-string.h"
> +#include "metadata.h"
> +#include "segtype.h"
> +#include "toolcontext.h"

Please clean up those includes: First one is required to be "lib.h" and then
you'll find several of the others listed are already included!

Alasdair



^ permalink raw reply	[flat|nested] 42+ messages in thread

* [PATCH 03/22] Replicator: add libdm support
  2010-04-26 13:46   ` Alasdair G Kergon
@ 2010-04-26 14:12     ` Zdenek Kabelac
  0 siblings, 0 replies; 42+ messages in thread
From: Zdenek Kabelac @ 2010-04-26 14:12 UTC (permalink / raw)
  To: lvm-devel

Dne 26.4.2010 15:46, Alasdair G Kergon napsal(a):
> On Mon, Apr 12, 2010 at 05:21:31PM +0200, Zdenek Kabelac wrote:
>> index aa8ad5c..3ab5ea2 100644
>> --- a/libdm/libdevmapper.h
>> +++ b/libdm/libdevmapper.h
>> @@ -439,6 +439,37 @@ int dm_tree_node_add_mirror_target_log(struct dm_tree_node *node,
>>  					  const char *log_uuid,
>>  					  unsigned area_count,
>>  					  uint32_t flags);
> 
> Add comment lines that clearly separate out this section of the header file,
> indicating that the functionality and API are not yet frozen.
> 
>> +
>> +/* Replicator operation mode */
>> +typedef enum {
> 
>> +/* Replicator-log has a list of sites */
>> +/* CHECKME: maybe move to seg_area too? */
> 
> Stick with 'FIXME' for anything like that.
> 
>> @@ -1688,6 +1807,9 @@ int dm_tree_preload_children(struct dm_tree_node *dnode,
>>  			}
>>  		}
>>  
>> +		if (child->activation_priority != 0)
>> +			continue;
>> +
> 
> That change could affect non-replicator code: please separate it out and
> explain the reasoning.

True - this code seems to be no longer needed - as it's been hack to avoid
some strange tree loading in some past versions of replicator.

Zdenek



^ permalink raw reply	[flat|nested] 42+ messages in thread

* [PATCH 08/22] Replicator: extend volume_group with list of VGs
  2010-04-12 15:21 ` [PATCH 08/22] Replicator: extend volume_group with list of VGs Zdenek Kabelac
@ 2010-04-26 14:26   ` Alasdair G Kergon
  2010-04-26 14:39     ` Zdenek Kabelac
  2010-04-26 14:27   ` Alasdair G Kergon
  1 sibling, 1 reply; 42+ messages in thread
From: Alasdair G Kergon @ 2010-04-26 14:26 UTC (permalink / raw)
  To: lvm-devel

On Mon, Apr 12, 2010 at 05:21:36PM +0200, Zdenek Kabelac wrote:
> Add linked list of opened VGs. List keeps the information
> about needed and locked and opened VGs for replicator target.
> Also add 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.
 
> diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
> index 6d40365..9c73dba 100644
> --- a/lib/metadata/metadata-exported.h
> +++ b/lib/metadata/metadata-exported.h
> @@ -250,6 +250,10 @@ struct volume_group {
> +        /* List of wanted/locked and opened VGs */
> +	struct dm_list vgs;
> +	uint32_t missing_vgs;

Can we think up more-specific names?

vg->vgs isn't very informative.

Alasdair



^ permalink raw reply	[flat|nested] 42+ messages in thread

* [PATCH 08/22] Replicator: extend volume_group with list of VGs
  2010-04-12 15:21 ` [PATCH 08/22] Replicator: extend volume_group with list of VGs Zdenek Kabelac
  2010-04-26 14:26   ` Alasdair G Kergon
@ 2010-04-26 14:27   ` Alasdair G Kergon
  2010-04-26 14:35     ` Zdenek Kabelac
  1 sibling, 1 reply; 42+ messages in thread
From: Alasdair G Kergon @ 2010-04-26 14:27 UTC (permalink / raw)
  To: lvm-devel

Also initialise the new fields and add to vg_validate as part of this patch, to
ensure internal data consistency.

Alasdair



^ permalink raw reply	[flat|nested] 42+ messages in thread

* [PATCH 09/22] Replicator: add sorted vgs_list
  2010-04-12 15:21 ` [PATCH 09/22] Replicator: add sorted vgs_list Zdenek Kabelac
@ 2010-04-26 14:34   ` Alasdair G Kergon
  2010-04-26 14:56     ` Zdenek Kabelac
  0 siblings, 1 reply; 42+ messages in thread
From: Alasdair G Kergon @ 2010-04-26 14:34 UTC (permalink / raw)
  To: lvm-devel

On Mon, Apr 12, 2010 at 05:21:37PM +0200, Zdenek Kabelac wrote:
> Introduce struct vgs_list to store information about needed
> volume group name, vgid, flags and the pointer to opened VG.
 
Why does this need a new structure?
How does this interact with internal caches?
How does this interact with 'struct volume_group' itself?  (The fields are
already part of it so why is a new struct needed?)

Alasdair



^ permalink raw reply	[flat|nested] 42+ messages in thread

* [PATCH 08/22] Replicator: extend volume_group with list of VGs
  2010-04-26 14:27   ` Alasdair G Kergon
@ 2010-04-26 14:35     ` Zdenek Kabelac
  0 siblings, 0 replies; 42+ messages in thread
From: Zdenek Kabelac @ 2010-04-26 14:35 UTC (permalink / raw)
  To: lvm-devel

Dne 26.4.2010 16:27, Alasdair G Kergon napsal(a):
> Also initialise the new fields and add to vg_validate as part of this patch, to
> ensure internal data consistency.

My plan here is to introduce one common routine for creation of volume_group
structure - not yet finished - so it should be handled there.

For now there is 'lazy' initialization of fields before it's usage - of
course, requires to not touch these fields on unexpected occasions.
This should be fixed once the common routine will be there.

Zdenek



^ permalink raw reply	[flat|nested] 42+ messages in thread

* [PATCH 15/22] Replicator: activate checks for missing vgs
  2010-04-12 15:21 ` [PATCH 15/22] Replicator: activate checks for missing vgs Zdenek Kabelac
@ 2010-04-26 14:39   ` Alasdair G Kergon
  0 siblings, 0 replies; 42+ messages in thread
From: Alasdair G Kergon @ 2010-04-26 14:39 UTC (permalink / raw)
  To: lvm-devel

On Mon, Apr 12, 2010 at 05:21:43PM +0200, Zdenek Kabelac wrote:
> Activation needs to have all remote VGs locked to pass for replicator.
 
> -	if (lv)
> +	if (lv) {
> +		lv_release_replicator_vgs(lv);
>  		vg_release(lv->vg);

Perhaps vg_release() should be sufficient here on its own?
- If other VGs are linked of it, they must necessarily also be released without the
caller needing to specify that explicitly?

Alasdair



^ permalink raw reply	[flat|nested] 42+ messages in thread

* [PATCH 08/22] Replicator: extend volume_group with list of VGs
  2010-04-26 14:26   ` Alasdair G Kergon
@ 2010-04-26 14:39     ` Zdenek Kabelac
  0 siblings, 0 replies; 42+ messages in thread
From: Zdenek Kabelac @ 2010-04-26 14:39 UTC (permalink / raw)
  To: lvm-devel

Dne 26.4.2010 16:26, Alasdair G Kergon napsal(a):
> On Mon, Apr 12, 2010 at 05:21:36PM +0200, Zdenek Kabelac wrote:
>> Add linked list of opened VGs. List keeps the information
>> about needed and locked and opened VGs for replicator target.
>> Also add 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.
>  
>> diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
>> index 6d40365..9c73dba 100644
>> --- a/lib/metadata/metadata-exported.h
>> +++ b/lib/metadata/metadata-exported.h
>> @@ -250,6 +250,10 @@ struct volume_group {
>> +        /* List of wanted/locked and opened VGs */
>> +	struct dm_list vgs;
>> +	uint32_t missing_vgs;
> 
> Can we think up more-specific names?
> 
> vg->vgs isn't very informative.
> 

In fact I've had there some different names - like remote_vgs, needed_vgs,
deps_vgs....
but I could not decide - and as we now already have  pvs, lvs,   vgs seems to
be natural extension of naming concept.

vgs - is list of vgnames and flags for openning, including the vg itself -
thus remote_vgs doesn't fit. Needed - seems plain ugly.

So I'm open for new names here - note there are some manipulation functions
which should also use this name.

Zdenek



^ permalink raw reply	[flat|nested] 42+ messages in thread

* [PATCH 22/22] Replicator: man pages for lvcreate, lvchange
  2010-04-12 15:21 ` [PATCH 22/22] Replicator: man pages for lvcreate, lvchange Zdenek Kabelac
@ 2010-04-26 14:49   ` Alasdair G Kergon
  0 siblings, 0 replies; 42+ messages in thread
From: Alasdair G Kergon @ 2010-04-26 14:49 UTC (permalink / raw)
  To: lvm-devel

On Mon, Apr 12, 2010 at 05:21:50PM +0200, Zdenek Kabelac wrote:
> +[\-\-activesite Site]
> +[\-\-passivesite Site]

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

Inconsistency.  Does it or does it not take 'Site' as an argument?
Can both be set together as the synopsis implies, or not?

What combinations of those args are meant to be permitted, or not?
--activesite site1 --passivesite site1  ?

(If it's either/or, use '|' or split into 2 args.)

Alasdair



^ permalink raw reply	[flat|nested] 42+ messages in thread

* [PATCH 09/22] Replicator: add sorted vgs_list
  2010-04-26 14:34   ` Alasdair G Kergon
@ 2010-04-26 14:56     ` Zdenek Kabelac
  2010-04-26 18:01       ` Dave Wysochanski
  0 siblings, 1 reply; 42+ messages in thread
From: Zdenek Kabelac @ 2010-04-26 14:56 UTC (permalink / raw)
  To: lvm-devel

Dne 26.4.2010 16:34, Alasdair G Kergon napsal(a):
> On Mon, Apr 12, 2010 at 05:21:37PM +0200, Zdenek Kabelac wrote:
>> Introduce struct vgs_list to store information about needed
>> volume group name, vgid, flags and the pointer to opened VG.
>  
> Why does this need a new structure?

We don't have any similar one - I would be aware of.

Using new structure here seems to simplify modification of routines to be able
to process some loops multiple times  - i.e. code changes are minimal to
extend it for work with remote VGs.


> How does this interact with internal caches?

There is no interaction  - VGs are opened in alphabetical order via standard
lvm mechanism - there are no peeks into internal caches.

Technically we could find names in caches - but we should also keep locks for
all VGs during activation so noone changes them.

> How does this interact with 'struct volume_group' itself?  (The fields are
> already part of it so why is a new struct needed?)

We keep list of needed VGs outside in command - once we open 'master' VG -
list is moved (spliced) to internal VG list - then it's filled with
potentially missing 'other VGs' - later - if there was found problem in
processing caused by missing VG - list is taken out of VG - and in
alphabetical order opened again. And this loop iterates until either all
missing VGs are satisfied or some VG couldn't be opened -> failing resource.
This is a bit tricky - but we do not need to put things to global structure
like cmd_context in this case.

Zdenek



^ permalink raw reply	[flat|nested] 42+ messages in thread

* [PATCH 09/22] Replicator: add sorted vgs_list
  2010-04-26 14:56     ` Zdenek Kabelac
@ 2010-04-26 18:01       ` Dave Wysochanski
  0 siblings, 0 replies; 42+ messages in thread
From: Dave Wysochanski @ 2010-04-26 18:01 UTC (permalink / raw)
  To: lvm-devel

On Mon, 2010-04-26 at 16:56 +0200, Zdenek Kabelac wrote:
> Dne 26.4.2010 16:34, Alasdair G Kergon napsal(a):
> > On Mon, Apr 12, 2010 at 05:21:37PM +0200, Zdenek Kabelac wrote:
> >> Introduce struct vgs_list to store information about needed
> >> volume group name, vgid, flags and the pointer to opened VG.
> >  
> > Why does this need a new structure?
> 
> We don't have any similar one - I would be aware of.
> 

It will likely also be very useful for certain library operations that
involve multiple VGs (vgsplit, vgmerge) - I started looking at
refactoring the vgsplit/vgmerge code to use this new structure (or
something very close to it).



^ permalink raw reply	[flat|nested] 42+ messages in thread

* [PATCH 22/22] Replicator: man pages for lvcreate, lvchange
  2010-03-30 15:17 [PATCH 00/22] Replicator 100430 Zdenek Kabelac
@ 2010-03-30 15:17 ` Zdenek Kabelac
  0 siblings, 0 replies; 42+ messages in thread
From: Zdenek Kabelac @ 2010-03-30 15:17 UTC (permalink / raw)
  To: lvm-devel

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.

Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
 man/lvchange.8.in |   57 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 man/lvcreate.8.in |   55 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 112 insertions(+), 0 deletions(-)

diff --git a/man/lvchange.8.in b/man/lvchange.8.in
index c3cb3b2..280e6d6 100644
--- a/man/lvchange.8.in
+++ b/man/lvchange.8.in
@@ -3,10 +3,18 @@
 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 +27,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 +111,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),
diff --git a/man/lvcreate.8.in b/man/lvcreate.8.in
index 3c36b97..bc162d3 100644
--- a/man/lvcreate.8.in
+++ b/man/lvcreate.8.in
@@ -15,6 +15,8 @@ lvcreate \- create a logical volume in an existing volume group
 [\-M|\-\-persistent y|n] [\-\-minor minor]
 [\-m|\-\-mirrors Mirrors [\-\-nosync] [\-\-mirrorlog {disk|core|mirrored}] [\-\-corelog]
 [\-R|\-\-regionsize MirrorLogRegionSize]]
+[[\-\-replicatordev ReplicatedLogicalVolumeName] [\-\-site Site]]
+[\-R|\-\-regionsize ReplicatorSyncLogRegionSize]]
 [\-n|\-\-name LogicalVolumeName]
 [\-p|\-\-permission r|rw] [\-r|\-\-readahead ReadAheadSectors|auto|none]
 [\-t|\-\-test]
@@ -35,6 +37,22 @@ VolumeGroupName [PhysicalVolumePath[:PE[-PE]]...]
 OriginalLogicalVolumePath | 
 [\-s|\-\-snapshot]
 VolumeGroupName \-\-virtualsize VirtualSize}
+.br
+
+.br
+.B lvcreate
+{\-l|\-\-extents LogicalExtentsNumber[%{VG|FREE|ORIGIN}] |
+ \-L|\-\-size LogicalVolumeSize[bBsSkKmMgGtTpPeE] |
+ \-\-replicatorlog ReplicatorLogLV}
+[\-\-replicatorlogtype ReplicatorLogType]
+[\-\-replicatorsynclog {disk|core}]
+[\-R|\-\-regionsize ReplicatorSyncLogRegionSize]]
+[\-\-nosync]
+\-n|\-\-name ReplicatorLogicalVolumeName
+\-\-replicator
+VolumeGroupName
+.br
+
 .SH DESCRIPTION
 lvcreate creates a new logical volume in a volume group ( see
 .B vgcreate(8), vgchange(8)
@@ -119,6 +137,38 @@ device is activated, for example, after every reboot.  Using "mirrored"
 will create a persistent log that is itself mirrored.
 
 The optional argument --corelog is equivalent to --mirrorlog core.
+.TP
+.I \-\-replicator
+Creates empty replicator logical volume. ( see
+.B lvchange(8)
+) for options, how to customize created replicator LV.
+
+Specifying optional argument --nosync will cause the creation
+of the replicator to skip the initial resynchronization. Any data written
+afterwards will be replicator, but the original contents will not be
+copied.  This is useful for skipping a potentially long and resource
+intensive initial sync of an empty device.
+
+The optional argument --replicatorsynclog specifies the type of synclog to be
+used. The default is disk, which is persistent and requires a small amount of
+storage space, usually on a separate device from the data being replicated.
+Using core means the replicator is regenerated by copying the data from the
+first device again each time the device is activated, for example, after every
+reboot.
+
+The optional argument --replicatorlog specifies the LogicalVolumeName of the
+LV to be used as the main backing store device for keeping replicator master
+log. If not specified, log is allocated with given -L|--size. Note: This
+backing store device should be very fast and reliable and storage (i.e. raid1),
+so should be selected with special care.
+
+The optional argument --replicatorlogtype specifies type of the backing store
+log. The default and currently the only valid and supported type is ringbuffer.
+
+.TP
+.I \-\-replicatordev
+Creates empty replicated logical volume. If the --site is not specified, local
+site is found inside replicator LV.
 
 .TP
 .I \-n, \-\-name LogicalVolumeName
@@ -237,10 +287,15 @@ under 100MB of actual data on it.
 creates a linear logical volume "vg00/lvol1" using physical extents
 /dev/sda:0-7 and /dev/sdb:0-7 for allocation of extents.
 
+"lvcreate -L 1G -n replicator0 vg00"
+.br
+creates an empty replicator logical volume "vg00/replicator0" and hidden backing
+store volume vg00/replicator0_rlog of size 1G.
 
 .SH SEE ALSO
 .BR lvm (8), 
 .BR vgcreate (8), 
+.BR lvchange (8)
 .BR lvremove (8), 
 .BR lvrename (8)
 .BR lvextend (8), 
-- 
1.7.0.1



^ permalink raw reply related	[flat|nested] 42+ messages in thread

end of thread, other threads:[~2010-04-26 18:01 UTC | newest]

Thread overview: 42+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-04-12 15:21 [PATCH 00/22] Replicator 100412 Zdenek Kabelac
2010-04-12 15:21 ` [PATCH 01/22] Add dm_list_splice() for list join Zdenek Kabelac
2010-04-14 11:38   ` Petr Rockai
2010-04-26 13:15   ` Alasdair G Kergon
2010-04-26 13:23     ` Alasdair G Kergon
2010-04-12 15:21 ` [PATCH 02/22] API change for args of process_each_lv_in_vg() Zdenek Kabelac
2010-04-26 13:34   ` Alasdair G Kergon
2010-04-26 13:46   ` Mike Snitzer
2010-04-12 15:21 ` [PATCH 03/22] Replicator: add libdm support Zdenek Kabelac
2010-04-26 13:46   ` Alasdair G Kergon
2010-04-26 14:12     ` Zdenek Kabelac
2010-04-12 15:21 ` [PATCH 04/22] Replicator: suspend/deactivate replicator Zdenek Kabelac
2010-04-26 13:50   ` Alasdair G Kergon
2010-04-12 15:21 ` [PATCH 05/22] Replicator: add lvm support Zdenek Kabelac
2010-04-26 14:10   ` Alasdair G Kergon
2010-04-12 15:21 ` [PATCH 06/22] Replicator: check replicator segment Zdenek Kabelac
2010-04-12 15:21 ` [PATCH 07/22] Replicator: extend _lv_each_dependency() rep. deps Zdenek Kabelac
2010-04-12 15:21 ` [PATCH 08/22] Replicator: extend volume_group with list of VGs Zdenek Kabelac
2010-04-26 14:26   ` Alasdair G Kergon
2010-04-26 14:39     ` Zdenek Kabelac
2010-04-26 14:27   ` Alasdair G Kergon
2010-04-26 14:35     ` Zdenek Kabelac
2010-04-12 15:21 ` [PATCH 09/22] Replicator: add sorted vgs_list Zdenek Kabelac
2010-04-26 14:34   ` Alasdair G Kergon
2010-04-26 14:56     ` Zdenek Kabelac
2010-04-26 18:01       ` Dave Wysochanski
2010-04-12 15:21 ` [PATCH 10/22] Replicator: add find_replicator_vgs Zdenek Kabelac
2010-04-12 15:21 ` [PATCH 11/22] Replicator: add read and release VGs for rsites Zdenek Kabelac
2010-04-12 15:21 ` [PATCH 12/22] Replicator: use vgs_list for _process_one_vg() Zdenek Kabelac
2010-04-12 15:21 ` [PATCH 13/22] Replicator: use vgs_list for process_each_lv_in_vg() Zdenek Kabelac
2010-04-12 15:21 ` [PATCH 14/22] Replicator: lock_vol() finds missing VGs Zdenek Kabelac
2010-04-12 15:21 ` [PATCH 15/22] Replicator: activate checks for missing vgs Zdenek Kabelac
2010-04-26 14:39   ` Alasdair G Kergon
2010-04-12 15:21 ` [PATCH 16/22] Replicator: update _create_partial_dtree() Zdenek Kabelac
2010-04-12 15:21 ` [PATCH 17/22] Replicator: vg with missing_vgs does not print Zdenek Kabelac
2010-04-12 15:21 ` [PATCH 18/22] Replicator: add replicator to dtree Zdenek Kabelac
2010-04-12 15:21 ` [PATCH 19/22] Replicator: do not remove of replicators' LVs Zdenek Kabelac
2010-04-12 15:21 ` [PATCH 20/22] Replicator: activate change for vgchange Zdenek Kabelac
2010-04-12 15:21 ` [PATCH 21/22] Replicator: add new options for replicator Zdenek Kabelac
2010-04-12 15:21 ` [PATCH 22/22] Replicator: man pages for lvcreate, lvchange Zdenek Kabelac
2010-04-26 14:49   ` Alasdair G Kergon
  -- strict thread matches above, loose matches on Subject: below --
2010-03-30 15:17 [PATCH 00/22] Replicator 100430 Zdenek Kabelac
2010-03-30 15:17 ` [PATCH 22/22] Replicator: man pages for lvcreate, lvchange Zdenek Kabelac

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.