reflink: add test support routines to a separate file
authorDarrick J. Wong <darrick.wong@oracle.com>
Mon, 16 Nov 2015 21:39:17 +0000 (08:39 +1100)
committerDave Chinner <david@fromorbit.com>
Mon, 16 Nov 2015 21:39:17 +0000 (08:39 +1100)
Put all the reflink/dedupe-related test support routines in a separate
file, then modify the existing reflink tests to use them.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Acked-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Dave Chinner <david@fromorbit.com>
common/rc
common/reflink [new file with mode: 0644]
tests/btrfs/029
tests/btrfs/031
tests/btrfs/108
tests/btrfs/109
tests/generic/110
tests/generic/111
tests/generic/115

index adf1edf64d8d396f4e9a3b97be25e226178944ca..4c2f42c8d0eb5c80fec8332bfc3c774fb0a24457 100644 (file)
--- a/common/rc
+++ b/common/rc
@@ -82,6 +82,27 @@ _md5_checksum()
        md5sum $1 | cut -d ' ' -f1
 }
 
        md5sum $1 | cut -d ' ' -f1
 }
 
+# Write a byte into a range of a file
+_pwrite_byte() {
+       pattern="$1"
+       offset="$2"
+       len="$3"
+       file="$4"
+       xfs_io_args="$5"
+
+       "$XFS_IO_PROG" $xfs_io_args -f -c "pwrite -S $pattern $offset $len" "$file"
+}
+
+# mmap-write a byte into a range of a file
+_mwrite_byte() {
+       pattern="$1"
+       offset="$2"
+       len="$3"
+       mmap_len="$4"
+       file="$5"
+
+       "$XFS_IO_PROG" -f -c "mmap -rw 0 $mmap_len" -c "mwrite -S $pattern $offset $len" "$file"
+}
 
 # ls -l w/ selinux sometimes puts a dot at the end:
 # -rwxrw-r--. id1 id2 file1
 
 # ls -l w/ selinux sometimes puts a dot at the end:
 # -rwxrw-r--. id1 id2 file1
@@ -2569,12 +2590,6 @@ _require_ugid_map()
        fi
 }
 
        fi
 }
 
-_require_cp_reflink()
-{
-       cp --help | grep -q reflink || \
-               _notrun "This test requires a cp with --reflink support."
-}
-
 _require_fssum()
 {
        FSSUM_PROG=$here/src/fssum
 _require_fssum()
 {
        FSSUM_PROG=$here/src/fssum
@@ -2588,21 +2603,6 @@ _require_cloner()
                _notrun "cloner binary not present at $CLONER_PROG"
 }
 
                _notrun "cloner binary not present at $CLONER_PROG"
 }
 
-# Given 2 files, verify that they have the same mapping but different
-# inodes - i.e. an undisturbed reflink
-# Silent if so, make noise if not
-_verify_reflink()
-{
-       # not a hard link or symlink?
-       cmp -s  <(stat -c '%i' $1) <(stat -c '%i' $2) \
-               && echo "$1 and $2 are not reflinks: same inode number"
-
-       # same mapping?
-       diff -u <($XFS_IO_PROG -c "fiemap" $1 | grep -v $1) \
-               <($XFS_IO_PROG -c "fiemap" $2 | grep -v $2) \
-               || echo "$1 and $2 are not reflinks: different extents"
-}
-
 _require_atime()
 {
        if [ "$FSTYP" == "nfs" ]; then
 _require_atime()
 {
        if [ "$FSTYP" == "nfs" ]; then
@@ -2764,6 +2764,15 @@ _require_btrfs_dev_del_by_devid()
                        "(must support 'btrfs device delete <devid> /<mnt>')"
 }
 
                        "(must support 'btrfs device delete <devid> /<mnt>')"
 }
 
