All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/22] Replicator lvm support
@ 2009-12-04 14:04 Zdenek Kabelac
  2009-12-04 14:04 ` [PATCH 01/22] Export outsz() and outhnt() for modules Zdenek Kabelac
                   ` (21 more replies)
  0 siblings, 22 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2009-12-04 14:04 UTC (permalink / raw)
  To: lvm-devel

LVM support for Replicator device mapper target.

Patches without Replicator: prefix are generic simple patches 
or some minor code cleanups - they are here just to get accurate diffs.

First Replicator patch adds libdm support followed by lvm code support.

Tricky part is the usage of sorted vg_name_list.

This patch set doesn't yet contain functional lvm commands for creation
of replicator, so for activation and deactivation hand written meta-data
must be used.

Current code will activate also VGs from remote volume groups if they
are not yet active and work with already active remote VGs.
Deactivation will leave remove VGs active. 

vgchange and lvchange is resolved.

Command line support is in progress.

Zdenek Kabelac (22):
  Export outsz() and outhnt() for modules
  Export outfc() macro and out_text_with_comment()
  Use outsz macro
  Replicator: add libdm support
  Replicator: suspend/deactivate replicator
  Replicator: add lvm support
  Replicator: validation of replicator segments
  Replicator: extend _lv_each_dependency() rep. deps
  Replicator: add sorted vg_name_list
  Replicator: use vg_name_list for _process_one_vg()
  Replicator: use str_list for process_each_lv_in_vg
  Replicator: update _create_partial_dtree()
  Replicator: using vgs_missed for error count
  Replicator: add vgs_print for message postponing
  Replicator: add replicator to dtree
  Replicator: do not remove of replicators' LVs
  Replicator: no crash lvresize if area_count is 0
  Replicator: activate change for vgchange
  Replicator: add new options for replicator
  Replicator: update copyright dates
  Replicator: new variable in generated file
  Replicator: update of generated configure file

 configure                        |   34 ++-
 configure.in                     |   17 +
 lib/Makefile.in                  |    9 +
 lib/activate/dev_manager.c       |  160 ++++++++-
 lib/commands/toolcontext.c       |    7 +
 lib/commands/toolcontext.h       |    4 +
 lib/config/defaults.h            |    1 +
 lib/format_text/export.c         |   29 +-
 lib/format_text/flags.c          |    2 +
 lib/format_text/text_export.h    |    6 +
 lib/metadata/lv_manip.c          |   15 +
 lib/metadata/merge.c             |   14 +
 lib/metadata/metadata-exported.h |  113 ++++++-
 lib/metadata/metadata.c          |   72 ++++
 lib/metadata/replicator_manip.c  |  354 ++++++++++++++++
 lib/metadata/segtype.h           |   10 +-
 lib/mirror/mirrored.c            |    4 +-
 lib/misc/configure.h.in          |    8 +-
 lib/replicator/.exported_symbols |    1 +
 lib/replicator/Makefile.in       |   28 ++
 lib/replicator/replicator.c      |  822 ++++++++++++++++++++++++++++++++++++++
 lib/striped/striped.c            |    4 +-
 libdm/.exported_symbols          |    3 +
 libdm/libdevmapper.h             |   29 ++
 libdm/libdm-deptree.c            |  342 ++++++++++++++++-
 tools/args.h                     |    5 +
 tools/commands.h                 |   10 +-
 tools/lvcreate.c                 |   49 +++
 tools/lvmcmdline.c               |    9 +
 tools/toollib.c                  |  170 +++++++--
 tools/tools.h                    |    1 +
 tools/vgchange.c                 |   15 +-
 32 files changed, 2286 insertions(+), 61 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] 23+ messages in thread

* [PATCH 01/22] Export outsz() and outhnt() for modules
  2009-12-04 14:04 [PATCH 00/22] Replicator lvm support Zdenek Kabelac
@ 2009-12-04 14:04 ` Zdenek Kabelac
  2009-12-04 14:04 ` [PATCH 02/22] Export outfc() macro and out_text_with_comment() Zdenek Kabelac
                   ` (20 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2009-12-04 14:04 UTC (permalink / raw)
  To: lvm-devel

Adding macro outsz() for out_size() and outhnt() for out_hint()
that checks for error in a similar way as outf() does for out_text()

Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
 lib/format_text/export.c      |   23 +++++++++--------------
 lib/format_text/text_export.h |    2 ++
 2 files changed, 11 insertions(+), 14 deletions(-)

diff --git a/lib/format_text/export.c b/lib/format_text/export.c
index 15439fd..8010121 100644
--- a/lib/format_text/export.c
+++ b/lib/format_text/export.c
@@ -386,9 +386,8 @@ static int _print_vg(struct formatter *f, struct volume_group *vg)
 	if (vg->system_id && *vg->system_id)
 		outf(f, "system_id = \"%s\"", vg->system_id);
 
-	if (!out_size(f, (uint64_t) vg->extent_size, "extent_size = %u",
-		      vg->extent_size))
-		return_0;
+	outsz(f, (uint64_t) vg->extent_size, "extent_size = %u",
+	      vg->extent_size);
 	outf(f, "max_lv = %u", vg->max_lv);
 	outf(f, "max_pv = %u", vg->max_pv);
 
@@ -453,9 +452,8 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg)
 			return 0;
 		}
 
-		if (!out_hint(f, "device = \"%s\"",
-			      escape_double_quotes(buf, pv_dev_name(pv))))
-			return_0;
+		outhnt(f, "device = \"%s\"",
+		       escape_double_quotes(buf, pv_dev_name(pv)));
 		outnl(f);
 
 		if (!_print_flag_config(f, pv->status, PV_FLAGS))
@@ -467,13 +465,11 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg)
 			outf(f, "tags = %s", buffer);
 		}
 
-		if (!out_size(f, pv->size, "dev_size = %" PRIu64, pv->size))
-			return_0;
+		outsz(f, pv->size, "dev_size = %" PRIu64, pv->size);
 
 		outf(f, "pe_start = %" PRIu64, pv->pe_start);
-		if (!out_size(f, vg->extent_size * (uint64_t) pv->pe_count,
-			      "pe_count = %u", pv->pe_count))
-			return_0;
+		outsz(f, vg->extent_size * (uint64_t) pv->pe_count,
+		      "pe_count = %u", pv->pe_count);
 
 		_dec_indent(f);
 		outf(f, "}");
@@ -493,9 +489,8 @@ static int _print_segment(struct formatter *f, struct volume_group *vg,
 	_inc_indent(f);
 
 	outf(f, "start_extent = %u", seg->le);
-	if (!out_size(f, (uint64_t) seg->len * vg->extent_size,
-		      "extent_count = %u", seg->len))
-		return_0;
+	outsz(f, (uint64_t) seg->len * vg->extent_size,
+	      "extent_count = %u", seg->len);
 
 	outnl(f);
 	outf(f, "type = \"%s\"", seg->segtype->name);
diff --git a/lib/format_text/text_export.h b/lib/format_text/text_export.h
index cdba82f..a452439 100644
--- a/lib/format_text/text_export.h
+++ b/lib/format_text/text_export.h
@@ -16,6 +16,8 @@
 #ifndef _LVM_TEXT_EXPORT_H
 #define _LVM_TEXT_EXPORT_H
 
+#define outsz(args...) do {if (!out_size(args)) return_0;} while (0)
+#define outhnt(args...) do {if (!out_hint(args)) return_0;} while (0)
 #define outf(args...) do {if (!out_text(args)) return_0;} while (0)
 #define outnl(f) do {if (!out_newline(f)) return_0;} while (0)
 
-- 
1.6.5.3



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

* [PATCH 02/22] Export outfc() macro and out_text_with_comment()
  2009-12-04 14:04 [PATCH 00/22] Replicator lvm support Zdenek Kabelac
  2009-12-04 14:04 ` [PATCH 01/22] Export outsz() and outhnt() for modules Zdenek Kabelac
