diff options
author | Alasdair G Kergon <agk@redhat.com> | 2014-04-18 02:46:34 +0100 |
---|---|---|
committer | Alasdair G Kergon <agk@redhat.com> | 2014-04-18 02:46:34 +0100 |
commit | b5f8f452ac563ef07513e770b3202c6dc209443c (patch) | |
tree | c75307dffc7318a7855730afa0589fe851cb688f | |
parent | 17e304e0ac24ba0d1887badfb51afa731aa138e9 (diff) | |
download | lvm2-b5f8f452ac563ef07513e770b3202c6dc209443c.tar.gz |
tools: Add --readonly support.
Offer lock-free access to display virtual machine or clustered VG metadata
while it might be in use.
-rw-r--r-- | WHATS_NEW | 2 | ||||
-rw-r--r-- | conf/example.conf.in | 9 | ||||
-rw-r--r-- | lib/activate/activate.c | 7 | ||||
-rw-r--r-- | lib/activate/activate.h | 2 | ||||
-rw-r--r-- | lib/commands/toolcontext.c | 2 | ||||
-rw-r--r-- | lib/locking/locking.c | 5 | ||||
-rw-r--r-- | lib/locking/locking_types.h | 7 | ||||
-rw-r--r-- | lib/locking/no_locking.c | 14 | ||||
-rw-r--r-- | man/lvm.8.in | 11 | ||||
-rw-r--r-- | tools/args.h | 1 | ||||
-rw-r--r-- | tools/commands.h | 37 | ||||
-rw-r--r-- | tools/lvmcmdline.c | 20 |
12 files changed, 96 insertions, 21 deletions
@@ -1,5 +1,7 @@ Version 2.02.107 - ================================== + Add --readonly to reporting and display tools for lock-free metadata access. + Add locking_type 5 for dummy locking for tools that do not need any locks. Fix _recover_vg() error path when lock conversion fails. Use X for LV attributes that are unknown when activation disabled. Only output lvdisplay 'LV Status' field when activation is enabled. diff --git a/conf/example.conf.in b/conf/example.conf.in index 2ed3fd65a..d5ddb1c5b 100644 --- a/conf/example.conf.in +++ b/conf/example.conf.in @@ -520,6 +520,15 @@ global { # Type 3 uses built-in clustered locking. # Type 4 uses read-only locking which forbids any operations that might # change metadata. + # Type 5 offers dummy locking for tools that do not need any locks. + # You should not need to set this directly: the tools will select when + # to use it instead of the configured locking_type. Do not use lvmetad or + # the kernel device-mapper driver with this locking type. + # It is used by the --readonly option that offers read-only access to + # Volume Group metadata that cannot be locked safely because it belongs to + # an inaccessible domain and might be in use, for example a virtual machine + # image or a disk that is shared by a clustered machine. + # # N.B. Don't use lvmetad with locking type 3 as lvmetad is not yet # supported in clustered environment. If use_lvmetad=1 and locking_type=3 # is set at the same time, LVM always issues a warning message about this diff --git a/lib/activate/activate.c b/lib/activate/activate.c index 4d3f8fe91..a7ec751b2 100644 --- a/lib/activate/activate.c +++ b/lib/activate/activate.c @@ -431,7 +431,7 @@ int lv_has_target_type(struct dm_pool *mem, struct logical_volume *lv, static int _activation = 1; -void set_activation(int act) +void set_activation(int act, int silent) { if (act == _activation) return; @@ -440,9 +440,12 @@ void set_activation(int act) if (_activation) log_verbose("Activation enabled. Device-mapper kernel " "driver will be used."); - else + else if (!silent) log_warn("WARNING: Activation disabled. No device-mapper " "interaction will be attempted."); + else + log_verbose("Activation disabled. No device-mapper " + "interaction will be attempted."); } int activation(void) diff --git a/lib/activate/activate.h b/lib/activate/activate.h index 435cac56a..946494ebf 100644 --- a/lib/activate/activate.h +++ b/lib/activate/activate.h @@ -52,7 +52,7 @@ struct lv_activate_opts { * that follows. */ }; -void set_activation(int activation); +void set_activation(int activation, int silent); int activation(void); int driver_version(char *version, size_t size); diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c index c76f281b2..d62fb8a17 100644 --- a/lib/commands/toolcontext.c +++ b/lib/commands/toolcontext.c @@ -348,7 +348,7 @@ static int _process_config(struct cmd_context *cmd) /* activation? */ cmd->default_settings.activation = find_config_tree_bool(cmd, global_activation_CFG, NULL); - set_activation(cmd->default_settings.activation); + set_activation(cmd->default_settings.activation, 0); cmd->auto_set_activation_skip = find_config_tree_bool(cmd, activation_auto_set_activation_skip_CFG, NULL); diff --git a/lib/locking/locking.c b/lib/locking/locking.c index 9433e4027..b5250c10b 100644 --- a/lib/locking/locking.c +++ b/lib/locking/locking.c @@ -284,6 +284,11 @@ int init_locking(int type, struct cmd_context *cmd, int suppress_messages) break; return 1; + case 5: + init_dummy_locking(&_locking, cmd, suppress_messages); + log_verbose("Locking disabled for read-only access."); + return 1; + default: log_error("Unknown locking type requested."); return 0; diff --git a/lib/locking/locking_types.h b/lib/locking/locking_types.h index 300949096..6e4adcc3b 100644 --- a/lib/locking/locking_types.h +++ b/lib/locking/locking_types.h @@ -38,8 +38,11 @@ struct locking_type { /* * Locking types */ -int init_no_locking(struct locking_type *locking, struct cmd_context *cmd, - int suppress_messages); +void init_no_locking(struct locking_type *locking, struct cmd_context *cmd, + int suppress_messages); + +void init_dummy_locking(struct locking_type *locking, struct cmd_context *cmd, + int suppress_messages); int init_readonly_locking(struct locking_type *locking, struct cmd_context *cmd, int suppress_messages); diff --git a/lib/locking/no_locking.c b/lib/locking/no_locking.c index dac2f8085..f7718be5c 100644 --- a/lib/locking/no_locking.c +++ b/lib/locking/no_locking.c @@ -91,7 +91,7 @@ static int _readonly_lock_resource(struct cmd_context *cmd, return _no_lock_resource(cmd, resource, flags, lv); } -int init_no_locking(struct locking_type *locking, struct cmd_context *cmd __attribute__((unused)), +void init_no_locking(struct locking_type *locking, struct cmd_context *cmd __attribute__((unused)), int suppress_messages) { locking->lock_resource = _no_lock_resource; @@ -99,8 +99,6 @@ int init_no_locking(struct locking_type *locking, struct cmd_context *cmd __attr locking->reset_locking = _no_reset_locking; locking->fin_locking = _no_fin_locking; locking->flags = LCK_CLUSTERED; - - return 1; } int init_readonly_locking(struct locking_type *locking, struct cmd_context *cmd __attribute__((unused)), @@ -114,3 +112,13 @@ int init_readonly_locking(struct locking_type *locking, struct cmd_context *cmd return 1; } + +void init_dummy_locking(struct locking_type *locking, struct cmd_context *cmd __attribute__((unused)), + int suppress_messages) +{ + locking->lock_resource = _readonly_lock_resource; + locking->query_resource = _no_query_resource; + locking->reset_locking = _no_reset_locking; + locking->fin_locking = _no_fin_locking; + locking->flags = LCK_CLUSTERED; +} diff --git a/man/lvm.8.in b/man/lvm.8.in index f6335ed25..e273935e7 100644 --- a/man/lvm.8.in +++ b/man/lvm.8.in @@ -223,6 +223,17 @@ Use to avoid exiting with an non-zero status code if the command is run without clustered locking and some clustered Volume Groups have to be skipped over. .TP +.B \-\-readonly +Run the command in a special read-only mode which will read on-disk +metadata without needing to take any locks. This can be used to peek +inside metadata used by a virtual machine image while the virtual +machine is running. +It can also be used to peek inside the metadata of clustered Volume +Groups when clustered locking is not configured or running. No attempt +will be made to communicate with the device-mapper kernel driver, so +this option is unable to report whether or not Logical Volumes are +actually in use. +.TP .B \-\-addtag \fITag Add the tag \fITag\fP to a PV, VG or LV. Supply this argument multiple times to add more than one tag at once. diff --git a/tools/args.h b/tools/args.h index f1a4ef48b..2e63adbf6 100644 --- a/tools/args.h +++ b/tools/args.h @@ -104,6 +104,7 @@ arg(detachprofile_ARG, '\0', "detachprofile", NULL, 0) arg(mergedconfig_ARG, '\0', "mergedconfig", NULL, 0) arg(ignoreskippedcluster_ARG, '\0', "ignoreskippedcluster", NULL, 0) arg(splitsnapshot_ARG, '\0', "splitsnapshot", NULL, 0) +arg(readonly_ARG, '\0', "readonly", NULL, 0) /* Allow some variations */ arg(resizable_ARG, '\0', "resizable", yes_no_arg, 0) diff --git a/tools/commands.h b/tools/commands.h index b0bad9d50..21a2075a8 100644 --- a/tools/commands.h +++ b/tools/commands.h @@ -335,6 +335,7 @@ xx(lvdisplay, "\t[-m|--maps]\n" "\t[--nosuffix]\n" "\t[-P|--partial] " "\n" + "\t[--readonly]\n" "\t[--units hHbBsSkKmMgGtTpPeE]\n" "\t[-v|--verbose]\n" "\t[--version]" "\n" @@ -352,6 +353,7 @@ xx(lvdisplay, "\t[-o|--options [+]Field[,Field]]\n" "\t[-O|--sort [+|-]key1[,[+|-]key2[,...]]]\n" "\t[-P|--partial] " "\n" + "\t[--readonly]\n" "\t[--segments]\n" "\t[--separator Separator]\n" "\t[--unbuffered]\n" @@ -362,8 +364,8 @@ xx(lvdisplay, aligned_ARG, all_ARG, colon_ARG, columns_ARG, ignorelockingfailure_ARG, ignoreskippedcluster_ARG, maps_ARG, noheadings_ARG, nosuffix_ARG, - options_ARG, sort_ARG, partial_ARG, segments_ARG, separator_ARG, - unbuffered_ARG, units_ARG) + options_ARG, sort_ARG, partial_ARG, readonly_ARG, segments_ARG, + separator_ARG, unbuffered_ARG, units_ARG) xx(lvextend, "Add space to a logical volume", @@ -414,9 +416,10 @@ xx(lvmdiskscan, "\t[-d|--debug]\n" "\t[-h|--help]\n" "\t[-l|--lvmpartition]\n" + "\t[--readonly]\n" "\t[--version]" "\n", - lvmpartition_ARG) + lvmpartition_ARG, readonly_ARG) xx(lvmsadc, "Collect activity data", @@ -539,6 +542,7 @@ xx(lvs, "\t[-o|--options [+]Field[,Field]]\n" "\t[-O|--sort [+|-]key1[,[+|-]key2[,...]]]\n" "\t[-P|--partial] " "\n" + "\t[--readonly]\n" "\t[--rows]\n" "\t[--segments]\n" "\t[--separator Separator]\n" @@ -553,6 +557,7 @@ xx(lvs, aligned_ARG, all_ARG, ignorelockingfailure_ARG, ignoreskippedcluster_ARG, nameprefixes_ARG, noheadings_ARG, nolocking_ARG, nosuffix_ARG, options_ARG, partial_ARG, + readonly_ARG, rows_ARG, segments_ARG, separator_ARG, sort_ARG, trustcache_ARG, unbuffered_ARG, units_ARG, unquoted_ARG) @@ -566,10 +571,12 @@ xx(lvscan, "\t[-h|-?|--help] " "\n" "\t[--ignorelockingfailure]\n" "\t[-P|--partial] " "\n" + "\t[--readonly]\n" "\t[-v|--verbose] " "\n" "\t[--version]\n", - all_ARG, blockdevice_ARG, ignorelockingfailure_ARG, partial_ARG) + all_ARG, blockdevice_ARG, ignorelockingfailure_ARG, partial_ARG, + readonly_ARG) xx(pvchange, "Change attributes of physical volume(s)", @@ -681,6 +688,7 @@ xx(pvdisplay, "\t[--ignoreskippedcluster]\n" "\t[-m|--maps]\n" "\t[--nosuffix]\n" + "\t[--readonly]\n" "\t[-s|--short]\n" "\t[--units hHbBsSkKmMgGtTpPeE]\n" "\t[-v|--verbose]\n" @@ -698,6 +706,7 @@ xx(pvdisplay, "\t[--nosuffix]\n" "\t[-o|--options [+]Field[,Field]]\n" "\t[-O|--sort [+|-]key1[,[+|-]key2[,...]]]\n" + "\t[--readonly]\n" "\t[--separator Separator]\n" "\t[--unbuffered]\n" "\t[--units hHbBsSkKmMgGtTpPeE]\n" @@ -707,7 +716,8 @@ xx(pvdisplay, aligned_ARG, all_ARG, colon_ARG, columns_ARG, ignorelockingfailure_ARG, ignoreskippedcluster_ARG, maps_ARG, noheadings_ARG, nosuffix_ARG, - options_ARG, separator_ARG, short_ARG, sort_ARG, unbuffered_ARG, units_ARG) + options_ARG, readonly_ARG, separator_ARG, short_ARG, sort_ARG, + unbuffered_ARG, units_ARG) xx(pvmove, "Move extents from one physical volume to another", @@ -763,6 +773,7 @@ xx(pvs, "\t[-o|--options [+]Field[,Field]]\n" "\t[-O|--sort [+|-]key1[,[+|-]key2[,...]]]\n" "\t[-P|--partial] " "\n" + "\t[--readonly]\n" "\t[--rows]\n" "\t[--segments]\n" "\t[--separator Separator]\n" @@ -776,7 +787,7 @@ xx(pvs, aligned_ARG, all_ARG, ignorelockingfailure_ARG, ignoreskippedcluster_ARG, nameprefixes_ARG, noheadings_ARG, nolocking_ARG, nosuffix_ARG, options_ARG, - partial_ARG, rows_ARG, segments_ARG, separator_ARG, sort_ARG, + partial_ARG, readonly_ARG, rows_ARG, segments_ARG, separator_ARG, sort_ARG, trustcache_ARG, unbuffered_ARG, units_ARG, unquoted_ARG) xx(pvscan, @@ -790,6 +801,7 @@ xx(pvscan, "\t[-h|-?|--help]" "\n" "\t[--ignorelockingfailure]\n" "\t[-P|--partial] " "\n" + "\t[--readonly]\n" "\t[-s|--short] " "\n" "\t[-u|--uuid] " "\n" "\t[-v|--verbose] " "\n" @@ -797,7 +809,7 @@ xx(pvscan, activate_ARG, available_ARG, backgroundfork_ARG, cache_ARG, exported_ARG, ignorelockingfailure_ARG, major_ARG, minor_ARG, - novolumegroup_ARG, partial_ARG, short_ARG, uuid_ARG) + novolumegroup_ARG, partial_ARG, readonly_ARG, short_ARG, uuid_ARG) xx(segtypes, "List available segment types", @@ -818,11 +830,12 @@ xx(vgcfgbackup, "\t[-h|-?|--help] " "\n" "\t[--ignorelockingfailure]\n" "\t[-P|--partial] " "\n" + "\t[--readonly]\n" "\t[-v|--verbose]" "\n" "\t[--version] " "\n" "\t[VolumeGroupName...]\n", - file_ARG, ignorelockingfailure_ARG, partial_ARG) + file_ARG, ignorelockingfailure_ARG, partial_ARG, readonly_ARG) xx(vgcfgrestore, "Restore volume group configuration", @@ -955,6 +968,7 @@ xx(vgdisplay, "\t[--ignoreskippedcluster]\n" "\t[--nosuffix]\n" "\t[-P|--partial] " "\n" + "\t[--readonly]\n" "\t[--units hHbBsSkKmMgGtTpPeE]\n" "\t[--version]" "\n" "\t[VolumeGroupName [VolumeGroupName...]]\n" @@ -970,6 +984,7 @@ xx(vgdisplay, "\t[-o|--options [+]Field[,Field]]\n" "\t[-O|--sort [+|-]key1[,[+|-]key2[,...]]]\n" "\t[-P|--partial] " "\n" + "\t[--readonly]\n" "\t[--separator Separator]\n" "\t[--unbuffered]\n" "\t[--units hHbBsSkKmMgGtTpPeE]\n" @@ -979,8 +994,8 @@ xx(vgdisplay, activevolumegroups_ARG, aligned_ARG, colon_ARG, columns_ARG, ignorelockingfailure_ARG, ignoreskippedcluster_ARG, noheadings_ARG, - nosuffix_ARG, options_ARG, partial_ARG, short_ARG, separator_ARG, - sort_ARG, unbuffered_ARG, units_ARG) + nosuffix_ARG, options_ARG, partial_ARG, readonly_ARG, short_ARG, + separator_ARG, sort_ARG, unbuffered_ARG, units_ARG) xx(vgexport, "Unregister volume group(s) from the system", @@ -1127,6 +1142,7 @@ xx(vgs, "\t[-o|--options [+]Field[,Field]]\n" "\t[-O|--sort [+|-]key1[,[+|-]key2[,...]]]\n" "\t[-P|--partial] " "\n" + "\t[--readonly]\n" "\t[--rows]\n" "\t[--separator Separator]\n" "\t[--trustcache]\n" @@ -1140,6 +1156,7 @@ xx(vgs, aligned_ARG, all_ARG, ignorelockingfailure_ARG, ignoreskippedcluster_ARG, nameprefixes_ARG, noheadings_ARG, nolocking_ARG, nosuffix_ARG, options_ARG, partial_ARG, + readonly_ARG, rows_ARG, separator_ARG, sort_ARG, trustcache_ARG, unbuffered_ARG, units_ARG, unquoted_ARG) diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c index b7d69efce..758c429d1 100644 --- a/tools/lvmcmdline.c +++ b/tools/lvmcmdline.c @@ -894,6 +894,13 @@ static int _get_settings(struct cmd_context *cmd) cmd->current_settings.archive = arg_int_value(cmd, autobackup_ARG, cmd->current_settings.archive); cmd->current_settings.backup = arg_int_value(cmd, autobackup_ARG, cmd->current_settings.backup); cmd->current_settings.cache_vgmetadata = cmd->command->flags & CACHE_VGMETADATA ? 1 : 0; + + if (arg_count(cmd, readonly_ARG)) { + cmd->current_settings.activation = 0; + cmd->current_settings.archive = 0; + cmd->current_settings.backup = 0; + } + cmd->partial_activation = 0; if (arg_count(cmd, partial_ARG)) { @@ -1022,7 +1029,7 @@ static void _apply_settings(struct cmd_context *cmd) archive_enable(cmd, cmd->current_settings.archive); backup_enable(cmd, cmd->current_settings.backup); - set_activation(cmd->current_settings.activation); + set_activation(cmd->current_settings.activation, cmd->metadata_read_only); cmd->fmt = get_format_by_name(cmd, arg_str_value(cmd, metadatatype_ARG, cmd->current_settings.fmt_name)); @@ -1141,6 +1148,9 @@ int lvm_run_command(struct cmd_context *cmd, int argc, char **argv) return_ECMD_FAILED; } + if (arg_count(cmd, readonly_ARG)) + cmd->metadata_read_only = 1; + if ((ret = _get_settings(cmd))) goto_out; _apply_settings(cmd); @@ -1168,7 +1178,13 @@ int lvm_run_command(struct cmd_context *cmd, int argc, char **argv) goto out; } - if (arg_count(cmd, nolocking_ARG)) + if (arg_count(cmd, readonly_ARG)) { + locking_type = 5; + if (lvmetad_used()) { + lvmetad_set_active(0); + log_verbose("Disabling use of lvmetad because read-only is set."); + } + } else if (arg_count(cmd, nolocking_ARG)) locking_type = 0; else locking_type = -1; |