All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/22] Replicator 100707
@ 2010-07-07 12:34 Zdenek Kabelac
  2010-07-07 12:34 ` [PATCH 01/22] Add units to passed parameters data & timeout Use size Zdenek Kabelac
                   ` (21 more replies)
  0 siblings, 22 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2010-07-07 12:34 UTC (permalink / raw)
  To: lvm-devel

This patchset enhances lvm with replicator metadata construction.
It 'should not' influence other commands.

Use case example:

# build remote devices
vgcreate vg_ny /dev/loop1
vgcreate vg_paris /dev/loop2

lvcreate -L10M -n L1 vg_ny
lvcreate -L10M -n L1 vg_paris
lvcreate -L20M -n L2 vg_ny
lvcreate -L20M -n L2 vg_paris

# build local replicator
vgcreate my /dev/loop0
lvcreate --replicator rep -L20M my

lvcreate --site Berlin --replicator my/rep
lvcreate --site NY --remotevg vg_ny --replicator my/rep
lvcreate --site Paris --remotevg vg_paris --replicator my/rep

lvcreate --replicatordev -L10M -n L1 --replicator my/rep
lvcreate --replicatordev -L20M -n L2 --replicator my/rep

lvcreate --replicator rep -L20M my || exit 1
lvcreate --replicatordev -L10M -n L1 --replicator my/rep

lvremove my/L1

Note: after removing 'L1'  LV  'L1_rimage' and '_slog' devices
are left in VG Ideally user should use  own 'VG'
and for removal just run:

vgremove my

lvchange --site Berlin --replicator my/rep  -ay
== lvchange --site Berlin my/L1  -ay
== lvchange --site Berlin my/rep  -ay


Zdenek Kabelac (22):
  Add units to passed parameters data & timeout     Use size
  Allow the user to not specify a size when creating snapshot.
  Skip check missing rem.VGs for non-activate locks
  Replicator: check for active replicator
  Replicator: add reserved names
  Replicator: man page update for lvm
  Replicator: add _replicator_in_sync
  Replicator: add report for replicator targets
  Replicator: improve detection of replicator-dev
  Replicator: new defaults
  Replicator: metadata update
  Replicator: replicator_manip changes
  Replicator: replicator.c changes
  Replicator: add new command option read functions
  Replicator: new args
  Replicator: read site_params
  Replicator: lv_manip - create replicator
  Replicator: lvcreate implementation
  Replicator: man page update for lvcreate
  Replicator: lvchange implementation
  Replicator: man page update for lvchange
  Replicator: lvremove implementation

 lib/config/defaults.h            |    9 +
 lib/locking/locking.h            |    2 +-
 lib/metadata/lv_manip.c          |  126 ++++-
 lib/metadata/merge.c             |   18 +-
 lib/metadata/metadata-exported.h |   59 ++-
 lib/metadata/replicator_manip.c  | 1211 +++++++++++++++++++++++++++++++-------
 lib/misc/lvm-globals.c           |   11 +
 lib/misc/lvm-globals.h           |    2 +
 lib/misc/lvm-string.c            |   18 +
 lib/replicator/replicator.c      |  178 ++----
 lib/report/columns.h             |    2 +
 lib/report/report.c              |   32 +
 libdm/libdm-deptree.c            |    4 +-
 man/lvchange.8.in                |   31 +
 man/lvcreate.8.in                |   76 +++
 man/lvm.8.in                     |    3 +-
 tools/args.h                     |   10 +
 tools/commands.h                 |   18 +-
 tools/lvchange.c                 |  195 ++++++-
 tools/lvcreate.c                 |  137 +++++-
 tools/lvmcmdline.c               |   24 +
 tools/lvremove.c                 |   19 +-
 tools/toollib.c                  |  111 ++++
 tools/toollib.h                  |    3 +
 tools/tools.h                    |    2 +
 tools/vgchange.c                 |    2 +-
 26 files changed, 1942 insertions(+), 361 deletions(-)



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

* [PATCH 01/22] Add units to passed parameters data & timeout Use size
  2010-07-07 12:34 [PATCH 00/22] Replicator 100707 Zdenek Kabelac
@ 2010-07-07 12:34 ` Zdenek Kabelac
  2010-07-07 12:34 ` [PATCH 02/22] Allow the user to not specify a size when creating snapshot Zdenek Kabelac
                   ` (20 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2010-07-07 12:34 UTC (permalink / raw)
  To: lvm-devel


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

diff --git a/libdm/libdm-deptree.c b/libdm/libdm-deptree.c
index fac9d21..ff714d9 100644
--- a/libdm/libdm-deptree.c
+++ b/libdm/libdm-deptree.c
@@ -1520,11 +1520,11 @@ static int _replicator_emit_segment_line(const struct load_segment *seg, char *p
 			    (rsite->mode == DM_REPLICATOR_SYNC) ? "synchronous" : "asynchronous");
 
 		if (rsite->fall_behind_data)
-			EMIT_PARAMS(*pos, " data %" PRIu64, rsite->fall_behind_data);
+			EMIT_PARAMS(*pos, " size %" PRIu64 "s", 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);
+			EMIT_PARAMS(*pos, " timeout %" PRIu32 "s", rsite->async_timeout);
 	}
 
 	return 1;
-- 
1.7.1.1



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

* [PATCH 02/22] Allow the user to not specify a size when creating snapshot.
  2010-07-07 12:34 [PATCH 00/22] Replicator 100707 Zdenek Kabelac
  2010-07-07 12:34 ` [PATCH 01/22] Add units to passed parameters data & timeout Use size Zdenek Kabelac
