Replicator 100707
cover Replicator 100707
This patchset enhances lvm with replicator metadata construction. It 'should not' influence other commands.
Use case example:
# build remote devices vgcreate vg_ny /dev/loop1 vgcreate vg_paris /dev/loop2
lvcreate -L10M -n L1 vg_ny
lvcreate -L10M -n L1 vg_paris
lvcreate -L20M -n L2 vg_ny
lvcreate -L20M -n L2 vg_paris
# build local replicator vgcreate my /dev/loop0 lvcreate --replicator rep -L20M my
lvcreate --site Berlin --replicator my/rep
lvcreate --site NY --remotevg vg_ny --replicator my/rep lvcreate --site Paris --remotevg vg_paris --replicator my/rep
lvcreate --replicatordev -L10M -n L1 --replicator my/rep lvcreate --replicatordev -L20M -n L2 --replicator my/rep
lvcreate --replicator rep -L20M my || exit 1 lvcreate --replicatordev -L10M -n L1 --replicator my/rep
lvremove my/L1
Note: after removing 'L1' LV 'L1_rimage' and '_slog' devices are left in VG Ideally user should use own 'VG'
and for removal just run:
vgremove my
lvchange --site Berlin --replicator my/rep -ay
== lvchange --site Berlin my/L1 -ay
== lvchange --site Berlin my/rep -ay
Zdenek Kabelac (22):
Add units to passed parameters data & timeout Use size
Allow the user to not specify a size when creating snapshot. Skip check missing rem.VGs for non-activate locks
Replicator: check for active replicator
Replicator: add reserved names
Replicator: man page update for lvm
Replicator: add _replicator_in_sync
Replicator: add report for replicator targets
Replicator: improve detection of replicator-dev
Replicator: new defaults
Replicator: metadata update
Replicator: replicator_manip changes
Replicator: replicator.c changes
Replicator: add new command option read functions
Replicator: new args
Replicator: read site_params
Replicator: lv_manip - create replicator
Replicator: lvcreate implementation
Replicator: man page update for lvcreate
Replicator: lvchange implementation
Replicator: man page update for lvchange
Replicator: lvremove implementation
lib/config/defaults.h | 9 + lib/locking/locking.h | 2 +- lib/metadata/lv_manip.c | 126 ++++- lib/metadata/merge.c | 18 +- lib/metadata/metadata-exported.h | 59 ++- lib/metadata/replicator_manip.c | 1211 +++++++++++++++++++++++++++++++------- lib/misc/lvm-globals.c | 11 + lib/misc/lvm-globals.h | 2 + lib/misc/lvm-string.c | 18 + lib/replicator/replicator.c | 178 ++---- lib/report/columns.h | 2 + lib/report/report.c | 32 + libdm/libdm-deptree.c | 4 +- man/lvchange.8.in | 31 + man/lvcreate.8.in | 76 +++ man/lvm.8.in | 3 +- tools/args.h | 10 + tools/commands.h | 18 +- tools/lvchange.c | 195 ++++++- tools/lvcreate.c | 137 +++++- tools/lvmcmdline.c | 24 + tools/lvremove.c | 19 +- tools/toollib.c | 111 ++++ tools/toollib.h | 3 + tools/tools.h | 2 + tools/vgchange.c | 2 +- 26 files changed, 1942 insertions(+), 361 deletions(-)
PATCH 1/22 Add units to passed parameters data & timeout Use size
--- libdm/libdm-deptree.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
libdm/libdm-deptree.c +2 -2
@@ -1520,11 +1520,11 @@ static int _replicator_emit_segment_line(const struct load_segment *seg, char *p (rsite->mode == DM_REPLICATOR_SYNC) ? "synchronous" : "asynchronous");if (rsite->fall_behind_data) -EMIT_PARAMS (*pos," data %" PRIu64, rsite->fall_behind_data); +EMIT_PARAMS (*pos," size %" PRIu64"s" , rsite->fall_behind_data);else if (rsite->fall_behind_ios)EMIT_PARAMS (*pos," ios %" PRIu32, rsite->fall_behind_ios);else if (rsite->async_timeout) -EMIT_PARAMS (*pos," timeout %" PRIu32, rsite->async_timeout); +EMIT_PARAMS (*pos," timeout %" PRIu32"s" , rsite->async_timeout); }return 1 ;
Signature · 1 line
1.7.1.1
PATCH 2/22 Allow the user to not specify a size when creating snapshot.
In reply to Zdenek KabelacFor shared snapshot, the size is not required. If the user creates other volume than a shared snapshot, zero size will be rejected in lv_create_single.
--- tools/lvcreate.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-)
tools/lvcreate.c +4 -0
@@ -191,6 +191,9 @@ static int _read_size_params(struct lvcreate_params *lp, struct lvcreate_cmdline_params *lcp, struct cmd_context *cmd) { +if (!arg_count (cmd, extents_ARG) && !arg_count (cmd, size_ARG)) + goto skip_size_arg; +if (arg_count (cmd, extents_ARG) +arg_count (cmd, size_ARG) !=1 ) {log_error ("Please specify either size or extents (not both)" );return 0 ;
@@ -215,6 +218,7 @@ static int _read_size_params(struct lvcreate_params *lp, lcp->percent =PERCENT_NONE ; } +skip_size_arg:/* Size returned in kilobyte units; held in sectors */ if (arg_count (cmd, virtualsize_ARG)) {if (arg_sign_value (cmd, virtualsize_ARG,0 ) ==SIGN_MINUS ) {
Signature · 1 line
1.7.1.1
PATCH 3/22 Skip check missing rem.VGs for non-activate locks
In reply to Zdenek KabelacSkip call for checking whether this LV needs to locks some more remote VGs (applies to replicator_dev devices).
The effect is, that deactivation of replicator-dev devices does not require to take a lock for remote VGs, so avoids repeated invoke of deactivate_lv.
--- lib/locking/locking.h | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
lib/locking/locking.h +1 -1
@@ -136,7 +136,7 @@ int check_lvm1_vg_inactive(struct cmd_context *cmd, const char *vgname); (vg_is_clustered((lv)->vg) ? LCK_CLUSTER_VG : 0)#define lock_lv_vol (cmd, lv, flags) \ - (find_replicator_vgs((lv)) ? \ + ((!((flags) & LCK_READ) || find_replicator_vgs((lv))) ? \ lock_vol(cmd, (lv)->lvid.s, flags | LCK_LV_CLUSTERED(lv)) : \ 0)
Signature · 1 line
1.7.1.1
PATCH 4/22 Replicator: check for active replicator
In reply to Zdenek KabelacSkip activation of other heads only for a active replicator. For inactive active all heads with linear overlay mapping
--- tools/vgchange.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
tools/vgchange.c +1 -1
@@ -106,7 +106,7 @@ static int _activate_lvs_in_vg(struct cmd_context *cmd,/* Only request activation of the first replicator-dev LV */ /* Avoids retry with all heads in case of failure */ -if (lv_is_replicator_dev (lv) && (lv !=first_replicator_dev (lv))) +if (lv_is_active_replicator_dev (lv) && (lv !=first_replicator_dev (lv)))continue ;/* Can't deactivate a pvmove LV */
Signature · 1 line
1.7.1.1
PATCH 5/22 Replicator: add reserved names
In reply to Zdenek KabelacAdd new reserved names for replicator related devices.
--- lib/misc/lvm-string.c | 18 ++++++++++++++++++ 1 files changed, 18 insertions(+), 0 deletions(-)
lib/misc/lvm-string.c +18 -0
@@ -275,6 +275,24 @@ int apply_lvname_restrictions(const char *name)return 0 ; } +if (strstr (name,"_slog" )) { +log_error ("Names including \"_slog\" are reserved. " +"Please choose a different LV name." ); +return 0 ; + } + +if (strstr (name,"_rlog" )) { +log_error ("Names including \"_rlog\" are reserved. " +"Please choose a different LV name." ); +return 0 ; + } + +if (strstr (name,"_rimage" )) { +log_error ("Names including \"_rimage\" are reserved. " +"Please choose a different LV name." ); +return 0 ; + } +return 1 ; }
Signature · 1 line
1.7.1.1
PATCH 6/22 Replicator: man page update for lvm
In reply to Zdenek KabelacAdd new reserved names to lvm man page.
--- man/lvm.8.in | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-)
man/lvm.8.in +2 -1
@@ -271,7 +271,8 @@ The following characters are valid for VG and LV names: VG and LV names cannot begin with a hyphen. There are also various reserved names that are used internally by lvm that can not be used as LV or VG names. A VG cannot be called anything that exists in /dev/ at the time of creation, nor can it be called '.' or '..'. -A LV cannot be called '.' '..' 'snapshot' or 'pvmove'. The LV name may also not contain the strings '_mlog' or '_mimage' +A LV cannot be called '.' '..' 'snapshot' or 'pvmove'. The LV name may also not contain the strings +'_mlog', '_mimage', '_rlog', '_slog', '_rimage'. .SH DIAGNOSTICS
Signature · 1 line
1.7.1.1
PATCH 7/22 Replicator: add _replicator_in_sync
In reply to Zdenek KabelacAdd function init_replicator_in_sync() to be similar as mirror. For now this function is not functional.
--- lib/misc/lvm-globals.c | 11 +++++++++++ lib/misc/lvm-globals.h | 2 ++ 2 files changed, 13 insertions(+), 0 deletions(-)
lib/misc/lvm-globals.c +11 -0
@@ -34,6 +34,7 @@ static int _ignorelockingfailure = 0;static int _security_level =SECURITY_LEVEL ;static char _cmd_name[30 ] ="" ;static int _mirror_in_sync =0 ; +static int _replicator_in_sync =0 ;static int _dmeventd_monitor =DEFAULT_DMEVENTD_MONITOR ;static int _background_polling =DEFAULT_BACKGROUND_POLLING ;static int _ignore_suspended_devices =0 ;
@@ -88,6 +89,11 @@ void init_mirror_in_sync(int in_sync) _mirror_in_sync = in_sync; } +void init_replicator_in_sync (int in_sync) +{ + _replicator_in_sync = in_sync; +} +void init_dmeventd_monitor (int reg) { _dmeventd_monitor = reg;
@@ -190,6 +196,11 @@ int mirror_in_sync(void)return _mirror_in_sync; } +int replicator_in_sync (void ) +{ +return _replicator_in_sync; +} +int dmeventd_monitor_mode (void ) {return _dmeventd_monitor;
lib/misc/lvm-globals.h +2 -0
@@ -31,6 +31,7 @@ void init_ignorelockingfailure(int level);void init_lockingfailed (int level);void init_security_level (int level);void init_mirror_in_sync (int in_sync); +void init_replicator_in_sync (int in_sync);void init_dmeventd_monitor (int reg);void init_background_polling (int polling);void init_ignore_suspended_devices (int ignore);
@@ -51,6 +52,7 @@ int ignorelockingfailure(void);int lockingfailed (void );int security_level (void );int mirror_in_sync (void ); +int replicator_in_sync (void );int background_polling (void );int ignore_suspended_devices (void );const char *log_command_name (void );
Signature · 1 line
1.7.1.1
PATCH 8/22 Replicator: add report for replicator targets
In reply to Zdenek KabelacElementary reporting tool for replicator and replicato-dev LVs. Replicator uses free flag 'q'.
Replicator-dev 'r' for normal, 'R' for unsynchronized replicator.
Note: unsychronized status not yet written.
--- lib/report/columns.h | 2 ++ lib/report/report.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 0 deletions(-)
lib/report/columns.h +2 -0
@@ -76,6 +76,8 @@ FIELD(LVS, lv, STR, "Convert", lvid, 7, convertlv, "convert_lv", "For lvconvert, FIELD(LVS, lv, STR, "LV Tags", tags, 7, tags, "lv_tags", "Tags, if any.") FIELD(LVS, lv, STR, "Log", lvid, 3, loglv, "mirror_log", "For mirrors, the LV holding the synchronisation log.") FIELD(LVS, lv, STR, "Modules", lvid, 7, modules, "modules", "Kernel device-mapper modules required for this LV.") +FIELD(LVS, lv, STR, "RImage", lvid, 7, rimage, "rimage", "For replicators, the replicated image of this LV.") +FIELD(LVS, lv, STR, "Replicator", lvid, 7, replicator, "replicator", "For replicators, the replicator control LV.") FIELD(LABEL, pv, STR, "Fmt", id, 3, pvfmt, "pv_fmt", "Type of metadata.")FIELD (LABEL , pv,STR ,"PV UUID" , id,38 , uuid,"pv_uuid" ,"Unique identifier." )
lib/report/report.c +32 -0
@@ -303,6 +303,10 @@ static int _lvstatus_disp(struct dm_report *rh __attribute((unused)), struct dm_ repstr[0 ] ='p' ; else if (lv->status & CONVERTING) repstr[0 ] ='c' ; + else if (lv_is_replicator(lv)) + repstr[0 ] ='q' ; + else if (lv_is_replicator_dev(lv)) + repstr[0 ] = (lv->status &REPLICATOR_NOTSYNCED ) ?'R' :'r' ; else if (lv->status & VIRTUAL) repstr[0 ] ='v' ;/* Origin takes precedence over Mirror */
@@ -605,6 +609,34 @@ static int _convertlv_disp(struct dm_report *rh, struct dm_pool *mem __attributereturn 1 ; } +static int _rimage_disp (struct dm_report *rh,struct dm_pool *mem, +struct dm_report_field *field, +const void *data,void *private) +{ +const struct logical_volume *lv = (const struct logical_volume *) data; + +if (lv_is_replicator_dev (lv)) +return _lvname_disp (rh, mem, field, lv->rdevice->lv, private); + +dm_report_field_set_value (field,"" ,NULL ); + +return 1 ; +} + +static int _replicator_disp (struct dm_report *rh,struct dm_pool *mem, +struct dm_report_field *field, +const void *data,void *private) +{ +const struct logical_volume *lv = (const struct logical_volume *) data; + +if (lv_is_replicator_dev (lv)) +return _lvname_disp (rh, mem, field, lv->rdevice->rsite->replicator, private); + +dm_report_field_set_value (field,"" ,NULL ); + +return 1 ; +} +static int _size32_disp (struct dm_report *rh __attribute((unused)),struct dm_pool *mem,struct dm_report_field *field,const void *data,void *private)
Signature · 1 line
1.7.1.1
PATCH 9/22 Replicator: improve detection of replicator-dev
In reply to Zdenek KabelacCheck for NULL replicator pointer in replicator-dev segment.
--- lib/metadata/merge.c | 18 ++++++++++++------ 1 files changed, 12 insertions(+), 6 deletions(-)
lib/metadata/merge.c +12 -6
@@ -219,14 +219,20 @@ int check_lv_segments(struct logical_volume *lv, int complete_vg) seg_found++; }if (seg_is_replicator_dev (seg)) { - dm_list_iterate_items(rsite, &seg->replicator->rsites) { - dm_list_iterate_items(rdev, &rsite->rdevices) { -if (lv == rdev->lv || lv == rdev->slog) - seg_found++; +if (!seg->replicator) { +log_error ("LV %s has replicator-dev segment " +"without replicator" , lv->name); + inc_error_count; + }else { + dm_list_iterate_items(rsite, &seg->replicator->rsites) { + dm_list_iterate_items(rdev, &rsite->rdevices) { +if (lv == rdev->lv || lv == rdev->slog) + seg_found++; + } } +if (lv == seg->replicator) + seg_found++; } -if (lv == seg->replicator) - seg_found++; }if (seg_is_replicator (seg) && lv == seg->rlog_lv) seg_found++;
Signature · 1 line
1.7.1.1
PATCH 10/22 Replicator: new defaults
In reply to Zdenek Kabelac--- lib/config/defaults.h | 9 +++++++++ 1 files changed, 9 insertions(+), 0 deletions(-)
lib/config/defaults.h +9 -0
@@ -48,6 +48,14 @@#define DEFAULT_DMEVENTD_MONITOR 1#define DEFAULT_BACKGROUND_POLLING 1 +#define DEFAULT_REPLICATOR_SYNCLOG "disk" +#define DEFAULT_REPLICATOR_LOG_TYPE "ringbuffer" +#define DEFAULT_REPLICATOR_LOCAL_SITE_NAME "local" +#define DEFAULT_REPLICATOR_FALL_BEHIND_DATA 0 +#define DEFAULT_REPLICATOR_FALL_BEHIND_IOS 0 +#define DEFAULT_REPLICATOR_FALL_BEHIND_TIMEOUT 0 +#define DEFAULT_REPLICATOR_ASYNC_MODE (DM_REPLICATOR_ASYNC_WARN) +#define DEFAULT_UMASK 0077#ifdef LVM1_FALLBACK
@@ -106,6 +114,7 @@#define DEFAULT_STRIPE_FILLER "error"#define DEFAULT_MIRROR_REGION_SIZE 512/* KB */ +#define DEFAULT_REPLICATOR_REGION_SIZE 512/* KB */ #define DEFAULT_INTERVAL 15#ifdef READLINE_SUPPORT
Signature · 1 line
1.7.1.1
PATCH 11/22 Replicator: metadata update
In reply to Zdenek Kabelac--- lib/metadata/metadata-exported.h | 59 ++++++++++++++++++++++++++++++-------- 1 files changed, 47 insertions(+), 12 deletions(-)
lib/metadata/metadata-exported.h +47 -12
@@ -74,6 +74,7 @@#define REPLICATOR 0x20000000U/* LV -internal use only for replicator */ #define REPLICATOR_LOG 0x40000000U/* LV -internal use only for replicator-dev */ +#define REPLICATOR_NOTSYNCED 0x80000000U/* LV -internal use only for replicator */ #define LVM_READ 0x00000100U/* LV VG */ #define LVM_WRITE 0x00000200U/* LV VG */
@@ -352,7 +353,7 @@ struct replicator_device {const char *name;/* Device LV name */ struct logical_volume *lv;/* LV from replicator site's VG */ struct logical_volume *slog;/* Synclog lv from VG */ -const char *slog_name;/* Debug - specify size of core synclog */ +uint32_t slog_core;/* Corelog size */ };/* -- Replicator datatypes */
@@ -622,6 +623,8 @@ uint64_t extents_from_size(struct cmd_context *cmd, uint64_t size,struct lvcreate_params {/* flags */ int snapshot;/* snap */ +const char *replicator;/* replicator */ +int replicator_dev;/* replicator-dev */ int zero;/* all */ int major;/* all */ int minor;/* all */
@@ -640,6 +643,9 @@ struct lvcreate_params {uint32_t mirrors;/* mirror */ +const char *rlog_type;/* replicator */ +struct replicator_site rsite;/* replicator, use only parameters */ +const struct segment_type *segtype;/* all */ /* size */
@@ -803,24 +809,53 @@ int collapse_mirrored_lv(struct logical_volume *lv);int shift_mirror_images (struct lv_segment *mirrored_seg,unsigned mimage);/* ++ metadata/replicator_manip.c */ -int replicator_add_replicator_dev (struct logical_volume *replicator_lv, -struct lv_segment *rdev_seg); -struct logical_volume *replicator_remove_replicator_dev (struct lv_segment *rdev_seg); -int replicator_add_rlog (struct lv_segment *replicator_seg,struct logical_volume *rlog_lv); -struct logical_volume *replicator_remove_rlog (struct lv_segment *replicator_seg); - -int replicator_dev_add_slog (struct replicator_device *rdev,struct logical_volume *slog_lv); -struct logical_volume *replicator_dev_remove_slog (struct replicator_device *rdev); -int replicator_dev_add_rimage (struct replicator_device *rdev,struct logical_volume *lv); -struct logical_volume *replicator_dev_remove_rimage (struct replicator_device *rdev); -int lv_is_active_replicator_dev (const struct logical_volume *lv);int lv_is_replicator (const struct logical_volume *lv);int lv_is_replicator_dev (const struct logical_volume *lv);int lv_is_rimage (const struct logical_volume *lv);int lv_is_rlog (const struct logical_volume *lv);int lv_is_slog (const struct logical_volume *lv); +struct replicator_site *find_site_in_replicator (const struct logical_volume *replicator, +const char *site_name); +struct replicator_site *find_local_site_in_replicator (const struct logical_volume *replicator);struct logical_volume *first_replicator_dev (const struct logical_volume *lv); +int replicator_add_rlog (struct lv_segment *replicator_seg,struct logical_volume *rlog_lv); +struct logical_volume *replicator_remove_rlog (struct lv_segment *replicator_seg); +int replicator_site_add_device (struct replicator_site *rsite, +struct lv_segment *replicator_dev_seg, +const char *name, +struct logical_volume *rimage, +uint32_t slog_core, +struct logical_volume *slog_lv, +uint64_t device_index); +int replicator_site_set_op_mode (struct replicator_site *rsite,const char *sitemode); +const char *replicator_site_get_op_mode (const struct replicator_site *rsite); +struct replicator_site *replicator_add_site (struct logical_volume *replicator, +const char *site_name); +void replicator_init (struct logical_volume *replicator); +int replicator_add_replicator_dev (struct logical_volume *replicator, +struct lv_segment *rdev_seg); + +int lv_add_replicator_dev (struct logical_volume *replicator, +struct logical_volume *lv); +int lv_remove_replicator_dev (struct logical_volume *replicator_dev); + +int lv_add_replicator_site (struct logical_volume *replicator, +const struct replicator_site *rsite); +int lv_remove_replicator_site (struct logical_volume *replicator,const char *site_name); + +int lv_add_sync_log (struct logical_volume *replicator, +unsigned site_index, +uint64_t device_index, +struct dm_list *allocatable_pvs, +alloc_policy_t alloc); + +int vg_prearrange_replicator (struct volume_group *vg, +const struct lvcreate_params *lp); +int vg_add_replicator (struct logical_volume *replicator, +const char *rlog_type, +uint32_t region_size); +int vg_remove_replicator (struct logical_volume *replicator);/* -- metadata/replicator_manip.c */ struct cmd_vg *cmd_vg_add(struct dm_pool *mem, struct dm_list *cmd_vgs, const char *vg_name, const char *vgid,
Signature · 1 line
1.7.1.1
PATCH 12/22 Replicator: replicator_manip changes
In reply to Zdenek KabelacChanges for replicator_manip.c source file.
Adding new API functions.
Lots of lines for log creation are copied from mirror code and then are adapted for _slog. Code is done with hope we could share same parametrized code later for both targets - mirror and replicator. But with recent changes to mirrored logs it is a harder task.
--- lib/metadata/replicator_manip.c | 1211 ++++++++++++++++++++++++++++++++------- 1 files changed, 1001 insertions(+), 210 deletions(-)
lib/metadata/replicator_manip.c +1001 -210
@@ -15,244 +15,741 @@#include "lib.h" #include "locking.h" #include "metadata.h" +#include "defaults.h" #include "segtype.h" #include "toolcontext.h" +#include "activate.h" +#include "archiver.h" +#include "lv_alloc.h" +#include "str_list.h" + +static const struct { +const char name[8 ]; +int value; +} dm_op_mode_table[] = { + {"sync" ,DM_REPLICATOR_SYNC }, + {"warn" ,DM_REPLICATOR_ASYNC_WARN }, + {"stall" ,DM_REPLICATOR_ASYNC_STALL }, + {"drop" ,DM_REPLICATOR_ASYNC_DROP }, + {"fail" ,DM_REPLICATOR_ASYNC_FAIL } +}; -/* Add lv as replicator_dev device */ -int replicator_dev_add_rimage (struct replicator_device *rdev, -struct logical_volume *lv) +/** +* Tests whether LV is member of an active replicator. +* +* \param lv Logical volume for testing +* +* \return Returns 1 if the lv is member of an active replicator, +* 0 otherwise. +*/ +int lv_is_active_replicator_dev (const struct logical_volume *lv) { -if (!lv || !rdev) - return_0; +return (lv_is_replicator_dev (lv) && + lv->rdevice && + lv->rdevice->rsite && + lv->rdevice->rsite->state ==REPLICATOR_STATE_ACTIVE ); +} + +/** +* Tests whether LV is replicator control device. +* (Segment-less LV could be also replicator.) +* +* \param lv Logical volume for testing +* +* \return Returns 1 if the lv is replicator control device, +* 0 otherwise. +*/ +int lv_is_replicator (const struct logical_volume *lv) +{ +return ((lv->status &REPLICATOR ) && + (dm_list_empty (&lv->segments) || +seg_is_replicator (first_seg (lv)))); +} + +/** +* Tests whether LV is replicator device. +* +* \param lv Logical volume for testing +* +* \return Returns 1 if the lv is replicator device, +* 0 otherwise. +*/ +int lv_is_replicator_dev (const struct logical_volume *lv) +{ +return ((lv->status &REPLICATOR ) && + !dm_list_empty (&lv->segments) && +seg_is_replicator_dev (first_seg (lv))); +} + +/** +* Tests whether LV is replicated rimage device. +* +* \param lv Logical volume for testing +* +* \return Returns 1 if the lv is replicated rimage device, +* 0 otherwise. +*/ +int lv_is_rimage (const struct logical_volume *lv) +{ +return (!lv_is_replicator_dev (lv) && + (lv->rdevice && lv->rdevice->lv == lv)); +} + +/** +* Tests whether LV is replicator log device. +* +* \param lv Logical volume for testing +* +* \return Returns 1 if the lv is replicator log device, +* 0 otherwise. +*/ +int lv_is_rlog (const struct logical_volume *lv) +{ +return (lv->status &REPLICATOR_LOG ); +} + +/** +* Tests whether LV is replicator sync log device. +* +* \param lv Logical volume for testing +* +* \return Returns 1 if the lv is replicator sync log device, +* 0 otherwise. +*/ +int lv_is_slog (const struct logical_volume *lv) +{ +return (lv->rdevice && lv->rdevice->slog == lv); +} + +/** +* Returns local site from replicator. +*/ +struct replicator_site *find_local_site_in_replicator (const struct logical_volume *replicator) +{ +struct replicator_site *rsite; + dm_list_iterate_items(rsite, &replicator->rsites) +if (rsite->site_index ==0 ) +return rsite; + +return NULL ; +} + +/** +* Returns site with name site_name from replicator. +*/ +struct replicator_site *find_site_in_replicator (const struct logical_volume *replicator, +const char *site_name) +{ +struct replicator_site *rsite; + + dm_list_iterate_items(rsite, &replicator->rsites) +if (strcmp (rsite->name, site_name) ==0 ) +return rsite; + +return NULL ; +} + +/** +* Returns first replicator-dev in site in case the LV is replicator-dev +* or replicator, NULL otherwise +*/ +struct logical_volume *first_replicator_dev (const struct logical_volume *lv) +{ +struct replicator_device *rdev; +struct replicator_site *rsite; +const struct logical_volume *replicator; + +if (lv_is_replicator_dev (lv)) + replicator =first_seg (lv)->replicator; +else if (lv_is_replicator (lv)) + replicator = lv; +else { +log_error (INTERNAL_ERROR "Logical volume %s is not " +"replicator" , lv->name); +return NULL ; + } + +if ((rsite =find_local_site_in_replicator (replicator))) + dm_list_iterate_items(rdev, &rsite->rdevices) +return rdev->replicator_dev->lv; + +return NULL ; +} + +/* Add lv as replicator_dev device */ +static int _replicator_device_add_rimage (struct replicator_device *rdev, +struct logical_volume *lv) +{if (lv_is_rimage (lv)) { -log_error ("Logical volume %s is already part of other " -"replicator." , lv->name); +log_error (INTERNAL_ERROR "Logical volume %s is used by replicator %s." , + lv->name, lv->rdevice->rsite->replicator->name);return 0 ; }if (rdev->lv) { -log_error ("Logical volume %s can not be attached to an " +log_error (INTERNAL_ERROR "Logical volume %s cannot be attached to an " "already defined replicator device" , lv->name);return 0 ; }lv_set_hidden (lv); lv->rdevice = rdev; + rdev->replicator_dev->lv->rdevice = rdev; rdev->lv = lv;return add_seg_to_segs_using_this_lv (lv, rdev->replicator_dev); }/* Remove lv from replicator_dev device */ -struct logical_volume *replicator_dev_remove_rimage (struct replicator_device *rdev) +static struct logical_volume *_replicator_device_remove_rimage (struct replicator_device *rdev) { -struct logical_volume *lv; +struct logical_volume *rimage = rdev->lv; -if (!rdev || !rdev->lv) - return_NULL; +if (!rimage || !lv_is_rimage (rimage)) { +log_error (INTERNAL_ERROR "Replicator device in site %s " +"does not have rimage." , rdev->rsite->name); +return NULL ; + } - lv = rdev->lv; -if (!remove_seg_from_segs_using_this_lv (lv, rdev->replicator_dev)) +if (!remove_seg_from_segs_using_this_lv (rimage, rdev->replicator_dev)) return_NULL; -/* FIXME: - check for site references */ rdev->lv =NULL ; - lv->rdevice =NULL ; -lv_set_visible (lv); + rimage->rdevice =NULL ; +lv_set_visible (rimage); -return lv; +return rimage; } -int replicator_dev_add_slog (struct replicator_device *rdev, -struct logical_volume *slog) +static int _replicator_device_add_slog (struct replicator_device *rdev, +struct logical_volume *slog) { -if (!slog || !rdev) - return_0; - -if (rdev->slog) { -log_error ("Replicator device in site %s already has sync log." , - rdev->rsite->name); +if (lv_is_slog (slog)) { +log_error (INTERNAL_ERROR "Logical volume %s cannot be used." , + slog->name);return 0 ; } -if (slog->rdevice) { -log_error ("Sync log %s is already used by replicator %s." , - slog->name, slog->rdevice->rsite->replicator->name); +if (rdev->slog) { +log_error (INTERNAL_ERROR "Replicator device in site %s has " +"sync log %s." , rdev->rsite->name, rdev->slog->name);return 0 ; } +if (!add_seg_to_segs_using_this_lv (slog, rdev->replicator_dev)) + return_0; +lv_set_hidden (slog); - slog->rdevice = rdev; rdev->slog = slog; + slog->rdevice = rdev; -return add_seg_to_segs_using_this_lv (slog, rdev->replicator_dev); +return 1 ; } -struct logical_volume *replicator_dev_remove_slog (struct replicator_device *rdev) +static struct logical_volume *_replicator_device_remove_slog (struct replicator_device *rdev) { -struct logical_volume *lv; +struct logical_volume *slog = rdev->slog; + +if (!slog || !lv_is_slog (slog)) { +log_error (INTERNAL_ERROR "Replicator device in site %s " +"does not have sync log." , rdev->rsite->name); +return NULL ; + } -if (!rdev) + slog->rdevice =NULL ; + rdev->slog =NULL ; +lv_set_visible (slog); + +if (!remove_seg_from_segs_using_this_lv (slog, rdev->replicator_dev)) return_NULL; - lv = rdev->slog; -if (!lv) { -log_error ("Replicator device in site %s does not have sync log." , - rdev->rsite->name); +return slog; +} + +static char *_replicator_device_slog_name (struct logical_volume *replicator, +unsigned site_index, +uint64_t device_index) +{ +char *name; +size_t len =strlen (replicator->name) +12 +22 +10 ; + +if (!(name =dm_pool_zalloc (replicator->vg->vgmem, len))) { +log_error ("Allocation of slog name failed." ); +return NULL ; + } + +if (!dm_snprintf (name, len,"%s_%u_%" PRIu64"_slog" , replicator->name, + site_index, device_index) <0 ) { +log_error ("Error in name creation" ); +return NULL ; + } + +return name; +} + +int replicator_add_rlog (struct lv_segment *replicator_seg, +struct logical_volume *rlog_lv) +{ +if (lv_is_rlog (rlog_lv)) { +log_error (INTERNAL_ERROR "Logical volume %s cannot be used." , + rlog_lv->name); +return 0 ; + } + +if (!add_seg_to_segs_using_this_lv (rlog_lv, replicator_seg)) + return_0; + +lv_set_hidden (rlog_lv); + rlog_lv->status |=REPLICATOR_LOG ; + replicator_seg->rlog_lv = rlog_lv; + +return 1 ; +} + +struct logical_volume *replicator_remove_rlog (struct lv_segment *replicator_seg) +{ +struct logical_volume *rlog_lv = replicator_seg->rlog_lv; + +if (!rlog_lv || !lv_is_rlog (rlog_lv)) { +log_error (INTERNAL_ERROR "Replicator %s does not have rlog." , + replicator_seg->lv->name);return NULL ; } -if (!remove_seg_from_segs_using_this_lv (lv, rdev->replicator_dev)) + replicator_seg->rlog_lv =NULL ; + rlog_lv->status &= ~REPLICATOR_LOG ; +lv_set_visible (rlog_lv); + +if (!remove_seg_from_segs_using_this_lv (rlog_lv, replicator_seg)) return_NULL; - rdev->slog =NULL ; - lv->rdevice =NULL ; -lv_set_visible (lv); +return rlog_lv; +} + +/** +* +*/ +int replicator_site_add_device (struct replicator_site *rsite, +struct lv_segment *replicator_dev_seg, +const char *name, +struct logical_volume *rimage, +uint32_t slog_core, +struct logical_volume *slog, +uint64_t device_index) +{ +struct dm_pool *mem = replicator_dev_seg->lv->vg->vgmem; +struct replicator_device *rdev; + +if (!(rdev =dm_pool_zalloc (mem,sizeof (*rdev)))) { +log_error ("Allocation of replicator device failed." ); +return 0 ; + } + +if (!(rdev->name =dm_pool_strdup (mem, name))) { +log_error ("Allocation of replicator device name failed." ); +return 0 ; + } + +log_very_verbose ("Created %s/%s" , rsite->name, rdev->name); + + rdev->rsite = rsite; + rdev->replicator_dev = replicator_dev_seg; + rdev->device_index = device_index; + rdev->slog_core = slog_core; + +dm_list_add (&rsite->rdevices, &rdev->list);// linked site list + +if (rimage && !_replicator_device_add_rimage (rdev, rimage)) + return_0; + +if (slog_core && slog) { +log_error ("Either slog or corelog must be used." ); +return 0 ; + } -return lv; +if (slog && !_replicator_device_add_slog (rdev, slog)) + return_0; + +return 1 ; } -int replicator_add_replicator_dev (struct logical_volume *replicator_lv, -struct lv_segment *replicator_dev_seg) +static int _replicator_site_remove_device (struct replicator_device *rdev) { -if (!replicator_lv) +if (rdev->lv && !_replicator_device_remove_rimage (rdev)) return_0; -if (!(replicator_lv->status &REPLICATOR )) { -dm_list_init (&replicator_lv->rsites); -lv_set_hidden (replicator_lv); - replicator_lv->status |=REPLICATOR ; +if (rdev->slog && !_replicator_device_remove_slog (rdev)) + return_0; + +dm_list_del (&rdev->list); + +return 1 ; +} + +struct replicator_site *replicator_add_site (struct logical_volume *replicator, +const char *site_name) +{ +struct replicator_site *rsite; + +if (find_site_in_replicator (replicator, site_name)) { +log_error ("Site name %s already exists." , site_name); +return NULL ; } -if (!replicator_dev_seg) -return 1 ; +if (!(rsite =dm_pool_zalloc (replicator->vg->vgmem, +sizeof (*rsite)))) { +log_error ("Allocation of replicator site failed." ); +return NULL ; + } + +if (!(rsite->name =dm_pool_strdup (replicator->vg->vgmem, + site_name))) { +log_error ("Allocation of replicator site name failed." ); +return NULL ; + } + + rsite->replicator = replicator; +dm_list_init (&rsite->rdevices); +dm_list_add (&replicator->rsites, &rsite->list); + +return rsite; +} + +static int _replicator_remove_site (struct replicator_site *rsite) +{ +struct replicator_device *rdev, *trdev; + + dm_list_iterate_items_safe(rdev, trdev, &rsite->rdevices) +if (!_replicator_site_remove_device (rdev)) + return_0; + +dm_list_del (&rsite->list); + +return 1 ; +} + + +void replicator_init (struct logical_volume *replicator) +{ +if (!lv_is_replicator (replicator)) { +dm_list_init (&replicator->rsites); +lv_set_hidden (replicator); + replicator->status |=REPLICATOR ; + } +} + +/** +* Connects replicator_dev segment to replicator. +* +* \param replicator +* \param replicator_dev_seg +*/ +int replicator_add_replicator_dev (struct logical_volume *replicator, +struct lv_segment *replicator_dev_seg) +{ +replicator_init (replicator);if (replicator_dev_seg->replicator) { -log_error ("Replicator device %s is already part of replicator." , - replicator_dev_seg->lv->name); +log_error (INTERNAL_ERROR "Replicator device %s is already " +"part of replicator." , replicator_dev_seg->lv->name);return 0 ; } - replicator_dev_seg->replicator = replicator_lv; + replicator_dev_seg->replicator = replicator; + replicator_dev_seg->rlog_lv =NULL ; + replicator_dev_seg->lv->status |=REPLICATOR ; + +if (!add_seg_to_segs_using_this_lv (replicator, replicator_dev_seg)) + return_0; -return add_seg_to_segs_using_this_lv (replicator_lv, replicator_dev_seg); +return 1 ; }/** -* Returns rimage ?? lv upon succeful detach of device -* entire LV entry should be removed by this crootall ?? +* Returns rimage LV upon succeful detach of device +* entire LV entry should be removed by this call ?? */ -struct logical_volume *replicator_remove_replicator_dev (struct lv_segment *replicator_dev_seg) +static int _replicator_remove_replicator_dev (struct lv_segment *replicator_dev_seg) { -struct logical_volume *lv =NULL ; - -log_error ("FIXME: not implemented." ); -#if 0 -/* FIXME: - this is going to be complex.... */ -if (!replicator_dev_seg) - return_NULL; +struct replicator_site *rsite; +struct replicator_device *rdev; +struct logical_volume *replicator = replicator_dev_seg->replicator; +uint64_t device_index = replicator_dev_seg->lv->rdevice->device_index; -/* if slog or rimage - exit */ + dm_list_iterate_items(rsite, &replicator->rsites) { + dm_list_iterate_items(rdev, &rsite->rdevices) { +if (rdev->device_index != device_index) +continue ; +if (!_replicator_site_remove_device (rdev)) + return_0; +/* no need for iterate_items_safe - 1 device per site */ +break ; + } + } -if (!remove_seg_from_segs_using_this_lv (lv, replicator_seg)) - return_NULL; +if (!remove_seg_from_segs_using_this_lv (replicator, replicator_dev_seg)) + return_0; - replicator_seg->rlog_lv =NULL ; - lv->status &= ~REPLICATOR_LOG ; -lv_set_visible (lv); -#endif + replicator_dev_seg->lv->status &= ~REPLICATOR ; + replicator_dev_seg->rlog_lv =NULL ; + replicator_dev_seg->replicator =NULL ; -return lv; +return 1 ; } -int replicator_add_rlog (struct lv_segment *replicator_seg, -struct logical_volume *rlog_lv) +/* +* Create new layered LV over the original LV +* this target will have a 'replicator-dev' segment +*/ +int lv_add_replicator_dev (struct logical_volume *replicator, +struct logical_volume *lv) { -if (!rlog_lv) +const struct segment_type *segtype; +struct logical_volume *rimage; +struct logical_volume *slog; +struct lv_segment *seg; +struct replicator_site *rsite; +const char *slog_name; +uint64_t dev_idx =first_seg (replicator)->rdevice_index_highest; + +if (!(segtype =get_segtype_from_string (lv->vg->cmd,"replicator-dev" ))) return_0; -if (rlog_lv->status &REPLICATOR_LOG ) { -log_error ("Rlog device %s is already used." , rlog_lv->name); +if (activation () && segtype->ops->target_present && + !segtype->ops->target_present (lv->vg->cmd,NULL ,NULL )) { +log_error ("%s: Required device-mapper target(s) not " +"detected in your kernel" , segtype->name);return 0 ; } -lv_set_hidden (rlog_lv); - rlog_lv->status |=REPLICATOR_LOG ; - replicator_seg->rlog_lv = rlog_lv; +/* If replicator does not have any site defined, add local default site */ +if (dm_list_empty (&replicator->rsites)) { +if (!replicator_add_site (replicator,DEFAULT_REPLICATOR_LOCAL_SITE_NAME )) + return_0; +first_seg (replicator)->rsite_index_highest++; + } + +first_seg (replicator)->rdevice_index_highest++; + dm_list_iterate_items(rsite, &replicator->rsites) { +if (rsite->site_index ==0 ) { +if (!(rimage =insert_layer_for_lv (lv->vg->cmd, lv,0 ,"_rimage" ))) + return_0; -return add_seg_to_segs_using_this_lv (rlog_lv, replicator_seg); + seg =first_seg (lv); + seg->segtype = segtype;/* switch to replicator-dev */ + +if (!replicator_add_replicator_dev (replicator, seg)) + return_0; + +if (!replicator_site_add_device (rsite, seg, rimage->name, + rimage,0 ,NULL , dev_idx)) + return_0; + }else { +// FIXME: corelog support missing + slog_name =_replicator_device_slog_name (replicator, rsite->site_index, + dev_idx); +if (!(slog =find_lv (lv->vg, slog_name))) { +log_error ("Cannot find slog LV %s for %s/%s" , + slog_name, rsite->name, lv->name); +return 0 ; + } + +if (!replicator_site_add_device (rsite, seg, lv->name, +NULL ,0 , slog, dev_idx)) + return_0; + } + } + +return 1 ; } -struct logical_volume *replicator_remove_rlog (struct lv_segment *replicator_seg) +int lv_remove_replicator_dev (struct logical_volume *lv) +{ +/* FIXME: collect all removed devices */ +if (!_replicator_remove_replicator_dev (first_seg (lv))) + return_0; + +return 1 ; +} + +int lv_add_replicator_site (struct logical_volume *replicator, +const struct replicator_site *rsite) { -struct logical_volume *lv; +struct replicator_site *nrsite; + +if (!lv_is_replicator (replicator)) { +log_error (INTERNAL_ERROR "Logical volume %s is not a " +"replicator." , replicator->name); +return 0 ; + } -if (!replicator_seg) +if (!(nrsite =replicator_add_site (replicator, rsite->name))) return_0; -if (!(lv = replicator_seg->rlog_lv)) { -log_error ("Replog segment %s does not have rlog." , - replicator_seg->lv->name); -return NULL ; +if (rsite->vg_name && + !(nrsite->vg_name =dm_pool_strdup (replicator->vg->vgmem, + rsite->vg_name))) { +log_error ("Allocation of replicator site vg_name failed." ); +return 0 ; } -if (!remove_seg_from_segs_using_this_lv (lv, replicator_seg)) - return_NULL; + nrsite->site_index =first_seg (replicator)->rsite_index_highest++; + nrsite->op_mode = rsite->op_mode; + nrsite->fall_behind_data = rsite->fall_behind_data; + nrsite->fall_behind_ios = rsite->fall_behind_ios; + nrsite->fall_behind_timeout = rsite->fall_behind_timeout; - replicator_seg->rlog_lv =NULL ; - lv->status &= ~REPLICATOR_LOG ; -lv_set_visible (lv); +return 1 ; +} -return lv; +int lv_remove_replicator_site (struct logical_volume *replicator, +const char *site_name) +{ +struct replicator_site *rsite, *trsite; + +if (!(rsite =find_site_in_replicator (replicator, site_name))) { +log_error (INTERNAL_ERROR "Replicator %s does not contain " +"site %s." , site_name, replicator->name); +return 0 ; + } + +if (!_replicator_remove_site (rsite)) + return_0; + +/* When the local site is removed, all remote sites must be removed */ +if (rsite->site_index ==0 ) { + dm_list_iterate_items_safe(rsite, trsite, &replicator->rsites) +if (!_replicator_remove_site (rsite)) + return_0; + } + +return 1 ; } +int vg_prearrange_replicator (struct volume_group *vg, +const struct lvcreate_params *lp) +{ +struct logical_volume *replicator =NULL ; +struct replicator_device *rdev; +struct replicator_site *rsite; +unsigned site_index; +uint64_t device_index; -#if 0 -/* -* Create new LV to pretend the original LV -* this target will have a 'replicator' segment -*/ -int lv_add_replicator (struct logical_volume *origin,const char *rep_suffix) +if (lp->replicator_dev || lp->rsite.name) +if (!(replicator =find_lv (vg, lp->replicator))) { +log_error ("Replicator %s not found." , lp->replicator); +return 0 ; + } + +if (lp->replicator_dev) { + device_index =first_seg (replicator)->rdevice_index_highest; + dm_list_iterate_items(rsite, &replicator->rsites) { +if (rsite->site_index !=0 && + !lv_add_sync_log (replicator, + rsite->site_index, + device_index, + lp->pvh, lp->alloc)) + return_0; + } + } + +if (lp->rsite.name) { + site_index =first_seg (replicator)->rsite_index_highest; + dm_list_iterate_items(rsite, &replicator->rsites) { +if (rsite->site_index !=0 ) +continue ; + + dm_list_iterate_items(rdev, &rsite->rdevices) { +if (!lv_add_sync_log (replicator, + site_index, + rdev->device_index, + lp->pvh, lp->alloc)) + return_0; + } + } + +if (!lv_add_replicator_site (replicator, &lp->rsite)) + return_0; + +if (!archive (vg)) + return_0; + +/* store vg on disk(s) */ +if (!vg_write (vg) || !vg_commit (vg)) + return_0; + +backup (vg); + } + +return 1 ; +} + +int vg_add_replicator (struct logical_volume *replicator, +const char *rlog_type, +uint32_t region_size) { -struct logical_volume *rep_lv; -char *name; -size_t slen; +const struct segment_type *segtype; +//float sync_percent; +//percent_range_t percent_range; +struct logical_volume *rlog_lv; +struct lv_segment *repseg; +struct lvinfo info; + +/* +* We are unable to convert the log of inactive cluster replictors +*/ +if (vg_is_clustered (replicator->vg) + && !(lv_info (replicator->vg->cmd, replicator, &info,0 ,0 ) && + info.exists)) { +log_error ("Replicator in this VG is not supported." ); +return 0 ; + } -if (!(name =strstr (origin->name, rep_suffix))) { -log_error ("Failed to find replicator suffix %s in LV name %s" , - rep_suffix, origin->name); +if (!(segtype =get_segtype_from_string (replicator->vg->cmd, +"replicator" ))) + return_0; + +if (activation () && segtype->ops->target_present && + !segtype->ops->target_present (replicator->vg->cmd,NULL ,NULL )) { +log_error ("%s: Required device-mapper target(s) not " +"detected in your kernel" , segtype->name);return 0 ; } - slen = (size_t )(name - origin->name); - name =alloca (slen +1 ); -memcpy (name, origin->name, slen); - name[slen] =0 ; -if ((rep_lv =find_lv (origin->vg, name))) { - rep_lv->status |=VIRTUAL ; -return 1 ; +if (!(rlog_lv =insert_layer_for_lv (replicator->vg->cmd, + replicator,0 ,"_rlog" ))) { +log_error ("Failed to insert replicator _rlog" ); +return 0 ; } -if (!(rep_lv =lv_create_empty (name, &origin->lvid, -LVM_READ |LVM_WRITE |VISIBLE_LV , -ALLOC_INHERIT , origin->vg))) - return_0; + repseg =first_seg (replicator); + repseg->segtype = segtype; + + repseg->rlog_type = rlog_type;//"ringbuffer"; + repseg->rdevice_index_highest =0 ; + repseg->rsite_index_highest =0 ; + repseg->region_size = region_size; -if (!lv_add_virtual_segment (rep_lv,0 , origin->le_count, -get_segtype_from_string (origin->vg->cmd, -"error" ))) +replicator_init (replicator); + +if (!replicator_add_rlog (repseg, rlog_lv)) return_0; - rep_lv->status |=VIRTUAL ;return 1 ; } -int lv_remove_replicator (struct logical_volume *lv) +int vg_remove_replicator (struct logical_volume *replicator) { +/* FIXME: replace heads with error targets first */ +if (!suspend_lv (replicator->vg->cmd, replicator)) { +log_error ("Failed to suspend %s." , + replicator->name); +return 0 ; + } +return 1 ; } -#endif /* * Check all replicator structures:
@@ -266,7 +763,7 @@ int check_replicator_segment(const struct lv_segment *rseg) {struct replicator_site *rsite, *rsiteb;struct replicator_device *rdev, *rdevb; -struct logical_volume *lv = rseg->lv; +struct logical_volume *lv = rseg->lv;int r =1 ;if (vg_is_clustered (lv->vg)) {
@@ -304,29 +801,30 @@ int check_replicator_segment(const struct lv_segment *rseg) } }else {if (rsite->fall_behind_timeout && rsite->fall_behind_ios) { -log_error ("Defined fall_behind_timeout and" -" fall_behind_ios for async replicator %s/%s." , +log_error ("Defined fall_behind_timeout and " +"fall_behind_ios for async replicator %s/%s." , lv->name, rsite->name); r =0 ; }if (rsite->fall_behind_timeout && rsite->fall_behind_data) { -log_error ("Defined fall_behind_timeout and" -" fall_behind_data for async replicator %s/%s." , +log_error ("Defined fall_behind_timeout and " +"fall_behind_data for async replicator %s/%s." , lv->name, rsite->name); r =0 ; }if (rsite->fall_behind_ios && rsite->fall_behind_data) { -log_error ("Defined fall_behind_ios and" -" fall_behind_data for async replicator %s/%s." , +log_error ("Defined fall_behind_ios and " +"fall_behind_data for async replicator %s/%s." , lv->name, rsite->name); r =0 ; }if (!rsite->fall_behind_ios && !rsite->fall_behind_data && !rsite->fall_behind_timeout) { -log_error ("fall_behind_timeout," -" fall_behind_ios and fall_behind_data are" -" undefined for async replicator %s/%s." , +log_error ("For async replicator %s/%s on of " +"fall_behind_timeout, " +"fall_behind_ios and fall_behind_data are " +"needs to be defined." , lv->name, rsite->name); r =0 ; }
@@ -335,16 +833,16 @@ int check_replicator_segment(const struct lv_segment *rseg)if (rsite == rsiteb)break ;if (strcasecmp (rsite->name, rsiteb->name) ==0 ) { -log_error ("Duplicate site name " -"%s detected for replicator %s." , +log_error ("Duplicate site name %s " +"detected for replicator %s." , rsite->name, lv->name); r =0 ; }if ((rsite->vg_name && rsiteb->vg_name &&strcasecmp (rsite->vg_name, rsiteb->vg_name) ==0 ) || (!rsite->vg_name && !rsiteb->vg_name)) { -log_error ("Duplicate VG name " -"%s detected for replicator %s." , +log_error ("Duplicate VG name %s " +"detected for replicator %s." , (rsite->vg_name) ? rsite->vg_name :"<local>" , lv->name); r =0 ;
@@ -356,8 +854,8 @@ int check_replicator_segment(const struct lv_segment *rseg) rsite->name); r =0 ; } -if (rsite->site_index > rseg->rsite_index_highest) { - log_error("Site index %d > %d (too high) " +if (rsite->site_index >= rseg->rsite_index_highest) { + log_error("Site index %d >= %d (too high) " "for replicator site %s/%s.", rsite->site_index, rseg->rsite_index_highest,
@@ -367,6 +865,20 @@ int check_replicator_segment(const struct lv_segment *rseg) } dm_list_iterate_items(rdev, &rsite->rdevices) { +if (rdev->rsite->site_index ==0 ) { +if (strcasecmp (rdev->name, + rdev->replicator_dev->lv->name) ==0 ) { +log_error ("Self referenced device name " +"%s detected for replicator %s." , + rdev->name, lv->name); + r =0 ; + } + }else if (!rdev->slog && !rdev->slog_core) { +log_error ("Undefined slog for %s/%s " +" for replicator %s." , + rdev->rsite->name, rdev->name, lv->name); + r =0 ; + } dm_list_iterate_items(rdevb, &rsite->rdevices) {if (rdev == rdevb)break ;
@@ -376,6 +888,13 @@ int check_replicator_segment(const struct lv_segment *rseg) rdev->slog->name, lv->name); r =0 ; } +if (strcasecmp (rdev->name, + rdevb->replicator_dev->lv->name) ==0 ) { +log_error ("Internal self reference device " +"name %s detected for replicator %s." , + rdev->name, lv->name); + r =0 ; + }if (strcasecmp (rdev->name, rdevb->name) ==0 ) { log_error("Duplicate device name %s " "detected for replicator %s.",
@@ -390,9 +909,9 @@ int check_replicator_segment(const struct lv_segment *rseg) lv->name, rsite->name); r =0 ; } -if (rdev->device_index > rseg->rdevice_index_highest) { - log_error("Device index %" PRIu64 - " > %" PRIu64 " (too high) " +if (rdev->device_index >= rseg->rdevice_index_highest) { + log_error("Device index %" PRIu64 " >= %" + PRIu64 " (too high) " "for replicator site %s/%s.", rdev->device_index, rseg->rdevice_index_highest,
@@ -406,78 +925,28 @@ int check_replicator_segment(const struct lv_segment *rseg)return r; } -/** -* Is this segment part of active replicator -*/ -int lv_is_active_replicator_dev (const struct logical_volume *lv) +int replicator_site_set_op_mode (struct replicator_site *rsite,const char *sitemode) { -return ((lv->status &REPLICATOR ) && - lv->rdevice && - lv->rdevice->rsite && - lv->rdevice->rsite->state ==REPLICATOR_STATE_ACTIVE ); -} +int i; -/** -* Is this LV replicator control device -*/ -int lv_is_replicator (const struct logical_volume *lv) -{ -return ((lv->status &REPLICATOR ) && - !dm_list_empty (&lv->segments) && -seg_is_replicator (first_seg (lv))); -} - -/** -* Is this LV replicator device -*/ -int lv_is_replicator_dev (const struct logical_volume *lv) -{ -return ((lv->status &REPLICATOR ) && - !dm_list_empty (&lv->segments) && -seg_is_replicator_dev (first_seg (lv))); -} - -/** -* Is this LV replicated origin lv -*/ -int lv_is_rimage (const struct logical_volume *lv) -{ -return (lv->rdevice && lv->rdevice->lv == lv); -} - -/** -* Is this LV rlog -*/ -int lv_is_rlog (const struct logical_volume *lv) -{ -return (lv->status &REPLICATOR_LOG ); -} +for (i =0 ; i <sizeof (dm_op_mode_table)/sizeof (dm_op_mode_table[0 ]); ++i) +if (strcasecmp (sitemode, dm_op_mode_table[i].name) ==0 ) { + rsite->op_mode = dm_op_mode_table[i].value; +return 1 ; + } -/** -* Is this LV sync log -*/ -int lv_is_slog (const struct logical_volume *lv) -{ -return (lv->rdevice && lv->rdevice->slog == lv); +return 0 ; } -/** -* Returns first replicator-dev in site in case the LV is replicator-dev, -* NULL otherwise -*/ -struct logical_volume *first_replicator_dev (const struct logical_volume *lv) +const char *replicator_site_get_op_mode (const struct replicator_site *rsite) { -struct replicator_device *rdev; -struct replicator_site *rsite; +int i; -if (lv_is_replicator_dev (lv)) - dm_list_iterate_items(rsite, &first_seg(lv)->replicator->rsites) { - dm_list_iterate_items(rdev, &rsite->rdevices) -return rdev->replicator_dev->lv; -break ; - } +for (i =0 ; i <sizeof (dm_op_mode_table)/sizeof (dm_op_mode_table[0 ]); ++i) +if (rsite->op_mode == dm_op_mode_table[i].value) +return dm_op_mode_table[i].name; -return NULL ; +return NULL ; }/**
@@ -646,13 +1115,13 @@ int lv_read_replicator_vgs(struct logical_volume *lv)struct replicator_site *rsite;struct volume_group *vg; -if (!lv_is_replicator_dev (lv)) +if (!lv_is_active_replicator_dev (lv))return 1 ; dm_list_iterate_items(rsite, &first_seg(lv)->replicator->rsites) {if (!rsite->vg_name)continue ; - vg =vg_read (lv->vg->cmd, rsite->vg_name,0 ,0 );// READ_WITHOUT_LOCK + vg =vg_read (lv->vg->cmd, rsite->vg_name,0 ,READ_WITHOUT_LOCK );if (vg_read_error (vg)) {log_error ("Unable to read volume group %s" , rsite->vg_name);
@@ -691,3 +1160,325 @@ void lv_release_replicator_vgs(struct logical_volume *lv) rsite->vg =NULL ; } } + +static int _write_replicator_header (struct cmd_context *cmd,struct logical_volume *lv) +{ +return 1 ; +} + +/* +* Initialize log contents +* +* log_name = "mirror log", "replicator sync log" +*/ +static int _init_log (struct cmd_context *cmd, +struct logical_volume *log_lv,int in_sync, +struct dm_list *tags,int remove_on_failure, +const char *log_name, +int (*write_header) (struct cmd_context *cmd, +struct logical_volume *lv)) +{ +struct str_list *sl; +struct lvinfo info; +uint64_t orig_status = log_lv->status; +int was_active =0 ; + +if (!activation () && in_sync) { +log_error ("Aborting. Unable to create in-sync %s " +"while activation is disabled." , log_name); +return 0 ; + } + +/* If the LV is active, deactivate it first. */ +if (lv_info (cmd, log_lv, &info,0 ,0 ) && info.exists) { + (void )deactivate_lv (cmd, log_lv); +/* +* FIXME: workaround to fail early +* Ensure that log is really deactivated because deactivate_lv +* on cluster do not fail if there is log_lv with different UUID. +*/ +if (lv_info (cmd, log_lv, &info,0 ,0 ) && info.exists) { +log_error ("Aborting. Unable to deactivate %s." , + log_name); + goto revert_new_lv; + } + was_active =1 ; + } + +/* Temporary make it visible for set_lv() */ +lv_set_visible (log_lv); + +/* Temporary tag mirror log for activation */ + dm_list_iterate_items(sl, tags) +if (!str_list_add (cmd->mem, &log_lv->tags, sl->str)) { +log_error ("Aborting. Unable to tag %s." , log_name); + goto activate_lv; + } + +/* store mirror log on disk(s) */ +if (!vg_write (log_lv->vg) || !vg_commit (log_lv->vg)) + goto activate_lv; + +backup (log_lv->vg); + +if (!activate_lv (cmd, log_lv)) { +log_error ("Aborting. Failed to activate %s." , log_name); + goto revert_new_lv; + } + +/* Remove the temporary tags */ + dm_list_iterate_items(sl, tags) +if (!str_list_del (&log_lv->tags, sl->str)) +log_error ("Failed to remove tag %s from %s." , + log_name, sl->str); + +if (activation () && !set_lv (cmd, log_lv, log_lv->size, + in_sync ?-1 :0 )) { +log_error ("Aborting. Failed to wipe %s." , log_name); + goto deactivate_and_revert_new_lv; + } + +if (activation () && !write_header (cmd, log_lv)) {/* FIXME */ +log_error ("Aborting. Failed to write %s header." , log_name); + goto deactivate_and_revert_new_lv; + } + +if (!deactivate_lv (cmd, log_lv)) { +log_error ("Aborting. Failed to deactivate %s. " +"Manual intervention required." , log_name); +return 0 ; + } + +lv_set_hidden (log_lv); + +if (was_active && !activate_lv (cmd, log_lv)) + return_0; + +return 1 ; + +deactivate_and_revert_new_lv: +if (!deactivate_lv (cmd, log_lv)) { +log_error ("Unable to deactivate %s LV. " +"Manual intervention required." , log_name); +return 0 ; + } + +revert_new_lv: + log_lv->status = orig_status; + + dm_list_iterate_items(sl, tags) +if (!str_list_del (&log_lv->tags, sl->str)) +log_error ("Failed to remove tag %s from %s." , + log_name, sl->str); + +if (remove_on_failure && !lv_remove (log_lv)) { +log_error ("Manual intervention may be required to remove " +"abandoned log LV before retrying." ); +return 0 ; + } + +if (!vg_write (log_lv->vg) || !vg_commit (log_lv->vg)) +log_error ("Manual intervention may be required to " +"remove/restore abandoned log LV before retrying." ); +else +backup (log_lv->vg); + +activate_lv: +if (was_active && !remove_on_failure && !activate_lv (cmd, log_lv)) + return_0; + +return 0 ; +} + +#if 0 +static int _init_replicator_log (struct cmd_context *cmd, +struct logical_volume *log_lv,int in_sync, +struct dm_list *tags,int remove_on_failure) +{ +if (!_init_log (cmd, log_lv, in_sync, tags, remove_on_failure, +"replicator log" , _write_replicator_header)) + return_0; + +return 1 ; +} +#endif + +static int _init_replicator_sync_log (struct cmd_context *cmd, +struct logical_volume *log_lv,int in_sync, +struct dm_list *tags,int remove_on_failure) +{ +if (!_init_log (cmd, log_lv, in_sync, tags, remove_on_failure, +"sync log" , _write_replicator_header)) + return_0; + +return 1 ; +} + +/* Could be shared with mirror */ +static struct logical_volume *_create_log (struct logical_volume *lv, +struct alloc_handle *ah, +alloc_policy_t alloc, +const char *lv_name, +const char *suffix, +uint64_t status) +{ +struct logical_volume *log_lv; +char *log_name; +size_t len; + + len =strlen (lv_name) +32 ; +if (!(log_name =alloca (len))) { +log_error ("log_name allocation failed." ); +return NULL ; + } + +if (dm_snprintf (log_name, len,"%s%s" , lv_name, suffix) <0 ) { +log_error ("log_name allocation failed." ); +return NULL ; + } + +if (!(log_lv =lv_create_empty (log_name,NULL , +VISIBLE_LV |LVM_READ |LVM_WRITE , + alloc, lv->vg))) + return_NULL; + +if (!lv_add_log_segment (ah,0 , log_lv, status)) + return_NULL; + +return log_lv; +} + +#if 0 +static struct logical_volume *_set_up_replicator_log (struct cmd_context *cmd, +struct alloc_handle *ah, +struct logical_volume *lv, +uint32_t log_size __attribute((unused)), +alloc_policy_t alloc, +int in_sync) +{ +struct logical_volume *log_lv; +const char *suffix, *c; +char *lv_name; +size_t len; +struct lv_segment *seg; + +//init_mirror_in_sync(in_sync); + +/* Replicator log name is lv_name + suffix, determined as the following: +* 1. suffix is: +* o "_rlog" for the original replicator LV. +* o "_rlogtmp_%d" for temporary mirror LV, +* 2. lv_name is: +* o lv->name, if the log is temporary +* o otherwise, the top-level LV name +*/ + seg =first_seg (lv); +if (seg_type (seg,0 ) ==AREA_LV && +strstr (seg_lv (seg,0 )->name,MIRROR_SYNC_LAYER )) { + lv_name = lv->name; + suffix ="_rlogtmp_%d" ; + }else if ((c =strstr (lv->name,MIRROR_SYNC_LAYER ))) { + len = (size_t )(c - lv->name +1 ); +if (!(lv_name =alloca (len)) || + !dm_snprintf (lv_name, len,"%s" , lv->name)) { +log_error ("replicator log name allocation failed" ); +return 0 ; + } + suffix ="_rlog" ; + }else { + lv_name = lv->name; + suffix ="_rlog" ; + } + +if (!(log_lv =_create_log (lv, ah, alloc, lv_name, suffix,REPLICATOR_LOG ))) { +log_error ("Failed to create replicator log." ); +return NULL ; + } + +if (!_init_replicator_log (cmd, log_lv, in_sync, &lv->tags,1 )) { +log_error ("Failed to initialise replicator log." ); +return NULL ; + } + +return log_lv; +} +#endif + +static struct logical_volume *_set_up_sync_log (struct cmd_context *cmd, +struct alloc_handle *ah, +struct logical_volume *replicator, +unsigned site_index, +uint64_t device_index, +alloc_policy_t alloc, +int in_sync) +{ +struct logical_volume *log_lv; +const char *suffix ="" ; +char *lv_name; + +if (!(lv_name =_replicator_device_slog_name (replicator, site_index, device_index))) + return_NULL; + +if (!(log_lv =_create_log (replicator, ah, alloc, lv_name, suffix, +REPLICATOR_LOG ))) { +log_error ("Failed to create replicator sync log." ); +return NULL ; + } + +if (!_init_replicator_sync_log (cmd, log_lv, in_sync, &replicator->tags,1 )) { +log_error ("Failed to initialise replicator sync log." ); +return NULL ; + } + +return log_lv; +} + +int lv_add_sync_log (struct logical_volume *replicator, +unsigned site_index, +uint64_t device_index, +struct dm_list *allocatable_pvs, +alloc_policy_t alloc) +{ +struct cmd_context *cmd = replicator->vg->cmd; +const struct segment_type *segtype; +struct alloc_handle *ah; +uint32_t region_size; +int in_sync; +int r =1 ; + +if (!(segtype =get_segtype_from_string (cmd,"striped" ))) + return_0; + +if (activation () && segtype->ops->target_present && + !segtype->ops->target_present (cmd,NULL ,NULL )) { +log_error ("%s: Required device-mapper target(s) not " +"detected in your kernel" , segtype->name); +return 0 ; + } + + region_size =adjusted_mirror_region_size (replicator->vg->extent_size, + replicator->le_count, +first_seg (replicator)->region_size); + +/* allocate destination extents */ + ah =allocate_extents (replicator->vg,NULL , segtype, +0 ,0 ,1 , region_size,0 , + allocatable_pvs, alloc,NULL ); +if (!ah) { +log_error ("Unable to allocate extents for replicator sync log." ); +return 0 ; + } + +/* check sync status */ + in_sync =0 ; + +if (!_set_up_sync_log (cmd, ah, replicator, site_index, device_index, + alloc, in_sync)) { + stack; + r =0 ; + } + +alloc_destroy (ah); + +return r; +}
Signature · 1 line
1.7.1.1
PATCH 13/22 Replicator: replicator.c changes
In reply to Zdenek KabelacChanges for replicator.c source file.
Reusing few new API functions from replicator_manip.c for replicator. Add few missing log_error() diagnostic messages instead of <backtrace>.
Segment for replicator has now SEG_VIRTUAL and SEG_CANNOT_BE_ZEROED flags. (Not really sure about logic here).
--- lib/replicator/replicator.c | 178 +++++++++++++++---------------------------- 1 files changed, 61 insertions(+), 117 deletions(-)
lib/replicator/replicator.c +61 -117
@@ -104,61 +104,17 @@ static replicator_state_t _get_state(const struct config_node *sn,return def; } -/* Strings for replicator_action_t enum */ -static const char _op_mode_txt[NUM_DM_REPLICATOR_MODES ][8 ] = { -"sync" , -"warn" , -"stall" , -"drop" , -"fail" -}; - - -/* Parse action string */ -static dm_replicator_mode_t _get_op_mode (const struct config_node *sn, -const char *path,dm_replicator_mode_t def) -{ -char *str; -unsigned i; - -if (get_config_str (sn, path, &str)) { -for (i =0 ; i <sizeof (_op_mode_txt)/sizeof (_op_mode_txt[0 ]); ++i) -if (strcasecmp (str, _op_mode_txt[i]) ==0 ) { -log_very_verbose ("Setting %s to %s" , - path, _op_mode_txt[i]); -return (dm_replicator_mode_t ) i; - } -log_warn ("%s: unknown value '%s', using default '%s' operation mode" , - path, str, _op_mode_txt[def]); - } - -return def; -} -static struct replicator_site *_get_site (struct logical_volume *replicator,const char *key) { -struct dm_pool *mem = replicator->vg->vgmem;struct replicator_site *rsite; - dm_list_iterate_items(rsite, &replicator->rsites) -if (strcasecmp (rsite->name, key) ==0 ) -return rsite; - -if (!(rsite =dm_pool_zalloc (mem,sizeof (*rsite)))) - return_NULL; - -if (!(rsite->name =dm_pool_strdup (mem, key))) - return_NULL; +if ((rsite =find_site_in_replicator (replicator, key))) +return rsite; - rsite->replicator = replicator; -dm_list_init (&rsite->rdevices); -dm_list_add (&replicator->rsites, &rsite->list); - -return rsite; +return replicator_add_site (replicator, key); } -/* Parse replicator site element */ static int _add_site(struct lv_segment *seg, const char *key,
@@ -167,6 +123,7 @@ static int _add_site(struct lv_segment *seg,struct dm_pool *mem = seg->lv->vg->vgmem;const struct config_node *cn;struct replicator_site *rsite; +char *op_mode;if (!(rsite =_get_site (seg->lv, key))) return_0;
@@ -200,8 +157,11 @@ static int _add_site(struct lv_segment *seg,return SEG_LOG_ERROR ("Defined both fall_behind_ios " "and fall_behind_timeout in" ); - rsite->op_mode =_get_op_mode (sn,"operation_mode" , - rsite->op_mode); +if (!get_config_str (sn,"operation_mode" , &op_mode)) +return SEG_LOG_ERROR ("Operation mode undefined in" ); + +if (!replicator_site_set_op_mode (rsite, op_mode)) +return SEG_LOG_ERROR ("Unknown value for operation mode in" ); }if ((cn =find_config_node (sn,"volume_group" ))) {
@@ -226,8 +186,7 @@ static int _replicator_text_import(struct lv_segment *seg,const struct config_node *cn;struct logical_volume *rlog_lv; -if (!replicator_add_replicator_dev (seg->lv,NULL )) - return_0; +replicator_init (seg->lv);if (!(cn =find_config_node (sn,"replicator_log" )) || !cn->v || cn->v->type !=CFG_STRING )
@@ -246,7 +205,6 @@ static int _replicator_text_import(struct lv_segment *seg,if (!(seg->rlog_type =dm_pool_strdup (seg->lv->vg->vgmem, cn->v->v.str))) return_0; -log_very_verbose ("replicator_log = %s" , rlog_lv->name);log_very_verbose ("replicator_log_type = %s" , seg->rlog_type);
@@ -267,6 +225,7 @@ static int _replicator_text_import(struct lv_segment *seg,if (!_add_site (seg, sn->key, sn->child)) return_0; } +return 1 ; }
@@ -275,9 +234,10 @@ static int _replicator_text_export(const struct lv_segment *seg, struct formatter *f) {struct replicator_site *rsite; +const char *op_mode;if (!seg->rlog_lv) - return_0; + return_0;outf (f,"replicator_log = \"%s\"" , seg->rlog_lv->name);outf (f,"replicator_log_type = \"%s\"" , seg->rlog_type);
@@ -299,9 +259,13 @@ static int _replicator_text_export(const struct lv_segment *seg,outf (f,"site_index = %d" , rsite->site_index);/* Only non-default parameters are written */ -if (rsite->op_mode !=DM_REPLICATOR_SYNC ) -outf (f,"operation_mode = \"%s\"" , - _op_mode_txt[rsite->op_mode]); +if (rsite->op_mode !=DM_REPLICATOR_SYNC ) { +if (!(op_mode =replicator_site_get_op_mode (rsite))) { +log_error ("Unknown operation mode." ); +return 0 ; + } +outf (f,"operation_mode = \"%s\"" , op_mode); + }if (rsite->fall_behind_timeout)outfc (f,"# seconds" ,"fall_behind_timeout = %u" , rsite->fall_behind_timeout);
@@ -445,13 +409,13 @@ static int _add_device(struct lv_segment *seg, const struct config_node *sn, uint64_t devidx) { - struct dm_pool *mem = seg->lv->vg->vgmem; -struct logical_volume *lv =NULL ; -struct logical_volume *slog_lv =NULL ; +struct logical_volume *rimage =NULL ; +struct logical_volume *slog =NULL ;struct replicator_site *rsite =_get_site (seg->replicator, site_name);struct replicator_device *rdev; -const char *dev_str =NULL ; +const char *lv_name =NULL ;const char *slog_str =NULL ; +uint32_t slog_core =0 ;const struct config_node *cn;dm_list_iterate_items (rdev, &rsite->rdevices)
@@ -459,61 +423,42 @@ static int _add_device(struct lv_segment *seg,return SEG_LOG_ERROR ("Duplicate site found in" );if ((cn =find_config_node (sn,"sync_log" ))) { -if (!cn->v || !cn->v->v.str) -return SEG_LOG_ERROR ("Sync log must be a string in" ); - slog_str = cn->v->v.str; +if (cn->v && cn->v->v.str) + slog_str = cn->v->v.str; +else if (!get_config_uint32 (sn,"sync_log" , &slog_core)) +return SEG_LOG_ERROR ("Could not read 'sync_log' for" ); }if (!(cn =find_config_node (sn,"logical_volume" )) || !cn->v || !cn->v->v.str)return SEG_LOG_ERROR ("Logical volume must be a string in" ); - dev_str = cn->v->v.str; + lv_name = cn->v->v.str;if (!seg->lv->rdevice) {if (slog_str)return SEG_LOG_ERROR ("Sync log %s defined for local " -"device in" , slog_str); +"site device in" , slog_str);/* Check for device in current VG */ -if (!(lv =find_lv (seg->lv->vg, dev_str))) +if (!(rimage =find_lv (seg->lv->vg, lv_name)))return SEG_LOG_ERROR ("Logical volume %s not found in" , - dev_str); + lv_name); }else { -if (!slog_str) +if (!slog_str && !slog_core)return SEG_LOG_ERROR ("Sync log is missing for remote " -"device in" ); +"site device in" );/* Check for slog device in current VG */ -if (!(slog_lv =find_lv (seg->lv->vg, slog_str))) +if (!slog_core && + !(slog =find_lv (seg->lv->vg, slog_str)))return SEG_LOG_ERROR ("Sync log %s not found in" , slog_str); } -if (!(rdev =dm_pool_zalloc (mem,sizeof (*rdev)))) - return_0; - -if (!(rdev->name =dm_pool_strdup (mem, dev_str))) +if (!replicator_site_add_device (rsite, seg, lv_name, rimage, + slog_core, slog, devidx)) return_0; - rdev->replicator_dev = seg; - rdev->rsite = rsite; - rdev->device_index = devidx; - -if (!seg->lv->rdevice) { -if (!replicator_dev_add_rimage (rdev, lv)) -return SEG_LOG_ERROR ("LV inconsistency found in" ); - seg->lv->rdevice = rdev; - }else { -if (!slog_str || - !(rdev->slog_name =dm_pool_strdup (mem, slog_str))) - return_0; - -if (!replicator_dev_add_slog (rdev, slog_lv)) -return SEG_LOG_ERROR ("Sync log inconsistency found in" ); - } - -dm_list_add (&rsite->rdevices, &rdev->list);// linked site list -return 1 ; }
@@ -553,9 +498,6 @@ static int _replicator_dev_text_import(struct lv_segment *seg,if (!seg->lv->rdevice)return SEG_LOG_ERROR ("Replicator device without site in" ); - seg->rlog_lv =NULL ; - seg->lv->status |=REPLICATOR ; -return 1 ; }
@@ -586,10 +528,12 @@ static int _replicator_dev_text_export(const struct lv_segment *seg,outf (f,"logical_volume = \"%s\"" , rdev->name ? rdev->name : rdev->lv->name); -if (rdev->slog) -outf (f,"sync_log = \"%s\"" , rdev->slog->name); -else if (rdev->slog_name) -outf (f,"sync_log = \"%s\"" , rdev->slog_name); +if (rsite->site_index !=0 ) { +if (rdev->slog) +outf (f,"sync_log = \"%s\"" , rdev->slog->name); +else +outf (f,"sync_log = %d" , rdev->slog_core); + }out_dec_indent (f);
@@ -625,8 +569,10 @@ static int _replicator_dev_add_target_line(struct dev_manager *dm, seg->lv->name, seg->lv->rdevice->lv->name);if (!dm_tree_node_add_linear_target (node, seg->lv->size)) return_0; -if (!(rdev_dlid =build_dm_uuid (mem, seg->lv->rdevice->lv->lvid.s,NULL ))) - return_0; +if (!(rdev_dlid =build_dm_uuid (mem, seg->lv->rdevice->lv->lvid.s,NULL ))) { +log_error ("Failed to build replicator-dev uuid." ); +return 0 ; + }return dm_tree_node_add_target_area (node,NULL , rdev_dlid,0 ); }else if (seg->lv->rdevice->rsite->site_index) { log_error("Active site with site_index != 0 (%s, %d)",
@@ -640,8 +586,10 @@ static int _replicator_dev_add_target_line(struct dev_manager *dm,* must be present in dm_tree */ if (!seg_is_replicator_dev (seg) || - !(replicator_dlid =build_dm_uuid (mem, seg->replicator->lvid.s,NULL ))) - return_0; + !(replicator_dlid =build_dm_uuid (mem, seg->replicator->lvid.s,NULL ))) { +log_error ("Failed to build replicator dlid." ); +return 0 ; + }/* Select remote devices with the same device index */ dm_list_iterate_items(rsite, &seg->replicator->rsites) {
@@ -664,8 +612,10 @@ static int _replicator_dev_add_target_line(struct dev_manager *dm, }if (!rdev->lv || - !(rdev_dlid =build_dm_uuid (mem, rdev->lv->lvid.s,NULL ))) - return_0; + !(rdev_dlid =build_dm_uuid (mem, rdev->lv->lvid.s,NULL ))) { +log_error ("Failed UUID allocation." ); +return 0 ; + } slog_dlid =NULL ;
@@ -675,18 +625,12 @@ static int _replicator_dev_add_target_line(struct dev_manager *dm, slog_size = (uint32_t ) rdev->slog->size;if (!(slog_dlid =build_dm_uuid (mem, rdev->slog->lvid.s,NULL ))) return_0; - } else if (rdev->slog_name && -sscanf (rdev->slog_name,"%" PRIu32, &slog_size) ==1 ) { - slog_flags =DM_CORELOG |DM_FORCESYNC ; -if (slog_size ==0 ) { -log_error ("Failed to use empty corelog size " -"in replicator '%s'." , - rsite->replicator->name); -return 0 ; - } - }else { + } else if (rdev->slog_core || (rsite->site_index == 0)) { slog_flags =DM_CORELOG |DM_FORCESYNC ; slog_size =0 ;/* NOLOG */ + }else { +log_error (INTERNAL_ERROR "Either slog or corelog must be used." ); +return 0 ; } if (!dm_tree_node_add_replicator_dev_target(node,
@@ -766,7 +710,7 @@ int init_multiple_segtype(struct segtype_library *seglib) segtype->ops = &_replicator_ops; segtype->name =REPLICATOR_MODULE ; segtype->private =NULL ; - segtype->flags =SEG_REPLICATOR ; + segtype->flags =SEG_REPLICATOR |SEG_VIRTUAL |SEG_CANNOT_BE_ZEROED ;if (!lvm_register_segtype (seglib, segtype)) return_0;
Signature · 1 line
1.7.1.1
PATCH 14/22 Replicator: add new command option read functions
In reply to Zdenek Kabelacsite_arg - reads name of the site.sitemode_arg - reads site mode.
--- tools/lvmcmdline.c | 24 ++++++++++++++++++++++++ tools/tools.h | 2 ++ 2 files changed, 26 insertions(+), 0 deletions(-)
tools/lvmcmdline.c +24 -0
@@ -473,6 +473,30 @@ int readahead_arg(struct cmd_context *cmd __attribute((unused)), struct arg *a)return 1 ; } +int site_arg (struct cmd_context *cmd __attribute((unused)),struct arg *a) +{ +if (!validate_name (a->value)) { +log_error ("Invalid site name." ); +return 0 ; + } + +return 1 ; +} + +int sitemode_arg (struct cmd_context *cmd __attribute((unused)),struct arg *a) +{ +struct replicator_site rsite; + +if (!replicator_site_set_op_mode (&rsite, a->value)) { +log_error ("Invalid site mode %s." , a->value); +return 0 ; + } + + a->ui_value = rsite.op_mode; + +return 1 ; +} +/* * Non-zero, positive integer, "all", or "unmanaged" */
tools/tools.h +2 -0
@@ -153,6 +153,8 @@ int segtype_arg(struct cmd_context *cmd, struct arg *a);int alloc_arg (struct cmd_context *cmd,struct arg *a);int readahead_arg (struct cmd_context *cmd,struct arg *a);int metadatacopies_arg (struct cmd_context *cmd __attribute((unused)),struct arg *a); +int site_arg (struct cmd_context *cmd,struct arg *a); +int sitemode_arg (struct cmd_context *cmd,struct arg *a);/* we use the enums to access the switches */ unsigned arg_count (const struct cmd_context *cmd,int a);
Signature · 1 line
1.7.1.1
PATCH 15/22 Replicator: new args
In reply to Zdenek Kabelac--- tools/args.h | 10 ++++++++++ 1 files changed, 10 insertions(+), 0 deletions(-)
tools/args.h +10 -0
@@ -69,6 +69,16 @@ arg(noudevsync_ARG, '\0', "noudevsync", NULL, 0) arg(poll_ARG, '\0', "poll", yes_no_arg, 0) arg(stripes_long_ARG, '\0', "stripes", int_arg, 0) arg(sysinit_ARG, '\0', "sysinit", NULL, 0) +arg(replicator_ARG, '\0', "replicator", string_arg, 0) +arg(replicatordev_ARG, '\0', "replicatordev", NULL, 0) +arg(replicatorsynclog_ARG, '\0', "replicatorsynclog", string_arg, 0) +arg(replicatorlogtype_ARG, '\0', "replicatorlogtype", string_arg, 0) +arg(site_ARG, '\0', "site", site_arg, 0) +arg(fallbehinddata_ARG, '\0', "fallbehinddata", size_mb_arg, 0) +arg(fallbehindios_ARG, '\0', "fallbehindios", int_arg, 0) +arg(fallbehindtimeout_ARG, '\0', "fallbehindtimeout", int_arg, 0) +arg(sitemode_ARG, '\0', "sitemode", sitemode_arg, 0) +arg (remotevg_ARG,'\0' ,"remotevg" , string_arg,0 ) /* Allow some variations */arg (resizable_ARG,'\0' ,"resizable" , yes_no_arg,0 )
Signature · 1 line
1.7.1.1
PATCH 16/22 Replicator: read site_params
In reply to Zdenek KabelacCommon function for parsing replicator site parameters. It's used by lvcreate and lvchange command in later patch.
--- tools/toollib.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ tools/toollib.h | 3 + 2 files changed, 114 insertions(+), 0 deletions(-)
tools/toollib.c +111 -0
@@ -1551,3 +1551,114 @@ int get_stripe_params(struct cmd_context *cmd, uint32_t *stripes, uint32_t *strireturn _validate_stripe_params (cmd, stripes, stripe_size); } +/** +* Parse parameters for replicator site +* +* \param cmd +* \param rsite +* \param changed +*/ +int get_replicator_site_params (struct cmd_context *cmd, +struct replicator_site *rsite, +int *changed) +{ +struct replicator_site nrsite; + +if (arg_count (cmd, fallbehinddata_ARG)) { + nrsite.fall_behind_data = +arg_uint64_value (cmd, fallbehinddata_ARG, +DEFAULT_REPLICATOR_FALL_BEHIND_DATA ); +if (rsite->fall_behind_data != nrsite.fall_behind_data) { + rsite->fall_behind_data = nrsite.fall_behind_data; + rsite->fall_behind_ios =0 ; + rsite->fall_behind_timeout =0 ; + (*changed)++; + } + } + +if (arg_count (cmd, fallbehindios_ARG)) { +if (arg_count (cmd, fallbehinddata_ARG)) { +log_error ("Only one asynchronous parameter can be used." ); +return 0 ; + } + nrsite.fall_behind_ios = +arg_uint_value (cmd, fallbehindios_ARG, +DEFAULT_REPLICATOR_FALL_BEHIND_IOS ); + +if (rsite->fall_behind_ios != nrsite.fall_behind_ios) { + rsite->fall_behind_data =0 ; + rsite->fall_behind_ios = nrsite.fall_behind_ios; + rsite->fall_behind_timeout =0 ; + (*changed)++; + } + } + +if (arg_count (cmd, fallbehindtimeout_ARG)) { +if (arg_count (cmd, fallbehinddata_ARG) || +arg_count (cmd, fallbehindios_ARG)) { +log_error ("Only one asynchronous parameter can be used." ); +return 0 ; + } + nrsite.fall_behind_timeout = +arg_uint_value (cmd, fallbehindtimeout_ARG, +DEFAULT_REPLICATOR_FALL_BEHIND_TIMEOUT ); + +if (rsite->fall_behind_timeout != nrsite.fall_behind_timeout) { + rsite->fall_behind_data =0 ; + rsite->fall_behind_ios =0 ; + rsite->fall_behind_timeout = nrsite.fall_behind_timeout; + (*changed)++; + } + } + + nrsite.op_mode =NUM_DM_REPLICATOR_MODES ; +if (arg_count (cmd, sitemode_ARG)) { + nrsite.op_mode =arg_uint_value (cmd, sitemode_ARG, +DEFAULT_REPLICATOR_ASYNC_MODE ); +if ((nrsite.op_mode ==DM_REPLICATOR_SYNC ) && + !arg_count (cmd, fallbehinddata_ARG) && + !arg_count (cmd, fallbehindios_ARG) && + !arg_count (cmd, fallbehindtimeout_ARG) && + (rsite->fall_behind_data || + rsite->fall_behind_ios || + rsite->fall_behind_timeout)) { + rsite->fall_behind_data =0 ; + rsite->fall_behind_ios =0 ; + rsite->fall_behind_timeout =0 ; + (*changed)++; +log_debug ("Clearing asynchronous parameters synchronous site." ); + } + } + +if (rsite->fall_behind_data || + rsite->fall_behind_ios || + rsite->fall_behind_timeout) { +if (!rsite->vg_name) { +log_error ("Cannot set asynchronous parameters for " +"the local site %s." , rsite->name); +return 0 ; + } +if (nrsite.op_mode ==DM_REPLICATOR_SYNC ) { +log_error ("For synchronous site mode all asynchronous " +"parameters must be deleted." ); +return 0 ; + }else if (nrsite.op_mode ==NUM_DM_REPLICATOR_MODES ) + nrsite.op_mode = (rsite->op_mode ==DM_REPLICATOR_SYNC ) ? +DEFAULT_REPLICATOR_ASYNC_MODE : rsite->op_mode; + }else { +if (nrsite.op_mode !=NUM_DM_REPLICATOR_MODES && + nrsite.op_mode !=DM_REPLICATOR_SYNC ) { +log_error ("For asynchronous site mode an asynchronous " +"non-zero parameter must be specified." ); +return 0 ; + } + nrsite.op_mode =DM_REPLICATOR_SYNC ; + } + +if (rsite->op_mode != nrsite.op_mode) { + rsite->op_mode = nrsite.op_mode; + (*changed)++; + } + +return 1 ; +}
tools/toollib.h +3 -0
@@ -118,4 +118,7 @@ int get_activation_monitoring_mode(struct cmd_context *cmd,int get_stripe_params (struct cmd_context *cmd,uint32_t *stripes,uint32_t *stripe_size); +int get_replicator_site_params (struct cmd_context *cmd, +struct replicator_site *rsite, +int *changed);#endif
Signature · 1 line
1.7.1.1
PATCH 17/22 Replicator: lv_manip - create replicator
In reply to Zdenek Kabelac--- lib/metadata/lv_manip.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 125 insertions(+), 1 deletions(-)
lib/metadata/lv_manip.c +125 -1
@@ -418,6 +418,8 @@ static int _lv_reduce(struct logical_volume *lv, uint32_t extents, int delete)/* FIXME Check this is safe */ if (seg->log_lv && !lv_remove (seg->log_lv)) return_0; +if (seg->rlog_lv && !lv_remove (seg->rlog_lv)) + return_0;dm_list_del (&seg->list); reduction = seg->len; }else
@@ -2205,6 +2207,7 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,struct volume_group *vg;struct lvinfo info;struct logical_volume *origin =NULL ; +struct logical_volume *replicator =NULL ;int was_merging =0 ; vg = lv->vg;
@@ -2230,6 +2233,12 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,return 0 ; } +if (lv_is_rimage (lv) ||lv_is_rlog (lv) ||lv_is_slog (lv)) { +log_error ("Can't remove logical volume %s used by a " +"replicator." , lv->name); +return 0 ; + } +if (lv->status &LOCKED ) {log_error ("Can't remove locked LV %s" , lv->name);return 0 ;
@@ -2267,6 +2276,14 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv, return_0; } +if (lv_is_replicator_dev (lv)) { + replicator =first_seg (lv)->replicator; +if (!lv_remove_replicator_dev (lv)) { +log_error ("Unable to remove replicator-dev %s" , lv->name); +return 0 ; + } + } +if (!deactivate_lv (cmd, lv)) {log_error ("Unable to deactivate logical volume \"%s\"" , lv->name);
@@ -2295,6 +2312,17 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv, } } +if (replicator) { +if (!suspend_lv (cmd, replicator)) { +log_error ("Failed to refresh replicator %s." , replicator->name); +return 0 ; + } +if (!resume_lv (cmd, replicator)) { +log_error ("Failed to resume replicator %s." , replicator->name); +return 0 ; + } + } +backup (vg);if (lv_is_visible (lv))
@@ -2310,6 +2338,8 @@ int lv_remove_with_dependencies(struct cmd_context *cmd, struct logical_volume * const force_t force, unsigned level) { struct dm_list *snh, *snht; +struct replicator_site *rsite; +struct replicator_device *rdev;if (lv_is_cow (lv)) {/* A merging snapshot cannot be removed directly */
@@ -2320,6 +2350,18 @@ int lv_remove_with_dependencies(struct cmd_context *cmd, struct logical_volume * } } +if (lv_is_replicator (lv)) { +/* Remove replicators' head LVs first */ + dm_list_iterate_items(rsite, &lv->rsites) { +if (rsite->site_index !=0 ) +continue ; + dm_list_iterate_items(rdev, &rsite->rdevices) +if (!lv_remove_with_dependencies (cmd, rdev->lv, + force, level +1 )) + return_0; + } + } +if (lv_is_origin (lv)) {/* remove snapshot LVs first */ dm_list_iterate_safe(snh, snht, &lv->snapshot_segs) {
@@ -2998,6 +3040,7 @@ int lv_create_single(struct volume_group *vg,struct logical_volume *lv, *org =NULL ;int origin_active =0 ;struct lvinfo info; +struct logical_volume *replicator;if (lp->lv_name &&find_lv_in_vg (vg, lp->lv_name)) { log_error("Logical volume \"%s\" already exists in "
@@ -3118,6 +3161,13 @@ int lv_create_single(struct volume_group *vg, } } +if (lp->replicator) { +if (!vg_prearrange_replicator (vg, lp)) + return_0; +if (lp->rsite.name && !lp->replicator_dev) +return 1 ;/* Do not create any LV this time */ + } +if (!lp->extents) {log_error ("Unable to create new logical volume with no extents" );return 0 ;
@@ -3169,6 +3219,19 @@ int lv_create_single(struct volume_group *vg, } } +if (lp->replicator_dev) { +init_replicator_in_sync (lp->nosync); + +if (lp->nosync) { +log_error ("FIXME: Unsupported." ); +return 0 ; + +log_warn ("WARNING: New replicator won't be synchronised. " +"Don't read what you didn't write!" ); + status |=REPLICATOR_NOTSYNCED ; + } + } +if (!(lv =lv_create_empty (lp->lv_name ? lp->lv_name :"lvol%d" ,NULL , status, lp->alloc, vg))) return_0;
@@ -3225,6 +3288,12 @@ int lv_create_single(struct volume_group *vg, "exception store."); goto revert_new_lv; } + }else if (lp->replicator_dev || lp->replicator) { +if (!activate_lv_excl (cmd, lv)) { +log_error ("Aborting. Failed to activate replicator " +"device." ); + goto revert_new_lv; + } }else if (!activate_lv (cmd, lv)) {if (lp->zero) { log_error("Aborting. Failed to activate new LV to wipe "
@@ -3240,10 +3309,65 @@ int lv_create_single(struct volume_group *vg,else if (!set_lv (cmd, lv,UINT64_C (0 ),0 )) {log_error ("Aborting. Failed to wipe %s." , lp->snapshot ?"snapshot exception store" : -"start of new LV" ); + lp->replicator ?"replicator backing store" : +"start of new LV" ); goto deactivate_and_revert_new_lv; } +if (!lp->replicator_dev && lp->replicator) { +if (!deactivate_lv (cmd, lv)) { +log_error ("Aborting. Couldn't deactivate replicator log." +" Manual intervention required." ); +return 0 ; + } +if (!vg_add_replicator (lv, lp->rlog_type, lp->region_size)) { +log_error ("Could not create replicator." ); + goto revert_new_lv; + } +/* store vg on disk(s) */ +if (!vg_write (vg) || !vg_commit (vg)) + return_0; + } + +if (lp->replicator_dev) { +if (!lp->replicator) { +log_error ("Replicator is not specified." ); +return 0 ; + } +if (!deactivate_lv (cmd, lv)) { +log_error ("Aborting. Could not deactivate new LV." ); +return 0 ; + } + +if (!(replicator =find_lv (vg, lp->replicator))) { +log_error ("Could not find replicator." ); + goto revert_new_lv; + } + +if (!lv_add_replicator_dev (replicator, lv)) { +log_error ("Could not insert replicator device to replicator." ); + goto revert_new_lv; + } + +/* store vg on disk(s) */ +if (!vg_write (vg)) + return_0; + +if (!suspend_lv (cmd, replicator)) { +log_error ("Failed to suspend replicator %s" , replicator->name); +vg_revert (vg); +return 0 ; + } + +if (!vg_commit (vg)) + return_0; + +if (!resume_lv (cmd, replicator)) { +log_error ("Problem reactivating replicator %s" , replicator->name); +return 0 ; + } + } +if (lp->snapshot) {/* Reset permission after zeroing */ if (!(lp->permission &LVM_WRITE ))
Signature · 1 line
1.7.1.1
PATCH 18/22 Replicator: lvcreate implementation
In reply to Zdenek Kabelac--- tools/commands.h | 9 ++++ tools/lvcreate.c | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 139 insertions(+), 3 deletions(-)
tools/commands.h +9 -0
@@ -165,6 +165,12 @@ xx(lvcreate,"\t[-p|--permission {r|rw}]\n" "\t[-r|--readahead ReadAheadSectors|auto|none]\n" "\t[-R|--regionsize MirrorLogRegionSize]\n" +"\t[--replicator [ReplicatorName] [--replicatorlogtype ringbuffer]\n" +"\t[{--replicatorsynclog {disk|core}|--corelog}]\n" +"\t[--site LocalSiteName [--sitemode {sync|warn|stall|drop|fail}]\n" +"\t [--remotevg RemoteVGName] [{--fallbehinddata Size[bBsSkKmMgG]|\n" +"\t --fallbehindios IOCount|--fallbehindtimeout Secs}]]\n" +"\t[--replicatordev]\n" "\t[-t|--test]\n" "\t[--type VolumeType]\n" "\t[-v|--verbose]\n"
@@ -203,6 +209,9 @@ xx(lvcreate, mirrorlog_ARG, mirrors_ARG, monitor_ARG, name_ARG, nosync_ARG, noudevsync_ARG, permission_ARG, persistent_ARG, readahead_ARG, regionsize_ARG, size_ARG, snapshot_ARG, stripes_ARG, stripesize_ARG, test_ARG, type_ARG, + replicator_ARG, replicatordev_ARG, replicatorlogtype_ARG, + remotevg_ARG, site_ARG, sitemode_ARG, + fallbehinddata_ARG, fallbehindios_ARG, fallbehindtimeout_ARG, virtualoriginsize_ARG, virtualsize_ARG, zero_ARG) xx(lvdisplay,
tools/lvcreate.c +130 -3
193 lines not on this page · raw message
Signature · 1 line
1.7.1.1
PATCH 19/22 Replicator: man page update for lvcreate
In reply to Zdenek KabelacUpdate man page to cover basic usage of lvcreate
Current descriptions shows how to create replicator, add site, add replicated device.
--- man/lvcreate.8.in | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 76 insertions(+), 0 deletions(-)
man/lvcreate.8.in +76 -0
@@ -36,6 +36,27 @@ VolumeGroupName [PhysicalVolumePath[:PE[-PE]]...] OriginalLogicalVolumePath | [\-s|\-\-snapshot] VolumeGroupName \-\-virtualsize VirtualSize} +.br + +.br +.B lvcreate +\-\-replicator [ReplicatorName[Path]] +[\-\-replicatordev] +{\-l|\-\-extents LogicalExtentsNumber[%{VG|FREE|ORIGIN}] | + \-L|\-\-size LogicalVolumeSize[bBsSkKmMgGtTpPeE]} +[\-\-nosync] +[\-\-replicatorlogtype ReplicatorLogType] +{[\-\-replicatorsynclog {disk|core}] | [\-\-corelog]} +[\-R|\-\-regionsize ReplicatorSyncLogRegionSize]] +[\-\-site SiteName [\-\-sitemode {sync|warn|stall|drop|fail}] +{[\-\-fallbehinddata Size[bBsSkKmMgGtTpPeE]] | +[\-\-fallbehindios IOS] | +[\-\-fallbehindtimeout secs]} +[\-\-remotevg RemoteVolumeGroupName]] +\-n|\-\-name ReplicatorName +VolumeGroupName +.br + .SH DESCRIPTION lvcreate creates a new logical volume in a volume group ( see .B vgcreate(8), vgchange(8)
@@ -52,6 +73,8 @@ extents will be restricted to these volumes. .br The second form supports the creation of snapshot logical volumes which keep the contents of the original logical volume for backup purposes. +.br +The third form supports the creation of replicated devices. .SH OPTIONS See \fBlvm\fP for common options. .TP
@@ -120,6 +143,40 @@ device is activated, for example, after every reboot. Using "mirrored" will create a persistent log that is itself mirrored. The optional argument --corelog is equivalent to --mirrorlog core. +.TP +.I \-\-replicator +Creates empty replicator logical volume. (see \fBlvchange\fP(8)) for +options, how to customize created replicator LV. +Specifying optional argument --nosync will cause the creation +of the replicator to skip the initial resynchronization. Any data written +afterwards will be replicated, but the original content will not be +copied. This is useful for skipping a potentially long and resource +intensive initial sync of an empty device. Currrently this flag is not +supported. + +The optional argument --replicatorsynclog specifies the type of synclog to be +used. The default is disk, which is persistent and requires a small amount of +storage space. Using core means the replicator is regenerated by copying the +data from the first device again each time the device is activated, for +example, after every reboot. + +The optional argument --replicatorlogtype specifies type of the backing store +log. The default and currently the only valid and supported type is +\fBringbuffer\fP. + +The optional argument --site creates \fIsite\fP in replicator. Site could have +operation mode {sync|warn|stall|drop|fail}. For asynchronous modes one +of the following fall behind parameters must be specified: --fallbehinddata, +--fallbehindios, --fallbehindtimeout (see \fBlvchange\fP(8)). +For remote sites --remotevg specifies the name of +the remote volume group. Note: current implementation expects +that any remote volume group contains prepared logical volumes +with the same size and name as the local replicated logical volumes. + +.TP +.I \-\-replicatordev +Creates empty replicated logical volume in the local site +of given Replicator. .TP .I \-n, \-\-name LogicalVolumeName
@@ -246,10 +303,29 @@ under 100MB of actual data on it. creates a linear logical volume "vg00/lvol1" using physical extents /dev/sda:0-7 and /dev/sdb:0-7 for allocation of extents. +"lvcreate --replicator -L 1G -n rep0 vg00" +.br +creates a replicator "vg00/rep0" and hidden replicator backing store device +"vg00/rep0_rlog" of size 1G. + +"lvcreate --site Remote --remotevg remotevg00 --fallbehinddata 100M +--replicator vg00/rep0" +.br +creates the remote site named Remote in replicator "vg00/rep0" +that uses remote volume group "remotevg00" and could get upto 100MiB +asynchronous behind replicated volume. +Current implementation needs remote LVs created by hand +in the remote volume group "remotevg00". + +"lvcreate --replicatordev -n lvol1 -L 64M --replicator vg00/rep0" +.br +creates a replicated device named "vg00/lvol1" of size 64M attached to +the local site in the replicator "vg00/rep0". .SH SEE ALSO .BR lvm (8), .BR vgcreate (8), +.BR lvchange (8), .BR lvremove (8), .BR lvrename (8) .BR lvextend (8),
Signature · 1 line
1.7.1.1
PATCH 20/22 Replicator: lvchange implementation
In reply to Zdenek Kabelac--- tools/commands.h | 6 ++ tools/lvchange.c | 195 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 196 insertions(+), 5 deletions(-)
tools/commands.h +6 -0
@@ -80,6 +80,10 @@ xx(lvchange,"\t[-r|--readahead ReadAheadSectors|auto|none]\n" "\t[--refresh]\n" "\t[--resync]\n" +"\t[--replicator ReplicatorName]\n" +"\t[--site SiteName [--sitemode {sync|warn|stall|drop|fail}]\n" +"\t [{--fallbehinddata Size[bBsSkKmMgG]|\n" +"\t --fallbehindios IOCount|--fallbehindtimeout Secs}]]]\n" "\t[--sysinit]\n" "\t[-t|--test]\n" "\t[-v|--verbose]\n"
@@ -91,6 +95,8 @@ xx(lvchange, ignorelockingfailure_ARG, ignoremonitoring_ARG, major_ARG, minor_ARG, monitor_ARG, noudevsync_ARG, partial_ARG, permission_ARG, persistent_ARG, poll_ARG, readahead_ARG, resync_ARG, refresh_ARG, addtag_ARG, deltag_ARG, + fallbehinddata_ARG, fallbehindios_ARG, fallbehindtimeout_ARG, + replicator_ARG, replicatorlogtype_ARG, remotevg_ARG, site_ARG, sitemode_ARG, sysinit_ARG, test_ARG, yes_ARG) xx(lvconvert,
tools/lvchange.c +190 -5
250 lines not on this page · raw message
Signature · 1 line
1.7.1.1
PATCH 21/22 Replicator: man page update for lvchange
In reply to Zdenek KabelacUpdate lvchange man page to cover basic usability commands.
--- man/lvchange.8.in | 31 +++++++++++++++++++++++++++++++ 1 files changed, 31 insertions(+), 0 deletions(-)
man/lvchange.8.in +31 -0
@@ -7,6 +7,11 @@ lvchange \- change attributes of a logical volume [\-A|\-\-autobackup y|n] [\-a|\-\-available y|n|ey|en|ly|ln] [\-\-alloc AllocationPolicy] [\-C|\-\-contiguous y|n] [\-d|\-\-debug] [\-\-deltag Tag] +[[\-\-site Site] +[\-\-sitemode [sync|warn|stall|drop|fail] +{[\-\-fallbehinddata Size[bBsSkKmMgGtTpPeE]] | +[\-\-fallbehindios IOS] | +[\-\-fallbehindtimeout sec]}] [\-\-resync] [\-h|\-?|\-\-help] [\-\-ignorelockingfailure]
@@ -112,10 +117,36 @@ If the logical volume is active, reload its metadata. This is not necessary in normal operation, but may be useful if something has gone wrong or if you're doing clustering manually without a clustered lock manager. +.TP +.I \-\-fallbehinddata +How many data could get replicator behind. Cannot be mixed +with --fallbehindios or --fallbehindtimeout. +.TP +.I \-\-fallbehindios +How many io operation could be queued in replicator backing store device. +Cannot be mixed with --fallbehinddata or --fallbehindtimeout. +.TP +.I \-\-fallbehindtimeout +How many seconds could be replicator behind actual data. Cannot be mixed +with --fallbehinddata or --fallbehindios. +.TP +.I \-\-sitemode +Select replication mode. Default is Warn. +Sync is synchronous mode. Warn,Stall,Drop,Fail are asynchronous modes. +Warn issues warning when remote site is switched to sync log. +Stall stalls replicator until remote site is back in range. +Drop drops whole remote site, if it get too behind. +Fail whole replicator fails is remote sites gets too behind. +Local site works usually in stall mode. There is no synclog for local +replicated volumes. +.TP .SH Examples "lvchange -pr vg00/lvol1" changes the permission on volume lvol1 in volume group vg00 to be read-only. +"lvchange --site Berlin -ay vg00/L1" +marks the local site Berlin for LV "vg00/L1" as active. + .SH SEE ALSO .BR lvm (8), .BR lvcreate (8),
Signature · 1 line
1.7.1.1
PATCH 22/22 Replicator: lvremove implementation
In reply to Zdenek Kabelac--- tools/commands.h | 3 ++- tools/lvremove.c | 19 ++++++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-)
tools/commands.h +2 -1
@@ -365,12 +365,13 @@ xx(lvremove, "\t[-f|--force]\n" "\t[-h|--help]\n" "\t[--noudevsync]\n" + "\t[--site SiteName]\n" "\t[-t|--test]\n" "\t[-v|--verbose]\n" "\t[--version]" "\n" "\tLogicalVolume[Path] [LogicalVolume[Path]...]\n", - autobackup_ARG, force_ARG, noudevsync_ARG, test_ARG) + autobackup_ARG, force_ARG, noudevsync_ARG, site_ARG, test_ARG) xx(lvrename, "Rename a logical volume",
tools/lvremove.c +18 -1
@@ -1,6 +1,6 @@/* * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. -* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. +* Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved. * * This file is part of LVM2. *
@@ -19,6 +19,8 @@ static int lvremove_single(struct cmd_context *cmd, struct logical_volume *lv, void *handle __attribute((unused))) {struct logical_volume *origin; +struct logical_volume *replicator; +const char *site_name;/* * If this is a sparse device, remove its origin too.
@@ -26,6 +28,21 @@ static int lvremove_single(struct cmd_context *cmd, struct logical_volume *lv,if (lv_is_cow (lv) &&lv_is_virtual_origin (origin =origin_from_cow (lv))) lv = origin; +if ((lv_is_replicator_dev (lv) ||lv_is_replicator (lv)) && +arg_count (cmd, site_ARG)) { + replicator =lv_is_replicator (lv) ? lv :first_seg (lv)->replicator; + site_name =arg_str_value (cmd, site_ARG, +DEFAULT_REPLICATOR_LOCAL_SITE_NAME ); + +log_error ("REMOVE SITE %s of %s" , site_name, replicator->name); +if (!lv_remove_replicator_site (replicator, site_name)) { + stack; +return ECMD_FAILED ; + } + +return ECMD_PROCESSED ; + } +if (!lv_remove_with_dependencies (cmd, lv,arg_count (cmd, force_ARG),0 )) { stack;return ECMD_FAILED ;
Signature · 1 line
1.7.1.1