summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlasdair G Kergon <agk@redhat.com>2014-04-18 02:46:34 +0100
committerAlasdair G Kergon <agk@redhat.com>2014-04-18 02:46:34 +0100
commitb5f8f452ac563ef07513e770b3202c6dc209443c (patch)
treec75307dffc7318a7855730afa0589fe851cb688f
parent17e304e0ac24ba0d1887badfb51afa731aa138e9 (diff)
downloadlvm2-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_NEW2
-rw-r--r--conf/example.conf.in9
-rw-r--r--lib/activate/activate.c7
-rw-r--r--lib/activate/activate.h2
-rw-r--r--lib/commands/toolcontext.c2
-rw-r--r--lib/locking/locking.c5
-rw-r--r--lib/locking/locking_types.h7
-rw-r--r--lib/locking/no_locking.c14
-rw-r--r--man/lvm.8.in11
-rw-r--r--tools/args.h1
-rw-r--r--tools/commands.h37
-rw-r--r--tools/lvmcmdline.c20
12 files changed, 96 insertions, 21 deletions
diff --git a/WHATS_NEW b/WHATS_NEW
index ac186016b..dfa50e841 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -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;