Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=b0d8a524a2c1d9cc…
Commit: b0d8a524a2c1d9ccf191392bf47a2023087ae362
Parent: 37a33d7414b85e4ce69a2ab6727522faba8a86eb
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Thu Jun 30 16:21:03 2016 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Fri Jul 1 00:44:49 2016 +0200
tests: test foreign users of thin-pool
Note: dmeventd should not need any notification and automatically
try to resize again when there is some metadata change.
---
test/shell/thin-foreign-dmeventd.sh | 104 +++++++++++++++++++++++++++++++++++
1 files changed, 104 insertions(+), 0 deletions(-)
diff --git a/test/shell/thin-foreign-dmeventd.sh b/test/shell/thin-foreign-dmeventd.sh
new file mode 100644
index 0000000..a96b206
--- /dev/null
+++ b/test/shell/thin-foreign-dmeventd.sh
@@ -0,0 +1,104 @@
+#!/bin/sh
+
+# Copyright (C) 2016 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+# test foreing user of thin-pool
+
+SKIP_WITH_LVMLOCKD=1
+SKIP_WITH_LVMPOLLD=1
+
+. lib/inittest
+
+MOUNT_DIR=mnt
+
+cleanup_mounted_and_teardown()
+{
+ umount "$MOUNT_DIR" || true
+ dmsetup remove $THIN
+ vgremove -ff $vg
+ aux teardown
+}
+
+percent_() {
+ get lv_field $vg/pool data_percent | cut -d. -f1
+}
+
+#
+# Main
+#
+aux have_thin 1 0 0 || skip
+which mkfs.ext4 || skip
+
+aux prepare_dmeventd
+aux prepare_pvs 2 64
+
+vgcreate $vg -s 64K $(cat DEVICES)
+
+# Create named pool only
+lvcreate --errorwhenfull y -L2100K -T $vg/pool
+
+POOL="$vg-pool"
+THIN="${PREFIX}_thin"
+
+# Foreing user is using own ioctl command to create thin devices
+dmsetup message $POOL 0 "create_thin 0"
+dmsetup message $POOL 0 "set_transaction_id 0 1"
+
+dmsetup status
+# Once the transaction id has changed, lvm2 shall not be able to create thinLV
+fail lvcreate -V10 $vg/pool
+
+trap 'cleanup_mounted_and_teardown' EXIT
+
+# 20M thin device
+dmsetup create $THIN --table "0 40960 thin $DM_DEV_DIR/mapper/$POOL 0"
+
+dmsetup table
+dmsetup info -c
+
+mkdir "$MOUNT_DIR"
+# This mkfs fills 2.2MB pool over 95%
+# no autoresize is configured
+mkfs.ext4 "$DM_DEV_DIR/mapper/$THIN"
+test $(percent_) -gt 95
+mount "$DM_DEV_DIR/mapper/$THIN" "$MOUNT_DIR"
+
+pvchange -x n "$dev1" "$dev2"
+
+test $(percent_) -gt 95
+# Configure autoresize
+aux lvmconf 'activation/thin_pool_autoextend_percent = 10' \
+ 'activation/thin_pool_autoextend_threshold = 75'
+
+# Give it some time to left dmeventd do some work
+sleep 20
+
+# And check foreign thin device is still mounted
+mount | grep "$MOUNT_DIR" | grep "$THIN"
+test $(percent_) -gt 95
+
+pvchange -x y "$dev1" "$dev2"
+
+# FIXME: ATM tell dmeventd explicitely we've changed metadata
+# however dmeventd shall be aware of any metadata change
+# and automagically retry resize operation after that.
+lvchange --refresh $vg/pool
+
+# Give it some time and let dmeventd do some work
+for i in $(seq 1 15) ; do
+ test $(percent_) -ge 75 || break
+ sleep 1
+done
+
+test $(percent_) -lt 75
+
+# And check foreign thin device is still mounted
+mount | grep "$MOUNT_DIR" | grep "$THIN"
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=458918b31953943a…
Commit: 458918b31953943a3cc44976388f008ca850c124
Parent: 2f638e07e814617152d617a2ca7c8acdae41968a
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Thu Jun 30 15:54:27 2016 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Fri Jul 1 00:44:46 2016 +0200
thin: fix link validation for unused thin-pool
This patch fixes link validation for used thin-pool.
Udev rules correctly creates symlinks only for unused new thin-pool.
Such thin-pool can be used by foreing apps (like Docker) thus
has /dev/vg/lv link.
However when thin-pool becomes used by thinLV - this link is no
longer exposed to user - but internal verfication missed this
and caused messages like this to be printed upon 'vgchange -ay':
The link /dev/vg/pool should have been created by udev but it was not
found. Falling back to direct link creation.
And same with 'vgchange -an':
The link /dev/vg/pool should have been removed by udev but it is still
present. Falling back to direct link removal.
This patch ensures only unused thin-pool has this link.
---
WHATS_NEW | 1 +
lib/activate/dev_manager.c | 10 ++++++++--
test/shell/thin-overprovisioning.sh | 4 ++++
3 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index a73744e..4d71ea8 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.159 -
=================================
+ Fix created link for a used pool for vgmknode.
Introduce and use is_power_of_2 macro.
Support conversions between striped and raid0 segment types.
Add infrastructure for raid takeover lvconvert options.
diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
index 51f1a9a..233a216 100644
--- a/lib/activate/dev_manager.c
+++ b/lib/activate/dev_manager.c
@@ -1599,6 +1599,12 @@ static int _dev_manager_lv_rmnodes(const struct logical_volume *lv)
return fs_del_lv(lv);
}
+static int _lv_has_mknode(const struct logical_volume *lv)
+{
+ return (lv_is_visible(lv) &&
+ (!lv_is_thin_pool(lv) || lv_is_new_thin_pool(lv)));
+}
+
int dev_manager_mknodes(const struct logical_volume *lv)
{
struct dm_info dminfo;
@@ -1610,7 +1616,7 @@ int dev_manager_mknodes(const struct logical_volume *lv)
if ((r = _info_run(MKNODES, name, NULL, &dminfo, NULL, NULL, 0, 0, 0, 0))) {
if (dminfo.exists) {
- if (lv_is_visible(lv))
+ if (_lv_has_mknode(lv))
r = _dev_manager_lv_mknodes(lv);
} else
r = _dev_manager_lv_rmnodes(lv);
@@ -2993,7 +2999,7 @@ static int _create_lv_symlinks(struct dev_manager *dm, struct dm_tree_node *root
r = 0;
continue;
}
- if (lv_is_visible(lvlayer->lv)) {
+ if (_lv_has_mknode(lvlayer->lv)) {
if (!_dev_manager_lv_mknodes(lvlayer->lv))
r = 0;
continue;
diff --git a/test/shell/thin-overprovisioning.sh b/test/shell/thin-overprovisioning.sh
index 8a396b6..07c74cc 100644
--- a/test/shell/thin-overprovisioning.sh
+++ b/test/shell/thin-overprovisioning.sh
@@ -24,6 +24,8 @@ aux have_thin 1 3 0 || skip
aux prepare_vg 2 33
lvcreate -L32 -T $vg/pool
+# check there is link node for UNUSED thin-pool
+test -e "$DM_DEV_DIR/$vg/pool"
# leave 12M free space
lvcreate -an -n $lv1 -L16 $vg 2>&1 | tee out
@@ -31,6 +33,8 @@ vgs $vg
lvcreate -n thin1 -V30 $vg/pool 2>&1 | tee out
not grep "WARNING: Sum" out
+# check again link node is now gone for a USED thin-pool
+test ! -e "$DM_DEV_DIR/$vg/pool"
# Pool gets overprovisioned
lvcreate -an -n thin2 -V4 $vg/pool 2>&1 | tee out
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=103c188681fce748…
Commit: 103c188681fce748ef193115c126bfbbc65fbab9
Parent: aed8bc8ae7b2f1c20a84470b033daababfb7c166
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Thu Jun 30 12:02:43 2016 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Thu Jun 30 17:08:50 2016 -0500
lvconvert: add comments describing conversions
---
tools/lvconvert.c | 387 ++++++++++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 352 insertions(+), 35 deletions(-)
diff --git a/tools/lvconvert.c b/tools/lvconvert.c
index 3b98116..795deef 100644
--- a/tools/lvconvert.c
+++ b/tools/lvconvert.c
@@ -18,6 +18,25 @@
#include "lv_alloc.h"
#include "lvconvert_poll.h"
+/*
+ * Guidelines for mapping options to operations.
+ *
+ * There should be a clear and unique correspondence between an option
+ * name and the operation to be performed.
+ *
+ * An option with a given name should always perform the same operation.
+ * If the same operation applies to two types of LV, then the same option
+ * name can be used with both LV types. But, a given option name should
+ * not be used to perform different operations depending on the LV type it
+ * is used with.
+ *
+ * --merge and --split are examples where a single option name has been
+ * overloaded with different operations. The case of --split has been
+ * corrected with the clear and unique variations --splitcache,
+ * --splitsnapshot, --splitmirror, which should allow --split to be
+ * deprecated. (The same is still needed for --merge.)
+ */
+
struct lvconvert_params {
/* Exactly one of these options is chosen */
int merge; /* Either merge_snapshot or merge_mirror is also set */
@@ -3295,24 +3314,44 @@ static int _lvconvert_cache(struct cmd_context *cmd,
* moved into the _convert_lvtype_operation() functions below.
*/
+/*
+ * Separate a COW snapshot LV from its origin.
+ * lvconvert --splitsnapshot LV
+ */
+
static int _convert_cow_snapshot_splitsnapshot(struct cmd_context *cmd, struct logical_volume *lv,
struct lvconvert_params *lp)
{
return _lvconvert_splitsnapshot(cmd, lv, lp);
}
+/*
+ * Merge a COW snapshot LV into its origin.
+ * lvconvert --merge LV
+ */
+
static int _convert_cow_snapshot_merge(struct cmd_context *cmd, struct logical_volume *lv,
struct lvconvert_params *lp)
{
return _lvconvert_merge_old_snapshot(cmd, lv, lp);
}
+/*
+ * Merge a snapshot thin LV into its origin.
+ * lvconvert --merge LV
+ */
+
static int _convert_thin_volume_merge(struct cmd_context *cmd, struct logical_volume *lv,
struct lvconvert_params *lp)
{
return _lvconvert_merge_thin_snapshot(cmd, lv, lp);
}
+/*
+ * Split and preserve a cache pool from the data portion of a thin pool LV.
+ * lvconvert --splitcache LV
+ */
+
static int _convert_thin_pool_splitcache(struct cmd_context *cmd, struct logical_volume *lv,
struct lvconvert_params *lp)
{
@@ -3328,6 +3367,11 @@ static int _convert_thin_pool_splitcache(struct cmd_context *cmd, struct logical
return _lvconvert_split_cached(cmd, sublv1);
}
+/*
+ * Split and remove a cache pool from the data portion of a thin pool LV.
+ * lvconvert --uncache LV
+ */
+
static int _convert_thin_pool_uncache(struct cmd_context *cmd, struct logical_volume *lv,
struct lvconvert_params *lp)
{
@@ -3343,16 +3387,35 @@ static int _convert_thin_pool_uncache(struct cmd_context *cmd, struct logical_vo
return _lvconvert_uncache(cmd, sublv1, lp);
}
+/*
+ * Repair a thin pool LV.
+ * lvconvert --repair LV
+ */
+
static int _convert_thin_pool_repair(struct cmd_context *cmd, struct logical_volume *lv,
struct lvconvert_params *lp)
{
return _lvconvert_thin_pool_repair(cmd, lv, lp);
}
+/*
+ * Convert the data portion of a thin pool LV to a cache LV.
+ * lvconvert --type cache LV
+ *
+ * Required options:
+ * --cachepool LV
+ *
+ * Auxiliary operation:
+ * Converts the --cachepool arg to a cache pool if it is not already.
+ *
+ * Alternate syntax:
+ * lvconvert --cache LV
+ */
+
static int _convert_thin_pool_cache(struct cmd_context *cmd, struct logical_volume *lv,
struct lvconvert_params *lp)
{
- /* lvconvert --cache includes an implicit conversion of the cachepool arg to type cache-pool. */
+ /* lvconvert --type cache includes an implicit conversion of the cachepool arg to type cache-pool. */
if (!_lvconvert_pool(cmd, lv, lp)) {
log_error("Implicit conversion of --cachepool arg to type cache-pool failed.");
return 0;
@@ -3363,24 +3426,49 @@ static int _convert_thin_pool_cache(struct cmd_context *cmd, struct logical_volu
return _lvconvert_cache(cmd, lv, lp);
}
+/*
+ * Replace the metadata LV in a thin pool LV.
+ * lvconvert --poolmetadata NewLV --thinpool LV
+ * FIXME: this will change so --swap-poolmetadata defines the operation.
+ * FIXME: should be lvconvert --swap-poolmetadata NewLV LV
+ */
+
static int _convert_thin_pool_swapmetadata(struct cmd_context *cmd, struct logical_volume *lv,
struct lvconvert_params *lp)
{
return _lvconvert_pool(cmd, lv, lp);
}
+/*
+ * Split and preserve a cache pool from a cache LV.
+ * lvconvert --splitcache LV
+ */
+
static int _convert_cache_volume_splitcache(struct cmd_context *cmd, struct logical_volume *lv,
struct lvconvert_params *lp)
{
return _lvconvert_split_cached(cmd, lv);
}
+/*
+ * Split and remove a cache pool from a cache LV.
+ * lvconvert --uncache LV
+ */
+
static int _convert_cache_volume_uncache(struct cmd_context *cmd, struct logical_volume *lv,
struct lvconvert_params *lp)
{
return _lvconvert_uncache(cmd, lv, lp);
}
+/*
+ * Split images from the raid1|mirror origin of a cache LV and use them to create a new LV.
+ * lvconvert --splitmirrors Number LV
+ *
+ * Required options:
+ * --trackchanges | --name Name
+ */
+
static int _convert_cache_volume_splitmirrors(struct cmd_context *cmd, struct logical_volume *lv,
struct lvconvert_params *lp)
{
@@ -3398,12 +3486,26 @@ static int _convert_cache_volume_splitmirrors(struct cmd_context *cmd, struct lo
return 0;
}
+/*
+ * Convert a cache LV to a thin pool (using the cache LV for thin pool data).
+ * lvconvert --type thin-pool LV
+ *
+ * Alternate syntax:
+ * This is equivalent to above, but not preferred because it's ambiguous and inconsistent.
+ * lvconvert --thinpool LV
+ */
+
static int _convert_cache_volume_thin_pool(struct cmd_context *cmd, struct logical_volume *lv,
struct lvconvert_params *lp)
{
return _lvconvert_pool(cmd, lv, lp);
}
+/*
+ * Split a cache volume from a cache pool LV.
+ * lvconvert --splitcache LV
+ */
+
static int _convert_cache_pool_splitcache(struct cmd_context *cmd, struct logical_volume *lv,
struct lvconvert_params *lp)
{
@@ -3429,30 +3531,63 @@ static int _convert_cache_pool_splitcache(struct cmd_context *cmd, struct logica
return _lvconvert_split_cached(cmd, sublv1);
}
+/*
+ * Replace the metadata LV in a cache pool LV.
+ * lvconvert --poolmetadata NewLV --cachepool LV
+ * FIXME: this will change so --swap-poolmetadata defines the operation.
+ * FIXME: should be lvconvert --swap-poolmetadata NewLV LV
+ */
+
static int _convert_cache_pool_swapmetadata(struct cmd_context *cmd, struct logical_volume *lv,
struct lvconvert_params *lp)
{
return _lvconvert_pool(cmd, lv, lp);
}
+/*
+ * Change the number of images in a mirror LV.
+ * lvconvert --mirrors Number LV
+ */
+
static int _convert_mirror_number(struct cmd_context *cmd, struct logical_volume *lv,
struct lvconvert_params *lp)
{
return _lvconvert_mirrors(cmd, lv, lp);
}
+/*
+ * Split images from a mirror LV and use them to create a new LV.
+ * lvconvert --splitmirrors Number LV
+ *
+ * Required options:
+ * --name Name
+ */
+
static int _convert_mirror_splitmirrors(struct cmd_context *cmd, struct logical_volume *lv,
struct lvconvert_params *lp)
{
return _lvconvert_mirrors(cmd, lv, lp);
}
+/*
+ * Change the type of log used by a mirror LV.
+ * lvconvert --mirrorlog Type LV
+ */
+
static int _convert_mirror_log(struct cmd_context *cmd, struct logical_volume *lv,
struct lvconvert_params *lp)
{
return _lvconvert_mirrors(cmd, lv, lp);
}
+/*
+ * Replace failed PVs in a mirror LV.
+ * lvconvert --repair LV
+ *
+ * Auxiliary operation:
+ * Removes missing, empty PVs from the VG, like vgreduce.
+ */
+
static int _convert_mirror_repair(struct cmd_context *cmd, struct logical_volume *lv,
struct lvconvert_params *lp)
{
@@ -3469,18 +3604,38 @@ static int _convert_mirror_repair(struct cmd_context *cmd, struct logical_volume
return ret;
}
+/*
+ * Convert mirror LV to raid1 LV.
+ * lvconvert --type raid1 LV
+ *
+ * FIXME: this is not yet implemented in the raid code.
+ */
+
static int _convert_mirror_raid(struct cmd_context *cmd, struct logical_volume *lv,
struct lvconvert_params *lp)
{
return _lvconvert_raid(lv, lp);
}
+/*
+ * Change the number of images in a raid1 LV.
+ * lvconvert --mirrors Number LV
+ */
+
static int _convert_raid_number(struct cmd_context *cmd, struct logical_volume *lv,
struct lvconvert_params *lp)
{
return _lvconvert_raid(lv, lp);
}
+/*
+ * Split images from a raid1 LV and use them to create a new LV.
+ * lvconvert --splitmirrors Number LV
+ *
+ * Required options:
+ * --trackchanges | --name Name
+ */
+
static int _convert_raid_splitmirrors(struct cmd_context *cmd, struct logical_volume *lv,
struct lvconvert_params *lp)
{
@@ -3488,6 +3643,12 @@ static int _convert_raid_splitmirrors(struct cmd_context *cmd, struct logical_vo
return _lvconvert_raid(lv, lp);
}
+/*
+ * Merge a raid1 LV into originalLV if the raid1 LV was
+ * previously split from the originalLV using --trackchanges.
+ * lvconvert --merge LV
+ */
+
static int _convert_raid_merge(struct cmd_context *cmd, struct logical_volume *lv,
struct lvconvert_params *lp)
{
@@ -3495,6 +3656,14 @@ static int _convert_raid_merge(struct cmd_context *cmd, struct logical_volume *l
return _lvconvert_raid(lv, lp);
}
+/*
+ * Replace failed PVs in a raid* LV.
+ * lvconvert --repair LV
+ *
+ * Auxiliary operation:
+ * Removes missing, empty PVs from the VG, like vgreduce.
+ */
+
static int _convert_raid_repair(struct cmd_context *cmd, struct logical_volume *lv,
struct lvconvert_params *lp)
{
@@ -3512,6 +3681,11 @@ static int _convert_raid_repair(struct cmd_context *cmd, struct logical_volume *
return ret;
}
+/*
+ * Replace a specific PV in a raid* LV with another PV.
+ * lvconvert --replace PV LV
+ */
+
static int _convert_raid_replace(struct cmd_context *cmd, struct logical_volume *lv,
struct lvconvert_params *lp)
{
@@ -3519,12 +3693,35 @@ static int _convert_raid_replace(struct cmd_context *cmd, struct logical_volume
return _lvconvert_raid(lv, lp);
}
+/*
+ * Combine a raid* LV with a snapshot LV that was previously
+ * split from the raid* LV using --splitsnapshot.
+ * lvconvert --type snapshot LV SnapshotLV
+ *
+ * Alternate syntax:
+ * lvconvert --snapshot LV SnapshotLV
+ */
+
static int _convert_raid_snapshot(struct cmd_context *cmd, struct logical_volume *lv,
struct lvconvert_params *lp)
{
return _lvconvert_snapshot(cmd, lv, lp);
}
+/*
+ * Convert a raid* LV to a thin LV with an external origin.
+ * lvconvert --type thin LV
+ *
+ * Required options:
+ * --thinpool LV
+ *
+ * Auxiliary operation:
+ * Converts the --thinpool arg to a thin pool if it is not already.
+ *
+ * Alternate syntax:
+ * lvconvert --thin LV
+ */
+
static int _convert_raid_thin(struct cmd_context *cmd, struct logical_volume *lv,
struct lvconvert_params *lp)
{
@@ -3537,10 +3734,24 @@ static int _convert_raid_thin(struct cmd_context *cmd, struct logical_volume *lv
return _lvconvert_thin(cmd, lv, lp);
}
+/*
+ * Convert a raid* LV to a cache LV.
+ * lvconvert --type cache LV
+ *
+ * Required options:
+ * --cachepool LV
+ *
+ * Auxiliary operation:
+ * Converts the --cachepool arg to a cache pool if it is not already.
+ *
+ * Alternate syntax:
+ * lvconvert --cache LV
+ */
+
static int _convert_raid_cache(struct cmd_context *cmd, struct logical_volume *lv,
struct lvconvert_params *lp)
{
- /* lvconvert --cache includes an implicit conversion of the cachepool arg to type cache-pool. */
+ /* lvconvert --type cache includes an implicit conversion of the cachepool arg to type cache-pool. */
if (!_lvconvert_pool(cmd, lv, lp)) {
log_error("Implicit conversion of --cachepool arg to type cache-pool failed.");
return 0;
@@ -3549,41 +3760,74 @@ static int _convert_raid_cache(struct cmd_context *cmd, struct logical_volume *l
return _lvconvert_cache(cmd, lv, lp);
}
+/*
+ * Convert a raid* LV to a thin-pool LV.
+ * lvconvert --type thin-pool LV
+ *
+ * Alternate syntax:
+ * This is equivalent to above, but not preferred because it's ambiguous and inconsistent.
+ * lvconvert --thinpool LV
+ */
+
static int _convert_raid_thin_pool(struct cmd_context *cmd, struct logical_volume *lv,
struct lvconvert_params *lp)
{
return _lvconvert_pool(cmd, lv, lp);
}
+/*
+ * Convert a raid* LV to cache-pool LV.
+ * lvconvert --type cache-pool LV
+ */
+
static int _convert_raid_cache_pool(struct cmd_context *cmd, struct logical_volume *lv,
struct lvconvert_params *lp)
{
return _lvconvert_pool(cmd, lv, lp);
}
+/*
+ * Convert a raid* LV to use a different raid level.
+ * lvconvert --type raid* LV
+ */
+
static int _convert_raid_raid(struct cmd_context *cmd, struct logical_volume *lv,
struct lvconvert_params *lp)
{
return _lvconvert_raid(lv, lp);
}
+/*
+ * Convert a raid* LV to a striped LV.
+ * lvconvert --type striped LV
+ *
+ * FIXME: this is not yet implemented in the raid code.
+ */
+
static int _convert_raid_striped(struct cmd_context *cmd, struct logical_volume *lv,
struct lvconvert_params *lp)
{
return _lvconvert_raid(lv, lp);
}
+/*
+ * Convert a raid* LV to a linear LV.
+ * lvconvert --type linear LV
+ *
+ * FIXME: this is not yet implemented in the raid code.
+ */
+
static int _convert_raid_linear(struct cmd_context *cmd, struct logical_volume *lv,
struct lvconvert_params *lp)
{
return _lvconvert_raid(lv, lp);
}
-static int _convert_striped_snapshot(struct cmd_context *cmd, struct logical_volume *lv,
- struct lvconvert_params *lp)
-{
- return _lvconvert_snapshot(cmd, lv, lp);
-}
+/*
+ * Merge a striped/linear LV into a raid1 LV if the striped/linear LV was
+ * previously split from the raid1 LV using --trackchanges.
+ * lvconvert --merge LV
+ */
static int _convert_striped_merge(struct cmd_context *cmd, struct logical_volume *lv,
struct lvconvert_params *lp)
@@ -3591,6 +3835,35 @@ static int _convert_striped_merge(struct cmd_context *cmd, struct logical_volume
return _lvconvert_raid(lv, lp);
}
+/*
+ * Combine a linear/striped LV with a snapshot LV that was previously
+ * split from the linear/striped LV using --splitsnapshot.
+ * lvconvert --type snapshot LV SnapshotLV
+ *
+ * Alternate syntax:
+ * lvconvert --snapshot LV SnapshotLV
+ */
+
+static int _convert_striped_snapshot(struct cmd_context *cmd, struct logical_volume *lv,
+ struct lvconvert_params *lp)
+{
+ return _lvconvert_snapshot(cmd, lv, lp);
+}
+
+/*
+ * Convert a striped/linear LV to a thin LV with an external origin.
+ * lvconvert --type thin LV
+ *
+ * Required options:
+ * --thinpool LV
+ *
+ * Auxiliary operation:
+ * Converts the --thinpool arg to a thin pool if it is not already.
+ *
+ * Alternate syntax:
+ * lvconvert --thin LV
+ */
+
static int _convert_striped_thin(struct cmd_context *cmd, struct logical_volume *lv,
struct lvconvert_params *lp)
{
@@ -3603,6 +3876,20 @@ static int _convert_striped_thin(struct cmd_context *cmd, struct logical_volume
return _lvconvert_thin(cmd, lv, lp);
}
+/*
+ * Convert a striped/linear LV to a cache LV.
+ * lvconvert --type cache LV
+ *
+ * Required options:
+ * --cachepool LV
+ *
+ * Auxiliary operation:
+ * Converts the --cachepool arg to a cache pool if it is not already.
+ *
+ * Alternate syntax:
+ * lvconvert --cache LV
+ */
+
static int _convert_striped_cache(struct cmd_context *cmd, struct logical_volume *lv,
struct lvconvert_params *lp)
{
@@ -3615,24 +3902,62 @@ static int _convert_striped_cache(struct cmd_context *cmd, struct logical_volume
return _lvconvert_cache(cmd, lv, lp);
}
+/*
+ * Convert a striped/linear LV to a thin-pool LV.
+ * lvconvert --type thin-pool LV
+ *
+ * Alternate syntax:
+ * This is equivalent to above, but not preferred because it's ambiguous and inconsistent.
+ * lvconvert --thinpool LV
+ */
+
static int _convert_striped_thin_pool(struct cmd_context *cmd, struct logical_volume *lv,
struct lvconvert_params *lp)
{
return _lvconvert_pool(cmd, lv, lp);
}
+/*
+ * Convert a striped/linear LV to a cache-pool LV.
+ * lvconvert --type cache-pool LV
+ */
+
static int _convert_striped_cache_pool(struct cmd_context *cmd, struct logical_volume *lv,
struct lvconvert_params *lp)
{
return _lvconvert_pool(cmd, lv, lp);
}
+/*
+ * Convert a striped/linear LV to a mirror LV.
+ * lvconvert --type mirror LV
+ *
+ * Required options:
+ * --mirrors Number
+ *
+ * Alternate syntax:
+ * This is equivalent to above when global/mirror_segtype_default="mirror".
+ * lvconvert --mirrors Number LV
+ */
+
static int _convert_striped_mirror(struct cmd_context *cmd, struct logical_volume *lv,
struct lvconvert_params *lp)
{
return _lvconvert_mirrors(cmd, lv, lp);
}
+/*
+ * Convert a striped/linear LV to a raid* LV.
+ * lvconvert --type raid* LV
+ *
+ * Required options:
+ * --mirrors Number
+ *
+ * Alternate syntax:
+ * This is equivalent to above when global/mirror_segtype_default="raid1".
+ * lvconvert --mirrors Number LV
+ */
+
static int _convert_striped_raid(struct cmd_context *cmd, struct logical_volume *lv,
struct lvconvert_params *lp)
{
@@ -3696,9 +4021,9 @@ static int _convert_thin_pool(struct cmd_context *cmd, struct logical_volume *lv
log_error("Operation not permitted on thin pool LV %s", display_lvname(lv));
log_error("Operations permitted on a thin pool LV are:\n"
- " --splitcache (operates on cache sub LV)\n"
- " --uncache (operates on cache sub LV)\n"
- " --cache (operates on data sub LV)\n"
+ " --splitcache (operates on cache sub LV)\n"
+ " --uncache (operates on cache sub LV)\n"
+ " --type cache | --cache (operates on data sub LV)\n"
" --repair\n");
return 0;
}
@@ -3718,12 +4043,12 @@ static int _convert_cache_volume(struct cmd_context *cmd, struct logical_volume
if (arg_is_set(cmd, splitmirrors_ARG))
return _convert_cache_volume_splitmirrors(cmd, lv, lp);
- /* The --thinpool alias is ambiguous and not preferred. */
+ /* Using --thinpool is ambiguous and not preferred. */
if ((new_type && !strcmp(new_type, "thin-pool")) || arg_is_set(cmd, thinpool_ARG))
return _convert_cache_volume_thin_pool(cmd, lv, lp);
- /* The --thinpool alias for --type thin-pool is not preferred, so not shown. */
+ /* The --thinpool alternative for --type thin-pool is not preferred, so not shown. */
log_error("Operation not permitted on cache LV %s", display_lvname(lv));
log_error("Operations permitted on a cache LV are:\n"
@@ -3782,6 +4107,7 @@ static int _convert_mirror(struct cmd_context *cmd, struct logical_volume *lv,
* explicit option should be added to enable this case,
* rather than making it the result of an ambiguous
* "lvconvert vg/lv" command.
+ * Add 'lvconvert --poll-mirror vg/lv' for this case.
*
* Old behavior was described as:
* "Collapsing a stack of mirrors.
@@ -3837,7 +4163,7 @@ static int _convert_raid(struct cmd_context *cmd, struct logical_volume *lv,
if (lp->cache)
return _convert_raid_cache(cmd, lv, lp);
- /* The --thinpool alias is ambiguous and not preferred. */
+ /* Using --thinpool is ambiguous and not preferred. */
if ((new_type && !strcmp(new_type, "thin-pool")) || arg_is_set(cmd, thinpool_ARG))
return _convert_raid_thin_pool(cmd, lv, lp);
@@ -3854,7 +4180,7 @@ static int _convert_raid(struct cmd_context *cmd, struct logical_volume *lv,
if (new_type && !strcmp(new_type, "linear"))
return _convert_raid_linear(cmd, lv, lp);
- /* The --thinpool alias for --type thin-pool is not preferred, so not shown. */
+ /* The --thinpool alternative for --type thin-pool is not preferred, so not shown. */
log_error("Operation not permitted on raid LV %s", display_lvname(lv));
log_error("Operations permitted on a raid LV are:\n"
@@ -3863,9 +4189,9 @@ static int _convert_raid(struct cmd_context *cmd, struct logical_volume *lv,
" --merge\n"
" --repair\n"
" --replace\n"
- " --snapshot\n"
- " --thin\n"
- " --cache\n"
+ " --type snapshot | --snapshot\n"
+ " --type thin | --thin\n"
+ " --type cache | --cache\n"
" --type thin-pool\n"
" --type cache-pool\n"
" --type raid*\n"
@@ -3884,20 +4210,20 @@ static int _convert_striped(struct cmd_context *cmd, struct logical_volume *lv,
if (new_type)
new_segtype = get_segtype_from_string(cmd, new_type);
- if (lp->snapshot)
- return _convert_striped_snapshot(cmd, lv, lp);
-
/* FIXME: add a new option to make this case more clear, e.g. --merge-splitmirror */
if (lp->merge)
return _convert_striped_merge(cmd, lv, lp);
+ if (lp->snapshot)
+ return _convert_striped_snapshot(cmd, lv, lp);
+
if (lp->thin)
return _convert_striped_thin(cmd, lv, lp);
if (lp->cache)
return _convert_striped_cache(cmd, lv, lp);
- /* The --thinpool alias is ambiguous and not preferred. */
+ /* Using --thinpool is ambiguous and not preferred. */
if ((new_type && !strcmp(new_type, "thin-pool")) || arg_is_set(cmd, thinpool_ARG))
return _convert_striped_thin_pool(cmd, lv, lp);
@@ -3919,14 +4245,14 @@ static int _convert_striped(struct cmd_context *cmd, struct logical_volume *lv,
if (arg_is_set(cmd, mirrors_ARG) && mirrors_type && !strcmp(mirrors_type, "raid1"))
return _convert_striped_raid(cmd, lv, lp);
- /* The --thinpool alias for --type thin-pool is not preferred, so not shown. */
+ /* The --thinpool alternative for --type thin-pool is not preferred, so not shown. */
log_error("Operation not permitted on striped or linear LV %s", display_lvname(lv));
log_error("Operations permitted on a striped or linear LV are:\n"
- " --snapshot\n"
" --merge\n"
- " --thin\n"
- " --cache\n"
+ " --type snapshot | --snapshot\n"
+ " --type thin | --thin\n"
+ " --type cache | --cache\n"
" --type thin-pool\n"
" --type cache-pool\n"
" --type mirror | --mirrors\n"
@@ -3949,6 +4275,7 @@ static int _convert_striped(struct cmd_context *cmd, struct logical_volume *lv,
* _convert_lvtype();
* for each lp->operation
* _convert_lvtype_operation();
+ *
*/
static int _lvconvert(struct cmd_context *cmd, struct logical_volume *lv,
@@ -3957,12 +4284,6 @@ static int _lvconvert(struct cmd_context *cmd, struct logical_volume *lv,
struct lv_segment *lv_seg = first_seg(lv);
int ret = 0;
- log_debug("lvconvert lv %s is type %s status %llx to type %s",
- display_lvname(lv),
- lv_seg->segtype->name,
- (unsigned long long)lv->status,
- arg_str_value(cmd, type_ARG, ""));
-
/*
* Check some conditions that can never be processed.
*/
@@ -4048,10 +4369,6 @@ static int _lvconvert(struct cmd_context *cmd, struct logical_volume *lv,
}
/*
- * Check for LV types that cannot be converted and print an error.
- */
-
- /*
* The intention is to explicitly check all cases above and never
* reach here, but this covers anything that was missed.
*/
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=a8e39530efdffc42…
Commit: a8e39530efdffc42d21e9bc968ab3966b719876a
Parent: 802ed9d4597443e21086b392d9ee160f6d99dde9
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Thu Jun 30 10:09:54 2016 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Thu Jun 30 10:09:54 2016 -0500
lvconvert: add missing alias for a thin-pool conversion
The case of converting a cache volume to a thin pool missed
recognizing the --thinpool alias for --type thin-pool.
---
tools/lvconvert.c | 6 +++++-
1 files changed, 5 insertions(+), 1 deletions(-)
diff --git a/tools/lvconvert.c b/tools/lvconvert.c
index 4808090..8ceb1c7 100644
--- a/tools/lvconvert.c
+++ b/tools/lvconvert.c
@@ -3718,9 +3718,13 @@ static int _convert_cache_volume(struct cmd_context *cmd, struct logical_volume
if (arg_is_set(cmd, splitmirrors_ARG))
return _convert_cache_volume_splitmirrors(cmd, lv, lp);
- if (new_type && !strcmp(new_type, "thin-pool"))
+ /* The --thinpool alias is ambiguous and not preferred. */
+
+ if ((new_type && !strcmp(new_type, "thin-pool")) || arg_is_set(cmd, thinpool_ARG))
return _convert_cache_volume_thin_pool(cmd, lv, lp);
+ /* The --thinpool alias for --type thin-pool is not preferred, so not shown. */
+
log_error("Operation not permitted on cache LV %s", display_lvname(lv));
log_error("Operations permitted on a cache LV are:\n"
" --splitcache\n"
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=eac0706761e62853…
Commit: eac0706761e628532ffcd27f3e4d7fa559a5f818
Parent: 686acce23fed6bd72af63201e4cc56bc5958379e
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Wed Jun 29 15:58:14 2016 +0200
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Wed Jun 29 15:58:18 2016 +0200
libdm: do not issue 'Failed to create directory' message for failure in dm_create_dir
There are detailed messages inside _create_dir_recursive that
dm_create_dir calls (except EROFS which where the message is not
generated, like anywhere else in the code).
---
libdm/libdm-file.c | 6 ++----
1 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/libdm/libdm-file.c b/libdm/libdm-file.c
index 9867824..2c313b3 100644
--- a/libdm/libdm-file.c
+++ b/libdm/libdm-file.c
@@ -97,10 +97,8 @@ int dm_create_dir(const char *dir)
if (stat(dir, &info) == 0 && S_ISDIR(info.st_mode))
return 1;
- if (!_create_dir_recursive(dir)) {
- log_error("Failed to create directory %s.", dir);
- return 0;
- }
+ if (!_create_dir_recursive(dir))
+ return_0;
return 1;
}
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=6f216692b47b38f4…
Commit: 6f216692b47b38f480e50d213de5c513a309d9e0
Parent: 1d3532d0a7d458550b53218a6b21798eab30b68e
Author: Tony Asleson <tasleson(a)redhat.com>
AuthorDate: Tue Jun 28 13:36:32 2016 -0500
Committer: Tony Asleson <tasleson(a)redhat.com>
CommitterDate: Tue Jun 28 13:36:32 2016 -0500
lvmdbustest: Comment out refresh check for LV create
When we test Vg.LvCreateRaid some of the hidden LVs volume type go from
'I' to 'i' between the time it takes us to create the LV and
the time it takes to call into refresh to verify the service is up to date.
This is a fairly rare occurance.
---
test/dbus/lvmdbustest.py | 6 +++++-
1 files changed, 5 insertions(+), 1 deletions(-)
diff --git a/test/dbus/lvmdbustest.py b/test/dbus/lvmdbustest.py
index 4443b0c..457db96 100755
--- a/test/dbus/lvmdbustest.py
+++ b/test/dbus/lvmdbustest.py
@@ -373,7 +373,11 @@ class TestDbusService(unittest.TestCase):
lv = ClientProxy(self.bus, path)
# TODO verify object properties
- self.assertEqual(self._refresh(), 0)
+ # We are quick enough now that we can get VolumeType changes from
+ # 'I' to 'i' between the time it takes to create a RAID and it returns
+ # and when we refresh state here. Not sure how we can handle this as
+ # we cannot just sit and poll all the time for changes...
+ # self.assertEqual(self._refresh(), 0)
return lv
def test_lv_create(self):
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=e6e5c3d3ecb7de18…
Commit: e6e5c3d3ecb7de18ec2d103df8e5b0229df9ce1c
Parent: 7c5a08521b687c7c7074b41d880e1e559d4ea6b8
Author: Tony Asleson <tasleson(a)redhat.com>
AuthorDate: Tue Jun 28 12:52:31 2016 -0500
Committer: Tony Asleson <tasleson(a)redhat.com>
CommitterDate: Tue Jun 28 12:54:48 2016 -0500
lvmdbusd: Remove WARNING for 'lvm help'
We call 'lvm help' to find out if fullreport is supported. Lvm
dumps help to stderr. Common code prints a warning if we exit
with 0, but have something in stderr so we are skipping the warning
message.
---
daemons/lvmdbusd/cmdhandler.py | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/daemons/lvmdbusd/cmdhandler.py b/daemons/lvmdbusd/cmdhandler.py
index 560b389..391757d 100644
--- a/daemons/lvmdbusd/cmdhandler.py
+++ b/daemons/lvmdbusd/cmdhandler.py
@@ -110,7 +110,7 @@ def call_lvm(command, debug=False):
_debug_c(command, process.returncode, (stdout_text, stderr_text))
if process.returncode == 0:
- if cfg.DEBUG and out[1] and len(out[1]):
+ if cfg.DEBUG and out[1] and len(out[1]) and 'help' not in command:
log_error('WARNING: lvm is out-putting text to STDERR on success!')
_debug_c(command, process.returncode, (stdout_text, stderr_text))
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=7c5a08521b687c7c…
Commit: 7c5a08521b687c7c7074b41d880e1e559d4ea6b8
Parent: 9e3ad37828a14924dd12f65e62194bef286a16f0
Author: Tony Asleson <tasleson(a)redhat.com>
AuthorDate: Tue Jun 28 12:45:55 2016 -0500
Committer: Tony Asleson <tasleson(a)redhat.com>
CommitterDate: Tue Jun 28 12:45:55 2016 -0500
lvmdbusd: Remove unneeded comment
---
daemons/lvmdbusd/lv.py | 2 --
1 files changed, 0 insertions(+), 2 deletions(-)
diff --git a/daemons/lvmdbusd/lv.py b/daemons/lvmdbusd/lv.py
index 8f063dc..5658d29 100644
--- a/daemons/lvmdbusd/lv.py
+++ b/daemons/lvmdbusd/lv.py
@@ -472,8 +472,6 @@ class Lv(LvCommon):
# it is a thin lv
if not dbo.IsThinVolume:
if optional_size == 0:
- # TODO: Should we pick a sane default or force user to
- # make a decision?
space = dbo.SizeBytes / 80
remainder = space % 512
optional_size = space + 512 - remainder
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=dd5d865020acd545…
Commit: dd5d865020acd545712d4bcc0f3236143de4d76d
Parent: 5274c2f11b9e262588c1dec86609e829618d2e76
Author: Tony Asleson <tasleson(a)redhat.com>
AuthorDate: Tue Jun 28 12:07:21 2016 -0500
Committer: Tony Asleson <tasleson(a)redhat.com>
CommitterDate: Tue Jun 28 12:09:28 2016 -0500
lvmdbusd: Fix hang when lvm compiled with 'enable-notify-dbus'
The following operations would hang if lvm was compiled with
'enable-notify-dbus' and the client specified -1 for the timeout:
* LV snapshot merge
* VG move
* LV move
This was caused because the implementation of these three dbus methods is
different. Most of the dbus method calls are executed by gathering information
needed to fulfill it, placing that information on a thread safe queue and
returning. The results later to be returned to the client with callbacks.
With this approach we can process an arbitrary number of commands without any
of them blocking other dbus commands. However, the 3 dbus methods listed
above did not utilize this functionality because they were implemented with a
separate thread that handles the fork & exec of lvm. This is done because these
operations can be very slow to complete. However, because of this the lvm
command that we were waiting on is trying to call back into the dbus service to
notify it that something changed. Because the code was blocking the process
that handles the incoming dbus activity the lvm command blocked. We were stuck
until the client timed-out the connection, which then causes the service to
unblock and continue. If the client did not have a timeout, we would have been
hung indefinitely.
The fix is to always utilize the worker queue on all dbus methods. We need to
ensure that lvm is tested with 'enable-notify-dbus' enabled and disabled.
---
daemons/lvmdbusd/background.py | 77 ++++++++++-----------------------------
daemons/lvmdbusd/job.py | 2 +-
daemons/lvmdbusd/lv.py | 34 ++++++++++++-----
daemons/lvmdbusd/request.py | 5 ++-
daemons/lvmdbusd/vg.py | 19 +++++++---
5 files changed, 62 insertions(+), 75 deletions(-)
diff --git a/daemons/lvmdbusd/background.py b/daemons/lvmdbusd/background.py
index 4265154..ca3d60e 100644
--- a/daemons/lvmdbusd/background.py
+++ b/daemons/lvmdbusd/background.py
@@ -43,40 +43,22 @@ def lv_merge_cmd(merge_options, lv_full_name):
return cmd
-def _create_background_dbus_job(job_state):
- job_obj = Job(None, job_state)
- cfg.om.register_object(job_obj)
- return job_obj.dbus_object_path()
-
-
-def _move_merge(interface_name, cmd, time_out):
- # Create job object to be used while running the command
- rc = '/'
- job_state = JobState(None)
+def _move_merge(interface_name, cmd, job_state):
add(cmd, job_state)
- if time_out == -1:
- # Waiting forever
- done = job_state.Wait(time_out)
- if not done:
- ec, err_msg = job_state.GetError
- raise dbus.exceptions.DBusException(
- interface_name,
- 'Exit code %s, stderr = %s' % (str(ec), err_msg))
- elif time_out == 0:
- # Immediately create and return a job
- rc = _create_background_dbus_job(job_state)
- else:
- # Willing to wait for a bit
- done = job_state.Wait(time_out)
- if not done:
- rc = _create_background_dbus_job(job_state)
+ done = job_state.Wait(-1)
+ if not done:
+ ec, err_msg = job_state.GetError
+ raise dbus.exceptions.DBusException(
+ interface_name,
+ 'Exit code %s, stderr = %s' % (str(ec), err_msg))
- return rc
+ cfg.load()
+ return '/'
def move(interface_name, lv_name, pv_src_obj, pv_source_range,
- pv_dests_and_ranges, move_options, time_out):
+ pv_dests_and_ranges, move_options, job_state):
"""
Common code for the pvmove handling.
:param interface_name: What dbus interface we are providing for
@@ -85,8 +67,8 @@ def move(interface_name, lv_name, pv_src_obj, pv_source_range,
:param pv_source_range: (0,0 to ignore, else start, end segments)
:param pv_dests_and_ranges: Array of PV object paths and start/end segs
:param move_options: Hash with optional arguments
- :param time_out:
- :return: Object path to job object
+ :param job_state: Used to convey information about jobs between processes
+ :return: '/' When complete, the empty object path
"""
pv_dests = []
pv_src = cfg.om.get_object_by_path(pv_src_obj)
@@ -112,18 +94,18 @@ def move(interface_name, lv_name, pv_src_obj, pv_source_range,
pv_source_range,
pv_dests)
- return _move_merge(interface_name, cmd, time_out)
+ return _move_merge(interface_name, cmd, job_state)
else:
raise dbus.exceptions.DBusException(
interface_name, 'pv_src_obj (%s) not found' % pv_src_obj)
-def merge(interface_name, lv_uuid, lv_name, merge_options, time_out):
+def merge(interface_name, lv_uuid, lv_name, merge_options, job_state):
# Make sure we have a dbus object representing it
dbo = cfg.om.get_object_by_uuid_lvm_id(lv_uuid, lv_name)
if dbo:
cmd = lv_merge_cmd(merge_options, dbo.lvm_id)
- return _move_merge(interface_name, cmd, time_out)
+ return _move_merge(interface_name, cmd, job_state)
else:
raise dbus.exceptions.DBusException(
interface_name,
@@ -143,17 +125,6 @@ def background_reaper():
time.sleep(3)
-def process_background_result(job_object, exit_code, error_msg):
- cfg.load()
- job_object.set_result(exit_code, error_msg)
- return None
-
-
-# noinspection PyUnusedLocal
-def empty_cb(disregard):
- pass
-
-
def background_execute(command, background_job, skip_first_line=False):
# Wrap this whole operation in an exception handler, otherwise if we
@@ -181,23 +152,15 @@ def background_execute(command, background_job, skip_first_line=False):
if process.returncode == 0:
background_job.Percent = 100
- # Queue up the result so that it gets executed in same thread as others.
- r = RequestEntry(
- -1, process_background_result,
- (background_job, process.returncode, out[1]),
- empty_cb, empty_cb, False)
- cfg.worker_q.put(r)
+ background_job.set_result(process.returncode, out[1])
+
except Exception:
- # In the unlikely event that we blew up, lets notify fill out the
- # job object so that the client doesn't hang potentially forever!
+ # In the unlikely event that we blow up, we need to unblock caller which
+ # is waiting on an answer.
st = traceback.format_exc()
error = "Exception in background thread: \n%s" % st
log_error(error)
- r = RequestEntry(
- -1, process_background_result,
- (background_job, 1, error),
- empty_cb, empty_cb, False)
- cfg.worker_q.put(r)
+ background_job.set_result(1, error)
def add(command, reporting_job):
diff --git a/daemons/lvmdbusd/job.py b/daemons/lvmdbusd/job.py
index b16f8e6..d7f8187 100644
--- a/daemons/lvmdbusd/job.py
+++ b/daemons/lvmdbusd/job.py
@@ -17,7 +17,7 @@ import threading
# noinspection PyPep8Naming
class JobState(object):
- def __init__(self, request):
+ def __init__(self, request=None):
self.rlock = threading.RLock()
self._percent = 0
diff --git a/daemons/lvmdbusd/lv.py b/daemons/lvmdbusd/lv.py
index 5c7b3b5..8f063dc 100644
--- a/daemons/lvmdbusd/lv.py
+++ b/daemons/lvmdbusd/lv.py
@@ -22,6 +22,7 @@ from .loader import common
from .state import State
from . import background
from .utils import round_size
+from .job import JobState
# Try and build a key for a LV, so that we sort the LVs with least dependencies
@@ -444,14 +445,21 @@ class Lv(LvCommon):
@dbus.service.method(
dbus_interface=LV_INTERFACE,
in_signature='o(tt)a(ott)ia{sv}',
- out_signature='o')
+ out_signature='o',
+ async_callbacks=('cb', 'cbe'))
def Move(self, pv_src_obj, pv_source_range,
pv_dests_and_ranges,
- tmo, move_options):
- return background.move(
- LV_INTERFACE, self.lvm_id, pv_src_obj,
- pv_source_range, pv_dests_and_ranges,
- move_options, tmo)
+ tmo, move_options, cb, cbe):
+
+ job_state = JobState()
+
+ r = RequestEntry(
+ tmo, background.move,
+ (LV_INTERFACE, self.lvm_id, pv_src_obj, pv_source_range,
+ pv_dests_and_ranges, move_options, job_state), cb, cbe, False,
+ job_state)
+
+ cfg.worker_q.put(r)
@staticmethod
def _snap_shot(lv_uuid, lv_name, name, optional_size,
@@ -875,7 +883,13 @@ class LvSnapShot(Lv):
@dbus.service.method(
dbus_interface=SNAPSHOT_INTERFACE,
in_signature='ia{sv}',
- out_signature='o')
- def Merge(self, tmo, merge_options):
- return background.merge(SNAPSHOT_INTERFACE, self.Uuid, self.lvm_id,
- merge_options, tmo)
+ out_signature='o',
+ async_callbacks=('cb', 'cbe'))
+ def Merge(self, tmo, merge_options, cb, cbe):
+ job_state = JobState()
+
+ r = RequestEntry(tmo, background.merge,
+ (SNAPSHOT_INTERFACE, self.Uuid, self.lvm_id,
+ merge_options, job_state), cb, cbe, False,
+ job_state)
+ cfg.worker_q.put(r)
diff --git a/daemons/lvmdbusd/request.py b/daemons/lvmdbusd/request.py
index 3e29b82..ce6a6ef 100644
--- a/daemons/lvmdbusd/request.py
+++ b/daemons/lvmdbusd/request.py
@@ -18,7 +18,7 @@ from .utils import log_error
class RequestEntry(object):
def __init__(self, tmo, method, arguments, cb, cb_error,
- return_tuple=True):
+ return_tuple=True, job_state=None):
self.tmo = tmo
self.method = method
self.arguments = arguments
@@ -33,6 +33,7 @@ class RequestEntry(object):
self._rc = 0
self._rc_error = None
self._return_tuple = return_tuple
+ self._job_state = job_state
if self.tmo < 0:
# Client is willing to block forever
@@ -53,7 +54,7 @@ class RequestEntry(object):
r.timer_expired()
def _return_job(self):
- self._job = Job(self)
+ self._job = Job(self, self._job_state)
cfg.om.register_object(self._job, True)
if self._return_tuple:
self.cb(('/', self._job.dbus_object_path()))
diff --git a/daemons/lvmdbusd/vg.py b/daemons/lvmdbusd/vg.py
index c700667..4cc938e 100644
--- a/daemons/lvmdbusd/vg.py
+++ b/daemons/lvmdbusd/vg.py
@@ -20,6 +20,7 @@ from .loader import common
from .state import State
from . import background
from .utils import round_size
+from .job import JobState
# noinspection PyUnusedLocal
@@ -352,12 +353,20 @@ class Vg(AutomatedProperties):
@dbus.service.method(
dbus_interface=VG_INTERFACE,
in_signature='o(tt)a(ott)ia{sv}',
- out_signature='o')
+ out_signature='o',
+ async_callbacks=('cb', 'cbe'))
def Move(self, pv_src_obj, pv_source_range, pv_dests_and_ranges,
- tmo, move_options):
- return background.move(
- VG_INTERFACE, None, pv_src_obj, pv_source_range,
- pv_dests_and_ranges, move_options, tmo)
+ tmo, move_options, cb, cbe):
+
+ job_state = JobState()
+
+ r = RequestEntry(
+ tmo, background.move,
+ (VG_INTERFACE, None, pv_src_obj, pv_source_range,
+ pv_dests_and_ranges, move_options, job_state), cb, cbe, False,
+ job_state)
+
+ cfg.worker_q.put(r)
@staticmethod
def _lv_create(uuid, vg_name, name, size_bytes, pv_dests_and_ranges,
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=4b337b20d47953e1…
Commit: 4b337b20d47953e130edc8a456e9431eba58a778
Parent: e514284c65a7cffa24549a34612392731f6e06af
Author: Tony Asleson <tasleson(a)redhat.com>
AuthorDate: Mon Jun 6 15:08:20 2016 -0500
Committer: Tony Asleson <tasleson(a)redhat.com>
CommitterDate: Tue Jun 28 12:09:28 2016 -0500
lvmdbusd: Remove sorting in db layer
When using the JSON this does not yield a totally sorted list as we don't
have a complete set of LVs, so remove this sort.
---
daemons/lvmdbusd/lvmdb.py | 8 +-------
1 files changed, 1 insertions(+), 7 deletions(-)
diff --git a/daemons/lvmdbusd/lvmdb.py b/daemons/lvmdbusd/lvmdb.py
index 5ac90e3..f070bb6 100755
--- a/daemons/lvmdbusd/lvmdb.py
+++ b/daemons/lvmdbusd/lvmdb.py
@@ -245,16 +245,10 @@ class DataStore(object):
# Each item item in the report is a collection of information pertaining
# to the vg
for r in _all['report']:
- tmp_lv = []
# Get the lv data for this VG.
if 'lv' in r:
- tmp_lv.extend(r['lv'])
-
- # Sort them
- sorted_tmp_lv = sorted(tmp_lv, key=lambda vk: vk['lv_name'])
-
# Add them to result set
- for i in sorted_tmp_lv:
+ for i in r['lv']:
full_name = "%s/%s" % (i['vg_name'], i['lv_name'])
c_lv_full_lookup[full_name] = i['lv_uuid']
c_lvs[i['lv_uuid']] = i
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=6d0c49df5b466e3d…
Commit: 6d0c49df5b466e3d5f842272d76452fd2b9e5dec
Parent: 0000000000000000000000000000000000000000
Author: Alasdair G Kergon <agk(a)redhat.com>
AuthorDate: 2016-06-25 19:35 +0000
Committer: Alasdair G Kergon <agk(a)redhat.com>
CommitterDate: 2016-06-25 19:35 +0000
annotated tag: v2_02_158 has been created
at 6d0c49df5b466e3d5f842272d76452fd2b9e5dec (tag)
tagging 887f071b2545bb2b60e13de854898ab71a6b0ff5 (commit)
replaces v2_02_157
Release 2.02.158.
An interim development release incorporating major extensions to the reporting
code (including a json facility). The interface changes are not yet frozen.
The vgimportclone script is also replaced with a new built-in implementation.
133 files changed, 4796 insertions(+), 1818 deletions(-)
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.14 (GNU/Linux)
iEYEABECAAYFAldu3m8ACgkQIoGRwVZ+LBcy0gCg2xMhF+rYQSYsuztV/w3u6W3E
pP8An1UtPzdIRLbj3hmFBFFS97lV2aAl
=zD0Y
-----END PGP SIGNATURE-----
Alasdair G Kergon (7):
post-release
tools: Use arg_is_set instead of arg_count.
lvconvert: Refactor argument handling code.
lvconvert: Fix --stripes handling.
Revert "locking: trace errors from dir creation"
doc: Resync kernel docs.
pre-release
David Teigland (9):
lvmlockd: fix dropping PVs in rescanning VG
vgreduce: fix location of lvmlockd global lock
vgscan: fix process_each args
vgcfgrestore: use lvmetad disabled state
lvmetad: process new connections after shutdown signal
lvmlockd: always try to connect to lvmetad
vgcfgrestore: check for missing device
vgcfgrestore: rescan to reenable lvmetad on error path
vgimportclone: add native command
Peter Rajnoha (55):
libdm: report: introduce dm_report_group
libdm: report: implement DM_REPORT_GROUP_SINGLE for a group containing single report only
libdm: report: implement DM_REPORT_GROUP_BASIC for extended report output
libdm: report: implement DM_REPORT_GROUP_JSON for JSON report output
report: add CMDLOG report type
conf: add log/command_log_{sort,cols} config settings
toollib: add report_format_init fn to create report group and to create/add log report handle
conf: add report/output_format config setting
conf: add log/report_command_log config setting
report: separate common report and per-report args
toollib: add report_group and log_rh to processing_handle and initialize cmd processing log report
toollib: add 'parent' field to processing_handle; init report format only if there's no parent
report: add current report to existing group
commands: recognize --reportformat option for pvs,vgs,lvs and devtypes command
commands: recognize --reportformat option for other commands
commands: report: add lvm fullreport command
conf: add report/{vgs,pvs,lvs,pvsegs,segs}_{cols,sort}_full config settings
args: add priorities for grouping args
args: add --configreport arg
report: add _get_report_idx_from_name and _should_process_report_idx helper fns
report: recognize list of fields to report (-o|--options) for each subreport
report: recognize list of keys to sort report by (-O|--sort) for each subreport; make -O|--sort groupable
report: recognize selection (-S|--select) for each subreport; make -S|--select groupable
report: check report type and options used for full report's subreports
toollib: make it possible to also process internal VGs, add 'include_internal' switch to process_each_vg fn
log: log warnings and errors via report if set; add log_set_report* fns
report: add report_current_object_cmdlog fn as a shortcut for reporting current object's log item
log: also pass log_print through report and add log_print_bypass_report for use in libdm-report for direct print without report
libdm: report: remember special field to display selection status in struct row's field_sel_status variable
refactor: move field width calculation and sort preparation from _do_report_object to dm_report_output
libdm: report: add DM_REPORT_OUTPUT_MULTIPLE_TIMES report flag to keep report data even after output is done
libdm: report: add dm_report_set_selection
report: add 'multiple_output' arg to report_init
log: annotate processing code with log_set_report_{context,object_type,id_and_name}
log: annotate processing code with report_current_object_cmdlog
refactor: move 'interactive' field from struct command_line to struct cmd_context as 'is_interactive' switch
tools: add 'lvm lastlog' command for interactive query and display of last command's log
log: use separate 'orphan' report object type for orphan VGs
conf: add log/command_log_selection config setting
libdm: select: recognize special selection string 'all' as an alias for blank selection string
report: use report type description for report's name if using DM_REPORT_GROUP_BASIC output format
report: add --logonly arg to report only log for a command
conf: regenerate profile templates
commands: add --configreport arg for all relevant commands
report: compare --configreport value with basic report type
log: add 'label' log report object type; annotate process_each_label with log_set_report_object_{type, id_and_name} and report_log_ret_code
cleanup: log: use hex numbers instead of decimal for _LOG_*
conf: add more comments for new settings related to output format and log report
filters: add comments about internal filter position in filter chain
log: move original print_log code to _vprint_log and make print_log a wrapper over _vprint_log
libdm: log: remove log_print_bypass_report calls and register new print_log_libdm for libdm during lvm initialization instead
commands: fix typo in arg assignment
commands: help: add missing --reportformat references
man: document --configreport, --logonly, --reportformat
man: lvs: move doc about --all so it's ordered alphabetically in the man page
Zdenek Kabelac (26):
activation: switch to warning
activation: _lv_active returns 0 on error
monitoring: preserve monitoring status during update
locking: trace errors from dir creation
lvresize: move and extend resizefs ignoring check
lvresize: inform about ignored args with --use-polices
lvresize: drop extra sigint handling
cleanup: code lines reodered
cleanup: add dots to some messages
cleanup: use display_lvname
lvresize: update lvresize_params struct
lvresize: check pvh list is vg->pvs
lvresize: pass only needed params to _fsadm_cmd
lvresize: do not pass struct cmd
lvresize: support more resized LVs
lvresize: return 0/1
cleanup: remove unused sizearg variable
cleanup: remove unused code
cleanup: drop setting lv_name
tests: aux prepare_thin_metadata
lvresize: fixes for recent commit
lvresize: let pass even protected names like _tmeta
cleanup: type cleanup
tests: smaller number of devs created to fill metadata
tests: update test for modified output
cleanup: clean warns from older gcc
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=cc3e7c7c31de8d69…
Commit: cc3e7c7c31de8d69d9f1eb610181584482ee90a3
Parent: 5a327755b4cfe45b35863a2b4177a6b32c17642f
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Tue Jun 7 16:09:45 2016 -0500
Committer: Alasdair G Kergon <agk(a)redhat.com>
CommitterDate: Tue Jun 28 02:30:25 2016 +0100
lvmetad: remove unused code for other format types
lvmetad is no longer used at all with the lvm1 format,
so the text format is the only one that uses lvmetad.
---
lib/metadata/metadata.c | 7 -------
1 files changed, 0 insertions(+), 7 deletions(-)
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index 9b1fd31..e55463b 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -3546,13 +3546,6 @@ int vg_write(struct volume_group *vg)
if (!_vg_update_vg_precommitted(vg)) /* prepare precommited */
return_0;
- /*
- * If precommit is not supported, changes take effect immediately.
- * FIXME Replace with a more-accurate FMT_COMMIT flag.
- */
- if (!(vg->fid->fmt->features & FMT_PRECOMMIT) && !lvmetad_vg_update(vg))
- return_0;
-
lockd_vg_update(vg);
return 1;
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=5a327755b4cfe45b…
Commit: 5a327755b4cfe45b35863a2b4177a6b32c17642f
Parent: 17ad29ebba4ba1a9361cd424ad1f58e89418a986
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Mon Jun 27 11:10:58 2016 -0500
Committer: Alasdair G Kergon <agk(a)redhat.com>
CommitterDate: Tue Jun 28 02:28:57 2016 +0100
WHATS_NEW: add recent changes
---
WHATS_NEW | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index 4b074a6..cfa707f 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -3,6 +3,12 @@ Version 2.02.159 -
Version 2.02.158 - 25th June 2016
=================================
+ Add a more efficient native vgimportclone command to replace the script.
+ Make lvmlockd always attempt to connect to lvmetad if no connection exists.
+ Let lvmetad handle new connections after shutdown signal.
+ Disable lvmetad when vgcfgrestore begins and enable it again after.
+ Make pvscan do activation if lvmetad is configured but not running.
+ Fix rescanning the PVs for a single VG when using lvmetad.
Pool metadata lvresize uses now same code as resize of normal volume.
Preserve monitoring status when updating thin-pool metadata.
Return 0 (inactive) when status cannot be queried in _lv_active().
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=887f071b2545bb2b…
Commit: 887f071b2545bb2b60e13de854898ab71a6b0ff5
Parent: 15b932a70e4a29f386ea57e1b845d637780b463b
Author: Alasdair G Kergon <agk(a)redhat.com>
AuthorDate: Sat Jun 25 20:35:14 2016 +0100
Committer: Alasdair G Kergon <agk(a)redhat.com>
CommitterDate: Sat Jun 25 20:35:14 2016 +0100
pre-release
---
VERSION | 2 +-
VERSION_DM | 2 +-
WHATS_NEW | 5 ++++-
WHATS_NEW_DM | 2 +-
4 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/VERSION b/VERSION
index 34e00b1..8cb5c44 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.02.158(2)-git (2016-06-17)
+2.02.158(2)-git (2016-06-25)
diff --git a/VERSION_DM b/VERSION_DM
index dd57819..389871f 100644
--- a/VERSION_DM
+++ b/VERSION_DM
@@ -1 +1 @@
-1.02.128-git (2016-06-17)
+1.02.128-git (2016-06-25)
diff --git a/WHATS_NEW b/WHATS_NEW
index 7238568..530ece8 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,10 +1,13 @@
-Version 2.02.158 -
+Version 2.02.158 - 25th June 2016
=================================
Pool metadata lvresize uses now same code as resize of normal volume.
Preserve monitoring status when updating thin-pool metadata.
Return 0 (inactive) when status cannot be queried in _lv_active().
Switch to log_warn() for failing activation status query.
+ Replace vgimportclone script with binary.
+ While lvmetad is shutting down, continue handling all connections cleanly.
Refactor lvconvert argument handling code.
+ Notify lvmetad when vgcfgrestore changes VG metadata.
Add --logonly option to report only cmd log for a command, not other reports.
Add log/command_log_selection to configure default selection used on cmd log.
Use 'orphan' object type in cmd log for groups to collect PVs not yet in VGs.
diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM
index 8911e36..a03308b 100644
--- a/WHATS_NEW_DM
+++ b/WHATS_NEW_DM
@@ -1,4 +1,4 @@
-Version 1.02.128 -
+Version 1.02.128 - 25th June 2016
=================================
Recognize 'all' keyword used in selection as synonym for "" (no selection).
Add dm_report_set_selection to set selection for multiple output of report.
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=e6c376ee2dae4539…
Commit: e6c376ee2dae4539b1cc38ed6d9c5430777d2753
Parent: 8eebb4bfb901caa5330676697557943fdb9733a5
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Tue Jun 7 16:09:45 2016 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Mon Jun 27 11:16:35 2016 -0500
lvmetad: remove unused code for other format types
lvmetad is no longer used at all with the lvm1 format,
so the text format is the only one that uses lvmetad.
---
lib/metadata/metadata.c | 7 -------
1 files changed, 0 insertions(+), 7 deletions(-)
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index 9b1fd31..e55463b 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -3546,13 +3546,6 @@ int vg_write(struct volume_group *vg)
if (!_vg_update_vg_precommitted(vg)) /* prepare precommited */
return_0;
- /*
- * If precommit is not supported, changes take effect immediately.
- * FIXME Replace with a more-accurate FMT_COMMIT flag.
- */
- if (!(vg->fid->fmt->features & FMT_PRECOMMIT) && !lvmetad_vg_update(vg))
- return_0;
-
lockd_vg_update(vg);
return 1;
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=8eebb4bfb901caa5…
Commit: 8eebb4bfb901caa5330676697557943fdb9733a5
Parent: 20f22a8bc0fa84d9abd09f580b93d53d37c4c361
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Mon Jun 27 11:10:58 2016 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Mon Jun 27 11:10:58 2016 -0500
WHATS_NEW: add recent changes
---
WHATS_NEW | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index 7238568..7a1f3cb 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,11 @@
Version 2.02.158 -
=================================
+ Add a more efficient native vgimportclone command to replace the script.
+ Make lvmlockd always attempt to connect to lvmetad if no connection exists.
+ Let lvmetad handle new connections after shutdown signal.
+ Disable lvmetad when vgcfgrestore begins and enable it again after.
+ Make pvscan do activation if lvmetad is configured but not running.
+ Fix rescanning the PVs for a single VG when using lvmetad.
Pool metadata lvresize uses now same code as resize of normal volume.
Preserve monitoring status when updating thin-pool metadata.
Return 0 (inactive) when status cannot be queried in _lv_active().
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=15b932a70e4a29f3…
Commit: 15b932a70e4a29f386ea57e1b845d637780b463b
Parent: d914151591dab4ac924fe3b72fb296bc66f2e51c
Author: Alasdair G Kergon <agk(a)redhat.com>
AuthorDate: Sat Jun 25 19:59:49 2016 +0100
Committer: Alasdair G Kergon <agk(a)redhat.com>
CommitterDate: Sat Jun 25 19:59:49 2016 +0100
doc: Resync kernel docs.
---
doc/kernel/cache-policies.txt | 102 +++++++++++++++++++++++--------------
doc/kernel/cache.txt | 15 +++++-
doc/kernel/delay.txt | 1 +
doc/kernel/raid.txt | 33 ++++++++++++
doc/kernel/snapshot.txt | 10 +++-
doc/kernel/statistics.txt | 47 ++++++++++++++++--
doc/kernel/thin-provisioning.txt | 9 +++-
doc/kernel/verity.txt | 40 ++++++++++++++-
8 files changed, 205 insertions(+), 52 deletions(-)
diff --git a/doc/kernel/cache-policies.txt b/doc/kernel/cache-policies.txt
index 0d124a9..d3ca8af 100644
--- a/doc/kernel/cache-policies.txt
+++ b/doc/kernel/cache-policies.txt
@@ -11,7 +11,7 @@ Every bio that is mapped by the target is referred to the policy.
The policy can return a simple HIT or MISS or issue a migration.
Currently there's no way for the policy to issue background work,
-e.g. to start writing back dirty blocks that are going to be evicte
+e.g. to start writing back dirty blocks that are going to be evicted
soon.
Because we map bios, rather than requests it's easy for the policy
@@ -25,53 +25,77 @@ trying to see when the io scheduler has let the ios run.
Overview of supplied cache replacement policies
===============================================
-multiqueue
-----------
+multiqueue (mq)
+---------------
-This policy is the default.
-
-The multiqueue policy has three sets of 16 queues: one set for entries
-waiting for the cache and another two for those in the cache (a set for
-clean entries and a set for dirty entries).
+This policy is now an alias for smq (see below).
-Cache entries in the queues are aged based on logical time. Entry into
-the cache is based on variable thresholds and queue selection is based
-on hit count on entry. The policy aims to take different cache miss
-costs into account and to adjust to varying load patterns automatically.
+The following tunables are accepted, but have no effect:
-Message and constructor argument pairs are:
'sequential_threshold <#nr_sequential_ios>'
'random_threshold <#nr_random_ios>'
'read_promote_adjustment <value>'
'write_promote_adjustment <value>'
'discard_promote_adjustment <value>'
-The sequential threshold indicates the number of contiguous I/Os
-required before a stream is treated as sequential. Once a stream is
-considered sequential it will bypass the cache. The random threshold
-is the number of intervening non-contiguous I/Os that must be seen
-before the stream is treated as random again.
-
-The sequential and random thresholds default to 512 and 4 respectively.
-
-Large, sequential I/Os are probably better left on the origin device
-since spindles tend to have good sequential I/O bandwidth. The
-io_tracker counts contiguous I/Os to try to spot when the I/O is in one
-of these sequential modes. But there are use-cases for wanting to
-promote sequential blocks to the cache (e.g. fast application startup).
-If sequential threshold is set to 0 the sequential I/O detection is
-disabled and sequential I/O will no longer implicitly bypass the cache.
-Setting the random threshold to 0 does _not_ disable the random I/O
-stream detection.
-
-Internally the mq policy determines a promotion threshold. If the hit
-count of a block not in the cache goes above this threshold it gets
-promoted to the cache. The read, write and discard promote adjustment
-tunables allow you to tweak the promotion threshold by adding a small
-value based on the io type. They default to 4, 8 and 1 respectively.
-If you're trying to quickly warm a new cache device you may wish to
-reduce these to encourage promotion. Remember to switch them back to
-their defaults after the cache fills though.
+Stochastic multiqueue (smq)
+---------------------------
+
+This policy is the default.
+
+The stochastic multi-queue (smq) policy addresses some of the problems
+with the multiqueue (mq) policy.
+
+The smq policy (vs mq) offers the promise of less memory utilization,
+improved performance and increased adaptability in the face of changing
+workloads. smq also does not have any cumbersome tuning knobs.
+
+Users may switch from "mq" to "smq" simply by appropriately reloading a
+DM table that is using the cache target. Doing so will cause all of the
+mq policy's hints to be dropped. Also, performance of the cache may
+degrade slightly until smq recalculates the origin device's hotspots
+that should be cached.
+
+Memory usage:
+The mq policy used a lot of memory; 88 bytes per cache block on a 64
+bit machine.
+
+smq uses 28bit indexes to implement it's data structures rather than
+pointers. It avoids storing an explicit hit count for each block. It
+has a 'hotspot' queue, rather than a pre-cache, which uses a quarter of
+the entries (each hotspot block covers a larger area than a single
+cache block).
+
+All this means smq uses ~25bytes per cache block. Still a lot of
+memory, but a substantial improvement nontheless.
+
+Level balancing:
+mq placed entries in different levels of the multiqueue structures
+based on their hit count (~ln(hit count)). This meant the bottom
+levels generally had the most entries, and the top ones had very
+few. Having unbalanced levels like this reduced the efficacy of the
+multiqueue.
+
+smq does not maintain a hit count, instead it swaps hit entries with
+the least recently used entry from the level above. The overall
+ordering being a side effect of this stochastic process. With this
+scheme we can decide how many entries occupy each multiqueue level,
+resulting in better promotion/demotion decisions.
+
+Adaptability:
+The mq policy maintained a hit count for each cache block. For a
+different block to get promoted to the cache it's hit count has to
+exceed the lowest currently in the cache. This meant it could take a
+long time for the cache to adapt between varying IO patterns.
+
+smq doesn't maintain hit counts, so a lot of this problem just goes
+away. In addition it tracks performance of the hotspot queue, which
+is used to decide which blocks to promote. If the hotspot queue is
+performing badly then it starts moving entries more quickly between
+levels. This lets it adapt to new IO patterns very quickly.
+
+Performance:
+Testing smq shows substantially better performance than mq.
cleaner
-------
diff --git a/doc/kernel/cache.txt b/doc/kernel/cache.txt
index 68c0f51..785eab8 100644
--- a/doc/kernel/cache.txt
+++ b/doc/kernel/cache.txt
@@ -221,6 +221,7 @@ Status
<#read hits> <#read misses> <#write hits> <#write misses>
<#demotions> <#promotions> <#dirty> <#features> <features>*
<#core args> <core args>* <policy name> <#policy args> <policy args>*
+<cache metadata mode>
metadata block size : Fixed block size for each metadata block in
sectors
@@ -251,8 +252,18 @@ core args : Key/value pairs for tuning the core
e.g. migration_threshold
policy name : Name of the policy
#policy args : Number of policy arguments to follow (must be even)
-policy args : Key/value pairs
- e.g. sequential_threshold
+policy args : Key/value pairs e.g. sequential_threshold
+cache metadata mode : ro if read-only, rw if read-write
+ In serious cases where even a read-only mode is deemed unsafe
+ no further I/O will be permitted and the status will just
+ contain the string 'Fail'. The userspace recovery tools
+ should then be used.
+needs_check : 'needs_check' if set, '-' if not set
+ A metadata operation has failed, resulting in the needs_check
+ flag being set in the metadata's superblock. The metadata
+ device must be deactivated and checked/repaired before the
+ cache can be made fully operational again. '-' indicates
+ needs_check is not set.
Messages
--------
diff --git a/doc/kernel/delay.txt b/doc/kernel/delay.txt
index 15adc55..a07b592 100644
--- a/doc/kernel/delay.txt
+++ b/doc/kernel/delay.txt
@@ -8,6 +8,7 @@ Parameters:
<device> <offset> <delay> [<write_device> <write_offset> <write_delay>]
With separate write parameters, the first set is only used for reads.
+Offsets are specified in sectors.
Delays are specified in milliseconds.
Example scripts
diff --git a/doc/kernel/raid.txt b/doc/kernel/raid.txt
index ef8ba9f..df2d636 100644
--- a/doc/kernel/raid.txt
+++ b/doc/kernel/raid.txt
@@ -209,6 +209,37 @@ include:
"repair" - Initiate a repair of the array.
"reshape"- Currently unsupported (-EINVAL).
+
+Discard Support
+---------------
+The implementation of discard support among hardware vendors varies.
+When a block is discarded, some storage devices will return zeroes when
+the block is read. These devices set the 'discard_zeroes_data'
+attribute. Other devices will return random data. Confusingly, some
+devices that advertise 'discard_zeroes_data' will not reliably return
+zeroes when discarded blocks are read! Since RAID 4/5/6 uses blocks
+from a number of devices to calculate parity blocks and (for performance
+reasons) relies on 'discard_zeroes_data' being reliable, it is important
+that the devices be consistent. Blocks may be discarded in the middle
+of a RAID 4/5/6 stripe and if subsequent read results are not
+consistent, the parity blocks may be calculated differently at any time;
+making the parity blocks useless for redundancy. It is important to
+understand how your hardware behaves with discards if you are going to
+enable discards with RAID 4/5/6.
+
+Since the behavior of storage devices is unreliable in this respect,
+even when reporting 'discard_zeroes_data', by default RAID 4/5/6
+discard support is disabled -- this ensures data integrity at the
+expense of losing some performance.
+
+Storage devices that properly support 'discard_zeroes_data' are
+increasingly whitelisted in the kernel and can thus be trusted.
+
+For trusted devices, the following dm-raid module parameter can be set
+to safely enable discard support for RAID 4/5/6:
+ 'devices_handle_discards_safely'
+
+
Version History
---------------
1.0.0 Initial version. Support for RAID 4/5/6
@@ -224,3 +255,5 @@ Version History
New status (STATUSTYPE_INFO) fields: sync_action and mismatch_cnt.
1.5.1 Add ability to restore transiently failed devices on resume.
1.5.2 'mismatch_cnt' is zero unless [last_]sync_action is "check".
+1.6.0 Add discard support (and devices_handle_discard_safely module param).
+1.7.0 Add support for MD RAID0 mappings.
diff --git a/doc/kernel/snapshot.txt b/doc/kernel/snapshot.txt
index 0d5bc46..ad6949b 100644
--- a/doc/kernel/snapshot.txt
+++ b/doc/kernel/snapshot.txt
@@ -41,9 +41,13 @@ useless and be disabled, returning errors. So it is important to monitor
the amount of free space and expand the <COW device> before it fills up.
<persistent?> is P (Persistent) or N (Not persistent - will not survive
-after reboot).
-The difference is that for transient snapshots less metadata must be
-saved on disk - they can be kept in memory by the kernel.
+after reboot). O (Overflow) can be added as a persistent store option
+to allow userspace to advertise its support for seeing "Overflow" in the
+snapshot status. So supported store types are "P", "PO" and "N".
+
+The difference between persistent and transient is with transient
+snapshots less metadata must be saved on disk - they can be kept in
+memory by the kernel.
* snapshot-merge <origin> <COW device> <persistent> <chunksize>
diff --git a/doc/kernel/statistics.txt b/doc/kernel/statistics.txt
index 2a1673a..170ac02 100644
--- a/doc/kernel/statistics.txt
+++ b/doc/kernel/statistics.txt
@@ -13,9 +13,14 @@ the range specified.
The I/O statistics counters for each step-sized area of a region are
in the same format as /sys/block/*/stat or /proc/diskstats (see:
Documentation/iostats.txt). But two extra counters (12 and 13) are
-provided: total time spent reading and writing in milliseconds. All
-these counters may be accessed by sending the @stats_print message to
-the appropriate DM device via dmsetup.
+provided: total time spent reading and writing. When the histogram
+argument is used, the 14th parameter is reported that represents the
+histogram of latencies. All these counters may be accessed by sending
+the @stats_print message to the appropriate DM device via dmsetup.
+
+The reported times are in milliseconds and the granularity depends on
+the kernel ticks. When the option precise_timestamps is used, the
+reported times are in nanoseconds.
Each region has a corresponding unique identifier, which we call a
region_id, that is assigned when the region is created. The region_id
@@ -33,7 +38,9 @@ memory is used by reading
Messages
========
- @stats_create <range> <step> [<program_id> [<aux_data>]]
+ @stats_create <range> <step>
+ [<number_of_optional_arguments> <optional_arguments>...]
+ [<program_id> [<aux_data>]]
Create a new region and return the region_id.
@@ -48,6 +55,29 @@ Messages
"/<number_of_areas>" - the range is subdivided into the specified
number of areas.
+ <number_of_optional_arguments>
+ The number of optional arguments
+
+ <optional_arguments>
+ The following optional arguments are supported
+ precise_timestamps - use precise timer with nanosecond resolution
+ instead of the "jiffies" variable. When this argument is
+ used, the resulting times are in nanoseconds instead of
+ milliseconds. Precise timestamps are a little bit slower
+ to obtain than jiffies-based timestamps.
+ histogram:n1,n2,n3,n4,... - collect histogram of latencies. The
+ numbers n1, n2, etc are times that represent the boundaries
+ of the histogram. If precise_timestamps is not used, the
+ times are in milliseconds, otherwise they are in
+ nanoseconds. For each range, the kernel will report the
+ number of requests that completed within this range. For
+ example, if we use "histogram:10,20,30", the kernel will
+ report four numbers a:b:c:d. a is the number of requests
+ that took 0-10 ms to complete, b is the number of requests
+ that took 10-20 ms to complete, c is the number of requests
+ that took 20-30 ms to complete and d is the number of
+ requests that took more than 30 ms to complete.
+
<program_id>
An optional parameter. A name that uniquely identifies
the userspace owner of the range. This groups ranges together
@@ -55,6 +85,9 @@ Messages
created and ignore those created by others.
The kernel returns this string back in the output of
@stats_list message, but it doesn't use it for anything else.
+ If we omit the number of optional arguments, program id must not
+ be a number, otherwise it would be interpreted as the number of
+ optional arguments.
<aux_data>
An optional parameter. A word that provides auxiliary data
@@ -88,6 +121,10 @@ Messages
Output format:
<region_id>: <start_sector>+<length> <step> <program_id> <aux_data>
+ precise_timestamps histogram:n1,n2,n3,...
+
+ The strings "precise_timestamps" and "histogram" are printed only
+ if they were specified when creating the region.
@stats_print <region_id> [<starting_line> <number_of_lines>]
@@ -168,7 +205,7 @@ statistics on them:
dmsetup message vol 0 @stats_create - /100
-Set the auxillary data string to "foo bar baz" (the escape for each
+Set the auxiliary data string to "foo bar baz" (the escape for each
space must also be escaped, otherwise the shell will consume them):
dmsetup message vol 0 @stats_set_aux 0 foo\\ bar\\ baz
diff --git a/doc/kernel/thin-provisioning.txt b/doc/kernel/thin-provisioning.txt
index 4f67578..1699a55 100644
--- a/doc/kernel/thin-provisioning.txt
+++ b/doc/kernel/thin-provisioning.txt
@@ -296,7 +296,7 @@ ii) Status
underlying device. When this is enabled when loading the table,
it can get disabled if the underlying device doesn't support it.
- ro|rw
+ ro|rw|out_of_data_space
If the pool encounters certain types of device failures it will
drop into a read-only metadata mode in which no changes to
the pool metadata (like allocating new blocks) are permitted.
@@ -314,6 +314,13 @@ ii) Status
module parameter can be used to change this timeout -- it
defaults to 60 seconds but may be disabled using a value of 0.
+ needs_check
+ A metadata operation has failed, resulting in the needs_check
+ flag being set in the metadata's superblock. The metadata
+ device must be deactivated and checked/repaired before the
+ thin-pool can be made fully operational again. '-' indicates
+ needs_check is not set.
+
iii) Messages
create_thin <dev id>
diff --git a/doc/kernel/verity.txt b/doc/kernel/verity.txt
index e15bc1a..89fd8f9 100644
--- a/doc/kernel/verity.txt
+++ b/doc/kernel/verity.txt
@@ -18,11 +18,11 @@ Construction Parameters
0 is the original format used in the Chromium OS.
The salt is appended when hashing, digests are stored continuously and
- the rest of the block is padded with zeros.
+ the rest of the block is padded with zeroes.
1 is the current format that should be used for new devices.
The salt is prepended when hashing and each digest is
- padded with zeros to the power of two.
+ padded with zeroes to the power of two.
<dev>
This is the device containing data, the integrity of which needs to be
@@ -79,6 +79,37 @@ restart_on_corruption
not compatible with ignore_corruption and requires user space support to
avoid restart loops.
+ignore_zero_blocks
+ Do not verify blocks that are expected to contain zeroes and always return
+ zeroes instead. This may be useful if the partition contains unused blocks
+ that are not guaranteed to contain zeroes.
+
+use_fec_from_device <fec_dev>
+ Use forward error correction (FEC) to recover from corruption if hash
+ verification fails. Use encoding data from the specified device. This
+ may be the same device where data and hash blocks reside, in which case
+ fec_start must be outside data and hash areas.
+
+ If the encoding data covers additional metadata, it must be accessible
+ on the hash device after the hash blocks.
+
+ Note: block sizes for data and hash devices must match. Also, if the
+ verity <dev> is encrypted the <fec_dev> should be too.
+
+fec_roots <num>
+ Number of generator roots. This equals to the number of parity bytes in
+ the encoding data. For example, in RS(M, N) encoding, the number of roots
+ is M-N.
+
+fec_blocks <num>
+ The number of encoding data blocks on the FEC device. The block size for
+ the FEC device is <data_block_size>.
+
+fec_start <offset>
+ This is the offset, in <data_block_size> blocks, from the start of the
+ FEC device to the beginning of the encoding data.
+
+
Theory of operation
===================
@@ -98,6 +129,11 @@ per-block basis. This allows for a lightweight hash computation on first read
into the page cache. Block hashes are stored linearly, aligned to the nearest
block size.
+If forward error correction (FEC) support is enabled any recovery of
+corrupted data will be verified using the cryptographic hash of the
+corresponding data. This is why combining error correction with
+integrity checking is essential.
+
Hash Tree
---------
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=d914151591dab4ac…
Commit: d914151591dab4ac924fe3b72fb296bc66f2e51c
Parent: a910052a2e7da4531ff0e39e569ab2eaa56b1870
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Fri Jun 24 14:56:43 2016 +0200
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Fri Jun 24 14:57:09 2016 +0200
man: lvs: move doc about --all so it's ordered alphabetically in the man page
---
man/lvs.8.in | 20 ++++++++++----------
1 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/man/lvs.8.in b/man/lvs.8.in
index 7bd25a6..3cb2d2b 100644
--- a/man/lvs.8.in
+++ b/man/lvs.8.in
@@ -53,6 +53,16 @@ for common options.
.B \-\-aligned
Use with \fB\-\-separator\fP to align the output columns.
.TP
+.B \-\-all
+Include information in the output about internal Logical Volumes that
+are components of normally-accessible Logical Volumes, such as mirrors,
+but which are not independently accessible (e.g. not mountable).
+The names of such Logical Volumes are enclosed within square brackets
+in the output. For example, after creating a mirror using
+.B lvcreate -m1 \-\-mirrorlog disk
+, this option will reveal three internal Logical
+Volumes, with suffixes mimage_0, mimage_1, and mlog.
+.TP
.B \-\-binary
Use binary values "0" or "1" instead of descriptive literal values
for columns that have exactly two valid values to report (not counting
@@ -67,16 +77,6 @@ command's main report is assumed. The log report is available only if
enabled by \fBlog/report_command_log\fP \fBlvm.conf\fP(5) setting or
if \fB\-\-logonly\fP option is used.
.TP
-.B \-\-all
-Include information in the output about internal Logical Volumes that
-are components of normally-accessible Logical Volumes, such as mirrors,
-but which are not independently accessible (e.g. not mountable).
-The names of such Logical Volumes are enclosed within square brackets
-in the output. For example, after creating a mirror using
-.B lvcreate -m1 \-\-mirrorlog disk
-, this option will reveal three internal Logical
-Volumes, with suffixes mimage_0, mimage_1, and mlog.
-.TP
.B \-H ", " \-\-history
Include historical logical volumes in the output.
(This has no effect unless logical volumes were removed while the configuration
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=e99a31c9502a2081…
Commit: e99a31c9502a2081c6608a831b601081008cc3b0
Parent: a67a5d465576d4a7c17b22a737725d6dee059e18
Author: Alasdair G Kergon <agk(a)redhat.com>
AuthorDate: Thu Jun 23 21:31:49 2016 +0100
Committer: Alasdair G Kergon <agk(a)redhat.com>
CommitterDate: Thu Jun 23 21:31:49 2016 +0100
Revert "locking: trace errors from dir creation"
This reverts commit fa69ed0bc845df3d2c7ae68d03cdd4a3dec339d8.
This code sometimes expects to be presented with a read-only filesystem
(during some boot sequences for example) and copes appropriately with
this and it should not lead to expected error messages that might cause
unnecessary alarm.
---
WHATS_NEW | 3 +--
lib/locking/file_locking.c | 6 ++----
2 files changed, 3 insertions(+), 6 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index a24325f..7238568 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,9 +1,8 @@
Version 2.02.158 -
=================================
Pool metadata lvresize uses now same code as resize of normal volume.
- Log system error when locking dir cannot be accessed.
Preserve monitoring status when updating thin-pool metadata.
- Rerurn 0 (inactive) when status cannot be queried in _lv_active().
+ Return 0 (inactive) when status cannot be queried in _lv_active().
Switch to log_warn() for failing activation status query.
Refactor lvconvert argument handling code.
Add --logonly option to report only cmd log for a command, not other reports.
diff --git a/lib/locking/file_locking.c b/lib/locking/file_locking.c
index 390f49f..230303b 100644
--- a/lib/locking/file_locking.c
+++ b/lib/locking/file_locking.c
@@ -158,13 +158,11 @@ int init_file_locking(struct locking_type *locking, struct cmd_context *cmd,
(void) dm_prepare_selinux_context(NULL, 0);
if (!r)
- return_0;
+ return 0;
/* Trap a read-only file system */
- if ((access(_lock_dir, R_OK | W_OK | X_OK) == -1) && (errno == EROFS)) {
- log_sys_error("access", _lock_dir);
+ if ((access(_lock_dir, R_OK | W_OK | X_OK) == -1) && (errno == EROFS))
return 0;
- }
return 1;
}
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=d578d8d3a1bbf5d2…
Commit: d578d8d3a1bbf5d20151ed8bc33caa307e2c7292
Parent: 58d414f7f5d998e32234e7a6c2d6c9d0ad38f996
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Tue Jun 14 13:40:57 2016 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Thu Jun 23 14:57:08 2016 +0200
lvresize: inform about ignored args with --use-polices
When --use-polices is specified, all size args are meaningless,
as the resize is based upon policy. So just keep user informed.
---
tools/lvresize.c | 9 +++++++++
1 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/tools/lvresize.c b/tools/lvresize.c
index fe200d4..9fb35bd 100644
--- a/tools/lvresize.c
+++ b/tools/lvresize.c
@@ -37,6 +37,15 @@ static int _lvresize_params(struct cmd_context *cmd, int argc, char **argv,
lp->extents = 0;
lp->sign = SIGN_PLUS;
lp->percent = PERCENT_LV;
+
+ if (arg_from_list_is_set(cmd, NULL,
+ chunksize_ARG, extents_ARG,
+ poolmetadatasize_ARG,
+ regionsize_ARG,
+ size_ARG,
+ stripes_ARG, stripesize_ARG,
+ -1))
+ log_print_unless_silent("Ignoring size parameters with --use-policies.");
} else {
/*
* Allow omission of extents and size if the user has given us
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=dc8c5c1886ea7c09…
Commit: dc8c5c1886ea7c090a3bfa96de8f22ca060614ec
Parent: eb51be4fbee95d76b53e5255242a8032c3028aa2
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Wed Jun 22 23:21:27 2016 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Thu Jun 23 14:56:10 2016 +0200
monitoring: preserve monitoring status during update
Ignore monitoring during whole update (suspend/resume) of thin-pool.
---
WHATS_NEW | 1 +
lib/metadata/thin_manip.c | 21 +++++++++++++--------
2 files changed, 14 insertions(+), 8 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index 7cd46d1..e61fbb2 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.158 -
=================================
+ Preserve monitoring status when updating thin-pool metadata.
Rerurn 0 (inactive) when status cannot be queried in _lv_active().
Switch to log_warn() for failing activation status query.
Refactor lvconvert argument handling code.
diff --git a/lib/metadata/thin_manip.c b/lib/metadata/thin_manip.c
index aa5f388..0d850d6 100644
--- a/lib/metadata/thin_manip.c
+++ b/lib/metadata/thin_manip.c
@@ -451,9 +451,15 @@ int update_pool_lv(struct logical_volume *lv, int activate)
if (activate) {
/* If the pool is not active, do activate deactivate */
+ monitored = dmeventd_monitor_mode();
+ init_dmeventd_monitor(DMEVENTD_MONITOR_IGNORE);
if (!lv_is_active(lv)) {
- monitored = dmeventd_monitor_mode();
- init_dmeventd_monitor(DMEVENTD_MONITOR_IGNORE);
+ /*
+ * FIXME:
+ * Rewrite activation code to handle whole tree of thinLVs
+ * as this version has major problem when it does not know
+ * which Node has pool active.
+ */
if (!activate_lv_excl(lv->vg->cmd, lv)) {
init_dmeventd_monitor(monitored);
return_0;
@@ -481,13 +487,12 @@ int update_pool_lv(struct logical_volume *lv, int activate)
}
}
- if (activate) {
- if (!deactivate_lv(lv->vg->cmd, lv)) {
- log_error("Failed to deactivate %s.", display_lvname(lv));
- ret = 0;
- }
- init_dmeventd_monitor(monitored);
+ if (activate &&
+ !deactivate_lv(lv->vg->cmd, lv)) {
+ log_error("Failed to deactivate %s.", display_lvname(lv));
+ ret = 0;
}
+ init_dmeventd_monitor(monitored);
/* Unlock memory if possible */
memlock_unlock(lv->vg->cmd);
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=eb51be4fbee95d76…
Commit: eb51be4fbee95d76b53e5255242a8032c3028aa2
Parent: af36f5ad369ebf4c1d768145a827436ccef22f63
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Wed Jun 22 23:04:53 2016 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Thu Jun 23 14:55:35 2016 +0200
activation: _lv_active returns 0 on error
We have only 2 users of _lv_active() - one was already checking for ==1
while the other use (_lv_is_active()) could have take '-1' as a sign of having
an LV active. So return 0 and log_debug also the reason while detection
has failed (i.e. in case --driverload n - it's kind of expectable,
but might have confused user seeing just <backtrace>).
---
WHATS_NEW | 1 +
lib/activate/activate.c | 6 ++++--
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index 6788e6a..7cd46d1 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.158 -
=================================
+ Rerurn 0 (inactive) when status cannot be queried in _lv_active().
Switch to log_warn() for failing activation status query.
Refactor lvconvert argument handling code.
Add --logonly option to report only cmd log for a command, not other reports.
diff --git a/lib/activate/activate.c b/lib/activate/activate.c
index 8892a2a..7f5d36f 100644
--- a/lib/activate/activate.c
+++ b/lib/activate/activate.c
@@ -1266,8 +1266,10 @@ static int _lv_active(struct cmd_context *cmd, const struct logical_volume *lv)
struct lvinfo info;
if (!lv_info(cmd, lv, 0, &info, 0, 0)) {
- stack;
- return -1;
+ log_debug("Cannot determine activation status of %s%s.",
+ display_lvname(lv),
+ activation() ? "" : " (no device driver)");
+ return 0;
}
return info.exists;
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=af36f5ad369ebf4c…
Commit: af36f5ad369ebf4c1d768145a827436ccef22f63
Parent: 751163a74375cc3bfc9f338f1317f14a23798812
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Tue Jun 21 15:16:03 2016 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Thu Jun 23 14:53:59 2016 +0200
activation: switch to warning
Since this function does not have a way to return error use correct
reporting level as warning.
---
WHATS_NEW | 1 +
lib/activate/activate.c | 4 ++--
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index ce77b6c..6788e6a 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.158 -
=================================
+ Switch to log_warn() for failing activation status query.
Refactor lvconvert argument handling code.
Add --logonly option to report only cmd log for a command, not other reports.
Add log/command_log_selection to configure default selection used on cmd log.
diff --git a/lib/activate/activate.c b/lib/activate/activate.c
index 089af53..8892a2a 100644
--- a/lib/activate/activate.c
+++ b/lib/activate/activate.c
@@ -1454,9 +1454,9 @@ static int _lv_is_active(const struct logical_volume *lv,
* Old users of this function will never be affected by this,
* since they are only concerned about active vs. not active.
* New users of this function who specifically ask for 'exclusive'
- * will be given an error message.
+ * will be given a warning message.
*/
- log_error("Unable to determine exclusivity of %s.", display_lvname(lv));
+ log_warn("WARNING: Unable to determine exclusivity of %s.", display_lvname(lv));
e = 0;
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=f96de674905cd9f1…
Commit: f96de674905cd9f109cd19e03ba5e92ac84104b8
Parent: 47a29f6b2eb78a71ba6eafa9f47c7519a629155f
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Mon Jun 20 16:02:07 2016 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Mon Jun 20 16:02:07 2016 -0500
vgcfgrestore: check for missing device
The missing device will generally be seen earlier
and cause the command to not reach this point, but
check anyway for completeness.
---
lib/format_text/archiver.c | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/lib/format_text/archiver.c b/lib/format_text/archiver.c
index e6d4b59..92799e4 100644
--- a/lib/format_text/archiver.c
+++ b/lib/format_text/archiver.c
@@ -339,6 +339,11 @@ static int _restore_vg_should_write_pv(struct physical_volume *pv, int do_pvcrea
if (!(pv->fmt->features & FMT_PV_FLAGS))
return 0;
+ if (!pv->dev) {
+ log_error("Failed to find device for PV.");
+ return -1;
+ }
+
if (!(info = lvmcache_info_from_pvid(pv->dev->pvid, pv->dev, 0))) {
log_error("Failed to find cached info for PV %s.", pv_dev_name(pv));
return -1;
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=b12961e7ebd6fb29…
Commit: b12961e7ebd6fb29d760daafd3c16e4ba3e54e80
Parent: 6ae22125c62ddea4340916a5e255d55844bfd087
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Mon Jun 20 13:19:02 2016 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Mon Jun 20 13:19:02 2016 -0500
lvmetad: process new connections after shutdown signal
Currently, a shutdown signal will cause lvmetad to quit
responding to new connections, but not actually exit until
all connections are gone. If a program is maintaining a
long running connection (e.g. lvmlockd, or even an lvm
command) when lvmetad gets a shutdown signal, then all
further commands will hang indefinately waiting for a
response that won't be sent.
With this patch, make lvmetad continue handling new
connections even after a shutdown signal. It will exit
once all connections are gone.
---
libdaemon/server/daemon-server.c | 16 +++++++++++-----
1 files changed, 11 insertions(+), 5 deletions(-)
diff --git a/libdaemon/server/daemon-server.c b/libdaemon/server/daemon-server.c
index d18bd4b..7911dd6 100644
--- a/libdaemon/server/daemon-server.c
+++ b/libdaemon/server/daemon-server.c
@@ -490,8 +490,10 @@ static int handle_connect(daemon_state s)
socklen_t sl = sizeof(sockaddr);
client.socket_fd = accept(s.socket_fd, (struct sockaddr *) &sockaddr, &sl);
- if (client.socket_fd < 0)
+ if (client.socket_fd < 0) {
+ ERROR(&s, "Failed to accept connection.");
return 0;
+ }
if (fcntl(client.socket_fd, F_SETFD, FD_CLOEXEC))
WARN(&s, "setting CLOEXEC on client socket fd %d failed", client.socket_fd);
@@ -510,8 +512,10 @@ static int handle_connect(daemon_state s)
ts->s = s;
ts->client = client;
- if (pthread_create(&ts->client.thread_id, NULL, client_thread, ts))
+ if (pthread_create(&ts->client.thread_id, NULL, client_thread, ts)) {
+ ERROR(&s, "Failed to create client thread.");
return 0;
+ }
return 1;
}
@@ -622,7 +626,7 @@ void daemon_start(daemon_state s)
if (!s.daemon_init(&s))
failed = 1;
- while (!_shutdown_requested && !failed) {
+ while (!failed) {
_reset_timeout(s);
FD_ZERO(&in);
FD_SET(s.socket_fd, &in);
@@ -630,12 +634,14 @@ void daemon_start(daemon_state s)
perror("select error");
if (FD_ISSET(s.socket_fd, &in)) {
timeout_count = 0;
- if (!_shutdown_requested && !handle_connect(s))
- ERROR(&s, "Failed to handle a client connection.");
+ handle_connect(s);
}
reap(s, 0);
+ if (_shutdown_requested && !s.threads->next)
+ break;
+
/* s.idle == NULL equals no shutdown on timeout */
if (_is_idle(s)) {
DEBUGLOG(&s, "timeout occured");
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=d1d3820219f6b090…
Commit: d1d3820219f6b0906bc0b3980b6eefcc187999d9
Parent: 99ea03571a835c3a56b364be4ccebcc745d09dbe
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Mon Jun 20 16:21:38 2016 +0200
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Mon Jun 20 16:21:38 2016 +0200
conf: add more comments for new settings related to output format and log report
---
conf/example.conf.in | 49 +++++++++++++++++++++++++++++++---------
lib/config/config_settings.h | 51 ++++++++++++++++++++++++++++++++----------
2 files changed, 77 insertions(+), 23 deletions(-)
diff --git a/conf/example.conf.in b/conf/example.conf.in
index bf8f177..f7cebf9 100644
--- a/conf/example.conf.in
+++ b/conf/example.conf.in
@@ -479,30 +479,51 @@ allocation {
log {
# Configuration option log/report_command_log.
- # If enabled, LVM will collect log during command processing.
- # After that the log is reported using current output format
- # as defined by report/output_format setting.
+ # Enable or disable LVM log reporting.
+ # If enabled, LVM will collect a log of operations, messages,
+ # per-object return codes with object identification and associated
+ # error numbers (errnos) during LVM command processing. Then the
+ # log is either reported solely or in addition to any existing
+ # reports, depending on LVM command used. If it is a reporting command
+ # (e.g. pvs, vgs, lvs, lvm fullreport), then the log is reported in
+ # addition to any existing reports. Otherwise, there's only log report
+ # on output. For all applicable LVM commands, you can request that
+ # the output has only log report by using --logonly command line
+ # option. Use log/command_log_cols and log/command_log_sort settings
+ # to define fields to display and sort fields for the log report.
+ # You can also use log/command_log_selection to define selection
+ # criteria used each time the log is reported.
# This configuration option has an automatic default value.
# report_command_log = 0
# Configuration option log/command_log_sort.
# List of columns to sort by when reporting command log.
- # Possible fields are: log_seq_num, log_type, log_context, log_object_type,
- # log_object_name, log_object_id, log_object_group, log_object_group_id,
- # log_message, log_errno, log_ret_code.
+ # See <lvm command> --logonly --configreport log -o help
+ # for the list of possible fields.
# This configuration option has an automatic default value.
# command_log_sort = "log_seq_num"
# Configuration option log/command_log_cols.
# List of columns to report when reporting command log.
- # Possible fields are: log_seq_num, log_type, log_context, log_object_type,
- # log_object_name, log_object_id, log_object_group, log_object_group_id,
- # log_message, log_errno, log_ret_code.
+ # See <lvm command> --logonly --configreport log -o help
+ # for the list of possible fields.
# This configuration option has an automatic default value.
# command_log_cols = "log_seq_num,log_type,log_context,log_object_type,log_object_name,log_object_id,log_object_group,log_object_group_id,log_message,log_errno,log_ret_code"
# Configuration option log/command_log_selection.
# Selection criteria used when reporting command log.
+ # You can define selection criteria that are applied each
+ # time log is reported. This way, it is possible to control the
+ # amount of log that is displayed on output and you can select
+ # only parts of the log that are important for you. To define
+ # selection criteria, use fields from log report. See also
+ # <lvm command> --logonly --configreport log -S help for the
+ # list of possible fields and selection operators. You can also
+ # define selection criteria for log report on command line directly
+ # using <lvm command> --configreport log -S <selection criteria>
+ # which has precedence over log/command_log_selection setting.
+ # For more information about selection criteria in general, see
+ # lvm(8) man page.
# This configuration option has an automatic default value.
# command_log_selection = "!(log_type=status && message=success)"
@@ -1580,10 +1601,16 @@ activation {
# report {
# Configuration option report/output_format.
- # Format of LVM2 command report output.
+ # Format of LVM command's report output.
+ # If there is more than one report per command, then the format
+ # is applied for all reports. You can also change output format
+ # directly on command line using --reportformat option which
+ # has precedence over log/output_format setting.
# Accepted values:
# basic
- # Original format with columns and rows.
+ # Original format with columns and rows. If there is more than
+ # one report per command, each report is prefixed with report's
+ # name for identification.
# json
# JSON format.
# This configuration option has an automatic default value.
diff --git a/lib/config/config_settings.h b/lib/config/config_settings.h
index 64859e4..25914ea 100644
--- a/lib/config/config_settings.h
+++ b/lib/config/config_settings.h
@@ -548,24 +548,45 @@ cfg(allocation_physical_extent_size_CFG, "physical_extent_size", allocation_CFG_
"Default physical extent size in KiB to use for new VGs.\n")
cfg(log_report_command_log_CFG, "report_command_log", log_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_COMMAND_LOG_REPORT, vsn(2, 2, 158), NULL, 0, NULL,
- "If enabled, LVM will collect log during command processing.\n"
- "After that the log is reported using current output format\n"
- "as defined by report/output_format setting.\n")
+ "Enable or disable LVM log reporting.\n"
+ "If enabled, LVM will collect a log of operations, messages,\n"
+ "per-object return codes with object identification and associated\n"
+ "error numbers (errnos) during LVM command processing. Then the\n"
+ "log is either reported solely or in addition to any existing\n"
+ "reports, depending on LVM command used. If it is a reporting command\n"
+ "(e.g. pvs, vgs, lvs, lvm fullreport), then the log is reported in\n"
+ "addition to any existing reports. Otherwise, there's only log report\n"
+ "on output. For all applicable LVM commands, you can request that\n"
+ "the output has only log report by using --logonly command line\n"
+ "option. Use log/command_log_cols and log/command_log_sort settings\n"
+ "to define fields to display and sort fields for the log report.\n"
+ "You can also use log/command_log_selection to define selection\n"
+ "criteria used each time the log is reported.\n")
cfg(log_command_log_sort_CFG, "command_log_sort", log_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_COMMAND_LOG_SORT, vsn(2, 2, 158), NULL, 0, NULL,
"List of columns to sort by when reporting command log.\n"
- "Possible fields are: log_seq_num, log_type, log_context, log_object_type,\n"
- "log_object_name, log_object_id, log_object_group, log_object_group_id,\n"
- "log_message, log_errno, log_ret_code.\n")
+ "See <lvm command> --logonly --configreport log -o help\n"
+ "for the list of possible fields.\n")
cfg(log_command_log_cols_CFG, "command_log_cols", log_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_COMMAND_LOG_COLS, vsn(2, 2, 158), NULL, 0, NULL,
"List of columns to report when reporting command log.\n"
- "Possible fields are: log_seq_num, log_type, log_context, log_object_type,\n"
- "log_object_name, log_object_id, log_object_group, log_object_group_id,\n"
- "log_message, log_errno, log_ret_code.\n")
+ "See <lvm command> --logonly --configreport log -o help\n"
+ "for the list of possible fields.\n")
cfg(log_command_log_selection_CFG, "command_log_selection", log_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_COMMAND_LOG_SELECTION, vsn(2, 2, 158), NULL, 0, NULL,
- "Selection criteria used when reporting command log.\n")
+ "Selection criteria used when reporting command log.\n"
+ "You can define selection criteria that are applied each\n"
+ "time log is reported. This way, it is possible to control the\n"
+ "amount of log that is displayed on output and you can select\n"
+ "only parts of the log that are important for you. To define\n"
+ "selection criteria, use fields from log report. See also\n"
+ "<lvm command> --logonly --configreport log -S help for the\n"
+ "list of possible fields and selection operators. You can also\n"
+ "define selection criteria for log report on command line directly\n"
+ "using <lvm command> --configreport log -S <selection criteria>\n"
+ "which has precedence over log/command_log_selection setting.\n"
+ "For more information about selection criteria in general, see\n"
+ "lvm(8) man page.\n")
cfg(log_verbose_CFG, "verbose", log_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_VERBOSE, vsn(1, 0, 0), NULL, 0, NULL,
"Controls the messages sent to stdout or stderr.\n")
@@ -1483,10 +1504,16 @@ cfg(disk_area_size_CFG, "size", disk_area_CFG_SUBSECTION, CFG_UNSUPPORTED | CFG_
cfg(disk_area_id_CFG, "id", disk_area_CFG_SUBSECTION, CFG_UNSUPPORTED | CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL, 0, NULL, NULL)
cfg(report_output_format_CFG, "output_format", report_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_REP_OUTPUT_FORMAT, vsn(2, 2, 158), NULL, 0, NULL,
- "Format of LVM2 command report output.\n"
+ "Format of LVM command's report output.\n"
+ "If there is more than one report per command, then the format\n"
+ "is applied for all reports. You can also change output format\n"
+ "directly on command line using --reportformat option which\n"
+ "has precedence over log/output_format setting.\n"
"Accepted values:\n"
" basic\n"
- " Original format with columns and rows.\n"
+ " Original format with columns and rows. If there is more than\n"
+ " one report per command, each report is prefixed with report's\n"
+ " name for identification.\n"
" json\n"
" JSON format.\n")
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=99ea03571a835c3a…
Commit: 99ea03571a835c3a56b364be4ccebcc745d09dbe
Parent: a77732c18089a12fa7c009a02cc1f1d6636a4284
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Mon Jun 20 14:22:31 2016 +0200
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Mon Jun 20 14:22:31 2016 +0200
cleanup: log: use hex numbers instead of decimal for _LOG_*
---
lib/log/log.h | 20 ++++++++++----------
1 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/lib/log/log.h b/lib/log/log.h
index 15d363e..1bc9cbe 100644
--- a/lib/log/log.h
+++ b/lib/log/log.h
@@ -41,16 +41,16 @@
#define EUNCLASSIFIED -1 /* Generic error code */
-#define _LOG_STDERR 128 /* force things to go to stderr, even if loglevel
- would make them go to stdout */
-#define _LOG_ONCE 256 /* downgrade to NOTICE if this has been already logged */
-#define _LOG_BYPASS_REPORT 512 /* do not log through report even if report available */
-#define _LOG_DEBUG 7
-#define _LOG_INFO 6
-#define _LOG_NOTICE 5
-#define _LOG_WARN 4
-#define _LOG_ERR 3
-#define _LOG_FATAL 2
+#define _LOG_FATAL 0x0002
+#define _LOG_ERR 0x0003
+#define _LOG_WARN 0x0004
+#define _LOG_NOTICE 0x0005
+#define _LOG_INFO 0x0006
+#define _LOG_DEBUG 0x0007
+#define _LOG_STDERR 0x0080 /* force things to go to stderr, even if loglevel would make them go to stdout */
+#define _LOG_ONCE 0x0100 /* downgrade to NOTICE if this has been already logged */
+#define _LOG_BYPASS_REPORT 0x0200 /* do not log through report even if report available */
+
#define INTERNAL_ERROR "Internal error: "
/*
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=f2facdc1d01b0353…
Commit: f2facdc1d01b0353b05623634d34924317c44a9c
Parent: 0ba5f4b8e977a6f2f45f95777da508b42d84c01a
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Thu May 12 14:34:04 2016 +0200
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Mon Jun 20 11:33:43 2016 +0200
libdm: report: add DM_REPORT_OUTPUT_MULTIPLE_TIMES report flag to keep report data even after output is done
The DM_REPORT_OUTPUT_MULTIPLE_TIMES instructs reporting code to
keep rows even after dm_report_output call - the rows are not
destroyed in this case which makes it possible to call dm_report_output
multiple times.
---
WHATS_NEW_DM | 1 +
libdm/libdevmapper.h | 1 +
libdm/libdm-report.c | 83 ++++++++++++++++++++++++++++++++++---------------
3 files changed, 59 insertions(+), 26 deletions(-)
diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM
index 7e98e1f..6842771 100644
--- a/WHATS_NEW_DM
+++ b/WHATS_NEW_DM
@@ -1,5 +1,6 @@
Version 1.02.128 -
=================================
+ Add DM_REPORT_OUTPUT_MULTIPLE_TIMES flag for multiple output of same report.
Move field width handling/sort init from dm_report_object to dm_report_output.
Add _LOG_BYPASS_REPORT flag for bypassing any log report currently set.
Introduce DM_REPORT_GROUP_JSON for report group with JSON output format.
diff --git a/libdm/libdevmapper.h b/libdm/libdevmapper.h
index cad79dd..61ab279 100644
--- a/libdm/libdevmapper.h
+++ b/libdm/libdevmapper.h
@@ -2606,6 +2606,7 @@ const void *dm_report_value_cache_get(struct dm_report *rh, const char *name);
#define DM_REPORT_OUTPUT_FIELD_NAME_PREFIX 0x00000008
#define DM_REPORT_OUTPUT_FIELD_UNQUOTED 0x00000010
#define DM_REPORT_OUTPUT_COLUMNS_AS_ROWS 0x00000020
+#define DM_REPORT_OUTPUT_MULTIPLE_TIMES 0x00000040
struct dm_report *dm_report_init(uint32_t *report_types,
const struct dm_report_object_type *types,
diff --git a/libdm/libdm-report.c b/libdm/libdm-report.c
index 7a5d6e5..95b6ded 100644
--- a/libdm/libdm-report.c
+++ b/libdm/libdm-report.c
@@ -1994,25 +1994,35 @@ static int _do_report_object(struct dm_report *rh, void *object, int do_output,
if (!_check_report_selection(rh, &row->fields)) {
row->selected = 0;
- if (!row->field_sel_status)
- goto out;
-
- /*
- * If field with id "selected" is reported,
- * report the row although it does not pass
- * the selection criteria.
- * The "selected" field reports the result
- * of the selection.
- */
- _implicit_report_fields[row->field_sel_status->props->field_num].report_fn(rh,
- rh->mem, row->field_sel_status, row, rh->private);
/*
- * If the "selected" field is not displayed, e.g.
- * because it is part of the sort field list,
- * skip the display of the row as usual.
+ * If the row is not selected, we still keep it for output if either:
+ * - we're displaying special "selected" field in the row,
+ * - or the report is supposed to be on output multiple times
+ * where each output can have a new selection defined.
*/
- if (row->field_sel_status->props->flags & FLD_HIDDEN)
+ if (!row->field_sel_status && !(rh->flags & DM_REPORT_OUTPUT_MULTIPLE_TIMES))
goto out;
+
+ if (row->field_sel_status) {
+ /*
+ * If field with id "selected" is reported,
+ * report the row although it does not pass
+ * the selection criteria.
+ * The "selected" field reports the result
+ * of the selection.
+ */
+ _implicit_report_fields[row->field_sel_status->props->field_num].report_fn(rh,
+ rh->mem, row->field_sel_status, row, rh->private);
+ /*
+ * If the "selected" field is not displayed, e.g.
+ * because it is part of the sort field list,
+ * skip the display of the row as usual unless
+ * we plan to do the output multiple times.
+ */
+ if ((row->field_sel_status->props->flags & FLD_HIDDEN) &&
+ !(rh->flags & DM_REPORT_OUTPUT_MULTIPLE_TIMES))
+ goto out;
+ }
}
if (!do_output)
@@ -4165,6 +4175,11 @@ static int _row_compare(const void *a, const void *b)
return 0; /* Identical */
}
+static int _should_display_row(struct row *row)
+{
+ return row->field_sel_status || row->selected;
+}
+
static int _sort_rows(struct dm_report *rh)
{
struct row *(*rows)[];
@@ -4439,6 +4454,11 @@ static int _output_as_columns(struct dm_report *rh)
/* Print and clear buffer */
last_row = dm_list_last(&rh->rows);
dm_list_iterate_safe(rowh, rtmp, &rh->rows) {
+ row = dm_list_item(rowh, struct row);
+
+ if (!_should_display_row(row))
+ continue;
+
if (!dm_pool_begin_object(rh->mem, 512)) {
log_error("dm_report: Unable to allocate output line");
return 0;
@@ -4451,7 +4471,6 @@ static int _output_as_columns(struct dm_report *rh)
}
}
- row = dm_list_item(rowh, struct row);
do_field_delim = 0;
dm_list_iterate_safe(fh, ftmp, &row->fields) {
@@ -4478,7 +4497,8 @@ static int _output_as_columns(struct dm_report *rh)
if (!_output_field(rh, field))
goto bad;
- dm_list_del(&field->list);
+ if (!(rh->flags & DM_REPORT_OUTPUT_MULTIPLE_TIMES))
+ dm_list_del(&field->list);
}
if (_is_json_report(rh)) {
@@ -4500,10 +4520,12 @@ static int _output_as_columns(struct dm_report *rh)
line = (char *) dm_pool_end_object(rh->mem);
log_print_bypass_report("%*s", rh->group_item ? rh->group_item->group->indent + (int) strlen(line) : 0, line);
- dm_list_del(&row->list);
+ if (!(rh->flags & DM_REPORT_OUTPUT_MULTIPLE_TIMES))
+ dm_list_del(&row->list);
}
- _destroy_rows(rh);
+ if (!(rh->flags & DM_REPORT_OUTPUT_MULTIPLE_TIMES))
+ _destroy_rows(rh);
return 1;
@@ -4631,14 +4653,17 @@ int dm_report_output(struct dm_report *rh)
dm_list_iterate_items(row, &rh->rows) {
dm_list_iterate_items(field, &row->fields) {
- len = (int) strlen(field->report_string);
- if ((len > field->props->width))
- field->props->width = len;
-
if ((rh->flags & RH_SORT_REQUIRED) &&
(field->props->flags & FLD_SORT_KEY)) {
(*row->sort_fields)[field->props->sort_posn] = field;
}
+
+ if (_should_display_row(row)) {
+ len = (int) strlen(field->report_string);
+ if ((len > field->props->width))
+ field->props->width = len;
+
+ }
}
}
@@ -4746,8 +4771,13 @@ static int _report_group_push_single(struct report_group_item *item, void *data)
static int _report_group_push_basic(struct report_group_item *item, const char *name)
{
- if (!item->report && !name && item->parent->store.finished_count > 0)
- log_print_bypass_report("%s", "");
+ if (item->report) {
+ if (!(item->report->flags & DM_REPORT_OUTPUT_BUFFERED))
+ item->report->flags &= ~(DM_REPORT_OUTPUT_MULTIPLE_TIMES);
+ } else {
+ if (!name && item->parent->store.finished_count > 0)
+ log_print_bypass_report("%s", "");
+ }
return 1;
}
@@ -4802,6 +4832,7 @@ int dm_report_group_push(struct dm_report_group *group, struct dm_report *report
item->store.orig_report_flags = report->flags;
report->group_item = item;
}
+
item->group = group;
item->data = data;
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=102cc4c1e241ee7c…
Commit: 102cc4c1e241ee7c3f6cc8c863a06dd29f373fbc
Parent: f50d4011cdd3ef38c15b9dea05e73321592d93c2
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Thu May 12 14:03:32 2016 +0200
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Mon Jun 20 11:33:42 2016 +0200
libdm: report: remember special field to display selection status in struct row's field_sel_status variable
This allows for moving parts of the code from dm_report_object to
dm_report_output which is important for subsequent patches that allow
for repeated dm_report_output, not destroying rows on each
dm_report_output call.
---
libdm/libdm-report.c | 13 +++++++------
1 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/libdm/libdm-report.c b/libdm/libdm-report.c
index 3fa596e..13f2027 100644
--- a/libdm/libdm-report.c
+++ b/libdm/libdm-report.c
@@ -254,6 +254,7 @@ struct row {
struct dm_list fields; /* Fields in display order */
struct dm_report_field *(*sort_fields)[]; /* Fields in sort order */
int selected;
+ struct dm_report_field *field_sel_status;
};
/*
@@ -1910,7 +1911,7 @@ static int _do_report_object(struct dm_report *rh, void *object, int do_output,
const struct dm_report_field_type *fields;
struct field_properties *fp;
struct row *row = NULL;
- struct dm_report_field *field, *field_sel_status = NULL;
+ struct dm_report_field *field;
void *data = NULL;
int len;
int r = 0;
@@ -1962,7 +1963,7 @@ static int _do_report_object(struct dm_report *rh, void *object, int do_output,
if (fp->implicit) {
fields = _implicit_report_fields;
if (!strcmp(fields[fp->field_num].id, SPECIAL_FIELD_SELECTED_ID))
- field_sel_status = field;
+ row->field_sel_status = field;
} else
fields = rh->fields;
@@ -1994,7 +1995,7 @@ static int _do_report_object(struct dm_report *rh, void *object, int do_output,
if (!_check_report_selection(rh, &row->fields)) {
row->selected = 0;
- if (!field_sel_status)
+ if (!row->field_sel_status)
goto out;
/*
@@ -2004,14 +2005,14 @@ static int _do_report_object(struct dm_report *rh, void *object, int do_output,
* The "selected" field reports the result
* of the selection.
*/
- _implicit_report_fields[field_sel_status->props->field_num].report_fn(rh,
- rh->mem, field_sel_status, row, rh->private);
+ _implicit_report_fields[row->field_sel_status->props->field_num].report_fn(rh,
+ rh->mem, row->field_sel_status, row, rh->private);
/*
* If the "selected" field is not displayed, e.g.
* because it is part of the sort field list,
* skip the display of the row as usual.
*/
- if (field_sel_status->props->flags & FLD_HIDDEN)
+ if (row->field_sel_status->props->flags & FLD_HIDDEN)
goto out;
}
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=9c37b7ed7c33bb6e…
Commit: 9c37b7ed7c33bb6e66daf369fd563c52f6743282
Parent: 26c43c6ce525f5b338a2fbdae72bf308d42708d7
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Tue Jun 14 12:38:40 2016 +0200
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Mon Jun 20 11:33:42 2016 +0200
conf: add report/{vgs,pvs,lvs,pvsegs,segs}_{cols,sort}_full config settings
---
WHATS_NEW | 1 +
conf/example.conf.in | 60 ++++++++++++++++++++++++++++++++++++++++++
lib/config/config_settings.h | 40 ++++++++++++++++++++++++++++
tools/reporter.c | 16 +++++-----
4 files changed, 109 insertions(+), 8 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index 79dfe09..4e87e47 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.158 -
=================================
+ Add report/{pvs,vgs,lvs,pvsegs,segs}_{cols,sort}_full to lvm.conf.
Add lvm fullreport command for joined PV, VG, LV and segment report per VG.
Integrate report group handling and cmd log report into cmd processing code.
Add log/report_command_log to lvm.conf to enable or disable cmd log report.
diff --git a/conf/example.conf.in b/conf/example.conf.in
index 69bb668..1918a3d 100644
--- a/conf/example.conf.in
+++ b/conf/example.conf.in
@@ -1900,6 +1900,66 @@ activation {
# This configuration option has an automatic default value.
# pvsegs_cols_verbose = "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,pvseg_start,pvseg_size,lv_name,seg_start_pe,segtype,seg_pe_ranges"
+ # Configuration option report/vgs_cols_full.
+ # List of columns to report for lvm fullreport's 'vgs' subreport.
+ # See 'vgs -o help' for the list of possible fields.
+ # This configuration option has an automatic default value.
+ # vgs_cols_full = "vg_all"
+
+ # Configuration option report/pvs_cols_full.
+ # List of columns to report for lvm fullreport's 'vgs' subreport.
+ # See 'pvs -o help' for the list of possible fields.
+ # This configuration option has an automatic default value.
+ # pvs_cols_full = "pv_all"
+
+ # Configuration option report/lvs_cols_full.
+ # List of columns to report for lvm fullreport's 'lvs' subreport.
+ # See 'lvs -o help' for the list of possible fields.
+ # This configuration option has an automatic default value.
+ # lvs_cols_full = "lv_all"
+
+ # Configuration option report/pvsegs_cols_full.
+ # List of columns to report for lvm fullreport's 'pvseg' subreport.
+ # See 'pvs --segments -o help' for the list of possible fields.
+ # This configuration option has an automatic default value.
+ # pvsegs_cols_full = "pvseg_all,pv_uuid,lv_uuid"
+
+ # Configuration option report/segs_cols_full.
+ # List of columns to report for lvm fullreport's 'seg' subreport.
+ # See 'lvs --segments -o help' for the list of possible fields.
+ # This configuration option has an automatic default value.
+ # segs_cols_full = "seg_all,lv_uuid"
+
+ # Configuration option report/vgs_sort_full.
+ # List of columns to sort by when reporting lvm fullreport's 'vgs' subreport.
+ # See 'vgs -o help' for the list of possible fields.
+ # This configuration option has an automatic default value.
+ # vgs_sort_full = "vg_name"
+
+ # Configuration option report/pvs_sort_full.
+ # List of columns to sort by when reporting lvm fullreport's 'vgs' subreport.
+ # See 'pvs -o help' for the list of possible fields.
+ # This configuration option has an automatic default value.
+ # pvs_sort_full = "pv_name"
+
+ # Configuration option report/lvs_sort_full.
+ # List of columns to sort by when reporting lvm fullreport's 'lvs' subreport.
+ # See 'lvs -o help' for the list of possible fields.
+ # This configuration option has an automatic default value.
+ # lvs_sort_full = "vg_name,lv_name"
+
+ # Configuration option report/pvsegs_sort_full.
+ # List of columns to sort by when reporting for lvm fullreport's 'pvseg' subreport.
+ # See 'pvs --segments -o help' for the list of possible fields.
+ # This configuration option has an automatic default value.
+ # pvsegs_sort_full = "pv_uuid,pvseg_start"
+
+ # Configuration option report/segs_sort_full.
+ # List of columns to sort by when reporting lvm fullreport's 'seg' subreport.
+ # See 'lvs --segments -o help' for the list of possible fields.
+ # This configuration option has an automatic default value.
+ # segs_sort_full = "lv_uuid,seg_start"
+
# Configuration option report/mark_hidden_devices.
# Use brackets [] to mark hidden devices.
# This configuration option has an automatic default value.
diff --git a/lib/config/config_settings.h b/lib/config/config_settings.h
index 09c9ab5..89e0771 100644
--- a/lib/config/config_settings.h
+++ b/lib/config/config_settings.h
@@ -1743,6 +1743,46 @@ cfg(report_pvsegs_cols_verbose_CFG, "pvsegs_cols_verbose", report_CFG_SECTION, C
"List of columns to sort by when reporting 'pvs --segments' command in verbose mode.\n"
"See 'pvs --segments -o help' for the list of possible fields.\n")
+cfg(report_vgs_cols_full_CFG, "vgs_cols_full", report_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_VGS_COLS_FULL, vsn(2, 2, 158), NULL, 0, NULL,
+ "List of columns to report for lvm fullreport's 'vgs' subreport.\n"
+ "See 'vgs -o help' for the list of possible fields.\n")
+
+cfg(report_pvs_cols_full_CFG, "pvs_cols_full", report_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_PVS_COLS_FULL, vsn(2, 2, 158), NULL, 0, NULL,
+ "List of columns to report for lvm fullreport's 'vgs' subreport.\n"
+ "See 'pvs -o help' for the list of possible fields.\n")
+
+cfg(report_lvs_cols_full_CFG, "lvs_cols_full", report_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_LVS_COLS_FULL, vsn(2, 2, 158), NULL, 0, NULL,
+ "List of columns to report for lvm fullreport's 'lvs' subreport.\n"
+ "See 'lvs -o help' for the list of possible fields.\n")
+
+cfg(report_pvsegs_cols_full_CFG, "pvsegs_cols_full", report_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_PVSEGS_COLS_FULL, vsn(2, 2, 158), NULL, 0, NULL,
+ "List of columns to report for lvm fullreport's 'pvseg' subreport.\n"
+ "See 'pvs --segments -o help' for the list of possible fields.\n")
+
+cfg(report_segs_cols_full_CFG, "segs_cols_full", report_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_SEGS_COLS_FULL, vsn(2, 2, 158), NULL, 0, NULL,
+ "List of columns to report for lvm fullreport's 'seg' subreport.\n"
+ "See 'lvs --segments -o help' for the list of possible fields.\n")
+
+cfg(report_vgs_sort_full_CFG, "vgs_sort_full", report_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_VGS_SORT_FULL, vsn(2, 2, 158), NULL, 0, NULL,
+ "List of columns to sort by when reporting lvm fullreport's 'vgs' subreport.\n"
+ "See 'vgs -o help' for the list of possible fields.\n")
+
+cfg(report_pvs_sort_full_CFG, "pvs_sort_full", report_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_PVS_SORT_FULL, vsn(2, 2, 158), NULL, 0, NULL,
+ "List of columns to sort by when reporting lvm fullreport's 'vgs' subreport.\n"
+ "See 'pvs -o help' for the list of possible fields.\n")
+
+cfg(report_lvs_sort_full_CFG, "lvs_sort_full", report_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_LVS_SORT_FULL, vsn(2, 2, 158), NULL, 0, NULL,
+ "List of columns to sort by when reporting lvm fullreport's 'lvs' subreport.\n"
+ "See 'lvs -o help' for the list of possible fields.\n")
+
+cfg(report_pvsegs_sort_full_CFG, "pvsegs_sort_full", report_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_PVSEGS_SORT_FULL, vsn(2, 2, 158), NULL, 0, NULL,
+ "List of columns to sort by when reporting for lvm fullreport's 'pvseg' subreport.\n"
+ "See 'pvs --segments -o help' for the list of possible fields.\n")
+
+cfg(report_segs_sort_full_CFG, "segs_sort_full", report_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_SEGS_SORT_FULL, vsn(2, 2, 158), NULL, 0, NULL,
+ "List of columns to sort by when reporting lvm fullreport's 'seg' subreport.\n"
+ "See 'lvs --segments -o help' for the list of possible fields.\n")
+
cfg(report_mark_hidden_devices_CFG, "mark_hidden_devices", report_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 1, vsn(2, 2, 140), NULL, 0, NULL,
"Use brackets [] to mark hidden devices.\n")
diff --git a/tools/reporter.c b/tools/reporter.c
index 2037f6e..408d410 100644
--- a/tools/reporter.c
+++ b/tools/reporter.c
@@ -1055,11 +1055,11 @@ out:
return r;
}
-#define _set_full_report_single(args,type,name) \
+#define _set_full_report_single(cmd,args,type,name) \
do { \
args->single_args[REPORT_IDX_FULL_ ## type].report_type = type; \
- args->single_args[REPORT_IDX_FULL_ ## type].keys = DEFAULT_ ## type ## _SORT_FULL; \
- args->single_args[REPORT_IDX_FULL_ ## type].options = DEFAULT_ ## type ## _COLS_FULL; \
+ args->single_args[REPORT_IDX_FULL_ ## type].keys = find_config_tree_str(cmd, report_ ## name ## _sort_full_CFG, NULL); \
+ args->single_args[REPORT_IDX_FULL_ ## type].options = find_config_tree_str(cmd, report_ ## name ## _cols_full_CFG, NULL); \
if (!_set_report_prefix_and_name(&args->single_args[REPORT_IDX_FULL_ ## type])) \
return_0; \
} while (0)
@@ -1125,11 +1125,11 @@ static int _config_report(struct cmd_context *cmd, struct report_args *args, str
single_args->options = find_config_tree_str(cmd, report_pvsegs_cols_verbose_CFG, NULL);
break;
case FULL:
- _set_full_report_single(args, VGS, vgs);
- _set_full_report_single(args, LVS, lvs);
- _set_full_report_single(args, PVS, pvs);
- _set_full_report_single(args, PVSEGS, pvsegs);
- _set_full_report_single(args, SEGS, segs);
+ _set_full_report_single(cmd, args, VGS, vgs);
+ _set_full_report_single(cmd, args, LVS, lvs);
+ _set_full_report_single(cmd, args, PVS, pvs);
+ _set_full_report_single(cmd, args, PVSEGS, pvsegs);
+ _set_full_report_single(cmd, args, SEGS, segs);
break;
case CMDLOG:
single_args->keys = find_config_tree_str(cmd, log_command_log_sort_CFG, NULL);
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=9c8f912ea79d9b83…
Commit: 9c8f912ea79d9b836c814b3d12cc331de634617e
Parent: 029f51e1a853297ca7246b75ac80cde9de23a2a4
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Mon May 2 14:21:05 2016 +0200
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Mon Jun 20 09:26:51 2016 +0200
libdm: report: introduce dm_report_group
This patch introduces DM report group (represented by dm_report_group
structure) that is used to group several reports to make a whole. As a
whole, all the reports in the group follow the same settings and/or
formatting used on output and it controls that the output is properly
ordered (e.g. the output from different reports is not interleaved
which would break readability and/or syntax of target output format
used for the whole group).
To support this feature, there are 4 new functions:
- dm_report_group_create
- dm_report_group_push
- dm_report_group_pop
- dm_report_group_destroy
>From the naming used (dm_report_group_push/pop), it's clear the reports
are pushed onto a stack. The rule then is that only the report on top
of the stack can be reported (that means calling dm_report_output).
This way we make sure that the output is not interleaved and provides
determinism and control over the output.
Different formats may allow or disallow some of the existing report
flags controlling output itself (DM_REPORT_OUTPUT_*) to be set or not so
once the report is pushed to a group, the grouping code makes sure that
all the reports have compatible flags set and then these flags are
restored once each report is popped from the report group stack.
We also allow to push/pop non-report item in which case such an item
creates a structure (e.g. to put several reports together with any
opening and/or closing lines needed on output which pose as extra
formatting structure besides formatting the reports).
The dm_report_group_push function accepts an argument to pass any
format-specific data needed (e.g. handle, name, structures passed
along while working with reports...).
We can call dm_report_output directly anytime we need (with the only
restriction that we can call dm_report_output only for the report that
is currently on top of the group's stack). Or we don't need to call
dm_report_output explicitly in which case all the reports in a stack are
reported on output automatically once we call dm_report_group_destroy.
---
WHATS_NEW_DM | 1 +
libdm/.exported_symbols.DM_1_02_128 | 4 +
libdm/libdevmapper.h | 14 +++
libdm/libdm-report.c | 188 ++++++++++++++++++++++++++++++++++-
4 files changed, 203 insertions(+), 4 deletions(-)
diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM
index 6fb1745..c16f0c1 100644
--- a/WHATS_NEW_DM
+++ b/WHATS_NEW_DM
@@ -1,5 +1,6 @@
Version 1.02.128 -
=================================
+ Add dm_report_group_{create,push,pop,destroy} to support report grouping.
Version 1.02.127 - 11th June 2016
=================================
diff --git a/libdm/.exported_symbols.DM_1_02_128 b/libdm/.exported_symbols.DM_1_02_128
new file mode 100644
index 0000000..6e365d5
--- /dev/null
+++ b/libdm/.exported_symbols.DM_1_02_128
@@ -0,0 +1,4 @@
+dm_report_group_create
+dm_report_group_push
+dm_report_group_pop
+dm_report_group_destroy
diff --git a/libdm/libdevmapper.h b/libdm/libdevmapper.h
index d2f40c9..c99ebe8 100644
--- a/libdm/libdevmapper.h
+++ b/libdm/libdevmapper.h
@@ -2704,6 +2704,20 @@ void dm_report_field_set_value(struct dm_report_field *field, const void *value,
const void *sortvalue);
/*
+ * Report group support.
+ */
+struct dm_report_group;
+
+typedef enum {
+ DM_REPORT_GROUP_SINGLE,
+} dm_report_group_type_t;
+
+struct dm_report_group *dm_report_group_create(dm_report_group_type_t type, void *data);
+int dm_report_group_push(struct dm_report_group *group, struct dm_report *report, void *data);
+int dm_report_group_pop(struct dm_report_group *group);
+int dm_report_group_destroy(struct dm_report_group *group);
+
+/*
* Stats counter access methods
*
* Each method returns the corresponding stats counter value from the
diff --git a/libdm/libdm-report.c b/libdm/libdm-report.c
index 3896b3c..ab87ba7 100644
--- a/libdm/libdm-report.c
+++ b/libdm/libdm-report.c
@@ -32,6 +32,8 @@ struct selection {
struct selection_node *selection_root;
};
+struct report_group_item;
+
struct dm_report {
struct dm_pool *mem;
@@ -71,6 +73,29 @@ struct dm_report {
/* Null-terminated array of reserved values */
const struct dm_report_reserved_value *reserved_values;
struct dm_hash_table *value_cache;
+
+ struct report_group_item *group_item;
+};
+
+struct dm_report_group {
+ dm_report_group_type_t type;
+ struct dm_pool *mem;
+ struct dm_list items;
+ int indent;
+};
+
+struct report_group_item {
+ struct dm_list list;
+ struct dm_report_group *group;
+ struct dm_report *report;
+ union {
+ uint32_t orig_report_flags;
+ uint32_t finished_count;
+ } store;
+ struct report_group_item *parent;
+ int output_done:1;
+ int needs_closing:1;
+ void *data;
};
/*
@@ -4426,16 +4451,171 @@ int dm_report_is_empty(struct dm_report *rh)
return dm_list_empty(&rh->rows) ? 1 : 0;
}
+static struct report_group_item *_get_topmost_report_group_item(struct dm_report_group *group)
+{
+ struct report_group_item *item;
+
+ if (group && !dm_list_empty(&group->items))
+ item = dm_list_item(dm_list_first(&group->items), struct report_group_item);
+ else
+ item = NULL;
+
+ return item;
+}
+
int dm_report_output(struct dm_report *rh)
{
- if (dm_list_empty(&rh->rows))
- return 1;
+ int r;
+
+ if (dm_list_empty(&rh->rows)) {
+ r = 1;
+ goto out;
+ }
if ((rh->flags & RH_SORT_REQUIRED))
_sort_rows(rh);
if ((rh->flags & DM_REPORT_OUTPUT_COLUMNS_AS_ROWS))
- return _output_as_rows(rh);
+ r = _output_as_rows(rh);
else
- return _output_as_columns(rh);
+ r = _output_as_columns(rh);
+out:
+ if (r && rh && rh->group_item)
+ rh->group_item->output_done = 1;
+ return r;
+}
+
+struct dm_report_group *dm_report_group_create(dm_report_group_type_t type, void *data)
+{
+ struct dm_report_group *group;
+ struct dm_pool *mem;
+ struct report_group_item *item;
+
+ if (!(mem = dm_pool_create("report_group", 1024))) {
+ log_error("dm_report: dm_report_init_group: failed to allocate mem pool");
+ return NULL;
+ }
+
+ if (!(group = dm_pool_zalloc(mem, sizeof(*group)))) {
+ log_error("dm_report: failed to allocate report group structure");
+ goto bad;
+ }
+
+ group->mem = mem;
+ group->type = type;
+ dm_list_init(&group->items);
+
+ if (!(item = dm_pool_zalloc(mem, sizeof(*item)))) {
+ log_error("dm_report: faile to allocate root report group item");
+ goto bad;
+ }
+
+ dm_list_add_h(&group->items, &item->list);
+
+ switch (type) {
+ default:
+ goto_bad;
+ }
+
+ return group;
+bad:
+ dm_pool_destroy(mem);
+ return NULL;
+}
+
+int dm_report_group_push(struct dm_report_group *group, struct dm_report *report, void *data)
+{
+ struct report_group_item *item, *tmp_item;
+
+ if (!group)
+ return 1;
+
+ if (!(item = dm_pool_zalloc(group->mem, sizeof(*item)))) {
+ log_error("dm_report: dm_report_group_push: group item allocation failed");
+ return 0;
+ }
+
+ if ((item->report = report)) {
+ item->store.orig_report_flags = report->flags;
+ report->group_item = item;
+ }
+ item->group = group;
+ item->data = data;
+
+ dm_list_iterate_items(tmp_item, &group->items) {
+ if (!tmp_item->report) {
+ item->parent = tmp_item;
+ break;
+ }
+ }
+
+ dm_list_add_h(&group->items, &item->list);
+
+ switch (group->type) {
+ default:
+ goto_bad;
+ }
+
+ return 1;
+bad:
+ dm_list_del(&item->list);
+ dm_pool_free(group->mem, item);
+ return 0;
+}
+
+int dm_report_group_pop(struct dm_report_group *group)
+{
+ struct report_group_item *item;
+
+ if (!group)
+ return 1;
+
+ if (!(item = _get_topmost_report_group_item(group))) {
+ log_error("dm_report: dm_report_group_pop: group has no items");
+ return 0;
+ }
+
+ switch (group->type) {
+ default:
+ return 0;
+ }
+
+ dm_list_del(&item->list);
+
+ if (item->report) {
+ item->report->flags = item->store.orig_report_flags;
+ item->report->group_item = NULL;
+ }
+
+ if (item->parent)
+ item->parent->store.finished_count++;
+
+ dm_pool_free(group->mem, item);
+ return 1;
+}
+
+int dm_report_group_destroy(struct dm_report_group *group)
+{
+ struct report_group_item *item, *tmp_item;
+ int r = 0;
+
+ if (!group)
+ return 1;
+
+ dm_list_iterate_items_safe(item, tmp_item, &group->items) {
+ if (item->report && !dm_report_output(item->report))
+ goto_out;
+ if (!dm_report_group_pop(group))
+ goto_out;
+ }
+
+ switch (group->type) {
+ default:
+ goto_out;
+ }
+
+ r = 1;
+out:
+ dm_pool_destroy(group->mem);
+ return r;
}
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=029f51e1a853297c…
Commit: 029f51e1a853297ca7246b75ac80cde9de23a2a4
Parent: 899a4ca275543425ca60fe361bc13fbc5c90e741
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Fri Jun 17 12:10:43 2016 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Fri Jun 17 12:22:58 2016 -0500
vgreduce: fix location of lvmlockd global lock
The lvmlockd global lock was missing the non-repair case,
which caused the new orphan PV created by vgreduce to
not be seen by other hosts.
---
tools/vgreduce.c | 12 +++++-------
1 files changed, 5 insertions(+), 7 deletions(-)
diff --git a/tools/vgreduce.c b/tools/vgreduce.c
index 19a0bb0..3176a0e 100644
--- a/tools/vgreduce.c
+++ b/tools/vgreduce.c
@@ -217,6 +217,11 @@ int vgreduce(struct cmd_context *cmd, int argc, char **argv)
argv++;
argc--;
+ /* Needed to change the set of orphan PVs. */
+ if (!lockd_gl(cmd, "ex", 0))
+ return_ECMD_FAILED;
+ cmd->lockd_gl_disable = 1;
+
if (!(handle = init_processing_handle(cmd))) {
log_error("Failed to initialize processing handle.");
return ECMD_FAILED;
@@ -236,13 +241,6 @@ int vgreduce(struct cmd_context *cmd, int argc, char **argv)
vp.force = arg_count(cmd, force_ARG);
- /* Needed to change the set of orphan PVs. */
- if (!lockd_gl(cmd, "ex", 0)) {
- ret = ECMD_FAILED;
- goto_out;
- }
- cmd->lockd_gl_disable = 1;
-
cmd->handles_missing_pvs = 1;
init_ignore_suspended_devices(1);
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=899a4ca275543425…
Commit: 899a4ca275543425ca60fe361bc13fbc5c90e741
Parent: ab7ade40957812b948a63527d1023747f8336e56
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Fri Jun 17 11:45:08 2016 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Fri Jun 17 12:21:09 2016 -0500
lvmlockd: fix dropping PVs in rescanning VG
This fixes a problem in commit ae0a8740c. The problem
in that commit was that all existing PVs are initially
dropped from lvmetad. This works if the VG is updated
at the end, which replaces the dropped PVs, but if the
rescan finds that the VG seqno is unchanged, it leaves
the cached VG in place. So, we should only drop the
existing PVs in lvmetad when the VG is going to be updated.
---
lib/cache/lvmetad.c | 48 ++++++++++++++++++++++++++++++------------------
1 files changed, 30 insertions(+), 18 deletions(-)
diff --git a/lib/cache/lvmetad.c b/lib/cache/lvmetad.c
index 0f1f269..0508291 100644
--- a/lib/cache/lvmetad.c
+++ b/lib/cache/lvmetad.c
@@ -1675,8 +1675,9 @@ static struct volume_group *lvmetad_pvscan_vg(struct cmd_context *cmd, struct vo
struct dm_config_tree *vgmeta_ret = NULL;
struct dm_config_tree *vgmeta;
struct pv_list *pvl, *pvl_new;
- struct device_list *devl, *devl_new;
+ struct device_list *devl, *devl_new, *devlsafe;
struct dm_list pvs_scan;
+ struct dm_list pvs_drop;
struct dm_list pvs_new;
struct lvmcache_info *info;
struct format_instance *fid;
@@ -1689,6 +1690,7 @@ static struct volume_group *lvmetad_pvscan_vg(struct cmd_context *cmd, struct vo
int found;
dm_list_init(&pvs_scan);
+ dm_list_init(&pvs_drop);
dm_list_init(&pvs_new);
log_debug_lvmetad("Rescanning VG %s (seqno %u).", vg->name, vg->seqno);
@@ -1713,23 +1715,12 @@ static struct volume_group *lvmetad_pvscan_vg(struct cmd_context *cmd, struct vo
dm_list_add(&pvs_scan, &devl->list);
}
- /*
- * Drop stale info from lvmetad.
- */
- dm_list_iterate_items(devl, &pvs_scan) {
- if (!devl->dev)
- continue;
- log_debug_lvmetad("Rescan VG %s dropping %s.", vg->name, dev_name(devl->dev));
- if (!lvmetad_pv_gone_by_dev(devl->dev))
- return_NULL;
- }
-
scan_more:
/*
* Run the equivalent of lvmetad_pvscan_single on each dev in the VG.
*/
- dm_list_iterate_items(devl, &pvs_scan) {
+ dm_list_iterate_items_safe(devl, devlsafe, &pvs_scan) {
if (!devl->dev)
continue;
@@ -1742,6 +1733,7 @@ scan_more:
if ((info = lvmcache_info_from_pvid(devl->dev->pvid, NULL, 0)))
lvmcache_del(info);
+ dm_list_move(&pvs_drop, &devl->list);
continue;
}
@@ -1755,6 +1747,7 @@ scan_more:
if (baton.fid->fmt->features & FMT_OBSOLETE) {
log_debug_lvmetad("Ignoring obsolete format on PV %s in VG %s.", dev_name(devl->dev), vg->name);
lvmcache_fmt(info)->ops->destroy_instance(baton.fid);
+ dm_list_move(&pvs_drop, &devl->list);
continue;
}
@@ -1770,8 +1763,7 @@ scan_more:
if (!baton.vg) {
log_debug_lvmetad("Rescan VG %s did not find %s.", vg->name, dev_name(devl->dev));
lvmcache_fmt(info)->ops->destroy_instance(baton.fid);
- lvmetad_pv_found(cmd, (const struct id *) &devl->dev->pvid, devl->dev,
- lvmcache_fmt(info), label->sector, NULL, NULL, NULL);
+ dm_list_move(&pvs_drop, &devl->list);
continue;
}
@@ -1783,8 +1775,7 @@ scan_more:
log_debug_lvmetad("Rescan VG %s found different VG %s on PV %s.",
vg->name, baton.vg->name, dev_name(devl->dev));
release_vg(baton.vg);
- lvmetad_pv_found(cmd, (const struct id *) &devl->dev->pvid, devl->dev,
- lvmcache_fmt(info), label->sector, NULL, NULL, NULL);
+ dm_list_move(&pvs_drop, &devl->list);
continue;
}
@@ -1873,9 +1864,19 @@ scan_more:
}
/*
- * Change the metadata into a vg struct to return.
+ * Remove pvs_drop entries from lvmetad.
*/
+ dm_list_iterate_items(devl, &pvs_drop) {
+ if (!devl->dev)
+ continue;
+ log_debug_lvmetad("Rescan VG %s dropping %s.", vg->name, dev_name(devl->dev));
+ if (!lvmetad_pv_gone_by_dev(devl->dev))
+ return_NULL;
+ }
+ /*
+ * Update the VG in lvmetad.
+ */
if (vgmeta_ret) {
fid = lvmcache_fmt(info)->ops->create_instance(lvmcache_fmt(info), &fic);
if (!(vg_ret = import_vg_from_config_tree(vgmeta_ret, fid))) {
@@ -1889,10 +1890,21 @@ scan_more:
* The "precommitted" name is a misnomer in this case,
* but that is the field which lvmetad_vg_update() uses
* to send the metadata cft to lvmetad.
+ *
+ * When the seqno is unchanged the cached VG can be left.
*/
if (save_seqno != vg->seqno) {
+ dm_list_iterate_items(devl, &pvs_scan) {
+ if (!devl->dev)
+ continue;
+ log_debug_lvmetad("Rescan VG %s dropping to replace %s.", vg->name, dev_name(devl->dev));
+ if (!lvmetad_pv_gone_by_dev(devl->dev))
+ return_NULL;
+ }
+
log_debug_lvmetad("Rescan VG %s updating lvmetad from seqno %u to seqno %u.",
vg->name, vg->seqno, save_seqno);
+
vg_ret->cft_precommitted = vgmeta_ret;
if (!lvmetad_vg_update(vg_ret))
log_error("Failed to update lvmetad with new VG meta");
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=3fbdd8be03f22912…
Commit: 3fbdd8be03f229121b6c2245721617a26b152618
Parent: 0000000000000000000000000000000000000000
Author: Alasdair G Kergon <agk(a)redhat.com>
AuthorDate: 2016-06-17 13:12 +0000
Committer: Alasdair G Kergon <agk(a)redhat.com>
CommitterDate: 2016-06-17 13:12 +0000
annotated tag: v2_02_157 has been created
at 3fbdd8be03f229121b6c2245721617a26b152618 (tag)
tagging 38cc03605ceff43a8a7733b72ed9da94f9598e00 (commit)
replaces v2_02_156
Release 2.02.157.
Just one change this week, so the boot isn't broken
if lvmetad is expected to be running but isn't
available.
7 files changed, 184 insertions(+), 36 deletions(-)
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.14 (GNU/Linux)
iEYEABECAAYFAldj918ACgkQIoGRwVZ+LBf5UACff1NWccZca44LPgtcUq0dhtTt
3Z0An0yzTCL/o00tnL4wEg+OfiGBdwWJ
=/2Yg
-----END PGP SIGNATURE-----
Alasdair G Kergon (2):
post-release
pre-release
David Teigland (4):
lvmlockd: fix rescanning VG
pvscan: do activation when lvmetad is not running
pvscan: fix lvmlockd global lock
pvscan: don't activate LVs when use_lvmetad=0
Peter Rajnoha (1):
tools: add missing destroy_processing_handle in pvscan and vgreduce code
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=f77fe436afb76ddb…
Commit: f77fe436afb76ddb798d236d34daf50413a184f6
Parent: 944ae4d2df0f15afb29ac0a68d0dd012d9df9acf
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Thu Jun 16 12:04:05 2016 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Thu Jun 16 12:04:05 2016 -0500
pvscan: don't activate LVs when use_lvmetad=0
commit 15da467b was meant to address the case where
use_lvmetad=1 in lvm.conf, and lvmetad is not available,
in which case, pvscan --cache -aay should activate LVs.
But the commit unintentionally also changed the case
where use_lvmetad=0 in lvm.conf, in which case
pvscan --cache -aay should not activate LVs, so fix
that here.
---
tools/pvscan.c | 31 ++++++++++++++++++++-----------
1 files changed, 20 insertions(+), 11 deletions(-)
diff --git a/tools/pvscan.c b/tools/pvscan.c
index 78dad82..73a97be 100644
--- a/tools/pvscan.c
+++ b/tools/pvscan.c
@@ -306,7 +306,7 @@ static int _pvscan_cache(struct cmd_context *cmd, int argc, char **argv)
int devno_args = 0;
struct arg_value_group_list *current_group;
dev_t devno;
- int do_activate = 0;
+ int do_activate;
int all_vgs = 0;
int remove_errors = 0;
int add_errors = 0;
@@ -315,17 +315,21 @@ static int _pvscan_cache(struct cmd_context *cmd, int argc, char **argv)
dm_list_init(&found_vgnames);
dm_list_init(&pp.changed_vgnames);
- if (!lvmetad_used() && !arg_is_set(cmd, activate_ARG)) {
- log_verbose("Ignoring pvscan --cache command because lvmetad is not in use.");
+ do_activate = arg_is_set(cmd, activate_ARG);
+
+ if (!lvmetad_used() && !do_activate) {
+ log_verbose("Ignoring pvscan --cache because lvmetad is not in use.");
return ret;
}
- if (arg_is_set(cmd, activate_ARG)) {
- if (arg_uint_value(cmd, activate_ARG, CHANGE_AAY) != CHANGE_AAY) {
- log_error("Only --activate ay allowed with pvscan.");
- return 0;
- }
- do_activate = 1;
+ if (do_activate && (arg_uint_value(cmd, activate_ARG, CHANGE_AAY) != CHANGE_AAY)) {
+ log_error("Only --activate ay allowed with pvscan.");
+ return 0;
+ }
+
+ if (!lvmetad_used() && do_activate && !find_config_tree_bool(cmd, global_use_lvmetad_CFG, NULL)) {
+ log_verbose("Ignoring pvscan --cache -aay because lvmetad is not in use.");
+ return ret;
}
if (arg_count(cmd, major_ARG) + arg_count(cmd, minor_ARG))
@@ -341,8 +345,13 @@ static int _pvscan_cache(struct cmd_context *cmd, int argc, char **argv)
return ECMD_FAILED;
}
- if (!lvmetad_used() && do_activate) {
- log_verbose("Activating all VGs without lvmetad running.");
+ /*
+ * This a special case where use_lvmetad=1 in lvm.conf but pvscan
+ * cannot use lvmetad for some reason. In this case pvscan should
+ * still activate LVs even though it's not updating the cache.
+ */
+ if (do_activate && !lvmetad_used()) {
+ log_verbose("Activating all VGs without lvmetad.");
all_vgs = 1;
devno_args = 0;
goto activate;
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=944ae4d2df0f15af…
Commit: 944ae4d2df0f15afb29ac0a68d0dd012d9df9acf
Parent: 15da467b52465076a8d587b94cc638bab8a0a95c
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Wed Jun 15 16:51:36 2016 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Wed Jun 15 16:51:36 2016 -0500
pvscan: fix lvmlockd global lock
This should have been removed when pvscan was
recently converted to use process_each_pv which
does the lvmlockd locking.
---
tools/pvscan.c | 4 ----
1 files changed, 0 insertions(+), 4 deletions(-)
diff --git a/tools/pvscan.c b/tools/pvscan.c
index 5987e8b..78dad82 100644
--- a/tools/pvscan.c
+++ b/tools/pvscan.c
@@ -624,10 +624,6 @@ int pvscan(struct cmd_context *cmd, int argc, char **argv)
return ECMD_FAILED;
}
- /* Needed for a current listing of the global VG namespace. */
- if (!lockd_gl(cmd, "sh", 0))
- return_ECMD_FAILED;
-
if (!(handle = init_processing_handle(cmd))) {
log_error("Failed to initialize processing handle.");
ret = ECMD_FAILED;
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=15da467b52465076…
Commit: 15da467b52465076a8d587b94cc638bab8a0a95c
Parent: ae0a8740c5899520ec4c94fbf080623167d8ecba
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Wed Jun 15 14:19:18 2016 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Wed Jun 15 14:19:18 2016 -0500
pvscan: do activation when lvmetad is not running
When pvscan --cache -aay fails to connect to lvmetad it will
simply exit and do nothing. Change this so that it will
skip the lvmetad cache step and do the activation step from
disk.
---
tools/pvscan.c | 9 ++++++++-
1 files changed, 8 insertions(+), 1 deletions(-)
diff --git a/tools/pvscan.c b/tools/pvscan.c
index 3e9efef..5987e8b 100644
--- a/tools/pvscan.c
+++ b/tools/pvscan.c
@@ -315,7 +315,7 @@ static int _pvscan_cache(struct cmd_context *cmd, int argc, char **argv)
dm_list_init(&found_vgnames);
dm_list_init(&pp.changed_vgnames);
- if (!lvmetad_used()) {
+ if (!lvmetad_used() && !arg_is_set(cmd, activate_ARG)) {
log_verbose("Ignoring pvscan --cache command because lvmetad is not in use.");
return ret;
}
@@ -341,6 +341,13 @@ static int _pvscan_cache(struct cmd_context *cmd, int argc, char **argv)
return ECMD_FAILED;
}
+ if (!lvmetad_used() && do_activate) {
+ log_verbose("Activating all VGs without lvmetad running.");
+ all_vgs = 1;
+ devno_args = 0;
+ goto activate;
+ }
+
/*
* Scan all devices when no args are given.
*/
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=dc2a9aaa637ffc7b…
Commit: dc2a9aaa637ffc7b38829dba86a30ddd22fe4c75
Parent: 0000000000000000000000000000000000000000
Author: Alasdair G Kergon <agk(a)redhat.com>
AuthorDate: 2016-06-10 23:08 +0000
Committer: Alasdair G Kergon <agk(a)redhat.com>
CommitterDate: 2016-06-10 23:08 +0000
annotated tag: v2_02_156 has been created
at dc2a9aaa637ffc7b38829dba86a30ddd22fe4c75 (tag)
tagging f2d1f5e9273232fccc05cc819b28ea47f7da7ff9 (commit)
replaces v2_02_155
Release 2.02.156.
Another development release with an assortment of bug fixes and some
extensions to the not-yet-finalised D-Bus support.
29 files changed, 939 insertions(+), 307 deletions(-)
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.14 (GNU/Linux)
iEYEABECAAYFAldbSQgACgkQIoGRwVZ+LBd0HwCeIcQOovZtM4ES7zipS5Tdeb3l
iLoAn0o/0C1bkpTIOcm0F1CBtrOkr6nB
=gbnf
-----END PGP SIGNATURE-----
Alasdair G Kergon (2):
post-release
pre-release
David Teigland (7):
lvmetad: define special update in progress string
lvmetad: remove disabled case for "scan error"
lvmetad: handle update failures
lvmcache: add optional dev arg to lvmcache_info_from_pvid
lvmcache: fix duplicate handling with multiple scans
vgcreate, pvcreate, vgextend: don't use a device with duplicates
WHATS_NEW: add recent changes
Peter Rajnoha (2):
blkdeactivate: fix regression in blkdeactivate causing dm and md devices to be skipped.
lvmdump: also collect output from lsblk command when running lvmdump -s
Tony Asleson (9):
lvmdbusd: Add roles property to LV common interface
lvmdbusd: Add data_lv and metadata_lv to cache pool interface
lvmdbusd: Bug fix for missing LV properties
lvmdbusd: Change print statement to py3 syntax
lvmdbusd: Rename get_object_path_by_lvm_id
lvmdbusd: Add method get_object_path_by_lvm_id
lvmdbusd: Create correct LV object type
lvmdbusd: Add test for DataLv & MetaDataLv
lvmdbusd: Remove duplicate test code
Zdenek Kabelac (2):
display: yes no prompt improvement
cleanup: typo in WHATS_NEW_DM
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=cdf06044e189ec1a…
Commit: cdf06044e189ec1adeaba101a21598c31752b9cd
Parent: b81186e535f0c93ef8b276cfb2b7bcf55268aec0
Author: Tony Asleson <tasleson(a)redhat.com>
AuthorDate: Fri Jun 10 12:11:17 2016 -0500
Committer: Tony Asleson <tasleson(a)redhat.com>
CommitterDate: Fri Jun 10 16:05:03 2016 -0500
lvmdbusd: Create correct LV object type
We were initially looking to see if an LV was hidden and if it was we were
creating an instance of a LvCommon object to represent it. Thus if we
had a hidden cache pool for example we were missing the methods and
properties for the cache pool. However, when we create the object path,
any hidden LVs, regardless of type/functionality will be placed in the
hidden path.
---
daemons/lvmdbusd/lv.py | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/daemons/lvmdbusd/lv.py b/daemons/lvmdbusd/lv.py
index e32f8e5..5c7b3b5 100644
--- a/daemons/lvmdbusd/lv.py
+++ b/daemons/lvmdbusd/lv.py
@@ -176,8 +176,6 @@ class LvState(State):
self.Name, (self.Attr, self.layout, self.role))
def _object_type_create(self):
- if self.Name[0] == '[':
- return LvCommon
if self.Attr[0] == 't':
return LvThinPool
elif self.Attr[0] == 'C':
@@ -185,6 +183,8 @@ class LvState(State):
return LvCachePool
else:
return LvCacheLv
+ elif self.Name[0] == '[':
+ return LvCommon
elif self.OriginLv != '/':
return LvSnapShot
else:
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=41ebed707700e926…
Commit: 41ebed707700e926d4224bc62289ea47014d9a0d
Parent: b717c5efae942c845f07d695593cfb2406627fe9
Author: Tony Asleson <tasleson(a)redhat.com>
AuthorDate: Mon Jun 6 15:06:50 2016 -0500
Committer: Tony Asleson <tasleson(a)redhat.com>
CommitterDate: Fri Jun 10 15:28:42 2016 -0500
lvmdbusd: Change print statement to py3 syntax
---
daemons/lvmdbusd/objectmanager.py | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/daemons/lvmdbusd/objectmanager.py b/daemons/lvmdbusd/objectmanager.py
index f28c5c8..f8f6d97 100644
--- a/daemons/lvmdbusd/objectmanager.py
+++ b/daemons/lvmdbusd/objectmanager.py
@@ -124,8 +124,8 @@ class ObjectManager(AutomatedProperties):
with self.rlock:
path, props = dbus_object.emit_data()
- # print 'Registering object path %s for %s' %
- # (path, dbus_object.lvm_id)
+ # print('Registering object path %s for %s' %
+ # (path, dbus_object.lvm_id))
# We want fast access to the object by a number of different ways
# so we use multiple hashs with different keys
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=b717c5efae942c84…
Commit: b717c5efae942c845f07d695593cfb2406627fe9
Parent: e04705b305626d37cbd076b47d6ad37c9b1b282e
Author: Tony Asleson <tasleson(a)redhat.com>
AuthorDate: Fri Jun 10 11:58:55 2016 -0500
Committer: Tony Asleson <tasleson(a)redhat.com>
CommitterDate: Fri Jun 10 15:28:42 2016 -0500
lvmdbusd: Bug fix for missing LV properties
When we are processing the LVs we need to build up dbus objects from least
dependent to most dependent, so that we have information available when
constructing.
---
daemons/lvmdbusd/lv.py | 41 ++++++++++++++++++++++++++++++++++++++++-
1 files changed, 40 insertions(+), 1 deletions(-)
diff --git a/daemons/lvmdbusd/lv.py b/daemons/lvmdbusd/lv.py
index 61cf7d3..2786f68 100644
--- a/daemons/lvmdbusd/lv.py
+++ b/daemons/lvmdbusd/lv.py
@@ -24,6 +24,39 @@ from . import background
from .utils import round_size
+# Try and build a key for a LV, so that we sort the LVs with least dependencies
+# first. This may be error prone because of the flexibility LVM
+# provides and what you can stack.
+def get_key(i):
+
+ name = i['lv_name']
+ parent = i['lv_parent']
+ pool = i['pool_lv']
+ a1 = ""
+ a2 = ""
+
+ if name[0] == '[':
+ a1 = '#'
+
+ # We have a parent
+ if parent:
+ # Check if parent is hidden
+ if parent[0] == '[':
+ a2 = '##'
+ else:
+ a2 = '#'
+
+ # If a LV has a pool, then it should be sorted/loaded after the pool
+ # lv, unless it's a hidden too, then after other hidden, but before visible
+ if pool:
+ if pool[0] != '[':
+ a2 += '~'
+ else:
+ a1 = '$' + a1
+
+ return "%s%s%s" % (a1, a2, name)
+
+
# noinspection PyUnusedLocal
def lvs_state_retrieve(selection, cache_refresh=True):
rc = []
@@ -31,7 +64,13 @@ def lvs_state_retrieve(selection, cache_refresh=True):
if cache_refresh:
cfg.db.refresh()
- for l in cfg.db.fetch_lvs(selection):
+ # When building up the model, it's best to process LVs with the least
+ # dependencies to those that are dependant upon other LVs. Otherwise, when
+ # we are trying to gather information we could be in a position where we
+ # don't have information available yet.
+ lvs = sorted(cfg.db.fetch_lvs(selection), key=get_key)
+
+ for l in lvs:
rc.append(LvState(
l['lv_uuid'], l['lv_name'],
l['lv_path'], n(l['lv_size']),
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=ad414e5ad61a25b9…
Commit: ad414e5ad61a25b97975c1d2e060e65050d45a69
Parent: 35612bd27c203774948c84005c9fb9237746c34a
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Fri Jun 3 15:33:27 2016 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Fri Jun 10 16:01:22 2016 +0200
cleanup: typo in WHATS_NEW_DM
---
WHATS_NEW_DM | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM
index 9c84854..371e8b5 100644
--- a/WHATS_NEW_DM
+++ b/WHATS_NEW_DM
@@ -104,7 +104,7 @@ Version 1.02.110 - 30th October 2015
Correct use of max_write_behind parameter when generating raid target line.
Fix dm-event systemd service to make sure it is executed before mounting.
-Version 1.02.109 - 22nd September 2016
+Version 1.02.109 - 22nd September 2015
======================================
Update man pages for dmsetup and dmstats.
Improve help text for dmsetup.
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=cfdc87b62331875c…
Commit: cfdc87b62331875c2f10cca2c41f486d40b2a67c
Parent: 86f92714574487cce6a9de785ba2ff93b23a98f7
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Thu Jun 9 13:51:09 2016 +0200
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Thu Jun 9 13:54:15 2016 +0200
lvmdump: also collect output from lsblk command when running lvmdump -s
lsblk provides nice and quick overview of the storage/sysfs structure
that is useful for debugging - collect its output when running lvmdump -s.
---
WHATS_NEW | 1 +
man/lvmdump.8.in | 9 +++++----
scripts/lvmdump.sh | 11 ++++++++++-
3 files changed, 16 insertions(+), 5 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index 2e7e138..0afd527 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.156 -
================================
+ If available, also collect output from lsblk command when running lvmdump -s.
Fix regression in blkdeactivate causing dm and md devices to be skipped. (2.02.155)
Version 2.02.155 - 3rd June 2016
diff --git a/man/lvmdump.8.in b/man/lvmdump.8.in
index f9c2284..d0e102e 100644
--- a/man/lvmdump.8.in
+++ b/man/lvmdump.8.in
@@ -85,10 +85,11 @@ history for all yet uncollected results of polling operations already finished
including reason.
.TP
.B \-s
-Gather system info and context. Currently, this encompasses systemd info
-and context only: overall state of systemd units present in the system,
-more detailed status of units controlling LVM functionality and the content
-of systemd journal for current boot.
+Gather system info and context. Currently, this encompasses info gathered
+by calling lsblk command and various systemd info and context: overall state
+of systemd units present in the system, more detailed status of units
+controlling LVM functionality and the content of systemd journal for
+current boot.
.TP
.B \-u
Gather udev info and context: /etc/udev/udev.conf file, udev daemon version
diff --git a/scripts/lvmdump.sh b/scripts/lvmdump.sh
index a813537..bfe79d9 100755
--- a/scripts/lvmdump.sh
+++ b/scripts/lvmdump.sh
@@ -252,13 +252,22 @@ if (( $sysreport )); then
SYSTEMCTL=$(which systemctl 2>> $log)
JOURNALCTL=$(which journalctl 2>> $log)
+ LSBLK=$(which lsblk 2>> $log)
+
+ log "$MKDIR -p \"$sysreport_dir\""
+
+ if test -z "LSBLK"; then
+ myecho "WARNING: lsblk not found"
+ else
+ log "$LSBLK -O >> \"$sysreport_dir/lsblk\""
+ log "$LSBLK -s >> \"$sysreport_dir/lsblk_s\""
+ fi
if test -z "$SYSTEMCTL"; then
myecho "WARNING: systemctl not found"
elif test -z "$JOURNALCTL"; then
myecho "WARNING: journalctl not found"
else
- log "$MKDIR -p \"$sysreport_dir\""
log "$JOURNALCTL -b --no-pager -o short-precise > \"$sysreport_dir/journal_content\" 2>> \"$log\""
log "$SYSTEMCTL status -l --no-pager -n $log_lines -o short-precise dm-event.socket dm-event.service \
lvm2-monitor.service \
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=199b7b55c21270d6…
Commit: 199b7b55c21270d62ce35f32b16df200417dc41c
Parent: 01156de6f70ba5b1c8e2ae23c655ccd36ac59441
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Mon Jun 6 15:20:55 2016 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Tue Jun 7 15:15:51 2016 -0500
lvmcache: fix duplicate handling with multiple scans
Some commands scan labels to populate lvmcache multiple
times, i.e. lvmcache_init, scan labels to fill lvmcache,
lvmcache_destroy, then later repeat
Each time labels are scanned, duplicates are detected,
and preferred devices are chosen. Each time this is done
within a single command, we want to choose the same
preferred devices. So, check for existing preferences
when choosing preferred devices.
This also fixes a problem with the list of unused duplicate
devs when run in an lvm shell. The devs had been allocated
from cmd memory, resulting in invalid list entries between
commands.
---
lib/cache/lvmcache.c | 90 ++++++++++++++++++++++++++++++++++++++-----
lib/commands/toolcontext.c | 2 +
lib/commands/toolcontext.h | 1 +
3 files changed, 82 insertions(+), 11 deletions(-)
diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c
index 1af6363..87b25f1 100644
--- a/lib/cache/lvmcache.c
+++ b/lib/cache/lvmcache.c
@@ -97,6 +97,8 @@ int lvmcache_init(void)
_vgs_locked = 0;
dm_list_init(&_vginfos);
+ dm_list_init(&_found_duplicate_devs);
+ dm_list_init(&_unused_duplicate_devs);
if (!(_vgname_hash = dm_hash_create(128)))
return 0;
@@ -471,6 +473,16 @@ void lvmcache_remove_unchosen_duplicate(struct device *dev)
}
}
+static void _destroy_duplicate_device_list(struct dm_list *head)
+{
+ struct device_list *devl, *devl2;
+
+ dm_list_iterate_items_safe(devl, devl2, head) {
+ dm_list_del(&devl->list);
+ dm_free(devl);
+ }
+ dm_list_init(head);
+}
static void _vginfo_attach_info(struct lvmcache_vginfo *vginfo,
struct lvmcache_info *info)
@@ -807,17 +819,22 @@ int vg_has_duplicate_pvs(struct volume_group *vg)
return 0;
}
-int lvmcache_dev_is_unchosen_duplicate(struct device *dev)
+static int _dev_in_device_list(struct device *dev, struct dm_list *head)
{
struct device_list *devl;
- dm_list_iterate_items(devl, &_unused_duplicate_devs) {
+ dm_list_iterate_items(devl, head) {
if (devl->dev == dev)
return 1;
}
return 0;
}
+int lvmcache_dev_is_unchosen_duplicate(struct device *dev)
+{
+ return _dev_in_device_list(dev, &_unused_duplicate_devs);
+}
+
/*
* Compare _found_duplicate_devs entries with the corresponding duplicate dev
* in lvmcache. There may be multiple duplicates in _found_duplicate_devs for
@@ -843,6 +860,7 @@ static void _choose_preferred_devs(struct cmd_context *cmd,
char uuid[64] __attribute__((aligned(8)));
const char *reason = "none";
struct dm_list altdevs;
+ struct dm_list new_unused;
struct dev_types *dt = cmd->dev_types;
struct device_list *devl, *devl_safe, *alt, *del;
struct lvmcache_info *info;
@@ -854,8 +872,11 @@ static void _choose_preferred_devs(struct cmd_context *cmd,
int has_fs1, has_fs2;
int has_lv1, has_lv2;
int same_size1, same_size2;
+ int prev_unchosen1, prev_unchosen2;
int change;
+ dm_list_init(&new_unused);
+
/*
* Create a list of all alternate devs for the same pvid: altdevs.
*/
@@ -873,8 +894,11 @@ next:
}
}
- if (!alt)
+ if (!alt) {
+ _destroy_duplicate_device_list(&_unused_duplicate_devs);
+ dm_list_splice(&_unused_duplicate_devs, &new_unused);
return;
+ }
/*
* Find the device for the pvid that's currently in lvmcache.
@@ -904,6 +928,21 @@ next:
continue;
}
+ prev_unchosen1 = _dev_in_device_list(dev1, &_unused_duplicate_devs);
+ prev_unchosen2 = _dev_in_device_list(dev2, &_unused_duplicate_devs);
+
+ if (!prev_unchosen1 && !prev_unchosen2) {
+ /*
+ * The cmd list saves the unchosen preference across
+ * lvmcache_destroy. Sometimes a single command will
+ * fill lvmcache, destroy it, and refill it, and we
+ * want the same duplicate preference to be preserved
+ * in each instance of lvmcache for a single command.
+ */
+ prev_unchosen1 = _dev_in_device_list(dev1, &cmd->unused_duplicate_devs);
+ prev_unchosen2 = _dev_in_device_list(dev2, &cmd->unused_duplicate_devs);
+ }
+
dev1_major = MAJOR(dev1->dev);
dev1_minor = MINOR(dev1->dev);
dev2_major = MAJOR(dev2->dev);
@@ -941,6 +980,11 @@ next:
dev_name(dev1), (unsigned long long)dev1_size,
dev_name(dev2), (unsigned long long)dev2_size);
+ log_debug_cache("PV %s: %s was prev %s. %s was prev %s.",
+ devl->dev->pvid,
+ dev_name(dev1), prev_unchosen1 ? "not chosen" : "<none>",
+ dev_name(dev2), prev_unchosen2 ? "not chosen" : "<none>");
+
log_debug_cache("PV %s: %s %s subsystem. %s %s subsystem.",
devl->dev->pvid,
dev_name(dev1), in_subsys1 ? "is in" : "is not in",
@@ -963,7 +1007,14 @@ next:
change = 0;
- if (has_lv1 && !has_lv2) {
+ if (prev_unchosen1 && !prev_unchosen2) {
+ /* change to 2 (NB when unchosen is set we unprefer) */
+ change = 1;
+ reason = "of previous preference";
+ } else if (prev_unchosen2 && !prev_unchosen1) {
+ /* keep 1 (NB when unchosen is set we unprefer) */
+ reason = "of previous preference";
+ } else if (has_lv1 && !has_lv2) {
/* keep 1 */
reason = "device is used by LV";
} else if (has_lv2 && !has_lv1) {
@@ -1023,7 +1074,7 @@ next:
dm_list_move(add_cache_devs, &alt->list);
- if ((del = dm_pool_alloc(cmd->mem, sizeof(*del)))) {
+ if ((del = dm_zalloc(sizeof(*del)))) {
del->dev = info->dev;
dm_list_add(del_cache_devs, &del->list);
}
@@ -1039,7 +1090,7 @@ next:
* duplicates not being used in lvmcache.
*/
- dm_list_splice(&_unused_duplicate_devs, &altdevs);
+ dm_list_splice(&new_unused, &altdevs);
goto next;
}
@@ -1087,6 +1138,11 @@ int lvmcache_label_scan(struct cmd_context *cmd)
log_very_verbose("Scanning device labels");
+ /*
+ * Duplicates found during this label scan are added to _found_duplicate_devs().
+ */
+ _destroy_duplicate_device_list(&_found_duplicate_devs);
+
while ((dev = dev_iter_get(iter))) {
(void) label_read(dev, &label, UINT64_C(0));
dev_count++;
@@ -2127,7 +2183,7 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller,
* use it.
*/
- if (!(devl = dm_pool_alloc(fmt->cmd->mem, sizeof(*devl))))
+ if (!(devl = dm_zalloc(sizeof(*devl))))
return_NULL;
devl->dev = dev;
@@ -2266,13 +2322,25 @@ void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans, int reset)
log_error(INTERNAL_ERROR "_vginfos list should be empty");
dm_list_init(&_vginfos);
+ /*
+ * Copy the current _unused_duplicate_devs into a cmd list before
+ * destroying _unused_duplicate_devs.
+ *
+ * One command can init/populate/destroy lvmcache multiple times. Each
+ * time it will encounter duplicates and choose the preferrred devs.
+ * We want the same preferred devices to be chosen each time, so save
+ * the unpreferred devs here so that _choose_preferred_devs can use
+ * this to make the same choice each time.
+ */
+ dm_list_init(&cmd->unused_duplicate_devs);
+ lvmcache_get_unused_duplicate_devs(cmd, &cmd->unused_duplicate_devs);
+ _destroy_duplicate_device_list(&_unused_duplicate_devs);
+ _destroy_duplicate_device_list(&_found_duplicate_devs); /* should be empty anyway */
+ _found_duplicate_pvs = 0;
+
if (retain_orphans)
if (!init_lvmcache_orphans(cmd))
stack;
-
- dm_list_init(&_found_duplicate_devs);
- dm_list_init(&_unused_duplicate_devs);
- _found_duplicate_pvs = 0;
}
int lvmcache_pvid_is_locked(const char *pvid) {
diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c
index 1e3f14a..076f48d 100644
--- a/lib/commands/toolcontext.c
+++ b/lib/commands/toolcontext.c
@@ -1977,6 +1977,8 @@ struct cmd_context *create_toolcontext(unsigned is_long_lived,
if (!init_lvmcache_orphans(cmd))
goto_out;
+ dm_list_init(&cmd->unused_duplicate_devs);
+
if (!_init_segtypes(cmd))
goto_out;
diff --git a/lib/commands/toolcontext.h b/lib/commands/toolcontext.h
index 2cecf27..f4beae1 100644
--- a/lib/commands/toolcontext.h
+++ b/lib/commands/toolcontext.h
@@ -197,6 +197,7 @@ struct cmd_context {
const char *report_list_item_separator;
const char *time_format;
unsigned rand_seed;
+ struct dm_list unused_duplicate_devs; /* save preferences between lvmcache instances */
};
/*
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=ed6ffc7a342149da…
Commit: ed6ffc7a342149dab60086bcabd5fbd2d12ceeb7
Parent: 851ccfccaf3dae184e0bd5f222bdcfcef33fa3b8
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Fri May 20 13:32:14 2016 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Tue Jun 7 10:17:00 2016 -0500
lvmetad: handle update failures
If a command gets stuck during an lvmetad update, lvmetad
will cancel that update after the timeout. The next command
to check the lvmetad will see that lvmetad needs to be
populated because lvmetad will return token of "none" after
a timed out update (same as when lvmetad is not populated
at all after starting.)
If a command gets an error during an lvmetad update, it
will now just quit and leave its updating token in place.
That update will be cancelled after the timeout.
---
daemons/lvmetad/lvmetactl.c | 26 +++
daemons/lvmetad/lvmetad-core.c | 210 +++++++++++++++++++---
lib/cache/lvmetad.c | 389 +++++++++++++++++++++++++++++----------
3 files changed, 498 insertions(+), 127 deletions(-)
diff --git a/daemons/lvmetad/lvmetactl.c b/daemons/lvmetad/lvmetactl.c
index 30ca1d6..dd2ee1e 100644
--- a/daemons/lvmetad/lvmetactl.c
+++ b/daemons/lvmetad/lvmetactl.c
@@ -55,24 +55,32 @@ int main(int argc, char **argv)
if (!strcmp(cmd, "dump")) {
reply = daemon_send_simple(h, "dump",
"token = %s", "skip",
+ "pid = " FMTd64, (int64_t)getpid(),
+ "cmd = %s", "lvmetactl",
NULL);
printf("%s\n", reply.buffer.mem);
} else if (!strcmp(cmd, "pv_list")) {
reply = daemon_send_simple(h, "pv_list",
"token = %s", "skip",
+ "pid = " FMTd64, (int64_t)getpid(),
+ "cmd = %s", "lvmetactl",
NULL);
printf("%s\n", reply.buffer.mem);
} else if (!strcmp(cmd, "vg_list")) {
reply = daemon_send_simple(h, "vg_list",
"token = %s", "skip",
+ "pid = " FMTd64, (int64_t)getpid(),
+ "cmd = %s", "lvmetactl",
NULL);
printf("%s\n", reply.buffer.mem);
} else if (!strcmp(cmd, "get_global_info")) {
reply = daemon_send_simple(h, "get_global_info",
"token = %s", "skip",
+ "pid = " FMTd64, (int64_t)getpid(),
+ "cmd = %s", "lvmetactl",
NULL);
printf("%s\n", reply.buffer.mem);
@@ -86,6 +94,8 @@ int main(int argc, char **argv)
reply = daemon_send_simple(h, "set_global_info",
"global_invalid = " FMTd64, (int64_t) val,
"token = %s", "skip",
+ "pid = " FMTd64, (int64_t)getpid(),
+ "cmd = %s", "lvmetactl",
NULL);
print_reply(reply);
@@ -100,6 +110,8 @@ int main(int argc, char **argv)
"global_disable = " FMTd64, (int64_t) val,
"disable_reason = %s", LVMETAD_DISABLE_REASON_DIRECT,
"token = %s", "skip",
+ "pid = " FMTd64, (int64_t)getpid(),
+ "cmd = %s", "lvmetactl",
NULL);
print_reply(reply);
@@ -123,18 +135,24 @@ int main(int argc, char **argv)
"name = %s", name,
"version = " FMTd64, (int64_t) ver,
"token = %s", "skip",
+ "pid = " FMTd64, (int64_t)getpid(),
+ "cmd = %s", "lvmetactl",
NULL);
} else if (uuid) {
reply = daemon_send_simple(h, "set_vg_info",
"uuid = %s", uuid,
"version = " FMTd64, (int64_t) ver,
"token = %s", "skip",
+ "pid = " FMTd64, (int64_t)getpid(),
+ "cmd = %s", "lvmetactl",
NULL);
} else if (name) {
reply = daemon_send_simple(h, "set_vg_info",
"name = %s", name,
"version = " FMTd64, (int64_t) ver,
"token = %s", "skip",
+ "pid = " FMTd64, (int64_t)getpid(),
+ "cmd = %s", "lvmetactl",
NULL);
} else {
printf("name or uuid required\n");
@@ -153,6 +171,8 @@ int main(int argc, char **argv)
reply = daemon_send_simple(h, "vg_lookup",
"name = %s", name,
"token = %s", "skip",
+ "pid = " FMTd64, (int64_t)getpid(),
+ "cmd = %s", "lvmetactl",
NULL);
printf("%s\n", reply.buffer.mem);
@@ -166,6 +186,8 @@ int main(int argc, char **argv)
reply = daemon_send_simple(h, "vg_lookup",
"uuid = %s", uuid,
"token = %s", "skip",
+ "pid = " FMTd64, (int64_t)getpid(),
+ "cmd = %s", "lvmetactl",
NULL);
printf("%s\n", reply.buffer.mem);
@@ -182,6 +204,8 @@ int main(int argc, char **argv)
reply = daemon_send_simple(h, "vg_lookup",
"uuid = %s", uuid,
"token = %s", "skip",
+ "pid = " FMTd64, (int64_t)getpid(),
+ "cmd = %s", "lvmetactl",
NULL);
/* printf("%s\n", reply.buffer.mem); */
@@ -208,6 +232,8 @@ int main(int argc, char **argv)
reply = daemon_send_simple(h, "pv_lookup",
"uuid = %s", uuid,
"token = %s", "skip",
+ "pid = " FMTd64, (int64_t)getpid(),
+ "cmd = %s", "lvmetactl",
NULL);
printf("%s\n", reply.buffer.mem);
diff --git a/daemons/lvmetad/lvmetad-core.c b/daemons/lvmetad/lvmetad-core.c
index 51db92f..ca1e4ed 100644
--- a/daemons/lvmetad/lvmetad-core.c
+++ b/daemons/lvmetad/lvmetad-core.c
@@ -207,6 +207,8 @@ struct vg_info {
#define VGFL_INVALID 0x00000001
+#define CMD_NAME_SIZE 32
+
typedef struct {
daemon_idle *idle;
log_state *log; /* convenience */
@@ -222,12 +224,25 @@ typedef struct {
struct dm_hash_table *vgname_to_vgid;
struct dm_hash_table *pvid_to_vgid;
char token[128];
+ char update_cmd[CMD_NAME_SIZE];
+ int update_pid;
+ int update_timeout;
+ uint64_t update_begin;
uint32_t flags; /* GLFL_ */
pthread_mutex_t token_lock;
pthread_mutex_t info_lock;
pthread_rwlock_t cache_lock;
} lvmetad_state;
+static uint64_t _monotonic_seconds(void)
+{
+ struct timespec ts;
+
+ if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0)
+ return 0;
+ return ts.tv_sec;
+}
+
static void destroy_metadata_hashes(lvmetad_state *s)
{
struct dm_hash_node *n = NULL;
@@ -2366,24 +2381,28 @@ static response set_global_info(lvmetad_state *s, request r)
#define REASON_BUF_SIZE 64
/*
- * FIXME: save the time when "updating" begins, and add a config setting for
- * how long we'll allow an update to take. Before returning "updating" as the
- * token value in get_global_info, check if the update has exceeded the max
- * allowed time. If so, then clear the current cache state and return "none"
- * as the current token value, so that the command will repopulate our cache.
+ * Save the time when "updating" begins, and the config setting for how long
+ * the update is allowed to take. Before returning "updating" as the token
+ * value in get_global_info, check if the update has exceeded the max allowed
+ * time. If so, then return "none" as the current token value (i.e.
+ * uninitialized), so that the command will repopulate our cache.
*
- * This will resolve the problem of a command starting to update the cache and
- * then failing, leaving the token set to "update in progress".
+ * This automatically clears a stuck update, where a command started to update
+ * the cache and then failed, leaving the token set to "update in progress".
*/
static response get_global_info(lvmetad_state *s, request r)
{
char reason[REASON_BUF_SIZE];
+ char flag_str[64];
+ int pid;
/* This buffer should be large enough to hold all the possible reasons. */
memset(reason, 0, sizeof(reason));
+ pid = (int)daemon_request_int(r, "pid", 0);
+
if (s->flags & GLFL_DISABLE) {
snprintf(reason, REASON_BUF_SIZE - 1, "%s%s%s",
(s->flags & GLFL_DISABLE_REASON_DIRECT) ? LVMETAD_DISABLE_REASON_DIRECT "," : "",
@@ -2394,17 +2413,46 @@ static response get_global_info(lvmetad_state *s, request r)
if (!reason[0])
strcpy(reason, "none");
- DEBUGLOG(s, "global info invalid is %d disable is %d reason %s",
- (s->flags & GLFL_INVALID) ? 1 : 0,
- (s->flags & GLFL_DISABLE) ? 1 : 0, reason);
+ /*
+ * If the current update has timed out, then return
+ * token of "none" which means "uninitialized" so that
+ * the caller will repopulate lvmetad.
+ */
+ if (s->update_begin && s->update_timeout) {
+ if (_monotonic_seconds() - s->update_begin >= s->update_timeout) {
+ DEBUGLOG(s, "global info cancel update after timeout %d len %d begin %llu pid %d cmd %s",
+ s->update_timeout,
+ (int)(_monotonic_seconds() - s->update_begin),
+ (unsigned long long)s->update_begin,
+ s->update_pid, s->update_cmd);
+ memset(s->token, 0, sizeof(s->token));
+ s->update_begin = 0;
+ s->update_timeout = 0;
+ s->update_pid = 0;
+ memset(s->update_cmd, 0, CMD_NAME_SIZE);
+ }
+ }
+
+ memset(flag_str, 0, sizeof(flag_str));
+ if (s->flags & GLFL_INVALID)
+ strcat(flag_str, "Invalid");
+ if (s->flags & GLFL_DISABLE)
+ strcat(flag_str, "Disable");
+ if (!flag_str[0])
+ strcat(flag_str, "none");
+
+ DEBUGLOG(s, "%d global info flags %s reason %s token %s update_pid %d",
+ pid, flag_str, reason, s->token[0] ? s->token : "none", s->update_pid);
- return daemon_reply_simple("OK", "global_invalid = " FMTd64,
- (int64_t)((s->flags & GLFL_INVALID) ? 1 : 0),
- "global_disable = " FMTd64,
- (int64_t)((s->flags & GLFL_DISABLE) ? 1 : 0),
+ return daemon_reply_simple("OK", "global_invalid = " FMTd64, (int64_t)((s->flags & GLFL_INVALID) ? 1 : 0),
+ "global_disable = " FMTd64, (int64_t)((s->flags & GLFL_DISABLE) ? 1 : 0),
"disable_reason = %s", reason,
- "token = %s",
- s->token[0] ? s->token : "none",
+ "daemon_pid = " FMTd64, (int64_t)getpid(),
+ "token = %s", s->token[0] ? s->token : "none",
+ "update_cmd = %s", s->update_cmd,
+ "update_pid = " FMTd64, (int64_t)s->update_pid,
+ "update_begin = " FMTd64, (int64_t)s->update_begin,
+ "update_timeout = " FMTd64, (int64_t)s->update_timeout,
NULL);
}
@@ -2593,37 +2641,145 @@ static response handler(daemon_state s, client_handle h, request r)
{
response res = { 0 };
lvmetad_state *state = s.private;
- const char *rq = daemon_request_str(r, "request", "NONE");
- const char *token = daemon_request_str(r, "token", "NONE");
char prev_token[128] = { 0 };
+ const char *rq;
+ const char *token;
+ const char *cmd;
+ int prev_in_progress, this_in_progress;
+ int update_timeout;
+ int pid;
int cache_lock = 0;
int info_lock = 0;
+ rq = daemon_request_str(r, "request", "NONE");
+ token = daemon_request_str(r, "token", "NONE");
+ pid = (int)daemon_request_int(r, "pid", 0);
+ cmd = daemon_request_str(r, "cmd", "NONE");
+ update_timeout = (int)daemon_request_int(r, "update_timeout", 0);
+
pthread_mutex_lock(&state->token_lock);
+
+ /*
+ * token_update: start populating the cache, i.e. a full update.
+ * To populate the lvmetad cache, a command does:
+ *
+ * - token_update, setting token to "update in progress"
+ * (further requests during the update continue using
+ * this same "update in progress" token)
+ * - pv_clear_all, to clear the current cache
+ * - pv_gone, for each PV
+ * - pv_found, for each PV to populate the cache
+ * - token_update, setting token to filter hash
+ */
if (!strcmp(rq, "token_update")) {
- memcpy(prev_token, state->token, 128);
- strncpy(state->token, token, 128);
- state->token[127] = 0;
+ prev_in_progress = !strcmp(state->token, LVMETAD_TOKEN_UPDATE_IN_PROGRESS);
+ this_in_progress = !strcmp(token, LVMETAD_TOKEN_UPDATE_IN_PROGRESS);
+
+ if (!prev_in_progress && this_in_progress) {
+ /* New update is starting (filter token is replaced by update token) */
+
+ memcpy(prev_token, state->token, 128);
+ strncpy(state->token, token, 128);
+ state->token[127] = 0;
+ state->update_begin = _monotonic_seconds();
+ state->update_timeout = update_timeout;
+ state->update_pid = pid;
+ strncpy(state->update_cmd, cmd, CMD_NAME_SIZE - 1);
+
+ DEBUGLOG(state, "token_update begin %llu timeout %d pid %d cmd %s",
+ (unsigned long long)state->update_begin,
+ state->update_timeout,
+ state->update_pid,
+ state->update_cmd);
+
+ } else if (prev_in_progress && this_in_progress) {
+ /* Current update is cancelled and replaced by a new update */
+
+ DEBUGLOG(state, "token_update replacing pid %d begin %llu len %d cmd %s",
+ state->update_pid,
+ (unsigned long long)state->update_begin,
+ (int)(_monotonic_seconds() - state->update_begin),
+ state->update_cmd);
+
+ memcpy(prev_token, state->token, 128);
+ strncpy(state->token, token, 128);
+ state->token[127] = 0;
+ state->update_begin = _monotonic_seconds();
+ state->update_timeout = update_timeout;
+ state->update_pid = pid;
+ strncpy(state->update_cmd, cmd, CMD_NAME_SIZE - 1);
+
+ DEBUGLOG(state, "token_update begin %llu timeout %d pid %d cmd %s",
+ (unsigned long long)state->update_begin,
+ state->update_timeout,
+ state->update_pid,
+ state->update_cmd);
+
+ } else if (prev_in_progress && !this_in_progress) {
+ /* Update is finished, update token is replaced by filter token */
+
+ if (state->update_pid != pid) {
+ /* If a pid doing update was cancelled, ignore its token update at the end. */
+ DEBUGLOG(state, "token_update ignored from cancelled update pid %d", pid);
+ pthread_mutex_unlock(&state->token_lock);
+
+ return daemon_reply_simple("token_mismatch",
+ "expected = %s", state->token,
+ "received = %s", token,
+ "update_pid = " FMTd64, (int64_t)state->update_pid,
+ "reason = %s", "another command has populated the cache");
+ }
+
+ DEBUGLOG(state, "token_update end len %d pid %d new token %s",
+ (int)(_monotonic_seconds() - state->update_begin),
+ state->update_pid, token);
+
+ memcpy(prev_token, state->token, 128);
+ strncpy(state->token, token, 128);
+ state->token[127] = 0;
+ state->update_begin = 0;
+ state->update_timeout = 0;
+ state->update_pid = 0;
+ memset(state->update_cmd, 0, CMD_NAME_SIZE);
+ }
pthread_mutex_unlock(&state->token_lock);
+
return daemon_reply_simple("OK",
"prev_token = %s", prev_token,
+ "update_pid = " FMTd64, (int64_t)state->update_pid,
NULL);
}
if (strcmp(token, state->token) && strcmp(rq, "dump") && strcmp(token, "skip")) {
pthread_mutex_unlock(&state->token_lock);
+
+ DEBUGLOG(state, "token_mismatch current \"%s\" got \"%s\" from pid %d cmd %s",
+ state->token, token, pid, cmd ?: "none");
+
+ return daemon_reply_simple("token_mismatch",
+ "expected = %s", state->token,
+ "received = %s", token,
+ "update_pid = " FMTd64, (int64_t)state->update_pid,
+ "reason = %s", "another command has populated the cache");
+ }
+
+ /* If a pid doing update was cancelled, ignore its update messages. */
+ if (!strcmp(token, LVMETAD_TOKEN_UPDATE_IN_PROGRESS) &&
+ state->update_pid && pid && (state->update_pid != pid)) {
+ pthread_mutex_unlock(&state->token_lock);
+
+ DEBUGLOG(state, "token_mismatch ignore update from pid %d current update pid %d",
+ pid, state->update_pid);
+
return daemon_reply_simple("token_mismatch",
"expected = %s", state->token,
"received = %s", token,
- "reason = %s",
- "lvmetad cache is invalid due to a global_filter change or due to a running rescan", NULL);
+ "update_pid = " FMTd64, (int64_t)state->update_pid,
+ "reason = %s", "another command has populated the lvmetad cache");
}
+
pthread_mutex_unlock(&state->token_lock);
- /*
- * TODO Add a stats call, with transaction count/rate, time since last
- * update &c.
- */
if (!strcmp(rq, "pv_found") ||
!strcmp(rq, "pv_gone") ||
diff --git a/lib/cache/lvmetad.c b/lib/cache/lvmetad.c
index bb86e88..02f0897 100644
--- a/lib/cache/lvmetad.c
+++ b/lib/cache/lvmetad.c
@@ -27,16 +27,15 @@
#include <time.h>
-#define SCAN_TIMEOUT_SECONDS 80
-#define MAX_RESCANS 10 /* Maximum number of times to scan all PVs and retry if the daemon returns a token mismatch error */
-
static daemon_handle _lvmetad = { .error = 0 };
static int _lvmetad_use = 0;
static int _lvmetad_connected = 0;
+static int _lvmetad_daemon_pid = 0;
static char *_lvmetad_token = NULL;
static const char *_lvmetad_socket = NULL;
static struct cmd_context *_lvmetad_cmd = NULL;
+static int64_t _lvmetad_update_timeout;
static int _found_lvm1_metadata = 0;
@@ -135,6 +134,8 @@ int lvmetad_connect(struct cmd_context *cmd)
return 0;
}
+ _lvmetad_update_timeout = find_config_tree_int(cmd, global_lvmetad_update_wait_time_CFG, NULL);
+
_lvmetad = lvmetad_open(_lvmetad_socket);
if (_lvmetad.socket_fd >= 0 && !_lvmetad.error) {
@@ -248,13 +249,15 @@ int lvmetad_token_matches(struct cmd_context *cmd)
uint64_t now = 0, wait_start = 0;
int ret = 1;
- wait_sec = (unsigned int)find_config_tree_int(cmd, global_lvmetad_update_wait_time_CFG, NULL);
+ wait_sec = (unsigned int)_lvmetad_update_timeout;
retry:
- log_debug_lvmetad("lvmetad send get_global_info");
+ log_debug_lvmetad("Sending lvmetad get_global_info");
reply = daemon_send_simple(_lvmetad, "get_global_info",
"token = %s", "skip",
+ "pid = " FMTd64, (int64_t)getpid(),
+ "cmd = %s", get_cmd_name(),
NULL);
if (reply.error) {
log_warn("WARNING: Not using lvmetad after send error (%d).", reply.error);
@@ -271,6 +274,8 @@ retry:
goto fail;
}
+ _lvmetad_daemon_pid = (int)daemon_reply_int(reply, "daemon_pid", 0);
+
/*
* If lvmetad is being updated by another command, then sleep and retry
* until the token shows the update is done, and go on to the token
@@ -278,13 +283,6 @@ retry:
*
* Between retries, sleep for a random period between 1 and 2 seconds.
* Retry in this way for up to a configurable period of time.
- *
- * If lvmetad is still being updated after the timeout period,
- * then disable this command's use of lvmetad.
- *
- * FIXME: lvmetad could return the number of objects in its cache along with
- * the update message so that callers could detect when a rescan has
- * stalled while updating lvmetad.
*/
if (!strcmp(daemon_token, LVMETAD_TOKEN_UPDATE_IN_PROGRESS)) {
if (!(now = _monotonic_seconds()))
@@ -293,7 +291,7 @@ retry:
if (!wait_start)
wait_start = now;
- if (now - wait_start >= wait_sec) {
+ if (now - wait_start > wait_sec) {
log_warn("WARNING: Not using lvmetad after %u sec lvmetad_update_wait_time.", wait_sec);
goto fail;
}
@@ -354,12 +352,14 @@ static int _lvmetad_is_updating(struct cmd_context *cmd, int do_wait)
uint64_t now = 0, wait_start = 0;
int ret = 0;
- wait_sec = (unsigned int)find_config_tree_int(cmd, global_lvmetad_update_wait_time_CFG, NULL);
+ wait_sec = (unsigned int)_lvmetad_update_timeout;
retry:
- log_debug_lvmetad("lvmetad send get_global_info");
+ log_debug_lvmetad("Sending lvmetad get_global_info");
reply = daemon_send_simple(_lvmetad, "get_global_info",
"token = %s", "skip",
+ "pid = " FMTd64, (int64_t)getpid(),
+ "cmd = %s", get_cmd_name(),
NULL);
if (reply.error)
goto out;
@@ -405,23 +405,28 @@ static daemon_reply _lvmetad_send(struct cmd_context *cmd, const char *id, ...)
va_list ap;
daemon_reply reply = { 0 };
daemon_request req;
+ const char *token_expected;
unsigned int delay_usec;
unsigned int wait_sec = 0;
uint64_t now = 0, wait_start = 0;
+ int daemon_in_update;
+ int we_are_in_update;
if (!_lvmetad_connected || !_lvmetad_use) {
reply.error = ECONNRESET;
return reply;
}
- if (cmd)
- wait_sec = (unsigned int)find_config_tree_int(cmd, global_lvmetad_update_wait_time_CFG, NULL);
+ wait_sec = (unsigned int)_lvmetad_update_timeout;
retry:
- log_debug_lvmetad("lvmetad_send %s", id);
-
req = daemon_request_make(id);
- if (_lvmetad_token && !daemon_request_extend(req, "token = %s", _lvmetad_token, NULL)) {
+ if (!daemon_request_extend(req,
+ "token = %s", _lvmetad_token ?: "none",
+ "update_timeout = " FMTd64, (int64_t)wait_sec,
+ "pid = " FMTd64, (int64_t)getpid(),
+ "cmd = %s", get_cmd_name(),
+ NULL)) {
reply.error = ENOMEM;
return reply;
}
@@ -437,22 +442,40 @@ retry:
if (reply.error == ECONNRESET)
log_warn("WARNING: lvmetad connection failed, cannot reconnect.");
+ /*
+ * For the "token_update" message, the result is handled entirely
+ * by the _token_update() function, so return the reply immediately.
+ */
+ if (!strcmp(id, "token_update"))
+ return reply;
+
+ /*
+ * For other messages it may be useful to retry and resend the
+ * message, so check for that case before returning the reply.
+ * The reply will be checked further in lvmetad_handle_reply.
+ */
+
if (reply.error)
- goto out;
+ return reply;
if (!strcmp(daemon_reply_str(reply, "response", ""), "token_mismatch")) {
- if (!strcmp(daemon_reply_str(reply, "expected", ""), LVMETAD_TOKEN_UPDATE_IN_PROGRESS)) {
+ token_expected = daemon_reply_str(reply, "expected", "");
+ daemon_in_update = !strcmp(token_expected, LVMETAD_TOKEN_UPDATE_IN_PROGRESS);
+ we_are_in_update = !strcmp(_lvmetad_token, LVMETAD_TOKEN_UPDATE_IN_PROGRESS);
+
+ if (daemon_in_update && !we_are_in_update) {
/*
- * Another command is updating the lvmetad cache, and
- * we cannot use lvmetad until the update is finished.
- * Retry our request for a while; the update should
- * finish shortly. This should not usually happen
- * because this command already checked that the token
- * is usable in lvmetad_token_matches(), but it's
- * possible for another command's rescan to slip in
- * between the time we call lvmetad_token_matches()
- * and the time we get here to lvmetad_send().
+ * Another command is updating lvmetad, and we cannot
+ * use lvmetad until the update is finished. Retry our
+ * request for a while; the update should finish
+ * shortly. This should not usually happen because
+ * this command already checked that the token is
+ * usable in lvmetad_token_matches(), but it's possible
+ * for another command's rescan to slip in between the
+ * time we call lvmetad_token_matches() and the time we
+ * get here to lvmetad_send().
*/
+
if (!(now = _monotonic_seconds()))
goto out;
@@ -472,61 +495,122 @@ retry:
usleep(delay_usec);
daemon_reply_destroy(reply);
goto retry;
+
} else {
- /*
- * Another command has updated the lvmetad cache, and
- * has done so using a different device filter from our
- * own, which has made the lvmetad token and our token
- * not match. This should not usually happen because
- * this command has already checked for a matching token
- * in lvmetad_token_matches(), but it's possible for
- * another command's rescan to slip in between the time
- * we call lvmetad_token_matches() and the time we get
- * here to lvmetad_send(). With a mismatched token
- * (different set of devices), we cannot use the lvmetad
- * cache.
- *
- * FIXME: it would be nice to have this command ignore
- * lvmetad at this point and revert to disk scanning,
- * but the layers above lvmetad_send are not yet able
- * to switch modes in the middle of processing.
- *
- * (The advantage of lvmetad_check_token is that it
- * can rescan to get the token in sync, or if that
- * fails it can make the command revert to scanning
- * from the start.)
- */
- log_warn("WARNING: Cannot use lvmetad while it caches different devices.");
+ /* See lvmetad_handle_reply for handling other cases. */
}
}
out:
return reply;
}
+/*
+ * token_update happens when starting or ending an lvmetad update.
+ * When starting we set the token to "update in progress".
+ * When ending we set the token to our filter:<hash>.
+ *
+ * From the perspective of a command, the lvmetad state is one of:
+ * "none" - the lvmetad cache is not populated and an update is required.
+ * "filter:<matching_hash>" - the command with can use the lvmetad cache.
+ * "filter:<unmatching_hash>" - the lvmetad cache must be updated to be used.
+ * "update in progress" - a command is updating the lvmetad cache.
+ *
+ * . If none, the command will update (scan and populate lvmetad),
+ * then use the cache.
+ *
+ * . If filter is matching, the command will use the cache.
+ *
+ * . If filter is unmatching, the command will update (scan and
+ * populate lvmetad), then use the cache.
+ *
+ * . If update in progress, the command will wait for a while for the state
+ * to become non-updating. If it changes, see above, if it doesn't change,
+ * then the command either reverts to not using lvmetad, or does an update
+ * (scan and populate lvmetad) and then uses the cache.
+ *
+ * A command that is explicitly intended to update the cache will always do
+ * that (it may wait for a while first to allow a current update to complete).
+ * A command that is not explicitly intended to update the cache may choose
+ * to revert to scanning and not use lvmetad.
+ *
+ * Because two different updates from two commands can potentially overlap,
+ * lvmetad saves the pid of the latest update to start, so it can reject messages
+ * from preempted updates. This prevents an invalid mix of two different updates.
+ * (The command makes use of the update_pid to print more informative messages.)
+ *
+ * If lvmetad detects that a command doing an update is taking too long, it will
+ * change the token from "update in progress" to "none", which means a new update
+ * is required, causing the next command to do an update. This effectively
+ * cancels/preempts a slow/stuck update, and helps to automatically resolve
+ * some failure cases.
+ */
+
static int _token_update(int *replaced_update)
{
daemon_reply reply;
+ const char *token_expected;
const char *prev_token;
+ int update_pid;
+ int ending_our_update;
- log_debug_lvmetad("Sending updated token to lvmetad: %s", _lvmetad_token ? : "<NONE>");
+ log_debug_lvmetad("Sending lvmetad token_update %s", _lvmetad_token);
reply = _lvmetad_send(NULL, "token_update", NULL);
if (replaced_update)
*replaced_update = 0;
- if (reply.error || strcmp(daemon_reply_str(reply, "response", ""), "OK")) {
+ if (reply.error) {
+ log_warn("WARNING: lvmetad token update error: %s", strerror(reply.error));
+ daemon_reply_destroy(reply);
+ return 0;
+ }
+
+ update_pid = (int)daemon_reply_int(reply, "update_pid", 0);
+
+ /*
+ * A mismatch can only happen when this command attempts to set the
+ * token to filter:<hash> at the end of its update, but the update has
+ * been preempted in lvmetad by a new one (from update_pid).
+ */
+ if (!strcmp(daemon_reply_str(reply, "response", ""), "token_mismatch")) {
+ token_expected = daemon_reply_str(reply, "expected", "");
+
+ ending_our_update = strcmp(_lvmetad_token, LVMETAD_TOKEN_UPDATE_IN_PROGRESS);
+
+ log_debug_lvmetad("Received token update mismatch expected \"%s\" our token \"%s\" update_pid %d our pid %d",
+ token_expected, _lvmetad_token, update_pid, getpid());
+
+ if (ending_our_update && (update_pid != getpid())) {
+ log_warn("WARNING: lvmetad was updated by another command (pid %d).", update_pid);
+ } else {
+ /*
+ * Shouldn't happen.
+ * If we're ending our update and our pid matches the update_pid,
+ * then there would not be a mismatch.
+ * If we're starting a new update, lvmetad never returns a
+ * token mismatch.
+ * In any case, it doesn't hurt to just return an error here.
+ */
+ log_error(INTERNAL_ERROR "lvmetad token update mismatch pid %d matches our own pid %d", update_pid, getpid());
+ }
+
+ daemon_reply_destroy(reply);
+ return 0;
+ }
+
+ if (strcmp(daemon_reply_str(reply, "response", ""), "OK")) {
+ log_error("Failed response from lvmetad for token update.");
daemon_reply_destroy(reply);
return 0;
}
if ((prev_token = daemon_reply_str(reply, "prev_token", NULL))) {
if (!strcmp(prev_token, LVMETAD_TOKEN_UPDATE_IN_PROGRESS))
- if (replaced_update)
+ if (replaced_update && (update_pid != getpid()))
*replaced_update = 1;
}
daemon_reply_destroy(reply);
-
return 1;
}
@@ -539,8 +623,12 @@ static int _token_update(int *replaced_update)
*/
static int _lvmetad_handle_reply(daemon_reply reply, const char *id, const char *object, int *found)
{
- int action_modifies = 0;
+ const char *token_expected;
const char *action;
+ int action_modifies = 0;
+ int daemon_in_update;
+ int we_are_in_update;
+ int update_pid;
if (!id)
action = "<none>";
@@ -574,33 +662,111 @@ static int _lvmetad_handle_reply(daemon_reply reply, const char *id, const char
}
if (reply.error) {
- log_error("Request to %s %s%sin lvmetad gave response %s.",
- action, object, *object ? " " : "", strerror(reply.error));
+ log_warn("WARNING: lvmetad cannot be used due to error: %s", strerror(reply.error));
goto fail;
}
/*
- * See the description of the token mismatch errors in lvmetad_send.
+ * Errors related to token mismatch.
*/
+
if (!strcmp(daemon_reply_str(reply, "response", ""), "token_mismatch")) {
- if (!strcmp(daemon_reply_str(reply, "expected", ""), LVMETAD_TOKEN_UPDATE_IN_PROGRESS)) {
+
+ token_expected = daemon_reply_str(reply, "expected", "");
+ update_pid = (int)daemon_reply_int(reply, "update_pid", 0);
+
+ log_debug("lvmetad token mismatch, expected \"%s\" our token \"%s\"",
+ token_expected, _lvmetad_token);
+
+ daemon_in_update = !strcmp(token_expected, LVMETAD_TOKEN_UPDATE_IN_PROGRESS);
+ we_are_in_update = !strcmp(_lvmetad_token, LVMETAD_TOKEN_UPDATE_IN_PROGRESS);
+
+ if (daemon_in_update && we_are_in_update) {
+
/*
- * lvmetad_send retried up to the limit and eventually
- * printed a warning and gave up.
+ * When we do not match the update_pid, it means our
+ * update was cancelled and another process is now
+ * updating the cache.
*/
- log_error("Request to %s %s%sin lvmetad failed after lvmetad_update_wait_time expired.",
- action, object, *object ? " " : "");
- } else {
+
+ if (update_pid != getpid()) {
+ log_warn("WARNING: lvmetad is being updated by another command (pid %d).", update_pid);
+ } else {
+ /* Shouldn't happen */
+ log_error(INTERNAL_ERROR "lvmetad update by pid %d matches our own pid %d", update_pid, getpid());
+ }
+ /* We don't care if the action was modifying during a token update. */
+ action_modifies = 0;
+ goto fail;
+
+ } else if (daemon_in_update && !we_are_in_update) {
+
+ /*
+ * Another command is updating lvmetad, and we cannot
+ * use lvmetad until the update is finished.
+ * lvmetad_send resent this message up to the limit and
+ * eventually gave up. The caller may choose to not
+ * use lvmetad at this point and revert to scanning.
+ */
+
+ log_warn("WARNING: lvmetad is being updated and cannot be used.");
+ goto fail;
+
+ } else if (!daemon_in_update && we_are_in_update) {
+
+ /*
+ * We are updating lvmetad after setting the token to
+ * "update in progress", but lvmetad has a non-update
+ * token and is rejecting our update messages. This
+ * must mean that lvmetad cancelled our update (we were
+ * probably too slow, taking longer than the timeout),
+ * so another command completed an update and set the
+ * token based on its filter. Here we've attempt to
+ * continue our cache update, and find we've been
+ * preempted, so we should just abort our failed
+ * update.
+ */
+
+ log_warn("WARNING: lvmetad was updated by another command.");
+ /* We don't care if the action was modifying during a token update. */
+ action_modifies = 0;
+ goto fail;
+
+ } else if (!daemon_in_update && !we_are_in_update) {
+
/*
- * lvmetad is caching different devices based on a different
- * device filter which causes a token mismatch.
+ * Another command has updated the lvmetad cache, and
+ * has done so using a different device filter from our
+ * own, which has made the lvmetad token and our token
+ * not match. This should not usually happen because
+ * this command has already checked for a matching token
+ * in lvmetad_token_matches(), but it's possible for
+ * another command's rescan to slip in between the time
+ * we call lvmetad_token_matches() and the time we get
+ * here to lvmetad_send(). With a mismatched token
+ * (different set of devices), we cannot use the lvmetad
+ * cache.
+ *
+ * FIXME: it would be nice to have this command ignore
+ * lvmetad at this point and revert to disk scanning,
+ * but the layers above lvmetad_send are not yet able
+ * to switch modes in the middle of processing.
+ *
+ * (The advantage of lvmetad_check_token is that it
+ * can rescan to get the token in sync, or if that
+ * fails it can make the command revert to scanning
+ * from the start.)
*/
- log_error("Request to %s %s%sin lvmetad failed after device filter mismatch.",
- action, object, *object ? " " : "");
+
+ log_warn("WARNING: Cannot use lvmetad while it caches different devices.");
+ goto fail;
}
- goto fail;
}
+ /*
+ * Non-token-mismatch related error checking.
+ */
+
/* All OK? */
if (!strcmp(daemon_reply_str(reply, "response", ""), "OK")) {
if (found)
@@ -634,14 +800,20 @@ static int _lvmetad_handle_reply(daemon_reply reply, const char *id, const char
daemon_reply_str(reply, "reason", "<missing>"));
fail:
/*
- * If the failed lvmetad message was updating lvmetad, it is important
- * to restart lvmetad (or at least rescan.)
- *
- * FIXME: attempt to set the disabled state in lvmetad here so that
- * commands will not use it until it's been properly repopulated.
+ * If the failed lvmetad message was updating lvmetad with new metadata
+ * that has been changed by this command, it is important to restart
+ * lvmetad (or at least rescan.) (An lvmetad update that is just
+ * scanning disks to populate the cache is not a problem, so we try to
+ * avoid printing a "corruption" warning in that case.)
*/
- if (action_modifies)
+
+ if (action_modifies) {
+ /*
+ * FIXME: experiment with killing the lvmetad process here, e.g.
+ * kill(_lvmetad_daemon_pid, SIGKILL);
+ */
log_warn("WARNING: To avoid corruption, restart lvmetad (or disable with use_lvmetad=0).");
+ }
return 0;
}
@@ -1617,7 +1789,6 @@ int lvmetad_pvscan_single(struct cmd_context *cmd, struct device *dev,
struct _lvmetad_pvscan_baton baton;
/* Create a dummy instance. */
struct format_instance_ctx fic = { .type = 0 };
- struct metadata_area *mda;
if (!lvmetad_used()) {
log_error("Cannot proceed since lvmetad is not active.");
@@ -1644,24 +1815,15 @@ int lvmetad_pvscan_single(struct cmd_context *cmd, struct device *dev,
log_warn("WARNING: Disabling lvmetad cache which does not support obsolete (lvm1) metadata.");
lvmetad_set_disabled(cmd, LVMETAD_DISABLE_REASON_LVM1);
_found_lvm1_metadata = 1;
+ /*
+ * return 1 (success) so that we'll continue to populate lvmetad
+ * instead of leaving the update incomplete.
+ */
return 1;
}
lvmcache_foreach_mda(info, _lvmetad_pvscan_single, &baton);
- /*
- * LVM1 VGs have no MDAs and lvmcache_foreach_mda isn't worth fixing
- * to use pseudo-mdas for PVs.
- * Note that the single_device parameter also gets ignored and this code
- * can scan further devices.
- */
- if (!baton.vg && !(baton.fid->fmt->features & FMT_MDAS)) {
- /* This code seems to be unreachable */
- if ((mda = (struct metadata_area *)dm_list_first(&baton.fid->metadata_areas_in_use)))
- baton.vg = mda->ops->vg_read(baton.fid, lvmcache_vgname_from_info(info),
- mda, NULL, NULL, 1);
- }
-
if (!baton.vg)
lvmcache_fmt(info)->ops->destroy_instance(baton.fid);
@@ -1758,12 +1920,12 @@ int lvmetad_pvscan_all_devs(struct cmd_context *cmd, int do_wait)
if (!replacing_other_update && replaced_update) {
if (do_wait && !retries) {
retries = 1;
- log_warn("WARNING: lvmetad update in progress, retry update.");
+ log_warn("WARNING: lvmetad update in progress, retrying update.");
dev_iter_destroy(iter);
_lvmetad_token = future_token;
goto retry;
}
- log_error("Concurrent lvmetad updates failed.");
+ log_warn("WARNING: lvmetad update in progress, skipping update.");
dev_iter_destroy(iter);
_lvmetad_token = future_token;
return 0;
@@ -1784,8 +1946,12 @@ int lvmetad_pvscan_all_devs(struct cmd_context *cmd, int do_wait)
stack;
break;
}
- if (!lvmetad_pvscan_single(cmd, dev, NULL, NULL))
+
+ if (!lvmetad_pvscan_single(cmd, dev, NULL, NULL)) {
ret = 0;
+ stack;
+ break;
+ }
}
init_silent(was_silent);
@@ -1793,6 +1959,17 @@ int lvmetad_pvscan_all_devs(struct cmd_context *cmd, int do_wait)
dev_iter_destroy(iter);
_lvmetad_token = future_token;
+
+ /*
+ * If we failed to fully and successfully populate lvmetad just leave
+ * the existing "update in progress" token in place so lvmetad will
+ * time out our update and force another command to do it.
+ * (We could try to set the token to empty here, but that doesn't
+ * help much.)
+ */
+ if (!ret)
+ return 0;
+
if (!_token_update(NULL)) {
log_error("Failed to update lvmetad token after device scan.");
return 0;
@@ -1802,7 +1979,7 @@ int lvmetad_pvscan_all_devs(struct cmd_context *cmd, int do_wait)
* If lvmetad is disabled, and no lvm1 metadata was seen and no
* duplicate PVs were seen, then re-enable lvmetad.
*/
- if (ret && lvmetad_is_disabled(cmd, &reason) &&
+ if (lvmetad_is_disabled(cmd, &reason) &&
!lvmcache_found_duplicate_pvs() && !_found_lvm1_metadata) {
log_debug_lvmetad("Enabling lvmetad which was previously disabled.");
lvmetad_clear_disabled(cmd);
@@ -1820,6 +1997,7 @@ int lvmetad_vg_clear_outdated_pvs(struct volume_group *vg)
if (!id_write_format(&vg->id, uuid, sizeof(uuid)))
return_0;
+ log_debug_lvmetad("Sending lvmetad vg_clear_outdated_pvs");
reply = _lvmetad_send(vg->cmd, "vg_clear_outdated_pvs", "vgid = %s", uuid, NULL);
result = _lvmetad_handle_reply(reply, "vg_clear_outdated_pvs", vg->name, NULL);
daemon_reply_destroy(reply);
@@ -2057,6 +2235,8 @@ void lvmetad_validate_global_cache(struct cmd_context *cmd, int force)
reply = daemon_send_simple(_lvmetad, "get_global_info",
"token = %s", "skip",
+ "pid = " FMTd64, (int64_t)getpid(),
+ "cmd = %s", get_cmd_name(),
NULL);
if (reply.error) {
@@ -2115,6 +2295,8 @@ void lvmetad_validate_global_cache(struct cmd_context *cmd, int force)
reply = daemon_send_simple(_lvmetad, "set_global_info",
"token = %s", "skip",
"global_invalid = " FMTd64, INT64_C(0),
+ "pid = " FMTd64, (int64_t)getpid(),
+ "cmd = %s", get_cmd_name(),
NULL);
if (reply.error)
log_error("lvmetad_validate_global_cache set_global_info error %d", reply.error);
@@ -2161,6 +2343,7 @@ int lvmetad_vg_is_foreign(struct cmd_context *cmd, const char *vgname, const cha
if (!id_write_format((const struct id*)vgid, uuid, sizeof(uuid)))
return_0;
+ log_debug_lvmetad("Sending lvmetad vg_clear_outdated_pvs");
reply = _lvmetad_send(cmd, "vg_lookup",
"uuid = %s", uuid,
"name = %s", vgname,
@@ -2321,12 +2504,14 @@ void lvmetad_set_disabled(struct cmd_context *cmd, const char *reason)
if (!_lvmetad_use)
return;
- log_debug_lvmetad("lvmetad send disabled %s", reason);
+ log_debug_lvmetad("Sending lvmetad disabled %s", reason);
reply = daemon_send_simple(_lvmetad, "set_global_info",
"token = %s", "skip",
"global_disable = " FMTd64, (int64_t)1,
"disable_reason = %s", reason,
+ "pid = " FMTd64, (int64_t)getpid(),
+ "cmd = %s", get_cmd_name(),
NULL);
if (reply.error)
log_error("Failed to send message to lvmetad %d", reply.error);
@@ -2344,11 +2529,13 @@ void lvmetad_clear_disabled(struct cmd_context *cmd)
if (!_lvmetad_use)
return;
- log_debug_lvmetad("lvmetad send disabled 0");
+ log_debug_lvmetad("Sending lvmetad disabled 0");
reply = daemon_send_simple(_lvmetad, "set_global_info",
"token = %s", "skip",
"global_disable = " FMTd64, (int64_t)0,
+ "pid = " FMTd64, (int64_t)getpid(),
+ "cmd = %s", get_cmd_name(),
NULL);
if (reply.error)
log_error("Failed to send message to lvmetad %d", reply.error);
@@ -2367,6 +2554,8 @@ int lvmetad_is_disabled(struct cmd_context *cmd, const char **reason)
reply = daemon_send_simple(_lvmetad, "get_global_info",
"token = %s", "skip",
+ "pid = " FMTd64, (int64_t)getpid(),
+ "cmd = %s", get_cmd_name(),
NULL);
if (reply.error) {
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=0e7f352c70decb77…
Commit: 0e7f352c70decb779508b038a22e87c8e3f58b61
Parent: 7ae05adf462b8de4428f32600fb43583dce5009a
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Thu May 19 16:19:38 2016 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Tue Jun 7 10:17:00 2016 -0500
lvmetad: define special update in progress string
---
daemons/lvmetad/lvmetad-client.h | 2 ++
lib/cache/lvmetad.c | 12 ++++++------
2 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/daemons/lvmetad/lvmetad-client.h b/daemons/lvmetad/lvmetad-client.h
index 1376e6b..47eb6b4 100644
--- a/daemons/lvmetad/lvmetad-client.h
+++ b/daemons/lvmetad/lvmetad-client.h
@@ -19,6 +19,8 @@
#define LVMETAD_SOCKET DEFAULT_RUN_DIR "/lvmetad.socket"
+#define LVMETAD_TOKEN_UPDATE_IN_PROGRESS "update in progress"
+
#define LVMETAD_DISABLE_REASON_DIRECT "DIRECT"
#define LVMETAD_DISABLE_REASON_LVM1 "LVM1"
#define LVMETAD_DISABLE_REASON_DUPLICATES "DUPLICATES"
diff --git a/lib/cache/lvmetad.c b/lib/cache/lvmetad.c
index 6f914b2..a87c952 100644
--- a/lib/cache/lvmetad.c
+++ b/lib/cache/lvmetad.c
@@ -286,7 +286,7 @@ retry:
* the update message so that callers could detect when a rescan has
* stalled while updating lvmetad.
*/
- if (!strcmp(daemon_token, "update in progress")) {
+ if (!strcmp(daemon_token, LVMETAD_TOKEN_UPDATE_IN_PROGRESS)) {
if (!(now = _monotonic_seconds()))
goto fail;
@@ -370,7 +370,7 @@ retry:
if (!(daemon_token = daemon_reply_str(reply, "token", NULL)))
goto out;
- if (!strcmp(daemon_token, "update in progress")) {
+ if (!strcmp(daemon_token, LVMETAD_TOKEN_UPDATE_IN_PROGRESS)) {
ret = 1;
if (!do_wait)
@@ -441,7 +441,7 @@ retry:
goto out;
if (!strcmp(daemon_reply_str(reply, "response", ""), "token_mismatch")) {
- if (!strcmp(daemon_reply_str(reply, "expected", ""), "update in progress")) {
+ if (!strcmp(daemon_reply_str(reply, "expected", ""), LVMETAD_TOKEN_UPDATE_IN_PROGRESS)) {
/*
* Another command is updating the lvmetad cache, and
* we cannot use lvmetad until the update is finished.
@@ -520,7 +520,7 @@ static int _token_update(int *replaced_update)
}
if ((prev_token = daemon_reply_str(reply, "prev_token", NULL))) {
- if (!strcmp(prev_token, "update in progress"))
+ if (!strcmp(prev_token, LVMETAD_TOKEN_UPDATE_IN_PROGRESS))
if (replaced_update)
*replaced_update = 1;
}
@@ -583,7 +583,7 @@ static int _lvmetad_handle_reply(daemon_reply reply, const char *id, const char
* See the description of the token mismatch errors in lvmetad_send.
*/
if (!strcmp(daemon_reply_str(reply, "response", ""), "token_mismatch")) {
- if (!strcmp(daemon_reply_str(reply, "expected", ""), "update in progress")) {
+ if (!strcmp(daemon_reply_str(reply, "expected", ""), LVMETAD_TOKEN_UPDATE_IN_PROGRESS)) {
/*
* lvmetad_send retried up to the limit and eventually
* printed a warning and gave up.
@@ -1739,7 +1739,7 @@ int lvmetad_pvscan_all_devs(struct cmd_context *cmd, int do_wait)
}
future_token = _lvmetad_token;
- _lvmetad_token = (char *) "update in progress";
+ _lvmetad_token = (char *) LVMETAD_TOKEN_UPDATE_IN_PROGRESS;
if (!_token_update(&replaced_update)) {
log_error("Failed to update lvmetad which had an update in progress.");
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=7ae05adf462b8de4…
Commit: 7ae05adf462b8de4428f32600fb43583dce5009a
Parent: 7c894911aee47662e8f85f4458d65baea97eb058
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Mon Jun 6 14:57:41 2016 +0200
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Mon Jun 6 14:57:46 2016 +0200
blkdeactivate: fix regression in blkdeactivate causing dm and md devices to be skipped.
Commit #5b3a4a9 caused the "name" variable to be cleared if
declaration and assignment is on two lines so put it back
so it's on one line for it to work again.
---
WHATS_NEW | 1 +
scripts/blkdeactivate.sh.in | 6 ++----
2 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index c1b90af..2e7e138 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.156 -
================================
+ Fix regression in blkdeactivate causing dm and md devices to be skipped. (2.02.155)
Version 2.02.155 - 3rd June 2016
================================
diff --git a/scripts/blkdeactivate.sh.in b/scripts/blkdeactivate.sh.in
index 2a48b3e..b4c3237 100644
--- a/scripts/blkdeactivate.sh.in
+++ b/scripts/blkdeactivate.sh.in
@@ -193,8 +193,7 @@ deactivate_holders () {
}
deactivate_dm () {
- local name
- name=$(printf "%s" "$name")
+ local name=$(printf "%s" "$name")
test -b "$DEV_DIR/mapper/$name" || return 0
test -z ${SKIP_DEVICE_LIST["$kname"]} || return 1
@@ -263,8 +262,7 @@ deactivate_lvm () {
}
deactivate_md () {
- local name
- name=$(printf "%s" "$name")
+ local name=$(printf "%s" "$name")
test -b "$DEV_DIR/$name" || return 0
test -z ${SKIP_DEVICE_LIST["$kname"]} || return 1
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=d0af97e64d143d46…
Commit: d0af97e64d143d466013d7480ec3abd4e34b82ef
Parent: 0000000000000000000000000000000000000000
Author: Alasdair G Kergon <agk(a)redhat.com>
AuthorDate: 2016-06-03 22:17 +0000
Committer: Alasdair G Kergon <agk(a)redhat.com>
CommitterDate: 2016-06-03 22:17 +0000
annotated tag: v2_02_155 has been created
at d0af97e64d143d466013d7480ec3abd4e34b82ef (tag)
tagging 767c9d653eb9c6deec576c23823781c6f184dea0 (commit)
replaces v2_02_154
Release 2.02.155.
A development release with an assortment of small enhancements and fixes
including limited support for striping using the dm-raid raid0 target.
97 files changed, 1964 insertions(+), 1288 deletions(-)
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.14 (GNU/Linux)
iEYEABECAAYFAldSApEACgkQIoGRwVZ+LBfzhwCfbtZNyjFQjV2vjlLQxCEcPD24
pZQAoIWjo4ahEadsLS2lri2dfSGNoxiE
=QAhm
-----END PGP SIGNATURE-----
Alasdair G Kergon (8):
post-release
raid0: Add raid0 segment type.
raid0: Standardise meta_areas checks before access.
raid10: Fix new use of area multiple calc.
metadata: Tidy merge.c
raid: Revert _lv_extend_layered_lv non-raid0 area_multiple.
Revert "libdm: trace missing settings"
pre-release
David Teigland (16):
python: move lvm_init
lvmetad: add request level thread locking
lvmetad: remove old thread locking
pvremove: allow clearing a duplicate PV
liblvm: allow config settings to be read without full lvm cmd
lvm2_activation_generator: don't create full context for liblvm2app
WHATS_NEW: include recent changes
tools: improve error message about VG name and select
toollib: add vg name list arg to process_each_vg
pvscan: use process_each_vg for autoactivate
test: lvmetad-pvscan-filter
test: lvmetad-disabled
lvconvert: use process_each_lv
vgreduce: use process_each_vg
WHATS_NEW: include recent changes
pvmove: disallow tag args
Peter Rajnoha (12):
refactor: split _report fn further into init and config part
toollib: simplify internal selection calls for non-reporting tools
report: fix lvm devtypes internal error if -S is used with field name from pvs/vgs/lvs
toollib: properly reset selection handle on selection failure in select_match_{pv,vg,lv}
tests: add dmstats to CLEAN_TARGETS for make clean
coverity: fix possible resource leak of descendants_buffer in _print_historical_lv fn
coverity: blkdeactivate: separate format and args for printf and declare and assign separately to avoid masking return values
coverity: missing check for id_write_format return value
coverity: fix warnings about missing return value check for sscanf
make: add generated parts of lvmdbusd to DISTCLEAN_TARGETS for make distclean
lvmconfig: fix lvmconfig --type diff to display complete diff if config cascade used
man: lvmconfig: add note about --type diff and --mergedconfig
Tobias Stoeckmann (1):
man: fixed typo in lvcreate.8
Zdenek Kabelac (28):
libdm: cache status reports passthrough cache mode
libdm: trace missing settings
lvchange: allow change of cache mode
debug: use display_lvname
tests: test change of cache mode
report: fix report copy_percent value
snapshot: check merging_cow is cow
setup_task: add with_flush
cache: call status only on cache pool in use
cache: enhance lv_cache_wait_for_clean
cleanup: substract integers
cleanup: drop cmd and constify lv for lv_refresh_suspend_resume()
refresh: call resume after failing suspend
lvstatus: enhance seg_status to handle snapshot
lv: introduce lvseg_percent_with_info_and_seg_status
snapshot: use seg_status for attrs
report: convert more options to use single status
cache: add log_error on error path
debug: use display_lvname
tests: check cache_mode change on cachepool
tests: stacked snapshot merge
snapshot: for invalid snapshot show 100%
tests: check thin is not flushed for status
devices: handle partscan loop devices
tests: extend prepare_loop
tests: check losetup -P is correctly handled
cleanup: use display_name
cleanup: compile fixes for --disable-devmapper
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=b321d2b1b9a3b6a1…
Commit: b321d2b1b9a3b6a1f8d67888a04c7318aa3148c2
Parent: 68e097972462e3c7c208ac34c62e737b161dd3c4
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Fri Jun 3 09:56:48 2016 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Fri Jun 3 09:56:48 2016 -0500
pvmove: disallow tag args
pvmove began processing tags unintentionally from commit,
6d7dc87cb pvmove: use toollib
pvmove works on a single PV, but tags can match multiple PVs.
If we allowed tags, but processed only the first matching PV,
then the resulting PV would be unpredictable.
Also, the current processing code does not allow us to simply
report an error and do nothing if more than one PV matches the tag,
because the command starts processing PVs as they are found,
so it's too late to do nothing if a second PV matches.
---
tools/commands.h | 4 +++-
tools/toollib.c | 5 +++++
tools/tools.h | 2 ++
3 files changed, 10 insertions(+), 1 deletions(-)
diff --git a/tools/commands.h b/tools/commands.h
index da432a7..888f3a2 100644
--- a/tools/commands.h
+++ b/tools/commands.h
@@ -874,9 +874,11 @@ xx(pvdisplay,
select_ARG, separator_ARG, shared_ARG, short_ARG, sort_ARG, unbuffered_ARG,
units_ARG)
+/* ALL_VGS_IS_DEFAULT is for polldaemon to find pvmoves in-progress using process_each_vg. */
+
xx(pvmove,
"Move extents from one physical volume to another",
- ALL_VGS_IS_DEFAULT, /* For polldaemon to find pvmoves in-progress using process_each_vg. */
+ ALL_VGS_IS_DEFAULT | DISALLOW_TAG_ARGS,
"pvmove\n"
"\t[--abort]\n"
"\t[--alloc AllocationPolicy]\n"
diff --git a/tools/toollib.c b/tools/toollib.c
index 0de6ee8..0563fea 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -3375,6 +3375,11 @@ int process_each_pv(struct cmd_context *cmd,
return ret;
}
+ if ((cmd->command->flags & DISALLOW_TAG_ARGS) && !dm_list_empty(&arg_tags)) {
+ log_error("Tags cannot be used with this command.");
+ return ECMD_FAILED;
+ }
+
orphans_locked = lvmcache_vgname_is_locked(VG_ORPHANS);
process_all_pvs = dm_list_empty(&arg_pvnames) && dm_list_empty(&arg_tags);
diff --git a/tools/tools.h b/tools/tools.h
index 2abc750..8704749 100644
--- a/tools/tools.h
+++ b/tools/tools.h
@@ -114,6 +114,8 @@ struct arg_value_group_list {
#define NO_LVMETAD_AUTOSCAN 0x00000200
/* Command should process unused duplicate devices. */
#define ENABLE_DUPLICATE_DEVS 0x00000400
+/* Command does not accept tags as args. */
+#define DISALLOW_TAG_ARGS 0x00000800
/* a register of the lvm commands */
struct command {
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=68e097972462e3c7…
Commit: 68e097972462e3c7c208ac34c62e737b161dd3c4
Parent: 8e4db009b8f215cb7f593f4b76a6f4bd4293e2ca
Author: Tobias Stoeckmann <tobias(a)stoeckmann.org>
AuthorDate: Mon May 30 23:13:40 2016 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Fri Jun 3 12:46:47 2016 +0200
man: fixed typo in lvcreate.8
It's supposed to be "smaller than" instead of "smaller then".
---
man/lvcreate.8.in | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/man/lvcreate.8.in b/man/lvcreate.8.in
index 8614cb1..c28bc41 100644
--- a/man/lvcreate.8.in
+++ b/man/lvcreate.8.in
@@ -261,7 +261,7 @@ and the default value is 4KiB.
For cache pools the value must a multiple of 32KiB
between 32KiB and 1GiB. The default is 64KiB.
When the size is specified with volume caching, it may not be smaller
-then cache pool creation chunk size was.
+than cache pool creation chunk size was.
.br
For thin pools the value must be a multiple of 64KiB
between 64KiB and 1GiB.
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=8012c223e0beb858…
Commit: 8012c223e0beb858bc2a6b1ea809c4a98a90a5c1
Parent: 687bc5cecfe6293ee5556aa4e448459bb5c167e6
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Thu Jun 2 14:07:07 2016 +0200
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Thu Jun 2 14:07:07 2016 +0200
man: lvmconfig: add note about --type diff and --mergedconfig
---
man/lvmconfig.8.in | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/man/lvmconfig.8.in b/man/lvmconfig.8.in
index 257029e..f4b6abd 100644
--- a/man/lvmconfig.8.in
+++ b/man/lvmconfig.8.in
@@ -71,6 +71,7 @@ Display all possible configuration settings with default values assigned.
.IP \fBdiff\fP 3
Display all configuration settings for which the values used differ from defaults.
The value assigned for each configuration setting is the value currently used.
+Using this type also implies the use of \fB\-\-mergedconfig\fP option.
This is actually minimal LVM configuration which can be used without
a change to current configured behaviour.
.IP \fBfull\fP 3
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=687bc5cecfe6293e…
Commit: 687bc5cecfe6293ee5556aa4e448459bb5c167e6
Parent: fc37ee63c0562d3f42b597d485495ee79a857dc5
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Thu Jun 2 13:41:55 2016 +0200
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Thu Jun 2 13:49:38 2016 +0200
lvmconfig: fix lvmconfig --type diff to display complete diff if config cascade used
If configuration consists of several sources in config cascade
("config cascade" defined in man lvmconfig(8)), lvmconfig displayed
only difference from defaults of the topmost config in the cascade.
Fix lvmconfig to display complete difference, considering all
the configuration in the cascade.
For example, before this patch:
(use_lvmetad=0 set in lvm.conf which differs from defaults)
$ lvmconfig --type diff
global {
use_lvmetad=0
}
(compact_output=1 set on cmd line)
$ lvmconfig --type diff --config report/compact_output=1
report {
compact_output=1
}
(headings=0 set in profile)
$ lvmconfig --type diff --commandprofile test
report {
headings=0
}
(difference in topmost configuration source is displayed)
$ lvmconfig --type diff --commandprofile test --config report/compact_output=1
report {
compact_output=1
}
With this patch applied (the config cascade is merged before looking for
difference from defaults in configuration):
$ lvmconfig --type diff
global {
use_lvmetad=0
}
$ lvmconfig --type diff --config report/compact_output=1
report {
compact_output=1
}
global {
use_lvmetad=0
}
$ lvmconfig --type diff --profile test
report {
headings=0
}
global {
use_lvmetad=0
}
$ lvmconfig --type diff --profile test --config report/compact_output=1
report {
headings=0
compact_output=1
}
global {
use_lvmetad=0
}
---
WHATS_NEW | 1 +
tools/dumpconfig.c | 2 +-
2 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index 74b5bdb..ea36c17 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.155 -
================================
+ Fix lvmconfig --type diff to display complete diff if config cascade used.
Automatically filter out partitioned loop devices with partscan (losetup -P).
Fix lvm devtypes internal error if -S used with field name from pvs/vgs/lvs.
When reporting Data%,Snap%,Meta%,Cpy%Sync use single ioctl per LV.
diff --git a/tools/dumpconfig.c b/tools/dumpconfig.c
index 81b488e..0880740 100644
--- a/tools/dumpconfig.c
+++ b/tools/dumpconfig.c
@@ -210,7 +210,7 @@ int dumpconfig(struct cmd_context *cmd, int argc, char **argv)
* Set the 'cft' to work with based on whether we need the plain
* config tree or merged config tree cascade if --mergedconfig is used.
*/
- if ((arg_count(cmd, mergedconfig_ARG) || !strcmp(type, "full")) && cmd->cft->cascade) {
+ if ((arg_count(cmd, mergedconfig_ARG) || !strcmp(type, "full") || !strcmp(type, "diff")) && cmd->cft->cascade) {
if (!_merge_config_cascade(cmd, cmd->cft, &cft)) {
log_error("Failed to merge configuration.");
r = ECMD_FAILED;
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=a5d65b4a513b322d…
Commit: a5d65b4a513b322def4b6da1d498e4491c9da6d0
Parent: d73a83e8cf508b6d97ee937a01ebd24a678dfabc
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Wed Jun 1 17:25:55 2016 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Wed Jun 1 17:37:52 2016 +0200
tests: check losetup -P is correctly handled
Validate pvcreate will not overwrite partitioned loop device.
---
test/shell/losetup_partscan.sh | 63 ++++++++++++++++++++++++++++++++++++++++
1 files changed, 63 insertions(+), 0 deletions(-)
diff --git a/test/shell/losetup_partscan.sh b/test/shell/losetup_partscan.sh
new file mode 100644
index 0000000..90fafc0
--- /dev/null
+++ b/test/shell/losetup_partscan.sh
@@ -0,0 +1,63 @@
+#!/bin/bash
+# Copyright (C) 2016 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+# Check how lvm2 handles partitions over losetup -P devices
+
+SKIP_WITH_LVMLOCKD=1
+SKIP_WITH_LVMPOLLD=1
+
+. lib/inittest
+
+which sfdisk || skip
+
+aux prepare_loop 1000 -P || skip
+
+test -f LOOP
+LOOP=$(< LOOP)
+
+echo "1 2" | sfdisk $LOOP
+
+# wait for links
+aux udev_wait
+
+# losetup -P should provide partition
+ls -la "${LOOP}"*
+test -e "${LOOP}p1"
+
+aux extend_filter "a|$LOOP|"
+
+# creation should fail for 'partitioned' loop device
+not pvcreate -y $LOOP
+not vgcreate vg $LOOP
+
+aux teardown_devs
+
+aux prepare_loop 1000 || skip
+
+test -f LOOP
+LOOP=$(< LOOP)
+
+
+echo "1 2" | sfdisk $LOOP
+
+# wait for links
+aux udev_wait
+
+# no partitione should be actually there
+ls -la "${LOOP}"*
+test ! -e "${LOOP}p1"
+
+aux extend_filter "a|$LOOP|"
+
+# creation should pass for 'non-partitioned' loop device
+pvcreate -y $LOOP
+
+vgcreate vg $LOOP