master - man lvmlockd: update
by David Teigland
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=2bbf2fa8ebc3d7...
Commit: 2bbf2fa8ebc3d723bc686689378db2a1fe8eaf6e
Parent: 1c013e7ae29a9e3aa20930a24f3fcf0637ef1e91
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Fri Aug 7 15:18:44 2015 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Fri Aug 7 15:18:44 2015 -0500
man lvmlockd: update
---
man/lvmlockd.8.in | 549 ++++++++++++++++++++++++++---------------------------
1 files changed, 269 insertions(+), 280 deletions(-)
diff --git a/man/lvmlockd.8.in b/man/lvmlockd.8.in
index 9318350..1daea18 100644
--- a/man/lvmlockd.8.in
+++ b/man/lvmlockd.8.in
@@ -8,75 +8,75 @@ LVM commands use lvmlockd to coordinate access to shared storage.
.br
When LVM is used on devices shared by multiple hosts, locks will:
-.IP \[bu] 2
+\[bu]
coordinate reading and writing of LVM metadata
-.IP \[bu] 2
+.br
+\[bu]
validate caching of LVM metadata
-.IP \[bu] 2
+.br
+\[bu]
prevent concurrent activation of logical volumes
-
-.P
+.br
lvmlockd uses an external lock manager to perform basic locking.
.br
Lock manager (lock type) options are:
-.IP \[bu] 2
+\[bu]
sanlock: places locks on disk within LVM storage.
-.IP \[bu] 2
+.br
+\[bu]
dlm: uses network communication and a cluster manager.
-
-.P
+.br
.SH OPTIONS
lvmlockd [options]
-For default settings, see lvmlockd -h.
+For default settings, see lvmlockd \-h.
-.B --help | -h
+.B \-\-help | \-h
Show this help information.
-.B --version | -V
+.B \-\-version | \-V
Show version of lvmlockd.
-.B --test | -T
+.B \-\-test | \-T
Test mode, do not call lock manager.
-.B --foreground | -f
+.B \-\-foreground | \-f
Don't fork.
-.B --daemon-debug | -D
+.B \-\-daemon\-debug | \-D
Don't fork and print debugging to stdout.
-.B --pid-file | -p
+.B \-\-pid\-file | \-p
.I path
Set path to the pid file.
-.B --socket-path | -s
+.B \-\-socket\-path | \-s
.I path
Set path to the socket to listen on.
-.B --syslog-priority | -S err|warning|debug
+.B \-\-syslog\-priority | \-S err|warning|debug
Write log messages from this level up to syslog.
-.B --gl-type | -g
-.I str
- Set global lock type to be sanlock|dlm.
+.B \-\-gl\-type | \-g sanlock|dlm
+ Set global lock type to be sanlock or dlm.
-.B --host-id | -i
+.B \-\-host\-id | \-i
.I num
Set the local sanlock host id.
-.B --host-id-file | -F
+.B \-\-host\-id\-file | \-F
.I path
A file containing the local sanlock host_id.
-.B --sanlock-timeout | -o
+.B \-\-sanlock\-timeout | \-o
.I seconds
Override the default sanlock I/O timeout.
-.B --adopt | A 0|1
+.B \-\-adopt | \-A 0|1
Adopt locks from a previous instance of lvmlockd.
@@ -84,7 +84,7 @@ For default settings, see lvmlockd -h.
.SS Initial set up
-Using LVM with lvmlockd for the first time includes some one-time set up
+Using LVM with lvmlockd for the first time includes some one\-time set up
steps:
.SS 1. choose a lock manager
@@ -112,9 +112,9 @@ use_lvmetad = 1
.I sanlock
.br
-Assign each host a unique host_id in the range 1-2000 by setting
+Assign each host a unique host_id in the range 1\-2000 by setting
.br
-/etc/lvm/lvmlocal.conf local/host_id = <num>
+/etc/lvm/lvmlocal.conf local/host_id
.SS 3. start lvmlockd
@@ -132,32 +132,32 @@ Follow external clustering documentation when applicable, otherwise:
.br
systemctl start corosync dlm
-.SS 5. create VGs on shared devices
+.SS 5. create VG on shared devices
-vgcreate --shared <vg_name> <devices>
+vgcreate \-\-shared <vgname> <devices>
-The vgcreate --shared option sets the VG lock type to sanlock or dlm
-depending on which lock manager is running. LVM commands will perform
-locking for the VG using lvmlockd.
+The shared option sets the VG lock type to sanlock or dlm depending on
+which lock manager is running. LVM commands will perform locking for the
+VG using lvmlockd.
-.SS 6. start VGs on all hosts
+.SS 6. start VG on all hosts
-vgchange --lock-start
+vgchange \-\-lock\-start
-lvmlockd requires shared VGs to be "started" before they are used. This
-is a lock manager operation to start/join the VG lockspace, and it may
-take some time. Until the start completes, locks for the VG are not
-available. LVM commands are allowed to read the VG while start is in
-progress. (A service/init file can be used to start VGs.)
+lvmlockd requires shared VGs to be started before they are used. This is
+a lock manager operation to start (join) the VG lockspace, and it may take
+some time. Until the start completes, locks for the VG are not available.
+LVM commands are allowed to read the VG while start is in progress. (An
+init/unit file can also be used to start VGs.)
.SS 7. create and activate LVs
Standard lvcreate and lvchange commands are used to create and activate
-LVs in a lockd VG.
+LVs in a shared VG.
An LV activated exclusively on one host cannot be activated on another.
When multiple hosts need to use the same LV concurrently, the LV can be
-activated with a shared lock (see lvchange options -aey vs -asy.)
+activated with a shared lock (see lvchange options \-aey vs \-asy.)
(Shared locks are disallowed for certain LV types that cannot be used from
multiple hosts.)
@@ -165,43 +165,51 @@ multiple hosts.)
.SS Normal start up and shut down
After initial set up, start up and shut down include the following general
-steps. They can be performed manually or using the system init/service
+steps. They can be performed manually or using the system service
manager.
-.IP \[bu] 2
+\[bu]
start lvmetad
-.IP \[bu] 2
+.br
+\[bu]
start lvmlockd
-.IP \[bu] 2
+.br
+\[bu]
start lock manager
-.IP \[bu] 2
-vgchange --lock-start
-.IP \[bu] 2
+.br
+\[bu]
+vgchange \-\-lock\-start
+.br
+\[bu]
activate LVs in shared VGs
-
-.P
+.br
The shut down sequence is the reverse:
-.IP \[bu] 2
+\[bu]
deactivate LVs in shared VGs
-.IP \[bu] 2
-vgchange --lock-stop
-.IP \[bu] 2
+.br
+\[bu]
+vgchange \-\-lock\-stop
+.br
+\[bu]
stop lock manager
-.IP \[bu] 2
+.br
+\[bu]
stop lvmlockd
-.IP \[bu] 2
+.br
+\[bu]
stop lvmetad
+.br
.P
.SH TOPICS
-.SS locking terms
+.SS VG access control
-The following terms are used to distinguish VGs that require locking from
-those that do not.
+The following terms are used to describe different forms of VG access
+control.
.I "lockd VG"
@@ -210,18 +218,19 @@ Using it requires lvmlockd. These VGs exist on shared storage that is
visible to multiple hosts. LVM commands use lvmlockd to perform locking
for these VGs when they are used.
-If the lock manager for a lock type is not available (e.g. not started or
-failed), lvmlockd is not able to acquire locks from it, and LVM commands
-are unable to fully use VGs with the given lock type. Commands generally
-allow reading VGs in this condition, but changes and activation are not
-allowed. Maintaining a properly running lock manager can require
-background not covered here.
+If the lock manager for the lock type is not available (e.g. not started
+or failed), lvmlockd is unable to acquire locks for LVM commands. LVM
+commands that only read the VG will generally be allowed to continue
+without locks in this case (with a warning). Commands to modify or
+activate the VG will fail without the necessary locks. Maintaining a
+properly running lock manager requires knowledge covered in separate
+documentation.
.I "local VG"
A "local VG" is meant to be used by a single host. It has no lock type or
lock type "none". LVM commands and lvmlockd do not perform locking for
-these VGs. A local VG typically exists on local (non-shared) devices and
+these VGs. A local VG typically exists on local (non\-shared) devices and
cannot be used concurrently from different hosts.
If a local VG does exist on shared devices, it should be owned by a single
@@ -240,21 +249,25 @@ clvmd for clustering. See below for converting a clvm VG to a lockd VG.
.SS lockd VGs from hosts not using lvmlockd
-Only hosts that will use lockd VGs should be configured to run lvmlockd.
+Only hosts that use lockd VGs should be configured to run lvmlockd.
However, devices with lockd VGs may be visible from hosts not using
lvmlockd. From a host not using lvmlockd, visible lockd VGs are ignored
in the same way as foreign VGs, i.e. those with a foreign system ID, see
.BR lvmsystemid (7).
-The --shared option displays lockd VGs on a host not using lvmlockd, like
-the --foreign option does for foreign VGs.
+The \-\-shared option for reporting and display commands causes lockd VGs
+to be displayed on a host not using lvmlockd, like the \-\-foreign option
+does for foreign VGs.
-.SS vgcreate differences
+.SS vgcreate comparison
-Forms of the vgcreate command:
+The type of VG access control is specified in the vgcreate command.
+See
+.BR vgcreate (8)
+for all vgcreate options.
-.B vgcreate <vg_name> <devices>
+.B vgcreate <vgname> <devices>
.IP \[bu] 2
Creates a local VG with the local system ID when neither lvmlockd nor clvm are configured.
@@ -265,11 +278,12 @@ Creates a clvm VG when clvm is configured.
.P
-.B vgcreate --shared <vg_name> <devices>
+.B vgcreate \-\-shared <vgname> <devices>
.IP \[bu] 2
-Requires lvmlockd to be configured (use_lvmlockd=1).
+Requires lvmlockd to be configured and running.
.IP \[bu] 2
-Creates a lockd VG with lock type sanlock|dlm depending on which is running.
+Creates a lockd VG with lock type sanlock|dlm depending on which lock
+manager is running.
.IP \[bu] 2
LVM commands request locks from lvmlockd to use the VG.
.IP \[bu] 2
@@ -277,9 +291,9 @@ lvmlockd obtains locks from the selected lock manager.
.P
-.B vgcreate -c|--clustered y <vg_name> <devices>
+.B vgcreate \-c|\-\-clustered y <vgname> <devices>
.IP \[bu] 2
-Requires clvm to be configured (locking_type=3).
+Requires clvm to be configured and running.
.IP \[bu] 2
Creates a clvm VG with the "clustered" flag.
.IP \[bu] 2
@@ -289,62 +303,79 @@ LVM commands request locks from clvmd to use the VG.
.SS using lockd VGs
+There are some special considerations to be aware of when using lockd VGs.
+
When use_lvmlockd is first enabled, and before the first lockd VG is
-created, no global lock will exist, and LVM commands will try and fail to
-acquire it. LVM commands will report a warning until the first lockd VG
-is created which will create the global lock. Before the global lock
-exists, VGs can still be read, but commands that require the global lock
-exclusively will fail.
+created, no global lock will exist. In this initial state, LVM commands
+try and fail to acquire the global lock, producing a warning, and some
+commands are disallowed. Once the first lockd VG is created, the global
+lock will be available, and LVM will be fully operational.
When a new lockd VG is created, its lockspace is automatically started on
-the host that creates the VG. Other hosts will need to run 'vgchange
---lock-start' to start the new VG before they can use it.
+the host that creates it. Other hosts need to run 'vgchange
+\-\-lock\-start' to start the new VG before they can use it.
From the 'vgs' command, lockd VGs are indicated by "s" (for shared) in the
sixth attr field. The specific lock type and lock args for a lockd VG can
-be displayed with 'vgs -o+locktype,lockargs'.
+be displayed with 'vgs \-o+locktype,lockargs'.
+
+lockd VGs need to be "started" and "stopped", unlike other types of VGs.
+See the following section for a full description of starting and stopping.
.SS starting and stopping VGs
-Starting a lockd VG (vgchange --lock-start) causes the lock manager to
-start or join the lockspace for the VG. This makes locks for the VG
-accessible to the host. Stopping the VG leaves the lockspace and makes
-locks for the VG inaccessible to the host.
+Starting a lockd VG (vgchange \-\-lock\-start) causes the lock manager to
+start (join) the lockspace for the VG on the host where it is run. This
+makes locks for the VG available to LVM commands on the host. Before a VG
+is started, only LVM commands that read/display the VG without locks are
+allowed.
-Lockspaces should be started as early as possible because starting
-(joining) a lockspace can take a long time (potentially minutes after a
-host failure when using sanlock.) A VG can be started after all the
-following are true:
+Stopping a lockd VG (vgchange \-\-lock\-stop) causes the lock manager to
+stop (leave) the lockspace for the VG on the host where it is run. This
+makes locks for the VG inaccessible to the host. A VG cannot be stopped
+while it has active LVs.
-.nf
-- lvmlockd is running
-- lock manager is running
-- VG is visible to the system
-.fi
+When using the lock type sanlock, starting a VG can take a long time
+(potentially minutes if the host was previously shut down without cleanly
+stopping the VG.)
+
+A lockd VG can be started after all the following are true:
+.br
+\[bu]
+lvmlockd is running
+.br
+\[bu]
+the lock manager is running
+.br
+\[bu]
+the VG is visible to the system
+.br
+
+A lockd VG can be stopped if all LVs are deactivated.
All lockd VGs can be started/stopped using:
.br
-vgchange --lock-start
+vgchange \-\-lock-start
.br
-vgchange --lock-stop
+vgchange \-\-lock-stop
Individual VGs can be started/stopped using:
.br
-vgchange --lock-start <vg_name> ...
+vgchange \-\-lock\-start <vgname> ...
.br
-vgchange --lock-stop <vg_name> ...
+vgchange \-\-lock\-stop <vgname> ...
To make vgchange not wait for start to complete:
.br
-vgchange --lock-start --lock-opt nowait
+vgchange \-\-lock\-start \-\-lock\-opt nowait
.br
-vgchange --lock-start --lock-opt nowait <vg_name>
+vgchange \-\-lock\-start \-\-lock\-opt nowait <vgname>
To stop all lockspaces and wait for all to complete:
.br
-lvmlockctl --stop-lockspaces --wait
+lvmlockctl \-\-stop\-lockspaces \-\-wait
To start only selected lockd VGs, use the lvm.conf
activation/lock_start_list. When defined, only VG names in this list are
@@ -366,7 +397,7 @@ Scripts or programs on a host that automatically start VGs will use the
"auto" option to indicate that the command is being run automatically by
the system:
-vgchange --lock-start --lock-opt auto [vg_name ...]
+vgchange \-\-lock\-start \-\-lock\-opt auto [<vgname> ...]
Without any additional configuration, including the "auto" option has no
effect; all VGs are started unless restricted by lock_start_list.
@@ -387,21 +418,25 @@ To use auto activation of lockd LVs (see auto_activation_volume_list),
auto starting of the corresponding lockd VGs is necessary.
-.SS locking activity
+.SS internal command locking
-To optimize the use of LVM with lvmlockd, consider the three kinds of
-locks in lvmlockd and when they are used:
+To optimize the use of LVM with lvmlockd, be aware of the three kinds of
+locks and when they are used:
.I GL lock
The global lock (GL lock) is associated with global information, which is
information not isolated to a single VG. This includes:
-- The global VG namespace.
+\[bu]
+The global VG namespace.
+.br
+\[bu]
+The set of orphan PVs and unused devices.
.br
-- The set of orphan PVs and unused devices.
+\[bu]
+The properties of orphan PVs, e.g. PV size.
.br
-- The properties of orphan PVs, e.g. PV size.
The global lock is used in shared mode by commands that read this
information, or in exclusive mode by commands that change it.
@@ -414,12 +449,7 @@ creates a new VG name, and it takes a PV from the list of unused PVs.
When an LVM command is given a tag argument, or uses select, it must read
all VGs to match the tag or selection, which causes the global lock to be
-acquired. To avoid use of the global lock, avoid using tags and select,
-and specify VG name arguments.
-
-When use_lvmlockd is enabled, LVM commands attempt to acquire the global
-lock even if no lockd VGs exist. For this reason, lvmlockd should not be
-enabled unless lockd VGs will be used.
+acquired.
.I VG lock
@@ -432,7 +462,7 @@ The command 'vgs' will not only acquire the GL lock to read the list of
all VG names, but will acquire the VG lock for each VG prior to reading
it.
-The command 'vgs <vg_name>' does not acquire the GL lock (it does not need
+The command 'vgs <vgname>' does not acquire the GL lock (it does not need
the list of all VG names), but will acquire the VG lock on each VG name
argument.
@@ -444,14 +474,14 @@ activated. LV locks are persistent and remain in place after the
activation command is done. GL and VG locks are transient, and are held
only while an LVM command is running.
-.I retries
+.I lock retries
If a request for a GL or VG lock fails due to a lock conflict with another
host, lvmlockd automatically retries for a short time before returning a
-failure to the LVM command. The LVM command will then retry the entire
-lock request a number of times specified by global/lvmlockd_lock_retries
-before failing. If a request for an LV lock fails due to a lock conflict,
-the command fails immediately.
+failure to the LVM command. If those retries are insufficient, the LVM
+command will retry the entire lock request a number of times specified by
+global/lvmlockd_lock_retries before failing. If a request for an LV lock
+fails due to a lock conflict, the command fails immediately.
.SS sanlock global lock
@@ -470,21 +500,22 @@ are moved or removed.
The vgcreate command typically acquires the global lock, but in the case
of the first sanlock VG, there will be no global lock to acquire until the
-initial vgcreate is complete. So, creating the first sanlock VG is a
+first vgcreate is complete. So, creating the first sanlock VG is a
special case that skips the global lock.
vgcreate for a sanlock VG determines it is the first one to exist if no
other sanlock VGs are visible. It is possible that other sanlock VGs do
-exist but are not visible or started on the host running vgcreate. This
-raises the possibility of more than one global lock existing. If this
-happens, commands will warn of the condition, and it should be manually
-corrected.
+exist but are not visible on the host running vgcreate. In this case,
+vgcreate would create a new sanlock VG with the global lock enabled. When
+the other VG containing a global lock appears, lvmlockd will see more than
+one VG with a global lock enabled, and LVM commands will report that there
+are duplicate global locks.
If the situation arises where more than one sanlock VG contains a global
lock, the global lock should be manually disabled in all but one of them
with the command:
-lvmlockctl --gl-disable <vg_name>
+lvmlockctl \-\-gl\-disable <vgname>
(The one VG with the global lock enabled must be visible to all hosts.)
@@ -494,55 +525,18 @@ and subsequent LVM commands will fail to acquire it. In this case, the
global lock needs to be manually enabled in one of the remaining sanlock
VGs with the command:
-lvmlockctl --gl-enable <vg_name>
+lvmlockctl \-\-gl\-enable <vgname>
A small sanlock VG dedicated to holding the global lock can avoid the case
where the GL lock must be manually enabled after a vgremove.
-.SS changing a local VG to a lockd VG
-
-All LVs must be inactive to change the lock type.
-
-lvmlockd must be configured and running as described in USAGE.
-
-Change a local VG to a lockd VG with the command:
-.br
-vgchange \-\-lock\-type sanlock|dlm <vg_name>
-
-Start the VG on any hosts that need to use it:
-.br
-vgchange \-\-lock\-start <vg_name>
+.SS sanlock VG usage
-
-.SS changing a clvm VG to a lockd VG
-
-All LVs must be inactive to change the lock type.
-
-1. Change the clvm VG to a local VG.
-
-Within a running clvm cluster, change a clvm VG to a local VG with the
-command:
-
-vgchange \-cn <vg_name>
-
-If the clvm cluster is no longer running on any nodes, then extra options
-can be used forcibly make the VG local. Caution: this is only safe if all
-nodes have stopped using the VG:
-
-vgchange \-\-config 'global/locking_type=0 global/use_lvmlockd=0'
-.RS
-\-cn <vg_name>
-.RE
-
-2. After the VG is local, follow the steps described in "changing a local
-VG to a lockd VG".
-
-
-.SS vgremove and vgreduce with sanlock VGs
+There are some special cases related to using a sanlock VG.
vgremove of a sanlock VG will fail if other hosts have the VG started.
-Run vgchange --lock-stop <vg_name> on all other hosts before vgremove.
+Run vgchange \-\-lock-stop <vgname> on all other hosts before vgremove.
(It may take several seconds before vgremove recognizes that all hosts
have stopped.)
@@ -550,17 +544,20 @@ have stopped.)
A sanlock VG contains a hidden LV called "lvmlock" that holds the sanlock
locks. vgreduce cannot yet remove the PV holding the lvmlockd LV.
+To place the lvmlock LV on a specific device, create the VG with only that
+device, then use vgextend to add other devices.
+
.SS shared LVs
When an LV is used concurrently from multiple hosts (e.g. by a
-multi-host/cluster application or file system), the LV can be activated on
-multiple hosts concurrently using a shared lock.
+multi\-host/cluster application or file system), the LV can be activated
+on multiple hosts concurrently using a shared lock.
-To activate the LV with a shared lock: lvchange -asy vg/lv.
+To activate the LV with a shared lock: lvchange \-asy vg/lv.
With lvmlockd, an unspecified activation mode is always exclusive, i.e.
--ay defaults to -aey.
+\-ay defaults to \-aey.
If the LV type does not allow the LV to be used concurrently from multiple
hosts, then a shared activation lock is not allowed and the lvchange
@@ -578,57 +575,13 @@ locks if the PV holding the locks is lost. Contact the LVM group for
help with this process.
-.\" This is not clean or safe enough to suggest using without help.
-.\"
-.\" .SS recover from lost PV holding sanlock locks
-.\"
-.\" In a sanlock VG, the locks are stored on a PV within the VG. If this PV
-.\" is lost, the locks need to be reconstructed as follows:
-.\"
-.\" 1. Enable the unsafe lock modes option in lvm.conf so that default locking requirements can be overriden.
-.\"
-.\" .nf
-.\" allow_override_lock_modes = 1
-.\" .fi
-.\"
-.\" 2. Remove missing PVs and partial LVs from the VG.
-.\"
-.\" Warning: this is a dangerous operation. Read the man page
-.\" for vgreduce first, and try running with the test option.
-.\" Verify that the only missing PV is the PV holding the sanlock locks.
-.\"
-.\" .nf
-.\" vgreduce --removemissing --force --lock-gl na --lock-vg na <vg>
-.\" .fi
-.\"
-.\" 3. If step 2 does not remove the internal/hidden "lvmlock" lv, it should be removed.
-.\"
-.\" .nf
-.\" lvremove --lock-vg na --lock-lv na <vg>/lvmlock
-.\" .fi
-.\"
-.\" 4. Change the lock type to none.
-.\"
-.\" .nf
-.\" vgchange --lock-type none --force --lock-gl na --lock-vg na <vg>
-.\" .fi
-.\"
-.\" 5. VG space is needed to recreate the locks. If there is not enough space, vgextend the vg.
-.\"
-.\" 6. Change the lock type back to sanlock. This creates a new internal
-.\" lvmlock lv, and recreates locks.
-.\"
-.\" .nf
-.\" vgchange --lock-type sanlock <vg>
-.\" .fi
-
.SS locking system failures
.B lvmlockd failure
If lvmlockd fails or is killed while holding locks, the locks are orphaned
-in the lock manager. lvmlockd can be restarted, and it will adopt the
-locks from the lock manager that had been held by the previous instance.
+in the lock manager. lvmlockd can be restarted with an option to adopt
+locks in the lock manager that had been held by the previous instance.
.B dlm/corosync failure
@@ -638,37 +591,33 @@ method configured within the dlm/corosync clustering environment.
LVM commands on other hosts will be blocked from acquiring any locks until
the dlm/corosync recovery process is complete.
-.B sanlock lock storage failure
-
-If access to the device containing the VG's locks is lost, sanlock cannot
-renew its leases for locked LVs. This means that the host could soon lose
-the lease to another host which could activate the LV exclusively.
-sanlock is designed to never reach the point where two hosts hold the
-same lease exclusively at once, so the same LV should never be active on
-two hosts at once when activated exclusively.
-
-The current method of handling this involves no action from lvmlockd,
-which allows sanlock to protect the leases itself. This produces a safe
-but potentially inconvenient result. Doing nothing from lvmlockd leads to
-the host's LV locks not being released, which leads to sanlock using the
-local watchdog to reset the host before another host can acquire any locks
-held by the local host.
-
-LVM commands on other hosts will be blocked from acquiring locks held by
-the failed/reset host until the sanlock recovery time expires (2-4
-minutes). This includes activation of any LVs that were locked by the
-failed host. It also includes GL/VG locks held by any LVM commands that
-happened to be running on the failed host at the time of the failure.
-
-(In the future, lvmlockd may have the option to suspend locked LVs in
-response the sanlock leases expiring. This would avoid the need for
-sanlock to reset the host.)
+.B sanlock lease storage failure
+
+If a host loses access to the device holding a VG's locks, sanlock cannot
+renew the VG's lockspace lease for those locks. After some time, the
+lease will expire, and locks held by the host can be acquired by other
+hosts.
+
+If no LVs are active in the VG, the lockspace with an expiring lease will
+be shut down, and errors will be reported when trying to use the VG. Use
+the lvmlockctl \-\-drop command to clear the stale lockspace from
+lvmlockd.
+
+If the VG has active LVs, the LVs must be quickly deactivated before the
+lockspace lease expires. After all LVs are deactivated, run lvmlockctl
+\-\-drop <vgname> to clear the expiring lockspace from lvmlockd. If all
+LVs in the VG are not deactivated within about 40 seconds, sanlock will
+reset the host using the local watchdog. The host reset is ultimately a
+severe form of "deactivating" LVs before they can be activated on other
+hosts. The reset is considered a better alternative than having LVs used
+by multiple hosts at once, which could easily damage or destroy their
+content. A future enhancement may automatically attempt to deactivate LVs
+before the lockspace lease expires.
.B sanlock daemon failure
If the sanlock daemon fails or exits while a lockspace is started, the
-local watchdog will reset the host. See previous section for the impact
-on other hosts.
+local watchdog will reset the host.
.SS changing dlm cluster name
@@ -688,44 +637,84 @@ cluster name for the dlm VG must be changed. To do this:
3. Change the VG lock type to none:
.br
- vgchange --lock-type none --force <vg_name>
+ vgchange \-\-lock\-type none \-\-force <vgname>
4. Change the VG lock type back to dlm which sets the new cluster name:
.br
- vgchange --lock-type dlm <vg_name>
+ vgchange \-\-lock\-type dlm <vgname>
-.SS limitations of lvmlockd and lockd VGs
+.SS changing a local VG to a lockd VG
-lvmlockd currently requires using lvmetad and lvmpolld.
+All LVs must be inactive to change the lock type.
+
+lvmlockd must be configured and running as described in USAGE.
-If a lockd VG becomes visible after the initial system startup, it is not
-automatically started through the system service/init manager, and LVs in
-it are not autoactivated.
+Change a local VG to a lockd VG with the command:
+.br
+vgchange \-\-lock\-type sanlock|dlm <vgname>
+
+Start the VG on any hosts that need to use it:
+.br
+vgchange \-\-lock\-start <vgname>
+
+
+.SS changing a clvm VG to a lockd VG
+
+All LVs must be inactive to change the lock type.
+
+First change the clvm VG to a local VG. Within a running clvm cluster,
+change a clvm VG to a local VG with the command:
+
+vgchange \-cn <vgname>
+
+If the clvm cluster is no longer running on any nodes, then extra options
+can be used forcibly make the VG local. Caution: this is only safe if all
+nodes have stopped using the VG:
+
+vgchange \-\-config 'global/locking_type=0 global/use_lvmlockd=0'
+.RS
+\-cn <vgname>
+.RE
+
+After the VG is local, follow the steps described in "changing a local VG
+to a lockd VG".
+
+
+.SS limitations of lockd VGs
+
+lvmlockd currently requires using lvmetad and lvmpolld.
Things that do not yet work in lockd VGs:
.br
-- creating a new thin pool and a new thin LV in a single command
+\[bu]
+creating a new thin pool and a new thin LV in a single command
.br
-- using lvcreate to create cache pools or cache LVs (use lvconvert)
+\[bu]
+using lvcreate to create cache pools or cache LVs (use lvconvert)
.br
-- using external origins for thin LVs
+\[bu]
+using external origins for thin LVs
.br
-- splitting mirrors and snapshots from LVs
+\[bu]
+splitting mirrors and snapshots from LVs
.br
-- vgsplit
+\[bu]
+vgsplit
.br
-- vgmerge
+\[bu]
+vgmerge
.br
-- resizing an LV that is active in the shared mode on multiple hosts
+\[bu]
+resizing an LV that is active in the shared mode on multiple hosts
-.SS clvmd to lvmlockd transition
+.SS lvmlockd changes from clvmd
(See above for converting an existing clvm VG to a lockd VG.)
-While lvmlockd and clvmd are entirely different systems, LVM usage remains
-largely the same. Differences are more notable when using lvmlockd's
+While lvmlockd and clvmd are entirely different systems, LVM command usage
+remains similar. Differences are more notable when using lvmlockd's
sanlock option.
Visible usage differences between lockd VGs with lvmlockd and clvm VGs
@@ -736,19 +725,16 @@ lvm.conf must be configured to use either lvmlockd (use_lvmlockd=1) or
clvmd (locking_type=3), but not both.
.IP \[bu] 2
-vgcreate --shared creates a lockd VG, and vgcreate --clustered y creates a
-clvm VG.
+vgcreate \-\-shared creates a lockd VG, and vgcreate \-\-clustered y
+creates a clvm VG.
.IP \[bu] 2
lvmlockd adds the option of using sanlock for locking, avoiding the
need for network clustering.
.IP \[bu] 2
-lvmlockd does not require all hosts to see all the same shared devices.
-
-.IP \[bu] 2
lvmlockd defaults to the exclusive activation mode whenever the activation
-mode is unspecified, i.e. -ay means -aey, not -asy.
+mode is unspecified, i.e. \-ay means \-aey, not \-asy.
.IP \[bu] 2
lvmlockd commands always apply to the local host, and never have an effect
@@ -762,13 +748,13 @@ lvmlockd saves the cluster name for a lockd VG using dlm. Only hosts in
the matching cluster can use the VG.
.IP \[bu] 2
-lvmlockd requires starting/stopping lockd VGs with vgchange --lock-start
-and --lock-stop.
+lvmlockd requires starting/stopping lockd VGs with vgchange \-\-lock-start
+and \-\-lock-stop.
.IP \[bu] 2
vgremove of a sanlock VG may fail indicating that all hosts have not
-stopped the lockspace for the VG. Stop the VG lockspace on all uses using
-vgchange --lock-stop.
+stopped the VG lockspace. Stop the VG on all hosts using vgchange
+\-\-lock-stop.
.IP \[bu] 2
vgreduce of a PV in a sanlock VG may fail if it holds the internal
@@ -777,12 +763,15 @@ vgreduce of a PV in a sanlock VG may fail if it holds the internal
.IP \[bu] 2
lvmlockd uses lock retries instead of lock queueing, so high lock
contention may require increasing global/lvmlockd_lock_retries to
-avoid transient lock contention failures.
+avoid transient lock failures.
+
+.IP \[bu] 2
+lvmlockd includes VG reporting options lock_type and lock_args, and LV
+reporting option lock_args to view the corresponding metadata fields.
.IP \[bu] 2
-The reporting options locktype and lockargs can be used to view lockd VG
-and LV lock_type and lock_args fields, i.g. vgs -o+locktype,lockargs.
-In the sixth VG attr field, "s" for "shared" is displayed for lockd VGs.
+In the 'vgs' command's sixth VG attr field, "s" for "shared" is displayed
+for lockd VGs.
.IP \[bu] 2
If lvmlockd fails or is killed while in use, locks it held remain but are
8 years, 8 months
master - man lvmcache: mention LVs must be in the same VG
by David Teigland
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=1c013e7ae29a9e...
Commit: 1c013e7ae29a9e3aa20930a24f3fcf0637ef1e91
Parent: fd1782b5fc41f3b9aceba6c27ba23098b0b4b6e2
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Thu Aug 6 10:05:12 2015 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Thu Aug 6 10:06:21 2015 -0500
man lvmcache: mention LVs must be in the same VG
---
man/lvmcache.7.in | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/man/lvmcache.7.in b/man/lvmcache.7.in
index 433746b..7257386 100644
--- a/man/lvmcache.7.in
+++ b/man/lvmcache.7.in
@@ -16,7 +16,7 @@ origin LV to increase speed. The cache metadata LV holds the
accounting information that specifies where data blocks are stored (e.g.
on the origin LV or on the cache data LV). Users should be familiar with
these LVs if they wish to create the best and most robust cached
-logical volumes.
+logical volumes. All of these associated LVs must be in the same VG.
.SH Cache Terms
.nf
8 years, 8 months
master - lvmlockd: handle loss of sanlock lease storage
by David Teigland
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=fd1782b5fc41f3...
Commit: fd1782b5fc41f3b9aceba6c27ba23098b0b4b6e2
Parent: 559ca8bc6593a9ef0b0b012ff0933b80f5d3e367
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Fri Jul 31 13:38:38 2015 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Wed Aug 5 10:21:45 2015 -0500
lvmlockd: handle loss of sanlock lease storage
This adds the infrastructure, code paths, error reporting,
etc. to handle storage errors, or storage loss, under the
sanlock leases in a VG that is being used. The loss of
storage means sanlock cannot renew its leases, which means
that the host needs to stop using the shared VG before its
leases expire.
This still requires manually shutting down a VG that has
lost lease storage, e.g. unmounting file systems,
deactivating LVs in the VG. The next step is to
automatically use a command like blkdeactivate to do that.
---
daemons/lvmlockd/lvmlockctl.c | 128 +++++++++++++++++++++--
daemons/lvmlockd/lvmlockd-client.h | 2 +
daemons/lvmlockd/lvmlockd-core.c | 99 ++++++++++++++++--
daemons/lvmlockd/lvmlockd-internal.h | 4 +
daemons/lvmlockd/lvmlockd-sanlock.c | 189 ++++++++++++++++++++++++----------
lib/locking/lvmlockd.c | 75 +++++++++++---
lib/locking/lvmlockd.h | 3 +-
7 files changed, 415 insertions(+), 85 deletions(-)
diff --git a/daemons/lvmlockd/lvmlockctl.c b/daemons/lvmlockd/lvmlockctl.c
index cb67296..148077e 100644
--- a/daemons/lvmlockd/lvmlockctl.c
+++ b/daemons/lvmlockd/lvmlockctl.c
@@ -17,6 +17,7 @@
#include <signal.h>
#include <errno.h>
#include <fcntl.h>
+#include <syslog.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <sys/un.h>
@@ -26,14 +27,16 @@ static int info = 0;
static int dump = 0;
static int wait_opt = 0;
static int force_opt = 0;
+static int kill_vg = 0;
+static int drop_vg = 0;
static int gl_enable = 0;
static int gl_disable = 0;
static int stop_lockspaces = 0;
-static char *able_vg_name = NULL;
+static char *arg_vg_name = NULL;
#define DUMP_SOCKET_NAME "lvmlockd-dump.sock"
#define DUMP_BUF_SIZE (1024 * 1024)
-static char dump_buf[DUMP_BUF_SIZE];
+static char dump_buf[DUMP_BUF_SIZE+1];
static int dump_len;
static struct sockaddr_un dump_addr;
static socklen_t dump_addrlen;
@@ -446,9 +449,9 @@ static int do_able(const char *req_name)
int rv;
reply = _lvmlockd_send(req_name,
- "cmd = %s", "lvmlock",
+ "cmd = %s", "lvmlockctl",
"pid = %d", getpid(),
- "vg_name = %s", able_vg_name,
+ "vg_name = %s", arg_vg_name,
NULL);
if (!_lvmlockd_result(reply, &result)) {
@@ -477,7 +480,7 @@ static int do_stop_lockspaces(void)
strcat(opts, "force ");
reply = _lvmlockd_send("stop_all",
- "cmd = %s", "lvmlock",
+ "cmd = %s", "lvmlockctl",
"pid = %d", getpid(),
"opts = %s", opts[0] ? opts : "none",
NULL);
@@ -493,6 +496,87 @@ static int do_stop_lockspaces(void)
return rv;
}
+static int do_kill(void)
+{
+ daemon_reply reply;
+ int result;
+ int rv;
+
+ syslog(LOG_EMERG, "Lost access to sanlock lease storage in VG %s.", arg_vg_name);
+ /* These two lines explain the manual alternative to the FIXME below. */
+ syslog(LOG_EMERG, "Immediately deactivate LVs in VG %s.", arg_vg_name);
+ syslog(LOG_EMERG, "Once VG is unused, run lvmlockctl --drop %s.", arg_vg_name);
+
+ /*
+ * It may not be strictly necessary to notify lvmlockd of the kill, but
+ * lvmlockd can use this information to avoid attempting any new lock
+ * requests in the VG (which would fail anyway), and can return an
+ * error indicating that the VG has been killed.
+ */
+
+ reply = _lvmlockd_send("kill_vg",
+ "cmd = %s", "lvmlockctl",
+ "pid = %d", getpid(),
+ "vg_name = %s", arg_vg_name,
+ NULL);
+
+ if (!_lvmlockd_result(reply, &result)) {
+ log_error("lvmlockd result %d", result);
+ rv = result;
+ } else {
+ rv = 0;
+ }
+
+ daemon_reply_destroy(reply);
+
+ /*
+ * FIXME: here is where we should implement a strong form of
+ * blkdeactivate, and if it completes successfully, automatically call
+ * do_drop() afterward. (The drop step may not always be necessary
+ * if the lvm commands run while shutting things down release all the
+ * leases.)
+ *
+ * run_strong_blkdeactivate();
+ * do_drop();
+ */
+
+ return rv;
+}
+
+static int do_drop(void)
+{
+ daemon_reply reply;
+ int result;
+ int rv;
+
+ syslog(LOG_WARNING, "Dropping locks for VG %s.", arg_vg_name);
+
+ /*
+ * Check for misuse by looking for any active LVs in the VG
+ * and refusing this operation if found? One possible way
+ * to kill LVs (e.g. if fs cannot be unmounted) is to suspend
+ * them, or replace them with the error target. In that
+ * case the LV will still appear to be active, but it is
+ * safe to release the lock.
+ */
+
+ reply = _lvmlockd_send("drop_vg",
+ "cmd = %s", "lvmlockctl",
+ "pid = %d", getpid(),
+ "vg_name = %s", arg_vg_name,
+ NULL);
+
+ if (!_lvmlockd_result(reply, &result)) {
+ log_error("lvmlockd result %d", result);
+ rv = result;
+ } else {
+ rv = 0;
+ }
+
+ daemon_reply_destroy(reply);
+ return rv;
+}
+
static void print_usage(void)
{
printf("lvmlockctl options\n");
@@ -509,12 +593,16 @@ static void print_usage(void)
printf(" Wait option for other commands.\n");
printf("--force | -f 0|1>\n");
printf(" Force option for other commands.\n");
- printf("--stop-lockspaces | -S\n");
- printf(" Stop all lockspaces.\n");
+ printf("--kill | -k <vg_name>\n");
+ printf(" Kill access to the vg when sanlock cannot renew lease.\n");
+ printf("--drop | -r <vg_name>\n");
+ printf(" Clear locks for the vg after it has been killed and is no longer used.\n");
printf("--gl-enable <vg_name>\n");
printf(" Tell lvmlockd to enable the global lock in a sanlock vg.\n");
printf("--gl-disable <vg_name>\n");
printf(" Tell lvmlockd to disable the global lock in a sanlock vg.\n");
+ printf("--stop-lockspaces | -S\n");
+ printf(" Stop all lockspaces.\n");
}
static int read_options(int argc, char *argv[])
@@ -529,6 +617,8 @@ static int read_options(int argc, char *argv[])
{"dump", no_argument, 0, 'd' },
{"wait", required_argument, 0, 'w' },
{"force", required_argument, 0, 'f' },
+ {"kill", required_argument, 0, 'k' },
+ {"drop", required_argument, 0, 'r' },
{"gl-enable", required_argument, 0, 'E' },
{"gl-disable", required_argument, 0, 'D' },
{"stop-lockspaces", no_argument, 0, 'S' },
@@ -541,7 +631,7 @@ static int read_options(int argc, char *argv[])
}
while (1) {
- c = getopt_long(argc, argv, "hqidE:D:w:S", long_options, &option_index);
+ c = getopt_long(argc, argv, "hqidE:D:w:k:r:S", long_options, &option_index);
if (c == -1)
break;
@@ -565,13 +655,21 @@ static int read_options(int argc, char *argv[])
case 'w':
wait_opt = atoi(optarg);
break;
+ case 'k':
+ kill_vg = 1;
+ arg_vg_name = strdup(optarg);
+ break;
+ case 'r':
+ drop_vg = 1;
+ arg_vg_name = strdup(optarg);
+ break;
case 'E':
gl_enable = 1;
- able_vg_name = strdup(optarg);
+ arg_vg_name = strdup(optarg);
break;
case 'D':
gl_disable = 1;
- able_vg_name = strdup(optarg);
+ arg_vg_name = strdup(optarg);
break;
case 'S':
stop_lockspaces = 1;
@@ -616,6 +714,16 @@ int main(int argc, char **argv)
goto out;
}
+ if (kill_vg) {
+ rv = do_kill();
+ goto out;
+ }
+
+ if (drop_vg) {
+ rv = do_drop();
+ goto out;
+ }
+
if (gl_enable) {
rv = do_able("enable_gl");
goto out;
diff --git a/daemons/lvmlockd/lvmlockd-client.h b/daemons/lvmlockd/lvmlockd-client.h
index e1d69d2..0a1424f 100644
--- a/daemons/lvmlockd/lvmlockd-client.h
+++ b/daemons/lvmlockd/lvmlockd-client.h
@@ -45,5 +45,7 @@ static inline void lvmlockd_close(daemon_handle h)
#define EMANAGER 214
#define EPREPARE 215
#define ELOCKD 216
+#define EVGKILLED 217 /* sanlock lost access to leases and VG is killed. */
+#define ELOCKIO 218 /* sanlock io errors during lock op, may be transient. */
#endif /* _LVM_LVMLOCKD_CLIENT_H */
diff --git a/daemons/lvmlockd/lvmlockd-core.c b/daemons/lvmlockd/lvmlockd-core.c
index 266339d..7493d11 100644
--- a/daemons/lvmlockd/lvmlockd-core.c
+++ b/daemons/lvmlockd/lvmlockd-core.c
@@ -735,6 +735,10 @@ static const char *op_str(int x)
return "find_free_lock";
case LD_OP_FORGET_VG_NAME:
return "forget_vg_name";
+ case LD_OP_KILL_VG:
+ return "kill_vg";
+ case LD_OP_DROP_VG:
+ return "drop_vg";
default:
return "op_unknown";
};
@@ -786,6 +790,7 @@ int version_from_args(char *args, unsigned int *major, unsigned int *minor, unsi
char *major_str, *minor_str, *patch_str;
char *n, *d1, *d2;
+ memset(version, 0, sizeof(version));
strncpy(version, args, MAX_ARGS);
version[MAX_ARGS] = '\0';
@@ -1828,7 +1833,7 @@ static int for_each_lock(struct lockspace *ls, int locks_do)
return 0;
}
-static int clear_locks(struct lockspace *ls, int free_vg)
+static int clear_locks(struct lockspace *ls, int free_vg, int drop_vg)
{
struct resource *r, *r_safe;
struct lock *lk, *lk_safe;
@@ -1847,10 +1852,10 @@ static int clear_locks(struct lockspace *ls, int free_vg)
/*
* Stopping a lockspace shouldn't happen with LV locks
* still held, but it will be stopped with GL and VG
- * locks held.
+ * locks held. The drop_vg case may see LV locks.
*/
- if (lk->flags & LD_LF_PERSISTENT)
+ if (lk->flags & LD_LF_PERSISTENT && !drop_vg)
log_error("S %s R %s clear lock persistent", ls->name, r->name);
else
log_debug("S %s R %s clear lock mode %s client %d", ls->name, r->name, mode_str(lk->mode), lk->client_id);
@@ -1884,8 +1889,8 @@ static int clear_locks(struct lockspace *ls, int free_vg)
rv = lm_unlock(ls, r, NULL, r_version, free_vg ? LMUF_FREE_VG : 0);
if (rv < 0) {
/* should never happen */
- log_error("S %s R %s clear_locks free %d lm unlock error %d",
- ls->name, r->name, free_vg, rv);
+ log_error("S %s R %s clear_locks free %d drop %d lm unlock error %d",
+ ls->name, r->name, free_vg, drop_vg, rv);
}
list_for_each_entry_safe(act, act_safe, &r->actions, list) {
@@ -1991,6 +1996,28 @@ static int other_sanlock_vgs_exist(struct lockspace *ls_rem)
}
/*
+ * LOCK is the main thing we're interested in; the others are unlikely.
+ */
+
+static int process_op_during_kill(struct action *act)
+{
+ if (act->op == LD_OP_LOCK && act->mode == LD_LK_UN)
+ return 1;
+
+ switch (act->op) {
+ case LD_OP_LOCK:
+ case LD_OP_ENABLE:
+ case LD_OP_DISABLE:
+ case LD_OP_UPDATE:
+ case LD_OP_RENAME_BEFORE:
+ case LD_OP_RENAME_FINAL:
+ case LD_OP_FIND_FREE_LOCK:
+ return 0;
+ };
+ return 1;
+}
+
+/*
* Process actions queued for this lockspace by
* client_recv_action / add_lock_action.
*
@@ -2010,6 +2037,7 @@ static void *lockspace_thread_main(void *arg_in)
struct list_head tmp_act;
struct list_head act_close;
int free_vg = 0;
+ int drop_vg = 0;
int error = 0;
int adopt_flag = 0;
int wait_flag = 0;
@@ -2114,7 +2142,43 @@ static void *lockspace_thread_main(void *arg_in)
act = list_first_entry(&ls->actions, struct action, list);
+ if (act->op == LD_OP_KILL_VG && act->rt == LD_RT_VG) {
+ /* Continue processing until DROP_VG arrives. */
+ log_debug("S %s kill_vg", ls->name);
+ ls->kill_vg = 1;
+ list_del(&act->list);
+ act->result = 0;
+ add_client_result(act);
+ continue;
+ }
+
+ if (ls->kill_vg && !process_op_during_kill(act)) {
+ log_debug("S %s disallow op %s after kill_vg", ls->name, op_str(act->op));
+ list_del(&act->list);
+ act->result = -EVGKILLED;
+ add_client_result(act);
+ continue;
+ }
+
+ if (act->op == LD_OP_DROP_VG && act->rt == LD_RT_VG) {
+ /*
+ * If leases are released after i/o errors begin
+ * but before lvmlockctl --kill, then the VG is not
+ * killed, but drop is still needed to clean up the
+ * VG, so in that case there would be a drop op without
+ * a preceding kill op.
+ */
+ if (!ls->kill_vg)
+ log_debug("S %s received drop without kill", ls->name);
+ log_debug("S %s drop_vg", ls->name);
+ ls->thread_work = 0;
+ ls->thread_stop = 1;
+ drop_vg = 1;
+ break;
+ }
+
if (act->op == LD_OP_STOP) {
+ /* thread_stop is already set */
ls->thread_work = 0;
break;
}
@@ -2238,6 +2302,9 @@ out_rem:
* allowed in emergency/force situations, otherwise it's
* obviously dangerous, since the lock holders are still
* operating under the assumption that they hold the lock.
+ * drop_vg drops all existing locks, but should only
+ * happen when the VG access has been forcibly and
+ * succesfully terminated.
*
* For vgremove of a sanlock vg, the vg lock will be held,
* and possibly the gl lock if this vg holds the gl.
@@ -2246,7 +2313,7 @@ out_rem:
log_debug("S %s clearing locks", ls->name);
- rv = clear_locks(ls, free_vg);
+ rv = clear_locks(ls, free_vg, drop_vg);
/*
* Tell any other hosts in the lockspace to leave it
@@ -2284,6 +2351,8 @@ out_act:
act->result = 0;
} else if (act->op == LD_OP_STOP)
act->result = 0;
+ else if (act->op == LD_OP_DROP_VG)
+ act->result = 0;
else if (act->op == LD_OP_RENAME_BEFORE)
act->result = 0;
else
@@ -2317,6 +2386,7 @@ out_act:
pthread_mutex_lock(&lockspaces_mutex);
ls->thread_done = 1;
ls->free_vg = free_vg;
+ ls->drop_vg = drop_vg;
pthread_mutex_unlock(&lockspaces_mutex);
/*
@@ -3539,7 +3609,6 @@ static int add_lock_action(struct action *act)
if (ls_create_fail)
act->flags |= LD_AF_ADD_LS_ERROR;
return -ENOLS;
-
} else {
log_debug("lockspace not found %s", ls_name);
return -ENOLS;
@@ -3714,6 +3783,16 @@ static int str_to_op_rt(const char *req_name, int *op, int *rt)
*rt = LD_RT_VG;
return 0;
}
+ if (!strcmp(req_name, "kill_vg")) {
+ *op = LD_OP_KILL_VG;
+ *rt = LD_RT_VG;
+ return 0;
+ }
+ if (!strcmp(req_name, "drop_vg")) {
+ *op = LD_OP_DROP_VG;
+ *rt = LD_RT_VG;
+ return 0;
+ }
out:
return -1;
}
@@ -3864,6 +3943,8 @@ static int print_lockspace(struct lockspace *ls, const char *prefix, int pos, in
"thread_work=%d "
"thread_stop=%d "
"thread_done=%d "
+ "kill_vg=%d "
+ "drop_vg=%d "
"sanlock_gl_enabled=%d\n",
prefix,
ls->name,
@@ -3878,6 +3959,8 @@ static int print_lockspace(struct lockspace *ls, const char *prefix, int pos, in
ls->thread_work ? 1 : 0,
ls->thread_stop ? 1 : 0,
ls->thread_done ? 1 : 0,
+ ls->kill_vg,
+ ls->drop_vg,
ls->sanlock_gl_enabled ? 1 : 0);
}
@@ -4273,6 +4356,8 @@ static void client_recv_action(struct client *cl)
case LD_OP_FREE:
case LD_OP_RENAME_BEFORE:
case LD_OP_FIND_FREE_LOCK:
+ case LD_OP_KILL_VG:
+ case LD_OP_DROP_VG:
rv = add_lock_action(act);
break;
case LD_OP_FORGET_VG_NAME:
diff --git a/daemons/lvmlockd/lvmlockd-internal.h b/daemons/lvmlockd/lvmlockd-internal.h
index 78ae88d..a1f74a7 100644
--- a/daemons/lvmlockd/lvmlockd-internal.h
+++ b/daemons/lvmlockd/lvmlockd-internal.h
@@ -51,6 +51,8 @@ enum {
LD_OP_RUNNING_LM,
LD_OP_FIND_FREE_LOCK,
LD_OP_FORGET_VG_NAME,
+ LD_OP_KILL_VG,
+ LD_OP_DROP_VG,
};
/* resource types */
@@ -184,6 +186,8 @@ struct lockspace {
unsigned int sanlock_gl_enabled: 1;
unsigned int sanlock_gl_dup: 1;
unsigned int free_vg: 1;
+ unsigned int kill_vg: 1;
+ unsigned int drop_vg: 1;
struct list_head actions; /* new client actions */
struct list_head resources; /* resource/lock state for gl/vg/lv */
diff --git a/daemons/lvmlockd/lvmlockd-sanlock.c b/daemons/lvmlockd/lvmlockd-sanlock.c
index 44926da..4317aad 100644
--- a/daemons/lvmlockd/lvmlockd-sanlock.c
+++ b/daemons/lvmlockd/lvmlockd-sanlock.c
@@ -33,52 +33,101 @@
#include <sys/socket.h>
/*
- * If access to the pv containing the vg's leases is lost, sanlock cannot renew
- * the leases we have acquired for locked LVs. This means that we could soon
- * loose the lease to another host which could activate our LV exclusively. We
- * do not want to get to the point of two hosts having the same LV active
- * exclusively (it obviously violates the purpose of LV locks.)
- *
- * The default method of preventing this problem is for lvmlockd to do nothing,
- * which produces a safe but potentially inconvenient result. Doing nothing
- * leads to our LV leases not being released, which leads to sanlock using the
- * local watchdog to reset us before another host can acquire our lock. It
- * would often be preferrable to avoid the abrupt hard reset from the watchdog.
- *
- * There are other options to avoid being reset by our watchdog. If we can
- * quickly stop using the LVs in question and release the locks for them, then
- * we could avoid a reset (there's a certain grace period of about 40 seconds
- * in which we can attempt this.) To do this, we can tell sanlock to run a
- * specific program when it has lost access to our leases. We could use this
- * program to:
- *
- * 1. Deactivate all lvs in the effected vg. If all the leases are
- * deactivated, then our LV locks would be released and sanlock would no longer
- * use the watchdog to reset us. If file systems are mounted on the active
- * lvs, then deactivating them would fail, so this option would be of limited
- * usefulness.
- *
- * 2. Option 1 could be extended to kill pids using the fs on the lv, unmount
- * the fs, and deactivate the lv. This is probably out of scope for lvm
- * directly, and would likely need the help of another system service.
- *
- * 3. Use dmsetup suspend to block access to lvs in the effected vg. If this
- * was successful, the local host could no longer write to the lvs, we could
- * safely release the LV locks, and sanlock would no longer reset us. At this
- * point, with suspended lvs, the host would be in a fairly hobbled state, and
- * would almost certainly need a manual, forcible reset.
- *
- * 4. Option 3 could be extended to monitor the lost storage, and if it is
- * reconnected, the leases could be reacquired, and the suspended lvs resumed
- * (reacquiring leases will fail if another host has acquired them since they
- * were released.) This complexity of this option, combined with the fact that
- * the error conditions are often not as simple as storage being lost and then
- * later connecting, will result in this option being too unreliable.
- *
- * Add a config option that we could use to select a different behavior than
- * the default. Then implement one of the simpler options as a proof of
- * concept, which could be extended if needed.
- */
+-------------------------------------------------------------------------------
+For each VG, lvmlockd creates a sanlock lockspace that holds the leases for
+that VG. There's a lease for the VG lock, and there's a lease for each active
+LV. sanlock maintains (reads/writes) these leases, which exist on storage.
+That storage is a hidden LV within the VG: /dev/vg/lvmlock. lvmlockd gives the
+path of this internal LV to sanlock, which then reads/writes the leases on it.
+
+# lvs -a cc -o+uuid
+ LV VG Attr LSize LV UUID
+ lv1 cc -wi-a----- 2.00g 7xoDtu-yvNM-iwQx-C94t-BbYs-UzBl-o8hAIa
+ lv2 cc -wi-a----- 100.00g exxNPX-wZdO-uCNy-yiGa-aJGT-JKVl-arfcYT
+ [lvmlock] cc -wi-ao---- 256.00m iLpDel-hR0T-hJ3u-rnVo-PcDh-mcjt-sF9egM
+
+# sanlock status
+s lvm_cc:1:/dev/mapper/cc-lvmlock:0
+r lvm_cc:exxNPX-wZdO-uCNy-yiGa-aJGT-JKVl-arfcYT:/dev/mapper/cc-lvmlock:71303168:13 p 26099
+r lvm_cc:7xoDtu-yvNM-iwQx-C94t-BbYs-UzBl-o8hAIa:/dev/mapper/cc-lvmlock:70254592:3 p 26099
+
+This shows that sanlock is maintaining leases on /dev/mapper/cc-lvmlock.
+
+sanlock acquires a lockspace lease when the lockspace is joined, i.e. when the
+VG is started by 'vgchange --lock-start cc'. This lockspace lease exists at
+/dev/mapper/cc-lvmlock offset 0, and sanlock regularly writes to it to maintain
+ownership of it. Joining the lockspace (by acquiring the lockspace lease in
+it) then allows standard resource leases to be acquired in the lockspace for
+whatever the application wants. lvmlockd uses resource leases for the VG lock
+and LV locks.
+
+sanlock acquires a resource lease for each actual lock that lvm commands use.
+Above, there are two LV locks that are held because the two LVs are active.
+These are on /dev/mapper/cc-lvmlock at offsets 71303168 and 70254592. sanlock
+does not write to these resource leases except when acquiring and releasing
+them (e.g. lvchange -ay/-an). The renewal of the lockspace lease maintains
+ownership of all the resource leases in the lockspace.
+
+If the host loses access to the disk that the sanlock lv lives on, then sanlock
+can no longer renew its lockspace lease. The lockspace lease will eventually
+expire, at which point the host will lose ownership of it, and of all resource
+leases it holds in the lockspace. Eventually, other hosts will be able to
+acquire those leases. sanlock ensures that another host will not be able to
+acquire one of the expired leases until the current host has quit using it.
+
+It is important that the host "quit using" the leases it is holding if the
+sanlock storage is lost and they begin expiring. If the host cannot quit using
+the leases and release them within a limited time, then sanlock will use the
+local watchdog to forcibly reset the host before any other host can acquire
+them. This is severe, but preferable to possibly corrupting the data protected
+by the lease. It ensures that two nodes will not be using the same lease at
+once. For LV leases, that means that another host will not be able to activate
+the LV while another host still has it active.
+
+sanlock notifies the application that it cannot renew the lockspace lease. The
+application needs to quit using all leases in the lockspace and release them as
+quickly as possible. In the initial version, lvmlockd ignored this
+notification, so sanlock would eventually reach the point where it would use
+the local watchdog to reset the host. However, it's better to attempt a
+response. If that response succeeds, the host can avoid being reset. If the
+response fails, then sanlock will eventually reset the host as the last resort.
+sanlock gives the application about 40 seconds to complete its response and
+release its leases before resetting the host.
+
+An application can specify the path and args of a program that sanlock should
+run to notify it if the lockspace lease cannot be renewed. This program should
+carry out the application's response to the expiring leases: attempt to quit
+using the leases and then release them. lvmlockd gives this command to sanlock
+for each VG when that VG is started: 'lvmlockctl --kill vg_name'
+
+If sanlock loses access to lease storage in that VG, it runs lvmlockctl --kill,
+which:
+
+1. Uses syslog to explain what is happening.
+
+2. Notifies lvmlockd that the VG is being killed, so lvmlockd can
+ immediatley return an error for this condition if any new lock
+ requests are made. (This step would not be strictly necessary.)
+
+3. Attempts to quit using the VG. This is not yet implemented, but
+ will eventually use blkdeactivate on the VG (or a more forceful
+ equivalent.)
+
+4. If step 3 was successful at terminating all use of the VG, then
+ lvmlockd is told to release all the leases for the VG. If this
+ is all done without about 40 seconds, the host can avoid being
+ reset.
+
+Until steps 3 and 4 are fully implemented, manual steps can be substituted.
+This is primarily for testing since the problem needs to be noticed and
+responded to in a very short time. The manual alternative to step 3 is to kill
+any processes using file systems on LV's in the VG, unmount all file systems on
+the LVs, and deactivate all the LVs. Once this is done, the manual alternative
+to step 4 is to run 'lvmlockctl --drop vg_name', which tells lvmlockd to
+release all the leases for the VG.
+-------------------------------------------------------------------------------
+*/
+
/*
* Each lockspace thread has its own sanlock daemon connection.
@@ -961,12 +1010,24 @@ int lm_prepare_lockspace_sanlock(struct lockspace *ls)
char lock_lv_name[MAX_ARGS+1];
char lsname[SANLK_NAME_LEN + 1];
char disk_path[SANLK_PATH_LEN];
+ char killpath[SANLK_PATH_LEN];
+ char killargs[SANLK_PATH_LEN];
int gl_found;
int ret, rv;
memset(disk_path, 0, sizeof(disk_path));
memset(lock_lv_name, 0, sizeof(lock_lv_name));
+ /*
+ * Construct the path to lvmlockctl by using the path to the lvm binary
+ * and appending "lockctl" to get /path/to/lvmlockctl.
+ */
+ memset(killpath, 0, sizeof(killpath));
+ snprintf(killpath, SANLK_PATH_LEN - 1, "%slockctl", LVM_PATH);
+
+ memset(killargs, 0, sizeof(killargs));
+ snprintf(killargs, SANLK_PATH_LEN - 1, "--kill %s", ls->vg_name);
+
rv = check_args_version(ls->vg_args, VG_LOCK_ARGS_MAJOR);
if (rv < 0) {
ret = -EARGS;
@@ -1051,6 +1112,15 @@ int lm_prepare_lockspace_sanlock(struct lockspace *ls)
goto fail;
}
+ log_debug("set killpath to %s %s", killpath, killargs);
+
+ rv = sanlock_killpath(lms->sock, 0, killpath, killargs);
+ if (rv < 0) {
+ log_error("S %s killpath error %d", lsname, rv);
+ ret = -EMANAGER;
+ goto fail;
+ }
+
rv = sanlock_restrict(lms->sock, SANLK_RESTRICT_SIGKILL);
if (rv < 0) {
log_error("S %s restrict error %d", lsname, rv);
@@ -1397,11 +1467,6 @@ int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
log_error("S %s R %s lock_san acquire error %d",
ls->name, r->name, rv);
- if (added) {
- lm_rem_resource_sanlock(ls, r);
- return rv;
- }
-
/* if the gl has been disabled, remove and free the gl resource */
if ((rv == SANLK_LEADER_RESOURCE) && (r->type == LD_RT_GL)) {
if (!lm_gl_is_enabled(ls)) {
@@ -1413,6 +1478,22 @@ int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
}
}
+ if (added)
+ lm_rem_resource_sanlock(ls, r);
+
+ /* sanlock gets i/o errors trying to read/write the leases. */
+ if (rv == -EIO)
+ rv = -ELOCKIO;
+
+ /*
+ * The sanlock lockspace can disappear if the lease storage fails,
+ * the delta lease renewals fail, the lockspace enters recovery,
+ * lvmlockd holds no leases in the lockspace, so sanlock can
+ * stop and free the lockspace.
+ */
+ if (rv == -ENOSPC)
+ rv = -ELOCKIO;
+
return rv;
}
@@ -1594,9 +1675,11 @@ int lm_unlock_sanlock(struct lockspace *ls, struct resource *r,
}
rv = sanlock_release(lms->sock, -1, 0, 1, &rs);
- if (rv < 0) {
+ if (rv < 0)
log_error("S %s R %s unlock_san release error %d", ls->name, r->name, rv);
- }
+
+ if (rv == -EIO)
+ rv = -ELOCKIO;
return rv;
}
diff --git a/lib/locking/lvmlockd.c b/lib/locking/lvmlockd.c
index 4e85ec1..7f14a86 100644
--- a/lib/locking/lvmlockd.c
+++ b/lib/locking/lvmlockd.c
@@ -1357,6 +1357,7 @@ int lockd_gl(struct cmd_context *cmd, const char *def_mode, uint32_t flags)
const char *mode = NULL;
const char *opts = NULL;
uint32_t lockd_flags;
+ int force_cache_update = 0;
int retries = 0;
int result;
@@ -1401,8 +1402,8 @@ int lockd_gl(struct cmd_context *cmd, const char *def_mode, uint32_t flags)
/* We can continue reading if a shared lock fails. */
if (!strcmp(mode, "sh")) {
log_warn("Reading without shared global lock.");
- lvmetad_validate_global_cache(cmd, 1);
- return 1;
+ force_cache_update = 1;
+ goto allow;
}
log_error("Global lock failed: check that lvmlockd is running.");
@@ -1425,9 +1426,19 @@ int lockd_gl(struct cmd_context *cmd, const char *def_mode, uint32_t flags)
*
* ESTARTING: the lockspace with the gl is starting.
* The VG with the global lock is starting and should finish shortly.
+ *
+ * ELOCKIO: sanlock gets i/o errors when trying to read/write leases
+ * (This can progress to EVGKILLED.)
+ *
+ * EVGKILLED: the sanlock lockspace is being killed after losing
+ * access to lease storage.
*/
- if (result == -ENOLS || result == -ESTARTING) {
+ if (result == -ENOLS ||
+ result == -ESTARTING ||
+ result == -EVGKILLED ||
+ result == -ELOCKIO) {
+
if (!strcmp(mode, "un"))
return 1;
@@ -1436,9 +1447,13 @@ int lockd_gl(struct cmd_context *cmd, const char *def_mode, uint32_t flags)
*/
if (strcmp(mode, "sh")) {
if (result == -ESTARTING)
- log_error("Global lock failed: lockspace is starting.");
+ log_error("Global lock failed: lockspace is starting");
else if (result == -ENOLS)
- log_error("Global lock failed: check that global lockspace is started.");
+ log_error("Global lock failed: check that global lockspace is started");
+ else if (result == -ELOCKIO)
+ log_error("Global lock failed: storage errors for sanlock leases");
+ else if (result == -EVGKILLED)
+ log_error("Global lock failed: storage failed for sanlock leases");
else
log_error("Global lock failed: error %d", result);
return 0;
@@ -1452,14 +1467,21 @@ int lockd_gl(struct cmd_context *cmd, const char *def_mode, uint32_t flags)
if (result == -ESTARTING) {
log_warn("Skipping global lock: lockspace is starting");
- lvmetad_validate_global_cache(cmd, 1);
- return 1;
+ force_cache_update = 1;
+ goto allow;
+ }
+
+ if (result == -ELOCKIO || result == -EVGKILLED) {
+ log_warn("Skipping global lock: storage %s for sanlock leases",
+ result == -ELOCKIO ? "errors" : "failed");
+ force_cache_update = 1;
+ goto allow;
}
if ((lockd_flags & LD_RF_NO_GL_LS) || (lockd_flags & LD_RF_NO_LOCKSPACES)) {
log_warn("Skipping global lock: lockspace not found or started");
- lvmetad_validate_global_cache(cmd, 1);
- return 1;
+ force_cache_update = 1;
+ goto allow;
}
/*
@@ -1492,9 +1514,8 @@ int lockd_gl(struct cmd_context *cmd, const char *def_mode, uint32_t flags)
}
}
- if (!(flags & LDGL_SKIP_CACHE_VALIDATE))
- lvmetad_validate_global_cache(cmd, 0);
-
+ allow:
+ lvmetad_validate_global_cache(cmd, force_cache_update);
return 1;
}
@@ -1510,7 +1531,7 @@ int lockd_gl(struct cmd_context *cmd, const char *def_mode, uint32_t flags)
*
* The result of the VG lock operation needs to be saved in lockd_state
* because the result needs to be passed into vg_read so it can be
- * assessed in combination with vg->lock_state.
+ * assessed in combination with vg->lock_type.
*
* The VG lock protects the VG metadata on disk from concurrent access
* among hosts. The VG lock also ensures that the local lvmetad cache
@@ -1687,6 +1708,28 @@ int lockd_vg(struct cmd_context *cmd, const char *vg_name, const char *def_mode,
}
/*
+ * sanlock is getting i/o errors while reading/writing leases, or the
+ * lockspace/VG is being killed after failing to renew its lease for
+ * too long.
+ */
+ if (result == -EVGKILLED || result == -ELOCKIO) {
+ const char *problem = (result == -ELOCKIO ? "errors" : "failed");
+
+ if (!strcmp(mode, "un")) {
+ ret = 1;
+ goto out;
+ } else if (!strcmp(mode, "sh")) {
+ log_warn("VG %s lock skipped: storage %s for sanlock leases", vg_name, problem);
+ ret = 1;
+ goto out;
+ } else {
+ log_error("VG %s lock failed: storage %s for sanlock leases", vg_name, problem);
+ ret = 0;
+ goto out;
+ }
+ }
+
+ /*
* An unused/previous lockspace for the VG was found.
* This means it must be a lockd VG, not local. The
* lockspace needs to be started to be used.
@@ -1903,6 +1946,12 @@ int lockd_lv_name(struct cmd_context *cmd, struct volume_group *vg,
return 0;
}
+ if (result == -EVGKILLED || result == -ELOCKIO) {
+ const char *problem = (result == -ELOCKIO ? "errors" : "failed");
+ log_error("LV %s/%s lock failed: storage %s for sanlock leases", vg->name, lv_name, problem);
+ return 0;
+ }
+
if (result < 0) {
log_error("LV %s/%s lock failed: error %d", vg->name, lv_name, result);
return 0;
diff --git a/lib/locking/lvmlockd.h b/lib/locking/lvmlockd.h
index b0edeae..64b3ce9 100644
--- a/lib/locking/lvmlockd.h
+++ b/lib/locking/lvmlockd.h
@@ -17,8 +17,7 @@
#define LOCKD_SANLOCK_LV_NAME "lvmlock"
/* lockd_gl flags */
-#define LDGL_SKIP_CACHE_VALIDATE 0x00000001
-#define LDGL_UPDATE_NAMES 0x00000002
+#define LDGL_UPDATE_NAMES 0x00000001
/* lockd_lv flags */
#define LDLV_MODE_NO_SH 0x00000001
8 years, 8 months
master - dmsetup: Report timestamps of ioctls with -vvv.
by Alasdair Kergon
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=559ca8bc6593a9...
Commit: 559ca8bc6593a9ef0b0b012ff0933b80f5d3e367
Parent: 2f334afb9836a792fd4e277d02ad6f317faa78ab
Author: Alasdair G Kergon <agk(a)redhat.com>
AuthorDate: Wed Aug 5 08:28:35 2015 +0100
Committer: Alasdair G Kergon <agk(a)redhat.com>
CommitterDate: Wed Aug 5 08:28:35 2015 +0100
dmsetup: Report timestamps of ioctls with -vvv.
If enabled, record timestamp immediately after the ioctl() returns.
---
WHATS_NEW_DM | 1 +
libdm/.exported_symbols.DM_1_02_104 | 2 +
libdm/ioctl/libdm-iface.c | 31 ++++++++++++++++-
libdm/ioctl/libdm-targets.h | 2 +
libdm/libdevmapper.h | 9 ++++-
libdm/libdm-common.c | 1 +
libdm/libdm-timestamp.c | 4 ++
tools/dmsetup.c | 63 ++++++++++++++++++++++++++---------
8 files changed, 93 insertions(+), 20 deletions(-)
diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM
index 57cfce4..c0cdadc 100644
--- a/WHATS_NEW_DM
+++ b/WHATS_NEW_DM
@@ -1,5 +1,6 @@
Version 1.02.104 -
=================================
+ Report timestamps of ioctls with dmsetup -vvv.
Recognize report field name variants without any underscores too.
Add dmsetup --interval and --count to repeat reports at specified intervals.
Add report interval and waiting functions to libdevmapper.
diff --git a/libdm/.exported_symbols.DM_1_02_104 b/libdm/.exported_symbols.DM_1_02_104
index 0039419..ec5c50b 100644
--- a/libdm/.exported_symbols.DM_1_02_104
+++ b/libdm/.exported_symbols.DM_1_02_104
@@ -4,6 +4,8 @@ dm_report_set_interval_ms
dm_report_set_interval_ns
dm_report_wait
dm_size_to_string
+dm_task_get_ioctl_timestamp
+dm_task_set_record_timestamp
dm_timestamp_alloc
dm_timestamp_compare
dm_timestamp_delta
diff --git a/libdm/ioctl/libdm-iface.c b/libdm/ioctl/libdm-iface.c
index e3b33b8..73af12b 100644
--- a/libdm/ioctl/libdm-iface.c
+++ b/libdm/ioctl/libdm-iface.c
@@ -68,6 +68,7 @@ static unsigned _dm_version = DM_VERSION_MAJOR;
static unsigned _dm_version_minor = 0;
static unsigned _dm_version_patchlevel = 0;
static int _log_suppress = 0;
+static struct dm_timestamp *_dm_ioctl_timestamp = NULL;
/*
* If the kernel dm driver only supports one major number
@@ -919,6 +920,24 @@ int dm_task_set_event_nr(struct dm_task *dmt, uint32_t event_nr)
return 1;
}
+int dm_task_set_record_timestamp(struct dm_task *dmt)
+{
+ if (!_dm_ioctl_timestamp)
+ _dm_ioctl_timestamp = dm_timestamp_alloc();
+
+ if (!_dm_ioctl_timestamp)
+ return_0;
+
+ dmt->record_timestamp = 1;
+
+ return 1;
+}
+
+struct dm_timestamp *dm_task_get_ioctl_timestamp(struct dm_task *dmt)
+{
+ return dmt->record_timestamp ? _dm_ioctl_timestamp : NULL;
+}
+
struct target *create_target(uint64_t start, uint64_t len, const char *type,
const char *params)
{
@@ -1716,6 +1735,7 @@ static struct dm_ioctl *_do_dm_ioctl(struct dm_task *dmt, unsigned command,
{
struct dm_ioctl *dmi;
int ioctl_with_uevent;
+ int r;
dmt->ioctl_errno = 0;
@@ -1803,8 +1823,13 @@ static struct dm_ioctl *_do_dm_ioctl(struct dm_task *dmt, unsigned command,
dmt->sector, _sanitise_message(dmt->message),
dmi->data_size, retry_repeat_count);
#ifdef DM_IOCTLS
- if (ioctl(_control_fd, command, dmi) < 0 &&
- dmt->expected_errno != errno) {
+ r = ioctl(_control_fd, command, dmi);
+
+ if (dmt->record_timestamp)
+ if (!dm_timestamp_get(_dm_ioctl_timestamp))
+ stack;
+
+ if (r < 0 && dmt->expected_errno != errno) {
dmt->ioctl_errno = errno;
if (dmt->ioctl_errno == ENXIO && ((dmt->type == DM_DEVICE_INFO) ||
(dmt->type == DM_DEVICE_MKNODES) ||
@@ -2049,6 +2074,8 @@ repeat_ioctl:
void dm_lib_release(void)
{
_close_control_fd();
+ dm_timestamp_destroy(_dm_ioctl_timestamp);
+ _dm_ioctl_timestamp = NULL;
update_devs();
}
diff --git a/libdm/ioctl/libdm-targets.h b/libdm/ioctl/libdm-targets.h
index 5545459..a3c1cb7 100644
--- a/libdm/ioctl/libdm-targets.h
+++ b/libdm/ioctl/libdm-targets.h
@@ -70,6 +70,8 @@ struct dm_task {
int expected_errno;
int ioctl_errno;
+ int record_timestamp;
+
char *uuid;
char *mangled_uuid;
};
diff --git a/libdm/libdevmapper.h b/libdm/libdevmapper.h
index 4a1703e..ed9a79e 100644
--- a/libdm/libdevmapper.h
+++ b/libdm/libdevmapper.h
@@ -128,6 +128,7 @@ enum {
*/
struct dm_task;
+struct dm_timestamp;
struct dm_task *dm_task_create(int type);
void dm_task_destroy(struct dm_task *dmt);
@@ -229,6 +230,12 @@ int dm_task_retry_remove(struct dm_task *dmt);
int dm_task_deferred_remove(struct dm_task *dmt);
/*
+ * Record timestamp immediately after the ioctl returns.
+ */
+int dm_task_set_record_timestamp(struct dm_task *dmt);
+struct dm_timestamp *dm_task_get_ioctl_timestamp(struct dm_task *dmt);
+
+/*
* Enable checks for common mistakes such as issuing ioctls in an unsafe order.
*/
int dm_task_enable_checks(struct dm_task *dmt);
@@ -1669,8 +1676,6 @@ dm_percent_t dm_make_percent(uint64_t numerator, uint64_t denominator);
* timestamp handling
********************/
-struct dm_timestamp;
-
/*
* Create a dm_timestamp object to use with dm_timestamp_get.
*/
diff --git a/libdm/libdm-common.c b/libdm/libdm-common.c
index 0811db0..e1bd44e 100644
--- a/libdm/libdm-common.c
+++ b/libdm/libdm-common.c
@@ -277,6 +277,7 @@ struct dm_task *dm_task_create(int type)
dmt->query_inactive_table = 0;
dmt->new_uuid = 0;
dmt->secure_data = 0;
+ dmt->record_timestamp = 0;
return dmt;
}
diff --git a/libdm/libdm-timestamp.c b/libdm/libdm-timestamp.c
index d2bd7bf..7690ccb 100644
--- a/libdm/libdm-timestamp.c
+++ b/libdm/libdm-timestamp.c
@@ -67,6 +67,8 @@ int dm_timestamp_get(struct dm_timestamp *ts)
if (clock_gettime(CLOCK_MONOTONIC, &ts->t)) {
log_sys_error("clock_gettime", "get_timestamp");
+ ts->t.tv_sec = 0;
+ ts->t.tv_nsec = 0;
return 0;
}
@@ -113,6 +115,8 @@ int dm_timestamp_get(struct dm_timestamp *ts)
if (gettimeofday(&ts->t, NULL)) {
log_sys_error("gettimeofday", "get_timestamp");
+ ts->t.tv_sec = 0;
+ ts->t.tv_usec = 0;
return 0;
}
diff --git a/tools/dmsetup.c b/tools/dmsetup.c
index 25789dc..485301a 100644
--- a/tools/dmsetup.c
+++ b/tools/dmsetup.c
@@ -185,6 +185,7 @@ static struct dm_report *_report;
static report_type_t _report_type;
static dev_name_t _dev_name_type;
static uint32_t _count = 1; /* count of repeating reports */
+static struct dm_timestamp *_initial_timestamp = NULL;
#define NSEC_PER_USEC UINT64_C(1000)
#define NSEC_PER_MSEC UINT64_C(1000000)
@@ -309,6 +310,24 @@ struct dmsetup_report_obj {
struct dm_split_name *split_name;
};
+static int _task_run(struct dm_task *dmt)
+{
+ int r;
+ uint64_t delta;
+
+ if (_initial_timestamp)
+ dm_task_set_record_timestamp(dmt);
+
+ r = dm_task_run(dmt);
+
+ if (_initial_timestamp) {
+ delta = dm_timestamp_delta(dm_task_get_ioctl_timestamp(dmt), _initial_timestamp);
+ log_debug("Timestamp: %7" PRIu64 ".%09" PRIu64 " seconds", delta / NSEC_PER_SEC, delta % NSEC_PER_SEC);
+ }
+
+ return r;
+}
+
static struct dm_task *_get_deps_task(int major, int minor)
{
struct dm_task *dmt;
@@ -330,7 +349,7 @@ static struct dm_task *_get_deps_task(int major, int minor)
if (_switches[CHECKS_ARG] && !dm_task_enable_checks(dmt))
goto err;
- if (!dm_task_run(dmt))
+ if (!_task_run(dmt))
goto err;
if (!dm_task_get_info(dmt, &info))
@@ -601,7 +620,7 @@ static int _load(CMD_ARGS)
if (_switches[CHECKS_ARG] && !dm_task_enable_checks(dmt))
goto out;
- if (!dm_task_run(dmt))
+ if (!_task_run(dmt))
goto out;
r = 1;
@@ -687,7 +706,7 @@ static int _create(CMD_ARGS)
udev_flags |= DM_UDEV_DISABLE_LIBRARY_FALLBACK;
if (!dm_task_set_cookie(dmt, &cookie, udev_flags) ||
- !dm_task_run(dmt))
+ !_task_run(dmt))
goto out;
r = 1;
@@ -743,7 +762,7 @@ static int _do_rename(const char *name, const char *new_name, const char *new_uu
udev_flags |= DM_UDEV_DISABLE_LIBRARY_FALLBACK;
if (!dm_task_set_cookie(dmt, &cookie, udev_flags) ||
- !dm_task_run(dmt))
+ !_task_run(dmt))
goto out;
r = 1;
@@ -833,7 +852,7 @@ static int _message(CMD_ARGS)
if (_switches[CHECKS_ARG] && !dm_task_enable_checks(dmt))
goto out;
- if (!dm_task_run(dmt))
+ if (!_task_run(dmt))
goto out;
if ((response = dm_task_get_message_response(dmt))) {
@@ -882,7 +901,7 @@ static int _setgeometry(CMD_ARGS)
goto out;
/* run the task */
- if (!dm_task_run(dmt))
+ if (!_task_run(dmt))
goto out;
r = 1;
@@ -1322,7 +1341,7 @@ static int _simple(int task, const char *name, uint32_t event_nr, int display)
if (_switches[DEFERRED_ARG] && (task == DM_DEVICE_REMOVE || task == DM_DEVICE_REMOVE_ALL))
dm_task_deferred_remove(dmt);
- r = dm_task_run(dmt);
+ r = _task_run(dmt);
out:
if (!_udev_cookie && udev_wait_flag)
@@ -1383,7 +1402,7 @@ static int _process_all(const struct command *cmd, const char *subcommand, int a
if (_switches[CHECKS_ARG] && !dm_task_enable_checks(dmt))
goto out;
- if (!dm_task_run(dmt)) {
+ if (!_task_run(dmt)) {
r = 0;
goto out;
}
@@ -1434,7 +1453,7 @@ static uint64_t _get_device_size(const char *name)
if (_switches[CHECKS_ARG] && !dm_task_enable_checks(dmt))
goto out;
- if (!dm_task_run(dmt))
+ if (!_task_run(dmt))
goto out;
if (!dm_task_get_info(dmt, &info) || !info.exists)
@@ -1483,7 +1502,7 @@ static int _error_device(CMD_ARGS)
if (_switches[CHECKS_ARG] && !dm_task_enable_checks(dmt))
goto error;
- if (!dm_task_run(dmt))
+ if (!_task_run(dmt))
goto error;
if (!_simple(DM_DEVICE_RESUME, name, 0, 0)) {
@@ -1671,7 +1690,7 @@ static int _status(CMD_ARGS)
if (_switches[NOFLUSH_ARG] && !dm_task_no_flush(dmt))
goto out;
- if (!dm_task_run(dmt))
+ if (!_task_run(dmt))
goto out;
if (!dm_task_get_info(dmt, &info) || !info.exists)
@@ -1747,7 +1766,7 @@ static int _targets(CMD_ARGS)
if (_switches[CHECKS_ARG] && !dm_task_enable_checks(dmt))
goto out;
- if (!dm_task_run(dmt))
+ if (!_task_run(dmt))
goto out;
target = dm_task_get_versions(dmt);
@@ -1799,7 +1818,7 @@ static int _info(CMD_ARGS)
if (_switches[CHECKS_ARG] && !dm_task_enable_checks(dmt))
goto out;
- if (!dm_task_run(dmt))
+ if (!_task_run(dmt))
goto out;
r = _display_info(dmt);
@@ -1843,7 +1862,7 @@ static int _deps(CMD_ARGS)
if (_switches[CHECKS_ARG] && !dm_task_enable_checks(dmt))
goto out;
- if (!dm_task_run(dmt))
+ if (!_task_run(dmt))
goto out;
if (!dm_task_get_info(dmt, &info))
@@ -3001,7 +3020,7 @@ static int _mangle(CMD_ARGS)
if (!_switches[CHECKS_ARG] && !dm_task_enable_checks(dmt))
goto out;
- if (!dm_task_run(dmt))
+ if (!_task_run(dmt))
goto out;
if (!dm_task_get_info(dmt, &info) || !info.exists)
@@ -3808,8 +3827,17 @@ static int _process_switches(int *argcp, char ***argvp, const char *dev_dir)
_switches[VERSION_ARG]++;
}
- if (_switches[VERBOSE_ARG] > 1)
+ if (_switches[VERBOSE_ARG] > 1) {
dm_log_init_verbose(_switches[VERBOSE_ARG] - 1);
+ if (_switches[VERBOSE_ARG] > 2) {
+ if (!(_initial_timestamp = dm_timestamp_alloc()))
+ stack;
+ else if (!dm_timestamp_get(_initial_timestamp))
+ stack;
+ else
+ log_debug("Timestamp: 0.000000000 seconds");
+ }
+ }
if ((_switches[MAJOR_ARG] && !_switches[MINOR_ARG]) ||
(!_switches[MAJOR_ARG] && _switches[MINOR_ARG])) {
@@ -3960,5 +3988,8 @@ out:
dm_free(_table);
+ if (_initial_timestamp)
+ dm_timestamp_destroy(_initial_timestamp);
+
return r;
}
8 years, 8 months
master - libdm: Whitespace.
by Alasdair Kergon
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=2f334afb9836a7...
Commit: 2f334afb9836a792fd4e277d02ad6f317faa78ab
Parent: 88551add9725ab9a6866bce2cd1e4428078d76d1
Author: Alasdair G Kergon <agk(a)redhat.com>
AuthorDate: Wed Aug 5 05:21:58 2015 +0100
Committer: Alasdair G Kergon <agk(a)redhat.com>
CommitterDate: Wed Aug 5 05:21:58 2015 +0100
libdm: Whitespace.
---
libdm/libdevmapper.h | 26 +++++++++++++-------------
1 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/libdm/libdevmapper.h b/libdm/libdevmapper.h
index 11ba0a3..4a1703e 100644
--- a/libdm/libdevmapper.h
+++ b/libdm/libdevmapper.h
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2015 Red Hat, Inc. All rights reserved.
- * Copyright (C) 2006 Rackable Systems All rights reserved.
+ * Copyright (C) 2006 Rackable Systems All rights reserved.
*
* This file is part of the device-mapper userspace tools.
*
@@ -528,12 +528,12 @@ struct dm_tree_node;
/*
* Initialise an empty dependency tree.
*
- * The tree consists of a root node together with one node for each mapped
+ * The tree consists of a root node together with one node for each mapped
* device which has child nodes for each device referenced in its table.
*
* Every node in the tree has one or more children and one or more parents.
*
- * The root node is the parent/child of every node that doesn't have other
+ * The root node is the parent/child of every node that doesn't have other
* parents/children.
*/
struct dm_tree *dm_tree_create(void);
@@ -641,7 +641,7 @@ int dm_tree_suspend_children(struct dm_tree_node *dnode,
* Skip the filesystem sync when suspending.
* Does nothing with other functions.
* Use this when no snapshots are involved.
- */
+ */
void dm_tree_skip_lockfs(struct dm_tree_node *dnode);
/*
@@ -712,7 +712,7 @@ int dm_tree_node_add_crypt_target(struct dm_tree_node *node,
const char *key);
int dm_tree_node_add_mirror_target(struct dm_tree_node *node,
uint64_t size);
-
+
/* Mirror log flags */
#define DM_NOSYNC 0x00000001 /* Known already in sync */
#define DM_FORCESYNC 0x00000002 /* Force resync */
@@ -1285,7 +1285,7 @@ struct dm_list *dm_list_prev(const struct dm_list *head, const struct dm_list *e
struct dm_list *dm_list_next(const struct dm_list *head, const struct dm_list *elem);
/*
- * Given the address v of an instance of 'struct dm_list' called 'head'
+ * Given the address v of an instance of 'struct dm_list' called 'head'
* contained in a structure of type t, return the containing structure.
*/
#define dm_list_struct_base(v, t, head) \
@@ -1317,7 +1317,7 @@ struct dm_list *dm_list_next(const struct dm_list *head, const struct dm_list *e
for (v = (head)->n; v != head; v = v->n)
/*
- * Set v to each element in a list in turn, starting from the element
+ * Set v to each element in a list in turn, starting from the element
* in front of 'start'.
* You can use this to 'unwind' a list_iterate and back out actions on
* already-processed elements.
@@ -1372,7 +1372,7 @@ struct dm_list *dm_list_next(const struct dm_list *head, const struct dm_list *e
dm_list_iterate_items_gen_safe(v, t, (head), list)
/*
- * Walk a list backwards, setting 'v' in turn to the containing structure
+ * Walk a list backwards, setting 'v' in turn to the containing structure
* of each item.
* The containing structure should be the same type as 'v'.
* The 'struct dm_list' variable within the containing structure is 'field'.
@@ -1383,7 +1383,7 @@ struct dm_list *dm_list_next(const struct dm_list *head, const struct dm_list *e
v = dm_list_struct_base(v->field.p, __typeof__(*v), field))
/*
- * Walk a list backwards, setting 'v' in turn to the containing structure
+ * Walk a list backwards, setting 'v' in turn to the containing structure
* of each item.
* The containing structure should be the same type as 'v'.
* The list should be 'struct dm_list list' within the containing structure.
@@ -1432,7 +1432,7 @@ int dm_split_words(char *buffer, unsigned max,
unsigned ignore_comments, /* Not implemented */
char **argv);
-/*
+/*
* Returns -1 if buffer too small
*/
int dm_snprintf(char *buf, size_t bufsize, const char *format, ...)
@@ -1555,8 +1555,8 @@ typedef enum {
* Set use_si_units to 1 for a suffix that does distinguish.
*/
const char *dm_size_to_string(struct dm_pool *mem, uint64_t size,
- char unit_type, int use_si_units,
- uint64_t unit_factor, int include_suffix,
+ char unit_type, int use_si_units,
+ uint64_t unit_factor, int include_suffix,
dm_size_suffix_t suffix_type);
/**************************
@@ -1683,7 +1683,7 @@ int dm_timestamp_get(struct dm_timestamp *ts);
/*
* Compare two timestamps.
- *
+ *
* Return: -1 if ts1 is less than ts2
* 0 if ts1 is equal to ts2
* 1 if ts1 is greater than ts2
8 years, 8 months
master - libdm: Whitespace.
by Alasdair Kergon
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=88551add9725ab...
Commit: 88551add9725ab9a6866bce2cd1e4428078d76d1
Parent: 23e8e849e47284b3e5db815767d2d47765579986
Author: Alasdair G Kergon <agk(a)redhat.com>
AuthorDate: Wed Aug 5 05:11:42 2015 +0100
Committer: Alasdair G Kergon <agk(a)redhat.com>
CommitterDate: Wed Aug 5 05:11:42 2015 +0100
libdm: Whitespace.
---
libdm/libdm-report.c | 20 ++++++++++----------
1 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/libdm/libdm-report.c b/libdm/libdm-report.c
index 225da90..1c4d221 100644
--- a/libdm/libdm-report.c
+++ b/libdm/libdm-report.c
@@ -154,18 +154,18 @@ static struct op_def _op_cmp[] = {
#define SEL_LIST_SUBSET_LE 0x00080000
static struct op_def _op_log[] = {
- { "&&", SEL_AND, "All fields must match" },
+ { "&&", SEL_AND, "All fields must match" },
{ ",", SEL_AND, "All fields must match" },
- { "||", SEL_OR, "At least one field must match" },
+ { "||", SEL_OR, "At least one field must match" },
{ "#", SEL_OR, "At least one field must match" },
- { "!", SEL_MODIFIER_NOT, "Logical negation" },
- { "(", SEL_PRECEDENCE_PS, "Left parenthesis" },
- { ")", SEL_PRECEDENCE_PE, "Right parenthesis" },
- { "[", SEL_LIST_LS, "List start" },
- { "]", SEL_LIST_LE, "List end"},
- { "{", SEL_LIST_SUBSET_LS, "List subset start"},
- { "}", SEL_LIST_SUBSET_LE, "List subset end"},
- { NULL, 0, NULL},
+ { "!", SEL_MODIFIER_NOT, "Logical negation" },
+ { "(", SEL_PRECEDENCE_PS, "Left parenthesis" },
+ { ")", SEL_PRECEDENCE_PE, "Right parenthesis" },
+ { "[", SEL_LIST_LS, "List start" },
+ { "]", SEL_LIST_LE, "List end"},
+ { "{", SEL_LIST_SUBSET_LS, "List subset start"},
+ { "}", SEL_LIST_SUBSET_LE, "List subset end"},
+ { NULL, 0, NULL},
};
struct selection_str_list {
8 years, 8 months
master - libdm: Sort new exported symbols.
by Alasdair Kergon
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=23e8e849e47284...
Commit: 23e8e849e47284b3e5db815767d2d47765579986
Parent: 362a1a5a820c07c94d0bf4b512b32a47141564d9
Author: Alasdair G Kergon <agk(a)redhat.com>
AuthorDate: Wed Aug 5 05:07:45 2015 +0100
Committer: Alasdair G Kergon <agk(a)redhat.com>
CommitterDate: Wed Aug 5 05:07:45 2015 +0100
libdm: Sort new exported symbols.
---
libdm/.exported_symbols.DM_1_02_104 | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/libdm/.exported_symbols.DM_1_02_104 b/libdm/.exported_symbols.DM_1_02_104
index 815c689..0039419 100644
--- a/libdm/.exported_symbols.DM_1_02_104
+++ b/libdm/.exported_symbols.DM_1_02_104
@@ -1,11 +1,11 @@
-dm_report_set_interval_ms
-dm_report_set_interval_ns
dm_report_get_interval_ms
dm_report_get_interval_ns
+dm_report_set_interval_ms
+dm_report_set_interval_ns
dm_report_wait
dm_size_to_string
dm_timestamp_alloc
dm_timestamp_compare
-dm_timestamp_get
dm_timestamp_delta
dm_timestamp_destroy
+dm_timestamp_get
8 years, 8 months
master - dmsetup: Tidy whitespace.
by Alasdair Kergon
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=362a1a5a820c07...
Commit: 362a1a5a820c07c94d0bf4b512b32a47141564d9
Parent: ce1528359a3021e255fec59962f21b18d6bb027a
Author: Alasdair G Kergon <agk(a)redhat.com>
AuthorDate: Wed Aug 5 05:03:33 2015 +0100
Committer: Alasdair G Kergon <agk(a)redhat.com>
CommitterDate: Wed Aug 5 05:03:33 2015 +0100
dmsetup: Tidy whitespace.
---
tools/dmsetup.c | 26 +++++++++++++-------------
1 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/tools/dmsetup.c b/tools/dmsetup.c
index bc71b35..25789dc 100644
--- a/tools/dmsetup.c
+++ b/tools/dmsetup.c
@@ -68,10 +68,10 @@ extern char *optarg;
#ifndef TEMP_FAILURE_RETRY
# define TEMP_FAILURE_RETRY(expression) \
- (__extension__ \
- ({ long int __result; \
- do __result = (long int) (expression); \
- while (__result == -1L && errno == EINTR); \
+ (__extension__ \
+ ({ long int __result; \
+ do __result = (long int) (expression); \
+ while (__result == -1L && errno == EINTR); \
__result; }))
#endif
@@ -295,10 +295,10 @@ static int _parse_file(struct dm_task *dmt, const char *file)
}
struct dm_split_name {
- char *subsystem;
- char *vg_name;
- char *lv_name;
- char *lv_layer;
+ char *subsystem;
+ char *vg_name;
+ char *lv_name;
+ char *lv_layer;
};
struct dmsetup_report_obj {
@@ -391,7 +391,7 @@ static struct dm_split_name *_get_split_name(const char *uuid, const char *name,
if (!strcmp(split_name->subsystem, "LVM") &&
(!(split_name->vg_name = dm_strdup(name)) ||
!dm_split_lvm_name(NULL, NULL, &split_name->vg_name,
- &split_name->lv_name, &split_name->lv_layer)))
+ &split_name->lv_name, &split_name->lv_layer)))
log_error("Failed to allocate memory to split LVM name "
"into components.");
@@ -678,7 +678,7 @@ static int _create(CMD_ARGS)
goto out;
if (!_set_task_add_node(dmt))
- goto out;
+ goto out;
if (_udev_cookie)
cookie = _udev_cookie;
@@ -900,7 +900,7 @@ static int _splitname(CMD_ARGS)
if (!(obj.split_name = _get_split_name((argc == 3) ? argv[2] : "LVM",
argv[1], '\0')))
- return_0;
+ return_0;
r = dm_report_object(_report, &obj);
_destroy_split_name(obj.split_name);
@@ -1296,7 +1296,7 @@ static int _simple(int task, const char *name, uint32_t event_nr, int display)
/* FIXME: needs to coperate with udev */
if (!_set_task_add_node(dmt))
- goto out;
+ goto out;
if (_switches[READAHEAD_ARG] &&
!dm_task_set_read_ahead(dmt, _int_args[READAHEAD_ARG],
@@ -3353,7 +3353,7 @@ static int _loop_table(char *table, size_t tlen, char *file,
#endif
if (close(fd))
- log_sys_error("close", file);
+ log_sys_error("close", file);
if (dm_snprintf(table, tlen, "%llu %llu loop %s %llu\n", 0ULL,
(long long unsigned)sectors, file, (long long unsigned)off) < 0)
8 years, 8 months
master - man: document --nameprefixes
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=ce1528359a3021...
Commit: ce1528359a3021e255fec59962f21b18d6bb027a
Parent: f02cdcff0084a323c9651d7ca2f22d60c83bcf3d
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Tue Aug 4 14:03:50 2015 +0200
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Tue Aug 4 14:03:50 2015 +0200
man: document --nameprefixes
---
man/dmsetup.8.in | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/man/dmsetup.8.in b/man/dmsetup.8.in
index 14e393a..ded7ca1 100644
--- a/man/dmsetup.8.in
+++ b/man/dmsetup.8.in
@@ -32,6 +32,7 @@ dmsetup \(em low level logical volume management
.br
.B dmsetup info
.BR \-c | \-C | \-\-columns
+.RB [ \-\-nameprefixes ]
.RB [ \-\-noheadings ]
.RB [ \-\-separator
.IR separator ]
@@ -236,6 +237,10 @@ Specify the minor number.
.BR \-n | \-\-notable
When creating a device, don't load any table.
.TP
+.BR \-\-nameprefixes
+Add a "DM_" prefix plus the field name to the output. Useful with --noheadings to produce a list of
+field=value pairs that can be used to set environment variables (for example, in udev(7) rules).
+.TP
.BR \-\-noheadings
Suppress the headings line when using columnar output.
.TP
8 years, 8 months
master - coverity: check vg->lvm1_system_id is not NULL before calling strncmp with that
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=f02cdcff0084a3...
Commit: f02cdcff0084a323c9651d7ca2f22d60c83bcf3d
Parent: 1f3d04cddf5a447de9bfb81ed22d0ccbe58e82fc
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Tue Aug 4 10:16:45 2015 +0200
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Tue Aug 4 10:35:31 2015 +0200
coverity: check vg->lvm1_system_id is not NULL before calling strncmp with that
lib/format1/import-export.c:167: var_deref_model: Passing null pointer "vg->lvm1_system_id" to "strncmp", which dereferences it.
---
lib/format1/import-export.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/lib/format1/import-export.c b/lib/format1/import-export.c
index 275583d..9e49a96 100644
--- a/lib/format1/import-export.c
+++ b/lib/format1/import-export.c
@@ -164,7 +164,7 @@ int export_pv(struct cmd_context *cmd, struct dm_pool *mem __attribute__((unused
/* Is VG already exported or being exported? */
if (vg && vg_is_exported(vg)) {
/* Does system_id need setting? */
- if ((vg->lvm1_system_id && !*vg->lvm1_system_id) ||
+ if (!vg->lvm1_system_id || !*vg->lvm1_system_id ||
strncmp(vg->lvm1_system_id, EXPORTED_TAG,
sizeof(EXPORTED_TAG) - 1)) {
if (!generate_lvm1_system_id(cmd, (char *)pvd->system_id, EXPORTED_TAG))
8 years, 8 months