master - tests: more debug in metadata-zero-space
by David Teigland
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=82b887a4cfa12f32781...
Commit: 82b887a4cfa12f32781cc0dc89c51d89658179a1
Parent: 1fe04f89efa97bf25b7b5ca6f382e957a9adf43d
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Thu Sep 12 11:19:44 2019 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Thu Sep 12 11:19:44 2019 -0500
tests: more debug in metadata-zero-space
---
test/shell/metadata-zero-space.sh | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/test/shell/metadata-zero-space.sh b/test/shell/metadata-zero-space.sh
index f69aee5..ec7b65c 100644
--- a/test/shell/metadata-zero-space.sh
+++ b/test/shell/metadata-zero-space.sh
@@ -36,6 +36,8 @@ dd if="$dev1" of=meta.raw bs=1M count=1
xxd meta.raw > meta.txt
# to help debug if the next grep fails
+ls -l meta.txt
+head -n 100 meta.txt
grep -A4 -B4 00001200 meta.txt
grep -B1 "$vg {" meta.txt > meta.vg
4 years, 7 months
master - tests: use standard md devices
by David Teigland
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=1fe04f89efa97bf25b7...
Commit: 1fe04f89efa97bf25b7b5ca6f382e957a9adf43d
Parent: 772dbb1e39d007c770dd7ddb5ca912009658f8a0
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Wed Sep 11 13:26:41 2019 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Thu Sep 12 10:11:27 2019 -0500
tests: use standard md devices
---
test/lib/aux.sh | 27 ++++++++++-
test/shell/duplicate-pvs-md0.sh | 74 +++++++++++++++------------
test/shell/duplicate-pvs-md1.sh | 95 +++++++++++++++++------------------
test/shell/lvm-on-md.sh | 50 +++++++++++--------
test/shell/pvcreate-operation-md.sh | 37 ++++++++++----
5 files changed, 169 insertions(+), 114 deletions(-)
diff --git a/test/lib/aux.sh b/test/lib/aux.sh
index 32d5a0b..b7207eb 100644
--- a/test/lib/aux.sh
+++ b/test/lib/aux.sh
@@ -775,6 +775,20 @@ cleanup_md_dev() {
rm -f MD_DEV MD_DEVICES MD_DEV_PV
}
+wait_md_create() {
+ local md=$1
+
+ while :; do
+ if ! grep `basename $md` /proc/mdstat; then
+ echo "$md not ready"
+ cat /proc/mdstat
+ sleep 2
+ else
+ break
+ fi
+ done
+}
+
prepare_backing_dev() {
local size=${1=32}
shift
@@ -1093,6 +1107,17 @@ extend_filter() {
lvmconf "$filter" "devices/scan_lvs = 1"
}
+extend_filter_md() {
+ local filter
+
+ filter=$(grep ^devices/global_filter CONFIG_VALUES | tail -n 1)
+ for rx in "$@"; do
+ filter=$(echo "$filter" | sed -e "s:\\[:[ \"$rx\", :")
+ done
+ lvmconf "$filter"
+ lvmconf "devices/scan = [ \"$DM_DEV_DIR\", \"/dev\" ]"
+}
+
extend_filter_LVMTEST() {
extend_filter "a|$DM_DEV_DIR/$PREFIX|" "$@"
}
@@ -1165,7 +1190,7 @@ devices/dir = "$DM_DEV_DIR"
devices/filter = "a|.*|"
devices/global_filter = [ "a|$DM_DEV_DIR/mapper/${PREFIX}.*pv[0-9_]*$|", "r|.*|" ]
devices/md_component_detection = 0
-devices/scan = "$DM_DEV_DIR"
+devices/scan = [ "$DM_DEV_DIR" ]
devices/sysfs_scan = 1
devices/write_cache_state = 0
global/abort_on_internal_errors = 1
diff --git a/test/shell/duplicate-pvs-md0.sh b/test/shell/duplicate-pvs-md0.sh
index 5578a0c..4c7863d 100644
--- a/test/shell/duplicate-pvs-md0.sh
+++ b/test/shell/duplicate-pvs-md0.sh
@@ -11,6 +11,7 @@
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
SKIP_WITH_LVMPOLLD=1
+SKIP_WITH_LVMLOCKD=1
RUNDIR="/run"
test -d "$RUNDIR" || RUNDIR="/var/run"
@@ -29,6 +30,7 @@ _clear_online_files() {
test -f /proc/mdstat && grep -q raid0 /proc/mdstat || \
modprobe raid0 || skip
+not grep md0 /proc/mdstat
aux lvmconf 'devices/md_component_detection = 1'
@@ -37,7 +39,7 @@ aux lvmconf 'devices/md_component_detection = 1'
# want to rely on that ability in this test.
aux lvmconf 'devices/obtain_device_list_from_udev = 0'
-aux extend_filter_LVMTEST "a|/dev/md|"
+aux extend_filter_md "a|/dev/md|"
aux prepare_devs 4
@@ -60,10 +62,9 @@ pvcreate "$dev3"
aux lvmconf 'devices/md_component_checks = "auto"'
-aux prepare_md_dev 0 64 2 "$dev1" "$dev2"
-cat /proc/mdstat
-mddev=$(< MD_DEV)
-pvdev=$(< MD_DEV_PV)
+mddev="/dev/md0"
+mdadm --create --metadata=1.0 "$mddev" --level 0 --chunk=64 --raid-devices=2 "$dev1" "$dev2"
+aux wait_md_create "$mddev"
pvcreate "$mddev"
PVIDMD=`pvs $mddev --noheading -o uuid | tr -d - | awk '{print $1}'`
echo $PVIDMD
@@ -119,7 +120,11 @@ not grep "active" out
vgchange -an $vg
vgremove -f $vg
-aux cleanup_md_dev
+mdadm --stop "$mddev"
+aux udev_wait
+wipefs -a "$dev1"
+wipefs -a "$dev2"
+aux udev_wait
##########################################
@@ -130,10 +135,9 @@ aux cleanup_md_dev
aux lvmconf 'devices/md_component_checks = "start"'
-aux prepare_md_dev 0 64 2 "$dev1" "$dev2"
-cat /proc/mdstat
-mddev=$(< MD_DEV)
-pvdev=$(< MD_DEV_PV)
+mddev="/dev/md0"
+mdadm --create --metadata=1.0 "$mddev" --level 0 --chunk=64 --raid-devices=2 "$dev1" "$dev2"
+aux wait_md_create "$mddev"
pvcreate "$mddev"
PVIDMD=`pvs $mddev --noheading -o uuid | tr -d - | awk '{print $1}'`
echo $PVIDMD
@@ -189,7 +193,11 @@ not grep "active" out
vgchange -an $vg
vgremove -f $vg
-aux cleanup_md_dev
+mdadm --stop "$mddev"
+aux udev_wait
+wipefs -a "$dev1"
+wipefs -a "$dev2"
+aux udev_wait
##########################################
@@ -200,10 +208,9 @@ aux cleanup_md_dev
aux lvmconf 'devices/md_component_checks = "auto"'
-aux prepare_md_dev 0 64 2 "$dev1" "$dev2"
-cat /proc/mdstat
-mddev=$(< MD_DEV)
-pvdev=$(< MD_DEV_PV)
+mddev="/dev/md0"
+mdadm --create --metadata=1.0 "$mddev" --level 0 --chunk=64 --raid-devices=2 "$dev1" "$dev2"
+aux wait_md_create "$mddev"
pvcreate "$mddev"
PVIDMD=`pvs $mddev --noheading -o uuid | tr -d - | awk '{print $1}'`
echo $PVIDMD
@@ -245,7 +252,9 @@ pvscan --cache -aay "$dev2"
not ls "$RUNDIR/lvm/pvs_online/$PVIDMD"
not ls "$RUNDIR/lvm/vgs_online/$vg"
-aux cleanup_md_dev
+wipefs -a "$dev1"
+wipefs -a "$dev2"
+aux udev_wait
##########################################
# PV on an md raid0 device, start+stopped
@@ -255,11 +264,9 @@ aux cleanup_md_dev
aux lvmconf 'devices/md_component_checks = "start"'
-wipefs -a "$dev1" "$dev2"
-aux prepare_md_dev 0 64 2 "$dev1" "$dev2"
-cat /proc/mdstat
-mddev=$(< MD_DEV)
-pvdev=$(< MD_DEV_PV)
+mddev="/dev/md0"
+mdadm --create --metadata=1.0 "$mddev" --level 0 --chunk=64 --raid-devices=2 "$dev1" "$dev2"
+aux wait_md_create "$mddev"
pvcreate "$mddev"
PVIDMD=`pvs $mddev --noheading -o uuid | tr -d - | awk '{print $1}'`
echo $PVIDMD
@@ -304,7 +311,9 @@ not ls "$RUNDIR/lvm/vgs_online/$vg"
lvs -o active $vg |tee out || true
not grep "active" out
-aux cleanup_md_dev
+wipefs -a "$dev1"
+wipefs -a "$dev2"
+aux udev_wait
##########################################
@@ -316,11 +325,9 @@ aux cleanup_md_dev
aux lvmconf 'devices/md_component_checks = "start"'
-wipefs -a "$dev1" "$dev2"
-aux prepare_md_dev 0 64 2 "$dev1" "$dev2"
-cat /proc/mdstat
-mddev=$(< MD_DEV)
-pvdev=$(< MD_DEV_PV)
+mddev="/dev/md0"
+mdadm --create --metadata=1.0 "$mddev" --level 0 --chunk=64 --raid-devices=2 "$dev1" "$dev2"
+aux wait_md_create "$mddev"
pvcreate "$mddev"
PVIDMD=`pvs $mddev --noheading -o uuid | tr -d - | awk '{print $1}'`
echo $PVIDMD
@@ -361,7 +368,7 @@ not ls "$RUNDIR/lvm/pvs_online/$PVIDMD"
not ls "$RUNDIR/lvm/vgs_online/$vg"
aux enable_dev "$dev2"
-aux udev_wait
+aux aux udev_wait
cat /proc/mdstat
# for some reason enabling dev2 starts an odd md dev
mdadm --stop "$mddev" || true
@@ -369,6 +376,7 @@ mdadm --stop --scan
cat /proc/mdstat
wipefs -a "$dev1" || true
wipefs -a "$dev2" || true
+aux udev_wait
##########################################
# PV on an md raid0 device, auto+stopped
@@ -379,10 +387,9 @@ wipefs -a "$dev2" || true
aux lvmconf 'devices/md_component_checks = "auto"'
-aux prepare_md_dev 0 64 2 "$dev1" "$dev2"
-cat /proc/mdstat
-mddev=$(< MD_DEV)
-pvdev=$(< MD_DEV_PV)
+mddev="/dev/md0"
+mdadm --create --metadata=1.0 "$mddev" --level 0 --chunk=64 --raid-devices=2 "$dev1" "$dev2"
+aux wait_md_create "$mddev"
pvcreate "$mddev"
PVIDMD=`pvs $mddev --noheading -o uuid | tr -d - | awk '{print $1}'`
echo $PVIDMD
@@ -428,7 +435,7 @@ not ls "$RUNDIR/lvm/pvs_online/$PVIDMD"
not ls "$RUNDIR/lvm/vgs_online/$vg"
aux enable_dev "$dev2"
-aux udev_wait
+aux aux udev_wait
cat /proc/mdstat
# for some reason enabling dev2 starts an odd md dev
mdadm --stop "$mddev" || true
@@ -436,3 +443,4 @@ mdadm --stop --scan
cat /proc/mdstat
wipefs -a "$dev1" || true
wipefs -a "$dev2" || true
+aux udev_wait
diff --git a/test/shell/duplicate-pvs-md1.sh b/test/shell/duplicate-pvs-md1.sh
index ccd113f..d242e03 100644
--- a/test/shell/duplicate-pvs-md1.sh
+++ b/test/shell/duplicate-pvs-md1.sh
@@ -16,6 +16,7 @@
# . a single PV/VG cloned plus a dm wrapper (two separate dups of a PV)
SKIP_WITH_LVMPOLLD=1
+SKIP_WITH_LVMLOCKD=1
RUNDIR="/run"
test -d "$RUNDIR" || RUNDIR="/var/run"
@@ -34,6 +35,7 @@ _clear_online_files() {
test -f /proc/mdstat && grep -q raid1 /proc/mdstat || \
modprobe raid1 || skip
+not grep md0 /proc/mdstat
aux lvmconf 'devices/md_component_detection = 1'
@@ -42,7 +44,7 @@ aux lvmconf 'devices/md_component_detection = 1'
# want to rely on that ability in this test.
aux lvmconf 'devices/obtain_device_list_from_udev = 0'
-aux extend_filter_LVMTEST "a|/dev/md|"
+aux extend_filter_md "a|/dev/md|"
aux prepare_devs 4
@@ -65,11 +67,9 @@ pvcreate "$dev3"
aux lvmconf 'devices/md_component_checks = "auto"'
-aux prepare_md_dev 1 64 2 "$dev1" "$dev2"
-sleep 4
-cat /proc/mdstat
-mddev=$(< MD_DEV)
-pvdev=$(< MD_DEV_PV)
+mddev="/dev/md0"
+mdadm --create --metadata=1.0 "$mddev" --level 1 --chunk=64 --raid-devices=2 "$dev1" "$dev2"
+aux wait_md_create "$mddev"
pvcreate "$mddev"
PVIDMD=`pvs $mddev --noheading -o uuid | tr -d - | awk '{print $1}'`
echo $PVIDMD
@@ -125,7 +125,12 @@ not grep "active" out
vgchange -an $vg
vgremove -f $vg
-aux cleanup_md_dev
+mdadm --stop "$mddev"
+aux udev_wait
+wipefs -a "$dev1"
+wipefs -a "$dev2"
+aux udev_wait
+
##########################################
@@ -136,11 +141,9 @@ aux cleanup_md_dev
aux lvmconf 'devices/md_component_checks = "start"'
-aux prepare_md_dev 1 64 2 "$dev1" "$dev2"
-sleep 4
-cat /proc/mdstat
-mddev=$(< MD_DEV)
-pvdev=$(< MD_DEV_PV)
+mddev="/dev/md0"
+mdadm --create --metadata=1.0 "$mddev" --level 1 --chunk=64 --raid-devices=2 "$dev1" "$dev2"
+aux wait_md_create "$mddev"
pvcreate "$mddev"
PVIDMD=`pvs $mddev --noheading -o uuid | tr -d - | awk '{print $1}'`
echo $PVIDMD
@@ -210,7 +213,11 @@ not pvscan --cache -aay "$dev1"
vgchange -an $vg
vgremove -f $vg
-aux cleanup_md_dev
+mdadm --stop "$mddev"
+aux udev_wait
+wipefs -a "$dev1"
+wipefs -a "$dev2"
+aux udev_wait
##########################################
@@ -221,11 +228,9 @@ aux cleanup_md_dev
aux lvmconf 'devices/md_component_checks = "auto"'
-aux prepare_md_dev 1 64 2 "$dev1" "$dev2"
-sleep 4
-cat /proc/mdstat
-mddev=$(< MD_DEV)
-pvdev=$(< MD_DEV_PV)
+mddev="/dev/md0"
+mdadm --create --metadata=1.0 "$mddev" --level 1 --chunk=64 --raid-devices=2 "$dev1" "$dev2"
+aux wait_md_create "$mddev"
pvcreate "$mddev"
PVIDMD=`pvs $mddev --noheading -o uuid | tr -d - | awk '{print $1}'`
echo $PVIDMD
@@ -267,7 +272,10 @@ pvscan --cache -aay "$dev2"
not ls "$RUNDIR/lvm/pvs_online/$PVIDMD"
not ls "$RUNDIR/lvm/vgs_online/$vg"
-aux cleanup_md_dev
+wipefs -a "$dev1"
+wipefs -a "$dev2"
+aux udev_wait
+
##########################################
# PV on an md raid1 device, start+stopped
@@ -285,12 +293,9 @@ aux cleanup_md_dev
aux lvmconf 'devices/md_component_checks = "start"'
-wipefs -a "$dev1" "$dev2"
-aux prepare_md_dev 1 64 2 "$dev1" "$dev2"
-sleep 4
-cat /proc/mdstat
-mddev=$(< MD_DEV)
-pvdev=$(< MD_DEV_PV)
+mddev="/dev/md0"
+mdadm --create --metadata=1.0 "$mddev" --level 1 --chunk=64 --raid-devices=2 "$dev1" "$dev2"
+aux wait_md_create "$mddev"
pvcreate "$mddev"
PVIDMD=`pvs $mddev --noheading -o uuid | tr -d - | awk '{print $1}'`
echo $PVIDMD
@@ -367,12 +372,9 @@ wipefs -a "$dev2" || true
aux lvmconf 'devices/md_component_checks = "start"'
-wipefs -a "$dev1" "$dev2"
-aux prepare_md_dev 1 64 2 "$dev1" "$dev2"
-sleep 4
-cat /proc/mdstat
-mddev=$(< MD_DEV)
-pvdev=$(< MD_DEV_PV)
+mddev="/dev/md0"
+mdadm --create --metadata=1.0 "$mddev" --level 1 --chunk=64 --raid-devices=2 "$dev1" "$dev2"
+aux wait_md_create "$mddev"
pvcreate "$mddev"
PVIDMD=`pvs $mddev --noheading -o uuid | tr -d - | awk '{print $1}'`
echo $PVIDMD
@@ -442,11 +444,9 @@ wipefs -a "$dev2" || true
aux lvmconf 'devices/md_component_checks = "auto"'
-aux prepare_md_dev 1 64 2 "$dev1" "$dev2"
-sleep 4
-cat /proc/mdstat
-mddev=$(< MD_DEV)
-pvdev=$(< MD_DEV_PV)
+mddev="/dev/md0"
+mdadm --create --metadata=1.0 "$mddev" --level 1 --chunk=64 --raid-devices=2 "$dev1" "$dev2"
+aux wait_md_create "$mddev"
pvcreate "$mddev"
PVIDMD=`pvs $mddev --noheading -o uuid | tr -d - | awk '{print $1}'`
echo $PVIDMD
@@ -511,11 +511,9 @@ wipefs -a "$dev2" || true
aux lvmconf 'devices/md_component_checks = "auto"'
-aux prepare_md_dev 1 64 3 "$dev1" "$dev2" "$dev4"
-sleep 4
-cat /proc/mdstat
-mddev=$(< MD_DEV)
-pvdev=$(< MD_DEV_PV)
+mddev="/dev/md0"
+mdadm --create --metadata=1.0 "$mddev" --level 1 --chunk=64 --raid-devices=3 "$dev1" "$dev2" "$dev4"
+aux wait_md_create "$mddev"
pvcreate "$mddev"
PVIDMD=`pvs $mddev --noheading -o uuid | tr -d - | awk '{print $1}'`
echo $PVIDMD
@@ -563,7 +561,11 @@ pvscan --cache -aay "$dev4"
not ls "$RUNDIR/lvm/pvs_online/$PVIDMD"
not ls "$RUNDIR/lvm/vgs_online/$vg"
-aux cleanup_md_dev
+wipefs -a "$dev1"
+wipefs -a "$dev2"
+wipefs -a "$dev4"
+aux udev_wait
+
##########################################
@@ -574,12 +576,9 @@ aux cleanup_md_dev
aux lvmconf 'devices/md_component_checks = "start"'
-wipefs -a "$dev1" "$dev2" "$dev4"
-aux prepare_md_dev 1 64 3 "$dev1" "$dev2" "$dev4"
-sleep 4
-cat /proc/mdstat
-mddev=$(< MD_DEV)
-pvdev=$(< MD_DEV_PV)
+mddev="/dev/md0"
+mdadm --create --metadata=1.0 "$mddev" --level 1 --chunk=64 --raid-devices=3 "$dev1" "$dev2" "$dev4"
+aux wait_md_create "$mddev"
pvcreate "$mddev"
PVIDMD=`pvs $mddev --noheading -o uuid | tr -d - | awk '{print $1}'`
echo $PVIDMD
diff --git a/test/shell/lvm-on-md.sh b/test/shell/lvm-on-md.sh
index 2877ea2..6862101 100644
--- a/test/shell/lvm-on-md.sh
+++ b/test/shell/lvm-on-md.sh
@@ -11,6 +11,7 @@
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
SKIP_WITH_LVMPOLLD=1
+SKIP_WITH_LVMLOCKD=1
RUNDIR="/run"
test -d "$RUNDIR" || RUNDIR="/var/run"
@@ -29,6 +30,7 @@ _clear_online_files() {
test -f /proc/mdstat && grep -q raid1 /proc/mdstat || \
modprobe raid1 || skip
+not grep md0 /proc/mdstat
aux lvmconf 'devices/md_component_detection = 1'
@@ -41,19 +43,16 @@ aux lvmconf 'devices/hints = "none"'
# want to rely on that ability in this test.
aux lvmconf 'devices/obtain_device_list_from_udev = 0'
-aux extend_filter_LVMTEST "a|/dev/md|"
+aux extend_filter_md "a|/dev/md|"
aux prepare_devs 3
# create 2 disk MD raid1 array
# by default using metadata format 1.0 with data at the end of device
-aux prepare_md_dev 1 64 2 "$dev1" "$dev2"
-
-cat /proc/mdstat
-
-mddev=$(< MD_DEV)
-pvdev=$(< MD_DEV_PV)
+mddev="/dev/md0"
+mdadm --create --metadata=1.0 "$mddev" --level 1 --chunk=64 --raid-devices=2 "$dev1" "$dev2"
+aux wait_md_create "$mddev"
vgcreate $vg "$mddev"
PVIDMD=`pvs $mddev --noheading -o uuid | tr -d - | awk '{print $1}'`
@@ -164,19 +163,21 @@ aux udev_wait
vgremove -f $vg
-aux cleanup_md_dev
+mdadm --stop "$mddev"
+aux udev_wait
+wipefs -a "$dev1"
+wipefs -a "$dev2"
+aux udev_wait
+
# create 2 disk MD raid0 array
# by default using metadata format 1.0 with data at the end of device
# When a raid0 md array is stopped, the components will not look like
# duplicate PVs as they do with raid1.
-aux prepare_md_dev 0 64 2 "$dev1" "$dev2"
-
-cat /proc/mdstat
-
-mddev=$(< MD_DEV)
-pvdev=$(< MD_DEV_PV)
+mddev="/dev/md0"
+mdadm --create --metadata=1.0 "$mddev" --level 0 --chunk=64 --raid-devices=2 "$dev1" "$dev2"
+aux wait_md_create "$mddev"
vgcreate $vg "$mddev"
PVIDMD=`pvs $mddev --noheading -o uuid | tr -d - | awk '{print $1}'`
@@ -288,7 +289,12 @@ aux udev_wait
vgremove -f $vg
-aux cleanup_md_dev
+mdadm --stop "$mddev"
+aux udev_wait
+wipefs -a "$dev1"
+wipefs -a "$dev2"
+aux udev_wait
+
# Repeat tests using the default config settings
@@ -299,12 +305,10 @@ aux lvmconf 'devices/obtain_device_list_from_udev = 1'
# by default using metadata format 1.0 with data at the end of device
# When a raid0 md array is stopped, the components will not look like
# duplicate PVs as they do with raid1.
-aux prepare_md_dev 0 64 2 "$dev1" "$dev2"
-cat /proc/mdstat
-
-mddev=$(< MD_DEV)
-pvdev=$(< MD_DEV_PV)
+mddev="/dev/md0"
+mdadm --create --metadata=1.0 "$mddev" --level 0 --chunk=64 --raid-devices=2 "$dev1" "$dev2"
+aux wait_md_create "$mddev"
# Create an unused PV so that there is at least one PV in the hints
# when the MD dev is stopped. If there are no PVs, the hints are
@@ -454,5 +458,9 @@ aux udev_wait
vgremove -f $vg
-aux cleanup_md_dev
+mdadm --stop "$mddev"
+aux udev_wait
+wipefs -a "$dev1"
+wipefs -a "$dev2"
+aux udev_wait
diff --git a/test/shell/pvcreate-operation-md.sh b/test/shell/pvcreate-operation-md.sh
index 4b51932..12cf891 100644
--- a/test/shell/pvcreate-operation-md.sh
+++ b/test/shell/pvcreate-operation-md.sh
@@ -20,17 +20,19 @@ which sfdisk || skip
test -f /proc/mdstat && grep -q raid0 /proc/mdstat || \
modprobe raid0 || skip
+not grep md0 /proc/mdstat
aux lvmconf 'devices/md_component_detection = 1'
-aux extend_filter_LVMTEST "a|/dev/md|"
+aux extend_filter_md "a|/dev/md|"
aux prepare_devs 2
# create 2 disk MD raid0 array (stripe_width=128K)
-aux prepare_md_dev 0 64 2 "$dev1" "$dev2"
+mddev="/dev/md0"
+mdadm --create --metadata=1.0 "$mddev" --level 0 --chunk=64 --raid-devices=2 "$dev1" "$dev2"
+aux wait_md_create "$mddev"
-mddev=$(< MD_DEV)
-pvdev=$(< MD_DEV_PV)
+pvdev="$mddev"
# Test alignment of PV on MD without any MD-aware or topology-aware detection
# - should treat $mddev just like any other block device
@@ -82,7 +84,7 @@ EOF
if aux kernel_at_least 2 6 33 ; then
# in case the system is running without devtmpfs /dev
# wait here for created device node on tmpfs
- test "$DM_DEV_DIR" = "/dev" || cp -LR "${mddev}p1" "${pvdev%/*}"
+ # test "$DM_DEV_DIR" = "/dev" || cp -LR "${mddev}p1" "${pvdev%/*}"
pvcreate --metadatasize 128k "${pvdev}p1"
@@ -105,17 +107,23 @@ EOF
check pv_field "${pvdev}p1" pe_start $pv_align --units b --nosuffix
pvremove "${pvdev}p1"
- test "$DM_DEV_DIR" = "/dev" || rm -f "${pvdev}p1"
+ # test "$DM_DEV_DIR" = "/dev" || rm -f "${pvdev}p1"
fi
fi
+mdadm --stop "$mddev"
+aux udev_wait
+wipefs -a "$dev1"
+wipefs -a "$dev2"
+aux udev_wait
+
# Test newer topology-aware alignment detection w/ --dataalignment override
if aux kernel_at_least 2 6 33 ; then
- # make sure we're clean for another test
- dd if=/dev/zero of="$mddev" bs=512 count=4 conv=fdatasync
- partprobe -s "$mddev"
- aux prepare_md_dev 0 1024 2 "$dev1" "$dev2"
- pvdev=$(< MD_DEV_PV)
+
+ mddev="/dev/md0"
+ mdadm --create --metadata=1.0 "$mddev" --level 0 --chunk=1024 --raid-devices=2 "$dev1" "$dev2"
+ aux wait_md_create "$mddev"
+ pvdev="$mddev"
# optimal_io_size=2097152, minimum_io_size=1048576
pvcreate --metadatasize 128k \
@@ -130,4 +138,11 @@ if aux kernel_at_least 2 6 33 ; then
pvcreate --dataalignment 64k --metadatasize 128k \
--config 'devices { md_chunk_alignment=0 }' "$pvdev"
check pv_field "$pvdev" pe_start "192.00k"
+
+ mdadm --stop "$mddev"
+ aux udev_wait
+ wipefs -a "$dev1"
+ wipefs -a "$dev2"
+ aux udev_wait
+
fi
4 years, 7 months
master - tests: metadata-zero-space add info for debugging
by David Teigland
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=772dbb1e39d007c770d...
Commit: 772dbb1e39d007c770dd7ddb5ca912009658f8a0
Parent: 447ba5f1c20161d2ca89e0673fc4b219f65209a9
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Wed Sep 11 14:20:59 2019 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Wed Sep 11 14:20:59 2019 -0500
tests: metadata-zero-space add info for debugging
---
test/shell/metadata-zero-space.sh | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/test/shell/metadata-zero-space.sh b/test/shell/metadata-zero-space.sh
index 11c358b..f69aee5 100644
--- a/test/shell/metadata-zero-space.sh
+++ b/test/shell/metadata-zero-space.sh
@@ -35,6 +35,9 @@ dd if="$dev1" of=meta.raw bs=1M count=1
xxd meta.raw > meta.txt
+# to help debug if the next grep fails
+grep -A4 -B4 00001200 meta.txt
+
grep -B1 "$vg {" meta.txt > meta.vg
cat meta.vg
4 years, 7 months
master - tests: skip without xxd
by David Teigland
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=447ba5f1c20161d2ca8...
Commit: 447ba5f1c20161d2ca89e0673fc4b219f65209a9
Parent: 31b6a04e4c1e851dc9d51c42a6cb54a82afeb4b4
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Wed Sep 11 13:59:16 2019 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Wed Sep 11 14:01:55 2019 -0500
tests: skip without xxd
---
test/shell/metadata-bad-mdaheader.sh | 6 ++----
test/shell/metadata-zero-space.sh | 6 ++----
2 files changed, 4 insertions(+), 8 deletions(-)
diff --git a/test/shell/metadata-bad-mdaheader.sh b/test/shell/metadata-bad-mdaheader.sh
index cf24936..e9e303d 100644
--- a/test/shell/metadata-bad-mdaheader.sh
+++ b/test/shell/metadata-bad-mdaheader.sh
@@ -12,6 +12,8 @@
. lib/inittest
+xxd -v || skip
+
aux prepare_devs 3
get_devs
@@ -33,8 +35,6 @@ vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3"
pvs
-if [ -e "/usr/bin/xxd" ]; then
-
# read mda_header which is 4k from start of disk
dd if="$dev1" of=meta1 bs=4k count=1 skip=1
@@ -54,8 +54,6 @@ dd if=meta1-bad of="$dev1" bs=4k seek=1
pvs 2>&1 | tee out
grep "bad metadata header" out
-fi
-
pvs "$dev1"
pvs "$dev2"
pvs "$dev3"
diff --git a/test/shell/metadata-zero-space.sh b/test/shell/metadata-zero-space.sh
index 847ef44..11c358b 100644
--- a/test/shell/metadata-zero-space.sh
+++ b/test/shell/metadata-zero-space.sh
@@ -14,6 +14,8 @@ SKIP_WITH_LVMPOLLD=1
. lib/inittest
+xxd -v || skip
+
aux prepare_devs 1 256
get_devs
@@ -27,8 +29,6 @@ vgcreate $SHARED "$vg" "$dev1"
for i in `seq 1 50`; do lvcreate -l1 -an $vg; done
-if [ -e "/usr/bin/xxd" ]; then
-
# Check metadata copies are separated by zeroes in the first mda
dd if="$dev1" of=meta.raw bs=1M count=1
@@ -81,6 +81,4 @@ cat meta.count | wc -l
test "$(cat meta.count | wc -l)" -gt 20
-fi
-
vgremove -ff $vg
4 years, 7 months
master - tests: open-file-limit skip without prlimit
by David Teigland
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=31b6a04e4c1e851dc9d...
Commit: 31b6a04e4c1e851dc9d51c42a6cb54a82afeb4b4
Parent: 69b7c00a77e09d23d57eef9d35afb1dc4663478c
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Wed Sep 11 13:55:47 2019 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Wed Sep 11 14:01:55 2019 -0500
tests: open-file-limit skip without prlimit
---
test/shell/open-file-limit.sh | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/test/shell/open-file-limit.sh b/test/shell/open-file-limit.sh
index 87b0f7e..6bd632d 100644
--- a/test/shell/open-file-limit.sh
+++ b/test/shell/open-file-limit.sh
@@ -16,6 +16,8 @@ SKIP_WITH_LVMLOCKD=1
. lib/inittest
+prlimit -h || skip
+
aux lvmconf 'devices/pv_min_size = 1024'
aux prepare_devs 200 1
4 years, 7 months
master - tests: allow-mixed-block-sizes skip with older losetup
by David Teigland
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=69b7c00a77e09d23d57...
Commit: 69b7c00a77e09d23d57eef9d35afb1dc4663478c
Parent: 715d2c778fb8f7b705a5c222e02638cdf845ea5b
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Wed Sep 11 13:52:51 2019 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Wed Sep 11 14:01:55 2019 -0500
tests: allow-mixed-block-sizes skip with older losetup
---
test/shell/allow-mixed-block-sizes.sh | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/test/shell/allow-mixed-block-sizes.sh b/test/shell/allow-mixed-block-sizes.sh
index 1803256..2f0b3a0 100644
--- a/test/shell/allow-mixed-block-sizes.sh
+++ b/test/shell/allow-mixed-block-sizes.sh
@@ -14,6 +14,8 @@ SKIP_WITH_LVMPOLLD=1
. lib/inittest
+losetup -h | grep sector-size || skip
+
dd if=/dev/zero of=loopa bs=$((1024*1024)) count=2 2> /dev/null
dd if=/dev/zero of=loopb bs=$((1024*1024)) count=2 2> /dev/null
LOOP1=$(losetup -f loopa --sector-size 4096 --show)
4 years, 7 months
master - tests: cache-single tests require version 1 10
by David Teigland
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=715d2c778fb8f7b705a...
Commit: 715d2c778fb8f7b705a5c222e02638cdf845ea5b
Parent: 3e5e7fd6c93517278b2451a08f47e16d052babbb
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Wed Sep 11 13:48:03 2019 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Wed Sep 11 14:01:55 2019 -0500
tests: cache-single tests require version 1 10
---
test/shell/cache-single-types.sh | 2 +-
test/shell/cache-single-usage.sh | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/test/shell/cache-single-types.sh b/test/shell/cache-single-types.sh
index a973679..34a799a 100644
--- a/test/shell/cache-single-types.sh
+++ b/test/shell/cache-single-types.sh
@@ -16,7 +16,7 @@ SKIP_WITH_LVMPOLLD=1
. lib/inittest
-aux have_cache 1 3 0 || skip
+aux have_cache 1 10 0 || skip
aux have_raid 1 3 5 || skip
which mkfs.xfs || skip
diff --git a/test/shell/cache-single-usage.sh b/test/shell/cache-single-usage.sh
index 09d5b10..4896d7a 100644
--- a/test/shell/cache-single-usage.sh
+++ b/test/shell/cache-single-usage.sh
@@ -16,7 +16,7 @@ SKIP_WITH_LVMPOLLD=1
. lib/inittest
-aux have_cache 1 3 0 || skip
+aux have_cache 1 10 0 || skip
which mkfs.xfs || skip
mount_dir="mnt"
4 years, 7 months
master - pvscan: allow use of noudevsync option
by David Teigland
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=3e5e7fd6c93517278b2...
Commit: 3e5e7fd6c93517278b2451a08f47e16d052babbb
Parent: aae2e872b4572ba72fa0321391f7eb77f569e5ff
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Tue Sep 10 09:47:33 2019 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Tue Sep 10 09:47:33 2019 -0500
pvscan: allow use of noudevsync option
When pvscan is used to activate a VG via an
asynchronous service (i.e. lvm2-pvscan), there
is no requirement that the command wait for
udev to create device nodes before returning.
It's possible that waiting for udev is slow
enough to cause the service running the command
to time out. So, allow the --noudevsync option
to be given to pvscan to skip waiting for udev.
(This commit is not changing the lvm2-pvscan
service itself to use --noudevsync.)
Still unknown is whether there are any complex
LV activation cases in which lvm itself requires
access to a device node, in which case the udev
wait could be needed by lvm itself.
(When running an activation command directly
from the command line, it's generally expected
that the activated LVs are ready to use when
the command is finished, so lvm waits for
udev to finish creating the dev nodes.)
---
tools/command-lines.in | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/tools/command-lines.in b/tools/command-lines.in
index 1169224..65221c0 100644
--- a/tools/command-lines.in
+++ b/tools/command-lines.in
@@ -1498,7 +1498,7 @@ DESC: Display PV information.
pvscan --cache_long
OO: --ignorelockingfailure, --reportformat ReportFmt,
---activate ay, --major Number, --minor Number
+--activate ay, --major Number, --minor Number, --noudevsync
OP: PV|String ...
IO: --background
ID: pvscan_cache
4 years, 7 months
2019-09-05-add-io-manager - Merge branch '2019-09-05-add-io-manager' of git+ssh://sourceware.org/git/lvm2 into 2019-09-05-add-io-manager
by Joe Thornber
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=510a6e86a354537c981...
Commit: 510a6e86a354537c981386e7a46d5f2c26855660
Parent: e4693f7f8db38230362255ebc30d6b8a5bd40918 13c702f862008192a36ee171e546ba0d247bcf9f
Author: Joe Thornber <ejt(a)redhat.com>
AuthorDate: Mon Sep 9 18:21:20 2019 +0100
Committer: Joe Thornber <ejt(a)redhat.com>
CommitterDate: Mon Sep 9 18:21:20 2019 +0100
Merge branch '2019-09-05-add-io-manager' of git+ssh://sourceware.org/git/lvm2 into 2019-09-05-add-io-manager
lib/device/io-manager.c | 62 +++++++++++++++++++++++++---------------------
lib/device/io-manager.h | 4 +-
2 files changed, 36 insertions(+), 30 deletions(-)
diff --cc lib/device/io-manager.h
index 253b3ad,af33259..923d0be
--- a/lib/device/io-manager.h
+++ b/lib/device/io-manager.h
@@@ -61,11 -61,11 +61,11 @@@ struct io_engine
// The path is there purely for logging.
bool (*get_size)(struct io_engine *e, const char *path, int fd, sector_t *size);
bool (*get_block_sizes)(struct io_engine *e, const char *path, int fd,
- unsigned *physical, unsigned *logical);
+ unsigned *physical_block_size, unsigned *logical_block_size);
};
-struct io_engine *create_async_io_engine(bool use_o_direct);
-struct io_engine *create_sync_io_engine(bool use_o_direct);
+struct io_engine *create_async_io_engine(void);
+struct io_engine *create_sync_io_engine(void);
// Same as create_async_io_engine(), except writes are not acted upon.
// Used when running with --test.
@@@ -198,11 -197,10 +198,11 @@@ bool io_invalidate_dev(struct io_manage
bool io_invalidate_all(struct io_manager *iom);
bool io_dev_size(struct io_dev *dev, uint64_t *sectors);
- bool io_dev_block_sizes(struct io_dev *dev, unsigned *physical, unsigned *block_size);
+ bool io_dev_block_sizes(struct io_dev *dev, unsigned *physical_block_size, unsigned *logical_block_size);
// For testing and debug only
-int io_get_fd(struct io_dev *dev);
+void *io_get_dev_context(struct io_dev *dev);
+int io_get_fd(void *dev_context);
bool io_is_well_formed(struct io_manager *iom);
//----------------------------------------------------------------
4 years, 7 months
2019-09-05-add-io-manager - [io-manager] Reopen without O_DIRECT if we need to write a partial block.
by Joe Thornber
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=e4693f7f8db38230362...
Commit: e4693f7f8db38230362255ebc30d6b8a5bd40918
Parent: 4b25dd7bc229645535698109fb411a9c0752c446
Author: Joe Thornber <ejt(a)redhat.com>
AuthorDate: Mon Sep 9 18:18:46 2019 +0100
Committer: Joe Thornber <ejt(a)redhat.com>
CommitterDate: Mon Sep 9 18:18:46 2019 +0100
[io-manager] Reopen without O_DIRECT if we need to write a partial block.
Still need to do a bit more testing.
Also need to think more about how we guarantee that we've reopened
the same device. Pass in a device_id_extractor object to push the
issue up a layer?
---
lib/device/io-manager.c | 87 +++++++++++++++++++++++++-------
lib/device/io-manager.h | 14 +++--
test/unit/io-manager-utils_t.c | 10 ++--
test/unit/io-manager_t.c | 107 ++++++++++++++++++++++++++++++----------
4 files changed, 161 insertions(+), 57 deletions(-)
diff --git a/lib/device/io-manager.c b/lib/device/io-manager.c
index 9b44ff3..9800eee 100644
--- a/lib/device/io-manager.c
+++ b/lib/device/io-manager.c
@@ -137,7 +137,6 @@ struct async_engine {
struct cb_set *cbs;
unsigned page_mask;
unsigned page_sector_mask;
- bool use_o_direct;
struct dm_list completed_fallbacks;
};
@@ -186,12 +185,11 @@ static int _open_common(const char *path, int os_flags)
return fd;
}
-static int _async_open(struct io_engine *ioe, const char *path, unsigned flags)
+static int _async_open(struct io_engine *ioe, const char *path, unsigned flags, bool o_direct)
{
- struct async_engine *e = _to_async(ioe);
int os_flags = 0;
- if (e->use_o_direct)
+ if (o_direct)
os_flags |= O_DIRECT;
if (flags & EF_READ_ONLY)
@@ -474,7 +472,7 @@ static bool _common_get_block_sizes(struct io_engine *e, const char *path, int f
return true;
}
-struct io_engine *create_async_io_engine(bool use_o_direct)
+struct io_engine *create_async_io_engine(void)
{
int r;
struct async_engine *e = malloc(sizeof(*e));
@@ -508,15 +506,14 @@ struct io_engine *create_async_io_engine(bool use_o_direct)
e->page_mask = sysconf(_SC_PAGESIZE) - 1;
e->page_sector_mask = (sysconf(_SC_PAGESIZE) / 512) - 1;
- e->use_o_direct = use_o_direct;
dm_list_init(&e->completed_fallbacks);
return &e->e;
}
-struct io_engine *create_test_io_engine(bool use_o_direct)
+struct io_engine *create_test_io_engine(void)
{
- struct io_engine *ioe = create_async_io_engine(use_o_direct);
+ struct io_engine *ioe = create_async_io_engine();
if (ioe) {
struct async_engine *e = _to_async(ioe);
@@ -536,7 +533,6 @@ struct sync_io {
struct sync_engine {
struct io_engine e;
struct dm_list complete;
- bool use_o_direct;
};
static struct sync_engine *_to_sync(struct io_engine *e)
@@ -550,12 +546,11 @@ static void _sync_destroy(struct io_engine *ioe)
free(e);
}
-static int _sync_open(struct io_engine *ioe, const char *path, unsigned flags)
+static int _sync_open(struct io_engine *ioe, const char *path, unsigned flags, bool o_direct)
{
- struct sync_engine *e = _to_sync(ioe);
int os_flags = 0;
- if (e->use_o_direct)
+ if (o_direct)
os_flags |= O_DIRECT;
if (flags & EF_READ_ONLY)
@@ -637,7 +632,7 @@ static unsigned _sync_max_io(struct io_engine *e)
return 1;
}
-struct io_engine *create_sync_io_engine(bool use_o_direct)
+struct io_engine *create_sync_io_engine(void)
{
struct sync_engine *e = malloc(sizeof(*e));
@@ -652,7 +647,6 @@ struct io_engine *create_sync_io_engine(bool use_o_direct)
e->e.max_io = _sync_max_io;
e->e.get_size = _common_get_size;
e->e.get_block_sizes = _common_get_block_sizes;
- e->use_o_direct = use_o_direct;
dm_list_init(&e->complete);
return &e->e;
@@ -719,6 +713,7 @@ struct io_dev_internal {
// These are the flags that actually used to open the dev.
unsigned flags;
+ bool opened_o_direct;
// Reopen uses this to check it's reopened the same device.
bool is_device;
@@ -740,6 +735,7 @@ struct io_dev_internal {
struct io_manager {
sector_t block_sectors;
uint64_t block_mask;
+ uint64_t page_sector_mask;
// 1 bit set for every sector in a block.
uint64_t sectors_mask;
@@ -748,6 +744,7 @@ struct io_manager {
uint64_t nr_cache_blocks;
unsigned max_io;
unsigned max_cache_devs;
+ bool use_o_direct;
struct io_engine *engine;
@@ -916,7 +913,7 @@ static struct io_dev_internal *_new_dev(struct io_manager *iom,
}
}
- dev->fd = iom->engine->open(iom->engine, path, flags);
+ dev->fd = iom->engine->open(iom->engine, path, flags, iom->use_o_direct);
if (dev->fd < 0) {
log_error("couldn't open io_dev(%s)", path);
free(dev);
@@ -937,6 +934,7 @@ static struct io_dev_internal *_new_dev(struct io_manager *iom,
dev->iom = iom;
dev->holders = 1;
dev->blocks = 0;
+ dev->opened_o_direct = iom->use_o_direct;
v.ptr = dev;
if (!radix_tree_insert(iom->dev_tree, (uint8_t *) path, (uint8_t *) (path + strlen(path)), v)) {
@@ -1012,7 +1010,7 @@ static struct io_dev_internal *_upgrade_dev(struct io_manager *iom, const char *
// Fast path
int fd;
- fd = iom->engine->open(iom->engine, path, flags);
+ fd = iom->engine->open(iom->engine, path, flags, iom->use_o_direct);
if ((fd < 0) || !_check_same_device(dev, fd, path)) {
log_error("couldn't reopen io_dev(%s)", path);
_dec_holders(dev);
@@ -1023,6 +1021,7 @@ static struct io_dev_internal *_upgrade_dev(struct io_manager *iom, const char *
dev->fd = fd;
dev->flags = flags;
+ dev->opened_o_direct = iom->use_o_direct;
}
return dev;
@@ -1243,6 +1242,29 @@ static void _complete_io(void *context, int err)
}
}
+static void _wait_all(struct io_manager *iom);
+static bool _reopen_without_o_direct(struct io_manager *iom, struct io_dev_internal *dev)
+{
+ int fd;
+
+ _wait_all(iom);
+
+ fd = iom->engine->open(iom->engine, dev->path, dev->flags, false);
+ if (fd < 0)
+ return false;
+
+ if (!_check_same_device(dev, fd, dev->path)) {
+ iom->engine->close(iom->engine, fd);
+ return false;
+ }
+
+ iom->engine->close(iom->engine, dev->fd);
+ dev->fd = fd;
+ dev->opened_o_direct = false;
+
+ return true;
+}
+
static void _issue_sectors(struct block *b, sector_t sb, sector_t se)
{
struct io_manager *iom = b->iom;
@@ -1287,10 +1309,16 @@ static void _issue_whole_block(struct block *b, enum dir d)
_issue_sectors(b, 0, b->iom->block_sectors);
}
+static bool _is_partial_write(struct io_manager *iom, struct block *b)
+{
+ return (b->io_dir == DIR_WRITE) && (b->dirty_bits != iom->block_mask);
+}
+
// |b->list| should be valid (either pointing to itself, on one of the other
// lists.
static void _issue(struct block *b, enum dir d)
{
+ bool fail = false;
struct io_manager *iom = b->iom;
if (_test_flags(b, BF_IO_PENDING))
@@ -1300,12 +1328,21 @@ static void _issue(struct block *b, enum dir d)
assert(!b->io_count);
b->io_dir = d;
+ if (_is_partial_write(iom, b) && b->dev->opened_o_direct) {
+ if (!_reopen_without_o_direct(iom, b->dev))
+ fail = true;
+ }
+
_set_flags(b, BF_IO_PENDING);
iom->nr_io_pending++;
dm_list_move(&iom->io_pending, &b->list);
- if ((d == DIR_WRITE) && (b->dirty_bits != iom->block_mask))
+ if (fail)
+ _complete_io(b, -EIO);
+
+ else if (_is_partial_write(iom, b))
_issue_partial_write(b);
+
else
_issue_whole_block(b, d);
}
@@ -1584,7 +1621,8 @@ static uint64_t _calc_block_mask(sector_t nr_sectors)
}
struct io_manager *io_manager_create(sector_t block_sectors, unsigned nr_cache_blocks,
- unsigned max_cache_devs, struct io_engine *engine)
+ unsigned max_cache_devs, struct io_engine *engine,
+ bool use_o_direct)
{
struct io_manager *iom;
unsigned max_io = engine->max_io(engine);
@@ -1607,6 +1645,7 @@ struct io_manager *io_manager_create(sector_t block_sectors, unsigned nr_cache_b
iom->nr_cache_blocks = nr_cache_blocks;
iom->max_io = nr_cache_blocks < max_io ? nr_cache_blocks : max_io;
iom->max_cache_devs = max_cache_devs;
+ iom->use_o_direct = use_o_direct;
iom->engine = engine;
iom->dev_index = 0;
iom->nr_open = 0;
@@ -1651,6 +1690,8 @@ struct io_manager *io_manager_create(sector_t block_sectors, unsigned nr_cache_b
}
dm_list_init(&iom->dev_lru);
+ iom->page_sector_mask = (sysconf(_SC_PAGESIZE) / 512) - 1;
+
return iom;
}
@@ -1989,9 +2030,15 @@ bool io_invalidate_all(struct io_manager *iom)
return it.success;
}
-int io_get_fd(struct io_dev *dev)
+void *io_get_dev_context(struct io_dev *dev)
+{
+ return dev->idev;
+}
+
+int io_get_fd(void *dev_context)
{
- return dev->idev->fd;
+ struct io_dev_internal *idev = dev_context;
+ return idev->fd;
}
bool io_is_well_formed(struct io_manager *iom)
diff --git a/lib/device/io-manager.h b/lib/device/io-manager.h
index 87429b6..253b3ad 100644
--- a/lib/device/io-manager.h
+++ b/lib/device/io-manager.h
@@ -50,7 +50,7 @@ enum {
struct io_engine {
void (*destroy)(struct io_engine *e);
- int (*open)(struct io_engine *e, const char *path, unsigned flags);
+ int (*open)(struct io_engine *e, const char *path, unsigned flags, bool o_direct);
void (*close)(struct io_engine *e, int fd);
unsigned (*max_io)(struct io_engine *e);
@@ -64,12 +64,12 @@ struct io_engine {
unsigned *physical, unsigned *logical);
};
-struct io_engine *create_async_io_engine(bool use_o_direct);
-struct io_engine *create_sync_io_engine(bool use_o_direct);
+struct io_engine *create_async_io_engine(void);
+struct io_engine *create_sync_io_engine(void);
// Same as create_async_io_engine(), except writes are not acted upon.
// Used when running with --test.
-struct io_engine *create_test_io_engine(bool use_o_direct);
+struct io_engine *create_test_io_engine(void);
/*----------------------------------------------------------------*/
@@ -104,7 +104,8 @@ struct block {
* dev will be closed, and all its data invalidated.
*/
struct io_manager *io_manager_create(sector_t block_size, unsigned nr_cache_blocks,
- unsigned max_cache_devs, struct io_engine *engine);
+ unsigned max_cache_devs, struct io_engine *engine,
+ bool use_o_direct);
void io_manager_destroy(struct io_manager *iom);
// IMPORTANT: It is up to the caller to normalise the device path. io does
@@ -200,7 +201,8 @@ bool io_dev_size(struct io_dev *dev, uint64_t *sectors);
bool io_dev_block_sizes(struct io_dev *dev, unsigned *physical, unsigned *block_size);
// For testing and debug only
-int io_get_fd(struct io_dev *dev);
+void *io_get_dev_context(struct io_dev *dev);
+int io_get_fd(void *dev_context);
bool io_is_well_formed(struct io_manager *iom);
//----------------------------------------------------------------
diff --git a/test/unit/io-manager-utils_t.c b/test/unit/io-manager-utils_t.c
index a23c2a5..8384c4e 100644
--- a/test/unit/io-manager-utils_t.c
+++ b/test/unit/io-manager-utils_t.c
@@ -95,7 +95,7 @@ static void *_fix_init(struct io_engine *engine)
}
close(fd);
- f->iom = io_manager_create(T_BLOCK_SIZE / 512, NR_BLOCKS, 256, engine);
+ f->iom = io_manager_create(T_BLOCK_SIZE / 512, NR_BLOCKS, 256, engine, true);
T_ASSERT(f->iom);
f->dev = io_get_dev(f->iom, f->fname, 0);
@@ -106,14 +106,14 @@ static void *_fix_init(struct io_engine *engine)
static void *_async_init(void)
{
- struct io_engine *e = create_async_io_engine(_use_o_direct());
+ struct io_engine *e = create_async_io_engine();
T_ASSERT(e);
return _fix_init(e);
}
static void *_sync_init(void)
{
- struct io_engine *e = create_sync_io_engine(_use_o_direct());
+ struct io_engine *e = create_sync_io_engine();
T_ASSERT(e);
return _fix_init(e);
}
@@ -236,10 +236,10 @@ static void _reopen(struct fixture *f)
io_put_dev(f->dev);
io_manager_destroy(f->iom);
- engine = create_async_io_engine(_use_o_direct());
+ engine = create_async_io_engine();
T_ASSERT(engine);
- f->iom = io_manager_create(T_BLOCK_SIZE / 512, NR_BLOCKS, 256, engine);
+ f->iom = io_manager_create(T_BLOCK_SIZE / 512, NR_BLOCKS, 256, engine, _use_o_direct());
T_ASSERT(f->iom);
f->dev = io_get_dev(f->iom, f->fname, 0);
diff --git a/test/unit/io-manager_t.c b/test/unit/io-manager_t.c
index d228257..f4187c1 100644
--- a/test/unit/io-manager_t.c
+++ b/test/unit/io-manager_t.c
@@ -57,7 +57,7 @@ struct mock_call {
enum dir d;
// We can't store the dev here because we want to track writebacks
// and the dev may have been put by then.
- int fd;
+ void *fd_context;
sector_t sb;
sector_t se;
bool issue_r;
@@ -119,7 +119,7 @@ static void _expect_read(struct mock_engine *e, struct io_dev *dev, block_addres
mc->m = E_ISSUE;
mc->match_args = true;
mc->d = DIR_READ;
- mc->fd = io_get_fd(dev);
+ mc->fd_context = io_get_dev_context(dev);
_set_block(e, mc, b);
mc->issue_r = true;
mc->wait_r = true;
@@ -142,7 +142,7 @@ static void _expect_write(struct mock_engine *e, struct io_dev *dev, block_addre
mc->m = E_ISSUE;
mc->match_args = true;
mc->d = DIR_WRITE;
- mc->fd = io_get_fd(dev);
+ mc->fd_context = io_get_dev_context(dev);
mc->sb = b * e->block_size;
mc->se = mc->sb + e->block_size;
mc->issue_r = true;
@@ -158,7 +158,11 @@ static void _expect_partial_write(struct mock_engine *e,
mc->m = E_ISSUE;
mc->match_args = true;
mc->d = DIR_WRITE;
- mc->fd = io_get_fd(dev);
+
+ // FIXME: this can be reopened to remove a partial write, so we
+ // shouldn't call the io_get_fd(dev) until the validation step, but
+ // the dev object will not be held/exist at that point ...
+ mc->fd_context = io_get_dev_context(dev);
mc->sb = sb;
mc->se = se;
mc->issue_r = true;
@@ -174,7 +178,7 @@ static void _expect_partial_write_bad_issue(struct mock_engine *e,
mc->m = E_ISSUE;
mc->match_args = true;
mc->d = DIR_WRITE;
- mc->fd = io_get_fd(dev);
+ mc->fd_context = io_get_dev_context(dev);
mc->sb = sb;
mc->se = se;
mc->issue_r = false;
@@ -190,7 +194,7 @@ static void _expect_partial_write_bad_wait(struct mock_engine *e,
mc->m = E_ISSUE;
mc->match_args = true;
mc->d = DIR_WRITE;
- mc->fd = io_get_fd(dev);
+ mc->fd_context = io_get_dev_context(dev);
mc->sb = sb;
mc->se = se;
mc->issue_r = true;
@@ -204,7 +208,7 @@ static void _expect_read_bad_issue(struct mock_engine *e, struct io_dev *dev, bl
mc->m = E_ISSUE;
mc->match_args = true;
mc->d = DIR_READ;
- mc->fd = io_get_fd(dev);
+ mc->fd_context = io_get_dev_context(dev);
_set_block(e, mc, b);
mc->issue_r = false;
mc->wait_r = true;
@@ -217,7 +221,7 @@ static void _expect_write_bad_issue(struct mock_engine *e, struct io_dev *dev, b
mc->m = E_ISSUE;
mc->match_args = true;
mc->d = DIR_WRITE;
- mc->fd = io_get_fd(dev);
+ mc->fd_context = io_get_dev_context(dev);
_set_block(e, mc, b);
mc->issue_r = false;
mc->wait_r = true;
@@ -230,7 +234,7 @@ static void _expect_read_bad_wait(struct mock_engine *e, struct io_dev *dev, blo
mc->m = E_ISSUE;
mc->match_args = true;
mc->d = DIR_READ;
- mc->fd = io_get_fd(dev);
+ mc->fd_context = io_get_dev_context(dev);
_set_block(e, mc, b);
mc->issue_r = true;
mc->wait_r = false;
@@ -243,7 +247,7 @@ static void _expect_write_bad_wait(struct mock_engine *e, struct io_dev *dev, bl
mc->m = E_ISSUE;
mc->match_args = true;
mc->d = DIR_WRITE;
- mc->fd = io_get_fd(dev);
+ mc->fd_context = io_get_dev_context(dev);
_set_block(e, mc, b);
mc->issue_r = true;
mc->wait_r = false;
@@ -265,7 +269,7 @@ static void _expect_get_size(struct mock_engine *e, struct io_dev *dev, uint64_t
mc->m = E_GET_SIZE;
mc->match_args = true;
mc->fail = true;
- mc->fd = io_get_fd(dev);
+ mc->fd_context = io_get_dev_context(dev);
mc->size = s;
dm_list_add(&e->expected_calls, &mc->list);
}
@@ -276,7 +280,7 @@ static void _expect_get_size_fail(struct mock_engine *e, struct io_dev *dev)
mc->m = E_GET_SIZE;
mc->match_args = true;
mc->fail = false;
- mc->fd = io_get_fd(dev);
+ mc->fd_context = io_get_dev_context(dev);
dm_list_add(&e->expected_calls, &mc->list);
}
@@ -333,7 +337,7 @@ static void _mock_destroy(struct io_engine *e)
free(_to_mock(e));
}
-static int _mock_open(struct io_engine *e, const char *path, unsigned flags)
+static int _mock_open(struct io_engine *e, const char *path, unsigned flags, bool o_direct)
{
struct mock_engine *me = _to_mock(e);
struct mock_call *mc;
@@ -365,7 +369,7 @@ static bool _mock_issue(struct io_engine *e, enum dir d, int fd,
mc = _match_pop(me, E_ISSUE);
if (mc->match_args) {
T_ASSERT(d == mc->d);
- T_ASSERT_EQUAL(fd, mc->fd);
+ T_ASSERT_EQUAL(fd, io_get_fd(mc->fd_context));
T_ASSERT(sb == mc->sb);
T_ASSERT(se == mc->se);
}
@@ -421,7 +425,7 @@ static bool _mock_get_size(struct io_engine *e, const char *path, int fd, uint64
struct mock_engine *me = _to_mock(e);
struct mock_call *mc = _match_pop(me, E_GET_SIZE);
if (mc->match_args && !mc->fail)
- T_ASSERT_EQUAL(fd, mc->fd);
+ T_ASSERT_EQUAL(fd, io_get_fd(mc->fd_context));
*s = mc->size;
r = mc->fail;
@@ -459,7 +463,8 @@ struct fixture {
};
static struct fixture *_fixture_init(sector_t block_size, unsigned nr_cache_blocks,
- unsigned max_cache_devs)
+ unsigned max_cache_devs,
+ bool use_o_direct)
{
struct fixture *f = malloc(sizeof(*f));
@@ -467,7 +472,8 @@ static struct fixture *_fixture_init(sector_t block_size, unsigned nr_cache_bloc
T_ASSERT(f->me);
_expect(f->me, E_MAX_IO);
- f->iom = io_manager_create(block_size, nr_cache_blocks, max_cache_devs, &f->me->e);
+ f->iom = io_manager_create(block_size, nr_cache_blocks, max_cache_devs,
+ &f->me->e, use_o_direct);
T_ASSERT(f->iom);
return f;
@@ -483,7 +489,7 @@ static void _fixture_exit(struct fixture *f)
static void *_small_fixture_init(void)
{
- return _fixture_init(T_BLOCK_SIZE >> SECTOR_SHIFT, 16, SMALL_MAX_CACHE_DEVS);
+ return _fixture_init(T_BLOCK_SIZE >> SECTOR_SHIFT, 16, SMALL_MAX_CACHE_DEVS, true);
}
static void _small_fixture_exit(void *context)
@@ -491,9 +497,19 @@ static void _small_fixture_exit(void *context)
_fixture_exit(context);
}
+static void *_no_o_direct_fixture_init(void)
+{
+ return _fixture_init(T_BLOCK_SIZE >> SECTOR_SHIFT, 16, SMALL_MAX_CACHE_DEVS, false);
+}
+
+static void _no_o_direct_fixture_exit(void *context)
+{
+ _fixture_exit(context);
+}
+
static void *_large_fixture_init(void)
{
- return _fixture_init(T_BLOCK_SIZE >> SECTOR_SHIFT, 1024, 256);
+ return _fixture_init(T_BLOCK_SIZE >> SECTOR_SHIFT, 1024, 256, true);
}
static void _large_fixture_exit(void *context)
@@ -510,7 +526,7 @@ static void good_create(sector_t block_size, unsigned nr_cache_blocks)
struct mock_engine *me = _mock_create(16, 128);
_expect(me, E_MAX_IO);
- iom = io_manager_create(block_size, nr_cache_blocks, 256, &me->e);
+ iom = io_manager_create(block_size, nr_cache_blocks, 256, &me->e, true);
T_ASSERT(iom);
_expect(me, E_DESTROY);
@@ -523,7 +539,7 @@ static void bad_create(sector_t block_size, unsigned nr_cache_blocks)
struct mock_engine *me = _mock_create(16, 128);
_expect(me, E_MAX_IO);
- iom = io_manager_create(block_size, nr_cache_blocks, 256, &me->e);
+ iom = io_manager_create(block_size, nr_cache_blocks, 256, &me->e, true);
T_ASSERT(!iom);
_expect(me, E_DESTROY);
@@ -1391,11 +1407,32 @@ static void test_concurrent_reads_after_invalidate(void *context)
* Partial block tests
*--------------------------------------------------------------*/
-// rather than having a single dirty flag we should rely on the dirty_bits field.
-// after a write we should clear the dirty_bits
-
-// different partial writes should aggregate in dirty_bits
-// nothing outside dirty_bits should be written
+static void test_reopen_without_direct(void *context)
+{
+ struct fixture *f = context;
+ const char *path = "/foo/bar/dev";
+ struct io_dev *dev;
+ struct mock_engine *me = f->me;
+ struct io_manager *iom = f->iom;
+
+ struct block *b;
+
+ _expect(f->me, E_OPEN);
+ dev = io_get_dev(f->iom, path, 0);
+
+ T_ASSERT(io_get_block_mask(iom, dev, 0, GF_ZERO, 0x1, &b));
+ io_put_block(b);
+
+ _expect(f->me, E_OPEN); // FIXME: check use_o_direct isn't set
+ _expect(f->me, E_CLOSE);
+
+ // Expect the write
+ _expect_partial_write(me, dev, 0, 1);
+ _expect(me, E_WAIT);
+
+ _expect(f->me, E_CLOSE);
+ io_put_dev(dev);
+}
static void _single_partial_write(struct fixture *f, uint64_t mask, sector_t sb, sector_t se)
{
@@ -2014,6 +2051,23 @@ static struct test_suite *_small_tests(void)
#undef T
#define T(path, desc, fn) register_test(ts, "/base/device/io-manager/core/partial-write/" path, desc, fn)
+ T("reopen-without-o-direct", "Partial writes prevent O_DIRECT being used", test_reopen_without_direct);
+#undef T
+
+ return ts;
+}
+
+
+static struct test_suite *_partial_tests(void)
+{
+ struct test_suite *ts = test_suite_create(_no_o_direct_fixture_init,
+ _no_o_direct_fixture_exit);
+ if (!ts) {
+ fprintf(stderr, "out of memory\n");
+ exit(1);
+ }
+
+#define T(path, desc, fn) register_test(ts, "/base/device/io-manager/core/partial-write/" path, desc, fn)
T("single-start", "Writes a single sector at the start of a block", test_partial_write_at_start);
T("single-end", "Writes a single sector at the end of a block", test_partial_write_at_end);
T("multi-start", "Writes multiple sectors at the start of a block", test_partial_write_multiple_sectors_start);
@@ -2069,5 +2123,6 @@ void io_manager_tests(struct dm_list *all_tests)
{
dm_list_add(all_tests, &_tiny_tests()->list);
dm_list_add(all_tests, &_small_tests()->list);
+ dm_list_add(all_tests, &_partial_tests()->list);
dm_list_add(all_tests, &_large_tests()->list);
}
4 years, 7 months