@ 2009-12-04 14:04 ` Zdenek Kabelac
  2009-12-04 14:04 ` [PATCH 03/22] Use outsz macro Zdenek Kabelac
                   ` (19 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2009-12-04 14:04 UTC (permalink / raw)
  To: lvm-devel

Support also commented lines with out_text_with_comment() API call.
It is similar to out_text() function and it takes extra argument
for comment. Macro outfc() is similar to outf().

Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
 lib/format_text/export.c      |    6 +++---
 lib/format_text/text_export.h |    4 ++++
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/lib/format_text/export.c b/lib/format_text/export.c
index 8010121..f0647e7 100644
--- a/lib/format_text/export.c
+++ b/lib/format_text/export.c
@@ -286,9 +286,9 @@ int out_hint(struct formatter *f, const char *fmt, ...)
 }
 
 /*
- * Appends a comment
+ * The normal output function with comment
  */
-static int _out_comment(struct formatter *f, const char *comment, const char *fmt, ...)
+int out_text_with_comment(struct formatter *f, const char *comment, const char *fmt, ...)
 {
 	va_list ap;
 	int r;
@@ -579,7 +579,7 @@ static int _print_lv(struct formatter *f, struct logical_volume *lv)
 
 	switch (lv->read_ahead) {
 	case DM_READ_AHEAD_NONE:
-		_out_comment(f, "# None", "read_ahead = -1");
+		outfc(f, "# None", "read_ahead = -1");
 		break;
 	case DM_READ_AHEAD_AUTO:
 		/* No output - use default */
diff --git a/lib/format_text/text_export.h b/lib/format_text/text_export.h
index a452439..63c8999 100644
--- a/lib/format_text/text_export.h
+++ b/lib/format_text/text_export.h
@@ -18,6 +18,7 @@
 
 #define outsz(args...) do {if (!out_size(args)) return_0;} while (0)
 #define outhnt(args...) do {if (!out_hint(args)) return_0;} while (0)
+#define outfc(args...) do {if (!out_text_with_comment(args)) return_0;} while (0)
 #define outf(args...) do {if (!out_text(args)) return_0;} while (0)
 #define outnl(f) do {if (!out_newline(f)) return_0;} while (0)
 
@@ -39,6 +40,9 @@ int out_config_node(struct formatter *f, const struct config_node *cn);
 int out_areas(struct formatter *f, const struct lv_segment *seg,
 	      const char *type);
 
+int out_text_with_comment(struct formatter *f, const char* comment, const char *fmt, ...)
+    __attribute__ ((format(printf, 3, 4)));
+
 void out_inc_indent(struct formatter *f);
 void out_dec_indent(struct formatter *f);
 int out_newline(struct formatter *f);
-- 
1.6.5.3



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

* [PATCH 03/22] Use outsz macro
  2009-12-04 14:04 [PATCH 00/22] Replicator lvm support Zdenek Kabelac
  2009-12-04 14:04 ` [PATCH 01/22] Export outsz() and outhnt() for modules Zdenek Kabelac
  2009-12-04 14:04 ` [PATCH 02/22] Export outfc() macro and out_text_with_comment() Zdenek Kabelac
@ 2009-12-04 14:04 ` Zdenek Kabelac
  2009-12-04 14:04 ` [PATCH 04/22] Replicator: add libdm support Zdenek Kabelac
                   ` (18 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2009-12-04 14:04 UTC (permalink / raw)
  To: lvm-devel

Using outsz() macro instead of direct call of out_size() with check
for error status of this function.

Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
 lib/mirror/mirrored.c |    4 ++--
 lib/striped/striped.c |    4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/lib/mirror/mirrored.c b/lib/mirror/mirrored.c
index 29746b0..fa6ec04 100644
--- a/lib/mirror/mirrored.c
+++ b/lib/mirror/mirrored.c
@@ -149,8 +149,8 @@ static int _mirrored_text_export(const struct lv_segment *seg, struct formatter
 {
 	outf(f, "mirror_count = %u", seg->area_count);
 	if (seg->status & PVMOVE)
-		out_size(f, (uint64_t) seg->extents_copied * seg->lv->vg->extent_size,
-			 "extents_moved = %" PRIu32, seg->extents_copied);
+		outsz(f, (uint64_t) seg->extents_copied * seg->lv->vg->extent_size,
+		      "extents_moved = %" PRIu32, seg->extents_copied);
 	if (seg->log_lv)
 		outf(f, "mirror_log = \"%s\"", seg->log_lv->name);
 	if (seg->region_size)
diff --git a/lib/striped/striped.c b/lib/striped/striped.c
index f187da5..220edd8 100644
--- a/lib/striped/striped.c
+++ b/lib/striped/striped.c
@@ -98,8 +98,8 @@ static int _striped_text_export(const struct lv_segment *seg, struct formatter *
 	     (seg->area_count == 1) ? "\t# linear" : "");
 
 	if (seg->area_count > 1)
-		out_size(f, (uint64_t) seg->stripe_size,
-			 "stripe_size = %u", seg->stripe_size);
+		outsz(f, (uint64_t) seg->stripe_size,
+		      "stripe_size = %u", seg->stripe_size);
 
 	return out_areas(f, seg, "stripe");
 }
-- 
1.6.5.3



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

* [PATCH 04/22] Replicator: add libdm support
  2009-12-04 14:04 [PATCH 00/22] Replicator lvm support Zdenek Kabelac
                   ` (2 preceding siblings ...)
  2009-12-04 14:04 ` [PATCH 03/22] Use outsz macro Zdenek Kabelac
@ 2009-12-04 14:04 ` Zdenek Kabelac
  2009-12-04 14:04 ` [PATCH 05/22] Replicator: suspend/deactivate replicator Zdenek Kabelac
                   ` (17 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2009-12-04 14:04 UTC (permalink / raw)
  To: lvm-devel

Introducing dm_tree_node_add_replicator_target() and
dm_tree_node_add_replicator_dev_target().

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

diff --git a/libdm/.exported_symbols b/libdm/.exported_symbols
index 554b90a..05d82bf 100644
--- a/libdm/.exported_symbols
+++ b/libdm/.exported_symbols
@@ -78,6 +78,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 c6546a6..c920154 100644
--- a/libdm/libdevmapper.h
+++ b/libdm/libdevmapper.h
@@ -431,6 +431,33 @@ int dm_tree_node_add_mirror_target_log(struct dm_tree_node *node,
 					  const char *log_uuid,
 					  unsigned area_count,
 					  uint32_t flags);
+
+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,
+				       int async_action,
+/* Replicator async action flags */
+#define DM_REPLICATOR_SYNC	0		/* Synchronous replication */
+#define DM_REPLICATOR_WARN	1		/* Warn if replicator is slow */
+#define DM_REPLICATOR_STALL	2		/* Stall replicator if not fast enough */
+#define DM_REPLICATOR_DROP	3		/* Drop legs */
+#define DM_REPLICATOR_FAIL	4		/* Fail replicator if slow */
+				       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_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 a596c83..d297c5f 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_STRIPED,
@@ -49,6 +51,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_STRIPED, "striped" },
@@ -62,6 +66,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;
+	int async_action;
+	uint32_t async_timeout;
+	uint32_t fall_behind_ios;
+	uint64_t fall_behind_data;
 };
 
 /* Per-segment properties */
@@ -72,8 +93,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 */
 
@@ -82,7 +103,7 @@ struct load_segment {
 	struct dm_tree_node *cow;	/* Snapshot */
 	struct dm_tree_node *origin;	/* Snapshot + Snapshot origin */
 
-	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 */
@@ -94,6 +115,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 */
@@ -1299,13 +1327,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) {
+				/* 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);
+			} else
+				EMIT_PARAMS(*pos, " nolog 0");
+
+			break;
+		default:
+			EMIT_PARAMS(*pos, "%s%s %" PRIu64, first_time ? "" : " ",
+				    devbuf, area->offset);
+		}
 
 		first_time = 0;
 	}
@@ -1313,6 +1379,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;
+	const 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->async_action == 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
  */
@@ -1453,6 +1555,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:
 		if (!_build_dev_string(originbuf, sizeof(originbuf), seg->origin))
 			return_0;
@@ -1480,12 +1597,14 @@ 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_ZERO:
 		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;
@@ -1638,6 +1757,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;
@@ -1900,6 +2022,151 @@ 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,
+				       int async_action,
+				       uint32_t async_timeout,
+				       uint64_t fall_behind_data,
+				       uint32_t fall_behind_ios)
+{
+	struct load_segment *rseg;
+	struct replicator_site *rsite;
+
+	if (rsite_index == 0) {
+		/* Local site0 - add replog segment and set rlog device */
+		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;
+	}
+
+	if (!node->props.segment_count) {
+		log_error("Internal error: Attempt to add remote site area before replog.");
+		return 0;
+	}
+
+	/* New remote site */
+	if (async_action == DM_REPLICATOR_SYNC
+	    && (async_timeout || fall_behind_ios || fall_behind_data)) {
+		log_error("Unsupported combination of sync options passed.");
+		return 0;
+	}
+
+	rseg = dm_list_item(dm_list_last(&node->props.segs), struct load_segment);
+
+	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->async_action = async_action;
+	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_size)
+{
+	struct seg_area *area;
+	struct load_segment *rseg;
+	int is_uuid = (rdev_uuid) ? (strchr(rdev_uuid, '/') == NULL) : 0;
+
+	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;
+		}
+
+		if (!rseg->replicator->props.segment_count) {
+			/* Local slink 0 for replicator must be always initialized first */
+			log_error("Internal error: Attempt to use empty replicator segment.");
+			return 0;
+		}
+
+		dm_list_item(dm_list_last(&rseg->replicator->props.segs),
+			     struct load_segment)->rdevice_count++;
+
+		if (!_link_tree_nodes(node, rseg->replicator))
+			return_0;
+
+		rseg->rdevice_index = rdevice_index;
+	} else {
+		if (!node->props.segment_count) {
+			/* Local slink 0 for replicator must be always initialized first */
+			log_error("Internal error: Attempt to add incorrrect remote target segment.");
+			return 0;
+		}
+
+		rseg = dm_list_item(dm_list_last(&node->props.segs), struct load_segment);
+	}
+
+	if (!(slog_flags & DM_CORELOG) && !slog_uuid) {
+		log_error("Unspecified sync log uuid.");
+		return 0;
+	}
+
+	if (!dm_tree_node_add_target_area(node, (is_uuid) ? NULL : rdev_uuid,
+					  (is_uuid) ? rdev_uuid :  NULL, 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_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.6.5.3



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

* [PATCH 05/22] Replicator: suspend/deactivate replicator
  2009-12-04 14:04 [PATCH 00/22] Replicator lvm support Zdenek Kabelac
                   ` (3 preceding siblings ...)
  2009-12-04 14:04 ` [PATCH 04/22] Replicator: add libdm support Zdenek Kabelac
@ 2009-12-04 14:04 ` Zdenek Kabelac
  2009-12-04 14:04 ` [PATCH 06/22] Replicator: add lvm support Zdenek Kabelac
                   ` (16 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2009-12-04 14:04 UTC (permalink / raw)
  To: lvm-devel

Introducing dm_tree_set_replicator_suspend() to suspend
replicator control device before actual deactivation of replicator-dev
head device.

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

diff --git a/libdm/.exported_symbols b/libdm/.exported_symbols
index 05d82bf..aa0e04a 100644
--- a/libdm/.exported_symbols
+++ b/libdm/.exported_symbols
@@ -80,6 +80,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_replicator_suspend
 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 c920154..2635d8b 100644
--- a/libdm/libdevmapper.h
+++ b/libdm/libdevmapper.h
@@ -458,6 +458,8 @@ int dm_tree_node_add_replicator_dev_target(struct dm_tree_node *node,
 					   uint32_t slog_flags,		/* Mirror log flags */
 					   uint32_t slog_size);
 
+int dm_tree_set_replicator_suspend(struct dm_tree *dtree, const char *uuid);
+
 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 d297c5f..a7fd7f4 100644
--- a/libdm/libdm-deptree.c
+++ b/libdm/libdm-deptree.c
@@ -157,6 +157,7 @@ struct dm_tree_node {
         struct dm_list used_by;    	/* Nodes that use this node */
 
 	int activation_priority;	/* 0 gets activated first */
+	int replicator_suspend;		/* 1 gets suspend first */
 
 	uint16_t udev_flags;		/* Udev control flags */
 
@@ -678,6 +679,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_replicator_suspend(struct dm_tree *dtree, const char *uuid)
+{
+	struct dm_tree_node *dnode;
+
+	if ((dnode = dm_tree_find_node_by_uuid(dtree, uuid))) {
+		log_verbose("Setting replicator suspend for %s.", dnode->name);
+		dnode->replicator_suspend = 1;
+	}
+
+	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) ? 1 : 0;
@@ -1030,6 +1043,53 @@ static int _suspend_node(const char *name, uint32_t major, uint32_t minor,
 	return r;
 }
 
+static int _suspend_replicator_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->replicator_suspend)
+			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;
+}
+
 int dm_tree_deactivate_children(struct dm_tree_node *dnode,
 				   const char *uuid_prefix,
 				   size_t uuid_prefix_len)
@@ -1066,6 +1126,9 @@ int dm_tree_deactivate_children(struct dm_tree_node *dnode,
 		    !info.exists || info.open_count)
 			continue;
 
+		if (!_suspend_replicator_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.6.5.3



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

* [PATCH 06/22] Replicator: add lvm support
  2009-12-04 14:04 [PATCH 00/22] Replicator lvm support Zdenek Kabelac
                   ` (4 preceding siblings ...)
  2009-12-04 14:04 ` [PATCH 05/22] Replicator: suspend/deactivate replicator Zdenek Kabelac
@ 2009-12-04 14:04 ` Zdenek Kabelac
  2009-12-04 14:04 ` [PATCH 07/22] Replicator: validation of replicator segments Zdenek Kabelac
                   ` (15 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2009-12-04 14:04 UTC (permalink / raw)
  To: lvm-devel

Adding configure.in support for Replicator.
Adding basic lib lvm support for Replicator.
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                  |    9 +
 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 |   95 +++++-
 lib/metadata/replicator_manip.c  |  309 ++++++++++++++
 lib/metadata/segtype.h           |    8 +
 lib/replicator/.exported_symbols |    1 +
 lib/replicator/Makefile.in       |   28 ++
 lib/replicator/replicator.c      |  822 ++++++++++++++++++++++++++++++++++++++
 12 files changed, 1310 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 834fd6e..288b4ac 100644
--- a/configure.in
+++ b/configure.in
@@ -306,6 +306,21 @@ if test x$MIRRORS = xinternal; then
 fi
 
 ################################################################################
+dnl -- Asynchronous Volume Replicator inclusion type
+AC_MSG_CHECKING(whether to include replicator)
+AC_ARG_WITH(replicator, AC_HELP_STRING([--with-replicator=TYPE],
+        [Replicator support: internal/shared/none [[TYPE=none]]]),
+        [ REPLICATOR="$withval" ], [ REPLICATOR="none" ])
+AC_MSG_RESULT($REPLICATOR)
+
+case "$REPLICATOR" in
+ none|shared) ;;
+ internal) AC_DEFINE([REPLICATOR_INTERNAL], 1,
+                     [Define to 1 to include built-in support for replicator.]) ;;
+ *) AC_MSG_ERROR([--with-replicator parameter invalid ($REPLICATOR)]) ;;
+esac
+
+################################################################################
 dnl -- Disable readline
 AC_MSG_CHECKING(whether to enable readline)
 AC_ARG_ENABLE([readline],
@@ -1115,6 +1130,7 @@ AC_SUBST(LVM_PATCHLEVEL)
 AC_SUBST(LVM_RELEASE)
 AC_SUBST(LVM_RELEASE_DATE)
 AC_SUBST(MIRRORS)
+AC_SUBST(REPLICATOR)
 AC_SUBST(MSGFMT)
 AC_SUBST(OWNER)
 AC_SUBST(PKGCONFIG)
@@ -1163,6 +1179,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 6c29a5e..4942926 100644
--- a/lib/Makefile.in
+++ b/lib/Makefile.in
@@ -33,6 +33,10 @@ ifeq ("@MIRRORS@", "shared")
   SUBDIRS += mirror
 endif
 
+ifeq ("@REPLICATOR@", "shared")
+  SUBDIRS += replicator
+endif
+
 SOURCES =\
 	activate/activate.c \
 	cache/lvmcache.c \
@@ -75,6 +79,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 \
@@ -130,6 +135,10 @@ ifeq ("@MIRRORS@", "internal")
   SOURCES += mirror/mirrored.c
 endif
 
+ifeq ("@REPLICATOR@", "internal")
+  SOURCES += replicator/replicator.c
+endif
+
 ifeq ("@DEVMAPPER@", "yes")
   SOURCES +=\
 	activate/dev_manager.c \
diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c
index bb3e5d2..4b68851 100644
--- a/lib/commands/toolcontext.c
+++ b/lib/commands/toolcontext.c
@@ -906,6 +906,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 ec87aac..2c91be8 100644
--- a/lib/format_text/flags.c
+++ b/lib/format_text/flags.c
@@ -66,6 +66,8 @@ static 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 b020cf5..1a2404c 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -1876,6 +1876,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 66e9ce0..3233d2b 100644
--- a/lib/metadata/merge.c
+++ b/lib/metadata/merge.c
@@ -66,6 +66,8 @@ int check_lv_segments(struct logical_volume *lv, int complete_vg)
 	int r = 1;
 	uint32_t area_multiplier, s;
 	struct seg_list *sl;
+	struct replicator_site *rsite;
+	struct replicator_device *rdev;
 
 	dm_list_iterate_items(seg, &lv->segments) {
 		seg_count++;
@@ -207,6 +209,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 e4bab7f..aa92339 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -61,6 +61,9 @@
 //#define PRECOMMITTED		0x00200000U	/* VG - internal use only */
 #define CONVERTING		0x00400000U	/* LV */
 
+#define REPLICATOR		0x10000000U	/* LV -internal use only for replicator/replicator-dev */
+#define REPLICATOR_LOG		0x20000000U	/* LV -internal use only for replicator/replicator-dev */
+
 #define MISSING_PV              0x00800000U	/* PV */
 #define PARTIAL_LV              0x01000000U	/* LV - derived flag, not
 						   written out in metadata*/
@@ -277,6 +280,54 @@ struct lv_segment_area {
 };
 
 struct segment_type;
+
+/* ++ replicator datatypes */
+typedef enum {
+	REPLICATOR_ACTION_WARN,
+	REPLICATOR_ACTION_STALL,
+	REPLICATOR_ACTION_DROP,
+	REPLICATOR_ACTION_FAIL,
+	NUM_REPLICATOR_ACTION
+} replicator_action_t;
+
+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;
+	const char *vg_name;		/* VG name/uuid */
+	struct volume_group *vg;	/* Site's volume group */
+	unsigned site_index;
+	replicator_state_t state;	/* Active or pasive state of site */
+	replicator_action_t async_action;/* fail|warn|drop|resync|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;		/* Any device path/uuid */
+	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;
@@ -295,7 +346,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;
 	void *segtype_private;
@@ -303,6 +354,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
@@ -328,6 +385,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;
@@ -686,6 +746,39 @@ 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 lvm_replicator_add_dev(struct logical_volume *replicator_lv, struct lv_segment *replicator_dev_seg);
+/*
+ * Returns rimage ?? lv upon succeful detach of device
+ * entire LV entry should be removed by this crootall ??
+ */
+struct logical_volume *lvm_replicator_remove_dev(struct lv_segment *replicator_dev_seg);//MAYBE: struct replicator_device *rdev??
+int lvm_replicator_add_rlog(struct lv_segment *replicator_seg, struct logical_volume *rlog_lv);
+struct logical_volume *lvm_replicator_remove_rlog(struct lv_segment *replicator_seg);
+
+int lvm_replicator_dev_add_slog(struct replicator_device *rdev, struct logical_volume *slog_lv);
+struct logical_volume *lvm_replicator_dev_remove_slog(struct replicator_device *rdev);
+int lvm_replicator_dev_add_rimage(struct replicator_device *rdev, struct logical_volume *lv);
+struct logical_volume *lvm_replicator_dev_remove_rimage(struct replicator_device *rdev);
+
+/* Is this segment part of active replicator */
+int lv_is_active_replicator_dev(const struct logical_volume *lv);
+
+/* Is this LV replicator control device */
+int lv_is_replicator(const struct logical_volume *lv);
+/* Is this LV replicator device */
+int lv_is_replicator_dev(const struct logical_volume *lv);
+/* Is this LV replicated origin lv */
+int lv_is_rimage(const struct logical_volume *lv);
+/* Is this LV rlog */
+int lv_is_rlog(const struct logical_volume *lv);
+/* Is this LV sync log */
+int lv_is_slog(const struct logical_volume *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);
+/* --  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..4b24e02
--- /dev/null
+++ b/lib/metadata/replicator_manip.c
@@ -0,0 +1,309 @@
+/*
+ * Copyright (C) 2009 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 "metadata.h"
+#include "toolcontext.h"
+#include "segtype.h"
+#include "archiver.h"
+#include "lvm-string.h"
+#include "str_list.h"
+#include "defaults.h"
+#include "lv_alloc.h"
+
+/* Add lv as replicator device */
+int lvm_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 device */
+struct logical_volume *lvm_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 lvm_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 *lvm_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 lvm_replicator_add_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);
+}
+
+struct logical_volume *lvm_replicator_remove_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 lvm_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 *lvm_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 lvm_replicator_lv_add(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 lvm_replicator_lv_remove(struct logical_volume *lv)
+{
+	return 1;
+}
+#endif
+
+int lv_is_replicator(const struct logical_volume *lv)
+{
+	return ((lv->status & REPLICATOR) &&
+		!dm_list_empty(&lv->segments) &&
+		seg_is_replicator(first_seg(lv)));
+}
+
+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)));
+}
+
+int lv_is_rimage(const struct logical_volume *lv)
+{
+	return (lv->rdevice && lv->rdevice->lv == lv);
+}
+
+int lv_is_rlog(const struct logical_volume *lv)
+{
+	return (lv->status & REPLICATOR_LOG) &&
+		(dm_list_empty(&lv->segments) ||
+		!seg_is_replicator(first_seg(lv)));
+}
+
+int lv_is_slog(const struct logical_volume *lv)
+{
+	return (lv->rdevice && lv->rdevice->slog == lv);
+}
+
+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);
+}
+
+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 c9a01aa..20a032f 100644
--- a/lib/metadata/segtype.h
+++ b/lib/metadata/segtype.h
@@ -36,8 +36,12 @@ struct dev_manager;
 #define SEG_CANNOT_BE_ZEROED	0x00000040U
 #define SEG_MONITORED		0x00000080U
 #define SEG_UNKNOWN		0x80000000U
+#define SEG_REPLICATOR		0x00000100U
+#define SEG_REPLICATOR_DEV	0x00000200U
 
 #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)
@@ -109,6 +113,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..db1f9b7
--- /dev/null
+++ b/lib/replicator/Makefile.in
@@ -0,0 +1,28 @@
+#
+# Copyright (C) 2009 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@
+VPATH = @srcdir@
+
+SOURCES = replicator.c
+
+LIB_SHARED = liblvm2replicator.so
+
+include $(top_srcdir)/make.tmpl
+
+install: $(LIB_SHARED)
+	$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
+		$(libdir)/$(LIB_SHARED).$(LIB_VERSION)
+	$(LN_S) -f $(LIB_SHARED).$(LIB_VERSION) \
+		$(libdir)/$(LIB_SHARED)
diff --git a/lib/replicator/replicator.c b/lib/replicator/replicator.c
new file mode 100644
index 0000000..1339e1b
--- /dev/null
+++ b/lib/replicator/replicator.c
@@ -0,0 +1,822 @@
+/*
+ * Copyright (C) 2009 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) {
+				log_very_verbose("Setting %s to %s",
+						 path, _state_txt[i]);
+				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 _action_txt[NUM_REPLICATOR_ACTION][8] = {
+	"warn",
+	"stall",
+	"drop",
+	"fail"
+};
+
+
+/* Parse action string */
+static replicator_action_t _get_action(const struct config_node *sn,
+				       const char *path, replicator_action_t def)
+{
+	char *str;
+	unsigned i;
+
+	if (get_config_str(sn, path, &str)) {
+		for (i = 0; i < sizeof(_action_txt)/sizeof(_action_txt[0]); ++i)
+			if (strcasecmp(str, _action_txt[i]) == 0) {
+				log_very_verbose("Setting %s to %s",
+						 path, _action_txt[i]);
+				return (replicator_action_t) i;
+			}
+		log_warn("%s: unknown value '%s', using default '%s' action",
+			 path, str, _action_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->async_action = REPLICATOR_ACTION_WARN;
+
+	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->async_action = _get_action(sn, "async_action",
+						  rsite->async_action);
+	}
+
+	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 (!lvm_replicator_add_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 (!lvm_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_uint64(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)
+{
+	const 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)
+		outsz(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->async_action != REPLICATOR_ACTION_WARN)
+			outf(f, "async_action = \"%s\"",
+			     _action_txt[rsite->async_action]);
+		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)
+			outsz(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;
+	const struct replicator_site *rsite;
+	int action;
+
+	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) {
+		action = (rsite->async_action == REPLICATOR_ACTION_WARN) ? DM_REPLICATOR_WARN :
+			(rsite->async_action == REPLICATOR_ACTION_STALL) ? DM_REPLICATOR_STALL :
+			(rsite->async_action == REPLICATOR_ACTION_DROP) ? DM_REPLICATOR_DROP : DM_REPLICATOR_FAIL;
+		if (!rsite->fall_behind_timeout && !rsite->fall_behind_data && !rsite->fall_behind_ios)
+			action = DM_REPLICATOR_SYNC;
+		if (!dm_tree_node_add_replicator_target(node,
+							seg->rlog_lv->size,
+							rlog_dlid,
+							seg->rlog_type,
+							rsite->site_index,
+							action,
+							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;
+
+	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 (!lvm_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 (!lvm_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 (!lvm_replicator_add_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)
+{
+	const struct replicator_site *rsite;
+	const 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;
+	const struct replicator_device *rdev, *rdev_search;
+	struct replicator_site *rsite;
+	struct logical_volume *lv;
+	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 rdev list error");
+				return 0;
+			}
+		}
+
+		if (!(lv = rdev->lv)) {
+			/* Should be already resolved in create partial */
+			log_error("Broken/Unused _create_partial_replicator()?");
+			if (!rdev->rsite->vg_name ||
+			    !rdev->name ||
+			    !rdev->rsite->vg)
+				return_0;
+
+			if (!(lv = find_lv(rdev->rsite->vg, rdev->name)))
+				return_0;
+		}
+
+		if (!(rdev_dlid = build_dlid(dm, 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 = 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 int _replicator_dev_modules_needed(struct dm_pool *mem,
+					  const struct lv_segment *seg __attribute((unused)),
+					  struct dm_list *modules)
+{
+	if (!str_list_add(mem, modules, REPLICATOR_DEV_MODULE))
+		return_0;
+
+	return 1;
+}
+
+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_dev_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.6.5.3



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

* [PATCH 07/22] Replicator: validation of replicator segments
  2009-12-04 14:04 [PATCH 00/22] Replicator lvm support Zdenek Kabelac
                   ` (5 preceding siblings ...)
  2009-12-04 14:04 ` [PATCH 06/22] Replicator: add lvm support Zdenek Kabelac
@ 2009-12-04 14:04 ` Zdenek Kabelac
  2009-12-04 14:04 ` [PATCH 08/22] Replicator: extend _lv_each_dependency() rep. deps Zdenek Kabelac
                   ` (14 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2009-12-04 14:04 UTC (permalink / raw)
  To: lvm-devel

Validate segments with Replicator content

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

diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index 8feb6fc..5b46c25 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -2088,6 +2088,71 @@ void lv_calculate_readahead(const struct logical_volume *lv, uint32_t *read_ahea
 	}
 }
 
+/*
+ * Check for duplicate
+ *  site name
+ *  site index
+ *  device name
+ *  device index
+ */
+static int _replicator_validate(const struct logical_volume *lv)
+{
+	const struct replicator_site *rsite, *rsiteb;
+	const struct replicator_device *rdev, *rdevb;
+	int r = 1;
+
+	dm_list_iterate_items(rsite, &lv->rsites) {
+		dm_list_iterate_items(rsiteb, &lv->rsites) {
+			if (rsite == rsiteb)
+				break;
+			if (strcasecmp(rsite->name, rsiteb->name) == 0) {
+				log_error("Internal error: Duplicate site name"
+					  " %s detected for replicator %s.",
+					  rsite->name, lv->name);
+				r = 0;
+			}
+			if (rsite->site_index == rsiteb->site_index) {
+				log_error("Internal error: Duplicate site index"
+					  " %d detected for replicator %s/%s.",
+					  rsite->site_index, 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("Internal 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("Internal error: Duplicate "
+						  "device name %s detected "
+						  "for replicator %s.",
+						  rdev->name, lv->name);
+					r = 0;
+				}
+				if (rdev->device_index == rdevb->device_index) {
+					log_error("Internal error: Duplicate "
+						  "device index %" PRId64
+						  " detected for replicator "
+						  "%s/%s.", rdev->device_index,
+						  lv->name, rsite->name);
+					r = 0;
+				}
+			}
+		}
+	}
+
+	return r;
+}
+
 int vg_validate(struct volume_group *vg)
 {
 	struct pv_list *pvl, *pvl2;
@@ -2188,6 +2253,9 @@ int vg_validate(struct volume_group *vg)
 				r = 0;
 			}
 		}
+
+		if (lv_is_replicator(lvl->lv) && !_replicator_validate(lvl->lv))
+			r = 0;
 	}
 
 	dm_list_iterate_items(lvl, &vg->lvs) {
-- 
1.6.5.3



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

* [PATCH 08/22] Replicator: extend _lv_each_dependency() rep. deps
  2009-12-04 14:04 [PATCH 00/22] Replicator lvm support Zdenek Kabelac
                   ` (6 preceding siblings ...)
  2009-12-04 14:04 ` [PATCH 07/22] Replicator: validation of replicator segments Zdenek Kabelac
@ 2009-12-04 14:04 ` Zdenek Kabelac
  2009-12-04 14:04 ` [PATCH 09/22] Replicator: add sorted vg_name_list Zdenek Kabelac
                   ` (13 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2009-12-04 14:04 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 5b46c25..9869a3c 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -1927,6 +1927,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) {
@@ -1937,6 +1939,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.6.5.3



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

* [PATCH 09/22] Replicator: add sorted vg_name_list
  2009-12-04 14:04 [PATCH 00/22] Replicator lvm support Zdenek Kabelac
                   ` (7 preceding siblings ...)
  2009-12-04 14:04 ` [PATCH 08/22] Replicator: extend _lv_each_dependency() rep. deps Zdenek Kabelac
@ 2009-12-04 14:04 ` Zdenek Kabelac
  2009-12-04 14:04 ` [PATCH 10/22] Replicator: use vg_name_list for _process_one_vg() Zdenek Kabelac
                   ` (12 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2009-12-04 14:04 UTC (permalink / raw)
  To: lvm-devel

Introduce struct vg_name_list to store information about needed
volume group name and the pointer to opened VG.

VG must be opened in alphabetical order, thus elements in the list
are being kept ordered all the time.

Introduce functions vg_name_list_add(), vg_name_list_lookup().
They extend dm_list functionality.

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

diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index aa92339..fd705c3 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -281,6 +281,14 @@ struct lv_segment_area {
 
 struct segment_type;
 
+/* List with VG names
+ * similar to  str_list with one extra pointer */
+struct vg_name_list {
+	struct dm_list list;
+	const char *name;
+	struct volume_group *vg;
+};
+
 /* ++ replicator datatypes */
 typedef enum {
 	REPLICATOR_ACTION_WARN,
@@ -778,6 +786,15 @@ int lv_is_slog(const struct logical_volume *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);
 /* --  metadata/replicator_manip.c */
+/*
+ * Maintain the alphabeticaly ordered list, avoid duplications
+ * return either newly created or already present vg_name_list entry
+ */
+struct vg_name_list *vg_name_list_add(struct dm_pool *mem, struct dm_list *,
+				      const char *name);
+/* Find element with given name in vg_name_list list */
+struct vg_name_list *vg_name_list_lookup(struct dm_list *, const char *name);
+
 
 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 4b24e02..1b970a0 100644
--- a/lib/metadata/replicator_manip.c
+++ b/lib/metadata/replicator_manip.c
@@ -307,3 +307,48 @@ struct logical_volume *first_replicator_dev(const struct logical_volume *lv)
 
 	return NULL;
 }
+
+/* Add to sorted list */
+struct vg_name_list *vg_name_list_add(struct dm_pool *mem, struct dm_list *l,
+				      const char *name)
+{
+	struct vg_name_list *vnl, *ins;
+
+	/* Is already in the list ? */
+	if ((vnl = vg_name_list_lookup(l, name)))
+		return vnl;
+
+	if (!(vnl = dm_pool_alloc(mem, sizeof(*vnl)))) {
+		log_error("Allocation of vg_name_list failed.");
+		return NULL;
+	}
+
+	if (!(vnl->name = dm_pool_strdup(mem, name))) {
+		dm_pool_free(mem, vnl);
+		log_error("Allocation of name failed.");
+		return NULL;
+	}
+
+	vnl->vg = NULL;
+	dm_list_iterate_items(ins, l)
+		if (strcmp(name, ins->name) < 0) {
+			l = &ins->list;
+			break;
+		}
+
+	dm_list_add(l, &vnl->list);
+
+	return vnl;
+}
+
+/* Lookup element with given name in ordered vg_name_list */
+struct vg_name_list *vg_name_list_lookup(struct dm_list *l, const char *name)
+{
+	struct vg_name_list *vnl;
+
+	dm_list_iterate_items(vnl, l)
+		if (!strcmp(name, vnl->name))
+			return vnl;
+
+	return NULL;
+}
-- 
1.6.5.3



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

* [PATCH 10/22] Replicator: use vg_name_list for _process_one_vg()
  2009-12-04 14:04 [PATCH 00/22] Replicator lvm support Zdenek Kabelac
                   ` (8 preceding siblings ...)
  2009-12-04 14:04 ` [PATCH 09/22] Replicator: add sorted vg_name_list Zdenek Kabelac
@ 2009-12-04 14:04 ` Zdenek Kabelac
  2009-12-04 14:04 ` [PATCH 11/22] Replicator: use str_list for process_each_lv_in_vg Zdenek Kabelac
                   ` (11 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2009-12-04 14:04 UTC (permalink / raw)
  To: lvm-devel

Use list of sorted VG names from cmd_context structure.

Patch modifes behavior of _process_one_vg() by handling error case
from vg_read() immeditaly and not in the 'out:' path.

For the first pass plain vg_read() for the given name is used. Replicator
collects sorted list of required VG names in this run. If any of them
is not yet opened next loop is taken with alphabetically opened VGs.
VGs are released in reversed order from their open order.

Extra flag vgs_missed is used to detect state, when some of VGs are
missing.

CHECKME: flags for external VGs could be probably different.
         memory release from cmd_context list.

Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
 lib/commands/toolcontext.c |    1 +
 lib/commands/toolcontext.h |    2 +
 tools/toollib.c            |   89 +++++++++++++++++++++++++++++++++-----------
 3 files changed, 70 insertions(+), 22 deletions(-)

diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c
index 4b68851..55cc46e 100644
--- a/lib/commands/toolcontext.c
+++ b/lib/commands/toolcontext.c
@@ -1098,6 +1098,7 @@ struct cmd_context *create_toolcontext(unsigned is_long_lived,
 	dm_list_init(&cmd->segtypes);
 	dm_list_init(&cmd->tags);
 	dm_list_init(&cmd->config_files);
+	dm_list_init(&cmd->vgs_list);
 
 	/* FIXME Make this configurable? */
 	reset_lvm_errno(1);
diff --git a/lib/commands/toolcontext.h b/lib/commands/toolcontext.h
index 2ffc86d..d01c4f7 100644
--- a/lib/commands/toolcontext.h
+++ b/lib/commands/toolcontext.h
@@ -60,6 +60,8 @@ struct cmd_context {
 
 	struct dm_list formats;	/* Available formats */
 	struct dm_list segtypes;	/* Available segment types */
+	struct dm_list vgs_list;	/* Required read-only VGs */
+	int vgs_missed;			/* Missed VGs */
 	const char *hostname;
 	const char *kernel_vsn;
 
diff --git a/tools/toollib.c b/tools/toollib.c
index 33daf30..bea7a98 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -426,36 +426,81 @@ static int _process_one_vg(struct cmd_context *cmd, const char *vg_name,
 						  struct volume_group * vg,
 						  void *handle))
 {
-	struct volume_group *vg;
+	struct volume_group *vg, *rvg;
+	struct vg_name_list *vnl;
 	int ret = 0;
 
 	log_verbose("Finding volume group \"%s\"", vg_name);
 
-	vg = vg_read(cmd, vg_name, vgid, flags);
-	/* Allow FAILED_INCONSISTENT through only for vgcfgrestore */
-	if (vg_read_error(vg) &&
-	    !((vg_read_error(vg) == FAILED_INCONSISTENT) &&
-	      (flags & READ_ALLOW_INCONSISTENT))) {
-		ret_max = ECMD_FAILED;
-		goto_out;
-	}
+	dm_list_init(&cmd->vgs_list);
+	if (!vg_name_list_add(cmd->mem, &cmd->vgs_list, vg_name))
+		return_0;
 
-	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;
-	}
+	while (!sigint_caught()) {
+		vg = NULL;
+		/* Iterate through alphabeticaly ordered list */
+		dm_list_iterate_items(vnl, &cmd->vgs_list) {
+			if (!vg && strcmp(vnl->name, vg_name) == 0)
+				rvg = vg = vg_read(cmd, vg_name, vgid, flags);
+			else /* CHECKME: use different flags for remote VG? */
+				rvg = vg_read(cmd, vnl->name, NULL, flags);
+
+			if (vg_read_error(rvg)) {
+				if ((vg != rvg) ||
+				    /* Allow FAILED_INCONSISTENT through
+				     * only for vgcfgrestore */
+				    !((flags & READ_ALLOW_INCONSISTENT) &&
+				      (vg_read_error(vg) == FAILED_INCONSISTENT))) {
+					vg_release(vg);
+					ret_max = ECMD_FAILED;
+					goto_out;
+				}
+			} else
+				vnl->vg = rvg; /* Only correctly opened */
+
+			if (rvg == vg &&
+			    !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, &vg->tags)) {
+				if (vg_read_error(vg))
+					vg_release(vg);
+				break;
+			}
+		}
+
+		cmd->vgs_missed = 0;
+		if ((ret = process_single(cmd, vg_name, vg,
+					  handle)) > ret_max)
+			ret_max = ret;
 
-	if ((ret = process_single(cmd, vg_name, vg,
-				  handle)) > ret_max)
-		ret_max = ret;
+		if (vg_read_error(vg)) {
+			/* Leave for inconsistent case */
+			vg_release(vg);
+			break;
+		}
+
+		if (!cmd->vgs_missed)
+			break;
 
+		/* Release opened VGs in reverse order */
+		dm_list_iterate_back_items(vnl, &cmd->vgs_list)
+			if (vnl->vg) {
+				unlock_and_release_vg(cmd, vnl->vg, vnl->name);
+				vnl->vg = NULL;
+			}
+	}
 out:
-	if (vg_read_error(vg))
-		vg_release(vg);
-	else
-		unlock_and_release_vg(cmd, vg, vg_name);
+	dm_list_iterate_back_items(vnl, &cmd->vgs_list)
+		if (vnl->vg) {
+			unlock_and_release_vg(cmd, vnl->vg, vnl->name);
+			vnl->vg = NULL;
+		}
+	/*
+	 * CHECKME: empty cmd->vgs_list?
+	 * using dm_malloc instead of dm_pool, as the list is reordered?
+	 */
+
 	return ret_max;
 }
 
-- 
1.6.5.3



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

* [PATCH 11/22] Replicator: use str_list for process_each_lv_in_vg
  2009-12-04 14:04 [PATCH 00/22] Replicator lvm support Zdenek Kabelac
                   ` (9 preceding siblings ...)
  2009-12-04 14:04 ` [PATCH 10/22] Replicator: use vg_name_list for _process_one_vg() Zdenek Kabelac
@ 2009-12-04 14:04 ` Zdenek Kabelac
  2009-12-04 14:04 ` [PATCH 12/22] Replicator: update _create_partial_dtree() Zdenek Kabelac
                   ` (10 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2009-12-04 14:04 UTC (permalink / raw)
  To: lvm-devel

As for _process_one_vg() we need similar retry loop for
process_each_lv_in_vg(). This patch tries to collect missed LVs and
then reopens collected VGs and process only selected LVs again.

Patch does not add any extra repeated invocations if there is no missed VG
during LV processing.

cmd_context is extended to avoid API change with vgs_lvs_retry list.

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

diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c
index 55cc46e..aa16fb0 100644
--- a/lib/commands/toolcontext.c
+++ b/lib/commands/toolcontext.c
@@ -1099,6 +1099,7 @@ struct cmd_context *create_toolcontext(unsigned is_long_lived,
 	dm_list_init(&cmd->tags);
 	dm_list_init(&cmd->config_files);
 	dm_list_init(&cmd->vgs_list);
+	dm_list_init(&cmd->vgs_lvs_retry);
 
 	/* FIXME Make this configurable? */
 	reset_lvm_errno(1);
diff --git a/lib/commands/toolcontext.h b/lib/commands/toolcontext.h
index d01c4f7..c48276c 100644
--- a/lib/commands/toolcontext.h
+++ b/lib/commands/toolcontext.h
@@ -61,6 +61,7 @@ struct cmd_context {
 	struct dm_list formats;	/* Available formats */
 	struct dm_list segtypes;	/* Available segment types */
 	struct dm_list vgs_list;	/* Required read-only VGs */
+	struct dm_list vgs_lvs_retry;	/* Retry LVs with more VGs */
 	int vgs_missed;			/* Missed VGs */
 	const char *hostname;
 	const char *kernel_vsn;
diff --git a/tools/toollib.c b/tools/toollib.c
index bea7a98..f76879f 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -118,6 +118,7 @@ int process_each_lv_in_vg(struct cmd_context *cmd,
 		process_all = 1;
 	}
 
+	dm_list_init(&cmd->vgs_lvs_retry);
 	dm_list_iterate_items(lvl, &vg->lvs) {
 		if (lvl->lv->status & SNAPSHOT)
 			continue;
@@ -147,7 +148,17 @@ int process_each_lv_in_vg(struct cmd_context *cmd,
 		if (!process_lv)
 			continue;
 
+		cmd->vgs_missed = 0;
 		ret = process_single(cmd, lvl->lv, handle);
+		if (cmd->vgs_missed) {
+			if (!str_list_add(cmd->mem, &cmd->vgs_lvs_retry,
+					  dm_pool_strdup(cmd->mem,
+							 lvl->lv->name))) {
+				log_error("Allocation failed for str_list .");
+				return ECMD_FAILED;
+			}
+			ret = 0;
+		}
 		if (ret > ret_max)
 			ret_max = ret;
 		if (sigint_caught())
@@ -175,8 +186,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 str_list *sll, *strl, *sllt;
+	struct volume_group *vg, *rvg;
+	struct vg_name_list *vnl;
 	struct dm_list tags, lvnames;
 	struct dm_list arg_lvnames;	/* Cmdline vgname or vgname/lvname */
 	char *vglv;
@@ -321,11 +333,69 @@ int process_each_lv(struct cmd_context *cmd, int argc, char **argv,
 			}
 		}
 
+		dm_list_init(&cmd->vgs_list);
 		ret = process_each_lv_in_vg(cmd, vg, &lvnames, tags_arg,
 					    handle, process_single);
 		unlock_and_release_vg(cmd, vg, vgname);
 		if (ret > ret_max)
 			ret_max = ret;
+
+		while (!sigint_caught() &&
+		       !dm_list_empty(&cmd->vgs_lvs_retry)) {
+			/*
+			 * Try again with missed LVs in this VG
+			 * Use retry list as list of LVs to be processed
+			 * CHECKME: maybe add support dm_list_splice()
+			 */
+			dm_list_init(&lvnames);
+			dm_list_iterate_items_safe(sll, sllt,
+						   &cmd->vgs_lvs_retry)
+				dm_list_move(&lvnames, &sll->list);
+
+			if (!vg_name_list_add(cmd->mem, &cmd->vgs_list,
+					      vgname)) {
+				stack;
+				return ECMD_FAILED;
+			}
+
+			vg = NULL;
+			dm_list_iterate_items(vnl, &cmd->vgs_list) {
+				if (!vg && strcmp(vnl->name, vgname) == 0)
+					rvg = vg = vg_read(cmd, vgname,
+							   NULL, flags);
+				else
+					/*
+					 * CHECKME: Use different flags
+					 *          for remote vg ??
+					 */
+					rvg = vg_read(cmd, vnl->name,
+						      NULL, flags);
+
+				if (vg_read_error(rvg)) {
+					vg_release(rvg);
+					log_error("Skipping volume group %s.",
+						  vnl->name);
+					vg = NULL;
+					break;
+				}
+				vnl->vg = rvg; /* Only correctly opened */
+			}
+
+			ret = (!vg) ? ECMD_FAILED :
+				process_each_lv_in_vg(cmd, vg, &lvnames,
+						      tags_arg, handle,
+						      process_single);
+
+			dm_list_iterate_back_items(vnl, &cmd->vgs_list)
+				if (vnl->vg) {
+					unlock_and_release_vg(cmd, vnl->vg,
+							      vnl->name);
+					vnl->vg = NULL;
+				}
+			if (ret > ret_max)
+				ret_max = ret;
+		}
+
 		if (sigint_caught())
 			break;
 	}
-- 
1.6.5.3



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

* [PATCH 12/22] Replicator: update _create_partial_dtree()
  2009-12-04 14:04 [PATCH 00/22] Replicator lvm support Zdenek Kabelac
                   ` (10 preceding siblings ...)
  2009-12-04 14:04 ` [PATCH 11/22] Replicator: use str_list for process_each_lv_in_vg Zdenek Kabelac
@ 2009-12-04 14:04 ` Zdenek Kabelac
  2009-12-04 14:04 ` [PATCH 13/22] Replicator: using vgs_missed for error count Zdenek Kabelac
                   ` (9 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2009-12-04 14:04 UTC (permalink / raw)
  To: lvm-devel

Creating partial tree for Replicator target.
Using dm_tree_set_priority() to set higher priority for Replicator.

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

diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
index 3071772..7363e46 100644
--- a/lib/activate/dev_manager.c
+++ b/lib/activate/dev_manager.c
@@ -725,6 +725,98 @@ 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;
+	struct vg_name_list *vnl;
+	const char *replicator_dlid;
+	int vg_missing = 0;
+
+	if (!lv_is_active_replicator_dev(seg->lv)) {
+		if (!_add_dev_to_dtree(dm, dtree, seg->lv->rdevice->lv,
+				       NULL))
+			return_0;
+		return 1;
+	}
+
+	/* Check and fill needed VGs */
+	dm_list_iterate_items(rsite, &seg->replicator->rsites) {
+		if (!rsite->vg_name)
+			continue;
+
+		if (!(vnl = vg_name_list_add(dm->cmd->mem, &dm->cmd->vgs_list,
+					     rsite->vg_name)))
+			return_0;
+
+		if ((rsite->vg = vnl->vg))
+			continue;
+
+		vg_missing++;
+		log_verbose("VG %s added as missing.", rsite->vg_name);
+	}
+
+	if (vg_missing) {
+		dm->cmd->vgs_missed++;
+		log_very_verbose("Some VGs are missing, retry with them.");
+		return 0;
+	}
+
+	/* 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;
+			}
+
+			/* Add _slog LV */
+			if (rdev->slog &&
+			    !_add_dev_to_dtree(dm, dtree, rdev->slog, NULL))
+				return_0;
+
+			/* Resolve and add remote LV  */
+			if (rdev->rsite->vg && rdev->name &&
+			    (!(rdev->lv = find_lv(rdev->rsite->vg, rdev->name)) ||
+			     !_add_dev_to_dtree(dm, dtree, rdev->lv, 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_replicator_suspend(dtree, replicator_dlid))
+		return_0;
+
+	return 1;
+}
+
 static struct dm_tree *_create_partial_dtree(struct dev_manager *dm, struct logical_volume *lv)
 {
 	struct dm_tree *dtree;
@@ -745,6 +837,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.6.5.3



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

* [PATCH 13/22] Replicator: using vgs_missed for error count
  2009-12-04 14:04 [PATCH 00/22] Replicator lvm support Zdenek Kabelac
                   ` (11 preceding siblings ...)
  2009-12-04 14:04 ` [PATCH 12/22] Replicator: update _create_partial_dtree() Zdenek Kabelac
@ 2009-12-04 14:04 ` Zdenek Kabelac
  2009-12-04 14:04 ` [PATCH 14/22] Replicator: add vgs_print for message postponing Zdenek Kabelac
                   ` (8 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2009-12-04 14:04 UTC (permalink / raw)
  To: lvm-devel

Lower expected_count for the case of missed VGs so no error is printed
in case the remote VGs are not opened. Currently it's needed only for
Replicator target.

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

diff --git a/tools/vgchange.c b/tools/vgchange.c
index f791e53..9da877e 100644
--- a/tools/vgchange.c
+++ b/tools/vgchange.c
@@ -102,6 +102,7 @@ static int _activate_lvs_in_vg(struct cmd_context *cmd,
 		count++;
 	}
 
+	expected_count -= cmd->vgs_missed;
 	if (expected_count)
 		log_verbose("%s %d logical volumes in volume group %s",
 			    activate ? "Activated" : "Deactivated",
-- 
1.6.5.3



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

* [PATCH 14/22] Replicator: add vgs_print for message postponing
  2009-12-04 14:04 [PATCH 00/22] Replicator lvm support Zdenek Kabelac
                   ` (12 preceding siblings ...)
  2009-12-04 14:04 ` [PATCH 13/22] Replicator: using vgs_missed for error count Zdenek Kabelac
@ 2009-12-04 14:04 ` Zdenek Kabelac
  2009-12-04 14:04 ` [PATCH 15/22] Replicator: add replicator to dtree Zdenek Kabelac
                   ` (7 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2009-12-04 14:04 UTC (permalink / raw)
  To: lvm-devel

For replicator we introduce multiple runs over the same function.
In the first step some error prints could be generated, because not all
resources were available. Such message could be postponed so usually
only the last message gets printed.

Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
 lib/commands/toolcontext.h |    1 +
 tools/toollib.c            |    7 +++++++
 tools/vgchange.c           |   10 ++++++++--
 3 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/lib/commands/toolcontext.h b/lib/commands/toolcontext.h
index c48276c..44ebe1f 100644
--- a/lib/commands/toolcontext.h
+++ b/lib/commands/toolcontext.h
@@ -63,6 +63,7 @@ struct cmd_context {
 	struct dm_list vgs_list;	/* Required read-only VGs */
 	struct dm_list vgs_lvs_retry;	/* Retry LVs with more VGs */
 	int vgs_missed;			/* Missed VGs */
+	char *vgs_print;		/* Error case print */
 	const char *hostname;
 	const char *kernel_vsn;
 
diff --git a/tools/toollib.c b/tools/toollib.c
index f76879f..e784fb7 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -561,6 +561,13 @@ static int _process_one_vg(struct cmd_context *cmd, const char *vg_name,
 			}
 	}
 out:
+	if (cmd->vgs_print) {
+		/* Postponed print */
+		log_print("%s", cmd->vgs_print);
+		dm_free(cmd->vgs_print);
+		cmd->vgs_print = NULL;
+	}
+
 	dm_list_iterate_back_items(vnl, &cmd->vgs_list)
 		if (vnl->vg) {
 			unlock_and_release_vg(cmd, vnl->vg, vnl->name);
diff --git a/tools/vgchange.c b/tools/vgchange.c
index 9da877e..7171f5d 100644
--- a/tools/vgchange.c
+++ b/tools/vgchange.c
@@ -168,8 +168,14 @@ 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);
+	/* Postpone print */
+	dm_free(cmd->vgs_print);
+	if (dm_asprintf(&cmd->vgs_print,
+			"%d logical volume(s) in volume group \"%s\" now active",
+			lvs_in_vg_activated(vg), vg->name) < 0) {
+		cmd->vgs_print = NULL;
+	}
+
 	return ret;
 }
 
-- 
1.6.5.3



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

* [PATCH 15/22] Replicator: add replicator to dtree
  2009-12-04 14:04 [PATCH 00/22] Replicator lvm support Zdenek Kabelac
                   ` (13 preceding siblings ...)
  2009-12-04 14:04 ` [PATCH 14/22] Replicator: add vgs_print for message postponing Zdenek Kabelac
@ 2009-12-04 14:04 ` Zdenek Kabelac
  2009-12-04 14:05 ` [PATCH 16/22] Replicator: do not remove of replicators' LVs Zdenek Kabelac
                   ` (6 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2009-12-04 14:04 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 7363e46..9fb8b2e 100644
--- a/lib/activate/dev_manager.c
+++ b/lib/activate/dev_manager.c
@@ -1024,6 +1024,58 @@ 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)
+{
+	const 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;
+	}
+
+	/* Activation of one replicator node activate all other nodes */
+	if (!seg->replicator ||
+	    !_add_new_lv_to_dtree(dm, dtree, seg->replicator, NULL))
+		return_0;
+
+	dm_list_iterate_items(rsite, &seg->replicator->rsites) {
+		dm_list_iterate_items(rdev, &rsite->rdevices) {
+			if (!rdev->lv || /* Resolved in _partial */
+			    !_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,
@@ -1054,8 +1106,14 @@ 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;
+	} else if (seg_is_replicator(seg) && seg->rlog_lv) {
+		if (!_add_new_lv_to_dtree(dm, dtree, seg->rlog_lv, NULL))
+			return_0;
 	/* If this is a snapshot origin, add 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.6.5.3



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

* [PATCH 16/22] Replicator: do not remove of replicators' LVs
  2009-12-04 14:04 [PATCH 00/22] Replicator lvm support Zdenek Kabelac
                   ` (14 preceding siblings ...)
  2009-12-04 14:04 ` [PATCH 15/22] Replicator: add replicator to dtree Zdenek Kabelac
@ 2009-12-04 14:05 ` Zdenek Kabelac
  2009-12-04 14:05 ` [PATCH 17/22] Replicator: no crash lvresize if area_count is 0 Zdenek Kabelac
                   ` (5 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2009-12-04 14:05 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 1a2404c..99aa8f9 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -2084,6 +2084,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.6.5.3



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

* [PATCH 17/22] Replicator: no crash lvresize if area_count is 0
  2009-12-04 14:04 [PATCH 00/22] Replicator lvm support Zdenek Kabelac
                   ` (15 preceding siblings ...)
  2009-12-04 14:05 ` [PATCH 16/22] Replicator: do not remove of replicators' LVs Zdenek Kabelac
@ 2009-12-04 14:05 ` Zdenek Kabelac
  2009-12-04 14:06 ` [PATCH 18/22] Replicator: activate change for vgchange Zdenek Kabelac
                   ` (4 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2009-12-04 14:05 UTC (permalink / raw)
  To: lvm-devel

Currently with replicator-dev LV we get area_count=0 for lvresize request.
The original reason needs to be exploread, meanwhile avoid crash,
but stopping processing if count is 0.

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

diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 99aa8f9..5f85261 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -1369,6 +1369,11 @@ int lv_add_segment(struct alloc_handle *ah,
 		return 0;
 	}
 
+	if (!ah->area_count) {
+		log_error("Allocated areas are empty.");
+		return 0;
+	}
+
 	if (!_setup_alloced_segments(lv, &ah->alloced_areas[first_area],
 				     num_areas, status,
 				     stripe_size, segtype,
-- 
1.6.5.3



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

* [PATCH 18/22] Replicator: activate change for vgchange
  2009-12-04 14:04 [PATCH 00/22] Replicator lvm support Zdenek Kabelac
                   ` (16 preceding siblings ...)
  2009-12-04 14:05 ` [PATCH 17/22] Replicator: no crash lvresize if area_count is 0 Zdenek Kabelac
@ 2009-12-04 14:06 ` Zdenek Kabelac
  2009-12-04 14:06 ` [PATCH 19/22] Replicator: add new options for replicator Zdenek Kabelac
                   ` (3 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2009-12-04 14:06 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 7171f5d..f83e613 100644
--- a/tools/vgchange.c
+++ b/tools/vgchange.c
@@ -72,6 +72,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.6.5.3



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

* [PATCH 19/22] Replicator: add new options for replicator
  2009-12-04 14:04 [PATCH 00/22] Replicator lvm support Zdenek Kabelac
                   ` (17 preceding siblings ...)
  2009-12-04 14:06 ` [PATCH 18/22] Replicator: activate change for vgchange Zdenek Kabelac
@ 2009-12-04 14:06 ` Zdenek Kabelac
  2009-12-04 14:06 ` [PATCH 20/22] Replicator: update copyright dates Zdenek Kabelac
                   ` (2 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2009-12-04 14:06 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                     |    5 ++++
 tools/commands.h                 |   10 ++++++-
 tools/lvcreate.c                 |   49 ++++++++++++++++++++++++++++++++++++++
 tools/lvmcmdline.c               |    9 +++++++
 tools/tools.h                    |    1 +
 7 files changed, 74 insertions(+), 2 deletions(-)

diff --git a/lib/config/defaults.h b/lib/config/defaults.h
index a4e8d09..5308678 100644
--- a/lib/config/defaults.h
+++ b/lib/config/defaults.h
@@ -105,6 +105,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 fd705c3..512253c 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -592,6 +592,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 1f2427b..40b92b3 100644
--- a/tools/args.h
+++ b/tools/args.h
@@ -64,6 +64,11 @@ arg(dataalignmentoffset_ARG, '\0', "dataalignmentoffset", size_kb_arg, 0)
 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(replicator_ARG, '\0', "replicator", 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)
 
 /* Allow some variations */
 arg(resizable_ARG, '\0', "resizable", yes_no_arg, 0)
diff --git a/tools/commands.h b/tools/commands.h
index 85222e4..fc37889 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"
@@ -89,7 +91,7 @@ xx(lvchange,
    ignorelockingfailure_ARG, ignoremonitoring_ARG, major_ARG, minor_ARG,
    monitor_ARG, noudevsync_ARG, partial_ARG, permission_ARG, persistent_ARG,
    readahead_ARG, resync_ARG, refresh_ARG, addtag_ARG, deltag_ARG, test_ARG,
-   yes_ARG)
+   addsite_ARG, delsite_ARG, yes_ARG)
 
 xx(lvconvert,
    "Change logical volume layout",
@@ -145,6 +147,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"
@@ -179,7 +184,8 @@ xx(lvcreate,
    addtag_ARG, alloc_ARG, autobackup_ARG, chunksize_ARG, contiguous_ARG,
    corelog_ARG, extents_ARG, major_ARG, minor_ARG, mirrorlog_ARG, mirrors_ARG,
    name_ARG, nosync_ARG, noudevsync_ARG, permission_ARG, persistent_ARG,
-   readahead_ARG, regionsize_ARG, size_ARG, snapshot_ARG, stripes_ARG,
+   readahead_ARG, regionsize_ARG, replicator_ARG, replicatorlog_ARG,
+   replicatorlogtype_ARG, size_ARG, snapshot_ARG, stripes_ARG,
    stripesize_ARG, test_ARG, type_ARG, virtualoriginsize_ARG, virtualsize_ARG,
    zero_ARG)
 
diff --git a/tools/lvcreate.c b/tools/lvcreate.c
index 06f3478..c415050 100644
--- a/tools/lvcreate.c
+++ b/tools/lvcreate.c
@@ -371,6 +371,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 regionsize in configuration "
+				  "file is invalid.");
+			return 0;
+		}
+		lp->region_size = region_size;
+	}
+
+	if (!_validate_mirror_params(cmd, lp))
+		return 0;
+
+	return 1;
+}
+
 static int _lvcreate_params(struct lvcreate_params *lp,
 			    struct lvcreate_cmdline_params *lcp,
 			    struct cmd_context *cmd,
@@ -403,6 +433,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)
@@ -467,6 +500,22 @@ static int _lvcreate_params(struct lvcreate_params *lp,
 		}
 	}
 
+	if (lp->replicator) {
+		log_error("--replicator for replicators");
+
+	} else {
+		if (arg_count(cmd, replicatorlog_ARG)) {
+			log_error("--replicatorlog is only available "
+				  "with replicators.");
+			return 0;
+		}
+		if (arg_count(cmd, replicatorlogtype_ARG)) {
+			log_error("--replicatorlogtype is only available "
+				  "with replicators.");
+			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 "
diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c
index e92675f..53e84bb 100644
--- a/tools/lvmcmdline.c
+++ b/tools/lvmcmdline.c
@@ -480,6 +480,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 578e32f..fb3b013 100644
--- a/tools/tools.h
+++ b/tools/tools.h
@@ -151,6 +151,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.6.5.3



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

* [PATCH 20/22] Replicator: update copyright dates
  2009-12-04 14:04 [PATCH 00/22] Replicator lvm support Zdenek Kabelac
                   ` (18 preceding siblings ...)
  2009-12-04 14:06 ` [PATCH 19/22] Replicator: add new options for replicator Zdenek Kabelac
@ 2009-12-04 14:06 ` Zdenek Kabelac
  2009-12-04 14:06 ` [PATCH 21/22] Replicator: new variable in generated file Zdenek Kabelac
  2009-12-04 14:06 ` [PATCH 22/22] Replicator: update of generated configure file Zdenek Kabelac
  21 siblings, 0 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2009-12-04 14:06 UTC (permalink / raw)
  To: lvm-devel

Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
 lib/activate/dev_manager.c |    2 +-
 lib/metadata/segtype.h     |    2 +-
 libdm/libdm-deptree.c      |    2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
index 9fb8b2e..fcbc0b2 100644
--- a/lib/activate/dev_manager.c
+++ b/lib/activate/dev_manager.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
- * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
  *
  * This file is part of LVM2.
  *
diff --git a/lib/metadata/segtype.h b/lib/metadata/segtype.h
index 20a032f..dfdb7bf 100644
--- a/lib/metadata/segtype.h
+++ b/lib/metadata/segtype.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
- * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
  *
  * This file is part of LVM2.
  *
diff --git a/libdm/libdm-deptree.c b/libdm/libdm-deptree.c
index a7fd7f4..a899854 100644
--- a/libdm/libdm-deptree.c
+++ b/libdm/libdm-deptree.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2005-2009 Red Hat, Inc. All rights reserved.
  *
  * This file is part of the device-mapper userspace tools.
  *
-- 
1.6.5.3



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

* [PATCH 21/22] Replicator: new variable in generated file
  2009-12-04 14:04 [PATCH 00/22] Replicator lvm support Zdenek Kabelac
                   ` (19 preceding siblings ...)
  2009-12-04 14:06 ` [PATCH 20/22] Replicator: update copyright dates Zdenek Kabelac
@ 2009-12-04 14:06 ` Zdenek Kabelac
  2009-12-04 14:06 ` [PATCH 22/22] Replicator: update of generated configure file Zdenek Kabelac
  21 siblings, 0 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2009-12-04 14:06 UTC (permalink / raw)
  To: lvm-devel


Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
 lib/misc/configure.h.in |    8 +++++++-
 1 files changed, 7 insertions(+), 1 deletions(-)

diff --git a/lib/misc/configure.h.in b/lib/misc/configure.h.in
index 4273eeb..a3ae9ad 100644
--- a/lib/misc/configure.h.in
+++ b/lib/misc/configure.h.in
@@ -273,7 +273,7 @@
 /* Define to 1 if you have the `strtoul' function. */
 #undef HAVE_STRTOUL
 
-/* Define to 1 if `st_rdev' is member of `struct stat'. */
+/* Define to 1 if `st_rdev' is a member of `struct stat'. */
 #undef HAVE_STRUCT_STAT_ST_RDEV
 
 /* Define to 1 if you have the <syslog.h> header file. */
@@ -410,6 +410,9 @@
 /* Define to the one symbol short name of this package. */
 #undef PACKAGE_TARNAME
 
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
 /* Define to the version of this package. */
 #undef PACKAGE_VERSION
 
@@ -419,6 +422,9 @@
 /* Define to 1 to include the LVM readline shell. */
 #undef READLINE_SUPPORT
 
+/* Define to 1 to include built-in support for replicator. */
+#undef REPLICATOR_INTERNAL
+
 /* Define as the return type of signal handlers (`int' or `void'). */
 #undef RETSIGTYPE
 
-- 
1.6.5.3



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

* [PATCH 22/22] Replicator: update of generated configure file
  2009-12-04 14:04 [PATCH 00/22] Replicator lvm support Zdenek Kabelac
                   ` (20 preceding siblings ...)
  2009-12-04 14:06 ` [PATCH 21/22] Replicator: new variable in generated file Zdenek Kabelac
@ 2009-12-04 14:06 ` Zdenek Kabelac
  21 siblings, 0 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2009-12-04 14:06 UTC (permalink / raw)
  To: lvm-devel


Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
 configure |   34 +++++++++++++++++++++++++++++++++-
 1 files changed, 33 insertions(+), 1 deletions(-)

diff --git a/configure b/configure
index 7da2d3c..d01d867 100755
--- a/configure
+++ b/configure
@@ -655,6 +655,7 @@ SELINUX_LIBS
 POOL
 PKGCONFIG
 OWNER
+REPLICATOR
 MIRRORS
 LVM_RELEASE_DATE
 LVM_RELEASE
@@ -814,6 +815,7 @@ with_pool
 with_cluster
 with_snapshots
 with_mirrors
+with_replicator
 enable_readline
 enable_realtime
 with_clvmd
@@ -1546,6 +1548,8 @@ Optional Packages:
                           TYPE=internal
   --with-mirrors=TYPE     Mirror support: internal/shared/none
                           TYPE=internal
+  --with-replicator=TYPE  Replicator support: internal/shared/none
+                          [TYPE=none]
   --with-clvmd=TYPE       Build cluster LVM Daemon.
                           The following cluster manager combinations are valid:
                            * cman,gulm             (RHEL4 or equivalent)
@@ -9325,6 +9329,32 @@ _ACEOF
 fi
 
 ################################################################################
+{ $as_echo "$as_me:$LINENO: checking whether to include replicator" >&5
+$as_echo_n "checking whether to include replicator... " >&6; }
+
+# Check whether --with-replicator was given.
+if test "${with_replicator+set}" = set; then
+  withval=$with_replicator;  REPLICATOR="$withval"
+else
+   REPLICATOR="none"
+fi
+
+{ $as_echo "$as_me:$LINENO: result: $REPLICATOR" >&5
+$as_echo "$REPLICATOR" >&6; }
+
+case "$REPLICATOR" in
+ none|shared) ;;
+ internal)
+cat >>confdefs.h <<\_ACEOF
+#define REPLICATOR_INTERNAL 1
+_ACEOF
+ ;;
+ *) { { $as_echo "$as_me:$LINENO: error: --with-replicator parameter invalid ($REPLICATOR)" >&5
+$as_echo "$as_me: error: --with-replicator parameter invalid ($REPLICATOR)" >&2;}
+   { (exit 1); exit 1; }; } ;;
+esac
+
+################################################################################
 { $as_echo "$as_me:$LINENO: checking whether to enable readline" >&5
 $as_echo_n "checking whether to enable readline... " >&6; }
 # Check whether --enable-readline was given.
@@ -15525,8 +15555,9 @@ LVM_LIBAPI=`echo "$VER" | $AWK -F '[()]' '{print $2}'`
 
 
 
+
 ################################################################################
-ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile daemons/cmirrord/Makefile daemons/dmeventd/Makefile daemons/dmeventd/libdevmapper-event.pc daemons/dmeventd/plugins/Makefile daemons/dmeventd/plugins/mirror/Makefile daemons/dmeventd/plugins/snapshot/Makefile doc/Makefile include/.symlinks include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile lib/misc/lvm-version.h lib/snapshot/Makefile libdm/Makefile libdm/libdevmapper.pc liblvm/Makefile liblvm/liblvm2app.pc man/Makefile po/Makefile scripts/clvmd_init_red_hat scripts/lvm2_monitoring_init_red_hat scripts/Makefile test/Makefile test/api/Makefile tools/Makefile udev/Makefile"
+ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile daemons/cmirrord/Makefile daemons/dmeventd/Makefile daemons/dmeventd/libdevmapper-event.pc daemons/dmeventd/plugins/Makefile daemons/dmeventd/plugins/mirror/Makefile daemons/dmeventd/plugins/snapshot/Makefile doc/Makefile include/.symlinks include/Makefile lib/Makefile 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 libdm/libdevmapper.pc liblvm/Makefile liblvm/liblvm2app.pc man/Makefile po/Makefile scripts/clvmd_init_red_hat scripts/lvm2_monitoring_init_red_hat scripts/Makefile test/Makefile test/api/Makefile tools/Makefile udev/Makefile"
 
 cat >confcache <<\_ACEOF
 # This file is a shell script that caches the results of configure
@@ -16143,6 +16174,7 @@ do
     "lib/format_pool/Makefile") CONFIG_FILES="$CONFIG_FILES lib/format_pool/Makefile" ;;
     "lib/locking/Makefile") CONFIG_FILES="$CONFIG_FILES lib/locking/Makefile" ;;
     "lib/mirror/Makefile") CONFIG_FILES="$CONFIG_FILES lib/mirror/Makefile" ;;
+    "lib/replicator/Makefile") CONFIG_FILES="$CONFIG_FILES lib/replicator/Makefile" ;;
     "lib/misc/lvm-version.h") CONFIG_FILES="$CONFIG_FILES lib/misc/lvm-version.h" ;;
     "lib/snapshot/Makefile") CONFIG_FILES="$CONFIG_FILES lib/snapshot/Makefile" ;;
     "libdm/Makefile") CONFIG_FILES="$CONFIG_FILES libdm/Makefile" ;;
-- 
1.6.5.3



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

end of thread, other threads:[~2009-12-04 14:06 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-12-04 14:04 [PATCH 00/22] Replicator lvm support Zdenek Kabelac
2009-12-04 14:04 ` [PATCH 01/22] Export outsz() and outhnt() for modules Zdenek Kabelac
2009-12-04 14:04 ` [PATCH 02/22] Export outfc() macro and out_text_with_comment() Zdenek Kabelac
2009-12-04 14:04 ` [PATCH 03/22] Use outsz macro Zdenek Kabelac
2009-12-04 14:04 ` [PATCH 04/22] Replicator: add libdm support Zdenek Kabelac
2009-12-04 14:04 ` [PATCH 05/22] Replicator: suspend/deactivate replicator Zdenek Kabelac
2009-12-04 14:04 ` [PATCH 06/22] Replicator: add lvm support Zdenek Kabelac
2009-12-04 14:04 ` [PATCH 07/22] Replicator: validation of replicator segments Zdenek Kabelac
2009-12-04 14:04 ` [PATCH 08/22] Replicator: extend _lv_each_dependency() rep. deps Zdenek Kabelac
2009-12-04 14:04 ` [PATCH 09/22] Replicator: add sorted vg_name_list Zdenek Kabelac
2009-12-04 14:04 ` [PATCH 10/22] Replicator: use vg_name_list for _process_one_vg() Zdenek Kabelac
2009-12-04 14:04 ` [PATCH 11/22] Replicator: use str_list for process_each_lv_in_vg Zdenek Kabelac
2009-12-04 14:04 ` [PATCH 12/22] Replicator: update _create_partial_dtree() Zdenek Kabelac
2009-12-04 14:04 ` [PATCH 13/22] Replicator: using vgs_missed for error count Zdenek Kabelac
2009-12-04 14:04 ` [PATCH 14/22] Replicator: add vgs_print for message postponing Zdenek Kabelac
2009-12-04 14:04 ` [PATCH 15/22] Replicator: add replicator to dtree Zdenek Kabelac
2009-12-04 14:05 ` [PATCH 16/22] Replicator: do not remove of replicators' LVs Zdenek Kabelac
2009-12-04 14:05 ` [PATCH 17/22] Replicator: no crash lvresize if area_count is 0 Zdenek Kabelac
2009-12-04 14:06 ` [PATCH 18/22] Replicator: activate change for vgchange Zdenek Kabelac
2009-12-04 14:06 ` [PATCH 19/22] Replicator: add new options for replicator Zdenek Kabelac
2009-12-04 14:06 ` [PATCH 20/22] Replicator: update copyright dates Zdenek Kabelac
2009-12-04 14:06 ` [PATCH 21/22] Replicator: new variable in generated file Zdenek Kabelac
2009-12-04 14:06 ` [PATCH 22/22] Replicator: update of generated configure file 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.