+_require_test_lsattr()
+{
+       testio=$(lsattr -d $TEST_DIR 2>&1)
+       echo $testio | grep -q "Operation not supported" && \
+               _notrun "lsattr not supported by test filesystem type: $FSTYP"
+       echo $testio | grep -q "Inappropriate ioctl for device" && \
+               _notrun "lsattr not supported by test filesystem type: $FSTYP"
+}
+
 _get_total_inode()
 {
        if [ -z "$1" ]; then
 _get_total_inode()
 {
        if [ -z "$1" ]; then
diff --git a/common/reflink b/common/reflink
new file mode 100644 (file)
index 0000000..eab7f66
--- /dev/null
@@ -0,0 +1,185 @@
+##/bin/bash
+# Routines for reflinking, deduping, and comparing parts of files.
+#-----------------------------------------------------------------------
+#  Copyright (c) 2015 Oracle.  All Rights Reserved.
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; either version 2 of the License, or
+#  (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+#  USA
+#
+#  Contact information: Oracle Corporation, 500 Oracle Parkway,
+#  Redwood Shores, CA 94065, USA, or: http://www.oracle.com/
+#-----------------------------------------------------------------------
+
+# Check that cp has a reflink argument
+_require_cp_reflink()
+{
+       cp --help | grep -q reflink || \
+               _notrun "This test requires a cp with --reflink support."
+}
+
+# Given 2 files, verify that they have the same mapping but different
+# inodes - i.e. an undisturbed reflink
+# Silent if so, make noise if not
+_verify_reflink()
+{
+       # not a hard link or symlink?
+       cmp -s  <(stat -c '%i' $1) <(stat -c '%i' $2) \
+               && echo "$1 and $2 are not reflinks: same inode number"
+
+       # same mapping?
+       diff -u <($XFS_IO_PROG -c "fiemap" $1 | grep -v $1) \
+               <($XFS_IO_PROG -c "fiemap" $2 | grep -v $2) \
+               || echo "$1 and $2 are not reflinks: different extents"
+}
+
+# New reflink/dedupe helpers
+
+# this test requires the test fs support reflink...
+_require_test_reflink()
+{
+       _require_test
+       _require_xfs_io_command "reflink"
+
+       rm -rf "$TEST_DIR/file1" "$TEST_DIR/file2"
+       "$XFS_IO_PROG" -f -c "pwrite -S 0x61 0 65536" "$TEST_DIR/file1" > /dev/null
+       "$XFS_IO_PROG" -f -c "reflink $TEST_DIR/file1 0 0 65536" "$TEST_DIR/file2" > /dev/null
+       if [ ! -s "$TEST_DIR/file2" ]; then
+               rm -rf "$TEST_DIR/file1" "$TEST_DIR/file2"
+               _notrun "Reflink not supported by test filesystem type: $FSTYP"
+       fi
+       rm -rf "$TEST_DIR/file1" "$TEST_DIR/file2"
+}
+
+# this test requires the scratch fs support reflink...
+_require_scratch_reflink()
+{
+       _require_scratch
+       _require_xfs_io_command "reflink"
+
+       _scratch_mkfs > /dev/null
+       _scratch_mount
+       "$XFS_IO_PROG" -f -c "pwrite -S 0x61 0 65536" "$SCRATCH_MNT/file1" > /dev/null
+       "$XFS_IO_PROG" -f -c "reflink $SCRATCH_MNT/file1 0 0 65536" "$SCRATCH_MNT/file2" > /dev/null
+       if [ ! -s "$SCRATCH_MNT/file2" ]; then
+               _scratch_unmount
+               _notrun "Reflink not supported by scratch filesystem type: $FSTYP"
+       fi
+       _scratch_unmount
+}
+
+# this test requires the test fs support dedupe...
+_require_test_dedupe()
+{
+       _require_test
+       _require_xfs_io_command "dedupe"
+
+       rm -rf "$TEST_DIR/file1" "$TEST_DIR/file2"
+       "$XFS_IO_PROG" -f -c "pwrite -S 0x61 0 65536" "$TEST_DIR/file1" > /dev/null
+       "$XFS_IO_PROG" -f -c "pwrite -S 0x61 0 65536" "$TEST_DIR/file2" > /dev/null
+       testio="$("$XFS_IO_PROG" -f -c "dedupe $TEST_DIR/file1 0 0 65536" "$TEST_DIR/file2" 2>&1)"
+       echo $testio | grep -q "Operation not supported" && \
+               _notrun "Dedupe not supported by test filesystem type: $FSTYP"
+       echo $testio | grep -q "Inappropriate ioctl for device" && \
+               _notrun "Dedupe not supported by test filesystem type: $FSTYP"
+       rm -rf "$TEST_DIR/file1" "$TEST_DIR/file2"
+}
+
+# this test requires the scratch fs support dedupe...
+_require_scratch_dedupe()
+{
+       _require_scratch
+       _require_xfs_io_command "dedupe"
+
+       _scratch_mkfs > /dev/null
+       _scratch_mount
+       "$XFS_IO_PROG" -f -c "pwrite -S 0x61 0 65536" "$SCRATCH_MNT/file1" > /dev/null
+       "$XFS_IO_PROG" -f -c "pwrite -S 0x61 0 65536" "$SCRATCH_MNT/file2" > /dev/null
+       testio="$("$XFS_IO_PROG" -f -c "dedupe $TEST_DIR/file1 0 0 65536" "$TEST_DIR/file2" 2>&1)"
+       echo $testio | grep -q "Operation not supported" && \
+               _notrun "Dedupe not supported by test filesystem type: $FSTYP"
+       echo $testio | grep -q "Inappropriate ioctl for device" && \
+               _notrun "Dedupe not supported by test filesystem type: $FSTYP"
+       _scratch_unmount
+}
+
+# Prints a range of a file as a hex dump
+_read_range() {
+       file="$1"
+       offset="$2"
+       len="$3"
+       xfs_io_args="$4"
+
+       $XFS_IO_PROG $xfs_io_args -f -c "pread -q -v $offset $len" "$file" | cut -d ' ' -f '3-18'
+}
+
+# Compare ranges of two files
+_compare_range() {
+       file1="$1"
+       offset1="$2"
+       file2="$3"
+       offset2="$4"
+       len="$5"
+
+       cmp -s <(_read_range "$file1" "$offset1" "$len") \
+              <(_read_range "$file2" "$offset2" "$len")
+}
+
+# Prints the md5 checksum of a hexdump of a part of a given file
+_md5_range_checksum() {
+       file="$1"
+       offset="$2"
+       len="$3"
+
+       md5sum <(_read_range "$file" "$offset" "$len") | cut -d ' ' -f 1
+}
+
+# Reflink some file1 into file2 via cp
+_cp_reflink() {
+       file1="$1"
+       file2="$2"
+
+       cp --reflink=always "$file1" "$file2"
+}
+
+# Reflink some file1 into file2
+_reflink() {
+       file1="$1"
+       file2="$2"
+
+       "$XFS_IO_PROG" -f -c "reflink $file1" "$file2"
+}
+
+# Reflink some part of file1 into another part of file2
+_reflink_range() {
+       file1="$1"
+       offset1="$2"
+       file2="$3"
+       offset2="$4"
+       len="$5"
+       xfs_io_args="$6"
+
+       "$XFS_IO_PROG" $xfs_io_args -f -c "reflink $file1 $offset1 $offset2 $len" "$file2"
+}
+
+# Dedupe some part of file1 into another part of file2
+_dedupe_range() {
+       file1="$1"
+       offset1="$2"
+       file2="$3"
+       offset2="$4"
+       len="$5"
+       xfs_io_args="$6"
+
+       "$XFS_IO_PROG" $xfs_io_args -f -c "dedupe $file1 $offset1 $offset2 $len" "$file2"
+}
index 0b77b33622fac3fb37bf78b9893ec42c8a131405..175317a8a5f7e4f697b36323f56a0b8279543a36 100755 (executable)
@@ -47,6 +47,7 @@ _cleanup()
 # get standard environment, filters and checks
 . ./common/rc
 . ./common/filter
 # get standard environment, filters and checks
 . ./common/rc
 . ./common/filter
+. ./common/reflink
 
 # real QA test starts here
 _supported_fs btrfs
 
 # real QA test starts here
 _supported_fs btrfs
index bcd332c385e0ac596266ec724a88f4dce650c716..c5763dab74d340d58c5afe40a62ef7d528593d2a 100755 (executable)
@@ -48,6 +48,7 @@ _cleanup()
 # get standard environment, filters and checks
 . ./common/rc
 . ./common/filter
 # get standard environment, filters and checks
 . ./common/rc
 . ./common/filter
+. ./common/reflink
 
 # real QA test starts here
 _supported_fs btrfs
 
 # real QA test starts here
 _supported_fs btrfs
index 5e3a40384c60bd73b8e332d787b10141757af59f..18e5b99d89d62f59e11a456eaef27c44f033ab57 100755 (executable)
@@ -41,6 +41,7 @@ _cleanup()
 # get standard environment, filters and checks
 . ./common/rc
 . ./common/filter
 # get standard environment, filters and checks
 . ./common/rc
 . ./common/filter
+. ./common/reflink
 
 # real QA test starts here
 _supported_fs btrfs
 
 # real QA test starts here
 _supported_fs btrfs
index e2aeb73de0b0c12d6dbdbfbd70e7a0a173fb854c..b86336c9afb3a646e41bd7b4824d60d4f1e5a998 100755 (executable)
@@ -41,6 +41,7 @@ _cleanup()
 # get standard environment, filters and checks
 . ./common/rc
 . ./common/filter
 # get standard environment, filters and checks
 . ./common/rc
 . ./common/filter
+. ./common/reflink
 
 # real QA test starts here
 _supported_fs btrfs
 
 # real QA test starts here
 _supported_fs btrfs
index ec743577783ee998ed04640c161df06b9ad2813f..468d859769d04cd6fcbd134ed477a58b14463fc8 100755 (executable)
@@ -43,9 +43,10 @@ _cleanup()
 # get standard environment, filters and checks
 . common/rc
 . common/filter
 # get standard environment, filters and checks
 . common/rc
 . common/filter
+. common/reflink
 
 # real QA test starts here
 
 # real QA test starts here
-_supported_fs btrfs
+_require_test_reflink
 _supported_os Linux
 
 _require_xfs_io_command "fiemap"
 _supported_os Linux
 
 _require_xfs_io_command "fiemap"
index 9da3f40363ca1938bccd4a5e2d3fbb1787566013..1797233f1a973fbde39a1e49780232f26dece3f3 100755 (executable)
@@ -43,9 +43,10 @@ _cleanup()
 # get standard environment, filters and checks
 . common/rc
 . common/filter
 # get standard environment, filters and checks
 . common/rc
 . common/filter
+. common/reflink
 
 # real QA test starts here
 
 # real QA test starts here
-_supported_fs btrfs
+_require_test_reflink
 _supported_os Linux
 
 _require_xfs_io_command "fiemap"
 _supported_os Linux
 
 _require_xfs_io_command "fiemap"
index 35f0417a357b8d92117c87409efad03d6c5be08c..b5c64ece992d9927b7a69b2374fd54d59ce7246e 100755 (executable)
@@ -41,9 +41,10 @@ _cleanup()
 # get standard environment, filters and checks
 . ./common/rc
 . ./common/filter
 # get standard environment, filters and checks
 . ./common/rc
 . ./common/filter
+. ./common/reflink
 
 # real QA test starts here
 
 # real QA test starts here
-_supported_fs btrfs
+_require_test_reflink
 _supported_os Linux
 
 _require_xfs_io_command "fiemap"
 _supported_os Linux
 
 _require_xfs_io_command "fiemap"