@ 2010-07-07 12:34 ` Zdenek Kabelac
  2010-07-07 12:34 ` [PATCH 03/22] Skip check missing rem.VGs for non-activate locks Zdenek Kabelac
                   ` (19 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2010-07-07 12:34 UTC (permalink / raw)
  To: lvm-devel

For shared snapshot, the size is not required. If the user creates other
volume than a shared snapshot, zero size will be rejected in
lv_create_single.

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

diff --git a/tools/lvcreate.c b/tools/lvcreate.c
index d0e962f..9e167aa 100644
--- a/tools/lvcreate.c
+++ b/tools/lvcreate.c
@@ -191,6 +191,9 @@ static int _read_size_params(struct lvcreate_params *lp,
 			     struct lvcreate_cmdline_params *lcp,
 			     struct cmd_context *cmd)
 {
+	if (!arg_count(cmd, extents_ARG) && !arg_count(cmd, size_ARG))
+		goto skip_size_arg;
+
 	if (arg_count(cmd, extents_ARG) + arg_count(cmd, size_ARG) != 1) {
 		log_error("Please specify either size or extents (not both)");
 		return 0;
@@ -215,6 +218,7 @@ static int _read_size_params(struct lvcreate_params *lp,
 		lcp->percent = PERCENT_NONE;
 	}
 
+skip_size_arg:
 	/* Size returned in kilobyte units; held in sectors */
 	if (arg_count(cmd, virtualsize_ARG)) {
 		if (arg_sign_value(cmd, virtualsize_ARG, 0) == SIGN_MINUS) {
-- 
1.7.1.1



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

* [PATCH 03/22] Skip check missing rem.VGs for non-activate locks
  2010-07-07 12:34 [PATCH 00/22] Replicator 100707 Zdenek Kabelac
  2010-07-07 12:34 ` [PATCH 01/22] Add units to passed parameters data & timeout Use size Zdenek Kabelac
  2010-07-07 12:34 ` [PATCH 02/22] Allow the user to not specify a size when creating snapshot Zdenek Kabelac
@ 2010-07-07 12:34 ` Zdenek Kabelac
  2010-07-07 12:34 ` [PATCH 04/22] Replicator: check for active replicator Zdenek Kabelac
                   ` (18 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2010-07-07 12:34 UTC (permalink / raw)
  To: lvm-devel

Skip call for checking whether this LV needs to locks some
more remote VGs (applies to replicator_dev devices).

The effect is, that deactivation of replicator-dev devices does
not require to take a lock for remote VGs, so avoids repeated invoke
of deactivate_lv.

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

diff --git a/lib/locking/locking.h b/lib/locking/locking.h
index 488d194..dde1a08 100644
--- a/lib/locking/locking.h
+++ b/lib/locking/locking.h
@@ -136,7 +136,7 @@ int check_lvm1_vg_inactive(struct cmd_context *cmd, const char *vgname);
 	(vg_is_clustered((lv)->vg) ? LCK_CLUSTER_VG : 0)
 
 #define lock_lv_vol(cmd, lv, flags)	\
-	(find_replicator_vgs((lv)) ? \
+	((!((flags) & LCK_READ) || find_replicator_vgs((lv))) ? \
 		lock_vol(cmd, (lv)->lvid.s, flags | LCK_LV_CLUSTERED(lv)) : \
 		0)
 
-- 
1.7.1.1



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

* [PATCH 04/22] Replicator: check for active replicator
  2010-07-07 12:34 [PATCH 00/22] Replicator 100707 Zdenek Kabelac
                   ` (2 preceding siblings ...)
  2010-07-07 12:34 ` [PATCH 03/22] Skip check missing rem.VGs for non-activate locks Zdenek Kabelac
@ 2010-07-07 12:34 ` Zdenek Kabelac
  2010-07-07 12:34 ` [PATCH 05/22] Replicator: add reserved names Zdenek Kabelac
                   ` (17 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2010-07-07 12:34 UTC (permalink / raw)
  To: lvm-devel

Skip activation of other heads only for a active replicator.
For inactive active all heads with linear overlay mapping

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

diff --git a/tools/vgchange.c b/tools/vgchange.c
index ed5a7ef..840552a 100644
--- a/tools/vgchange.c
+++ b/tools/vgchange.c
@@ -106,7 +106,7 @@ static int _activate_lvs_in_vg(struct cmd_context *cmd,
 
 		/* Only request activation of the first replicator-dev LV */
 		/* Avoids retry with all heads in case of failure */
-		if (lv_is_replicator_dev(lv) && (lv != first_replicator_dev(lv)))
+		if (lv_is_active_replicator_dev(lv) && (lv != first_replicator_dev(lv)))
 			continue;
 
 		/* Can't deactivate a pvmove LV */
-- 
1.7.1.1



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

* [PATCH 05/22] Replicator: add reserved names
  2010-07-07 12:34 [PATCH 00/22] Replicator 100707 Zdenek Kabelac
                   ` (3 preceding siblings ...)
  2010-07-07 12:34 ` [PATCH 04/22] Replicator: check for active replicator Zdenek Kabelac
@ 2010-07-07 12:34 ` Zdenek Kabelac
  2010-07-07 12:34 ` [PATCH 06/22] Replicator: man page update for lvm Zdenek Kabelac
                   ` (16 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2010-07-07 12:34 UTC (permalink / raw)
  To: lvm-devel

Add new reserved names for replicator related devices.

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

diff --git a/lib/misc/lvm-string.c b/lib/misc/lvm-string.c
index 7eed799..fb73674 100644
--- a/lib/misc/lvm-string.c
+++ b/lib/misc/lvm-string.c
@@ -275,6 +275,24 @@ int apply_lvname_restrictions(const char *name)
 		return 0;
 	}
 
+	if (strstr(name, "_slog")) {
+		log_error("Names including \"_slog\" are reserved. "
+			  "Please choose a different LV name.");
+		return 0;
+	}
+
+	if (strstr(name, "_rlog")) {
+		log_error("Names including \"_rlog\" are reserved. "
+			  "Please choose a different LV name.");
+		return 0;
+	}
+
+	if (strstr(name, "_rimage")) {
+		log_error("Names including \"_rimage\" are reserved. "
+			  "Please choose a different LV name.");
+		return 0;
+	}
+
 	return 1;
 }
 
-- 
1.7.1.1



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

* [PATCH 06/22] Replicator: man page update for lvm
  2010-07-07 12:34 [PATCH 00/22] Replicator 100707 Zdenek Kabelac
                   ` (4 preceding siblings ...)
  2010-07-07 12:34 ` [PATCH 05/22] Replicator: add reserved names Zdenek Kabelac
@ 2010-07-07 12:34 ` Zdenek Kabelac
  2010-07-07 12:34 ` [PATCH 07/22] Replicator: add _replicator_in_sync Zdenek Kabelac
                   ` (15 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2010-07-07 12:34 UTC (permalink / raw)
  To: lvm-devel

Add new reserved names to lvm man page.

Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
 man/lvm.8.in |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/man/lvm.8.in b/man/lvm.8.in
index e38ce4f..7d070f7 100644
--- a/man/lvm.8.in
+++ b/man/lvm.8.in
@@ -271,7 +271,8 @@ The following characters are valid for VG and LV names:
 VG and LV names cannot begin with a hyphen.
 There are also various reserved names that are used internally by lvm that can not be used as LV or VG names.
 A VG cannot be called anything that exists in /dev/ at the time of creation, nor can it be called '.' or '..'.
-A LV cannot be called '.' '..' 'snapshot' or 'pvmove'. The LV name may also not contain the strings '_mlog' or '_mimage'
+A LV cannot be called '.' '..' 'snapshot' or 'pvmove'. The LV name may also not contain the strings 
+'_mlog', '_mimage', '_rlog', '_slog', '_rimage'.
 
 
 .SH DIAGNOSTICS
-- 
1.7.1.1



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

* [PATCH 07/22] Replicator: add _replicator_in_sync
  2010-07-07 12:34 [PATCH 00/22] Replicator 100707 Zdenek Kabelac
                   ` (5 preceding siblings ...)
  2010-07-07 12:34 ` [PATCH 06/22] Replicator: man page update for lvm Zdenek Kabelac
@ 2010-07-07 12:34 ` Zdenek Kabelac
  2010-07-07 12:34 ` [PATCH 08/22] Replicator: add report for replicator targets Zdenek Kabelac
                   ` (14 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2010-07-07 12:34 UTC (permalink / raw)
  To: lvm-devel

Add function init_replicator_in_sync() to be similar as mirror.
For now this function is not functional.

Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
 lib/misc/lvm-globals.c |   11 +++++++++++
 lib/misc/lvm-globals.h |    2 ++
 2 files changed, 13 insertions(+), 0 deletions(-)

diff --git a/lib/misc/lvm-globals.c b/lib/misc/lvm-globals.c
index 8dc2b02..5334691 100644
--- a/lib/misc/lvm-globals.c
+++ b/lib/misc/lvm-globals.c
@@ -34,6 +34,7 @@ static int _ignorelockingfailure = 0;
 static int _security_level = SECURITY_LEVEL;
 static char _cmd_name[30] = "";
 static int _mirror_in_sync = 0;
+static int _replicator_in_sync = 0;
 static int _dmeventd_monitor = DEFAULT_DMEVENTD_MONITOR;
 static int _background_polling = DEFAULT_BACKGROUND_POLLING;
 static int _ignore_suspended_devices = 0;
@@ -88,6 +89,11 @@ void init_mirror_in_sync(int in_sync)
 	_mirror_in_sync = in_sync;
 }
 
+void init_replicator_in_sync(int in_sync)
+{
+	_replicator_in_sync = in_sync;
+}
+
 void init_dmeventd_monitor(int reg)
 {
 	_dmeventd_monitor = reg;
@@ -190,6 +196,11 @@ int mirror_in_sync(void)
 	return _mirror_in_sync;
 }
 
+int replicator_in_sync(void)
+{
+	return _replicator_in_sync;
+}
+
 int dmeventd_monitor_mode(void)
 {
 	return _dmeventd_monitor;
diff --git a/lib/misc/lvm-globals.h b/lib/misc/lvm-globals.h
index 0134c32..c08aa2e 100644
--- a/lib/misc/lvm-globals.h
+++ b/lib/misc/lvm-globals.h
@@ -31,6 +31,7 @@ void init_ignorelockingfailure(int level);
 void init_lockingfailed(int level);
 void init_security_level(int level);
 void init_mirror_in_sync(int in_sync);
+void init_replicator_in_sync(int in_sync);
 void init_dmeventd_monitor(int reg);
 void init_background_polling(int polling);
 void init_ignore_suspended_devices(int ignore);
@@ -51,6 +52,7 @@ int ignorelockingfailure(void);
 int lockingfailed(void);
 int security_level(void);
 int mirror_in_sync(void);
+int replicator_in_sync(void);
 int background_polling(void);
 int ignore_suspended_devices(void);
 const char *log_command_name(void);
-- 
1.7.1.1



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

* [PATCH 08/22] Replicator: add report for replicator targets
  2010-07-07 12:34 [PATCH 00/22] Replicator 100707 Zdenek Kabelac
                   ` (6 preceding siblings ...)
  2010-07-07 12:34 ` [PATCH 07/22] Replicator: add _replicator_in_sync Zdenek Kabelac
@ 2010-07-07 12:34 ` Zdenek Kabelac
  2010-07-07 12:34 ` [PATCH 09/22] Replicator: improve detection of replicator-dev Zdenek Kabelac
                   ` (13 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2010-07-07 12:34 UTC (permalink / raw)
  To: lvm-devel

Elementary reporting tool for replicator and replicato-dev LVs.
Replicator uses free flag 'q'.
Replicator-dev  'r' for normal, 'R' for unsynchronized replicator.
Note: unsychronized status not yet written.

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

diff --git a/lib/report/columns.h b/lib/report/columns.h
index 823ce2c..b6e00ef 100644
--- a/lib/report/columns.h
+++ b/lib/report/columns.h
@@ -76,6 +76,8 @@ FIELD(LVS, lv, STR, "Convert", lvid, 7, convertlv, "convert_lv", "For lvconvert,
 FIELD(LVS, lv, STR, "LV Tags", tags, 7, tags, "lv_tags", "Tags, if any.")
 FIELD(LVS, lv, STR, "Log", lvid, 3, loglv, "mirror_log", "For mirrors, the LV holding the synchronisation log.")
 FIELD(LVS, lv, STR, "Modules", lvid, 7, modules, "modules", "Kernel device-mapper modules required for this LV.")
+FIELD(LVS, lv, STR, "RImage", lvid, 7, rimage, "rimage", "For replicators, the replicated image of this LV.")
+FIELD(LVS, lv, STR, "Replicator", lvid, 7, replicator, "replicator", "For replicators, the replicator control LV.")
 
 FIELD(LABEL, pv, STR, "Fmt", id, 3, pvfmt, "pv_fmt", "Type of metadata.")
 FIELD(LABEL, pv, STR, "PV UUID", id, 38, uuid, "pv_uuid", "Unique identifier.")
diff --git a/lib/report/report.c b/lib/report/report.c
index 9a76334..b7fb15b 100644
--- a/lib/report/report.c
+++ b/lib/report/report.c
@@ -303,6 +303,10 @@ static int _lvstatus_disp(struct dm_report *rh __attribute((unused)), struct dm_
 		repstr[0] = 'p';
 	else if (lv->status & CONVERTING)
 		repstr[0] = 'c';
+	else if (lv_is_replicator(lv))
+		repstr[0] = 'q';
+	else if (lv_is_replicator_dev(lv))
+		repstr[0] = (lv->status & REPLICATOR_NOTSYNCED) ? 'R' : 'r';
 	else if (lv->status & VIRTUAL)
 		repstr[0] = 'v';
 	/* Origin takes precedence over Mirror */
@@ -605,6 +609,34 @@ static int _convertlv_disp(struct dm_report *rh, struct dm_pool *mem __attribute
 	return 1;
 }
 
+static int _rimage_disp(struct dm_report *rh, struct dm_pool *mem,
+			struct dm_report_field *field,
+			const void *data, void *private)
+{
+	const struct logical_volume *lv = (const struct logical_volume *) data;
+
+	if (lv_is_replicator_dev(lv))
+		return _lvname_disp(rh, mem, field, lv->rdevice->lv, private);
+
+	dm_report_field_set_value(field, "", NULL);
+
+	return 1;
+}
+
+static int _replicator_disp(struct dm_report *rh, struct dm_pool *mem,
+			struct dm_report_field *field,
+			const void *data, void *private)
+{
+	const struct logical_volume *lv = (const struct logical_volume *) data;
+
+	if (lv_is_replicator_dev(lv))
+		return _lvname_disp(rh, mem, field, lv->rdevice->rsite->replicator, private);
+
+	dm_report_field_set_value(field, "", NULL);
+
+	return 1;
+}
+
 static int _size32_disp(struct dm_report *rh __attribute((unused)), struct dm_pool *mem,
 			struct dm_report_field *field,
 			const void *data, void *private)
-- 
1.7.1.1



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

* [PATCH 09/22] Replicator: improve detection of replicator-dev
  2010-07-07 12:34 [PATCH 00/22] Replicator 100707 Zdenek Kabelac
                   ` (7 preceding siblings ...)
  2010-07-07 12:34 ` [PATCH 08/22] Replicator: add report for replicator targets Zdenek Kabelac
@ 2010-07-07 12:34 ` Zdenek Kabelac
  2010-07-07 12:34 ` [PATCH 10/22] Replicator: new defaults Zdenek Kabelac
                   ` (12 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2010-07-07 12:34 UTC (permalink / raw)
  To: lvm-devel

Check for NULL replicator pointer in replicator-dev segment.

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

diff --git a/lib/metadata/merge.c b/lib/metadata/merge.c
index 3b8895c..11c58f9 100644
--- a/lib/metadata/merge.c
+++ b/lib/metadata/merge.c
@@ -219,14 +219,20 @@ int check_lv_segments(struct logical_volume *lv, int complete_vg)
 				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 (!seg->replicator) {
+				log_error("LV %s has replicator-dev segment "
+					  "without replicator", lv->name);
+				inc_error_count;
+			} else {
+				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 (lv == seg->replicator)
-				seg_found++;
 		}
 		if (seg_is_replicator(seg) && lv == seg->rlog_lv)
 				seg_found++;
-- 
1.7.1.1



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

* [PATCH 10/22] Replicator: new defaults
  2010-07-07 12:34 [PATCH 00/22] Replicator 100707 Zdenek Kabelac
                   ` (8 preceding siblings ...)
  2010-07-07 12:34 ` [PATCH 09/22] Replicator: improve detection of replicator-dev Zdenek Kabelac
@ 2010-07-07 12:34 ` Zdenek Kabelac
  2010-07-07 12:34 ` [PATCH 11/22] Replicator: metadata update Zdenek Kabelac
                   ` (11 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2010-07-07 12:34 UTC (permalink / raw)
  To: lvm-devel


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

diff --git a/lib/config/defaults.h b/lib/config/defaults.h
index 3d8881c..fc5649e 100644
--- a/lib/config/defaults.h
+++ b/lib/config/defaults.h
@@ -48,6 +48,14 @@
 #define DEFAULT_DMEVENTD_MONITOR 1
 #define DEFAULT_BACKGROUND_POLLING 1
 
+#define DEFAULT_REPLICATOR_SYNCLOG "disk"
+#define DEFAULT_REPLICATOR_LOG_TYPE "ringbuffer"
+#define DEFAULT_REPLICATOR_LOCAL_SITE_NAME "local"
+#define DEFAULT_REPLICATOR_FALL_BEHIND_DATA 0
+#define DEFAULT_REPLICATOR_FALL_BEHIND_IOS 0
+#define DEFAULT_REPLICATOR_FALL_BEHIND_TIMEOUT 0
+#define DEFAULT_REPLICATOR_ASYNC_MODE (DM_REPLICATOR_ASYNC_WARN)
+
 #define DEFAULT_UMASK 0077
 
 #ifdef LVM1_FALLBACK
@@ -106,6 +114,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
-- 
1.7.1.1



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

* [PATCH 11/22] Replicator: metadata update
  2010-07-07 12:34 [PATCH 00/22] Replicator 100707 Zdenek Kabelac
                   ` (9 preceding siblings ...)
  2010-07-07 12:34 ` [PATCH 10/22] Replicator: new defaults Zdenek Kabelac
@ 2010-07-07 12:34 ` Zdenek Kabelac
  2010-07-07 12:34 ` [PATCH 12/22] Replicator: replicator_manip changes Zdenek Kabelac
                   ` (10 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2010-07-07 12:34 UTC (permalink / raw)
  To: lvm-devel


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

diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index 7824005..cb7fd3d 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -74,6 +74,7 @@
 
 #define REPLICATOR		0x20000000U	/* LV -internal use only for replicator */
 #define REPLICATOR_LOG		0x40000000U	/* LV -internal use only for replicator-dev */
+#define REPLICATOR_NOTSYNCED   	0x80000000U	/* LV -internal use only for replicator */
 
 #define LVM_READ              	0x00000100U	/* LV VG */
 #define LVM_WRITE             	0x00000200U	/* LV VG */
@@ -352,7 +353,7 @@ struct replicator_device {
 	const char *name;		/* Device LV name */
 	struct logical_volume *lv;	/* LV from replicator site's VG */
 	struct logical_volume *slog;	/* Synclog lv from VG  */
-	const char *slog_name;		/* Debug - specify size of core synclog */
+	uint32_t slog_core;		/* Corelog size */
 };
 /* -- Replicator datatypes */
 
@@ -622,6 +623,8 @@ uint64_t extents_from_size(struct cmd_context *cmd, uint64_t size,
 struct lvcreate_params {
 	/* flags */
 	int snapshot; /* snap */
+	const char *replicator; /* replicator */
+	int replicator_dev; /* replicator-dev */
 	int zero; /* all */
 	int major; /* all */
 	int minor; /* all */
@@ -640,6 +643,9 @@ struct lvcreate_params {
 
 	uint32_t mirrors; /* mirror */
 
+	const char *rlog_type; /* replicator */
+	struct replicator_site rsite; /* replicator, use only parameters */
+
 	const struct segment_type *segtype; /* all */
 
 	/* size */
@@ -803,24 +809,53 @@ int collapse_mirrored_lv(struct logical_volume *lv);
 int shift_mirror_images(struct lv_segment *mirrored_seg, unsigned mimage);
 
 /* ++  metadata/replicator_manip.c */
-int replicator_add_replicator_dev(struct logical_volume *replicator_lv,
-				  struct lv_segment *rdev_seg);
-struct logical_volume *replicator_remove_replicator_dev(struct lv_segment *rdev_seg);
-int replicator_add_rlog(struct lv_segment *replicator_seg, struct logical_volume *rlog_lv);
-struct logical_volume *replicator_remove_rlog(struct lv_segment *replicator_seg);
-
-int replicator_dev_add_slog(struct replicator_device *rdev, struct logical_volume *slog_lv);
-struct logical_volume *replicator_dev_remove_slog(struct replicator_device *rdev);
-int replicator_dev_add_rimage(struct replicator_device *rdev, struct logical_volume *lv);
-struct logical_volume *replicator_dev_remove_rimage(struct replicator_device *rdev);
-
 int lv_is_active_replicator_dev(const struct logical_volume *lv);
 int lv_is_replicator(const struct logical_volume *lv);
 int lv_is_replicator_dev(const struct logical_volume *lv);
 int lv_is_rimage(const struct logical_volume *lv);
 int lv_is_rlog(const struct logical_volume *lv);
 int lv_is_slog(const struct logical_volume *lv);
+struct replicator_site *find_site_in_replicator(const struct logical_volume *replicator,
+						const char *site_name);
+struct replicator_site *find_local_site_in_replicator(const struct logical_volume *replicator);
 struct logical_volume *first_replicator_dev(const struct logical_volume *lv);
+int replicator_add_rlog(struct lv_segment *replicator_seg, struct logical_volume *rlog_lv);
+struct logical_volume *replicator_remove_rlog(struct lv_segment *replicator_seg);
+int replicator_site_add_device(struct replicator_site *rsite,
+			       struct lv_segment *replicator_dev_seg,
+			       const char *name,
+			       struct logical_volume *rimage,
+			       uint32_t slog_core,
+			       struct logical_volume *slog_lv,
+			       uint64_t device_index);
+int replicator_site_set_op_mode(struct replicator_site *rsite, const char *sitemode);
+const char *replicator_site_get_op_mode(const struct replicator_site *rsite);
+struct replicator_site *replicator_add_site(struct logical_volume *replicator,
+					    const char *site_name);
+void replicator_init(struct logical_volume *replicator);
+int replicator_add_replicator_dev(struct logical_volume *replicator,
+				  struct lv_segment *rdev_seg);
+
+int lv_add_replicator_dev(struct logical_volume *replicator,
+			  struct logical_volume *lv);
+int lv_remove_replicator_dev(struct logical_volume *replicator_dev);
+
+int lv_add_replicator_site(struct logical_volume *replicator,
+			   const struct replicator_site *rsite);
+int lv_remove_replicator_site(struct logical_volume *replicator, const char *site_name);
+
+int lv_add_sync_log(struct logical_volume *replicator,
+		    unsigned site_index,
+		    uint64_t device_index,
+		    struct dm_list *allocatable_pvs,
+		    alloc_policy_t alloc);
+
+int vg_prearrange_replicator(struct volume_group *vg,
+			     const struct lvcreate_params *lp);
+int vg_add_replicator(struct logical_volume *replicator,
+		      const char *rlog_type,
+		      uint32_t region_size);
+int vg_remove_replicator(struct logical_volume *replicator);
 /* --  metadata/replicator_manip.c */
 struct cmd_vg *cmd_vg_add(struct dm_pool *mem, struct dm_list *cmd_vgs,
 			  const char *vg_name, const char *vgid,
-- 
1.7.1.1



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

* [PATCH 12/22] Replicator: replicator_manip changes
  2010-07-07 12:34 [PATCH 00/22] Replicator 100707 Zdenek Kabelac
                   ` (10 preceding siblings ...)
  2010-07-07 12:34 ` [PATCH 11/22] Replicator: metadata update Zdenek Kabelac
@ 2010-07-07 12:34 ` Zdenek Kabelac
  2010-07-07 12:34 ` [PATCH 13/22] Replicator: replicator.c changes Zdenek Kabelac
                   ` (9 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2010-07-07 12:34 UTC (permalink / raw)
  To: lvm-devel

Changes for replicator_manip.c source file.

Adding new API functions.

Lots of lines for log creation are copied from mirror code and then
are adapted for _slog. Code is done with hope we could share same
parametrized code later for both targets - mirror and replicator.
But with recent changes to mirrored logs it is a harder task.

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

diff --git a/lib/metadata/replicator_manip.c b/lib/metadata/replicator_manip.c
index b3a2fff..b2c4eda 100644
--- a/lib/metadata/replicator_manip.c
+++ b/lib/metadata/replicator_manip.c
@@ -15,244 +15,741 @@
 #include "lib.h"
 #include "locking.h"
 #include "metadata.h"
+#include "defaults.h"
 #include "segtype.h"
 #include "toolcontext.h"
+#include "activate.h"
+#include "archiver.h"
+#include "lv_alloc.h"
+#include "str_list.h"
+
+static const struct {
+	const char name[8];
+	int value;
+} dm_op_mode_table[] = {
+	{ "sync", DM_REPLICATOR_SYNC },
+	{ "warn", DM_REPLICATOR_ASYNC_WARN },
+	{ "stall", DM_REPLICATOR_ASYNC_STALL },
+	{ "drop", DM_REPLICATOR_ASYNC_DROP },
+	{ "fail", DM_REPLICATOR_ASYNC_FAIL }
+};
 
-/* Add lv as replicator_dev device */
-int replicator_dev_add_rimage(struct replicator_device *rdev,
-			      struct logical_volume *lv)
+/**
+ * Tests whether LV is member of an active replicator.
+ *
+ * \param lv    Logical volume for testing
+ *
+ * \return	Returns 1 if the lv is member of an active replicator,
+ *		0 otherwise.
+ */
+int lv_is_active_replicator_dev(const struct logical_volume *lv)
 {
-	if (!lv || !rdev)
-		return_0;
+	return (lv_is_replicator_dev(lv) &&
+		lv->rdevice &&
+		lv->rdevice->rsite &&
+		lv->rdevice->rsite->state == REPLICATOR_STATE_ACTIVE);
+}
+
+/**
+ * Tests whether LV is replicator control device.
+ * (Segment-less LV could be also replicator.)
+ *
+ * \param lv    Logical volume for testing
+ *
+ * \return	Returns 1 if the lv is replicator control device,
+ *		0 otherwise.
+ */
+int lv_is_replicator(const struct logical_volume *lv)
+{
+	return ((lv->status & REPLICATOR) &&
+		(dm_list_empty(&lv->segments) ||
+		 seg_is_replicator(first_seg(lv))));
+}
+
+/**
+ * Tests whether LV is replicator device.
+ *
+ * \param lv    Logical volume for testing
+ *
+ * \return	Returns 1 if the lv is replicator device,
+ *		0 otherwise.
+ */
+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)));
+}
+
+/**
+ * Tests whether LV is replicated rimage device.
+ *
+ * \param lv    Logical volume for testing
+ *
+ * \return	Returns 1 if the lv is replicated rimage device,
+ *		0 otherwise.
+ */
+int lv_is_rimage(const struct logical_volume *lv)
+{
+	return (!lv_is_replicator_dev(lv) &&
+		(lv->rdevice && lv->rdevice->lv == lv));
+}
+
+/**
+ * Tests whether LV is replicator log device.
+ *
+ * \param lv    Logical volume for testing
+ *
+ * \return	Returns 1 if the lv is replicator log device,
+ *		0 otherwise.
+ */
+int lv_is_rlog(const struct logical_volume *lv)
+{
+	return (lv->status & REPLICATOR_LOG);
+}
+
+/**
+ * Tests whether LV is replicator sync log device.
+ *
+ * \param lv    Logical volume for testing
+ *
+ * \return	Returns 1 if the lv is replicator sync log device,
+ *		0 otherwise.
+ */
+int lv_is_slog(const struct logical_volume *lv)
+{
+	return (lv->rdevice && lv->rdevice->slog == lv);
+}
+
+/**
+ * Returns local site from replicator.
+ */
+struct replicator_site *find_local_site_in_replicator(const struct logical_volume *replicator)
+{
+	struct replicator_site *rsite;
 
+	dm_list_iterate_items(rsite, &replicator->rsites)
+		if (rsite->site_index == 0)
+			return rsite;
+
+	return NULL;
+}
+
+/**
+ * Returns site with name site_name from replicator.
+ */
+struct replicator_site *find_site_in_replicator(const struct logical_volume *replicator,
+						const char *site_name)
+{
+	struct replicator_site *rsite;
+
+	dm_list_iterate_items(rsite, &replicator->rsites)
+		if (strcmp(rsite->name, site_name) == 0)
+			return rsite;
+
+	return NULL;
+}
+
+/**
+ * Returns first replicator-dev in site in case the LV is replicator-dev
+ * or replicator, NULL otherwise
+ */
+struct logical_volume *first_replicator_dev(const struct logical_volume *lv)
+{
+	struct replicator_device *rdev;
+	struct replicator_site *rsite;
+	const struct logical_volume *replicator;
+
+	if (lv_is_replicator_dev(lv))
+		replicator = first_seg(lv)->replicator;
+	else if (lv_is_replicator(lv))
+		replicator = lv;
+	else {
+		log_error(INTERNAL_ERROR "Logical volume %s is not "
+			  "replicator", lv->name);
+		return NULL;
+	}
+
+	if ((rsite = find_local_site_in_replicator(replicator)))
+		dm_list_iterate_items(rdev, &rsite->rdevices)
+			return rdev->replicator_dev->lv;
+
+	return NULL;
+}
+
+/* Add lv as replicator_dev device */
+static int _replicator_device_add_rimage(struct replicator_device *rdev,
+					 struct logical_volume *lv)
+{
 	if (lv_is_rimage(lv)) {
-		log_error("Logical volume %s is already part of other "
-			  "replicator.", lv->name);
+		log_error(INTERNAL_ERROR "Logical volume %s is used by replicator %s.",
+			  lv->name, lv->rdevice->rsite->replicator->name);
 		return 0;
 	}
 
 	if (rdev->lv) {
-		log_error("Logical volume %s can not be attached to an "
+		log_error(INTERNAL_ERROR "Logical volume %s cannot be attached to an "
 			  "already defined replicator device", lv->name);
 		return 0;
 	}
 
 	lv_set_hidden(lv);
 	lv->rdevice = rdev;
+	rdev->replicator_dev->lv->rdevice = rdev;
 	rdev->lv = lv;
 
 	return add_seg_to_segs_using_this_lv(lv, rdev->replicator_dev);
 }
 
 /* Remove lv from replicator_dev device */
-struct logical_volume *replicator_dev_remove_rimage(struct replicator_device *rdev)
+static struct logical_volume *_replicator_device_remove_rimage(struct replicator_device *rdev)
 {
-	struct logical_volume *lv;
+	struct logical_volume *rimage = rdev->lv;
 
-	if (!rdev || !rdev->lv)
-		return_NULL;
+	if (!rimage || !lv_is_rimage(rimage)) {
+		log_error(INTERNAL_ERROR "Replicator device in site %s "
+			  "does not have rimage.", rdev->rsite->name);
+		return NULL;
+	}
 
-	lv = rdev->lv;
-	if (!remove_seg_from_segs_using_this_lv(lv, rdev->replicator_dev))
+	if (!remove_seg_from_segs_using_this_lv(rimage, rdev->replicator_dev))
 		return_NULL;
 
-	/* FIXME: - check for site references */
 	rdev->lv = NULL;
-	lv->rdevice = NULL;
-	lv_set_visible(lv);
+	rimage->rdevice = NULL;
+	lv_set_visible(rimage);
 
-	return lv;
+	return rimage;
 }
 
-int replicator_dev_add_slog(struct replicator_device *rdev,
-			    struct logical_volume *slog)
+static int _replicator_device_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);
+	if (lv_is_slog(slog)) {
+		log_error(INTERNAL_ERROR "Logical volume %s cannot be used.",
+			  slog->name);
 		return 0;
 	}
 
-	if (slog->rdevice) {
-		log_error("Sync log %s is already used by replicator %s.",
-			  slog->name, slog->rdevice->rsite->replicator->name);
+	if (rdev->slog) {
+		log_error(INTERNAL_ERROR "Replicator device in site %s has "
+			  "sync log %s.", rdev->rsite->name, rdev->slog->name);
 		return 0;
 	}
 
+	if (!add_seg_to_segs_using_this_lv(slog, rdev->replicator_dev))
+		return_0;
+
 	lv_set_hidden(slog);
-	slog->rdevice = rdev;
 	rdev->slog = slog;
+	slog->rdevice = rdev;
 
-	return add_seg_to_segs_using_this_lv(slog, rdev->replicator_dev);
+	return 1;
 }
 
-struct logical_volume *replicator_dev_remove_slog(struct replicator_device *rdev)
+static struct logical_volume *_replicator_device_remove_slog(struct replicator_device *rdev)
 {
-	struct logical_volume *lv;
+	struct logical_volume *slog = rdev->slog;
+
+	if (!slog || !lv_is_slog(slog)) {
+		log_error(INTERNAL_ERROR "Replicator device in site %s "
+			  "does not have sync log.", rdev->rsite->name);
+		return NULL;
+	}
 
-	if (!rdev)
+	slog->rdevice = NULL;
+	rdev->slog = NULL;
+	lv_set_visible(slog);
+
+	if (!remove_seg_from_segs_using_this_lv(slog, rdev->replicator_dev))
 		return_NULL;
 
-	lv = rdev->slog;
-	if (!lv) {
-		log_error("Replicator device in site %s does not have sync log.",
-			  rdev->rsite->name);
+	return slog;
+}
+
+static char *_replicator_device_slog_name(struct logical_volume *replicator,
+					  unsigned site_index,
+					  uint64_t device_index)
+{
+	char *name;
+	size_t len = strlen(replicator->name) + 12 + 22 + 10;
+
+	if (!(name = dm_pool_zalloc(replicator->vg->vgmem, len))) {
+		log_error("Allocation of slog name failed.");
+		return NULL;
+	}
+
+	if (!dm_snprintf(name, len, "%s_%u_%" PRIu64 "_slog", replicator->name,
+			 site_index, device_index) < 0) {
+		log_error("Error in name creation");
+		return NULL;
+	}
+
+	return name;
+}
+
+int replicator_add_rlog(struct lv_segment *replicator_seg,
+			struct logical_volume *rlog_lv)
+{
+	if (lv_is_rlog(rlog_lv)) {
+		log_error(INTERNAL_ERROR "Logical volume %s cannot be used.",
+			  rlog_lv->name);
+		return 0;
+	}
+
+	if (!add_seg_to_segs_using_this_lv(rlog_lv, replicator_seg))
+		return_0;
+
+	lv_set_hidden(rlog_lv);
+	rlog_lv->status |= REPLICATOR_LOG;
+	replicator_seg->rlog_lv = rlog_lv;
+
+	return 1;
+}
+
+struct logical_volume *replicator_remove_rlog(struct lv_segment *replicator_seg)
+{
+	struct logical_volume *rlog_lv = replicator_seg->rlog_lv;
+
+	if (!rlog_lv || !lv_is_rlog(rlog_lv)) {
+		log_error(INTERNAL_ERROR "Replicator %s does not have rlog.",
+			  replicator_seg->lv->name);
 		return NULL;
 	}
 
-	if (!remove_seg_from_segs_using_this_lv(lv, rdev->replicator_dev))
+	replicator_seg->rlog_lv = NULL;
+	rlog_lv->status &= ~REPLICATOR_LOG;
+	lv_set_visible(rlog_lv);
+
+	if (!remove_seg_from_segs_using_this_lv(rlog_lv, replicator_seg))
 		return_NULL;
 
-	rdev->slog = NULL;
-	lv->rdevice = NULL;
-	lv_set_visible(lv);
+	return rlog_lv;
+}
+
+/**
+ *
+ */
+int replicator_site_add_device(struct replicator_site *rsite,
+			       struct lv_segment *replicator_dev_seg,
+			       const char *name,
+			       struct logical_volume *rimage,
+			       uint32_t slog_core,
+			       struct logical_volume *slog,
+			       uint64_t device_index)
+{
+	struct dm_pool *mem = replicator_dev_seg->lv->vg->vgmem;
+	struct replicator_device *rdev;
+
+	if (!(rdev = dm_pool_zalloc(mem, sizeof(*rdev)))) {
+		log_error("Allocation of replicator device failed.");
+		return 0;
+	}
+
+	if (!(rdev->name = dm_pool_strdup(mem, name))) {
+		log_error("Allocation of replicator device name failed.");
+		return 0;
+	}
+
+	log_very_verbose("Created %s/%s", rsite->name, rdev->name);
+
+	rdev->rsite = rsite;
+	rdev->replicator_dev = replicator_dev_seg;
+	rdev->device_index = device_index;
+	rdev->slog_core = slog_core;
+
+	dm_list_add(&rsite->rdevices, &rdev->list);// linked site list
+
+	if (rimage && !_replicator_device_add_rimage(rdev, rimage))
+		return_0;
+
+	if (slog_core && slog) {
+		log_error("Either slog or corelog must be used.");
+		return 0;
+	}
 
-	return lv;
+	if (slog && !_replicator_device_add_slog(rdev, slog))
+		return_0;
+
+	return 1;
 }
 
-int replicator_add_replicator_dev(struct logical_volume *replicator_lv,
-				  struct lv_segment *replicator_dev_seg)
+static int _replicator_site_remove_device(struct replicator_device *rdev)
 {
-	if (!replicator_lv)
+	if (rdev->lv && !_replicator_device_remove_rimage(rdev))
 		return_0;
 
-	if (!(replicator_lv->status & REPLICATOR)) {
-		dm_list_init(&replicator_lv->rsites);
-		lv_set_hidden(replicator_lv);
-		replicator_lv->status |= REPLICATOR;
+	if (rdev->slog && !_replicator_device_remove_slog(rdev))
+		return_0;
+
+	dm_list_del(&rdev->list);
+
+	return 1;
+}
+
+struct replicator_site *replicator_add_site(struct logical_volume *replicator,
+					    const char *site_name)
+{
+	struct replicator_site *rsite;
+
+	if (find_site_in_replicator(replicator, site_name)) {
+		log_error("Site name %s already exists.", site_name);
+		return NULL;
 	}
 
-	if (!replicator_dev_seg)
-		return 1;
+	if (!(rsite = dm_pool_zalloc(replicator->vg->vgmem,
+				     sizeof(*rsite)))) {
+		log_error("Allocation of replicator site failed.");
+		return NULL;
+	}
+
+	if (!(rsite->name = dm_pool_strdup(replicator->vg->vgmem,
+					   site_name))) {
+		log_error("Allocation of replicator site name failed.");
+		return NULL;
+	}
+
+	rsite->replicator = replicator;
+	dm_list_init(&rsite->rdevices);
+	dm_list_add(&replicator->rsites, &rsite->list);
+
+	return rsite;
+}
+
+static int _replicator_remove_site(struct replicator_site *rsite)
+{
+	struct replicator_device *rdev, *trdev;
+
+	dm_list_iterate_items_safe(rdev, trdev, &rsite->rdevices)
+		if (!_replicator_site_remove_device(rdev))
+			return_0;
+
+	dm_list_del(&rsite->list);
+
+	return 1;
+}
+
+
+void replicator_init(struct logical_volume *replicator)
+{
+	if (!lv_is_replicator(replicator)) {
+		dm_list_init(&replicator->rsites);
+		lv_set_hidden(replicator);
+		replicator->status |= REPLICATOR;
+	}
+}
+
+/**
+ * Connects replicator_dev segment to replicator.
+ *
+ * \param replicator
+ * \param replicator_dev_seg
+ */
+int replicator_add_replicator_dev(struct logical_volume *replicator,
+				  struct lv_segment *replicator_dev_seg)
+{
+	replicator_init(replicator);
 
 	if (replicator_dev_seg->replicator) {
-		log_error("Replicator device %s is already part of replicator.",
-			  replicator_dev_seg->lv->name);
+		log_error(INTERNAL_ERROR "Replicator device %s is already "
+			  "part of replicator.", replicator_dev_seg->lv->name);
 		return 0;
 	}
 
-	replicator_dev_seg->replicator = replicator_lv;
+	replicator_dev_seg->replicator = replicator;
+	replicator_dev_seg->rlog_lv = NULL;
+	replicator_dev_seg->lv->status |= REPLICATOR;
+
+	if (!add_seg_to_segs_using_this_lv(replicator, replicator_dev_seg))
+		return_0;
 
-	return add_seg_to_segs_using_this_lv(replicator_lv, replicator_dev_seg);
+	return 1;
 }
 
 /**
- * Returns rimage ?? lv upon succeful detach of device
- * entire LV entry should be removed by this crootall ??
+ * Returns rimage LV upon succeful detach of device
+ * entire LV entry should be removed by this call ??
  */
-struct logical_volume *replicator_remove_replicator_dev(struct lv_segment *replicator_dev_seg)
+static int _replicator_remove_replicator_dev(struct lv_segment *replicator_dev_seg)
 {
-	struct logical_volume *lv = NULL;
-
-	log_error("FIXME: not implemented.");
-#if 0
-	/* FIXME: - this is going to be complex.... */
-	if (!replicator_dev_seg)
-		return_NULL;
+	struct replicator_site *rsite;
+	struct replicator_device *rdev;
+	struct logical_volume *replicator = replicator_dev_seg->replicator;
+	uint64_t device_index = replicator_dev_seg->lv->rdevice->device_index;
 
-	/* if slog or rimage - exit */
+	dm_list_iterate_items(rsite, &replicator->rsites) {
+		dm_list_iterate_items(rdev, &rsite->rdevices) {
+			if (rdev->device_index != device_index)
+				continue;
+			if (!_replicator_site_remove_device(rdev))
+				return_0;
+			/* no need for iterate_items_safe - 1 device per site */
+			break;
+		}
+	}
 
-	if (!remove_seg_from_segs_using_this_lv(lv, replicator_seg))
-		return_NULL;
+	if (!remove_seg_from_segs_using_this_lv(replicator, replicator_dev_seg))
+		return_0;
 
-	replicator_seg->rlog_lv = NULL;
-	lv->status &= ~REPLICATOR_LOG;
-	lv_set_visible(lv);
-#endif
+	replicator_dev_seg->lv->status &= ~REPLICATOR;
+	replicator_dev_seg->rlog_lv = NULL;
+	replicator_dev_seg->replicator = NULL;
 
-	return lv;
+	return 1;
 }
 
-int replicator_add_rlog(struct lv_segment *replicator_seg,
-			struct logical_volume *rlog_lv)
+/*
+ * Create new layered LV over the original LV
+ * this target will have a 'replicator-dev' segment
+ */
+int lv_add_replicator_dev(struct logical_volume *replicator,
+			  struct logical_volume *lv)
 {
-	if (!rlog_lv)
+	const struct segment_type *segtype;
+	struct logical_volume *rimage;
+	struct logical_volume *slog;
+	struct lv_segment *seg;
+	struct replicator_site *rsite;
+	const char *slog_name;
+	uint64_t dev_idx = first_seg(replicator)->rdevice_index_highest;
+
+	if (!(segtype = get_segtype_from_string(lv->vg->cmd, "replicator-dev")))
 		return_0;
 
-	if (rlog_lv->status & REPLICATOR_LOG) {
-		log_error("Rlog device %s is already used.", rlog_lv->name);
+	if (activation() && segtype->ops->target_present &&
+	    !segtype->ops->target_present(lv->vg->cmd, NULL, NULL)) {
+		log_error("%s: Required device-mapper target(s) not "
+			  "detected in your kernel", segtype->name);
 		return 0;
 	}
 
-	lv_set_hidden(rlog_lv);
-	rlog_lv->status |= REPLICATOR_LOG;
-	replicator_seg->rlog_lv = rlog_lv;
+	/* If replicator does not have any site defined, add local default site */
+	if (dm_list_empty(&replicator->rsites)) {
+		if (!replicator_add_site(replicator, DEFAULT_REPLICATOR_LOCAL_SITE_NAME))
+			return_0;
+		first_seg(replicator)->rsite_index_highest++;
+	}
+
+	first_seg(replicator)->rdevice_index_highest++;
+	dm_list_iterate_items(rsite, &replicator->rsites) {
+		if (rsite->site_index == 0) {
+			if (!(rimage = insert_layer_for_lv(lv->vg->cmd, lv, 0, "_rimage")))
+				return_0;
 
-	return add_seg_to_segs_using_this_lv(rlog_lv, replicator_seg);
+			seg = first_seg(lv);
+			seg->segtype = segtype; /* switch to replicator-dev */
+
+			if (!replicator_add_replicator_dev(replicator, seg))
+				return_0;
+
+			if (!replicator_site_add_device(rsite, seg, rimage->name,
+							rimage, 0, NULL, dev_idx))
+				return_0;
+		} else {
+			// FIXME: corelog support missing
+			slog_name = _replicator_device_slog_name(replicator, rsite->site_index,
+								 dev_idx);
+			if (!(slog = find_lv(lv->vg, slog_name))) {
+				log_error("Cannot find slog LV %s for %s/%s",
+					  slog_name, rsite->name, lv->name);
+				return 0;
+			}
+
+			if (!replicator_site_add_device(rsite, seg, lv->name,
+							NULL, 0, slog, dev_idx))
+				return_0;
+		}
+	}
+
+	return 1;
 }
 
-struct logical_volume *replicator_remove_rlog(struct lv_segment *replicator_seg)
+int lv_remove_replicator_dev(struct logical_volume *lv)
+{
+	/* FIXME: collect all removed devices */
+	if (!_replicator_remove_replicator_dev(first_seg(lv)))
+		return_0;
+
+	return 1;
+}
+
+int lv_add_replicator_site(struct logical_volume *replicator,
+			   const struct replicator_site *rsite)
 {
-	struct logical_volume *lv;
+	struct replicator_site *nrsite;
+
+	if (!lv_is_replicator(replicator)) {
+		log_error(INTERNAL_ERROR "Logical volume %s is not a "
+			  "replicator.", replicator->name);
+		return 0;
+	}
 
-	if (!replicator_seg)
+	if (!(nrsite = replicator_add_site(replicator, rsite->name)))
 		return_0;
 
-	if (!(lv = replicator_seg->rlog_lv)) {
-		log_error("Replog segment %s does not have rlog.",
-			  replicator_seg->lv->name);
-		return NULL;
+	if (rsite->vg_name &&
+	    !(nrsite->vg_name = dm_pool_strdup(replicator->vg->vgmem,
+					       rsite->vg_name))) {
+		log_error("Allocation of replicator site vg_name failed.");
+		return 0;
 	}
 
-	if (!remove_seg_from_segs_using_this_lv(lv, replicator_seg))
-		return_NULL;
+	nrsite->site_index = first_seg(replicator)->rsite_index_highest++;
+	nrsite->op_mode = rsite->op_mode;
+	nrsite->fall_behind_data = rsite->fall_behind_data;
+	nrsite->fall_behind_ios = rsite->fall_behind_ios;
+	nrsite->fall_behind_timeout = rsite->fall_behind_timeout;
 
-	replicator_seg->rlog_lv = NULL;
-	lv->status &= ~REPLICATOR_LOG;
-	lv_set_visible(lv);
+	return 1;
+}
 
-	return lv;
+int lv_remove_replicator_site(struct logical_volume *replicator,
+			      const char *site_name)
+{
+	struct replicator_site *rsite, *trsite;
+
+	if (!(rsite = find_site_in_replicator(replicator, site_name))) {
+		log_error(INTERNAL_ERROR "Replicator %s does not contain "
+			  "site %s.", site_name, replicator->name);
+		return 0;
+	}
+
+	if (!_replicator_remove_site(rsite))
+		return_0;
+
+	/* When the local site is removed, all remote sites must be removed */
+	if (rsite->site_index == 0) {
+		dm_list_iterate_items_safe(rsite, trsite, &replicator->rsites)
+			if (!_replicator_remove_site(rsite))
+				return_0;
+	}
+
+	return 1;
 }
 
+int vg_prearrange_replicator(struct volume_group *vg,
+			     const struct lvcreate_params *lp)
+{
+	struct logical_volume *replicator = NULL;
+	struct replicator_device *rdev;
+	struct replicator_site *rsite;
+	unsigned site_index;
+	uint64_t device_index;
 
-#if 0
-/*
- * Create new LV to pretend the original LV
- * this target will have a 'replicator' segment
- */
-int lv_add_replicator(struct logical_volume *origin, const char *rep_suffix)
+	if (lp->replicator_dev || lp->rsite.name)
+		if (!(replicator = find_lv(vg, lp->replicator))) {
+			log_error("Replicator %s not found.", lp->replicator);
+			return 0;
+		}
+
+	if (lp->replicator_dev) {
+		device_index = first_seg(replicator)->rdevice_index_highest;
+		dm_list_iterate_items(rsite, &replicator->rsites) {
+			if (rsite->site_index != 0 &&
+			    !lv_add_sync_log(replicator,
+					     rsite->site_index,
+					     device_index,
+					     lp->pvh, lp->alloc))
+				return_0;
+		}
+	}
+
+	if (lp->rsite.name) {
+		site_index = first_seg(replicator)->rsite_index_highest;
+		dm_list_iterate_items(rsite, &replicator->rsites) {
+			if (rsite->site_index != 0)
+				continue;
+
+			dm_list_iterate_items(rdev, &rsite->rdevices) {
+				if (!lv_add_sync_log(replicator,
+						     site_index,
+						     rdev->device_index,
+						     lp->pvh, lp->alloc))
+					return_0;
+			}
+		}
+
+		if (!lv_add_replicator_site(replicator, &lp->rsite))
+			return_0;
+
+		if (!archive(vg))
+			return_0;
+
+		/* store vg on disk(s) */
+		if (!vg_write(vg) || !vg_commit(vg))
+			return_0;
+
+		backup(vg);
+	}
+
+	return 1;
+}
+
+int vg_add_replicator(struct logical_volume *replicator,
+		      const char *rlog_type,
+		      uint32_t region_size)
 {
-	struct logical_volume *rep_lv;
-	char *name;
-	size_t slen;
+	const struct segment_type *segtype;
+	//float sync_percent;
+	//percent_range_t percent_range;
+	struct logical_volume *rlog_lv;
+	struct lv_segment *repseg;
+	struct lvinfo info;
+
+	/*
+	 * We are unable to convert the log of inactive cluster replictors
+	 */
+	if (vg_is_clustered(replicator->vg)
+	    && !(lv_info(replicator->vg->cmd, replicator, &info, 0, 0) &&
+		 info.exists)) {
+		log_error("Replicator in this VG is not supported.");
+		return 0;
+	}
 
-	if (!(name = strstr(origin->name, rep_suffix))) {
-		log_error("Failed to find replicator suffix %s in LV name %s",
-			  rep_suffix, origin->name);
+	if (!(segtype = get_segtype_from_string(replicator->vg->cmd,
+						"replicator")))
+		return_0;
+
+	if (activation() && segtype->ops->target_present &&
+	    !segtype->ops->target_present(replicator->vg->cmd, NULL, NULL)) {
+		log_error("%s: Required device-mapper target(s) not "
+			  "detected in your kernel", segtype->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 (!(rlog_lv = insert_layer_for_lv(replicator->vg->cmd,
+					    replicator, 0, "_rlog"))) {
+		log_error("Failed to insert replicator _rlog");
+		return 0;
 	}
 
-	if (!(rep_lv = lv_create_empty(name, &origin->lvid,
-				       LVM_READ | LVM_WRITE | VISIBLE_LV,
-				       ALLOC_INHERIT, origin->vg)))
-		return_0;
+	repseg = first_seg(replicator);
+	repseg->segtype = segtype;
+
+	repseg->rlog_type = rlog_type; //"ringbuffer";
+	repseg->rdevice_index_highest = 0;
+	repseg->rsite_index_highest = 0;
+	repseg->region_size = region_size;
 
-	if (!lv_add_virtual_segment(rep_lv, 0, origin->le_count,
-				    get_segtype_from_string(origin->vg->cmd,
-							    "error")))
+	replicator_init(replicator);
+
+	if (!replicator_add_rlog(repseg, rlog_lv))
 		return_0;
 
-	rep_lv->status |= VIRTUAL;
 	return 1;
 }
 
-int lv_remove_replicator(struct logical_volume *lv)
+int vg_remove_replicator(struct logical_volume *replicator)
 {
+	/* FIXME: replace heads with error targets first */
+	if (!suspend_lv(replicator->vg->cmd, replicator)) {
+		log_error("Failed to suspend %s.",
+			  replicator->name);
+		return 0;
+	}
+
 	return 1;
 }
-#endif
 
 /*
  * Check all replicator structures:
@@ -266,7 +763,7 @@ int check_replicator_segment(const struct lv_segment *rseg)
 {
 	struct replicator_site *rsite, *rsiteb;
 	struct replicator_device *rdev, *rdevb;
-        struct logical_volume *lv = rseg->lv;
+	struct logical_volume *lv = rseg->lv;
 	int r = 1;
 
 	if (vg_is_clustered(lv->vg)) {
@@ -304,29 +801,30 @@ int check_replicator_segment(const struct lv_segment *rseg)
 			}
 		} else {
 			if (rsite->fall_behind_timeout && rsite->fall_behind_ios) {
-				log_error("Defined fall_behind_timeout and"
-					  " fall_behind_ios for async replicator %s/%s.",
+				log_error("Defined fall_behind_timeout and "
+					  "fall_behind_ios for async replicator %s/%s.",
 					  lv->name, rsite->name);
 				r = 0;
 			}
 			if (rsite->fall_behind_timeout && rsite->fall_behind_data) {
-				log_error("Defined fall_behind_timeout and"
-					  " fall_behind_data for async replicator %s/%s.",
+				log_error("Defined fall_behind_timeout and "
+					  "fall_behind_data for async replicator %s/%s.",
 					  lv->name, rsite->name);
 				r = 0;
 			}
 			if (rsite->fall_behind_ios && rsite->fall_behind_data) {
-				log_error("Defined fall_behind_ios and"
-					  " fall_behind_data for async replicator %s/%s.",
+				log_error("Defined fall_behind_ios and "
+					  "fall_behind_data for async replicator %s/%s.",
 					  lv->name, rsite->name);
 				r = 0;
 			}
 			if (!rsite->fall_behind_ios &&
 			    !rsite->fall_behind_data &&
 			    !rsite->fall_behind_timeout) {
-				log_error("fall_behind_timeout,"
-					  " fall_behind_ios and fall_behind_data are"
-					  " undefined for async replicator %s/%s.",
+				log_error("For async replicator %s/%s on of "
+					  "fall_behind_timeout, "
+					  "fall_behind_ios and fall_behind_data are "
+					  "needs to be defined.",
 					  lv->name, rsite->name);
 				r = 0;
 			}
@@ -335,16 +833,16 @@ int check_replicator_segment(const struct lv_segment *rseg)
 			if (rsite == rsiteb)
 				break;
 			if (strcasecmp(rsite->name, rsiteb->name) == 0) {
-				log_error("Duplicate site name "
-					  "%s detected for replicator %s.",
+				log_error("Duplicate site name %s "
+					  "detected for replicator %s.",
 					  rsite->name, lv->name);
 				r = 0;
 			}
 			if ((rsite->vg_name && rsiteb->vg_name &&
 			     strcasecmp(rsite->vg_name, rsiteb->vg_name) == 0) ||
 			    (!rsite->vg_name && !rsiteb->vg_name)) {
-				log_error("Duplicate VG name "
-					  "%s detected for replicator %s.",
+				log_error("Duplicate VG name %s "
+					  "detected for replicator %s.",
 					  (rsite->vg_name) ? rsite->vg_name : "<local>",
 					  lv->name);
 				r = 0;
@@ -356,8 +854,8 @@ int check_replicator_segment(const struct lv_segment *rseg)
 					  rsite->name);
 				r = 0;
 			}
-			if (rsite->site_index > rseg->rsite_index_highest) {
-				log_error("Site index %d > %d (too high) "
+			if (rsite->site_index >= rseg->rsite_index_highest) {
+				log_error("Site index %d >= %d (too high) "
 					  "for replicator site %s/%s.",
 					  rsite->site_index,
 					  rseg->rsite_index_highest,
@@ -367,6 +865,20 @@ int check_replicator_segment(const struct lv_segment *rseg)
 		}
 
 		dm_list_iterate_items(rdev, &rsite->rdevices) {
+			if (rdev->rsite->site_index == 0) {
+				if (strcasecmp(rdev->name,
+					       rdev->replicator_dev->lv->name) == 0) {
+					log_error("Self referenced device name "
+						  "%s detected for replicator %s.",
+						  rdev->name, lv->name);
+					r = 0;
+				}
+			} else if (!rdev->slog && !rdev->slog_core) {
+				log_error("Undefined slog for %s/%s "
+					  " for replicator %s.",
+					  rdev->rsite->name, rdev->name, lv->name);
+				r = 0;
+			}
 			dm_list_iterate_items(rdevb, &rsite->rdevices) {
 				if (rdev == rdevb)
 					break;
@@ -376,6 +888,13 @@ int check_replicator_segment(const struct lv_segment *rseg)
 						  rdev->slog->name, lv->name);
 					r = 0;
 				}
+				if (strcasecmp(rdev->name,
+					       rdevb->replicator_dev->lv->name) == 0) {
+					log_error("Internal self reference device "
+						  "name %s detected for replicator %s.",
+						  rdev->name, lv->name);
+					r = 0;
+				}
 				if (strcasecmp(rdev->name, rdevb->name) == 0) {
 					log_error("Duplicate device name %s "
 						  "detected for replicator %s.",
@@ -390,9 +909,9 @@ int check_replicator_segment(const struct lv_segment *rseg)
 						  lv->name, rsite->name);
 					r = 0;
 				}
-				if (rdev->device_index > rseg->rdevice_index_highest) {
-					log_error("Device index %" PRIu64
-						  " > %" PRIu64 " (too high) "
+				if (rdev->device_index >= rseg->rdevice_index_highest) {
+					log_error("Device index %" PRIu64 " >= %"
+						  PRIu64 " (too high) "
 						  "for replicator site %s/%s.",
 						  rdev->device_index,
 						  rseg->rdevice_index_highest,
@@ -406,78 +925,28 @@ int check_replicator_segment(const struct lv_segment *rseg)
 	return r;
 }
 
-/**
- * Is this segment part of active replicator
- */
-int lv_is_active_replicator_dev(const struct logical_volume *lv)
+int replicator_site_set_op_mode(struct replicator_site *rsite, const char *sitemode)
 {
-	return ((lv->status & REPLICATOR) &&
-		lv->rdevice &&
-		lv->rdevice->rsite &&
-		lv->rdevice->rsite->state == REPLICATOR_STATE_ACTIVE);
-}
+	int i;
 
-/**
- * Is this LV replicator control device
- */
-int lv_is_replicator(const struct logical_volume *lv)
-{
-	return ((lv->status & REPLICATOR) &&
-		!dm_list_empty(&lv->segments) &&
-		seg_is_replicator(first_seg(lv)));
-}
-
-/**
- * Is this LV replicator device
- */
-int lv_is_replicator_dev(const struct logical_volume *lv)
-{
-	return ((lv->status & REPLICATOR) &&
-		!dm_list_empty(&lv->segments) &&
-		seg_is_replicator_dev(first_seg(lv)));
-}
-
-/**
- * Is this LV replicated origin lv
- */
-int lv_is_rimage(const struct logical_volume *lv)
-{
-	return (lv->rdevice && lv->rdevice->lv == lv);
-}
-
-/**
- * Is this LV rlog
- */
-int lv_is_rlog(const struct logical_volume *lv)
-{
-	return (lv->status & REPLICATOR_LOG);
-}
+	for (i = 0; i < sizeof(dm_op_mode_table)/sizeof(dm_op_mode_table[0]); ++i)
+		if (strcasecmp(sitemode, dm_op_mode_table[i].name) == 0) {
+			rsite->op_mode = dm_op_mode_table[i].value;
+			return 1;
+		}
 
-/**
- * Is this LV sync log
- */
-int lv_is_slog(const struct logical_volume *lv)
-{
-	return (lv->rdevice && lv->rdevice->slog == lv);
+	return 0;
 }
 
-/**
- * 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)
+const char *replicator_site_get_op_mode(const struct replicator_site *rsite)
 {
-	struct replicator_device *rdev;
-	struct replicator_site *rsite;
+	int i;
 
-	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;
-		}
+	for (i = 0; i < sizeof(dm_op_mode_table)/sizeof(dm_op_mode_table[0]); ++i)
+		if (rsite->op_mode == dm_op_mode_table[i].value)
+			return dm_op_mode_table[i].name;
 
-	return NULL;
+        return NULL;
 }
 
 /**
@@ -646,13 +1115,13 @@ int lv_read_replicator_vgs(struct logical_volume *lv)
 	struct replicator_site *rsite;
 	struct volume_group *vg;
 
-	if (!lv_is_replicator_dev(lv))
+	if (!lv_is_active_replicator_dev(lv))
 		return 1;
 
 	dm_list_iterate_items(rsite, &first_seg(lv)->replicator->rsites) {
 		if (!rsite->vg_name)
 			continue;
-		vg = vg_read(lv->vg->cmd, rsite->vg_name, 0, 0); // READ_WITHOUT_LOCK
+		vg = vg_read(lv->vg->cmd, rsite->vg_name, 0, READ_WITHOUT_LOCK);
 		if (vg_read_error(vg)) {
 			log_error("Unable to read volume group %s",
 				  rsite->vg_name);
@@ -691,3 +1160,325 @@ void lv_release_replicator_vgs(struct logical_volume *lv)
 			rsite->vg = NULL;
 		}
 }
+
+static int _write_replicator_header(struct cmd_context *cmd, struct logical_volume *lv)
+{
+	return 1;
+}
+
+/*
+ * Initialize log contents
+ *
+ * log_name = "mirror log", "replicator sync log"
+ */
+static int _init_log(struct cmd_context *cmd,
+		     struct logical_volume *log_lv, int in_sync,
+		     struct dm_list *tags, int remove_on_failure,
+		     const char *log_name,
+		     int (*write_header) (struct cmd_context *cmd,
+					  struct logical_volume *lv))
+{
+	struct str_list *sl;
+	struct lvinfo info;
+	uint64_t orig_status = log_lv->status;
+	int was_active = 0;
+
+	if (!activation() && in_sync) {
+		log_error("Aborting. Unable to create in-sync %s "
+			  "while activation is disabled.", log_name);
+		return 0;
+	}
+
+	/* If the LV is active, deactivate it first. */
+	if (lv_info(cmd, log_lv, &info, 0, 0) && info.exists) {
+		(void)deactivate_lv(cmd, log_lv);
+		/*
+		 * FIXME: workaround to fail early
+		 * Ensure that log is really deactivated because deactivate_lv
+		 * on cluster do not fail if there is log_lv with different UUID.
+		 */
+		if (lv_info(cmd, log_lv, &info, 0, 0) && info.exists) {
+			log_error("Aborting. Unable to deactivate %s.",
+				  log_name);
+			goto revert_new_lv;
+		}
+		was_active = 1;
+	}
+
+	/* Temporary make it visible for set_lv() */
+	lv_set_visible(log_lv);
+
+	/* Temporary tag mirror log for activation */
+	dm_list_iterate_items(sl, tags)
+		if (!str_list_add(cmd->mem, &log_lv->tags, sl->str)) {
+			log_error("Aborting. Unable to tag %s.", log_name);
+			goto activate_lv;
+		}
+
+	/* store mirror log on disk(s) */
+	if (!vg_write(log_lv->vg) || !vg_commit(log_lv->vg))
+		goto activate_lv;
+
+	backup(log_lv->vg);
+
+	if (!activate_lv(cmd, log_lv)) {
+		log_error("Aborting. Failed to activate %s.", log_name);
+		goto revert_new_lv;
+	}
+
+	/* Remove the temporary tags */
+	dm_list_iterate_items(sl, tags)
+		if (!str_list_del(&log_lv->tags, sl->str))
+			log_error("Failed to remove tag %s from %s.",
+				  log_name, sl->str);
+
+	if (activation() && !set_lv(cmd, log_lv, log_lv->size,
+				    in_sync ? -1 : 0)) {
+		log_error("Aborting. Failed to wipe %s.", log_name);
+		goto deactivate_and_revert_new_lv;
+	}
+
+	if (activation() && !write_header(cmd, log_lv)) { /* FIXME */
+		log_error("Aborting. Failed to write %s header.", log_name);
+		goto deactivate_and_revert_new_lv;
+	}
+
+	if (!deactivate_lv(cmd, log_lv)) {
+		log_error("Aborting. Failed to deactivate %s. "
+			  "Manual intervention required.", log_name);
+		return 0;
+	}
+
+	lv_set_hidden(log_lv);
+
+	if (was_active && !activate_lv(cmd, log_lv))
+		return_0;
+
+	return 1;
+
+deactivate_and_revert_new_lv:
+	if (!deactivate_lv(cmd, log_lv)) {
+		log_error("Unable to deactivate %s LV. "
+			  "Manual intervention required.", log_name);
+		return 0;
+	}
+
+revert_new_lv:
+	log_lv->status = orig_status;
+
+	dm_list_iterate_items(sl, tags)
+		if (!str_list_del(&log_lv->tags, sl->str))
+			log_error("Failed to remove tag %s from %s.",
+				  log_name, sl->str);
+
+	if (remove_on_failure && !lv_remove(log_lv)) {
+		log_error("Manual intervention may be required to remove "
+			  "abandoned log LV before retrying.");
+		return 0;
+	}
+
+	if (!vg_write(log_lv->vg) || !vg_commit(log_lv->vg))
+		log_error("Manual intervention may be required to "
+			  "remove/restore abandoned log LV before retrying.");
+	else
+		backup(log_lv->vg);
+
+activate_lv:
+	if (was_active && !remove_on_failure && !activate_lv(cmd, log_lv))
+		return_0;
+
+	return 0;
+}
+
+#if 0
+static int _init_replicator_log(struct cmd_context *cmd,
+				struct logical_volume *log_lv, int in_sync,
+				struct dm_list *tags, int remove_on_failure)
+{
+	if (!_init_log(cmd, log_lv, in_sync, tags, remove_on_failure,
+		       "replicator log", _write_replicator_header))
+		return_0;
+
+	return 1;
+}
+#endif
+
+static int _init_replicator_sync_log(struct cmd_context *cmd,
+				     struct logical_volume *log_lv, int in_sync,
+				     struct dm_list *tags, int remove_on_failure)
+{
+	if (!_init_log(cmd, log_lv, in_sync, tags, remove_on_failure,
+		       "sync log", _write_replicator_header))
+		return_0;
+
+	return 1;
+}
+
+/* Could be shared with mirror */
+static struct logical_volume *_create_log(struct logical_volume *lv,
+					  struct alloc_handle *ah,
+					  alloc_policy_t alloc,
+					  const char *lv_name,
+					  const char *suffix,
+					  uint64_t status)
+{
+	struct logical_volume *log_lv;
+	char *log_name;
+	size_t len;
+
+	len = strlen(lv_name) + 32;
+	if (!(log_name = alloca(len))) {
+		log_error("log_name allocation failed.");
+		return NULL;
+	}
+
+	if (dm_snprintf(log_name, len, "%s%s", lv_name, suffix) < 0) {
+		log_error("log_name allocation failed.");
+		return NULL;
+	}
+
+	if (!(log_lv = lv_create_empty(log_name, NULL,
+				       VISIBLE_LV | LVM_READ | LVM_WRITE,
+				       alloc, lv->vg)))
+		return_NULL;
+
+	if (!lv_add_log_segment(ah, 0, log_lv, status))
+		return_NULL;
+
+	return log_lv;
+}
+
+#if 0
+static struct logical_volume *_set_up_replicator_log(struct cmd_context *cmd,
+						     struct alloc_handle *ah,
+						     struct logical_volume *lv,
+						     uint32_t log_size __attribute((unused)),
+						     alloc_policy_t alloc,
+						     int in_sync)
+{
+	struct logical_volume *log_lv;
+	const char *suffix, *c;
+	char *lv_name;
+	size_t len;
+	struct lv_segment *seg;
+
+	//init_mirror_in_sync(in_sync);
+
+	/* Replicator log name is lv_name + suffix, determined as the following:
+	 *   1. suffix is:
+	 *        o "_rlog" for the original replicator LV.
+	 *        o "_rlogtmp_%d" for temporary mirror LV,
+	 *   2. lv_name is:
+	 *        o lv->name, if the log is temporary
+	 *        o otherwise, the top-level LV name
+	 */
+	seg = first_seg(lv);
+	if (seg_type(seg, 0) == AREA_LV &&
+	    strstr(seg_lv(seg, 0)->name, MIRROR_SYNC_LAYER)) {
+		lv_name = lv->name;
+		suffix = "_rlogtmp_%d";
+	} else if ((c = strstr(lv->name, MIRROR_SYNC_LAYER))) {
+		len = (size_t)(c - lv->name + 1);
+		if (!(lv_name = alloca(len)) ||
+		    !dm_snprintf(lv_name, len, "%s", lv->name)) {
+			log_error("replicator log name allocation failed");
+			return 0;
+		}
+		suffix = "_rlog";
+	} else {
+		lv_name = lv->name;
+		suffix = "_rlog";
+	}
+
+	if (!(log_lv = _create_log(lv, ah, alloc, lv_name, suffix, REPLICATOR_LOG))) {
+		log_error("Failed to create replicator log.");
+		return NULL;
+	}
+
+	if (!_init_replicator_log(cmd, log_lv, in_sync, &lv->tags, 1)) {
+		log_error("Failed to initialise replicator log.");
+		return NULL;
+	}
+
+	return log_lv;
+}
+#endif
+
+static struct logical_volume *_set_up_sync_log(struct cmd_context *cmd,
+					       struct alloc_handle *ah,
+					       struct logical_volume *replicator,
+                                               unsigned site_index,
+					       uint64_t device_index,
+					       alloc_policy_t alloc,
+					       int in_sync)
+{
+	struct logical_volume *log_lv;
+	const char *suffix = "";
+	char *lv_name;
+
+	if (!(lv_name = _replicator_device_slog_name(replicator, site_index, device_index)))
+		return_NULL;
+
+	if (!(log_lv = _create_log(replicator, ah, alloc, lv_name, suffix,
+				   REPLICATOR_LOG))) {
+		log_error("Failed to create replicator sync log.");
+		return NULL;
+	}
+
+	if (!_init_replicator_sync_log(cmd, log_lv, in_sync, &replicator->tags, 1)) {
+		log_error("Failed to initialise replicator sync log.");
+		return NULL;
+	}
+
+	return log_lv;
+}
+
+int lv_add_sync_log(struct logical_volume *replicator,
+		    unsigned site_index,
+		    uint64_t device_index,
+		    struct dm_list *allocatable_pvs,
+		    alloc_policy_t alloc)
+{
+	struct cmd_context *cmd = replicator->vg->cmd;
+	const struct segment_type *segtype;
+	struct alloc_handle *ah;
+	uint32_t region_size;
+	int in_sync;
+	int r = 1;
+
+	if (!(segtype = get_segtype_from_string(cmd, "striped")))
+		return_0;
+
+	if (activation() && segtype->ops->target_present &&
+	    !segtype->ops->target_present(cmd, NULL, NULL)) {
+		log_error("%s: Required device-mapper target(s) not "
+			  "detected in your kernel", segtype->name);
+		return 0;
+	}
+
+	region_size = adjusted_mirror_region_size(replicator->vg->extent_size,
+						  replicator->le_count,
+						  first_seg(replicator)->region_size);
+
+	/* allocate destination extents */
+	ah = allocate_extents(replicator->vg, NULL, segtype,
+			      0, 0, 1, region_size, 0,
+			      allocatable_pvs, alloc, NULL);
+	if (!ah) {
+		log_error("Unable to allocate extents for replicator sync log.");
+		return 0;
+	}
+
+	/* check sync status */
+	in_sync = 0;
+
+	if (!_set_up_sync_log(cmd, ah, replicator, site_index, device_index,
+			      alloc, in_sync)) {
+		stack;
+		r = 0;
+	}
+
+	alloc_destroy(ah);
+
+	return r;
+}
-- 
1.7.1.1



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

* [PATCH 13/22] Replicator: replicator.c changes
  2010-07-07 12:34 [PATCH 00/22] Replicator 100707 Zdenek Kabelac
                   ` (11 preceding siblings ...)
  2010-07-07 12:34 ` [PATCH 12/22] Replicator: replicator_manip changes Zdenek Kabelac
@ 2010-07-07 12:34 ` Zdenek Kabelac
  2010-07-07 12:34 ` [PATCH 14/22] Replicator: add new command option read functions Zdenek Kabelac
                   ` (8 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2010-07-07 12:34 UTC (permalink / raw)
  To: lvm-devel

Changes for replicator.c source file.

Reusing few new API functions from replicator_manip.c for replicator.
Add few missing log_error() diagnostic messages instead of <backtrace>.

Segment for replicator has now SEG_VIRTUAL and SEG_CANNOT_BE_ZEROED
flags. (Not really sure about logic here).

Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
 lib/replicator/replicator.c |  178 +++++++++++++++----------------------------
 1 files changed, 61 insertions(+), 117 deletions(-)

diff --git a/lib/replicator/replicator.c b/lib/replicator/replicator.c
index 6f09321..821e16d 100644
--- a/lib/replicator/replicator.c
+++ b/lib/replicator/replicator.c
@@ -104,61 +104,17 @@ static replicator_state_t _get_state(const struct config_node *sn,
 	return def;
 }
 
-/* Strings for replicator_action_t enum */
-static const char _op_mode_txt[NUM_DM_REPLICATOR_MODES][8] = {
-	"sync",
-	"warn",
-	"stall",
-	"drop",
-	"fail"
-};
-
-
-/* Parse action string */
-static dm_replicator_mode_t _get_op_mode(const struct config_node *sn,
-					 const char *path, dm_replicator_mode_t def)
-{
-	char *str;
-	unsigned i;
-
-	if (get_config_str(sn, path, &str)) {
-		for (i = 0; i < sizeof(_op_mode_txt)/sizeof(_op_mode_txt[0]); ++i)
-			if (strcasecmp(str, _op_mode_txt[i]) == 0) {
-				log_very_verbose("Setting %s to %s",
-						 path, _op_mode_txt[i]);
-				return (dm_replicator_mode_t) i;
-			}
-		log_warn("%s: unknown value '%s', using default '%s' operation mode",
-			 path, str, _op_mode_txt[def]);
-	}
-
-	return def;
-}
-
 static struct replicator_site *_get_site(struct logical_volume *replicator,
 					 const char *key)
 {
-	struct dm_pool *mem = replicator->vg->vgmem;
 	struct replicator_site *rsite;
 
-	dm_list_iterate_items(rsite, &replicator->rsites)
-		if (strcasecmp(rsite->name, key) == 0)
-			return rsite;
-
-	if (!(rsite = dm_pool_zalloc(mem, sizeof(*rsite))))
-		return_NULL;
-
-	if (!(rsite->name = dm_pool_strdup(mem, key)))
-		return_NULL;
+	if ((rsite = find_site_in_replicator(replicator, key)))
+		return rsite;
 
-	rsite->replicator = replicator;
-	dm_list_init(&rsite->rdevices);
-	dm_list_add(&replicator->rsites, &rsite->list);
-
-	return rsite;
+	return replicator_add_site(replicator, key);
 }
 
-
 /* Parse replicator site element */
 static int _add_site(struct lv_segment *seg,
 		     const char *key,
@@ -167,6 +123,7 @@ static int _add_site(struct lv_segment *seg,
 	struct dm_pool *mem = seg->lv->vg->vgmem;
 	const struct config_node *cn;
 	struct replicator_site *rsite;
+	char *op_mode;
 
 	if (!(rsite = _get_site(seg->lv, key)))
 		return_0;
@@ -200,8 +157,11 @@ static int _add_site(struct lv_segment *seg,
 			return SEG_LOG_ERROR("Defined both fall_behind_ios "
 					     "and fall_behind_timeout in");
 
-		rsite->op_mode = _get_op_mode(sn, "operation_mode",
-					      rsite->op_mode);
+		if (!get_config_str(sn, "operation_mode", &op_mode))
+			return SEG_LOG_ERROR("Operation mode undefined in");
+
+		if (!replicator_site_set_op_mode(rsite, op_mode))
+			return SEG_LOG_ERROR("Unknown value for operation mode in");
 	}
 
 	if ((cn = find_config_node(sn, "volume_group"))) {
@@ -226,8 +186,7 @@ static int _replicator_text_import(struct lv_segment *seg,
 	const struct config_node *cn;
 	struct logical_volume *rlog_lv;
 
-	if (!replicator_add_replicator_dev(seg->lv, NULL))
-		return_0;
+	replicator_init(seg->lv);
 
 	if (!(cn = find_config_node(sn, "replicator_log")) ||
 	    !cn->v || cn->v->type != CFG_STRING)
@@ -246,7 +205,6 @@ static int _replicator_text_import(struct lv_segment *seg,
 	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);
 
@@ -267,6 +225,7 @@ static int _replicator_text_import(struct lv_segment *seg,
 			if (!_add_site(seg, sn->key, sn->child))
 				return_0;
 		}
+
 	return 1;
 }
 
@@ -275,9 +234,10 @@ static int _replicator_text_export(const struct lv_segment *seg,
 				   struct formatter *f)
 {
 	struct replicator_site *rsite;
+	const char *op_mode;
 
 	if (!seg->rlog_lv)
-                return_0;
+		return_0;
 
 	outf(f, "replicator_log = \"%s\"", seg->rlog_lv->name);
 	outf(f, "replicator_log_type = \"%s\"", seg->rlog_type);
@@ -299,9 +259,13 @@ static int _replicator_text_export(const struct lv_segment *seg,
 		outf(f, "site_index = %d", rsite->site_index);
 
 		/* Only non-default parameters are written */
-		if (rsite->op_mode != DM_REPLICATOR_SYNC)
-			outf(f, "operation_mode = \"%s\"",
-			     _op_mode_txt[rsite->op_mode]);
+		if (rsite->op_mode != DM_REPLICATOR_SYNC) {
+			if (!(op_mode = replicator_site_get_op_mode(rsite))) {
+				log_error("Unknown operation mode.");
+				return 0;
+			}
+			outf(f, "operation_mode = \"%s\"", op_mode);
+		}
 		if (rsite->fall_behind_timeout)
 			outfc(f, "# seconds", "fall_behind_timeout = %u",
 			     rsite->fall_behind_timeout);
@@ -445,13 +409,13 @@ static int _add_device(struct lv_segment *seg,
 		       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 logical_volume *rimage = NULL;
+	struct logical_volume *slog = NULL;
 	struct replicator_site *rsite = _get_site(seg->replicator, site_name);
 	struct replicator_device *rdev;
-	const char *dev_str = NULL;
+	const char *lv_name = NULL;
 	const char *slog_str = NULL;
+	uint32_t slog_core = 0;
 	const struct config_node *cn;
 
 	dm_list_iterate_items(rdev, &rsite->rdevices)
@@ -459,61 +423,42 @@ static int _add_device(struct lv_segment *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->v && cn->v->v.str)
+			slog_str = cn->v->v.str;
+		else if (!get_config_uint32(sn, "sync_log", &slog_core))
+			return SEG_LOG_ERROR("Could not read 'sync_log' for");
 	}
 
 	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;
+	lv_name = 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);
+					     "site device in", slog_str);
 
 		/* Check for device in current VG */
-		if (!(lv = find_lv(seg->lv->vg, dev_str)))
+		if (!(rimage = find_lv(seg->lv->vg, lv_name)))
 			return SEG_LOG_ERROR("Logical volume %s not found in",
-					     dev_str);
+					     lv_name);
 	} else {
-		if (!slog_str)
+		if (!slog_str && !slog_core)
 			return SEG_LOG_ERROR("Sync log is missing for remote "
-					     "device in");
+					     "site device in");
 		/* Check for slog device in current VG */
-		if (!(slog_lv = find_lv(seg->lv->vg, slog_str)))
+		if (!slog_core &&
+		    !(slog = 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)))
+	if (!replicator_site_add_device(rsite, seg, lv_name, rimage,
+					slog_core, slog, devidx))
 		return_0;
 
-	rdev->replicator_dev = seg;
-	rdev->rsite = rsite;
-	rdev->device_index = devidx;
-
-	if (!seg->lv->rdevice) {
-		if (!replicator_dev_add_rimage(rdev, lv))
-			return SEG_LOG_ERROR("LV inconsistency found in");
-		seg->lv->rdevice = rdev;
-	} else {
-		if (!slog_str ||
-		    !(rdev->slog_name = dm_pool_strdup(mem, slog_str)))
-			return_0;
-
-		if (!replicator_dev_add_slog(rdev, slog_lv))
-			return SEG_LOG_ERROR("Sync log inconsistency found in");
-	}
-
-	dm_list_add(&rsite->rdevices, &rdev->list);// linked site list
-
 	return 1;
 }
 
@@ -553,9 +498,6 @@ static int _replicator_dev_text_import(struct lv_segment *seg,
 	if (!seg->lv->rdevice)
 		return SEG_LOG_ERROR("Replicator device without site in");
 
-	seg->rlog_lv = NULL;
-	seg->lv->status |= REPLICATOR;
-
 	return 1;
 }
 
@@ -586,10 +528,12 @@ static int _replicator_dev_text_export(const struct lv_segment *seg,
 			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);
+			if (rsite->site_index != 0) {
+				if (rdev->slog)
+					outf(f, "sync_log = \"%s\"", rdev->slog->name);
+				else
+					outf(f, "sync_log = %d", rdev->slog_core);
+			}
 
 			out_dec_indent(f);
 
@@ -625,8 +569,10 @@ static int _replicator_dev_add_target_line(struct dev_manager *dm,
 				 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_dm_uuid(mem, seg->lv->rdevice->lv->lvid.s, NULL)))
-			return_0;
+		if (!(rdev_dlid = build_dm_uuid(mem, seg->lv->rdevice->lv->lvid.s, NULL))) {
+			log_error("Failed to build replicator-dev uuid.");
+			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)",
@@ -640,8 +586,10 @@ static int _replicator_dev_add_target_line(struct dev_manager *dm,
 	 * must be present in dm_tree
 	 */
 	if (!seg_is_replicator_dev(seg) ||
-	    !(replicator_dlid = build_dm_uuid(mem, seg->replicator->lvid.s, NULL)))
-		return_0;
+	    !(replicator_dlid = build_dm_uuid(mem, seg->replicator->lvid.s, NULL))) {
+		log_error("Failed to build replicator dlid.");
+		return 0;
+	}
 
 	/* Select remote devices with the same device index */
 	dm_list_iterate_items(rsite, &seg->replicator->rsites) {
@@ -664,8 +612,10 @@ static int _replicator_dev_add_target_line(struct dev_manager *dm,
 		}
 
 		if (!rdev->lv ||
-		    !(rdev_dlid = build_dm_uuid(mem, rdev->lv->lvid.s, NULL)))
-			return_0;
+		    !(rdev_dlid = build_dm_uuid(mem, rdev->lv->lvid.s, NULL))) {
+			log_error("Failed UUID allocation.");
+			return 0;
+		}
 
 		slog_dlid = NULL;
 
@@ -675,18 +625,12 @@ static int _replicator_dev_add_target_line(struct dev_manager *dm,
 			slog_size = (uint32_t) rdev->slog->size;
 			if (!(slog_dlid = build_dm_uuid(mem, 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  {
+		} else if (rdev->slog_core || (rsite->site_index == 0)) {
 			slog_flags = DM_CORELOG | DM_FORCESYNC;
 			slog_size = 0; /* NOLOG */
+		} else {
+			log_error(INTERNAL_ERROR "Either slog or corelog must be used.");
+			return 0;
 		}
 
 		if (!dm_tree_node_add_replicator_dev_target(node,
@@ -766,7 +710,7 @@ int init_multiple_segtype(struct segtype_library *seglib)
 	segtype->ops = &_replicator_ops;
 	segtype->name = REPLICATOR_MODULE;
 	segtype->private = NULL;
-	segtype->flags = SEG_REPLICATOR;
+	segtype->flags = SEG_REPLICATOR | SEG_VIRTUAL | SEG_CANNOT_BE_ZEROED;
 
 	if (!lvm_register_segtype(seglib, segtype))
 		return_0;
-- 
1.7.1.1



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

* [PATCH 14/22] Replicator: add new command option read functions
  2010-07-07 12:34 [PATCH 00/22] Replicator 100707 Zdenek Kabelac
                   ` (12 preceding siblings ...)
  2010-07-07 12:34 ` [PATCH 13/22] Replicator: replicator.c changes Zdenek Kabelac
@ 2010-07-07 12:34 ` Zdenek Kabelac
  2010-07-07 12:34 ` [PATCH 15/22] Replicator: new args Zdenek Kabelac
                   ` (7 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2010-07-07 12:34 UTC (permalink / raw)
  To: lvm-devel

site_arg - reads name of the site.
sitemode_arg - reads site mode.

Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
 tools/lvmcmdline.c |   24 ++++++++++++++++++++++++
 tools/tools.h      |    2 ++
 2 files changed, 26 insertions(+), 0 deletions(-)

diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c
index 8ff74ac..7d55e48 100644
--- a/tools/lvmcmdline.c
+++ b/tools/lvmcmdline.c
@@ -473,6 +473,30 @@ 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)
+{
+	if (!validate_name(a->value)) {
+		log_error("Invalid site name.");
+		return 0;
+	}
+
+	return 1;
+}
+
+int sitemode_arg(struct cmd_context *cmd __attribute((unused)), struct arg *a)
+{
+	struct replicator_site rsite;
+
+	if (!replicator_site_set_op_mode(&rsite, a->value)) {
+		log_error("Invalid site mode %s.", a->value);
+		return 0;
+	}
+
+	a->ui_value = rsite.op_mode;
+
+	return 1;
+}
+
 /*
  * Non-zero, positive integer, "all", or "unmanaged"
  */
diff --git a/tools/tools.h b/tools/tools.h
index 2e06fc2..3104d0a 100644
--- a/tools/tools.h
+++ b/tools/tools.h
@@ -153,6 +153,8 @@ 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 metadatacopies_arg(struct cmd_context *cmd __attribute((unused)), struct arg *a);
+int site_arg(struct cmd_context *cmd, struct arg *a);
+int sitemode_arg(struct cmd_context *cmd, struct arg *a);
 
 /* we use the enums to access the switches */
 unsigned arg_count(const struct cmd_context *cmd, int a);
-- 
1.7.1.1



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

* [PATCH 15/22] Replicator: new args
  2010-07-07 12:34 [PATCH 00/22] Replicator 100707 Zdenek Kabelac
                   ` (13 preceding siblings ...)
  2010-07-07 12:34 ` [PATCH 14/22] Replicator: add new command option read functions Zdenek Kabelac
@ 2010-07-07 12:34 ` Zdenek Kabelac
  2010-07-07 12:34 ` [PATCH 16/22] Replicator: read site_params Zdenek Kabelac
                   ` (6 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2010-07-07 12:34 UTC (permalink / raw)
  To: lvm-devel


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

diff --git a/tools/args.h b/tools/args.h
index a23c46c..78f2177 100644
--- a/tools/args.h
+++ b/tools/args.h
@@ -69,6 +69,16 @@ arg(noudevsync_ARG, '\0', "noudevsync", NULL, 0)
 arg(poll_ARG, '\0', "poll", yes_no_arg, 0)
 arg(stripes_long_ARG, '\0', "stripes", int_arg, 0)
 arg(sysinit_ARG, '\0', "sysinit", NULL, 0)
+arg(replicator_ARG, '\0', "replicator", string_arg, 0)
+arg(replicatordev_ARG, '\0', "replicatordev", NULL, 0)
+arg(replicatorsynclog_ARG, '\0', "replicatorsynclog", string_arg, 0)
+arg(replicatorlogtype_ARG, '\0', "replicatorlogtype", string_arg, 0)
+arg(site_ARG, '\0', "site", site_arg, 0)
+arg(fallbehinddata_ARG, '\0', "fallbehinddata", size_mb_arg, 0)
+arg(fallbehindios_ARG, '\0', "fallbehindios", int_arg, 0)
+arg(fallbehindtimeout_ARG, '\0', "fallbehindtimeout", int_arg, 0)
+arg(sitemode_ARG, '\0', "sitemode", sitemode_arg, 0)
+arg(remotevg_ARG, '\0', "remotevg", string_arg, 0)
 
 /* Allow some variations */
 arg(resizable_ARG, '\0', "resizable", yes_no_arg, 0)
-- 
1.7.1.1



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

* [PATCH 16/22] Replicator: read site_params
  2010-07-07 12:34 [PATCH 00/22] Replicator 100707 Zdenek Kabelac
                   ` (14 preceding siblings ...)
  2010-07-07 12:34 ` [PATCH 15/22] Replicator: new args Zdenek Kabelac
@ 2010-07-07 12:34 ` Zdenek Kabelac
  2010-07-07 12:34 ` [PATCH 17/22] Replicator: lv_manip - create replicator Zdenek Kabelac
                   ` (5 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2010-07-07 12:34 UTC (permalink / raw)
  To: lvm-devel

Common function for parsing replicator site parameters.
It's used by lvcreate and lvchange command in later patch.

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

diff --git a/tools/toollib.c b/tools/toollib.c
index bdb52d5..f1da944 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -1551,3 +1551,114 @@ int get_stripe_params(struct cmd_context *cmd, uint32_t *stripes, uint32_t *stri
 	return _validate_stripe_params(cmd, stripes, stripe_size);
 }
 
+/**
+ * Parse parameters for replicator site
+ *
+ * \param cmd
+ * \param rsite
+ * \param changed
+ */
+int get_replicator_site_params(struct cmd_context *cmd,
+			       struct replicator_site *rsite,
+			       int *changed)
+{
+	struct replicator_site nrsite;
+
+	if (arg_count(cmd, fallbehinddata_ARG)) {
+		nrsite.fall_behind_data =
+			arg_uint64_value(cmd, fallbehinddata_ARG,
+					 DEFAULT_REPLICATOR_FALL_BEHIND_DATA);
+		if (rsite->fall_behind_data != nrsite.fall_behind_data) {
+			rsite->fall_behind_data = nrsite.fall_behind_data;
+			rsite->fall_behind_ios = 0;
+			rsite->fall_behind_timeout = 0;
+			(*changed)++;
+		}
+	}
+
+	if (arg_count(cmd, fallbehindios_ARG)) {
+		if (arg_count(cmd, fallbehinddata_ARG)) {
+			log_error("Only one asynchronous parameter can be used.");
+			return 0;
+		}
+		nrsite.fall_behind_ios =
+			arg_uint_value(cmd, fallbehindios_ARG,
+				       DEFAULT_REPLICATOR_FALL_BEHIND_IOS);
+
+		if (rsite->fall_behind_ios != nrsite.fall_behind_ios) {
+			rsite->fall_behind_data = 0;
+			rsite->fall_behind_ios = nrsite.fall_behind_ios;
+			rsite->fall_behind_timeout = 0;
+			(*changed)++;
+		}
+	}
+
+	if (arg_count(cmd, fallbehindtimeout_ARG)) {
+		if (arg_count(cmd, fallbehinddata_ARG) ||
+		    arg_count(cmd, fallbehindios_ARG)) {
+			log_error("Only one asynchronous parameter can be used.");
+			return 0;
+		}
+		nrsite.fall_behind_timeout =
+			arg_uint_value(cmd, fallbehindtimeout_ARG,
+				       DEFAULT_REPLICATOR_FALL_BEHIND_TIMEOUT);
+
+		if (rsite->fall_behind_timeout != nrsite.fall_behind_timeout) {
+			rsite->fall_behind_data = 0;
+			rsite->fall_behind_ios = 0;
+			rsite->fall_behind_timeout = nrsite.fall_behind_timeout;
+			(*changed)++;
+		}
+	}
+
+	nrsite.op_mode = NUM_DM_REPLICATOR_MODES;
+	if (arg_count(cmd, sitemode_ARG)) {
+		nrsite.op_mode = arg_uint_value(cmd, sitemode_ARG,
+						DEFAULT_REPLICATOR_ASYNC_MODE);
+		if ((nrsite.op_mode == DM_REPLICATOR_SYNC) &&
+		    !arg_count(cmd, fallbehinddata_ARG) &&
+		    !arg_count(cmd, fallbehindios_ARG) &&
+		    !arg_count(cmd, fallbehindtimeout_ARG) &&
+		    (rsite->fall_behind_data ||
+		     rsite->fall_behind_ios ||
+		     rsite->fall_behind_timeout)) {
+			rsite->fall_behind_data = 0;
+			rsite->fall_behind_ios = 0;
+			rsite->fall_behind_timeout = 0;
+			(*changed)++;
+			log_debug("Clearing asynchronous parameters synchronous site.");
+		}
+	}
+
+	if (rsite->fall_behind_data ||
+	    rsite->fall_behind_ios ||
+	    rsite->fall_behind_timeout) {
+		if (!rsite->vg_name) {
+			log_error("Cannot set asynchronous parameters for "
+				  "the local site %s.", rsite->name);
+			return 0;
+		}
+		if (nrsite.op_mode == DM_REPLICATOR_SYNC) {
+			log_error("For synchronous site mode all asynchronous "
+				  "parameters must be deleted.");
+			return 0;
+		} else if (nrsite.op_mode == NUM_DM_REPLICATOR_MODES)
+			nrsite.op_mode = (rsite->op_mode == DM_REPLICATOR_SYNC) ?
+				DEFAULT_REPLICATOR_ASYNC_MODE : rsite->op_mode;
+	} else {
+		if (nrsite.op_mode != NUM_DM_REPLICATOR_MODES &&
+		    nrsite.op_mode != DM_REPLICATOR_SYNC) {
+			log_error("For asynchronous site mode an asynchronous "
+				  "non-zero parameter must be specified.");
+			return 0;
+		}
+		nrsite.op_mode = DM_REPLICATOR_SYNC;
+	}
+
+	if (rsite->op_mode != nrsite.op_mode) {
+		rsite->op_mode = nrsite.op_mode;
+		(*changed)++;
+	}
+
+	return 1;
+}
diff --git a/tools/toollib.h b/tools/toollib.h
index daab95a..1d3d3c1 100644
--- a/tools/toollib.h
+++ b/tools/toollib.h
@@ -118,4 +118,7 @@ int get_activation_monitoring_mode(struct cmd_context *cmd,
 int get_stripe_params(struct cmd_context *cmd, uint32_t *stripes,
 		      uint32_t *stripe_size);
 
+int get_replicator_site_params(struct cmd_context *cmd,
+			       struct replicator_site *rsite,
+			       int *changed);
 #endif
-- 
1.7.1.1



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

* [PATCH 17/22] Replicator: lv_manip - create replicator
  2010-07-07 12:34 [PATCH 00/22] Replicator 100707 Zdenek Kabelac
                   ` (15 preceding siblings ...)
  2010-07-07 12:34 ` [PATCH 16/22] Replicator: read site_params Zdenek Kabelac
@ 2010-07-07 12:34 ` Zdenek Kabelac
  2010-07-07 12:34 ` [PATCH 18/22] Replicator: lvcreate implementation Zdenek Kabelac
                   ` (4 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2010-07-07 12:34 UTC (permalink / raw)
  To: lvm-devel

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

diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 5e4a674..e59f264 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -418,6 +418,8 @@ static int _lv_reduce(struct logical_volume *lv, uint32_t extents, int delete)
 			/* FIXME Check this is safe */
 			if (seg->log_lv && !lv_remove(seg->log_lv))
 				return_0;
+			if (seg->rlog_lv && !lv_remove(seg->rlog_lv))
+				return_0;
 			dm_list_del(&seg->list);
 			reduction = seg->len;
 		} else
@@ -2205,6 +2207,7 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
 	struct volume_group *vg;
 	struct lvinfo info;
 	struct logical_volume *origin = NULL;
+	struct logical_volume *replicator = NULL;
 	int was_merging = 0;
 
 	vg = lv->vg;
@@ -2230,6 +2233,12 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
 		return 0;
 	}
 
+	if (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;
@@ -2267,6 +2276,14 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
 			return_0;
 	}
 
+	if (lv_is_replicator_dev(lv)) {
+                replicator = first_seg(lv)->replicator;
+		if (!lv_remove_replicator_dev(lv)) {
+			log_error("Unable to remove replicator-dev %s", lv->name);
+			return 0;
+		}
+	}
+
 	if (!deactivate_lv(cmd, lv)) {
 		log_error("Unable to deactivate logical volume \"%s\"",
 			  lv->name);
@@ -2295,6 +2312,17 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
 		}
 	}
 
+	if (replicator) {
+		if (!suspend_lv(cmd, replicator)) {
+			log_error("Failed to refresh replicator %s.", replicator->name);
+			return 0;
+		}
+		if (!resume_lv(cmd, replicator)) {
+			log_error("Failed to resume replicator %s.", replicator->name);
+			return 0;
+		}
+	}
+
 	backup(vg);
 
 	if (lv_is_visible(lv))
@@ -2310,6 +2338,8 @@ int lv_remove_with_dependencies(struct cmd_context *cmd, struct logical_volume *
 				const force_t force, unsigned level)
 {
 	struct dm_list *snh, *snht;
+	struct replicator_site *rsite;
+	struct replicator_device *rdev;
 
 	if (lv_is_cow(lv)) {
 		/* A merging snapshot cannot be removed directly */
@@ -2320,6 +2350,18 @@ int lv_remove_with_dependencies(struct cmd_context *cmd, struct logical_volume *
 		}
 	}
 
+	if (lv_is_replicator(lv)) {
+		/* Remove replicators' head LVs first */
+		dm_list_iterate_items(rsite, &lv->rsites) {
+			if (rsite->site_index != 0)
+				continue;
+			dm_list_iterate_items(rdev, &rsite->rdevices)
+				if (!lv_remove_with_dependencies(cmd, rdev->lv,
+								 force, level + 1))
+					return_0;
+		}
+	}
+
 	if (lv_is_origin(lv)) {
 		/* remove snapshot LVs first */
 		dm_list_iterate_safe(snh, snht, &lv->snapshot_segs) {
@@ -2998,6 +3040,7 @@ int lv_create_single(struct volume_group *vg,
 	struct logical_volume *lv, *org = NULL;
 	int origin_active = 0;
 	struct lvinfo info;
+	struct logical_volume *replicator;
 
 	if (lp->lv_name && find_lv_in_vg(vg, lp->lv_name)) {
 		log_error("Logical volume \"%s\" already exists in "
@@ -3118,6 +3161,13 @@ int lv_create_single(struct volume_group *vg,
 		}
 	}
 
+	if (lp->replicator) {
+		if (!vg_prearrange_replicator(vg, lp))
+			return_0;
+		if (lp->rsite.name && !lp->replicator_dev)
+			return 1; /* Do not create any LV this time */
+	}
+
 	if (!lp->extents) {
 		log_error("Unable to create new logical volume with no extents");
 		return 0;
@@ -3169,6 +3219,19 @@ int lv_create_single(struct volume_group *vg,
 		}
 	}
 
+	if (lp->replicator_dev) {
+		init_replicator_in_sync(lp->nosync);
+
+		if (lp->nosync) {
+			log_error("FIXME: Unsupported.");
+			return 0;
+
+			log_warn("WARNING: New replicator won't be synchronised. "
+				  "Don't read what you didn't write!");
+			status |= REPLICATOR_NOTSYNCED;
+		}
+	}
+
 	if (!(lv = lv_create_empty(lp->lv_name ? lp->lv_name : "lvol%d", NULL,
 				   status, lp->alloc, vg)))
 		return_0;
@@ -3225,6 +3288,12 @@ int lv_create_single(struct volume_group *vg,
 				  "exception store.");
 			goto revert_new_lv;
 		}
+	} else if (lp->replicator_dev || lp->replicator) {
+		if (!activate_lv_excl(cmd, lv)) {
+			log_error("Aborting. Failed to activate replicator "
+				  "device.");
+			goto revert_new_lv;
+		}
 	} else if (!activate_lv(cmd, lv)) {
 		if (lp->zero) {
 			log_error("Aborting. Failed to activate new LV to wipe "
@@ -3240,10 +3309,65 @@ int lv_create_single(struct volume_group *vg,
 	else if (!set_lv(cmd, lv, UINT64_C(0), 0)) {
 		log_error("Aborting. Failed to wipe %s.",
 			  lp->snapshot ? "snapshot exception store" :
-					 "start of new LV");
+			  lp->replicator ? "replicator backing store" :
+					   "start of new LV");
 		goto deactivate_and_revert_new_lv;
 	}
 
+	if (!lp->replicator_dev && lp->replicator) {
+		if (!deactivate_lv(cmd, lv)) {
+			log_error("Aborting. Couldn't deactivate replicator log."
+				  " Manual intervention required.");
+			return 0;
+		}
+		if (!vg_add_replicator(lv, lp->rlog_type, lp->region_size)) {
+			log_error("Could not create replicator.");
+			goto revert_new_lv;
+		}
+		/* store vg on disk(s) */
+		if (!vg_write(vg) || !vg_commit(vg))
+			return_0;
+	}
+
+	if (lp->replicator_dev) {
+		if (!lp->replicator) {
+			log_error("Replicator is not specified.");
+			return 0;
+		}
+		if (!deactivate_lv(cmd, lv)) {
+			log_error("Aborting. Could not deactivate new LV.");
+			return 0;
+		}
+
+		if (!(replicator = find_lv(vg, lp->replicator))) {
+			log_error("Could not find replicator.");
+			goto revert_new_lv;
+		}
+
+		if (!lv_add_replicator_dev(replicator, lv)) {
+			log_error("Could not insert replicator device to replicator.");
+			goto revert_new_lv;
+		}
+
+		/* store vg on disk(s) */
+		if (!vg_write(vg))
+			return_0;
+
+		if (!suspend_lv(cmd, replicator)) {
+			log_error("Failed to suspend replicator %s", replicator->name);
+			vg_revert(vg);
+			return 0;
+		}
+
+		if (!vg_commit(vg))
+			return_0;
+
+		if (!resume_lv(cmd, replicator)) {
+			log_error("Problem reactivating replicator %s", replicator->name);
+			return 0;
+		}
+	}
+
 	if (lp->snapshot) {
 		/* Reset permission after zeroing */
 		if (!(lp->permission & LVM_WRITE))
-- 
1.7.1.1



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

* [PATCH 18/22] Replicator: lvcreate implementation
  2010-07-07 12:34 [PATCH 00/22] Replicator 100707 Zdenek Kabelac
                   ` (16 preceding siblings ...)
  2010-07-07 12:34 ` [PATCH 17/22] Replicator: lv_manip - create replicator Zdenek Kabelac
@ 2010-07-07 12:34 ` Zdenek Kabelac
  2010-07-07 12:34 ` [PATCH 19/22] Replicator: man page update for lvcreate Zdenek Kabelac
                   ` (3 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2010-07-07 12:34 UTC (permalink / raw)
  To: lvm-devel

Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
 tools/commands.h |    9 ++++
 tools/lvcreate.c |  133 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 139 insertions(+), 3 deletions(-)

diff --git a/tools/commands.h b/tools/commands.h
index 2b34933..7966cff 100644
--- a/tools/commands.h
+++ b/tools/commands.h
@@ -165,6 +165,12 @@ xx(lvcreate,
    "\t[-p|--permission {r|rw}]\n"
    "\t[-r|--readahead ReadAheadSectors|auto|none]\n"
    "\t[-R|--regionsize MirrorLogRegionSize]\n"
+   "\t[--replicator [ReplicatorName] [--replicatorlogtype ringbuffer]\n"
+   "\t[{--replicatorsynclog {disk|core}|--corelog}]\n"
+   "\t[--site LocalSiteName [--sitemode {sync|warn|stall|drop|fail}]\n"
+   "\t  [--remotevg RemoteVGName] [{--fallbehinddata Size[bBsSkKmMgG]|\n"
+   "\t    --fallbehindios IOCount|--fallbehindtimeout Secs}]]\n"
+   "\t[--replicatordev]\n"
    "\t[-t|--test]\n"
    "\t[--type VolumeType]\n"
    "\t[-v|--verbose]\n"
@@ -203,6 +209,9 @@ xx(lvcreate,
    mirrorlog_ARG, mirrors_ARG, monitor_ARG, name_ARG, nosync_ARG, noudevsync_ARG,
    permission_ARG, persistent_ARG, readahead_ARG, regionsize_ARG, size_ARG,
    snapshot_ARG, stripes_ARG, stripesize_ARG, test_ARG, type_ARG,
+   replicator_ARG, replicatordev_ARG, replicatorlogtype_ARG,
+   remotevg_ARG, site_ARG, sitemode_ARG,
+   fallbehinddata_ARG, fallbehindios_ARG, fallbehindtimeout_ARG,
    virtualoriginsize_ARG, virtualsize_ARG, zero_ARG)
 
 xx(lvdisplay,
diff --git a/tools/lvcreate.c b/tools/lvcreate.c
index 9e167aa..0a605ef 100644
--- a/tools/lvcreate.c
+++ b/tools/lvcreate.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
- * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved.
  *
  * This file is part of LVM2.
  *
@@ -60,7 +60,10 @@ static int _lvcreate_name_params(struct lvcreate_params *lp,
 		 * environment.
 		 */
 		if (!argc) {
-			if (!(lp->vg_name = extract_vgname(cmd, lp->lv_name))) {
+			if (!(lp->vg_name = extract_vgname(cmd, lp->lv_name)) &&
+			    /* try to detect vg name from --replicator arg */
+			    (lp->replicator &&
+			     !(lp->vg_name = extract_vgname(cmd, lp->replicator)))) {
 				log_error("Please provide a volume group name");
 				return 0;
 			}
@@ -73,6 +76,11 @@ static int _lvcreate_name_params(struct lvcreate_params *lp,
 				return 0;
 			}
 
+			if (!lp->lv_name &&
+			    !lp->replicator_dev &&
+			    lp->replicator &&
+			    strlen(lp->replicator))
+				lp->lv_name = lp->replicator;
 			/*
 			 * Ensure lv_name doesn't contain a
 			 * different VG.
@@ -116,6 +124,20 @@ static int _lvcreate_name_params(struct lvcreate_params *lp,
 		}
 	}
 
+	if (lp->replicator) {
+		if ((ptr = strrchr(lp->replicator, '/')))
+			lp->replicator = ptr + 1;
+
+		if (!apply_lvname_restrictions(lp->replicator))
+			return_0;
+
+		if (!validate_name(lp->replicator)) {
+			log_error("Logical volume name \"%s\" is invalid",
+				  lp->replicator);
+			return 0;
+		}
+	}
+
 	return 1;
 }
 
@@ -315,7 +337,81 @@ static int _read_mirror_params(struct lvcreate_params *lp,
 	}
 
 	if (!_validate_mirror_params(cmd, lp))
+		return_0;
+
+	return 1;
+}
+
+static int _read_replicator_params(struct lvcreate_params *lp,
+				   struct cmd_context *cmd)
+{
+	int region_size;
+	const char *replicatorsynclog;
+	int corelog = arg_count(cmd, corelog_ARG);
+	int changed;
+
+	if (arg_count(cmd, sitemode_ARG)) {
+		log_error("FIXME: Sorry, sitemode parameter is not yet supported.");
+		return 0;
+	}
+
+	replicatorsynclog = arg_str_value(cmd, replicatorsynclog_ARG,
+					  corelog ? "core" : DEFAULT_REPLICATOR_SYNCLOG);
+
+	if (strcmp("core", replicatorsynclog) && corelog) {
+		log_error("Please use only one of --replicatorlog or --corelog");
+		return 0;
+	}
+
+	if (!strcmp("disk", replicatorsynclog))
+		lp->log_count = 1;
+	else if (!strcmp("core", replicatorsynclog))
+		lp->log_count = 0;
+	else {
+		log_error("Unknown replicatorsynclog type: %s", replicatorsynclog);
 		return 0;
+	}
+
+	log_verbose("Setting sync logging type to %s", replicatorsynclog);
+	if (arg_count(cmd, regionsize_ARG)) {
+		if (arg_sign_value(cmd, regionsize_ARG, 0) == SIGN_MINUS) {
+			log_error("Negative regionsize is invalid.");
+			return 0;
+		}
+		lp->region_size = arg_uint_value(cmd, regionsize_ARG, 0);
+	} else {
+		region_size = 2 * find_config_tree_int(cmd,
+						       "activation/replicator_region_size",
+						       DEFAULT_REPLICATOR_REGION_SIZE);
+		if (region_size < 0) {
+			log_error("Negative replicator_region_size in configuration "
+				  "file is invalid.");
+			return 0;
+		}
+		lp->region_size = region_size;
+	}
+
+	if (!_validate_mirror_params(cmd, lp)) /* reuse for mirror's region_size */
+		return 0;
+
+	lp->rlog_type = arg_str_value(cmd, replicatorlogtype_ARG,
+				      DEFAULT_REPLICATOR_LOG_TYPE);
+
+	if (strcmp(lp->rlog_type, DEFAULT_REPLICATOR_LOG_TYPE)) {
+		log_error("Unsupported replicator log type %s", lp->rlog_type);
+		return 0;
+	}
+
+	if (arg_count(cmd, remotevg_ARG))
+		lp->rsite.vg_name = arg_str_value(cmd, remotevg_ARG, NULL);
+
+	if (arg_count(cmd, site_ARG))
+		lp->rsite.name = arg_str_value(cmd, site_ARG,
+					       DEFAULT_REPLICATOR_LOCAL_SITE_NAME);
+
+	lp->rsite.op_mode = DM_REPLICATOR_SYNC;
+	if (!get_replicator_site_params(cmd, &lp->rsite, &changed))
+		return_0;
 
 	return 1;
 }
@@ -327,6 +423,7 @@ static int _lvcreate_params(struct lvcreate_params *lp,
 {
 	int contiguous;
 	unsigned pagesize;
+	int i;
 
 	memset(lp, 0, sizeof(*lp));
 	memset(lcp, 0, sizeof(*lcp));
@@ -346,6 +443,12 @@ 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 = arg_str_value(cmd, replicator_ARG, "");
+
+	if (seg_is_replicator_dev(lp) || arg_count(cmd, replicatordev_ARG))
+		lp->replicator_dev = 1;
+
 	if (arg_count(cmd, mirrors_ARG)) {
 		lp->mirrors = arg_uint_value(cmd, mirrors_ARG, 0) + 1;
 		if (lp->mirrors == 1)
@@ -383,7 +486,7 @@ static int _lvcreate_params(struct lvcreate_params *lp,
 		}
 	}
 
-	if (lp->mirrors > 1) {
+	if (lp->mirrors > 1 || lp->replicator) {
 		if (lp->snapshot) {
 			log_error("mirrors and snapshots are currently "
 				  "incompatible");
@@ -409,6 +512,29 @@ static int _lvcreate_params(struct lvcreate_params *lp,
 		}
 	}
 
+	if (!lp->replicator) {
+		static const struct {
+			const char str[20]; // carefull
+			int argname;
+		} repargs[] = {
+			{ "fallbehinddata", fallbehinddata_ARG },
+			{ "fallbehindios", fallbehindios_ARG },
+			{ "fallbehindtimeout", fallbehindtimeout_ARG },
+			{ "remotevg", remotevg_ARG },
+			{ "replicatorlogtype", replicatorlogtype_ARG },
+			{ "replicatorsynclog", replicatorsynclog_ARG },
+			{ "site", site_ARG },
+			{ "sitemode", sitemode_ARG }
+		};
+
+		for (i = 0; i < sizeof(repargs)/sizeof(repargs[0]); ++i)
+			if (arg_count(cmd, repargs[i].argname)) {
+				log_error("--%s is only available "
+					  "with replicators.", repargs[i].str);
+				return 0;
+			}
+	}
+
 	if (activation() && lp->segtype->ops->target_present &&
 	    !lp->segtype->ops->target_present(cmd, NULL, NULL)) {
 		log_error("%s: Required device-mapper target(s) not "
@@ -423,6 +549,7 @@ static int _lvcreate_params(struct lvcreate_params *lp,
 	if (!_lvcreate_name_params(lp, cmd, &argc, &argv) ||
 	    !_read_size_params(lp, lcp, cmd) ||
 	    !get_stripe_params(cmd, &lp->stripes, &lp->stripe_size) ||
+	    !_read_replicator_params(lp, cmd) ||
 	    !_read_mirror_params(lp, cmd))
 		return_0;
 
-- 
1.7.1.1



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

* [PATCH 19/22] Replicator: man page update for lvcreate
  2010-07-07 12:34 [PATCH 00/22] Replicator 100707 Zdenek Kabelac
                   ` (17 preceding siblings ...)
  2010-07-07 12:34 ` [PATCH 18/22] Replicator: lvcreate implementation Zdenek Kabelac
@ 2010-07-07 12:34 ` Zdenek Kabelac
  2010-07-07 12:34 ` [PATCH 20/22] Replicator: lvchange implementation Zdenek Kabelac
                   ` (2 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2010-07-07 12:34 UTC (permalink / raw)
  To: lvm-devel

Update man page to cover basic usage of lvcreate

Current descriptions shows how to create replicator,
add site, add replicated device.

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

diff --git a/man/lvcreate.8.in b/man/lvcreate.8.in
index 0d0976f..eecedf7 100644
--- a/man/lvcreate.8.in
+++ b/man/lvcreate.8.in
@@ -36,6 +36,27 @@ VolumeGroupName [PhysicalVolumePath[:PE[-PE]]...]
 OriginalLogicalVolumePath | 
 [\-s|\-\-snapshot]
 VolumeGroupName \-\-virtualsize VirtualSize}
+.br
+
+.br
+.B lvcreate
+\-\-replicator [ReplicatorName[Path]]
+[\-\-replicatordev]
+{\-l|\-\-extents LogicalExtentsNumber[%{VG|FREE|ORIGIN}] |
+ \-L|\-\-size LogicalVolumeSize[bBsSkKmMgGtTpPeE]}
+[\-\-nosync]
+[\-\-replicatorlogtype ReplicatorLogType]
+{[\-\-replicatorsynclog {disk|core}] | [\-\-corelog]}
+[\-R|\-\-regionsize ReplicatorSyncLogRegionSize]]
+[\-\-site SiteName [\-\-sitemode {sync|warn|stall|drop|fail}]
+{[\-\-fallbehinddata Size[bBsSkKmMgGtTpPeE]] |
+[\-\-fallbehindios  IOS] |
+[\-\-fallbehindtimeout secs]}
+[\-\-remotevg RemoteVolumeGroupName]]
+\-n|\-\-name ReplicatorName
+VolumeGroupName
+.br
+
 .SH DESCRIPTION
 lvcreate creates a new logical volume in a volume group ( see
 .B vgcreate(8), vgchange(8)
@@ -52,6 +73,8 @@ extents will be restricted to these volumes.
 .br
 The second form supports the creation of snapshot logical volumes which 
 keep the contents of the original logical volume for backup purposes.
+.br
+The third form supports the creation of replicated devices.
 .SH OPTIONS
 See \fBlvm\fP for common options.
 .TP
@@ -120,6 +143,40 @@ device is activated, for example, after every reboot.  Using "mirrored"
 will create a persistent log that is itself mirrored.
 
 The optional argument --corelog is equivalent to --mirrorlog core.
+.TP
+.I \-\-replicator
+Creates empty replicator logical volume. (see \fBlvchange\fP(8)) for
+options, how to customize created replicator LV.
+Specifying optional argument --nosync will cause the creation
+of the replicator to skip the initial resynchronization. Any data written
+afterwards will be replicated, but the original content will not be
+copied.  This is useful for skipping a potentially long and resource
+intensive initial sync of an empty device.  Currrently this flag is not
+supported.
+
+The optional argument --replicatorsynclog specifies the type of synclog to be
+used. The default is disk, which is persistent and requires a small amount of
+storage space. Using core means the replicator is regenerated by copying the
+data from the first device again each time the device is activated, for
+example, after every reboot.
+
+The optional argument --replicatorlogtype specifies type of the backing store
+log. The default and currently the only valid and supported type is
+\fBringbuffer\fP.
+
+The optional argument --site creates \fIsite\fP in replicator. Site could have
+operation mode {sync|warn|stall|drop|fail}. For asynchronous modes one
+of the following fall behind parameters must be specified: --fallbehinddata,
+--fallbehindios, --fallbehindtimeout (see \fBlvchange\fP(8)).
+For remote sites --remotevg specifies the name of
+the remote volume group. Note: current implementation expects
+that any remote volume group contains prepared logical volumes
+with the same size and name as the local replicated logical volumes.
+
+.TP
+.I \-\-replicatordev
+Creates empty replicated logical volume in the local site
+of given Replicator.
 
 .TP
 .I \-n, \-\-name LogicalVolumeName
@@ -246,10 +303,29 @@ under 100MB of actual data on it.
 creates a linear logical volume "vg00/lvol1" using physical extents
 /dev/sda:0-7 and /dev/sdb:0-7 for allocation of extents.
 
+"lvcreate --replicator -L 1G -n rep0 vg00"
+.br
+creates a replicator "vg00/rep0" and hidden replicator backing store device
+"vg00/rep0_rlog" of size 1G.
+
+"lvcreate --site Remote --remotevg remotevg00 --fallbehinddata 100M
+--replicator vg00/rep0"
+.br
+creates the remote site named Remote in replicator "vg00/rep0"
+that uses remote volume group "remotevg00" and could get upto 100MiB
+asynchronous behind replicated volume.
+Current implementation needs remote LVs created by hand
+in the remote volume group "remotevg00".
+
+"lvcreate --replicatordev -n lvol1 -L 64M --replicator vg00/rep0"
+.br
+creates a replicated device named "vg00/lvol1" of size 64M attached to
+the local site in the replicator "vg00/rep0".
 
 .SH SEE ALSO
 .BR lvm (8), 
 .BR vgcreate (8), 
+.BR lvchange (8),
 .BR lvremove (8), 
 .BR lvrename (8)
 .BR lvextend (8), 
-- 
1.7.1.1



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

* [PATCH 20/22] Replicator: lvchange implementation
  2010-07-07 12:34 [PATCH 00/22] Replicator 100707 Zdenek Kabelac
                   ` (18 preceding siblings ...)
  2010-07-07 12:34 ` [PATCH 19/22] Replicator: man page update for lvcreate Zdenek Kabelac
@ 2010-07-07 12:34 ` Zdenek Kabelac
  2010-07-07 12:34 ` [PATCH 21/22] Replicator: man page update for lvchange Zdenek Kabelac
  2010-07-07 12:34 ` [PATCH 22/22] Replicator: lvremove implementation Zdenek Kabelac
  21 siblings, 0 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2010-07-07 12:34 UTC (permalink / raw)
  To: lvm-devel

Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
 tools/commands.h |    6 ++
 tools/lvchange.c |  195 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 196 insertions(+), 5 deletions(-)

diff --git a/tools/commands.h b/tools/commands.h
index 7966cff..9e27ad9 100644
--- a/tools/commands.h
+++ b/tools/commands.h
@@ -80,6 +80,10 @@ xx(lvchange,
    "\t[-r|--readahead ReadAheadSectors|auto|none]\n"
    "\t[--refresh]\n"
    "\t[--resync]\n"
+   "\t[--replicator ReplicatorName]\n"
+   "\t[--site SiteName [--sitemode {sync|warn|stall|drop|fail}]\n"
+   "\t  [{--fallbehinddata Size[bBsSkKmMgG]|\n"
+   "\t    --fallbehindios IOCount|--fallbehindtimeout Secs}]]]\n"
    "\t[--sysinit]\n"
    "\t[-t|--test]\n"
    "\t[-v|--verbose]\n"
@@ -91,6 +95,8 @@ xx(lvchange,
    ignorelockingfailure_ARG, ignoremonitoring_ARG, major_ARG, minor_ARG,
    monitor_ARG, noudevsync_ARG, partial_ARG, permission_ARG, persistent_ARG,
    poll_ARG, readahead_ARG, resync_ARG, refresh_ARG, addtag_ARG, deltag_ARG,
+   fallbehinddata_ARG, fallbehindios_ARG, fallbehindtimeout_ARG,
+   replicator_ARG, replicatorlogtype_ARG, remotevg_ARG, site_ARG, sitemode_ARG,
    sysinit_ARG, test_ARG, yes_ARG)
 
 xx(lvconvert,
diff --git a/tools/lvchange.c b/tools/lvchange.c
index 126e61a..4d43db4 100644
--- a/tools/lvchange.c
+++ b/tools/lvchange.c
@@ -15,6 +15,11 @@
 
 #include "tools.h"
 
+/* Internal data storage used for process_each_lv callbacks */
+struct lvchange_data {
+	struct dm_list activate_names;
+};
+
 static int lvchange_permission(struct cmd_context *cmd,
 			       struct logical_volume *lv)
 {
@@ -514,12 +519,156 @@ static int lvchange_tag(struct cmd_context *cmd, struct logical_volume *lv,
 	return 1;
 }
 
+static int lvchange_site(struct cmd_context *cmd, struct logical_volume *lv,
+			 int *skip_available)
+{
+	struct lvinfo info;
+	struct replicator_site nrsite;
+	struct logical_volume *replicator;
+	struct replicator_site *rsite;
+	const char *replicator_name, *trname;
+	int active;
+	int changed = 0;
+
+	replicator = (lv_is_replicator(lv)) ? lv : first_seg(lv)->replicator;
+	rsite = find_local_site_in_replicator(replicator);
+
+	if (arg_count(cmd, replicator_ARG)) {
+		if (lv == replicator) {
+			log_error("Replicator specified twice.");
+			return 0;
+		}
+		replicator_name = arg_str_value(cmd, replicator_ARG, "");
+		/* Strip the volume group from the replicator */
+		if ((trname = strrchr(replicator_name, (int)'/')))
+			replicator_name = trname + 1;
+		/* Skip different replicator */
+		if (strcmp(replicator->name, replicator_name)) {
+			log_debug("Replicator %s/%s name does not match %s.",
+				  replicator->name, lv->name, replicator_name);
+			return 2;
+		}
+	}
+
+	if (arg_count(cmd, site_ARG)) {
+		nrsite.name = arg_str_value(cmd, site_ARG,
+					    DEFAULT_REPLICATOR_LOCAL_SITE_NAME);
+
+		/* Skip different replicator */
+		if (!(rsite = find_site_in_replicator(replicator, nrsite.name))) {
+			log_debug("Replicator %s/%s does not have site %s.",
+				  replicator->name, lv->name, nrsite.name);
+			return 2;
+		}
+	}
+
+	if (arg_count(cmd, remotevg_ARG)) {
+		log_error("Cannot change remotevg.");
+		return 0;
+	}
+
+	if (arg_count(cmd, replicatorlogtype_ARG)) {
+		log_error("Cannot change replicator log type.");
+		return 0;
+	}
+
+	memset(&nrsite, 0, sizeof(nrsite));
+	nrsite.state = NUM_REPLICATOR_STATE; /* invalid state */
+	if (arg_count(cmd, available_ARG)) {
+		if (rsite->site_index != 0) {
+			log_error("Cannot change state of remote site %s/%s.",
+				  replicator->name, rsite->name);
+			return 0;
+		}
+		switch (arg_uint_value(cmd, available_ARG, 0)) {
+		case CHANGE_ALY:
+		case CHANGE_AE:
+		case CHANGE_AY:
+			nrsite.state = REPLICATOR_STATE_ACTIVE;
+			break;
+		default:
+			nrsite.state = REPLICATOR_STATE_PASSIVE;
+		}
+
+		if (rsite->state != nrsite.state) {
+			rsite->state = nrsite.state;
+			changed++;
+		}
+	}
+
+	if (!get_replicator_site_params(cmd, rsite, &changed))
+		return_0;
+
+	if (!changed)
+		return 2;
+
+	/* Replicator heads needs to be updated */
+	if (lv == replicator)
+		lv = first_replicator_dev(replicator);
+
+	active = (lv_info(cmd, lv, &info, 0, 0) && info.exists);
+
+	if (active && !arg_count(cmd, force_ARG) &&
+	    yes_no_prompt("Replicator LVs %s will be deactivated. "
+			  "Continue? [y/n]: ",
+			  replicator->name) == 'n') {
+		log_error("%s site not changed.", rsite->name);
+		return 0;
+	}
+
+	if (active) {
+		/* FIXME: some cases may require synchronization of data from log */
+		if (arg_count(cmd, available_ARG) &&
+		    (nrsite.state == REPLICATOR_STATE_PASSIVE)) {
+			if (!lvchange_availability(cmd, lv))
+				return_0;
+			*skip_available = 1; /* skip later change of available */
+		} else if (!deactivate_lv(cmd, lv)) {
+			log_error("Unable to deactivate replicator %s.",
+				  replicator->name);
+			return 0;
+		}
+	}
+
+	if (!vg_write(lv->vg) || !vg_commit(lv->vg))
+		return_0;
+
+	backup(lv->vg);
+
+	if (active && !arg_count(cmd, available_ARG) &&
+	    !activate_lv(cmd, lv)) {
+		log_debug("Retry to activate replicator %s.",
+			  replicator->name);
+		return 0;
+	}
+
+	return 1;
+}
+
 static int lvchange_single(struct cmd_context *cmd, struct logical_volume *lv,
-			   void *handle __attribute((unused)))
+			   void *handle)
 {
 	int doit = 0, docmds = 0;
 	int dmeventd_mode, archived = 0;
 	struct logical_volume *origin;
+	struct lvchange_data *lvc_data = handle;
+	int skip_available = 0;
+
+	struct str_list *sl;
+	dm_list_iterate_items(sl, &lvc_data->activate_names)
+		log_error("LIST %s  %p", sl->str, sl->str);
+
+	if (str_list_match_item(&lvc_data->activate_names, lv->name)) {
+		if (lv_is_replicator(lv))
+			lv = first_replicator_dev(lv);
+
+		if (!activate_lv(cmd, lv)) {
+			log_error("Reactivation of replicator %s failed.",
+				  lv->rdevice->rsite->replicator->name);
+			return ECMD_FAILED;
+		}
+		return ECMD_PROCESSED;
+	}
 
 	if (!(lv->vg->status & LVM_WRITE) &&
 	    (arg_count(cmd, contiguous_ARG) || arg_count(cmd, permission_ARG) ||
@@ -569,7 +718,8 @@ static int lvchange_single(struct cmd_context *cmd, struct logical_volume *lv,
 	    lv_is_virtual_origin(origin = origin_from_cow(lv)))
 		lv = origin;
 
-	if (!(lv_is_visible(lv)) && !lv_is_virtual_origin(lv)) {
+	if (!lv_is_visible(lv) && !lv_is_virtual_origin(lv) &&
+	    !lv_is_replicator(lv)) {
 		log_error("Unable to change internal LV %s directly",
 			  lv->name);
 		return ECMD_FAILED;
@@ -663,6 +813,21 @@ static int lvchange_single(struct cmd_context *cmd, struct logical_volume *lv,
 		docmds++;
 	}
 
+        /* Update replicator paramaters */
+	if ((lv_is_replicator(lv) || lv_is_replicator_dev(lv)) &&
+	    (arg_count(cmd, site_ARG) || arg_count(cmd, replicator_ARG))) {
+		if (!archived && !archive(lv->vg)) {
+			stack;
+			return ECMD_FAILED;
+		}
+		archived = 1;
+		switch (lvchange_site(cmd, lv, &skip_available)) {
+		case 0: docmds++; break;
+		case 1: docmds++; doit++; break;
+		default: /* 2 = ok, but nothing changed */;
+		}
+	}
+
 	if (doit)
 		log_print("Logical volume \"%s\" changed", lv->name);
 
@@ -673,7 +838,7 @@ static int lvchange_single(struct cmd_context *cmd, struct logical_volume *lv,
 		}
 
 	/* availability change */
-	if (arg_count(cmd, available_ARG)) {
+	if (!skip_available && arg_count(cmd, available_ARG)) {
 		if (!lvchange_availability(cmd, lv)) {
 			stack;
 			return ECMD_FAILED;
@@ -705,7 +870,18 @@ static int lvchange_single(struct cmd_context *cmd, struct logical_volume *lv,
 	}
 
 	if (doit != docmds) {
-		stack;
+		if (lv->vg->cmd_missing_vgs) {
+			if (!str_list_add(lv->vg->cmd->mem,
+					  &lvc_data->activate_names,
+					  lv->name)) {
+				log_error("Allocation of lv name failed.");
+				lv->vg->cmd_missing_vgs = 0;
+			}
+		} else
+			stack;
+		/* Note: using cmd mempool to live across vg lifetime */
+		/* return ECMD_FAILED for reprocessing */
+
 		return ECMD_FAILED;
 	}
 
@@ -718,8 +894,16 @@ int lvchange(struct cmd_context *cmd, int argc, char **argv)
 		arg_count(cmd, contiguous_ARG) || arg_count(cmd, permission_ARG) ||
 		arg_count(cmd, readahead_ARG) || arg_count(cmd, persistent_ARG) ||
 		arg_count(cmd, addtag_ARG) || arg_count(cmd, deltag_ARG) ||
+		arg_count(cmd, replicator_ARG) || arg_count(cmd, site_ARG) ||
+		arg_count(cmd, remotevg_ARG) || arg_count(cmd, replicatorlogtype_ARG) ||
+		arg_count(cmd, fallbehinddata_ARG) || arg_count(cmd, fallbehindios_ARG) ||
+		arg_count(cmd, fallbehindtimeout_ARG) || arg_count(cmd, sitemode_ARG) ||
 		arg_count(cmd, resync_ARG) || arg_count(cmd, alloc_ARG);
 
+	struct lvchange_data lvc_data;
+
+	dm_list_init(&lvc_data.activate_names);
+
 	if (!update &&
             !arg_count(cmd, available_ARG) && !arg_count(cmd, refresh_ARG) &&
             !arg_count(cmd, monitor_ARG) && !arg_count(cmd, poll_ARG) &&
@@ -767,7 +951,8 @@ int lvchange(struct cmd_context *cmd, int argc, char **argv)
 		return EINVALID_CMD_LINE;
 	}
 
+	log_error("LVCHANGE DATA  %d ", argc);
 	return process_each_lv(cmd, argc, argv,
-			       update ? READ_FOR_UPDATE : 0, NULL,
+			       update ? READ_FOR_UPDATE : 0, &lvc_data,
 			       &lvchange_single);
 }
-- 
1.7.1.1



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

* [PATCH 21/22] Replicator: man page update for lvchange
  2010-07-07 12:34 [PATCH 00/22] Replicator 100707 Zdenek Kabelac
                   ` (19 preceding siblings ...)
  2010-07-07 12:34 ` [PATCH 20/22] Replicator: lvchange implementation Zdenek Kabelac
@ 2010-07-07 12:34 ` Zdenek Kabelac
  2010-07-07 12:34 ` [PATCH 22/22] Replicator: lvremove implementation Zdenek Kabelac
  21 siblings, 0 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2010-07-07 12:34 UTC (permalink / raw)
  To: lvm-devel

Update lvchange man page to cover basic usability commands.

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

diff --git a/man/lvchange.8.in b/man/lvchange.8.in
index e269802..6899613 100644
--- a/man/lvchange.8.in
+++ b/man/lvchange.8.in
@@ -7,6 +7,11 @@ lvchange \- change attributes of a logical volume
 [\-A|\-\-autobackup y|n] [\-a|\-\-available y|n|ey|en|ly|ln]
 [\-\-alloc AllocationPolicy]
 [\-C|\-\-contiguous y|n] [\-d|\-\-debug] [\-\-deltag Tag]
+[[\-\-site Site]
+[\-\-sitemode [sync|warn|stall|drop|fail]
+{[\-\-fallbehinddata Size[bBsSkKmMgGtTpPeE]] |
+[\-\-fallbehindios  IOS] |
+[\-\-fallbehindtimeout sec]}]
 [\-\-resync]
 [\-h|\-?|\-\-help]
 [\-\-ignorelockingfailure]
@@ -112,10 +117,36 @@ If the logical volume is active, reload its metadata.
 This is not necessary in normal operation, but may be useful
 if something has gone wrong or if you're doing clustering 
 manually without a clustered lock manager.
+.TP
+.I \-\-fallbehinddata
+How many data could get replicator behind. Cannot be mixed
+with --fallbehindios or --fallbehindtimeout.
+.TP
+.I \-\-fallbehindios
+How many io operation could be queued in replicator backing store device.
+Cannot be mixed with --fallbehinddata or --fallbehindtimeout.
+.TP
+.I \-\-fallbehindtimeout
+How many seconds could be replicator behind actual data. Cannot be mixed
+with --fallbehinddata or --fallbehindios.
+.TP
+.I \-\-sitemode
+Select replication mode. Default is Warn.
+Sync is synchronous mode. Warn,Stall,Drop,Fail are asynchronous modes.
+Warn issues warning when remote site is switched to sync log.
+Stall stalls replicator until remote site is back in range.
+Drop drops whole remote site, if it get too behind.
+Fail whole replicator fails is remote sites gets too behind.
+Local site works usually in stall mode. There is no synclog for local
+replicated volumes.
+.TP
 .SH Examples
 "lvchange -pr vg00/lvol1" changes the permission on 
 volume lvol1 in volume group vg00 to be read-only.
 
+"lvchange --site Berlin -ay vg00/L1"
+marks the local site Berlin for LV "vg00/L1" as active.
+
 .SH SEE ALSO
 .BR lvm (8), 
 .BR lvcreate (8),
-- 
1.7.1.1



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

* [PATCH 22/22] Replicator: lvremove implementation
  2010-07-07 12:34 [PATCH 00/22] Replicator 100707 Zdenek Kabelac
                   ` (20 preceding siblings ...)
  2010-07-07 12:34 ` [PATCH 21/22] Replicator: man page update for lvchange Zdenek Kabelac
@ 2010-07-07 12:34 ` Zdenek Kabelac
  21 siblings, 0 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2010-07-07 12:34 UTC (permalink / raw)
  To: lvm-devel

Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
 tools/commands.h |    3 ++-
 tools/lvremove.c |   19 ++++++++++++++++++-
 2 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/tools/commands.h b/tools/commands.h
index 9e27ad9..73bede8 100644
--- a/tools/commands.h
+++ b/tools/commands.h
@@ -365,12 +365,13 @@ xx(lvremove,
    "\t[-f|--force]\n"
    "\t[-h|--help]\n"
    "\t[--noudevsync]\n"
+   "\t[--site SiteName]\n"
    "\t[-t|--test]\n"
    "\t[-v|--verbose]\n"
    "\t[--version]" "\n"
    "\tLogicalVolume[Path] [LogicalVolume[Path]...]\n",
 
-   autobackup_ARG, force_ARG, noudevsync_ARG, test_ARG)
+   autobackup_ARG, force_ARG, noudevsync_ARG, site_ARG, test_ARG)
 
 xx(lvrename,
    "Rename a logical volume",
diff --git a/tools/lvremove.c b/tools/lvremove.c
index dbf2f1d..15005c3 100644
--- a/tools/lvremove.c
+++ b/tools/lvremove.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
- * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved.
  *
  * This file is part of LVM2.
  *
@@ -19,6 +19,8 @@ static int lvremove_single(struct cmd_context *cmd, struct logical_volume *lv,
 			   void *handle __attribute((unused)))
 {
 	struct logical_volume *origin;
+	struct logical_volume *replicator;
+	const char *site_name;
 
 	/*
 	 * If this is a sparse device, remove its origin too.
@@ -26,6 +28,21 @@ static int lvremove_single(struct cmd_context *cmd, struct logical_volume *lv,
         if (lv_is_cow(lv) && lv_is_virtual_origin(origin = origin_from_cow(lv)))
                 lv = origin;
 
+	if ((lv_is_replicator_dev(lv) || lv_is_replicator(lv)) &&
+	    arg_count(cmd, site_ARG)) {
+		replicator = lv_is_replicator(lv) ? lv : first_seg(lv)->replicator;
+		site_name = arg_str_value(cmd, site_ARG,
+					  DEFAULT_REPLICATOR_LOCAL_SITE_NAME);
+
+		log_error("REMOVE SITE  %s   of %s", site_name, replicator->name);
+		if (!lv_remove_replicator_site(replicator, site_name)) {
+			stack;
+			return ECMD_FAILED;
+		}
+
+		return ECMD_PROCESSED;
+	}
+
 	if (!lv_remove_with_dependencies(cmd, lv, arg_count(cmd, force_ARG), 0)) {
 		stack;
 		return ECMD_FAILED;
-- 
1.7.1.1



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

end of thread, other threads:[~2010-07-07 12:34 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-07-07 12:34 [PATCH 00/22] Replicator 100707 Zdenek Kabelac
2010-07-07 12:34 ` [PATCH 01/22] Add units to passed parameters data & timeout Use size Zdenek Kabelac
2010-07-07 12:34 ` [PATCH 02/22] Allow the user to not specify a size when creating snapshot Zdenek Kabelac
2010-07-07 12:34 ` [PATCH 03/22] Skip check missing rem.VGs for non-activate locks Zdenek Kabelac
2010-07-07 12:34 ` [PATCH 04/22] Replicator: check for active replicator Zdenek Kabelac
2010-07-07 12:34 ` [PATCH 05/22] Replicator: add reserved names Zdenek Kabelac
2010-07-07 12:34 ` [PATCH 06/22] Replicator: man page update for lvm Zdenek Kabelac
2010-07-07 12:34 ` [PATCH 07/22] Replicator: add _replicator_in_sync Zdenek Kabelac
2010-07-07 12:34 ` [PATCH 08/22] Replicator: add report for replicator targets Zdenek Kabelac
2010-07-07 12:34 ` [PATCH 09/22] Replicator: improve detection of replicator-dev Zdenek Kabelac
2010-07-07 12:34 ` [PATCH 10/22] Replicator: new defaults Zdenek Kabelac
2010-07-07 12:34 ` [PATCH 11/22] Replicator: metadata update Zdenek Kabelac
2010-07-07 12:34 ` [PATCH 12/22] Replicator: replicator_manip changes Zdenek Kabelac
2010-07-07 12:34 ` [PATCH 13/22] Replicator: replicator.c changes Zdenek Kabelac
2010-07-07 12:34 ` [PATCH 14/22] Replicator: add new command option read functions Zdenek Kabelac
2010-07-07 12:34 ` [PATCH 15/22] Replicator: new args Zdenek Kabelac
2010-07-07 12:34 ` [PATCH 16/22] Replicator: read site_params Zdenek Kabelac
2010-07-07 12:34 ` [PATCH 17/22] Replicator: lv_manip - create replicator Zdenek Kabelac
2010-07-07 12:34 ` [PATCH 18/22] Replicator: lvcreate implementation Zdenek Kabelac
2010-07-07 12:34 ` [PATCH 19/22] Replicator: man page update for lvcreate Zdenek Kabelac
2010-07-07 12:34 ` [PATCH 20/22] Replicator: lvchange implementation Zdenek Kabelac
2010-07-07 12:34 ` [PATCH 21/22] Replicator: man page update for lvchange Zdenek Kabelac
2010-07-07 12:34 ` [PATCH 22/22] Replicator: lvremove implementation 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.