|
|
1d62a4 |
commit 8aa13d867d8c707450bb1de1479e18a3bbbc324a
|
|
|
1d62a4 |
Author: Peter Rajnoha <prajnoha@redhat.com>
|
|
|
1d62a4 |
Date: Tue Dec 1 13:10:31 2015 +0100
|
|
|
1d62a4 |
|
|
|
1d62a4 |
bz1274676
|
|
|
1d62a4 |
---
|
|
|
1d62a4 |
lib/activate/dev_manager.c | 11 ++++--
|
|
|
1d62a4 |
libdm/.exported_symbols.Base | 1 -
|
|
|
1d62a4 |
libdm/.exported_symbols.DM_1_02_107 | 1 +
|
|
|
1d62a4 |
libdm/libdevmapper.h | 5 +++
|
|
|
1d62a4 |
libdm/libdm-deptree.c | 25 ++++++++++++--
|
|
|
1d62a4 |
test/shell/lvextend-thin-bz1274676.sh | 63 +++++++++++++++++++++++++++++++++++
|
|
|
1d62a4 |
6 files changed, 100 insertions(+), 6 deletions(-)
|
|
|
1d62a4 |
|
|
|
1d62a4 |
diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
|
|
|
1d62a4 |
index c8e9589..e1f547f 100644
|
|
|
1d62a4 |
--- a/lib/activate/dev_manager.c
|
|
|
1d62a4 |
+++ b/lib/activate/dev_manager.c
|
|
|
1d62a4 |
@@ -3277,7 +3277,7 @@ static int _tree_action(struct dev_manager *dm, const struct logical_volume *lv,
|
|
|
1d62a4 |
break;
|
|
|
1d62a4 |
case SUSPEND:
|
|
|
1d62a4 |
dm_tree_skip_lockfs(root);
|
|
|
1d62a4 |
- if (!dm->flush_required && lv_is_mirror(lv) && !lv_is_pvmove(lv))
|
|
|
1d62a4 |
+ if (!dm->flush_required && !lv_is_pvmove(lv))
|
|
|
1d62a4 |
dm_tree_use_no_flush_suspend(root);
|
|
|
1d62a4 |
/* Fall through */
|
|
|
1d62a4 |
case SUSPEND_WITH_LOCKFS:
|
|
|
1d62a4 |
@@ -3296,7 +3296,14 @@ static int _tree_action(struct dev_manager *dm, const struct logical_volume *lv,
|
|
|
1d62a4 |
if (!dm_tree_preload_children(root, dlid, DLID_SIZE))
|
|
|
1d62a4 |
goto_out;
|
|
|
1d62a4 |
|
|
|
1d62a4 |
- if (dm_tree_node_size_changed(root))
|
|
|
1d62a4 |
+ if ((dm_tree_node_size_changed(root) < 0))
|
|
|
1d62a4 |
+ dm->flush_required = 1;
|
|
|
1d62a4 |
+
|
|
|
1d62a4 |
+ /* Currently keep the code require flush for any
|
|
|
1d62a4 |
+ * non 'thin pool/volume, mirror' or with any size change */
|
|
|
1d62a4 |
+ if (!lv_is_thin_volume(lv) &&
|
|
|
1d62a4 |
+ !lv_is_thin_pool(lv) &&
|
|
|
1d62a4 |
+ (!lv_is_mirror(lv) || dm_tree_node_size_changed(root)))
|
|
|
1d62a4 |
dm->flush_required = 1;
|
|
|
1d62a4 |
|
|
|
1d62a4 |
if (action == ACTIVATE) {
|
|
|
1d62a4 |
diff --git a/libdm/.exported_symbols.Base b/libdm/.exported_symbols.Base
|
|
|
1d62a4 |
index f9c3cb1..27fef53 100644
|
|
|
1d62a4 |
--- a/libdm/.exported_symbols.Base
|
|
|
1d62a4 |
+++ b/libdm/.exported_symbols.Base
|
|
|
1d62a4 |
@@ -262,7 +262,6 @@ dm_tree_node_set_thin_external_origin
|
|
|
1d62a4 |
dm_tree_node_set_thin_pool_discard
|
|
|
1d62a4 |
dm_tree_node_set_thin_pool_error_if_no_space
|
|
|
1d62a4 |
dm_tree_node_set_udev_flags
|
|
|
1d62a4 |
-dm_tree_node_size_changed
|
|
|
1d62a4 |
dm_tree_preload_children
|
|
|
1d62a4 |
dm_tree_retry_remove
|
|
|
1d62a4 |
dm_tree_set_cookie
|
|
|
1d62a4 |
diff --git a/libdm/.exported_symbols.DM_1_02_107 b/libdm/.exported_symbols.DM_1_02_107
|
|
|
1d62a4 |
index 89d3464..0c7b7af 100644
|
|
|
1d62a4 |
--- a/libdm/.exported_symbols.DM_1_02_107
|
|
|
1d62a4 |
+++ b/libdm/.exported_symbols.DM_1_02_107
|
|
|
1d62a4 |
@@ -13,3 +13,4 @@ dm_stats_create_region
|
|
|
1d62a4 |
dm_stats_driver_supports_histogram
|
|
|
1d62a4 |
dm_stats_get_histogram
|
|
|
1d62a4 |
dm_stats_get_region_nr_histogram_bins
|
|
|
1d62a4 |
+dm_tree_node_size_changed
|
|
|
1d62a4 |
diff --git a/libdm/libdevmapper.h b/libdm/libdevmapper.h
|
|
|
1d62a4 |
index 098fa85..8d4b096 100644
|
|
|
1d62a4 |
--- a/libdm/libdevmapper.h
|
|
|
1d62a4 |
+++ b/libdm/libdevmapper.h
|
|
|
1d62a4 |
@@ -1252,6 +1252,11 @@ const char *dm_tree_node_get_name(const struct dm_tree_node *node);
|
|
|
1d62a4 |
const char *dm_tree_node_get_uuid(const struct dm_tree_node *node);
|
|
|
1d62a4 |
const struct dm_info *dm_tree_node_get_info(const struct dm_tree_node *node);
|
|
|
1d62a4 |
void *dm_tree_node_get_context(const struct dm_tree_node *node);
|
|
|
1d62a4 |
+/*
|
|
|
1d62a4 |
+ * Returns 0 when node size and its children is unchanged.
|
|
|
1d62a4 |
+ * Returns 1 when node or any of its children has increased size.
|
|
|
1d62a4 |
+ * Rerurns -1 when node or any of its children has reduced size.
|
|
|
1d62a4 |
+ */
|
|
|
1d62a4 |
int dm_tree_node_size_changed(const struct dm_tree_node *dnode);
|
|
|
1d62a4 |
|
|
|
1d62a4 |
/*
|
|
|
1d62a4 |
diff --git a/libdm/libdm-deptree.c b/libdm/libdm-deptree.c
|
|
|
1d62a4 |
index fc79e33..0584079 100644
|
|
|
1d62a4 |
--- a/libdm/libdm-deptree.c
|
|
|
1d62a4 |
+++ b/libdm/libdm-deptree.c
|
|
|
1d62a4 |
@@ -220,7 +220,7 @@ struct load_properties {
|
|
|
1d62a4 |
uint32_t read_ahead_flags;
|
|
|
1d62a4 |
|
|
|
1d62a4 |
unsigned segment_count;
|
|
|
1d62a4 |
- unsigned size_changed;
|
|
|
1d62a4 |
+ int size_changed;
|
|
|
1d62a4 |
struct dm_list segs;
|
|
|
1d62a4 |
|
|
|
1d62a4 |
const char *new_name;
|
|
|
1d62a4 |
@@ -2768,7 +2768,8 @@ static int _load_node(struct dm_tree_node *dnode)
|
|
|
1d62a4 |
|
|
|
1d62a4 |
existing_table_size = dm_task_get_existing_table_size(dmt);
|
|
|
1d62a4 |
if ((dnode->props.size_changed =
|
|
|
1d62a4 |
- (existing_table_size == seg_start) ? 0 : 1)) {
|
|
|
1d62a4 |
+ (existing_table_size == seg_start) ? 0 :
|
|
|
1d62a4 |
+ (existing_table_size > seg_start) ? -1 : 1)) {
|
|
|
1d62a4 |
/*
|
|
|
1d62a4 |
* Kernel usually skips size validation on zero-length devices
|
|
|
1d62a4 |
* now so no need to preload them.
|
|
|
1d62a4 |
@@ -2864,8 +2865,10 @@ int dm_tree_preload_children(struct dm_tree_node *dnode,
|
|
|
1d62a4 |
}
|
|
|
1d62a4 |
|
|
|
1d62a4 |
/* Propagate device size change change */
|
|
|
1d62a4 |
- if (child->props.size_changed)
|
|
|
1d62a4 |
+ if (child->props.size_changed > 0 && !dnode->props.size_changed)
|
|
|
1d62a4 |
dnode->props.size_changed = 1;
|
|
|
1d62a4 |
+ else if (child->props.size_changed < 0)
|
|
|
1d62a4 |
+ dnode->props.size_changed = -1;
|
|
|
1d62a4 |
|
|
|
1d62a4 |
/* Resume device immediately if it has parents and its size changed */
|
|
|
1d62a4 |
if (!dm_tree_node_num_children(child, 1) || !child->props.size_changed)
|
|
|
1d62a4 |
@@ -4190,3 +4193,19 @@ void dm_tree_node_set_callback(struct dm_tree_node *dnode,
|
|
|
1d62a4 |
dnode->callback = cb;
|
|
|
1d62a4 |
dnode->callback_data = data;
|
|
|
1d62a4 |
}
|
|
|
1d62a4 |
+
|
|
|
1d62a4 |
+/*
|
|
|
1d62a4 |
+ * Backward compatible dm_tree_node_size_changed() implementations.
|
|
|
1d62a4 |
+ *
|
|
|
1d62a4 |
+ * Keep these at the end of the file to avoid adding clutter around the
|
|
|
1d62a4 |
+ * current dm_tree_node_size_changed() version.
|
|
|
1d62a4 |
+ */
|
|
|
1d62a4 |
+#if defined(__GNUC__)
|
|
|
1d62a4 |
+int dm_tree_node_size_changed_base(const struct dm_tree_node *dnode);
|
|
|
1d62a4 |
+DM_EXPORT_SYMBOL_BASE(dm_tree_node_size_changed);
|
|
|
1d62a4 |
+int dm_tree_node_size_changed_base(const struct dm_tree_node *dnode)
|
|
|
1d62a4 |
+{
|
|
|
1d62a4 |
+ /* Base does not make difference between smaller and bigger */
|
|
|
1d62a4 |
+ return dm_tree_node_size_changed(dnode) ? 1 : 0;
|
|
|
1d62a4 |
+}
|
|
|
1d62a4 |
+#endif
|
|
|
1d62a4 |
diff --git a/test/shell/lvextend-thin-bz1274676.sh b/test/shell/lvextend-thin-bz1274676.sh
|
|
|
1d62a4 |
new file mode 100644
|
|
|
1d62a4 |
index 0000000..facace0
|
|
|
1d62a4 |
--- /dev/null
|
|
|
1d62a4 |
+++ b/test/shell/lvextend-thin-bz1274676.sh
|
|
|
1d62a4 |
@@ -0,0 +1,63 @@
|
|
|
1d62a4 |
+#!/bin/bash
|
|
|
1d62a4 |
+# Copyright (C) 2015 Red Hat, Inc. All rights reserved.
|
|
|
1d62a4 |
+#
|
|
|
1d62a4 |
+# This copyrighted material is made available to anyone wishing to use,
|
|
|
1d62a4 |
+# modify, copy, or redistribute it subject to the terms and conditions
|
|
|
1d62a4 |
+# of the GNU General Public License v.2.
|
|
|
1d62a4 |
+#
|
|
|
1d62a4 |
+# You should have received a copy of the GNU General Public License
|
|
|
1d62a4 |
+# along with this program; if not, write to the Free Software Foundation,
|
|
|
1d62a4 |
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
1d62a4 |
+
|
|
|
1d62a4 |
+# ensure there is no data loss during thin-pool resize
|
|
|
1d62a4 |
+
|
|
|
1d62a4 |
+export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false}
|
|
|
1d62a4 |
+
|
|
|
1d62a4 |
+. lib/inittest
|
|
|
1d62a4 |
+
|
|
|
1d62a4 |
+test -e LOCAL_LVMPOLLD && skip
|
|
|
1d62a4 |
+
|
|
|
1d62a4 |
+which md5sum || skip
|
|
|
1d62a4 |
+
|
|
|
1d62a4 |
+aux have_thin 1 0 0 || skip
|
|
|
1d62a4 |
+
|
|
|
1d62a4 |
+aux prepare_pvs 2 20
|
|
|
1d62a4 |
+
|
|
|
1d62a4 |
+vgcreate -s 512K $vg $(< DEVICES)
|
|
|
1d62a4 |
+
|
|
|
1d62a4 |
+lvcreate -L1M -V2M -n $lv1 -T $vg/pool
|
|
|
1d62a4 |
+
|
|
|
1d62a4 |
+# just ensure we check what we need to check
|
|
|
1d62a4 |
+check lv_field $vg/pool size "1.00m"
|
|
|
1d62a4 |
+check lv_field $vg/$lv1 size "2.00m"
|
|
|
1d62a4 |
+
|
|
|
1d62a4 |
+# prepare 2097152 file content
|
|
|
1d62a4 |
+seq 0 315465 > 2M
|
|
|
1d62a4 |
+md5sum 2M | cut -f 1 -d ' ' | tee MD5
|
|
|
1d62a4 |
+dd if=2M of="$DM_DEV_DIR/mapper/$vg-$lv1" bs=512K conv=fdatasync 2>&1 >log &
|
|
|
1d62a4 |
+#dd if=2M of="$DM_DEV_DIR/mapper/$vg-$lv1" bs=2M oflag=direct &
|
|
|
1d62a4 |
+
|
|
|
1d62a4 |
+# give it some time to fill thin-volume
|
|
|
1d62a4 |
+# eventually loop to wait for 100% full pool...
|
|
|
1d62a4 |
+sleep .1
|
|
|
1d62a4 |
+lvs -a $vg
|
|
|
1d62a4 |
+
|
|
|
1d62a4 |
+# this must not 'block & wait' on suspending flush
|
|
|
1d62a4 |
+# if it waits on thin-pool's target timeout
|
|
|
1d62a4 |
+# it will harm queued data
|
|
|
1d62a4 |
+lvextend -L+512k $vg/pool
|
|
|
1d62a4 |
+lvextend -L+512k $vg/pool
|
|
|
1d62a4 |
+
|
|
|
1d62a4 |
+# collect 'dd' result
|
|
|
1d62a4 |
+wait
|
|
|
1d62a4 |
+cat log
|
|
|
1d62a4 |
+
|
|
|
1d62a4 |
+lvs -a $vg
|
|
|
1d62a4 |
+
|
|
|
1d62a4 |
+dd if="$DM_DEV_DIR/mapper/$vg-$lv1" of=2M-2 iflag=direct
|
|
|
1d62a4 |
+md5sum 2M-2 | cut -f 1 -d ' ' | tee MD5-2
|
|
|
1d62a4 |
+
|
|
|
1d62a4 |
+# these 2 are supposed to match
|
|
|
1d62a4 |
+diff MD5 MD5-2
|
|
|
1d62a4 |
+
|
|
|
1d62a4 |
+vgremove -f $vg
|