* [PATCH 01/13] Replicator: export out_ function for modules
@ 2009-10-05 14:00 Zdenek Kabelac
2009-10-05 14:00 ` [PATCH 02/13] Replicator: add libdm support Zdenek Kabelac
2009-10-07 15:05 ` [PATCH 01/13] Replicator: export out_ function for modules Alasdair G Kergon
0 siblings, 2 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2009-10-05 14:00 UTC (permalink / raw)
To: lvm-devel
Exporting functions out_inc_indent(), out_dec_indent(), out_newline()
for creating indented metadata lines.
Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
lib/format_text/export.c | 19 +++++++++++++++++++
lib/format_text/text_export.h | 4 ++++
2 files changed, 23 insertions(+), 0 deletions(-)
diff --git a/lib/format_text/export.c b/lib/format_text/export.c
index 482eea9..49cf785 100644
--- a/lib/format_text/export.c
+++ b/lib/format_text/export.c
@@ -235,6 +235,25 @@ static int _sectors_to_units(uint64_t sectors, char *buffer, size_t s)
return dm_snprintf(buffer, s, "# %g %s", d, _units[i]) > 0;
}
+/* increment indention level */
+void out_inc_indent(struct formatter *f)
+{
+ _inc_indent(f);
+}
+
+/* decrement indention level */
+void out_dec_indent(struct formatter *f)
+{
+ _dec_indent(f);
+}
+
+/* insert new line */
+int out_newline(struct formatter *f)
+{
+ outnl(f);
+ return 0;
+}
+
/*
* Appends a comment giving a size in more easily
* readable form (eg, 4M instead of 8096).
diff --git a/lib/format_text/text_export.h b/lib/format_text/text_export.h
index 2f2b531..12a8691 100644
--- a/lib/format_text/text_export.h
+++ b/lib/format_text/text_export.h
@@ -34,4 +34,8 @@ int out_text(struct formatter *f, const char *fmt, ...)
int out_areas(struct formatter *f, const struct lv_segment *seg,
const char *type);
+void out_inc_indent(struct formatter *f);
+void out_dec_indent(struct formatter *f);
+int out_newline(struct formatter *f);
+
#endif
--
1.6.5.rc2
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 02/13] Replicator: add libdm support
2009-10-05 14:00 [PATCH 01/13] Replicator: export out_ function for modules Zdenek Kabelac
@ 2009-10-05 14:00 ` Zdenek Kabelac
2009-10-05 14:00 ` [PATCH 03/13] Replicator: add lvm support Zdenek Kabelac
` (2 more replies)
2009-10-07 15:05 ` [PATCH 01/13] Replicator: export out_ function for modules Alasdair G Kergon
1 sibling, 3 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2009-10-05 14:00 UTC (permalink / raw)
To: lvm-devel
Introducing dm_tree_node_add_replicator_target() and
dm_tree_node_add_replicator_dev_target()
Modifing API dm_tree_suspend_children() to support prioritized suspend
and update lvm activation.
Avoid preloading childrens with nonzero activation priority
Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
lib/activate/dev_manager.c | 2 +-
libdm/.exported_symbols | 3 +
libdm/libdevmapper.h | 34 +++++-
libdm/libdm-deptree.c | 296 ++++++++++++++++++++++++++++++++++++++++++--
4 files changed, 323 insertions(+), 12 deletions(-)
diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
index 13cec36..19deab8 100644
--- a/lib/activate/dev_manager.c
+++ b/lib/activate/dev_manager.c
@@ -1221,7 +1221,7 @@ static int _tree_action(struct dev_manager *dm, struct logical_volume *lv, actio
if (!dm->flush_required && (lv->status & MIRRORED) && !(lv->status & PVMOVE))
dm_tree_use_no_flush_suspend(root);
case SUSPEND_WITH_LOCKFS:
- if (!dm_tree_suspend_children(root, dlid, ID_LEN + sizeof(UUID_PREFIX) - 1))
+ if (!dm_tree_suspend_children(root, dlid, ID_LEN + sizeof(UUID_PREFIX) - 1, 0))
goto_out;
break;
case PRELOAD:
diff --git a/libdm/.exported_symbols b/libdm/.exported_symbols
index c357131..5fd81ec 100644
--- a/libdm/.exported_symbols
+++ b/libdm/.exported_symbols
@@ -64,6 +64,7 @@ dm_tree_next_parent
dm_tree_deactivate_children
dm_tree_activate_children
dm_tree_preload_children
+dm_tree_set_priority
dm_tree_suspend_children
dm_tree_children_use_uuid
dm_tree_node_add_snapshot_origin_target
@@ -76,6 +77,8 @@ dm_tree_node_add_crypt_target
dm_tree_node_add_mirror_target
dm_tree_node_add_mirror_target_log
dm_tree_node_add_target_area
+dm_tree_node_add_replicator_target
+dm_tree_node_add_replicator_dev_target
dm_tree_node_set_read_ahead
dm_tree_skip_lockfs
dm_tree_use_no_flush_suspend
diff --git a/libdm/libdevmapper.h b/libdm/libdevmapper.h
index 204372a..4e0103a 100644
--- a/libdm/libdevmapper.h
+++ b/libdm/libdevmapper.h
@@ -341,8 +341,9 @@ int dm_tree_activate_children(struct dm_tree_node *dnode,
* Ignores devices that don't have a uuid starting with uuid_prefix.
*/
int dm_tree_suspend_children(struct dm_tree_node *dnode,
- const char *uuid_prefix,
- size_t uuid_prefix_len);
+ const char *uuid_prefix,
+ size_t uuid_prefix_len,
+ int priority);
/*
* Skip the filesystem sync when suspending.
@@ -421,11 +422,40 @@ int dm_tree_node_add_mirror_target_log(struct dm_tree_node *node,
const char *log_uuid,
unsigned area_count,
uint32_t flags);
+
+int dm_tree_node_add_replicator_target(struct dm_tree_node *node,
+ uint64_t size,
+ const char *rlog_uuid,
+ const char *rlog_type,
+ unsigned site_index,
+ int async_action,
+/* Replicator async action flags */
+#define DM_REPLICATOR_SYNC 0 /* use synchronous replication */
+#define DM_REPLICATOR_WARN 1 /* warn if replicator is slow */
+#define DM_REPLICATOR_STALL 2 /* stall replicator if not fast enough */
+#define DM_REPLICATOR_DROP 3 /* drop legs */
+#define DM_REPLICATOR_FAIL 4 /* fail replicator if slow */
+ uint32_t async_timeout,
+ uint64_t fall_behind_data,
+ uint32_t fall_behind_ios);
+
+int dm_tree_node_add_replicator_dev_target(struct dm_tree_node *node,
+ uint64_t size,
+ const char *replog_uuid, /* replicator-log device */
+ uint64_t rdevice_index,
+ const char *rdev_uuid, /* remove/rimage device name/uuid */
+ unsigned rsite_index,
+ const char *llog_uuid,
+ uint32_t llog_flags, /* Mirror log flags */
+ uint32_t llog_size);
+
int dm_tree_node_add_target_area(struct dm_tree_node *node,
const char *dev_name,
const char *dlid,
uint64_t offset);
+int dm_tree_set_priority(struct dm_tree *dtree, const char *uuid, int priority);
+
/*
* Set readahead (in sectors) after loading the node.
*/
diff --git a/libdm/libdm-deptree.c b/libdm/libdm-deptree.c
index 75fb201..4fc625f 100644
--- a/libdm/libdm-deptree.c
+++ b/libdm/libdm-deptree.c
@@ -33,6 +33,8 @@ enum {
SEG_ERROR,
SEG_LINEAR,
SEG_MIRRORED,
+ SEG_REPLICATOR,
+ SEG_REPLICATOR_DEV,
SEG_SNAPSHOT,
SEG_SNAPSHOT_ORIGIN,
SEG_STRIPED,
@@ -49,6 +51,8 @@ struct {
{ SEG_ERROR, "error" },
{ SEG_LINEAR, "linear" },
{ SEG_MIRRORED, "mirror" },
+ { SEG_REPLICATOR, "replicator" },
+ { SEG_REPLICATOR_DEV, "replicator-dev" },
{ SEG_SNAPSHOT, "snapshot" },
{ SEG_SNAPSHOT_ORIGIN, "snapshot-origin" },
{ SEG_STRIPED, "striped" },
@@ -62,6 +66,23 @@ struct seg_area {
struct dm_tree_node *dev_node;
uint64_t offset;
+
+ unsigned rsite_index; /* Replicator site index */
+ struct dm_tree_node *llog; /* Replicator link log node */
+ uint64_t region_size; /* Replicator link log size */
+ uint32_t flags; /* Replicator link log flags */
+};
+
+/* Replicator-log has a list of sites */
+/* CHECKME: maybe move to seg_area too ?? */
+struct replicator_site {
+ struct dm_list list;
+
+ unsigned rsite_index;
+ int async_action;
+ uint32_t async_timeout;
+ uint32_t fall_behind_ios;
+ uint64_t fall_behind_data;
};
/* Per-segment properties */
@@ -72,8 +93,8 @@ struct load_segment {
uint64_t size;
- unsigned area_count; /* Linear + Striped + Mirrored + Crypt */
- struct dm_list areas; /* Linear + Striped + Mirrored + Crypt */
+ unsigned area_count; /* Linear + Striped + Mirrored + Crypt + Replicator */
+ struct dm_list areas; /* Linear + Striped + Mirrored + Crypt + Replicator */
uint32_t stripe_size; /* Striped */
@@ -82,7 +103,7 @@ struct load_segment {
struct dm_tree_node *cow; /* Snapshot */
struct dm_tree_node *origin; /* Snapshot + Snapshot origin */
- struct dm_tree_node *log; /* Mirror */
+ struct dm_tree_node *log; /* Mirror + Replicator + Replicator-dev */
uint32_t region_size; /* Mirror */
unsigned clustered; /* Mirror */
unsigned mirror_area_count; /* Mirror */
@@ -94,6 +115,12 @@ struct load_segment {
const char *iv; /* Crypt */
uint64_t iv_offset; /* Crypt */
const char *key; /* Crypt */
+
+ const char *rlog_type; /* Replicator */
+ struct dm_list rsites; /* Replicator */
+ unsigned rsite_count; /* Replicator */
+ unsigned rdevice_count; /* Replicator */
+ uint64_t rdevice_index; /* Replicator-dev */
};
/* Per-device properties */
@@ -625,6 +652,18 @@ void dm_tree_node_set_read_ahead(struct dm_tree_node *dnode,
dnode->props.read_ahead_flags = read_ahead_flags;
}
+int dm_tree_set_priority(struct dm_tree *dtree, const char *uuid, int priority)
+{
+ struct dm_tree_node *dnode;
+
+ if ((dnode = dm_tree_find_node_by_uuid(dtree, uuid))) {
+ log_verbose("Setting activation priority %d for %s", priority, dnode->name);
+ dnode->activation_priority = priority;
+ }
+
+ return 1;
+}
+
int dm_tree_add_dev(struct dm_tree *dtree, uint32_t major, uint32_t minor)
{
return _add_dev(dtree, &dtree->root, major, minor) ? 1 : 0;
@@ -1036,8 +1075,9 @@ void dm_tree_use_no_flush_suspend(struct dm_tree_node *dnode)
}
int dm_tree_suspend_children(struct dm_tree_node *dnode,
- const char *uuid_prefix,
- size_t uuid_prefix_len)
+ const char *uuid_prefix,
+ size_t uuid_prefix_len,
+ int priority)
{
void *handle = NULL;
struct dm_tree_node *child = dnode;
@@ -1068,13 +1108,17 @@ int dm_tree_suspend_children(struct dm_tree_node *dnode,
continue;
/* Ensure immediate parents are already suspended */
- if (!_children_suspended(child, 1, uuid_prefix, uuid_prefix_len))
+ if (priority == 0 &&
+ !_children_suspended(child, 1, uuid_prefix, uuid_prefix_len))
continue;
if (!_info_by_dev(dinfo->major, dinfo->minor, 0, &info) ||
!info.exists || info.suspended)
continue;
+ if (child->activation_priority != priority)
+ continue;
+
if (!_suspend_node(name, info.major, info.minor,
child->dtree->skip_lockfs,
child->dtree->no_flush, &newinfo)) {
@@ -1102,7 +1146,7 @@ int dm_tree_suspend_children(struct dm_tree_node *dnode,
continue;
if (dm_tree_node_num_children(child, 0))
- dm_tree_suspend_children(child, uuid_prefix, uuid_prefix_len);
+ dm_tree_suspend_children(child, uuid_prefix, uuid_prefix_len, priority);
}
return 1;
@@ -1270,13 +1314,49 @@ static int _emit_areas_line(struct dm_task *dmt __attribute((unused)),
struct seg_area *area;
char devbuf[DM_FORMAT_DEV_BUFSIZE];
unsigned first_time = 1;
+ const char *logtype;
+ unsigned log_parm_count;
dm_list_iterate_items(area, &seg->areas) {
if (!_build_dev_string(devbuf, sizeof(devbuf), area->dev_node))
return_0;
- EMIT_PARAMS(*pos, "%s%s %" PRIu64, first_time ? "" : " ",
- devbuf, area->offset);
+ switch (seg->type) {
+ case SEG_REPLICATOR_DEV:
+ EMIT_PARAMS(*pos, " %d 1 %s", area->rsite_index, devbuf);
+ if (!first_time) {
+ /* remote devices */
+ log_parm_count = (area->flags & (DM_NOSYNC | DM_FORCESYNC)) ? 2 : 1;
+
+ if (!area->llog) {
+ devbuf[0] = 0; /* only core log parameters */
+ logtype = "core";
+ } else {
+ devbuf[0] = ' '; /* extra space before device name */
+ if (!_build_dev_string(devbuf + 1, sizeof(devbuf) - 1,
+ area->llog))
+ return_0;
+ logtype = "disk";
+ log_parm_count++; /* extra link log device name parameter */
+ }
+
+ EMIT_PARAMS(*pos, " %s %u%s %" PRIu64, logtype,
+ log_parm_count, devbuf, area->region_size);
+
+ logtype = (area->flags & DM_NOSYNC) ?
+ " nosync" : (area->flags & DM_FORCESYNC) ?
+ " sync" : NULL;
+
+ if (logtype)
+ EMIT_PARAMS(*pos, logtype);
+ } else
+ EMIT_PARAMS(*pos, " nolog 0");
+
+ break;
+ default:
+ EMIT_PARAMS(*pos, "%s%s %" PRIu64, first_time ? "" : " ",
+ devbuf, area->offset);
+ }
first_time = 0;
}
@@ -1284,6 +1364,42 @@ static int _emit_areas_line(struct dm_task *dmt __attribute((unused)),
return 1;
}
+static int _replicator_emit_segment_line(const struct load_segment *seg, char *params,
+ size_t paramsize, int *pos)
+{
+ const struct load_segment *rlog_seg;
+ const struct replicator_site *rsite;
+ char rlogbuf[DM_FORMAT_DEV_BUFSIZE];
+ unsigned parm_count;
+
+ if (!seg->log || !_build_dev_string(rlogbuf, sizeof(rlogbuf), seg->log))
+ return_0;
+
+ rlog_seg = dm_list_item(dm_list_last(&seg->log->props.segs),
+ struct load_segment);
+
+ EMIT_PARAMS(*pos, "%s 4 %s 0 auto %" PRIu64,
+ seg->rlog_type, rlogbuf, rlog_seg->size);
+
+ dm_list_iterate_items(rsite, &seg->rsites) {
+ parm_count = (rsite->fall_behind_data
+ || rsite->fall_behind_ios
+ || rsite->async_timeout) ? 4 : 2;
+
+ EMIT_PARAMS(*pos, " blockdev %u %u %s", parm_count, rsite->rsite_index,
+ (rsite->async_action == DM_REPLICATOR_SYNC) ? "sync" : "async");
+
+ if (rsite->fall_behind_data)
+ EMIT_PARAMS(*pos, " data %" PRIu64, rsite->fall_behind_data);
+ else if (rsite->fall_behind_ios)
+ EMIT_PARAMS(*pos, " ios %" PRIu32, rsite->fall_behind_ios);
+ else if (rsite->async_timeout)
+ EMIT_PARAMS(*pos, " timeout %" PRIu32, rsite->async_timeout);
+ }
+
+ return 1;
+}
+
/*
* Returns: 1 on success, 0 on failure
*/
@@ -1424,6 +1540,19 @@ static int _emit_segment_line(struct dm_task *dmt, uint32_t major,
if (!r)
return_0;
break;
+ case SEG_REPLICATOR:
+ if ((r = _replicator_emit_segment_line(seg, params, paramsize, &pos))
+ <= 0) {
+ stack;
+ return r;
+ }
+ break;
+ case SEG_REPLICATOR_DEV:
+ if (!seg->log || !_build_dev_string(originbuf, sizeof(originbuf), seg->log))
+ return_0;
+
+ EMIT_PARAMS(pos, "%s %" PRIu64, originbuf, seg->rdevice_index);
+ break;
case SEG_SNAPSHOT:
if (!_build_dev_string(originbuf, sizeof(originbuf), seg->origin))
return_0;
@@ -1451,12 +1580,14 @@ static int _emit_segment_line(struct dm_task *dmt, uint32_t major,
switch(seg->type) {
case SEG_ERROR:
+ case SEG_REPLICATOR:
case SEG_SNAPSHOT:
case SEG_SNAPSHOT_ORIGIN:
case SEG_ZERO:
break;
case SEG_CRYPT:
case SEG_LINEAR:
+ case SEG_REPLICATOR_DEV:
case SEG_STRIPED:
if ((r = _emit_areas_line(dmt, seg, params, paramsize, &pos)) <= 0) {
stack;
@@ -1609,6 +1740,9 @@ int dm_tree_preload_children(struct dm_tree_node *dnode,
}
}
+ if (child->activation_priority != 0)
+ continue;
+
/* Propagate device size change change */
if (child->props.size_changed)
dnode->props.size_changed = 1;
@@ -1871,6 +2005,150 @@ int dm_tree_node_add_mirror_target(struct dm_tree_node *node,
return 1;
}
+int dm_tree_node_add_replicator_target(struct dm_tree_node *node,
+ uint64_t size,
+ const char *rlog_uuid,
+ const char *rlog_type,
+ unsigned rsite_index,
+ int async_action,
+ uint32_t async_timeout,
+ uint64_t fall_behind_data,
+ uint32_t fall_behind_ios)
+{
+ struct load_segment *rseg;
+ struct replicator_site *rsite;
+
+ if (rsite_index == 0) {
+ /* local site0 - add replog segment and set rlog device */
+ if (!(rseg = _add_segment(node, SEG_REPLICATOR, size)))
+ return_0;
+
+ if (!(rseg->log = dm_tree_find_node_by_uuid(node->dtree, rlog_uuid))) {
+ log_error("Missing replicator log uuid %s.", rlog_uuid);
+ return 0;
+ }
+
+ if (!_link_tree_nodes(node, rseg->log))
+ return_0;
+
+ if (strcmp(rlog_type, "ringbuffer") != 0) {
+ log_error("Unsupported rlog type %s.", rlog_type);
+ return 0;
+ }
+
+ if (!(rseg->rlog_type = dm_pool_strdup(node->dtree->mem, rlog_type)))
+ return_0;
+
+ dm_list_init(&rseg->rsites);
+ rseg->rdevice_count = 0;
+ node->activation_priority = 1;
+ }
+
+ if (!node->props.segment_count) {
+ log_error("Internal error: Attempt to add remote site area before replog.");
+ return 0;
+ }
+
+ /* new remote site */
+ if (async_action == DM_REPLICATOR_SYNC
+ && (async_timeout || fall_behind_ios || fall_behind_data)) {
+ log_error("Unsupported combination of sync options passed.");
+ return 0;
+ }
+
+ rseg = dm_list_item(dm_list_last(&node->props.segs), struct load_segment);
+
+ if (!(rsite = dm_pool_zalloc(node->dtree->mem, sizeof (*rsite)))) {
+ log_error("Failed to allocate remote site segment.");
+ return 0;
+ }
+ dm_list_add(&rseg->rsites, &rsite->list);
+ rseg->rsite_count++;
+
+ rsite->async_action = async_action;
+ rsite->async_timeout = async_timeout;
+ rsite->fall_behind_data = fall_behind_data;
+ rsite->fall_behind_ios = fall_behind_ios;
+ rsite->rsite_index = rsite_index;
+
+ return 1;
+}
+
+/* Appends device node to Replicator */
+int dm_tree_node_add_replicator_dev_target(struct dm_tree_node *node,
+ uint64_t size,
+ const char *replog_uuid,
+ uint64_t rdevice_index,
+ const char *rdev_uuid,
+ unsigned rsite_index,
+ const char *llog_uuid,
+ uint32_t llog_flags,
+ uint32_t llog_size)
+{
+ struct seg_area *area;
+ struct load_segment *rseg;
+ int is_uuid = (rdev_uuid) ? (strchr(rdev_uuid, '/') == NULL) : 0;
+
+ if (rsite_index == 0) {
+ /* site index for local target */
+ if (!(rseg = _add_segment(node, SEG_REPLICATOR_DEV, size)))
+ return_0;
+
+ if (!(rseg->log = dm_tree_find_node_by_uuid(node->dtree, replog_uuid))) {
+ log_error("Missing replicator log uuid %s.", replog_uuid);
+ return 0;
+ }
+
+ if (!rseg->log->props.segment_count) {
+ /* local slink 0 for replicator must be always initialized first */
+ log_error("Internal error: Attempt to use empty replog segment.");
+ return 0;
+ }
+ dm_list_item(dm_list_last(&rseg->log->props.segs),
+ struct load_segment)->rdevice_count++;
+
+ if (!_link_tree_nodes(node, rseg->log))
+ return_0;
+
+ rseg->rdevice_index = rdevice_index;
+ } else {
+ if (!node->props.segment_count) {
+ /* local slink 0 for replicator must be always initialized first */
+ log_error("Internal error: Attempt to add incorrrect remote target segment.");
+ return 0;
+ }
+
+ rseg = dm_list_item(dm_list_last(&node->props.segs), struct load_segment);
+ }
+
+ if (!(llog_flags & DM_CORELOG) && !llog_uuid) {
+ log_error("Unspecified link log uuid.");
+ return 0;
+ }
+
+ if (!dm_tree_node_add_target_area(node, (is_uuid) ? NULL : rdev_uuid,
+ (is_uuid) ? rdev_uuid : NULL, 0))
+ return 0;
+
+ area = dm_list_item(dm_list_last(&rseg->areas), struct seg_area);
+
+ if (!(llog_flags & DM_CORELOG)) {
+ if (!(area->llog = dm_tree_find_node_by_uuid(node->dtree, llog_uuid))) {
+ log_error("Couldn't find link log uuid %s.", llog_uuid);
+ return 0;
+ }
+
+ if (!_link_tree_nodes(node, area->llog))
+ return_0;
+ }
+
+ area->flags = llog_flags;
+ area->region_size = llog_size;
+ area->rsite_index = rsite_index;
+
+ return 1;
+}
+
static int _add_area(struct dm_tree_node *node, struct load_segment *seg, struct dm_tree_node *dev_node, uint64_t offset)
{
struct seg_area *area;
--
1.6.5.rc2
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 03/13] Replicator: add lvm support
2009-10-05 14:00 ` [PATCH 02/13] Replicator: add libdm support Zdenek Kabelac
@ 2009-10-05 14:00 ` Zdenek Kabelac
2009-10-05 14:00 ` [PATCH 04/13] Replicator: new variable in generated file Zdenek Kabelac
2009-10-07 15:07 ` [PATCH 03/13] Replicator: add lvm support Alasdair G Kergon
2009-10-07 14:39 ` [PATCH 02/13] Replicator: add libdm support Alasdair G Kergon
2009-10-08 9:32 ` Petr Rockai
2 siblings, 2 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2009-10-05 14:00 UTC (permalink / raw)
To: lvm-devel
Adding basic lib lvm elements for Replicator
Validation of Replicator segment
Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
configure.in | 17 +
lib/Makefile.in | 9 +
lib/commands/toolcontext.c | 5 +
lib/metadata/lv_manip.c | 1 +
lib/metadata/merge.c | 14 +
lib/metadata/metadata-exported.h | 94 ++++-
lib/metadata/replicator.c | 339 ++++++++++++++
lib/metadata/segtype.h | 8 +
lib/replicator/.exported_symbols | 1 +
lib/replicator/Makefile.in | 28 ++
lib/replicator/replicator.c | 912 ++++++++++++++++++++++++++++++++++++++
11 files changed, 1427 insertions(+), 1 deletions(-)
create mode 100644 lib/metadata/replicator.c
create mode 100644 lib/replicator/.exported_symbols
create mode 100644 lib/replicator/Makefile.in
create mode 100644 lib/replicator/replicator.c
diff --git a/configure.in b/configure.in
index bf360ed..197e17a 100644
--- a/configure.in
+++ b/configure.in
@@ -308,6 +308,21 @@ if test x$MIRRORS = xinternal; then
fi
################################################################################
+dnl -- Asynchronous Volume Replicator inclusion type
+AC_MSG_CHECKING(whether to include replicator)
+AC_ARG_WITH(replicator, AC_HELP_STRING([--with-replicator=TYPE],
+ [Replicator support: internal/shared/none [[TYPE=none]]]),
+ [ REPLICATOR="$withval" ], [ REPLICATOR="none" ])
+AC_MSG_RESULT($REPLICATOR)
+
+case "$REPLICATOR" in
+ none|shared) ;;
+ internal) AC_DEFINE([REPLICATOR_INTERNAL], 1,
+ [Define to 1 to include built-in support for replicator.]) ;;
+ *) AC_MSG_ERROR([--with-replicator parameter invalid ($REPLICATOR)]) ;;
+esac
+
+################################################################################
dnl -- Disable readline
AC_MSG_CHECKING(whether to enable readline)
AC_ARG_ENABLE([readline],
@@ -1116,6 +1131,7 @@ AC_SUBST(LVM_PATCHLEVEL)
AC_SUBST(LVM_RELEASE)
AC_SUBST(LVM_RELEASE_DATE)
AC_SUBST(MIRRORS)
+AC_SUBST(REPLICATOR)
AC_SUBST(MSGFMT)
AC_SUBST(OWNER)
AC_SUBST(PKGCONFIG)
@@ -1163,6 +1179,7 @@ lib/format1/Makefile
lib/format_pool/Makefile
lib/locking/Makefile
lib/mirror/Makefile
+lib/replicator/Makefile
lib/misc/lvm-version.h
lib/snapshot/Makefile
libdm/Makefile
diff --git a/lib/Makefile.in b/lib/Makefile.in
index 9396fb2..38a3589 100644
--- a/lib/Makefile.in
+++ b/lib/Makefile.in
@@ -33,6 +33,10 @@ ifeq ("@MIRRORS@", "shared")
SUBDIRS += mirror
endif
+ifeq ("@REPLICATOR@", "shared")
+ SUBDIRS += replicator
+endif
+
SOURCES =\
activate/activate.c \
cache/lvmcache.c \
@@ -74,6 +78,7 @@ SOURCES =\
metadata/mirror.c \
metadata/pv_manip.c \
metadata/pv_map.c \
+ metadata/replicator.c \
metadata/segtype.c \
metadata/snapshot_manip.c \
misc/crc.c \
@@ -125,6 +130,10 @@ ifeq ("@MIRRORS@", "internal")
SOURCES += mirror/mirrored.c
endif
+ifeq ("@REPLICATOR@", "internal")
+ SOURCES += replicator/replicator.c
+endif
+
ifeq ("@DEVMAPPER@", "yes")
SOURCES +=\
activate/dev_manager.c \
diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c
index 2a56100..d1f4724 100644
--- a/lib/commands/toolcontext.c
+++ b/lib/commands/toolcontext.c
@@ -904,6 +904,11 @@ static int _init_segtypes(struct cmd_context *cmd)
dm_list_add(&cmd->segtypes, &segtype->list);
#endif
+#ifdef REPLICATOR_INTERNAL
+ if (!init_replicator_segtype(&seglib))
+ return 0;
+#endif
+
#ifdef HAVE_LIBDL
/* Load any formats in shared libs unless static */
if (!is_static() &&
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 7bcd64f..51e100e 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -1876,6 +1876,7 @@ struct logical_volume *alloc_lv(struct dm_pool *mem)
dm_list_init(&lv->segments);
dm_list_init(&lv->tags);
dm_list_init(&lv->segs_using_this_lv);
+ dm_list_init(&lv->rsites);
return lv;
}
diff --git a/lib/metadata/merge.c b/lib/metadata/merge.c
index 66e9ce0..3233d2b 100644
--- a/lib/metadata/merge.c
+++ b/lib/metadata/merge.c
@@ -66,6 +66,8 @@ int check_lv_segments(struct logical_volume *lv, int complete_vg)
int r = 1;
uint32_t area_multiplier, s;
struct seg_list *sl;
+ struct replicator_site *rsite;
+ struct replicator_device *rdev;
dm_list_iterate_items(seg, &lv->segments) {
seg_count++;
@@ -207,6 +209,18 @@ int check_lv_segments(struct logical_volume *lv, int complete_vg)
if (lv == seg_lv(seg, s))
seg_found++;
}
+ if (seg_is_replicator_dev(seg)) {
+ dm_list_iterate_items(rsite, &seg->replicator->rsites) {
+ dm_list_iterate_items(rdev, &rsite->rdevices) {
+ if (lv == rdev->lv || lv == rdev->slog)
+ seg_found++;
+ }
+ }
+ if (lv == seg->replicator)
+ seg_found++;
+ }
+ if (seg_is_replicator(seg) && lv == seg->rlog_lv)
+ seg_found++;
if (seg->log_lv == lv)
seg_found++;
if (!seg_found) {
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index bf830aa..2d08c2d 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -61,6 +61,9 @@
//#define PRECOMMITTED 0x00200000U /* VG - internal use only */
#define CONVERTING 0x00400000U /* LV */
+#define REPLICATOR 0x10000000U /* LV -internal use only for replicator/replicator-dev */
+#define REPLICATOR_LOG 0x20000000U /* LV -internal use only for replicator/replicator-dev */
+
#define MISSING_PV 0x00800000U /* PV */
#define PARTIAL_LV 0x01000000U /* LV - derived flag, not
written out in metadata*/
@@ -277,6 +280,54 @@ struct lv_segment_area {
};
struct segment_type;
+
+/* ++ replicator datatypes */
+typedef enum {
+ REPLICATOR_ACTION_WARN,
+ REPLICATOR_ACTION_STALL,
+ REPLICATOR_ACTION_DROP,
+ REPLICATOR_ACTION_FAIL,
+ NUM_REPLICATOR_ACTION
+} replicator_action_t;
+
+typedef enum {
+ REPLICATOR_STATE_PASSIVE,
+ REPLICATOR_STATE_ACTIVE,
+ NUM_REPLICATOR_STATE
+} replicator_state_t;
+
+struct replicator_site {
+ struct dm_list list; /* chained list of sites */
+ struct dm_list rdevices; /* device list */
+
+ struct logical_volume *replicator; /* reference to replicator */
+
+ const char *name;
+ const char *vg_name; /* vg name/uuid */
+ struct volume_group *vg; /* site's volume group */
+ unsigned site_index;
+ replicator_state_t state; /* active|pasive state of site */
+ replicator_action_t async_action;/* fail|warn|drop|resync|stall */
+ uint64_t fall_behind_data; /* in bytes */
+ uint32_t fall_behind_ios; /* io operations */
+ uint32_t fall_behind_timeout; /* seconds */
+};
+
+struct replicator_device {
+ struct dm_list list; /* chained list of devices from same site */
+
+ struct lv_segment *replicator_dev; /* reference to replicator-dev segment */
+ struct replicator_site *rsite; /* reference to site parameters */
+
+ uint64_t device_index;
+ const char *name; /* any device path/uuid */
+ struct logical_volume *lv; /* lv from rsite's VG */
+ struct logical_volume *slog; /* llog lv from VG */
+ const char *slog_name; /* ?debug? - specify ram based core log size */
+};
+
+/* -- replicator datatypes */
+
struct lv_segment {
struct dm_list list;
struct logical_volume *lv;
@@ -295,13 +346,19 @@ struct lv_segment {
struct logical_volume *cow;
struct dm_list origin_list;
uint32_t chunk_size; /* For snapshots - in sectors */
- uint32_t region_size; /* For mirrors - in sectors */
+ uint32_t region_size; /* For mirrors, replicators - in sectors */
uint32_t extents_copied;
struct logical_volume *log_lv;
struct dm_list tags;
struct lv_segment_area *areas;
+
+ struct logical_volume *replicator;/* For replicator-devs - link to replicator LV */
+ struct logical_volume *rlog_lv; /* For replicators */
+ const char *rlog_type; /* For replicators */
+ uint64_t rdevice_index_highest; /* For replicators */
+ unsigned rsite_index_highest; /* For replicators */
};
#define seg_type(seg, s) (seg)->areas[(s)].type
@@ -327,6 +384,9 @@ struct logical_volume {
struct dm_list snapshot_segs;
struct lv_segment *snapshot;
+ struct replicator_device *rdevice;/* For replicator-devs, rimages, slogs - reference to rdevice */
+ struct dm_list rsites; /* For replicators - all sites */
+
struct dm_list segments;
struct dm_list tags;
struct dm_list segs_using_this_lv;
@@ -520,6 +580,7 @@ uint64_t extents_from_size(struct cmd_context *cmd, uint64_t size,
struct lvcreate_params {
/* flags */
int snapshot; /* snap */
+ int replicator; /* replicator */
int zero; /* all */
int major; /* all */
int minor; /* all */
@@ -682,6 +743,37 @@ int reconfigure_mirror_images(struct lv_segment *mirrored_seg, uint32_t num_mirr
int collapse_mirrored_lv(struct logical_volume *lv);
int shift_mirror_images(struct lv_segment *mirrored_seg, unsigned mimage);
+/* ++ metadata/replicator.c */
+
+int lvm_replicator_add_dev(struct logical_volume *replicator_lv, struct lv_segment *replicator_dev_seg);
+/*
+ * returns rimage ?? lv upon succeful detach of device
+ * entire LV entry should be removed by this crootall ??
+ */
+struct logical_volume *lvm_replicator_remove_dev(struct lv_segment *replicator_dev_seg);//MAYBE: struct replicator_device *rdev??
+int lvm_replicator_add_rlog(struct lv_segment *replicator_seg, struct logical_volume *rlog_lv);
+struct logical_volume *lvm_replicator_remove_rlog(struct lv_segment *replicator_seg);
+
+int lvm_replicator_dev_add_slog(struct replicator_device *rdev, struct logical_volume *llog_lv);
+struct logical_volume *lvm_replicator_dev_remove_slog(struct replicator_device *rdev);
+int lvm_replicator_dev_add_rimage(struct replicator_device *rdev, struct logical_volume *lv);
+struct logical_volume *lvm_replicator_dev_remove_rimage(struct replicator_device *rdev);
+
+/* is this segment part of active replicator */
+int lv_is_active_replicator_dev(const struct logical_volume *lv);
+
+/* is this lv replicator control device */
+int lv_is_replicator(const struct logical_volume *lv);
+/* is this lv replicator device */
+int lv_is_replicator_dev(const struct logical_volume *lv);
+/* is this lv replicated origin lv */
+int lv_is_rimage(const struct logical_volume *lv);
+/* is this lv rlog */
+int lv_is_rlog(const struct logical_volume *lv);
+/* is this lv sync log */
+int lv_is_slog(const struct logical_volume *lv);
+/* -- metadata/replicator.c */
+
struct logical_volume *find_pvmove_lv(struct volume_group *vg,
struct device *dev, uint32_t lv_type);
struct logical_volume *find_pvmove_lv_from_pvname(struct cmd_context *cmd,
diff --git a/lib/metadata/replicator.c b/lib/metadata/replicator.c
new file mode 100644
index 0000000..ca87085
--- /dev/null
+++ b/lib/metadata/replicator.c
@@ -0,0 +1,339 @@
+/*
+ * Copyright (C) 2009 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "lib.h"
+#include "metadata.h"
+#include "toolcontext.h"
+#include "segtype.h"
+#include "archiver.h"
+#include "lvm-string.h"
+#include "str_list.h"
+#include "defaults.h"
+#include "lv_alloc.h"
+
+/* Add lv as replicator device */
+int lvm_replicator_dev_add_rimage(struct replicator_device *rdev,
+ struct logical_volume *lv)
+{
+ if (!lv || !rdev)
+ return_0;
+ log_verbose("try add_rimage");
+
+ if (lv_is_rimage(lv)) {
+ log_error("Logical volume %s is already part of other "
+ "replicator.", lv->name);
+ return 0;
+ }
+
+ if (rdev->lv) {
+ log_error("Logical volume %s can not be attached to an "
+ "already defined replicator_device", lv->name);
+ return 0;
+ }
+
+ lv_set_hidden(lv);
+ lv->rdevice = rdev;
+ rdev->lv = lv;
+
+ //{ static int kill = 4; if (getenv("LVMKILL") && kill-- < 0) abort(); }
+
+ log_verbose("LV rdev rd:%p repseg:%p", rdev, rdev->replicator_dev);
+ return add_seg_to_segs_using_this_lv(lv, rdev->replicator_dev);
+}
+
+/* Remove lv from replicator device */
+struct logical_volume *lvm_replicator_dev_remove_rimage(struct replicator_device *rdev)
+{
+ struct logical_volume *lv;
+
+ if (!rdev || !rdev->lv)
+ return_NULL;
+
+ lv = rdev->lv;
+ if (!remove_seg_from_segs_using_this_lv(lv, rdev->replicator_dev))
+ return NULL;
+
+ // FIXME: - check for site references
+ rdev->lv = NULL;
+ lv->rdevice = NULL;
+ lv_set_visible(lv);
+
+ return lv;
+}
+
+int lvm_replicator_dev_add_slog(struct replicator_device *rdev,
+ struct logical_volume *slog)
+{
+ if (!slog || !rdev)
+ return_0;
+
+ if (rdev->slog) {
+ log_error("Replicator device in site %s already has sync log.",
+ rdev->rsite->name);
+ return 0;
+ }
+
+ if (slog->rdevice) {
+ log_error("Sync log %s is already part of other replicator.",
+ slog->name);
+ return 0;
+ }
+
+ lv_set_hidden(slog);
+ slog->rdevice = rdev;
+ rdev->slog = slog;
+
+ return add_seg_to_segs_using_this_lv(slog, rdev->replicator_dev);
+}
+
+struct logical_volume *lvm_replicator_dev_remove_slog(struct replicator_device *rdev)
+{
+ struct logical_volume *lv;
+
+ if (!rdev)
+ return_NULL;
+
+ lv = rdev->slog;
+ if (!lv) {
+ log_error("Replicator device in site %s does not have sync log.",
+ rdev->rsite->name);
+ return NULL;
+ }
+
+ if (!remove_seg_from_segs_using_this_lv(lv, rdev->replicator_dev))
+ return NULL;
+
+ rdev->slog = NULL;
+ lv->rdevice = NULL;
+ lv_set_visible(lv);
+
+ return lv;
+}
+
+int lvm_replicator_add_dev(struct logical_volume *replicator_lv,
+ struct lv_segment *replicator_dev_seg)
+{
+ if (!replicator_lv)
+ return_0;
+
+ if (!(replicator_lv->status & REPLICATOR)) {
+ dm_list_init(&replicator_lv->rsites);
+ lv_set_hidden(replicator_lv);
+ replicator_lv->status |= REPLICATOR;
+ }
+
+ if (!replicator_dev_seg)
+ return 1;
+
+ if (replicator_dev_seg->replicator) {
+ log_error("Replicator device %s is already part of replicator.",
+ replicator_dev_seg->lv->name);
+ return 0;
+ }
+
+ replicator_dev_seg->replicator = replicator_lv;
+
+ return add_seg_to_segs_using_this_lv(replicator_lv, replicator_dev_seg);
+}
+
+struct logical_volume *lvm_replicator_remove_dev(struct lv_segment *replicator_dev_seg)
+{
+ struct logical_volume *lv = NULL;
+
+#if 0
+ // FIXME - this is going to be complex....
+ if (!replicator_dev_seg)
+ return_NULL;
+
+ // if slog - exit
+ // if rimage - exit
+
+ if (!remove_seg_from_segs_using_this_lv(lv, replicator_seg))
+ return NULL;
+ replicator_seg->rlog_lv = NULL;
+ lv->status &= ~REPLICATOR_LOG;
+ lv_set_visible(lv);
+#endif
+
+ return lv;
+}
+
+int lvm_replicator_add_rlog(struct lv_segment *replicator_seg,
+ struct logical_volume *rlog_lv)
+{
+ if (!rlog_lv)
+ return_0;
+
+ if (rlog_lv->status & REPLICATOR_LOG) {
+ log_error("Rlog device %s is already used.", rlog_lv->name);
+ return 0;
+ }
+
+ lv_set_hidden(rlog_lv);
+ rlog_lv->status |= REPLICATOR_LOG;
+ replicator_seg->rlog_lv = rlog_lv;
+
+ return add_seg_to_segs_using_this_lv(rlog_lv, replicator_seg);
+}
+
+struct logical_volume *lvm_replicator_remove_rlog(struct lv_segment *replicator_seg)
+{
+ struct logical_volume *lv;
+
+ if (!replicator_seg)
+ return_0;
+
+ if (!(lv = replicator_seg->rlog_lv)) {
+ log_error("Replog segment %s does not have rlog.",
+ replicator_seg->lv->name);
+ return NULL;
+ }
+
+ if (!remove_seg_from_segs_using_this_lv(lv, replicator_seg))
+ return NULL;
+
+ replicator_seg->rlog_lv = NULL;
+ lv->status &= ~REPLICATOR_LOG;
+ lv_set_visible(lv);
+
+ return lv;
+}
+
+
+#if 0
+/*
+ * Create new LV to pretend the original LV
+ * this target will have a 'replicator' segment
+ */
+int lvm_replicator_lv_add(struct logical_volume *origin, const char *rep_suffix)
+{
+ struct logical_volume *rep_lv;
+ //struct lv_segment *seg;
+ char *name;
+ size_t slen;
+
+ //name = strcpy(alloc(strlen(s) + 1), s), if (!strstr(name, suffix) ? ),
+
+ if (!(name = strstr(origin->name, rep_suffix))) {
+ log_error("Failed to find replicator suffix %s in LV name %s",
+ rep_suffix, origin->name);
+ return 0;
+ }
+ slen = (size_t)(name - origin->name);
+ name = alloca(slen + 1);
+ memcpy(name, origin->name, slen);
+ name[slen] = 0;
+
+ if ((rep_lv = find_lv(origin->vg, name))) {
+ rep_lv->status |= VIRTUAL;
+ log_very_verbose("Found already created lv %s le:%" PRIu32,
+ rep_lv->name, rep_lv->le_count);
+ return 1;
+ }
+
+ if (!(rep_lv = lv_create_empty(name, &origin->lvid,
+ LVM_READ | LVM_WRITE | VISIBLE_LV,
+ ALLOC_INHERIT, origin->vg)))
+ return_0;
+
+ log_very_verbose("Created empty lv %s %s le:%" PRIu32,
+ rep_lv->name, origin->name, origin->le_count);
+
+ if (!lv_add_virtual_segment(rep_lv, 0, origin->le_count,
+ get_segtype_from_string(origin->vg->cmd,
+ "error")))
+ return_0;
+
+ /*
+ if (!(seg = alloc_snapshot_seg(rep, 0, 0)))
+ return_0;
+
+ seg->chunk_size = chunk_size;
+ seg->origin = origin;
+ seg->cow = cow;
+ seg->lv->status |= SNAPSHOT;
+
+ origin->origin_count++;
+ origin->vg->snapshot_count++;
+ origin->vg->lv_count--;
+ cow->snapshot = seg;
+
+ cow->status &= ~VISIBLE_LV;
+
+ dm_list_add(&origin->snapshot_segs, &seg->origin_list);
+ */
+
+ //rep_lv->status |= REPLICATOR | VIRTUAL;
+ rep_lv->status |= VIRTUAL;
+ return 1;
+}
+
+int lvm_replicator_lv_remove(struct logical_volume *lv)
+{
+ dm_list_del(&cow->snapshot->origin_list);
+ cow->snapshot->origin->origin_count--;
+
+ if (!lv_remove(cow->snapshot->lv)) {
+ log_error("Failed to remove internal snapshot LV %s",
+ cow->snapshot->lv->name);
+ return 0;
+ }
+
+ cow->snapshot = NULL;
+
+ cow->vg->snapshot_count--;
+ cow->status |= VISIBLE_LV;
+
+ return 1;
+}
+#endif
+
+int lv_is_replicator(const struct logical_volume *lv)
+{
+ return ((lv->status & REPLICATOR) &&
+ !dm_list_empty(&lv->segments) &&
+ seg_is_replicator(first_seg(lv)));
+}
+
+int lv_is_replicator_dev(const struct logical_volume *lv)
+{
+ return ((lv->status & REPLICATOR) &&
+ !dm_list_empty(&lv->segments) &&
+ seg_is_replicator_dev(first_seg(lv)));
+}
+
+int lv_is_rimage(const struct logical_volume *lv)
+{
+ return (lv->rdevice && lv->rdevice->lv == lv);
+}
+
+int lv_is_rlog(const struct logical_volume *lv)
+{
+ return (lv->status & REPLICATOR_LOG) &&
+ !dm_list_empty(&lv->segments) &&
+ seg_is_replicator(first_seg(lv));
+}
+
+int lv_is_slog(const struct logical_volume *lv)
+{
+ return (lv->rdevice && lv->rdevice->slog == lv);
+}
+
+int lv_is_active_replicator_dev(const struct logical_volume *lv)
+{
+ if (!(lv->status & REPLICATOR) ||
+ !lv->rdevice || !lv->rdevice->rsite)
+ return 0;
+ return (lv->rdevice->rsite->state == REPLICATOR_STATE_ACTIVE);
+}
diff --git a/lib/metadata/segtype.h b/lib/metadata/segtype.h
index ff6fb08..4454cb2 100644
--- a/lib/metadata/segtype.h
+++ b/lib/metadata/segtype.h
@@ -35,8 +35,12 @@ struct dev_manager;
#define SEG_VIRTUAL 0x00000020U
#define SEG_CANNOT_BE_ZEROED 0x00000040U
#define SEG_MONITORED 0x00000080U
+#define SEG_REPLICATOR 0x00000100U
+#define SEG_REPLICATOR_DEV 0x00000200U
#define seg_is_mirrored(seg) ((seg)->segtype->flags & SEG_AREAS_MIRRORED ? 1 : 0)
+#define seg_is_replicator(seg) ((seg)->segtype->flags & SEG_REPLICATOR ? 1 : 0)
+#define seg_is_replicator_dev(seg) ((seg)->segtype->flags & SEG_REPLICATOR_DEV ? 1 : 0)
#define seg_is_striped(seg) ((seg)->segtype->flags & SEG_AREAS_STRIPED ? 1 : 0)
#define seg_is_snapshot(seg) ((seg)->segtype->flags & SEG_SNAPSHOT ? 1 : 0)
#define seg_is_virtual(seg) ((seg)->segtype->flags & SEG_VIRTUAL ? 1 : 0)
@@ -106,6 +110,10 @@ struct segment_type *init_zero_segtype(struct cmd_context *cmd);
struct segment_type *init_error_segtype(struct cmd_context *cmd);
struct segment_type *init_free_segtype(struct cmd_context *cmd);
+#ifdef REPLICATOR_INTERNAL
+int init_replicator_segtype(struct segtype_library *seglib);
+#endif
+
#ifdef SNAPSHOT_INTERNAL
struct segment_type *init_snapshot_segtype(struct cmd_context *cmd);
#endif
diff --git a/lib/replicator/.exported_symbols b/lib/replicator/.exported_symbols
new file mode 100644
index 0000000..1c92c6a
--- /dev/null
+++ b/lib/replicator/.exported_symbols
@@ -0,0 +1 @@
+init_segtype
diff --git a/lib/replicator/Makefile.in b/lib/replicator/Makefile.in
new file mode 100644
index 0000000..db1f9b7
--- /dev/null
+++ b/lib/replicator/Makefile.in
@@ -0,0 +1,28 @@
+#
+# Copyright (C) 2009 Red Hat, Inc. All rights reserved.
+#
+# This file is part of LVM2.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+
+SOURCES = replicator.c
+
+LIB_SHARED = liblvm2replicator.so
+
+include $(top_srcdir)/make.tmpl
+
+install: $(LIB_SHARED)
+ $(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
+ $(libdir)/$(LIB_SHARED).$(LIB_VERSION)
+ $(LN_S) -f $(LIB_SHARED).$(LIB_VERSION) \
+ $(libdir)/$(LIB_SHARED)
diff --git a/lib/replicator/replicator.c b/lib/replicator/replicator.c
new file mode 100644
index 0000000..6e0f7a6
--- /dev/null
+++ b/lib/replicator/replicator.c
@@ -0,0 +1,912 @@
+/*
+ * Copyright (C) 2009 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "lib.h"
+#include "toolcontext.h"
+#include "metadata.h"
+#include "segtype.h"
+#include "text_export.h"
+#include "text_import.h"
+#include "config.h"
+#include "activate.h"
+#include "str_list.h"
+#include "targets.h" /* build_dlid */
+#ifdef DMEVENTD
+# include "sharedlib.h"
+# include "libdevmapper-event.h"
+#endif
+
+/* dm kernel module name for replicator */
+#define REPLICATOR_MODULE "replicator"
+#define REPLICATOR_DEV_MODULE "replicator-dev"
+
+#define SEG_LOG_ERROR(t, p...) \
+ log_error(t " segment %s of logical volume %s.", ## p, \
+ config_parent_name(sn), seg->lv->name), 0; \
+
+
+/*
+ * Replicator target
+ */
+static const char *_replicator_name(const struct lv_segment *seg)
+{
+ return seg->segtype->name;
+}
+
+/* FIXME: */
+static void _replicator_display(const struct lv_segment *seg)
+{
+ //const char *size;
+ //uint32_t s;
+
+ log_print(" Replicator");
+ if (seg->rlog_lv)
+ log_print(" Replicator volume\t%s", seg->rlog_lv->name);
+}
+
+/* Wrapper for get_config_uint32 with default value */
+static uint32_t _get_config_uint32(const struct config_node *cn,
+ const char *path,
+ uint32_t def)
+{
+ uint32_t t;
+
+ return get_config_uint32(cn, path, &t) ? t : def;
+}
+
+/* Wrapper for get_config_uint64 with default value */
+static uint64_t _get_config_uint64(const struct config_node *cn,
+ const char *path,
+ uint64_t def)
+{
+ uint64_t t;
+
+ return get_config_uint64(cn, path, &t) ? t : def;
+}
+
+
+/* Strings replicator_state_t enum */
+static const char _state_txt[NUM_REPLICATOR_STATE][8] = {
+ "passive",
+ "active"
+};
+
+/* Parse state string */
+static replicator_state_t _get_state(const struct config_node *sn,
+ const char *path, replicator_state_t def)
+{
+ char *str;
+ unsigned i;
+
+ if (get_config_str(sn, path, &str)) {
+ for (i = 0; i < sizeof(_state_txt)/sizeof(_state_txt[0]); ++i)
+ if (strcasecmp(str, _state_txt[i]) == 0) {
+ log_very_verbose("Setting %s to %s",
+ path, _state_txt[i]);
+ return (replicator_state_t) i;
+ }
+
+ log_warn("%s: unknown value '%s', using default '%s' state",
+ path, str, _state_txt[def]);
+ }
+
+ return def;
+}
+
+/* Strings for replicator_action_t enum */
+static const char _action_txt[NUM_REPLICATOR_ACTION][8] = {
+ "warn",
+ "stall",
+ "drop",
+ "fail"
+};
+
+
+/* Parse action string */
+static replicator_action_t _get_action(const struct config_node *sn,
+ const char *path, replicator_action_t def)
+{
+ char *str;
+ unsigned i;
+
+ if (get_config_str(sn, path, &str)) {
+ for (i = 0; i < sizeof(_action_txt)/sizeof(_action_txt[0]); ++i)
+ if (strcasecmp(str, _action_txt[i]) == 0) {
+ log_very_verbose("Setting %s to %s",
+ path, _action_txt[i]);
+ return (replicator_action_t) i;
+ }
+ log_warn("%s: unknown value '%s', using default '%s' action",
+ path, str, _action_txt[def]);
+ }
+
+ return def;
+}
+
+static struct replicator_site *_get_site(struct logical_volume *replicator,
+ const char *key)
+{
+ struct dm_pool *mem = replicator->vg->vgmem;
+ struct replicator_site *rsite;
+
+ dm_list_iterate_items(rsite, &replicator->rsites) {
+ if (strcasecmp(rsite->name, key) == 0) {
+ return rsite;
+ }
+ }
+ if (!(rsite = dm_pool_zalloc(mem, sizeof(*rsite))))
+ return_NULL;
+
+ if (!(rsite->name = dm_pool_strdup(mem, key)))
+ return_NULL;
+
+ rsite->replicator = replicator;
+ dm_list_init(&rsite->rdevices);
+ dm_list_add(&replicator->rsites, &rsite->list);
+
+ return rsite;
+}
+
+
+/* Parse replicator site element */
+static int _add_site(struct lv_segment *seg,
+ const char *key,
+ const struct config_node *sn)
+{
+ struct dm_pool *mem = seg->lv->vg->vgmem;
+ const struct config_node *cn;
+ struct replicator_site *rsite;
+
+ if (!(rsite = _get_site(seg->lv, key)))
+ return_0;
+
+ if (!find_config_node(sn, "site_index"))
+ return SEG_LOG_ERROR("Mandatory site_index is missing for");
+
+ rsite->state = _get_state(sn, "state", REPLICATOR_STATE_PASSIVE);
+ rsite->site_index = _get_config_uint32(sn, "site_index", 0);
+ if (rsite->site_index > seg->rsite_index_highest)
+ return SEG_LOG_ERROR("site_index=%d > highest_site_index=%d for",
+ rsite->site_index, seg->rsite_index_highest);
+
+ rsite->fall_behind_data = _get_config_uint64(sn, "fall_behind_data", 0);
+ rsite->fall_behind_ios = _get_config_uint32(sn, "fall_behind_ios", 0);
+ rsite->fall_behind_timeout = _get_config_uint32(sn, "fall_behind_timeout", 0);
+ rsite->async_action = REPLICATOR_ACTION_WARN;
+
+ if (rsite->fall_behind_data ||
+ rsite->fall_behind_ios ||
+ rsite->fall_behind_timeout) {
+ if (rsite->fall_behind_data && rsite->fall_behind_ios)
+ return SEG_LOG_ERROR("Defined both fall_behind_data "
+ "and fall_behind_ios in");
+
+ if (rsite->fall_behind_data && rsite->fall_behind_timeout)
+ return SEG_LOG_ERROR("Defined both fall_behind_data "
+ "and fall_behind_timeout in");
+
+ if (rsite->fall_behind_ios && rsite->fall_behind_timeout)
+ return SEG_LOG_ERROR("Defined both fall_behind_ios "
+ "and fall_behind_timeout in");
+
+ rsite->async_action = _get_action(sn, "async_action",
+ rsite->async_action);
+ }
+
+ if ((cn = find_config_node(sn, "volume_group"))) {
+ if (!cn->v || cn->v->type != CFG_STRING)
+ return SEG_LOG_ERROR("volume_group must be a string in");
+
+ if (!(rsite->vg_name = dm_pool_strdup(mem, cn->v->v.str)))
+ return_0;
+
+ } else if (rsite->site_index != 0)
+ return SEG_LOG_ERROR("volume_group is mandatory for remote site in");
+
+ return 1;
+}
+
+
+/* Import replicator segment */
+static int _replicator_text_import(struct lv_segment *seg,
+ const struct config_node *sn,
+ struct dm_hash_table *pv_hash __attribute((unused)))
+{
+ const struct config_node *cn;
+ struct logical_volume *rlog_lv;
+
+ if (!lvm_replicator_add_dev(seg->lv, NULL))
+ return_0;
+
+ if (!(cn = find_config_node(sn, "replicator_log")) ||
+ !cn->v || cn->v->type != CFG_STRING)
+ return SEG_LOG_ERROR("Replicator log type must be a string in");
+
+ if (!(rlog_lv = find_lv(seg->lv->vg, cn->v->v.str)))
+ return SEG_LOG_ERROR("Unknown replicator log %s in",
+ cn->v->v.str);
+
+ if (!(cn = find_config_node(sn, "replicator_log_type")) ||
+ !cn->v || cn->v->type != CFG_STRING)
+ return SEG_LOG_ERROR("Replicator log's type must be a string in");
+ if (strcasecmp(cn->v->v.str, "ringbuffer"))
+ return SEG_LOG_ERROR("Only ringbuffer replicator log type is supported in");
+
+ if (!(seg->rlog_type = dm_pool_strdup(seg->lv->vg->vgmem, cn->v->v.str)))
+ return_0;
+
+
+ log_very_verbose("replicator_log = %s", rlog_lv->name);
+ log_very_verbose("replicator_log_type = %s", seg->rlog_type);
+
+ if (!lvm_replicator_add_rlog(seg, rlog_lv))
+ return_0;
+
+ seg->rdevice_index_highest = _get_config_uint64(sn, "highest_device_index", 0);
+ seg->rsite_index_highest = _get_config_uint64(sn, "highest_site_index", 0);
+
+ seg->region_size = _get_config_uint32(sn, "sync_log_size", 0);
+
+ for (; sn; sn = sn->sib)
+ if (!sn->v && !_add_site(seg, sn->key, sn->child))
+ return 0;
+
+ return 1;
+}
+
+/* Export replicator segment */
+static int _replicator_text_export(const struct lv_segment *seg,
+ struct formatter *f)
+{
+ const struct replicator_site *rsite;
+
+ if (!seg->rlog_lv)
+ return_0;
+
+ outf(f, "replicator_log = \"%s\"", seg->rlog_lv->name);
+ outf(f, "replicator_log_type = \"%s\"", seg->rlog_type);
+ outf(f, "highest_device_index = %" PRIu64, seg->rdevice_index_highest);
+ outf(f, "highest_site_index = %d", seg->rsite_index_highest);
+
+ if (seg->region_size)
+ outf(f, "sync_log_size = %d", seg->region_size);
+
+ if (!dm_list_empty(&seg->lv->rsites))
+ out_newline(f);
+
+ dm_list_iterate_items(rsite, &seg->lv->rsites) {
+ outf(f, "%s {", rsite->name);
+ out_inc_indent(f);
+
+ outf(f, "state = \"%s\"", _state_txt[rsite->state]);
+ outf(f, "site_index = %d", rsite->site_index);
+
+ /* only non-default parameters are written */
+ if (rsite->async_action != REPLICATOR_ACTION_WARN)
+ outf(f, "async_action = \"%s\"",
+ _action_txt[rsite->async_action]);
+ if (rsite->fall_behind_timeout)
+ outf(f, "fall_behind_timeout = %u\t# seconds",
+ rsite->fall_behind_timeout);
+ if (rsite->fall_behind_ios)
+ outf(f, "fall_behind_ios = %u\t# io operations",
+ rsite->fall_behind_ios);
+ if (rsite->fall_behind_data)
+ outf(f, "fall_behind_data = %" PRIu64 "\t# bytes",
+ rsite->fall_behind_data);
+ if (rsite->state != REPLICATOR_STATE_ACTIVE && rsite->vg_name)
+ outf(f, "volume_group = \"%s\"", rsite->vg_name);
+
+ out_dec_indent(f);
+ outf(f, "}");
+ }
+
+ return 1;
+}
+
+#ifdef DEVMAPPER_SUPPORT
+static int _replicator_add_target_line(struct dev_manager *dm,
+ struct dm_pool *mem,
+ struct cmd_context *cmd,
+ void **target_state,
+ struct lv_segment *seg,
+ struct dm_tree_node *node,
+ uint64_t len,
+ uint32_t *pvmove_mirror_count)
+{
+ const char *rlog_dlid;
+ const struct replicator_site *rsite;
+ int action;
+
+ if (!seg->rlog_lv)
+ return_0;
+
+ if (!(rlog_dlid = build_dlid(dm, seg->rlog_lv->lvid.s, NULL)))
+ return_0;
+
+ dm_list_iterate_items(rsite, &seg->lv->rsites) {
+ action = (rsite->async_action == REPLICATOR_ACTION_WARN) ? DM_REPLICATOR_WARN :
+ (rsite->async_action == REPLICATOR_ACTION_STALL) ? DM_REPLICATOR_STALL :
+ (rsite->async_action == REPLICATOR_ACTION_DROP) ? DM_REPLICATOR_DROP : DM_REPLICATOR_FAIL;
+ if (!rsite->fall_behind_timeout && !rsite->fall_behind_data && !rsite->fall_behind_ios)
+ action = DM_REPLICATOR_SYNC;
+ if (!dm_tree_node_add_replicator_target(node,
+ seg->rlog_lv->size,
+ rlog_dlid,
+ seg->rlog_type,
+ rsite->site_index,
+ action,
+ rsite->fall_behind_timeout,
+ rsite->fall_behind_data,
+ rsite->fall_behind_ios)) {
+ if (rsite->site_index == 0) {
+ log_error("Failed to add replicator log '%s' "
+ "to replicator '%s'.",
+ rlog_dlid, seg->lv->name);
+ return 0;
+ }
+ // FIXME:
+ }
+ }
+
+ return 1;
+}
+
+/* FIXME write something useful for replicator here */
+static int _replicator_target_percent(void **target_state, struct dm_pool *mem,
+ struct cmd_context *cmd,
+ struct lv_segment *seg,
+ char *params, uint64_t *total_numerator,
+ uint64_t *total_denominator)
+{
+ struct mirror_state *mirr_state;
+ uint64_t numerator, denominator;
+ unsigned mirror_count, m;
+ int used;
+ char *pos = params;
+
+ //if (!*target_state)
+ // *target_state = _mirrored_init_target(mem, cmd);
+
+ mirr_state = *target_state;
+
+ /* Status line: <#mirrors> (maj:min)+ <synced>/<total_regions> */
+ log_debug("Replicator status: %s", params);
+
+ if (sscanf(pos, "%u %n", &mirror_count, &used) != 1) {
+ log_error("Failure parsing mirror status mirror count: %s.",
+ params);
+ return 0;
+ }
+ pos += used;
+
+ for (m = 0; m < mirror_count; ++m) {
+ if (sscanf(pos, "%*x:%*x %n", &used) != 0) {
+ log_error("Failure parsing mirror status devices: %s.",
+ params);
+ return 0;
+ }
+ pos += used;
+ }
+
+ if (sscanf(pos, "%" PRIu64 "/%" PRIu64 "%n", &numerator, &denominator,
+ &used) != 2) {
+ log_error("Failure parsing replicator status fraction: %s.",
+ params);
+ return 0;
+ }
+ pos += used;
+
+ *total_numerator += numerator;
+ *total_denominator += denominator;
+
+ if (seg)
+ seg->extents_copied = (uint32_t)(seg->area_len * numerator / denominator);
+
+ return 1;
+}
+
+/* Check for module presence */
+static int _replicator_target_present(struct cmd_context *cmd,
+ const struct lv_segment *seg __attribute((unused)),
+ unsigned *attributes __attribute((unused)))
+{
+ static int _checked = 0;
+ static int _present = 0;
+
+ if (!_checked) {
+ _present = target_present(cmd, REPLICATOR_MODULE, 1);
+ _checked = 1;
+ }
+
+ return _present;
+}
+
+#endif
+
+static int _replicator_modules_needed(struct dm_pool *mem,
+ const struct lv_segment *seg __attribute((unused)),
+ struct dm_list *modules)
+{
+ if (!str_list_add(mem, modules, REPLICATOR_MODULE))
+ return_0;
+
+ return 1;
+}
+
+static void _replicator_destroy(const struct segment_type *segtype)
+{
+ dm_free((void *)segtype);
+}
+
+static struct segtype_handler _replicator_ops = {
+ .name = _replicator_name,
+ .display = _replicator_display,
+ .text_import = _replicator_text_import,
+ .text_export = _replicator_text_export,
+#ifdef DEVMAPPER_SUPPORT
+ .add_target_line = _replicator_add_target_line,
+ .target_percent = _replicator_target_percent,
+ .target_present = _replicator_target_present,
+#endif
+ .modules_needed = _replicator_modules_needed,
+ .destroy = _replicator_destroy,
+};
+
+/*
+ * Replicator-dev target
+ */
+static void _replicator_dev_display(const struct lv_segment *seg)
+{
+ //const char *size;
+ //uint32_t s;
+
+ log_print(" Replicator\t\t%u", seg->area_count);
+ log_print(" Mirror size\t\t%u", seg->area_len);
+ if (seg->log_lv)
+ log_print(" Replicator log volume\t%s", seg->rlog_lv->name);
+
+}
+
+static int _add_device(struct lv_segment *seg,
+ const char *site_name,
+ const struct config_node *sn)
+{
+ struct dm_pool *mem = seg->lv->vg->vgmem;
+ struct logical_volume *lv = NULL;
+ struct logical_volume *slog_lv = NULL;
+ struct replicator_site *rsite = _get_site(seg->replicator, site_name);
+ struct replicator_device *rdev;
+ const char *dev_str = NULL;
+ const char *slog_str = NULL;
+ const struct config_node *cn;
+
+ if ((cn = find_config_node(sn, "sync_log"))) {
+ if (!cn->v || !cn->v->v.str)
+ return SEG_LOG_ERROR("Sync log must be a string in");
+ slog_str = cn->v->v.str;
+ }
+
+ if (!(cn = find_config_node(sn, "logical_volume")) ||
+ !cn->v || !cn->v->v.str)
+ return SEG_LOG_ERROR("Logical volume must be a string in");
+
+ dev_str = cn->v->v.str;
+
+ if (!seg->lv->rdevice) {
+ if (slog_str)
+ return SEG_LOG_ERROR("Sync log %s defined for local "
+ "device in", slog_str);
+
+ // check for device in current VG
+ if (!(lv = find_lv(seg->lv->vg, dev_str)))
+ return SEG_LOG_ERROR("Logical volume %s not found in",
+ dev_str);
+ } else {
+ if (!slog_str)
+ return SEG_LOG_ERROR("Sync log is missing for remote "
+ "device in");
+ if (!(slog_lv = find_lv(seg->lv->vg, slog_str)))
+ return SEG_LOG_ERROR("Sync log %s not found in",
+ slog_str);
+ }
+
+ // check for slog device in current VG
+
+ if (!(rdev = dm_pool_zalloc(mem, sizeof(*rdev))))
+ return_0;
+
+ if (!(rdev->name = dm_pool_strdup(mem, dev_str)))
+ return_0;
+
+ rdev->replicator_dev = seg;
+ rdev->rsite = rsite;
+
+ if (!seg->lv->rdevice) {
+ lvm_replicator_dev_add_rimage(rdev, lv);
+ seg->lv->rdevice = rdev;
+ } else {
+ if (!slog_str ||
+ !(rdev->slog_name = dm_pool_strdup(mem, slog_str)))
+ return_0;
+
+ lvm_replicator_dev_add_slog(rdev, slog_lv);
+ }
+
+ dm_list_add(&rsite->rdevices, &rdev->list);// linked site list
+
+ return 1;
+}
+
+/* Import replicator segment */
+static int _replicator_dev_text_import(struct lv_segment *seg,
+ const struct config_node *sn,
+ struct dm_hash_table *pv_hash __attribute((unused)))
+{
+ const struct config_node *cn;
+ struct logical_volume *replicator;
+
+ if (!(cn = find_config_node(sn, "replicator")))
+ return SEG_LOG_ERROR("Replicator is missing for");
+
+ if (!cn->v || !cn->v->v.str)
+ return SEG_LOG_ERROR("Replicator must be a string for");
+
+ if (!(replicator = find_lv(seg->lv->vg, cn->v->v.str)))
+ return SEG_LOG_ERROR("Unknown replicator %s for", cn->v->v.str);
+
+ if (!lvm_replicator_add_dev(replicator, seg))
+ return_0;
+
+ log_very_verbose("replicator=%s", replicator->name);
+
+ // mandatory!!
+ if (!find_config_node(sn, "device_index"))
+ return SEG_LOG_ERROR("Missing device index for");
+
+ // read devices from sites
+ for (; sn; sn = sn->sib)
+ if (!(sn->v) && !_add_device(seg, sn->key, sn->child))
+ return 0;
+
+ if (seg->lv->rdevice)
+ seg->lv->rdevice->device_index = _get_config_uint64(sn, "device_index", 0);
+
+ seg->rlog_lv = NULL;
+ seg->lv->status |= REPLICATOR;
+
+ return 1;
+}
+
+/* Export replicator-dev segment */
+static int _replicator_dev_text_export(const struct lv_segment *seg,
+ struct formatter *f)
+{
+ const struct replicator_site *rsite;
+ const struct replicator_device *rdev;
+
+ if (!seg->replicator || !seg->lv->rdevice)
+ return_0;
+
+ outf(f, "replicator = \"%s\"", seg->replicator->name);
+ outf(f, "device_index = %" PRId64, seg->lv->rdevice->device_index);
+
+ out_newline(f);
+
+ dm_list_iterate_items(rsite, &seg->replicator->rsites) {
+ dm_list_iterate_items(rdev, &rsite->rdevices) {
+ if (rdev->replicator_dev != seg)
+ continue;
+
+ outf(f, "%s {", rdev->rsite->name);
+
+ out_inc_indent(f);
+
+ outf(f, "logical_volume = \"%s\"",
+ rdev->name ? rdev->name : rdev->lv->name);
+
+ if (rdev->slog)
+ outf(f, "sync_log = \"%s\"", rdev->slog->name);
+ else if (rdev->slog_name)
+ outf(f, "sync_log = \"%s\"", rdev->slog_name);
+
+ out_dec_indent(f);
+
+ outf(f, "}");
+ }
+ }
+
+ return 1;
+}
+
+#ifdef DEVMAPPER_SUPPORT
+/*
+ * Add target for passive site matching the device index
+ */
+static int _replicator_dev_add_target_line(struct dev_manager *dm,
+ struct dm_pool *mem,
+ struct cmd_context *cmd,
+ void **target_state,
+ struct lv_segment *seg,
+ struct dm_tree_node *node,
+ uint64_t len,
+ uint32_t *pvmove_mirror_count)
+{
+ const char *replicator_dlid, *rdev_dlid, *slog_dlid;
+ const struct replicator_device *rdev, *rdev_search;
+ const struct replicator_site *rsite;
+ char *rdev_path; /* needed for write */
+ uint32_t slog_size;
+ uint32_t slog_flags;
+
+ if (!lv_is_active_replicator_dev(seg->lv)) {
+ /* Create passive linear mapping */
+ log_very_verbose("Inactive replicator %s using %s.",
+ seg->lv->name, seg->lv->rdevice->lv->name);
+ if (!dm_tree_node_add_linear_target(node, seg->lv->size))
+ return_0;
+ if (!(rdev_dlid = build_dlid(dm, seg->lv->rdevice->lv->lvid.s, NULL)))
+ return_0;
+ return dm_tree_node_add_target_area(node, NULL, rdev_dlid, 0);
+ } else if (seg->lv->rdevice->rsite->site_index) {
+ log_error("Active site with site_index != 0 (%s, %d)",
+ seg->lv->rdevice->rsite->name,
+ seg->lv->rdevice->rsite->site_index);
+ return 0; /* replicator without any active site */
+ }
+
+ /*
+ * At this point all devices that have some connection with replicator
+ * must be present in dm_tree
+ */
+ if (!seg_is_replicator_dev(seg) ||
+ !(replicator_dlid = build_dlid(dm, seg->replicator->lvid.s, NULL)))
+ return_0;
+
+ /* Select remote devices with the same device index */
+ dm_list_iterate_items(rsite, &seg->replicator->rsites) {
+ if (rsite->site_index == 0) {
+ /* local slink0 device */
+ rdev = seg->lv->rdevice;
+ } else {
+ rdev = NULL;
+ dm_list_iterate_items(rdev_search, &rsite->rdevices) {
+ if (rdev_search->replicator_dev == seg) {
+ rdev = rdev_search;
+ break;
+ }
+ }
+
+ if (!rdev) {
+ log_error("Internal rdev list error");
+ return 0;
+ }
+ }
+
+ if (rdev->lv) {
+ if (!(rdev_dlid = build_dlid(dm, rdev->lv->lvid.s, NULL)))
+ return_0;
+ } else {
+ /* (?debug?) support remote device nodes */
+ if (!rdev->rsite->vg_name || !rdev->name)
+ return_0;
+
+ /* FIXME:
+ * vg_read/_process_one_vg needs to be fixed to locate and lock remote vg
+ * so we can use
+ * lv = find_lv(rdev->rsite->vg, rdev->name);
+ * if (!lv || !(rdev_dlid = build_dm_name(mem, rdev->rsite->vg, lv->lvid.s, NULL)))
+ * return_0;
+ *
+ * meanwhile use solution vg_name + name
+ */
+ if (!(rdev_path = dm_pool_alloc(mem, strlen(rdev->rsite->replicator->vg->cmd->dev_dir) +
+ strlen(rdev->rsite->vg_name) +
+ strlen(rdev->name) + 2)))
+ return_0;
+
+ sprintf(rdev_path, "%s%s/%s",
+ rdev->rsite->replicator->vg->cmd->dev_dir,
+ rdev->rsite->vg_name, rdev->name);
+ rdev_dlid = rdev_path;
+ }
+
+ slog_dlid = NULL;
+ /* using either disk or core (in memory) log */
+#if 0
+ /* HACK: avoid using slog device - currently kernel driver is broken */
+ slog_flags = DM_CORELOG | DM_FORCESYNC;
+ slog_size = 2048;
+#else
+ if (rdev->slog) {
+ slog_flags = DM_NOSYNC;
+ slog_size = rdev->slog->size;
+ if (!(slog_dlid = build_dlid(dm, rdev->slog->lvid.s, NULL)))
+ return_0;
+ slog_size = 2048; // FIXME: HACK
+ } else if (rdev->slog_name &&
+ sscanf(rdev->slog_name, "%" PRIu32, &slog_size) == 1) {
+ slog_flags = DM_CORELOG | DM_FORCESYNC;
+ if (slog_size == 0) {
+ log_error("Failed to use empty corelog size in replicator '%s'.",
+ rsite->replicator->name);
+ return 0;
+ }
+ } else {
+ slog_flags = DM_CORELOG | DM_FORCESYNC;
+ slog_size = 0; // NOLOG
+ }
+
+#endif
+ if (!dm_tree_node_add_replicator_dev_target(node,
+ seg->lv->size,
+ replicator_dlid,
+ seg->lv->rdevice->device_index,
+ rdev_dlid, /* rdev_uuid/path */
+ rsite->site_index,
+ slog_dlid,
+ slog_flags,
+ slog_size)) {
+ //if (seg->lv->rdevice->device_index == 0)
+ return_0;
+
+ /*
+ * FIXME: add 'state = dropped'
+ */
+
+ // CHECKME: is it fatal or just warning here ?? */
+ log_warn("Failed to add LV '%s' to replicator '%s'.",
+ rdev->name, rsite->replicator->name);
+ return 1;
+ }
+ }
+
+ return 1;
+}
+
+/* FIXME write something useful for replicator here */
+static int _replicator_dev_target_percent(void **target_state,
+ struct dm_pool *mem,
+ struct cmd_context *cmd,
+ struct lv_segment *seg,
+ char *params,
+ uint64_t *total_numerator,
+ uint64_t *total_denominator)
+{
+ struct mirror_state *mirr_state;
+ uint64_t numerator, denominator;
+ unsigned mirror_count, m;
+ int used;
+ char *pos = params;
+
+ //if (!*target_state)
+ // *target_state = _mirrored_init_target(mem, cmd);
+
+ mirr_state = *target_state;
+
+ /* Status line: <#mirrors> (maj:min)+ <synced>/<total_regions> */
+ log_debug("Replicator status: %s", params);
+
+ if (sscanf(pos, "%u %n", &mirror_count, &used) != 1) {
+ log_error("Failure parsing mirror status mirror count: %s.",
+ params);
+ return 0;
+ }
+ pos += used;
+
+ for (m = 0; m < mirror_count; ++m) {
+ if (sscanf(pos, "%*x:%*x %n", &used) != 0) {
+ log_error("Failure parsing mirror status devices: %s.",
+ params);
+ return 0;
+ }
+ pos += used;
+ }
+
+ if (sscanf(pos, "%" PRIu64 "/%" PRIu64 "%n", &numerator, &denominator,
+ &used) != 2) {
+ log_error("Failure parsing replicator status fraction: %s.",
+ params);
+ return 0;
+ }
+ pos += used;
+
+ *total_numerator += numerator;
+ *total_denominator += denominator;
+
+ if (seg)
+ seg->extents_copied = (uint32_t)(seg->area_len * numerator / denominator);
+
+ return 1;
+}
+
+/* Check for module presence */
+static int _replicator_dev_target_present(struct cmd_context *cmd,
+ const struct lv_segment *seg __attribute((unused)),
+ unsigned *attributes __attribute((unused)))
+{
+ static int _checked = 0;
+ static int _present = 0;
+
+ if (!_checked) {
+ _present = target_present(cmd, REPLICATOR_DEV_MODULE, 1);
+ _checked = 1;
+ }
+
+ return _present;
+}
+
+#endif
+
+static int _replicator_dev_modules_needed(struct dm_pool *mem,
+ const struct lv_segment *seg __attribute((unused)),
+ struct dm_list *modules)
+{
+ if (!str_list_add(mem, modules, REPLICATOR_DEV_MODULE))
+ return_0;
+
+ return 1;
+}
+
+static struct segtype_handler _replicator_dev_ops = {
+ .name = _replicator_name,
+ .display = _replicator_dev_display,
+ .text_import = _replicator_dev_text_import,
+ .text_export = _replicator_dev_text_export,
+#ifdef DEVMAPPER_SUPPORT
+ .add_target_line = _replicator_dev_add_target_line,
+ .target_percent = _replicator_dev_target_percent,
+ .target_present = _replicator_dev_target_present,
+#endif
+ .modules_needed = _replicator_dev_modules_needed,
+ .destroy = _replicator_destroy,
+};
+
+#ifdef REPLICATOR_INTERNAL
+int init_replicator_segtype(struct segtype_library *seglib)
+#else /* Shared */
+int init_multiple_segtype(struct segtype_library *seglib);
+int init_multiple_segtype(struct segtype_library *seglib)
+#endif
+{
+ struct segment_type *segtype;
+
+ if (!(segtype = dm_malloc(sizeof(*segtype))))
+ return_0;
+
+ segtype->ops = &_replicator_ops;
+ segtype->name = REPLICATOR_MODULE;
+ segtype->private = NULL;
+ segtype->flags = SEG_REPLICATOR;
+
+ if (!lvm_register_segtype(seglib, segtype))
+ return 0;
+
+ log_very_verbose("Initialised segtype: " REPLICATOR_MODULE);
+
+ if (!(segtype = dm_malloc(sizeof(*segtype))))
+ return_0;
+
+ segtype->ops = &_replicator_dev_ops;
+ segtype->name = REPLICATOR_DEV_MODULE;
+ segtype->private = NULL;
+ segtype->flags = SEG_REPLICATOR_DEV;
+
+ if (!lvm_register_segtype(seglib, segtype))
+ return 0;
+
+ log_very_verbose("Initialised segtype: " REPLICATOR_DEV_MODULE);
+
+ return 1;
+}
--
1.6.5.rc2
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 04/13] Replicator: new variable in generated file
2009-10-05 14:00 ` [PATCH 03/13] Replicator: add lvm support Zdenek Kabelac
@ 2009-10-05 14:00 ` Zdenek Kabelac
2009-10-05 14:00 ` [PATCH 05/13] Replicator: use dm_tree_suspend_children Zdenek Kabelac
2009-10-07 15:07 ` [PATCH 03/13] Replicator: add lvm support Alasdair G Kergon
1 sibling, 1 reply; 23+ messages in thread
From: Zdenek Kabelac @ 2009-10-05 14:00 UTC (permalink / raw)
To: lvm-devel
---
lib/misc/configure.h.in | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/lib/misc/configure.h.in b/lib/misc/configure.h.in
index 4273eeb..a49cd6e 100644
--- a/lib/misc/configure.h.in
+++ b/lib/misc/configure.h.in
@@ -419,6 +419,9 @@
/* Define to 1 to include the LVM readline shell. */
#undef READLINE_SUPPORT
+/* Define to 1 to include built-in support for replicator. */
+#undef REPLICATOR_INTERNAL
+
/* Define as the return type of signal handlers (`int' or `void'). */
#undef RETSIGTYPE
--
1.6.5.rc2
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 05/13] Replicator: use dm_tree_suspend_children
2009-10-05 14:00 ` [PATCH 04/13] Replicator: new variable in generated file Zdenek Kabelac
@ 2009-10-05 14:00 ` Zdenek Kabelac
2009-10-05 14:00 ` [PATCH 06/13] Replicator: extend _lv_each_dependency() rep. deps Zdenek Kabelac
0 siblings, 1 reply; 23+ messages in thread
From: Zdenek Kabelac @ 2009-10-05 14:00 UTC (permalink / raw)
To: lvm-devel
Before of suspend/deactivation of replicator_dev node
the suspend of replicator node is mandatory.
Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
lib/activate/dev_manager.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
index 19deab8..55daf14 100644
--- a/lib/activate/dev_manager.c
+++ b/lib/activate/dev_manager.c
@@ -1169,6 +1169,7 @@ static int _clean_tree(struct dev_manager *dm, struct dm_tree_node *root)
continue;
dm_tree_set_cookie(root, 0);
+ dm_tree_suspend_children(root, uuid, strlen(uuid), 1);
r = dm_tree_deactivate_children(root, uuid, strlen(uuid));
if (!dm_udev_wait(dm_tree_get_cookie(root)))
stack;
@@ -1208,6 +1209,7 @@ static int _tree_action(struct dev_manager *dm, struct logical_volume *lv, actio
case DEACTIVATE:
/* Deactivate LV and all devices it references that nothing else has open. */
dm_tree_set_cookie(root, 0);
+ dm_tree_suspend_children(root, dlid, ID_LEN + sizeof(UUID_PREFIX) - 1, 1);
r = dm_tree_deactivate_children(root, dlid, ID_LEN + sizeof(UUID_PREFIX) - 1);
if (!dm_udev_wait(dm_tree_get_cookie(root)))
stack;
--
1.6.5.rc2
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 06/13] Replicator: extend _lv_each_dependency() rep. deps
2009-10-05 14:00 ` [PATCH 05/13] Replicator: use dm_tree_suspend_children Zdenek Kabelac
@ 2009-10-05 14:00 ` Zdenek Kabelac
2009-10-05 14:00 ` [PATCH 07/13] Replicator: update _create_partial_dtree() Zdenek Kabelac
0 siblings, 1 reply; 23+ messages in thread
From: Zdenek Kabelac @ 2009-10-05 14:00 UTC (permalink / raw)
To: lvm-devel
Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
lib/metadata/metadata.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index 263c705..feb7cc1 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -1850,6 +1850,8 @@ static int _lv_each_dependency(struct logical_volume *lv,
struct lv_segment *lvseg;
struct logical_volume *deps[] = {
+ (lv->rdevice && lv != lv->rdevice->lv) ? lv->rdevice->lv : 0,
+ (lv->rdevice && lv != lv->rdevice->slog) ? lv->rdevice->slog : 0,
lv->snapshot ? lv->snapshot->origin : 0,
lv->snapshot ? lv->snapshot->cow : 0 };
for (i = 0; i < sizeof(deps) / sizeof(*deps); ++i) {
@@ -1860,6 +1862,8 @@ static int _lv_each_dependency(struct logical_volume *lv,
dm_list_iterate_items(lvseg, &lv->segments) {
if (lvseg->log_lv && !fn(lvseg->log_lv, data))
return_0;
+ if (lvseg->rlog_lv && !fn(lvseg->rlog_lv, data))
+ return_0;
for (s = 0; s < lvseg->area_count; ++s) {
if (seg_type(lvseg, s) == AREA_LV && !fn(seg_lv(lvseg,s), data))
return_0;
--
1.6.5.rc2
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 07/13] Replicator: update _create_partial_dtree()
2009-10-05 14:00 ` [PATCH 06/13] Replicator: extend _lv_each_dependency() rep. deps Zdenek Kabelac
@ 2009-10-05 14:00 ` Zdenek Kabelac
2009-10-05 14:00 ` [PATCH 08/13] Replicator: add replicator/_dev to dtree Zdenek Kabelac
0 siblings, 1 reply; 23+ messages in thread
From: Zdenek Kabelac @ 2009-10-05 14:00 UTC (permalink / raw)
To: lvm-devel
Creating partial tree for Replicator target.
Using dm_tree_set_priority() to set higher priority for Replicator.
Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
lib/activate/dev_manager.c | 27 ++++++++++++++++++++++++++-
1 files changed, 26 insertions(+), 1 deletions(-)
diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
index 55daf14..8ad737b 100644
--- a/lib/activate/dev_manager.c
+++ b/lib/activate/dev_manager.c
@@ -730,6 +730,9 @@ static struct dm_tree *_create_partial_dtree(struct dev_manager *dm, struct logi
struct dm_list *snh, *snht;
struct lv_segment *seg;
uint32_t s;
+ struct replicator_device *rdev;
+ struct replicator_site *rsite;
+ const char *replog_dlid;
if (!(dtree = dm_tree_create())) {
log_error("Partial dtree creation failed for %s.", lv->name);
@@ -745,12 +748,34 @@ static struct dm_tree *_create_partial_dtree(struct dev_manager *dm, struct logi
goto_bad;
/* Add any LVs used by segments in this LV */
- dm_list_iterate_items(seg, &lv->segments)
+ dm_list_iterate_items(seg, &lv->segments) {
for (s = 0; s < seg->area_count; s++)
if (seg_type(seg, s) == AREA_LV && seg_lv(seg, s)) {
if (!_add_lv_to_dtree(dm, dtree, seg_lv(seg, s)))
goto_bad;
}
+ if (seg->replicator) {
+ /* Add all replicator-dev from same replicator */
+ dm_list_iterate_items(rsite, &seg->replicator->rsites) {
+ dm_list_iterate_items(rdev, &rsite->rdevices) {
+ if (rsite->state == REPLICATOR_STATE_ACTIVE) {
+ if (!rdev->replicator_dev->lv)
+ goto_bad;
+ if (lv == rdev->replicator_dev->lv)
+ continue;
+ /* Add replicator-dev LV */
+ if (!_add_lv_to_dtree(dm, dtree, rdev->replicator_dev->lv))
+ goto_bad;
+ }
+ }
+ }
+
+ if (!(replog_dlid = build_dlid(dm, seg->replicator->lvid.s, NULL)))
+ goto_bad;
+ if (!dm_tree_set_priority(dtree, replog_dlid, 1))
+ goto_bad;
+ }
+ }
return dtree;
--
1.6.5.rc2
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 08/13] Replicator: add replicator/_dev to dtree
2009-10-05 14:00 ` [PATCH 07/13] Replicator: update _create_partial_dtree() Zdenek Kabelac
@ 2009-10-05 14:00 ` Zdenek Kabelac
2009-10-05 14:00 ` [PATCH 09/13] Replicator: do not remove of replicators' LVs Zdenek Kabelac
0 siblings, 1 reply; 23+ messages in thread
From: Zdenek Kabelac @ 2009-10-05 14:00 UTC (permalink / raw)
To: lvm-devel
Adding all replicator related LVs to dtree.
Start of one replicator_dev initiate start of all other related.
Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
lib/activate/dev_manager.c | 40 +++++++++++++++++++++++++++++++++++++++-
1 files changed, 39 insertions(+), 1 deletions(-)
diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
index 8ad737b..ce2d7bf 100644
--- a/lib/activate/dev_manager.c
+++ b/lib/activate/dev_manager.c
@@ -950,6 +950,38 @@ static int _add_target_to_dtree(struct dev_manager *dm,
static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
struct logical_volume *lv, const char *layer);
+/* Add all replicators' LVs from active segment */
+static int _add_replicator_dev_target_to_dtree(struct dev_manager *dm,
+ struct dm_tree *dtree,
+ struct lv_segment *seg)
+{
+ struct replicator_device *rdev;
+ struct replicator_site *rsite;
+
+ if (lv_is_active_replicator_dev(seg->lv)) {
+ /* activation of one replicator node activate all other nodes */
+ if (!seg->replicator ||
+ !_add_new_lv_to_dtree(dm, dtree, seg->replicator, NULL))
+ return_0;
+
+ dm_list_iterate_items(rsite, &seg->replicator->rsites) {
+ dm_list_iterate_items(rdev, &rsite->rdevices) {
+ if (rdev->slog && !_add_new_lv_to_dtree(dm, dtree, rdev->slog, NULL))
+ return_0;
+ if (rsite->state == REPLICATOR_STATE_ACTIVE &&
+ (!rdev->lv ||
+ !_add_new_lv_to_dtree(dm, dtree, rdev->lv, NULL) ||
+ !rdev->replicator_dev->lv ||
+ !_add_new_lv_to_dtree(dm, dtree, rdev->replicator_dev->lv, NULL)))
+ return_0;
+ }
+ }
+ } else if (!_add_new_lv_to_dtree(dm, dtree, seg->lv->rdevice->lv, NULL))
+ return_0;
+
+ return 1;
+}
+
static int _add_segment_to_dtree(struct dev_manager *dm,
struct dm_tree *dtree,
struct dm_tree_node *dnode,
@@ -980,8 +1012,14 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
!_add_new_lv_to_dtree(dm, dtree, seg->log_lv, NULL))
return_0;
+ if (seg_is_replicator_dev(seg)) {
+ if (!_add_replicator_dev_target_to_dtree(dm, dtree, seg))
+ return_0;
+ } else if (seg_is_replicator(seg) && seg->rlog_lv) {
+ if (!_add_new_lv_to_dtree(dm, dtree, seg->rlog_lv, NULL))
+ return_0;
/* If this is a snapshot origin, add real LV */
- if (lv_is_origin(seg->lv) && !layer) {
+ } else if (lv_is_origin(seg->lv) && !layer) {
if (vg_is_clustered(seg->lv->vg)) {
log_error("Clustered snapshots are not yet supported");
return 0;
--
1.6.5.rc2
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 09/13] Replicator: do not remove of replicators' LVs
2009-10-05 14:00 ` [PATCH 08/13] Replicator: add replicator/_dev to dtree Zdenek Kabelac
@ 2009-10-05 14:00 ` Zdenek Kabelac
2009-10-05 14:00 ` [PATCH 10/13] Replicator: activate change for vgchange Zdenek Kabelac
0 siblings, 1 reply; 23+ messages in thread
From: Zdenek Kabelac @ 2009-10-05 14:00 UTC (permalink / raw)
To: lvm-devel
Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
lib/metadata/lv_manip.c | 9 +++++++++
1 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 51e100e..5e21fca 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -2084,6 +2084,15 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
return 0;
}
+ if (lv_is_replicator_dev(lv) ||
+ lv_is_rimage(lv) ||
+ lv_is_rlog(lv) ||
+ lv_is_slog(lv)) {
+ log_error("Can't remove logical volume %s used by a replicator",
+ lv->name);
+ return 0;
+ }
+
if (lv->status & LOCKED) {
log_error("Can't remove locked LV %s", lv->name);
return 0;
--
1.6.5.rc2
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 10/13] Replicator: activate change for vgchange
2009-10-05 14:00 ` [PATCH 09/13] Replicator: do not remove of replicators' LVs Zdenek Kabelac
@ 2009-10-05 14:00 ` Zdenek Kabelac
2009-10-05 14:00 ` [PATCH 11/13] Replicator: add new options for replicator Zdenek Kabelac
0 siblings, 1 reply; 23+ messages in thread
From: Zdenek Kabelac @ 2009-10-05 14:00 UTC (permalink / raw)
To: lvm-devel
Activate only replicator-dev segment. Activation of one segment will
activivate also all other related heads.
Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
tools/vgchange.c | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/tools/vgchange.c b/tools/vgchange.c
index 07d5262..78660be 100644
--- a/tools/vgchange.c
+++ b/tools/vgchange.c
@@ -69,6 +69,11 @@ static int _activate_lvs_in_vg(struct cmd_context *cmd,
if ((lv->status & MIRROR_IMAGE) || (lv->status & MIRROR_LOG))
continue;
+ /* Only request activation of replicator device LV */
+ if (lv_is_rlog(lv) || lv_is_slog(lv) || lv_is_rimage(lv) ||
+ lv_is_replicator(lv))
+ continue;
+
/* Can't deactivate a pvmove LV */
/* FIXME There needs to be a controlled way of doing this */
if (((activate == CHANGE_AN) || (activate == CHANGE_ALN)) &&
--
1.6.5.rc2
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 11/13] Replicator: add new options for replicator
2009-10-05 14:00 ` [PATCH 10/13] Replicator: activate change for vgchange Zdenek Kabelac
@ 2009-10-05 14:00 ` Zdenek Kabelac
2009-10-05 14:00 ` [PATCH 12/13] Replicator: update copyright dates Zdenek Kabelac
0 siblings, 1 reply; 23+ messages in thread
From: Zdenek Kabelac @ 2009-10-05 14:00 UTC (permalink / raw)
To: lvm-devel
New options: addsite, delsite, replicator,
replicatorlog, replicatorlogtype
Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
tools/args.h | 5 +++++
tools/commands.h | 10 ++++++++--
tools/lvcreate.c | 17 +++++++++++++++++
tools/lvmcmdline.c | 10 ++++++++++
tools/tools.h | 1 +
5 files changed, 41 insertions(+), 2 deletions(-)
diff --git a/tools/args.h b/tools/args.h
index 1204683..f3b61b7 100644
--- a/tools/args.h
+++ b/tools/args.h
@@ -63,6 +63,11 @@ arg(dataalignmentoffset_ARG, '\0', "dataalignmentoffset", size_kb_arg, 0)
arg(virtualoriginsize_ARG, '\0', "virtualoriginsize", size_mb_arg, 0)
arg(virtualsize_ARG, '\0', "virtualsize", size_mb_arg, 0)
arg(noudevsync_ARG, '\0', "noudevsync", NULL, 0)
+arg(replicator_ARG, '\0', "replicator", NULL, 0)
+arg(replicatorlog_ARG, '\0', "replicatorlog", NULL, 0)
+arg(replicatorlogtype_ARG, '\0', "replicatorlogtype", NULL, 0)
+arg(addsite_ARG, '\0', "addsite", site_arg, 0)
+arg(delsite_ARG, '\0', "delsite", site_arg, 0)
/* Allow some variations */
arg(resizable_ARG, '\0', "resizable", yes_no_arg, 0)
diff --git a/tools/commands.h b/tools/commands.h
index 73ebd0b..fbf59b2 100644
--- a/tools/commands.h
+++ b/tools/commands.h
@@ -63,10 +63,12 @@ xx(lvchange,
"\t[-A|--autobackup y|n]\n"
"\t[-a|--available [e|l]y|n]\n"
"\t[--addtag Tag]\n"
+ "\t[--addsite Site]\n"
"\t[--alloc AllocationPolicy]\n"
"\t[-C|--contiguous y|n]\n"
"\t[-d|--debug]\n"
"\t[--deltag Tag]\n"
+ "\t[--delsite Site]\n"
"\t[-f|--force]\n"
"\t[-h|--help]\n"
"\t[--ignorelockingfailure]\n"
@@ -89,7 +91,7 @@ xx(lvchange,
ignorelockingfailure_ARG, ignoremonitoring_ARG, major_ARG, minor_ARG,
monitor_ARG, noudevsync_ARG, partial_ARG, permission_ARG, persistent_ARG,
readahead_ARG, resync_ARG, refresh_ARG, addtag_ARG, deltag_ARG, test_ARG,
- yes_ARG)
+ addsite_ARG, delsite_ARG, yes_ARG)
xx(lvconvert,
"Change logical volume layout",
@@ -145,6 +147,9 @@ xx(lvcreate,
"\t[-p|--permission {r|rw}]\n"
"\t[-r|--readahead ReadAheadSectors|auto|none]\n"
"\t[-R|--regionsize MirrorLogRegionSize]\n"
+ "\t[--replicator]\n"
+ "\t[--replicatorlog LogicalVolumeName]\n"
+ "\t[--replicatorlogtype ringbuffer]\n"
"\t[-t|--test]\n"
"\t[--type VolumeType]\n"
"\t[-v|--verbose]\n"
@@ -179,7 +184,8 @@ xx(lvcreate,
addtag_ARG, alloc_ARG, autobackup_ARG, chunksize_ARG, contiguous_ARG,
corelog_ARG, extents_ARG, major_ARG, minor_ARG, mirrorlog_ARG, mirrors_ARG,
name_ARG, nosync_ARG, noudevsync_ARG, permission_ARG, persistent_ARG,
- readahead_ARG, regionsize_ARG, size_ARG, snapshot_ARG, stripes_ARG,
+ readahead_ARG, regionsize_ARG, replicator_ARG, replicatorlog_ARG,
+ replicatorlogtype_ARG, size_ARG, snapshot_ARG, stripes_ARG,
stripesize_ARG, test_ARG, type_ARG, virtualoriginsize_ARG, virtualsize_ARG,
zero_ARG)
diff --git a/tools/lvcreate.c b/tools/lvcreate.c
index be6b5cc..c655a2b 100644
--- a/tools/lvcreate.c
+++ b/tools/lvcreate.c
@@ -405,6 +405,9 @@ static int _lvcreate_params(struct lvcreate_params *lp,
if (seg_is_mirrored(lp))
lp->mirrors = 2;
+ if (seg_is_replicator(lp) || arg_count(cmd, replicator_ARG))
+ lp->replicator = 1;
+
if (arg_count(cmd, mirrors_ARG)) {
lp->mirrors = arg_uint_value(cmd, mirrors_ARG, 0) + 1;
if (lp->mirrors == 1)
@@ -469,6 +472,20 @@ static int _lvcreate_params(struct lvcreate_params *lp,
}
}
+ if (lp->replicator) {
+ log_error("--replicator for replicators");
+
+ } else {
+ if (arg_count(cmd, replicatorlog_ARG)) {
+ log_error("--replicatorlog is only available with replicators");
+ return 0;
+ }
+ if (arg_count(cmd, replicatorlogtype_ARG)) {
+ log_error("--replicatorlogtype is only available with replicators");
+ return 0;
+ }
+ }
+
if (activation() && lp->segtype->ops->target_present &&
!lp->segtype->ops->target_present(cmd, NULL, NULL)) {
log_error("%s: Required device-mapper target(s) not "
diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c
index 80c1a46..f3c0e21 100644
--- a/tools/lvmcmdline.c
+++ b/tools/lvmcmdline.c
@@ -483,6 +483,16 @@ int readahead_arg(struct cmd_context *cmd __attribute((unused)), struct arg *a)
return 1;
}
+int site_arg(struct cmd_context *cmd __attribute((unused)), struct arg *a)
+{
+ char *pos = a->value;
+ if (!validate_name(pos))
+ return 0;
+
+ return 1;
+}
+
+
static void __alloc(int size)
{
if (!(_cmdline.commands = dm_realloc(_cmdline.commands, sizeof(*_cmdline.commands) * size))) {
diff --git a/tools/tools.h b/tools/tools.h
index 3afa1a1..67b2178 100644
--- a/tools/tools.h
+++ b/tools/tools.h
@@ -151,6 +151,7 @@ int units_arg(struct cmd_context *cmd, struct arg *a);
int segtype_arg(struct cmd_context *cmd, struct arg *a);
int alloc_arg(struct cmd_context *cmd, struct arg *a);
int readahead_arg(struct cmd_context *cmd, struct arg *a);
+int site_arg(struct cmd_context *cmd, struct arg *a);
/* we use the enums to access the switches */
unsigned int arg_count(const struct cmd_context *cmd, int a);
--
1.6.5.rc2
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 12/13] Replicator: update copyright dates
2009-10-05 14:00 ` [PATCH 11/13] Replicator: add new options for replicator Zdenek Kabelac
@ 2009-10-05 14:00 ` Zdenek Kabelac
2009-10-05 14:00 ` [PATCH 13/13] Replicator: update of generated configure file Zdenek Kabelac
0 siblings, 1 reply; 23+ messages in thread
From: Zdenek Kabelac @ 2009-10-05 14:00 UTC (permalink / raw)
To: lvm-devel
Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
lib/activate/dev_manager.c | 2 +-
lib/metadata/segtype.h | 2 +-
libdm/libdm-deptree.c | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
index ce2d7bf..0a3c30c 100644
--- a/lib/activate/dev_manager.c
+++ b/lib/activate/dev_manager.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
- * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
diff --git a/lib/metadata/segtype.h b/lib/metadata/segtype.h
index 4454cb2..009a199 100644
--- a/lib/metadata/segtype.h
+++ b/lib/metadata/segtype.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
- * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
diff --git a/libdm/libdm-deptree.c b/libdm/libdm-deptree.c
index 4fc625f..d80b13b 100644
--- a/libdm/libdm-deptree.c
+++ b/libdm/libdm-deptree.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2005-2009 Red Hat, Inc. All rights reserved.
*
* This file is part of the device-mapper userspace tools.
*
--
1.6.5.rc2
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 13/13] Replicator: update of generated configure file
2009-10-05 14:00 ` [PATCH 12/13] Replicator: update copyright dates Zdenek Kabelac
@ 2009-10-05 14:00 ` Zdenek Kabelac
0 siblings, 0 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2009-10-05 14:00 UTC (permalink / raw)
To: lvm-devel
---
configure | 34 +++++++++++++++++++++++++++++++++-
1 files changed, 33 insertions(+), 1 deletions(-)
diff --git a/configure b/configure
index ae42377..88ca84c 100755
--- a/configure
+++ b/configure
@@ -654,6 +654,7 @@ SNAPSHOTS
POOL
PKGCONFIG
OWNER
+REPLICATOR
MIRRORS
LVM_RELEASE_DATE
LVM_RELEASE
@@ -813,6 +814,7 @@ with_pool
with_cluster
with_snapshots
with_mirrors
+with_replicator
enable_readline
enable_realtime
with_clvmd
@@ -1545,6 +1547,8 @@ Optional Packages:
TYPE=internal
--with-mirrors=TYPE Mirror support: internal/shared/none
TYPE=internal
+ --with-replicator=TYPE Replicator support: internal/shared/none
+ [TYPE=none]
--with-clvmd=TYPE Build cluster LVM Daemon.
The following cluster manager combinations are valid:
* cman,gulm (RHEL4 or equivalent)
@@ -9326,6 +9330,32 @@ _ACEOF
fi
################################################################################
+{ $as_echo "$as_me:$LINENO: checking whether to include replicator" >&5
+$as_echo_n "checking whether to include replicator... " >&6; }
+
+# Check whether --with-replicator was given.
+if test "${with_replicator+set}" = set; then
+ withval=$with_replicator; REPLICATOR="$withval"
+else
+ REPLICATOR="none"
+fi
+
+{ $as_echo "$as_me:$LINENO: result: $REPLICATOR" >&5
+$as_echo "$REPLICATOR" >&6; }
+
+case "$REPLICATOR" in
+ none|shared) ;;
+ internal)
+cat >>confdefs.h <<\_ACEOF
+#define REPLICATOR_INTERNAL 1
+_ACEOF
+ ;;
+ *) { { $as_echo "$as_me:$LINENO: error: --with-replicator parameter invalid ($REPLICATOR)" >&5
+$as_echo "$as_me: error: --with-replicator parameter invalid ($REPLICATOR)" >&2;}
+ { (exit 1); exit 1; }; } ;;
+esac
+
+################################################################################
{ $as_echo "$as_me:$LINENO: checking whether to enable readline" >&5
$as_echo_n "checking whether to enable readline... " >&6; }
# Check whether --enable-readline was given.
@@ -15524,8 +15554,9 @@ LVM_LIBAPI=`echo "$VER" | $AWK -F '[()]' '{print $2}'`
+
################################################################################
-ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile daemons/cmirrord/Makefile daemons/dmeventd/Makefile daemons/dmeventd/libdevmapper-event.pc daemons/dmeventd/plugins/Makefile daemons/dmeventd/plugins/mirror/Makefile daemons/dmeventd/plugins/snapshot/Makefile doc/Makefile include/.symlinks include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile lib/misc/lvm-version.h lib/snapshot/Makefile libdm/Makefile libdm/libdevmapper.pc liblvm/Makefile liblvm/liblvm2app.pc man/Makefile po/Makefile scripts/clvmd_init_red_hat scripts/lvm2_monitoring_init_red_hat scripts/Makefile test/Makefile test/api/Makefile tools/Makefile udev/Makefile"
+ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile daemons/cmirrord/Makefile daemons/dmeventd/Makefile daemons/dmeventd/libdevmapper-event.pc daemons/dmeventd/plugins/Makefile daemons/dmeventd/plugins/mirror/Makefile daemons/dmeventd/plugins/snapshot/Makefile doc/Makefile include/.symlinks include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile lib/replicator/Makefile lib/misc/lvm-version.h lib/snapshot/Makefile libdm/Makefile libdm/libdevmapper.pc liblvm/Makefile liblvm/liblvm2app.pc man/Makefile po/Makefile scripts/clvmd_init_red_hat scripts/lvm2_monitoring_init_red_hat scripts/Makefile test/Makefile test/api/Makefile tools/Makefile udev/Makefile"
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
@@ -16142,6 +16173,7 @@ do
"lib/format_pool/Makefile") CONFIG_FILES="$CONFIG_FILES lib/format_pool/Makefile" ;;
"lib/locking/Makefile") CONFIG_FILES="$CONFIG_FILES lib/locking/Makefile" ;;
"lib/mirror/Makefile") CONFIG_FILES="$CONFIG_FILES lib/mirror/Makefile" ;;
+ "lib/replicator/Makefile") CONFIG_FILES="$CONFIG_FILES lib/replicator/Makefile" ;;
"lib/misc/lvm-version.h") CONFIG_FILES="$CONFIG_FILES lib/misc/lvm-version.h" ;;
"lib/snapshot/Makefile") CONFIG_FILES="$CONFIG_FILES lib/snapshot/Makefile" ;;
"libdm/Makefile") CONFIG_FILES="$CONFIG_FILES libdm/Makefile" ;;
--
1.6.5.rc2
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 02/13] Replicator: add libdm support
2009-10-05 14:00 ` [PATCH 02/13] Replicator: add libdm support Zdenek Kabelac
2009-10-05 14:00 ` [PATCH 03/13] Replicator: add lvm support Zdenek Kabelac
@ 2009-10-07 14:39 ` Alasdair G Kergon
2009-10-08 9:42 ` Petr Rockai
2009-10-08 9:32 ` Petr Rockai
2 siblings, 1 reply; 23+ messages in thread
From: Alasdair G Kergon @ 2009-10-07 14:39 UTC (permalink / raw)
To: lvm-devel
On Mon, Oct 05, 2009 at 04:00:29PM +0200, Zdenek Kabelac wrote:
> int dm_tree_suspend_children(struct dm_tree_node *dnode,
> - const char *uuid_prefix,
> - size_t uuid_prefix_len);
> + const char *uuid_prefix,
> + size_t uuid_prefix_len,
> + int priority);
We can't change the published interface like that.
If there really is no alternative to this parameter then you need to introduce
a new function instead.
Alasdair
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH 01/13] Replicator: export out_ function for modules
2009-10-05 14:00 [PATCH 01/13] Replicator: export out_ function for modules Zdenek Kabelac
2009-10-05 14:00 ` [PATCH 02/13] Replicator: add libdm support Zdenek Kabelac
@ 2009-10-07 15:05 ` Alasdair G Kergon
2009-10-08 11:02 ` Zdenek Kabelac
1 sibling, 1 reply; 23+ messages in thread
From: Alasdair G Kergon @ 2009-10-07 15:05 UTC (permalink / raw)
To: lvm-devel
On Mon, Oct 05, 2009 at 04:00:28PM +0200, Zdenek Kabelac wrote:
> +/* insert new line */
> +int out_newline(struct formatter *f)
> +{
> + outnl(f);
> + return 0;
Should return 1 here, and the caller has to check that.
Instead, I think the outnl macro should be changed to work like the outf one.
(make the 'f->nl' part internal to an export.c function instead of the header file)
The idea was that the callers would be using this so frequently, it was
clearer just writing 'outf(...)' than 'if (!out_text(...)) return_0;' everywhere.
Alasdair
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH 03/13] Replicator: add lvm support
2009-10-05 14:00 ` [PATCH 03/13] Replicator: add lvm support Zdenek Kabelac
2009-10-05 14:00 ` [PATCH 04/13] Replicator: new variable in generated file Zdenek Kabelac
@ 2009-10-07 15:07 ` Alasdair G Kergon
2009-10-08 8:56 ` Zdenek Kabelac
1 sibling, 1 reply; 23+ messages in thread
From: Alasdair G Kergon @ 2009-10-07 15:07 UTC (permalink / raw)
To: lvm-devel
On Mon, Oct 05, 2009 at 04:00:30PM +0200, Zdenek Kabelac wrote:
> lib/metadata/replicator.c | 339 ++++++++++++++
> lib/replicator/replicator.c | 912 ++++++++++++++++++++++++++++++++++++++
Filenames need to be globally unique in this tree: one of those needs
renaming.
Alasdair
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH 03/13] Replicator: add lvm support
2009-10-07 15:07 ` [PATCH 03/13] Replicator: add lvm support Alasdair G Kergon
@ 2009-10-08 8:56 ` Zdenek Kabelac
0 siblings, 0 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2009-10-08 8:56 UTC (permalink / raw)
To: lvm-devel
Dne 7.10.2009 17:07, Alasdair G Kergon napsal(a):
> On Mon, Oct 05, 2009 at 04:00:30PM +0200, Zdenek Kabelac wrote:
>> lib/metadata/replicator.c | 339 ++++++++++++++
>> lib/replicator/replicator.c | 912 ++++++++++++++++++++++++++++++++++++++
>
> Filenames need to be globally unique in this tree: one of those needs
> renaming.
>
> Alasdair
>
lib/metadata/replicator.c -> lib/metadata/replicator_manip.c ?
Zdenek
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH 02/13] Replicator: add libdm support
2009-10-05 14:00 ` [PATCH 02/13] Replicator: add libdm support Zdenek Kabelac
2009-10-05 14:00 ` [PATCH 03/13] Replicator: add lvm support Zdenek Kabelac
2009-10-07 14:39 ` [PATCH 02/13] Replicator: add libdm support Alasdair G Kergon
@ 2009-10-08 9:32 ` Petr Rockai
2 siblings, 0 replies; 23+ messages in thread
From: Petr Rockai @ 2009-10-08 9:32 UTC (permalink / raw)
To: lvm-devel
Hi,
Zdenek Kabelac <zkabelac@redhat.com> writes:
> case SUSPEND_WITH_LOCKFS:
> - if (!dm_tree_suspend_children(root, dlid, ID_LEN + sizeof(UUID_PREFIX) - 1))
> + if (!dm_tree_suspend_children(root, dlid, ID_LEN + sizeof(UUID_PREFIX) - 1, 0))
other than the API change Alasdair pointed out, this bit here changes existing
behaviour (although it may turn out to not affect anything, it would at least
deserve a comment as to why only priority 0 targets should be suspended).
Please also note that just calling this twice, once for 0 and once for 1 does
not correspond to pre-existing behaviour either (it constitutes an ordering
change).
Yours,
Petr.
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH 02/13] Replicator: add libdm support
2009-10-07 14:39 ` [PATCH 02/13] Replicator: add libdm support Alasdair G Kergon
@ 2009-10-08 9:42 ` Petr Rockai
2009-10-09 12:42 ` Zdenek Kabelac
0 siblings, 1 reply; 23+ messages in thread
From: Petr Rockai @ 2009-10-08 9:42 UTC (permalink / raw)
To: lvm-devel
Hi,
Alasdair G Kergon <agk@redhat.com> writes:
> On Mon, Oct 05, 2009 at 04:00:29PM +0200, Zdenek Kabelac wrote:
>> int dm_tree_suspend_children(struct dm_tree_node *dnode,
>> - const char *uuid_prefix,
>> - size_t uuid_prefix_len);
>> + const char *uuid_prefix,
>> + size_t uuid_prefix_len,
>> + int priority);
>
> We can't change the published interface like that.
>
> If there really is no alternative to this parameter then you need to introduce
> a new function instead.
I have discussed this in person with Zden?k, and it seems that the main reason
for this is to allow more atomic suspension of complete replicator.
The normal semantics of DM tree operations is that suspension of a node is done
after all its children are suspended. For replicator, it would be beneficial to
suspend the parent first (to stop the IO stream from the client side) and only
afterwards start suspending the inferior nodes.
In practice, this constitutes only a very slight increase in risk of tripping a
"synchronicity" threshold -- by the amount of data that arrives to the
replicator head in the time frame between a leg is suspended and the replicator
as a whole is suspended -- if this extra data exceeds the amount of free space
in the replicator log, this could trip an extra resync that would be
costly. But it should be stressed, that in these situations, this was already
quite likely to happen, and the outlined problem only increases the chance of
this happening by a small margin.
In other words, I think it is not worth worrying about just yet. At the point
when a dmeventd-style leg dropping is implemented for replicator, this may
become a more pressing problem, but I think the solution should be deferred
until the work on that aspect has begun -- at that time, we ought to have a
clearer picture of the problem area, so it may turn out that a better solution
exists that would not require similar incompatible (and arguably risky) changes
to the libdm core.
Yours,
Petr.
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH 01/13] Replicator: export out_ function for modules
2009-10-07 15:05 ` [PATCH 01/13] Replicator: export out_ function for modules Alasdair G Kergon
@ 2009-10-08 11:02 ` Zdenek Kabelac
2009-10-09 12:47 ` Zdenek Kabelac
0 siblings, 1 reply; 23+ messages in thread
From: Zdenek Kabelac @ 2009-10-08 11:02 UTC (permalink / raw)
To: lvm-devel
Dne 7.10.2009 17:05, Alasdair G Kergon napsal(a):
> On Mon, Oct 05, 2009 at 04:00:28PM +0200, Zdenek Kabelac wrote:
>> +/* insert new line */
>> +int out_newline(struct formatter *f)
>> +{
>> + outnl(f);
>> + return 0;
>
> Should return 1 here, and the caller has to check that.
true
> Instead, I think the outnl macro should be changed to work like the outf one.
> (make the 'f->nl' part internal to an export.c function instead of the header file)
> The idea was that the callers would be using this so frequently, it was
> clearer just writing 'outf(...)' than 'if (!out_text(...)) return_0;' everywhere.
>
> Alasdair
>
So how about this:
+/* insert new line */
+int out_newline(struct formatter *f)
+{
+ return f->nl(f);
+}
+
I think this will be the easiest way - nl() is virtual function thus it can't
be easily 'macro-ised'.
Zdenek
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH 02/13] Replicator: add libdm support
2009-10-08 9:42 ` Petr Rockai
@ 2009-10-09 12:42 ` Zdenek Kabelac
0 siblings, 0 replies; 23+ messages in thread
From: Zdenek Kabelac @ 2009-10-09 12:42 UTC (permalink / raw)
To: lvm-devel
Dne 8.10.2009 11:42, Petr Rockai napsal(a):
> Hi,
>
> Alasdair G Kergon <agk@redhat.com> writes:
>> On Mon, Oct 05, 2009 at 04:00:29PM +0200, Zdenek Kabelac wrote:
>>> int dm_tree_suspend_children(struct dm_tree_node *dnode,
>>> - const char *uuid_prefix,
>>> - size_t uuid_prefix_len);
>>> + const char *uuid_prefix,
>>> + size_t uuid_prefix_len,
>>> + int priority);
>>
>> We can't change the published interface like that.
>>
>> If there really is no alternative to this parameter then you need to introduce
>> a new function instead.
> I have discussed this in person with Zden?k, and it seems that the main reason
> for this is to allow more atomic suspension of complete replicator.
>
> The normal semantics of DM tree operations is that suspension of a node is done
> after all its children are suspended. For replicator, it would be beneficial to
> suspend the parent first (to stop the IO stream from the client side) and only
> afterwards start suspending the inferior nodes.
>
> In practice, this constitutes only a very slight increase in risk of tripping a
> "synchronicity" threshold -- by the amount of data that arrives to the
> replicator head in the time frame between a leg is suspended and the replicator
> as a whole is suspended -- if this extra data exceeds the amount of free space
> in the replicator log, this could trip an extra resync that would be
> costly. But it should be stressed, that in these situations, this was already
> quite likely to happen, and the outlined problem only increases the chance of
> this happening by a small margin.
>
> In other words, I think it is not worth worrying about just yet. At the point
> when a dmeventd-style leg dropping is implemented for replicator, this may
> become a more pressing problem, but I think the solution should be deferred
> until the work on that aspect has begun -- at that time, we ought to have a
> clearer picture of the problem area, so it may turn out that a better solution
> exists that would not require similar incompatible (and arguably risky) changes
> to the libdm core.
The orginal primary idea for my suspend_children patch was the intent to keep
logic inverse to prioritized activation - so what is activated last gets
suspended first - but it seems to be a problematic concept.
So this is my second attempt to suspend the replicator control node before
deactivation of the replicator's head.
I think we need to be able to distinguish from the situation when we want to
simply cut off one of replicator's head - and gracefully shutdown whole
replicator.
So I've introduced new variable along the old activation_priority and I use it
as a sign (similar to noflush,skipfs) and before deactivation of node I simply
check whether that node is connected with flagged replicator control node. In
that case the node is suspend in front of deactivation.
This patch should have no influence on other targets.
Zdenek
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: 0008-Replicator-solution-for-suspend-deactivate.patch
URL: <http://listman.redhat.com/archives/lvm-devel/attachments/20091009/4a8de653/attachment.ksh>
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH 01/13] Replicator: export out_ function for modules
2009-10-08 11:02 ` Zdenek Kabelac
@ 2009-10-09 12:47 ` Zdenek Kabelac
2009-10-09 12:59 ` Alasdair G Kergon
0 siblings, 1 reply; 23+ messages in thread
From: Zdenek Kabelac @ 2009-10-09 12:47 UTC (permalink / raw)
To: lvm-devel
Dne 8.10.2009 13:02, Zdenek Kabelac napsal(a):
> Dne 7.10.2009 17:05, Alasdair G Kergon napsal(a):
>> On Mon, Oct 05, 2009 at 04:00:28PM +0200, Zdenek Kabelac wrote:
>>> +/* insert new line */
>>> +int out_newline(struct formatter *f)
>>> +{
>>> + outnl(f);
>>> + return 0;
>>
>> Should return 1 here, and the caller has to check that.
>
> true
>
>> Instead, I think the outnl macro should be changed to work like the outf one.
>> (make the 'f->nl' part internal to an export.c function instead of the header file)
>> The idea was that the callers would be using this so frequently, it was
>> clearer just writing 'outf(...)' than 'if (!out_text(...)) return_0;' everywhere.
>>
>> Alasdair
>>
>
> So how about this:
>
> +/* insert new line */
> +int out_newline(struct formatter *f)
> +{
> + return f->nl(f);
> +}
> +
>
> I think this will be the easiest way - nl() is virtual function thus it can't
> be easily 'macro-ised'.
>
Hmm I've maybe slightly misunderstood your comment.
So would you agree with following extension:
-#define outnl(f) do {if (!f->nl(f)) return_0;} while (0)
+#define outnl(f) do {if (!out_newline(f)) return_0;} while (0)
Thus the internal code would be also using out_newline() just like
outf() is using out_text()?
Eventually we may keep outnl() as is - and introduce outnewl for externs.
+#define outnewl(f) do {if (!out_newline(f)) return_0;} while (0)
Zdenek
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH 01/13] Replicator: export out_ function for modules
2009-10-09 12:47 ` Zdenek Kabelac
@ 2009-10-09 12:59 ` Alasdair G Kergon
0 siblings, 0 replies; 23+ messages in thread
From: Alasdair G Kergon @ 2009-10-09 12:59 UTC (permalink / raw)
To: lvm-devel
On Fri, Oct 09, 2009 at 02:47:42PM +0200, Zdenek Kabelac wrote:
> -#define outnl(f) do {if (!f->nl(f)) return_0;} while (0)
> +#define outnl(f) do {if (!out_newline(f)) return_0;} while (0)
That was what I was thinking, yes.
Alasdair
^ permalink raw reply [flat|nested] 23+ messages in thread
end of thread, other threads:[~2009-10-09 12:59 UTC | newest]
Thread overview: 23+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-10-05 14:00 [PATCH 01/13] Replicator: export out_ function for modules Zdenek Kabelac
2009-10-05 14:00 ` [PATCH 02/13] Replicator: add libdm support Zdenek Kabelac
2009-10-05 14:00 ` [PATCH 03/13] Replicator: add lvm support Zdenek Kabelac
2009-10-05 14:00 ` [PATCH 04/13] Replicator: new variable in generated file Zdenek Kabelac
2009-10-05 14:00 ` [PATCH 05/13] Replicator: use dm_tree_suspend_children Zdenek Kabelac
2009-10-05 14:00 ` [PATCH 06/13] Replicator: extend _lv_each_dependency() rep. deps Zdenek Kabelac
2009-10-05 14:00 ` [PATCH 07/13] Replicator: update _create_partial_dtree() Zdenek Kabelac
2009-10-05 14:00 ` [PATCH 08/13] Replicator: add replicator/_dev to dtree Zdenek Kabelac
2009-10-05 14:00 ` [PATCH 09/13] Replicator: do not remove of replicators' LVs Zdenek Kabelac
2009-10-05 14:00 ` [PATCH 10/13] Replicator: activate change for vgchange Zdenek Kabelac
2009-10-05 14:00 ` [PATCH 11/13] Replicator: add new options for replicator Zdenek Kabelac
2009-10-05 14:00 ` [PATCH 12/13] Replicator: update copyright dates Zdenek Kabelac
2009-10-05 14:00 ` [PATCH 13/13] Replicator: update of generated configure file Zdenek Kabelac
2009-10-07 15:07 ` [PATCH 03/13] Replicator: add lvm support Alasdair G Kergon
2009-10-08 8:56 ` Zdenek Kabelac
2009-10-07 14:39 ` [PATCH 02/13] Replicator: add libdm support Alasdair G Kergon
2009-10-08 9:42 ` Petr Rockai
2009-10-09 12:42 ` Zdenek Kabelac
2009-10-08 9:32 ` Petr Rockai
2009-10-07 15:05 ` [PATCH 01/13] Replicator: export out_ function for modules Alasdair G Kergon
2009-10-08 11:02 ` Zdenek Kabelac
2009-10-09 12:47 ` Zdenek Kabelac
2009-10-09 12:59 ` Alasdair G Kergon
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.