Add "degraded" activation mode
PATCH 1/1 Add "degraded" activation mode
Hi,
Here is my suggested patch for "degraded" activation mode. Without the ability to create a new cluster flag (e.g. LCK_DEGRADED_MODE), I may need to rethink the approach. RAID LVs are not cluster-aware and can only be activated exclusively in a cluster. However, activating a RAID LV in degraded mode would still be impossible if the activation was going through clvmd. The user would be forced to use "partial" activation in a cluster to activate the RAID LV.
brassow
activation: Add "degraded" activation mode
Currently, we have two modes of activation an unnamed nominal mode (which I will refer to as "complete") and "partial" mode. The "complete" mode requires that a volume group be 'complete' - that is, no missing PVs. If there are any missing PVs, no affected LVs are allowed to activate - even RAID LVs which might be able to tolerate a failure. The "partial" mode allows anything to be activated (or at least attempted). If a non-redundant LV is missing a portion of its addressable space due to a device failure, it will be replaced with an error target. RAID LVs will either activate or fail to activate depending on how badly their redundancy is compromised.
This patch adds a third option, "degraded" mode. This mode can be selected via the '--activationmode {complete|degraded|partial}' option to lvchange/vgchange. It can also be set in lvm.conf. The "degraded" activation mode allows RAID LVs with a sufficient level of redundancy to activate (e.g. a RAID5 LV with one device failure, a RAID6 with two device failures, or RAID1 with n-1 failures). RAID LVs with too many device failures are not allowed to activate - nor are any non-redundant LVs that may have been affected. This patch also makes the "degraded" mode the default activation mode.
The degraded activation mode does not yet work in a cluster. A new cluster lock flag (LCK_DEGRADED_MODE) will need to be created to make that work. Currently, there is limited space for this extra flag and I am looking for possible solutions.
conf/example.conf.in +25 -0
@@ -1011,6 +1011,31 @@ activation { # are no progress reports, but the process is awoken immediately the # operation is complete. polling_interval = 15 + + # 'activation_mode' determines how logical volumes are activated if + # devices are missing. Possible settings are: + # + # "complete" - Only allow activation of an LV if all of the PVs + # that it uses are available (i.e. the volume group + # is complete). There may be a failed PV in the + # volume group; but if a particular LV is not on that + # PV, it is still allowed to activate in this mode. + # + # "degraded" - Like "complete", except that RAID logical volumes of + # segment type "raid{1,4,5,6,10}" are activated if + # they have sufficient redundancy to present the entire + # addressable range of the logical volume. + # + # "partial" - Allow activation for any logical volume - even if + # a missing or failed PV would cause a portion of the + # logical volume to be inaccessible. (E.g. a stripe + # volume that has lost one of its members would be + # unable to access a portion of the logical volume.) + # This setting is not recommended for normal use. + # + # This setting was introduced in LVM version 2.02.108. It corresponds + # with the '--activationmode' option for lvchange and vgchange. + activation_mode = "degraded" } # Report settings.
lib/activate/activate.c +117 -3
132 lines not on this page · raw message
lib/activate/dev_manager.c +6 -3
@@ -2067,9 +2067,12 @@ int add_areas_line(struct dev_manager *d stat(name, &info) < 0 || !S_ISBLK(info.st_mode))) || (seg_type(seg, s) == AREA_LV && !seg_lv(seg, s))) {if (!seg->lv->vg->cmd->partial_activation) { -log_error ("Aborting. LV %s is now incomplete " -"and --partial was not specified." , seg->lv->name); -return 0 ; +if (!seg->lv->vg->cmd->degraded_activation || + !lv_is_raid_type (seg->lv)) { +log_error ("Aborting. LV %s is now incomplete " +"and '--activationmode partial' was not specified." , seg->lv->name); +return 0 ; + } }if (!_add_error_area (dm, node, seg, s)) return_0;
lib/commands/toolcontext.h +1 -0
@@ -86,6 +86,7 @@ struct cmd_context { unsigned handles_unknown_segments:1; unsigned use_linear_target:1; unsigned partial_activation:1; + unsigned degraded_activation:1; unsigned auto_set_activation_skip:1; unsigned si_unit_consistency:1; unsigned report_binary_values_as_numeric:1;
lib/config/config_settings.h +1 -0
@@ -212,6 +212,7 @@ cfg(activation_use_mlockall_CFG, "use_ml cfg(activation_monitoring_CFG, "monitoring", activation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_DMEVENTD_MONITOR, vsn(2, 2, 63), NULL) cfg(activation_polling_interval_CFG, "polling_interval", activation_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_INTERVAL, vsn(2, 2, 63), NULL) cfg(activation_auto_set_activation_skip_CFG, "auto_set_activation_skip", activation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_AUTO_SET_ACTIVATION_SKIP, vsn(2,2,99), NULL) +cfg(activation_mode_CFG, "activation_mode", activation_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_ACTIVATION_MODE, vsn(2,2,108), NULL) cfg(metadata_pvmetadatacopies_CFG, "pvmetadatacopies", metadata_CFG_SECTION, CFG_ADVANCED, CFG_TYPE_INT, DEFAULT_PVMETADATACOPIES, vsn(1, 0, 0), NULL)cfg (metadata_vgmetadatacopies_CFG,"vgmetadatacopies" , metadata_CFG_SECTION,CFG_ADVANCED ,CFG_TYPE_INT ,DEFAULT_VGMETADATACOPIES ,vsn (2 ,2 ,69 ),NULL )
lib/config/defaults.h +1 -0
@@ -163,6 +163,7 @@#define DEFAULT_PROCESS_PRIORITY -18#define DEFAULT_AUTO_SET_ACTIVATION_SKIP 1 +#define DEFAULT_ACTIVATION_MODE "degraded"#define DEFAULT_USE_LINEAR_TARGET 1#define DEFAULT_STRIPE_FILLER "error"#define DEFAULT_RAID_REGION_SIZE 512/* KB */
man/lvchange.8.in +19 -0
@@ -9,6 +9,8 @@ lvchange \(em change attributes of a log .RI { y | n }] .RB [ \-a | \-\-activate .RI [ a | e | l ]{ y | n }] +.RB [ \-\-activationmode +.IR { complete | degraded | partial } ] .RB [ \-k | \-\-setactivationskip { y | n } ] .RB [ \-K | \-\-ignoreactivationskip ] .RB [ \-\-alloc
@@ -18,6 +20,7 @@ lvchange \(em change attributes of a log .RB [ \-C | \-\-contiguous .RI { y | n }] .RB [ \-d | \-\-debug ] +.RB [ \-\-degraded ] .RB [ \-\-deltag .IR Tag ] .RB [ \-\-detachprofile ]
@@ -97,6 +100,22 @@ To deactivate only on the local node use Logical volumes with single-host snapshots are always activated exclusively because they can only be used on one node at once. .TP +.BR \-\-activationmode " {" \fIcomplete | \fIdegraded | \fIpartial } +The activation mode determines whether logical volumes are allowed to +activate when there are physical volumes missing (e.g. due to a device +failure). \fIcomplete is the most restrictive; allowing only those +logical volumes to be activated that are not affected by the missing +PVs. \fIdegraded allows RAID logical volumes to be activated even if +they have PVs missing. (Note that the "mirror" segment type is not +considered a RAID logical volume. The "raid1" segment type should +be used instead.) Finally, \fIpartial allows any logical volume to +be activated even if portions are missing due to a missing or failed +PV. This last option should only be used when performing recovery or +repair operations. \fIdegraded is the default mode. To change it, modify +.B activation_mode +in +.BR lvm.conf (5). +.TP .BR \-k ", " \-\-setactivationskip " {" \fIy | \fIn } Controls whether Logical Volumes are persistently flagged to be skipped during activation. By default, thin snapshot volumes are
man/vgchange.8.in +18 -0
@@ -12,6 +12,8 @@ vgchange \(em change attributes of a vol .RB [ \-a | \-\-activate .RI [ a | e | l ] .RI { y | n }] +.RB [ \-\-activationmode +.IR { complete | degraded | partial } ] .RB [ \-K | \-\-ignoreactivationskip ] .RB [ \-\-monitor .RI { y | n }]
@@ -98,6 +100,22 @@ on the local node. Logical volumes with single-host snapshots are always activated exclusively because they can only be used on one node at once. .TP +.BR \-\-activationmode " {" \fIcomplete | \fIdegraded | \fIpartial } +The activation mode determines whether logical volumes are allowed to +activate when there are physical volumes missing (e.g. due to a device +failure). \fIcomplete is the most restrictive; allowing only those +logical volumes to be activated that are not affected by the missing +PVs. \fIdegraded allows RAID logical volumes to be activated even if +they have PVs missing. (Note that the "mirror" segment type is not +considered a RAID logical volume. The "raid1" segment type should +be used instead.) Finally, \fIpartial allows any logical volume to +be activated even if portions are missing due to a missing or failed +PV. This last option should only be used when performing recovery or +repair operations. \fIdegraded is the default mode. To change it, modify +.B activation_mode +in +.BR lvm.conf (5). +.TP .BR \-K ", " \-\-ignoreactivationskip Ignore the flag to skip Logical Volumes during activation. .TP
tools/args.h +2 -0
@@ -109,6 +109,8 @@ arg(ignoreskippedcluster_ARG, '\0', "ign arg(splitsnapshot_ARG, '\0', "splitsnapshot", NULL, 0) arg(readonly_ARG, '\0', "readonly", NULL, 0) arg(atomic_ARG, '\0', "atomic", NULL, 0) +arg (activationmode_ARG,'\0' ,"activationmode" , string_arg,0 ) + /* Allow some variations */arg (resizable_ARG,'\0' ,"resizable" , yes_no_arg,0 )
tools/commands.h +6 -2
@@ -103,6 +103,7 @@ xx(lvchange,"lvchange\n" "\t[-A|--autobackup y|n]\n" "\t[-a|--activate [a|e|l]{y|n}]\n" +"\t[--activationmode {complete|degraded|partial}" "\t[--addtag Tag]\n" "\t[--alloc AllocationPolicy]\n" "\t[-C|--contiguous y|n]\n"
@@ -141,7 +142,8 @@ xx(lvchange,"\t[-Z|--zero {y|n}]\n" "\tLogicalVolume[Path] [LogicalVolume[Path]...]\n" , - addtag_ARG, alloc_ARG, autobackup_ARG, activate_ARG, available_ARG, + activationmode_ARG, addtag_ARG, alloc_ARG, autobackup_ARG, activate_ARG, + available_ARG, contiguous_ARG, deltag_ARG, discards_ARG, detachprofile_ARG, force_ARG, ignorelockingfailure_ARG, ignoremonitoring_ARG, ignoreactivationskip_ARG, ignoreskippedcluster_ARG, major_ARG, metadataprofile_ARG, minor_ARG,
@@ -933,6 +935,7 @@ xx(vgchange,"\t[-v|--verbose] " "\n" "\t[--version]" "\n" "\t{-a|--activate [a|e|l]{y|n} |" "\n" +"\t[--activationmode {complete|degraded|partial}]" "\n" "\t -c|--clustered {y|n} |" "\n" "\t -x|--resizeable {y|n} |" "\n" "\t -l|--logicalvolume MaxLogicalVolumes |" "\n"
@@ -942,7 +945,8 @@ xx(vgchange,"\t --deltag Tag}\n" "\t[VolumeGroupName...]\n" , - addtag_ARG, alloc_ARG, allocation_ARG, autobackup_ARG, activate_ARG, + activationmode_ARG, addtag_ARG, alloc_ARG, allocation_ARG, autobackup_ARG, + activate_ARG, available_ARG, clustered_ARG, deltag_ARG, detachprofile_ARG, ignoreactivationskip_ARG, ignorelockingfailure_ARG, ignoremonitoring_ARG, ignoreskippedcluster_ARG, logicalvolume_ARG, maxphysicalvolumes_ARG,
tools/lvmcmdline.c +27 -1
@@ -866,6 +866,8 @@ int version(struct cmd_context *cmd __atstatic int _get_settings (struct cmd_context *cmd) { +const char *activation_mode; + cmd->current_settings = cmd->default_settings;if (arg_count (cmd, debug_ARG))
@@ -903,10 +905,34 @@ static int _get_settings(struct cmd_cont } cmd->partial_activation =0 ; + cmd->degraded_activation =0 ; + activation_mode =find_config_tree_str (cmd, activation_mode_CFG,NULL ); +if (!activation_mode) + activation_mode =DEFAULT_ACTIVATION_MODE ; + +if (arg_count (cmd, activationmode_ARG)) { + activation_mode =arg_str_value (cmd, activationmode_ARG, + activation_mode); + +/* complain only if the two arguments conflict */ +if (arg_count (cmd, partial_ARG) && +strcmp (activation_mode,"partial" )) { +log_error ("--partial and --activationmode are mutually" +" exclusive arguments" ); +return EINVALID_CMD_LINE ; + } + }else if (arg_count (cmd, partial_ARG)) + activation_mode ="partial" ; -if (arg_count (cmd, partial_ARG)) { +if (!strcmp (activation_mode,"partial" )) { cmd->partial_activation =1 ;log_warn ("PARTIAL MODE. Incomplete logical volumes will be processed." ); + }else if (!strcmp (activation_mode,"degraded" )) { + cmd->degraded_activation =1 ; +log_debug ("DEGRADED MODE. Incomplete RAID LVs will be processed." ); + }else if (strcmp (activation_mode,"complete" )) { +log_error ("Invalid activation mode given." ); +return EINVALID_CMD_LINE ; }if (arg_count (cmd, ignorelockingfailure_ARG) ||arg_count (cmd, sysinit_ARG))
tools/toollib.c +2 -1
@@ -1431,7 +1431,8 @@ int lv_change_activate(struct cmd_contexint lv_refresh (struct cmd_context *cmd,struct logical_volume *lv) {if (!cmd->partial_activation && (lv->status &PARTIAL_LV )) { -log_error ("Refusing refresh of partial LV %s. Use --partial to override." , +log_error ("Refusing refresh of partial LV %s." +" Use '--activationmode partial' to override." , lv->name);return 0 ; }
test/shell/lvchange-activationmode.sh new file +139 -0
139 lines not on this page · raw message
test/shell/vgchange-activationmode.sh new file +247 -0
247 lines not on this page · raw message