reflink: test that CoW writes fail when we're out of space
authorDarrick J. Wong <darrick.wong@oracle.com>
Mon, 16 Nov 2015 21:40:08 +0000 (08:40 +1100)
committerDave Chinner <david@fromorbit.com>
Mon, 16 Nov 2015 21:40:08 +0000 (08:40 +1100)
Ensure that copy-on-writing a reflinked file when there's no free disk
space reflects the desired ENOSPC back to userspace during the write
call.  Tests the buffered IO, direct IO, and mmap write paths.

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>
tests/generic/171 [new file with mode: 0755]
tests/generic/171.out [new file with mode: 0644]
tests/generic/172 [new file with mode: 0755]
tests/generic/172.out [new file with mode: 0644]
tests/generic/173 [new file with mode: 0755]
tests/generic/173.out [new file with mode: 0644]
tests/generic/174 [new file with mode: 0755]
tests/generic/174.out [new file with mode: 0644]
tests/generic/group

diff --git a/tests/generic/171 b/tests/generic/171
new file mode 100755 (executable)
index 0000000..99e4d5e
--- /dev/null
@@ -0,0 +1,107 @@
+#! /bin/bash
+# FS QA Test No. 171
+#
+# Reflink a file, use up the rest of the space, then try to observe ENOSPC
+# while copy-on-writing the file via the page cache.
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2015, Oracle and/or its affiliates.  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.
+#
+# This program is distributed in the hope that it would 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 the Free Software Foundation,
+# Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#-----------------------------------------------------------------------
+
+seq=`basename "$0"`
+seqres="$RESULT_DIR/$seq"
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1    # failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+_cleanup()
+{
+    cd /
+    rm -rf "$tmp".* "$TESTDIR1"
+}
+
+# get standard environment, filters and checks
+. ./common/rc
+. ./common/filter
+. ./common/attr
+. ./common/reflink
+
+# real QA test starts here
+_supported_os Linux
+_require_scratch_reflink
+_require_cp_reflink
+
+rm -f "$seqres.full"
+
+echo "Format and mount"
+_scratch_mkfs > "$seqres.full" 2>&1
+_scratch_mount >> "$seqres.full" 2>&1
+
+TESTDIR="$SCRATCH_MNT/test-$seq"
+rm -rf "$TESTDIR"
+mkdir "$TESTDIR"
+
+echo "Reformat with appropriate size"
+BLKSZ="$(stat -f "$TESTDIR" -c '%S')"
+NR_BLKS=10240
+umount "$SCRATCH_MNT"
+SZ_BYTES=$((NR_BLKS * 8 * BLKSZ))
+if [ $SZ_BYTES -lt $((32 * 1048576)) ]; then
+       SZ_BYTES=$((32 * 1048576))
+fi
+_scratch_mkfs_sized $SZ_BYTES >> "$seqres.full" 2>&1
+_scratch_mount >> "$seqres.full" 2>&1
+rm -rf "$TESTDIR"
+mkdir "$TESTDIR"
+
+echo "Create a big file and reflink it"
+_pwrite_byte 0x61 0 $((BLKSZ * NR_BLKS)) "$TESTDIR/bigfile" >> "$seqres.full" 2>&1
+_cp_reflink "$TESTDIR/bigfile" "$TESTDIR/clonefile"
+sync
+
+echo "Allocate the rest of the space"
+NR_FREE="$(stat -f -c '%f' "$TESTDIR")"
+touch "$TESTDIR/file0" "$TESTDIR/file1"
+_pwrite_byte 0x61 0 $((BLKSZ * NR_FREE)) "$TESTDIR/eat_my_space" >> "$seqres.full" 2>&1
+sync
+
+echo "CoW the big file"
+out="$(_pwrite_byte 0x62 0 $((BLKSZ * NR_BLKS)) "$TESTDIR/bigfile" 2>&1)"
+echo "${out}" | grep -q "No space left on device" || echo "CoW should have failed with ENOSPC"
+echo "${out}" >> "$seqres.full" 2>&1
+echo "${out}"
+
+echo "Remount and try CoW again"
+_scratch_remount
+
+out="$(_pwrite_byte 0x62 0 $((BLKSZ * NR_BLKS)) "$TESTDIR/bigfile" 2>&1)"
+echo "${out}" | grep -q "No space left on device" || echo "CoW should have failed with ENOSPC"
+echo "${out}" >> "$seqres.full" 2>&1
+echo "${out}"
+
+#filefrag -v $TESTDIR/bigfile
+#filefrag -v $TESTDIR/clonefile
+
+echo "Check scratch fs"
+umount "$SCRATCH_MNT"
+_check_scratch_fs
+
+# success, all done
+status=0
+exit
diff --git a/tests/generic/171.out b/tests/generic/171.out
new file mode 100644 (file)
index 0000000..c2b0ddd
--- /dev/null
@@ -0,0 +1,10 @@
+QA output created by 171
+Format and mount
+Reformat with appropriate size
+Create a big file and reflink it
+Allocate the rest of the space
+CoW the big file
+pwrite64: No space left on device
+Remount and try CoW again
+pwrite64: No space left on device
+Check scratch fs
diff --git a/tests/generic/172 b/tests/generic/172
new file mode 100755 (executable)
index 0000000..eb00f0a
--- /dev/null
@@ -0,0 +1,107 @@
+#! /bin/bash
+# FS QA Test No. 172
+#
+# Reflink a file that uses more than half of the space, then try to observe
+# ENOSPC while copy-on-writing the file via the page cache.
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2015, Oracle and/or its affiliates.  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.
+#
+# This program is distributed in the hope that it would 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 the Free Software Foundation,
+# Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#-----------------------------------------------------------------------
+
+seq=`basename "$0"`
+seqres="$RESULT_DIR/$seq"
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1    # failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+_cleanup()
+{
+    cd /
+    rm -rf "$tmp".* "$TESTDIR1"
+}
+
+# get standard environment, filters and checks
+. ./common/rc
+. ./common/filter
+. ./common/attr
+. ./common/reflink
+
+# real QA test starts here
+_supported_os Linux
+_require_scratch_reflink
+_require_cp_reflink
+
+rm -f "$seqres.full"
+
+echo "Format and mount"
+_scratch_mkfs > "$seqres.full" 2>&1
+_scratch_mount >> "$seqres.full" 2>&1
+
+TESTDIR="$SCRATCH_MNT/test-$seq"
+rm -rf "$TESTDIR"
+mkdir "$TESTDIR"
+
+echo "Reformat with appropriate size"
+BLKSZ="$(stat -f "$TESTDIR" -c '%S')"
+NR_BLKS=10240
+umount "$SCRATCH_MNT"
+SZ_BYTES=$((NR_BLKS * 3 / 2 * BLKSZ))
+if [ $SZ_BYTES -lt $((32 * 1048576)) ]; then
+       SZ_BYTES=$((32 * 1048576))
+fi
+_scratch_mkfs_sized $SZ_BYTES >> "$seqres.full" 2>&1
+_scratch_mount >> "$seqres.full" 2>&1
+rm -rf "$TESTDIR"
+mkdir "$TESTDIR"
+
+echo "Create a big file and reflink it"
+_pwrite_byte 0x61 0 $((BLKSZ * NR_BLKS)) "$TESTDIR/bigfile" >> "$seqres.full" 2>&1
+_cp_reflink "$TESTDIR/bigfile" "$TESTDIR/clonefile"
+sync
+
+echo "Allocate the rest of the space"
+NR_FREE="$(stat -f -c '%f' "$TESTDIR")"
+touch "$TESTDIR/file0" "$TESTDIR/file1"
+_pwrite_byte 0x61 0 $((BLKSZ * NR_FREE)) "$TESTDIR/eat_my_space" >> "$seqres.full" 2>&1
+sync
+
+echo "CoW the big file"
+out="$(_pwrite_byte 0x62 0 $((BLKSZ * NR_BLKS)) "$TESTDIR/bigfile" 2>&1)"
+echo "${out}" | grep -q "No space left on device" || echo "CoW should have failed with ENOSPC"
+echo "${out}" >> "$seqres.full" 2>&1
+echo "${out}"
+
+echo "Remount and try CoW again"
+_scratch_remount
+
+out="$(_pwrite_byte 0x62 0 $((BLKSZ * NR_BLKS)) "$TESTDIR/bigfile" 2>&1)"
+echo "${out}" | grep -q "No space left on device" || echo "CoW should have failed with ENOSPC"
+echo "${out}" >> "$seqres.full" 2>&1
+echo "${out}"
+
+#filefrag -v $TESTDIR/bigfile
+#filefrag -v $TESTDIR/clonefile
+
+echo "Check scratch fs"
+umount "$SCRATCH_MNT"
+_check_scratch_fs
+
+# success, all done
+status=0
+exit
diff --git a/tests/generic/172.out b/tests/generic/172.out
new file mode 100644 (file)
index 0000000..3913dd7
--- /dev/null
@@ -0,0 +1,10 @@
+QA output created by 172
+Format and mount
+Reformat with appropriate size
+Create a big file and reflink it
+Allocate the rest of the space
+CoW the big file
+pwrite64: No space left on device
+Remount and try CoW again
+pwrite64: No space left on device
+Check scratch fs
diff --git a/tests/generic/173 b/tests/generic/173
new file mode 100755 (executable)
index 0000000..76463d2
--- /dev/null
@@ -0,0 +1,109 @@
+#! /bin/bash
+# FS QA Test No. 173
+#
+# Reflink a file, use up the rest of the space, then try to observe ENOSPC
+# while copy-on-writing the file via mmap.
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2015, Oracle and/or its affiliates.  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.
+#
+# This program is distributed in the hope that it would 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 the Free Software Foundation,
+# Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#-----------------------------------------------------------------------
+
+seq=`basename "$0"`
+seqres="$RESULT_DIR/$seq"
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1    # failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+_cleanup()
+{
+    cd /
+    rm -rf "$tmp".* "$TESTDIR1"
+}
+
+# get standard environment, filters and checks
+. ./common/rc
+. ./common/filter
+. ./common/attr
+. ./common/reflink
+
+# real QA test starts here
+_supported_os Linux
+_require_scratch_reflink
+_require_cp_reflink
+
+rm -f "$seqres.full"
+
+echo "Format and mount"
+_scratch_mkfs > "$seqres.full" 2>&1
+_scratch_mount >> "$seqres.full" 2>&1
+
+TESTDIR="$SCRATCH_MNT/test-$seq"
+rm -rf "$TESTDIR"
+mkdir "$TESTDIR"
+
+echo "Reformat with appropriate size"
+BLKSZ="$(stat -f "$TESTDIR" -c '%S')"
+NR_BLKS=10240
+umount "$SCRATCH_MNT"
+SZ_BYTES=$((NR_BLKS * 8 * BLKSZ))
+if [ $SZ_BYTES -lt $((32 * 1048576)) ]; then
+       SZ_BYTES=$((32 * 1048576))
+fi
+_scratch_mkfs_sized $SZ_BYTES >> "$seqres.full" 2>&1
+_scratch_mount >> "$seqres.full" 2>&1
+rm -rf "$TESTDIR"
+mkdir "$TESTDIR"
+
+echo "Create a big file and reflink it"
+_pwrite_byte 0x61 0 $((BLKSZ * NR_BLKS)) "$TESTDIR/bigfile" >> "$seqres.full" 2>&1
+_cp_reflink "$TESTDIR/bigfile" "$TESTDIR/clonefile"
+sync
+
+echo "Allocate the rest of the space"
+NR_FREE="$(stat -f -c '%f' "$TESTDIR")"
+touch "$TESTDIR/file0" "$TESTDIR/file1"
+_pwrite_byte 0x61 0 $((BLKSZ * NR_FREE)) "$TESTDIR/eat_my_space" >> "$seqres.full" 2>&1
+sync
+
+echo "mmap CoW the big file"
+out="$(_mwrite_byte 0x62 0 $((BLKSZ * NR_BLKS)) $((BLKSZ * NR_BLKS)) "$TESTDIR/bigfile" 2>&1)"
+err="$?"
+if [ "$err" -lt 128 ]; then
+       echo "mmap CoW should have failed with SIGBUS, got SIG$(kill -l $err)"
+fi
+
+echo "Remount and try CoW again"
+_scratch_remount
+
+out="$(_mwrite_byte 0x62 0 $((BLKSZ * NR_BLKS)) $((BLKSZ * NR_BLKS)) "$TESTDIR/bigfile" 2>&1)"
+err="$?"
+if [ "$err" -lt 128 ]; then
+       echo "mmap CoW should have failed with SIGBUS, got SIG$(kill -l $err)"
+fi
+
+#filefrag -v $TESTDIR/bigfile
+#filefrag -v $TESTDIR/clonefile
+
+echo "Check scratch fs"
+umount "$SCRATCH_MNT"
+_check_scratch_fs
+
+# success, all done
+status=0
+exit
diff --git a/tests/generic/173.out b/tests/generic/173.out
new file mode 100644 (file)
index 0000000..49abb17
--- /dev/null
@@ -0,0 +1,8 @@
+QA output created by 173
+Format and mount
+Reformat with appropriate size
+Create a big file and reflink it
+Allocate the rest of the space
+mmap CoW the big file
+Remount and try CoW again
+Check scratch fs
diff --git a/tests/generic/174 b/tests/generic/174
new file mode 100755 (executable)
index 0000000..8df292a
--- /dev/null
@@ -0,0 +1,107 @@
+#! /bin/bash
+# FS QA Test No. 174
+#
+# Reflink a file, use up the rest of the space, then try to observe ENOSPC
+# while copy-on-writing the file via direct-io.
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2015, Oracle and/or its affiliates.  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.
+#
+# This program is distributed in the hope that it would 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 the Free Software Foundation,
+# Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#-----------------------------------------------------------------------
+
+seq=`basename "$0"`
+seqres="$RESULT_DIR/$seq"
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1    # failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+_cleanup()
+{
+    cd /
+    rm -rf "$tmp".* "$TESTDIR1"
+}
+
+# get standard environment, filters and checks
+. ./common/rc
+. ./common/filter
+. ./common/attr
+. ./common/reflink
+
+# real QA test starts here
+_supported_os Linux
+_require_scratch_reflink
+_require_cp_reflink
+
+rm -f "$seqres.full"
+
+echo "Format and mount"
+_scratch_mkfs > "$seqres.full" 2>&1
+_scratch_mount >> "$seqres.full" 2>&1
+
+TESTDIR="$SCRATCH_MNT/test-$seq"
+rm -rf "$TESTDIR"
+mkdir "$TESTDIR"
+
+echo "Reformat with appropriate size"
+BLKSZ="$(stat -f "$TESTDIR" -c '%S')"
+NR_BLKS=10240
+umount "$SCRATCH_MNT"
+SZ_BYTES=$((NR_BLKS * 8 * BLKSZ))
+if [ $SZ_BYTES -lt $((32 * 1048576)) ]; then
+       SZ_BYTES=$((32 * 1048576))
+fi
+_scratch_mkfs_sized $SZ_BYTES >> "$seqres.full" 2>&1
+_scratch_mount >> "$seqres.full" 2>&1
+rm -rf "$TESTDIR"
+mkdir "$TESTDIR"
+
+echo "Create a big file and reflink it"
+_pwrite_byte 0x61 0 $((BLKSZ * NR_BLKS)) "$TESTDIR/bigfile" >> "$seqres.full" 2>&1
+_cp_reflink "$TESTDIR/bigfile" "$TESTDIR/clonefile"
+sync
+
+echo "Allocate the rest of the space"
+NR_FREE="$(stat -f -c '%f' "$TESTDIR")"
+touch "$TESTDIR/file0" "$TESTDIR/file1"
+_pwrite_byte 0x61 0 $((BLKSZ * NR_FREE)) "$TESTDIR/eat_my_space" >> "$seqres.full" 2>&1
+sync
+
+echo "CoW the big file"
+out="$(_pwrite_byte 0x62 0 $((BLKSZ * NR_BLKS)) "$TESTDIR/bigfile" -d 2>&1)"
+echo "${out}" | grep -q "No space left on device" || echo "CoW should have failed with ENOSPC"
+echo "${out}" >> "$seqres.full" 2>&1
+echo "${out}"
+
+echo "Remount and try CoW again"
+_scratch_remount
+
+out="$(_pwrite_byte 0x62 0 $((BLKSZ * NR_BLKS)) "$TESTDIR/bigfile" -d 2>&1)"
+echo "${out}" | grep -q "No space left on device" || echo "CoW should have failed with ENOSPC"
+echo "${out}" >> "$seqres.full" 2>&1
+echo "${out}"
+
+#filefrag -v $TESTDIR/bigfile
+#filefrag -v $TESTDIR/clonefile
+
+echo "Check scratch fs"
+umount "$SCRATCH_MNT"
+_check_scratch_fs
+
+# success, all done
+status=0
+exit
diff --git a/tests/generic/174.out b/tests/generic/174.out
new file mode 100644 (file)
index 0000000..702d067
--- /dev/null
@@ -0,0 +1,10 @@
+QA output created by 174
+Format and mount
+Reformat with appropriate size
+Create a big file and reflink it
+Allocate the rest of the space
+CoW the big file
+pwrite64: No space left on device
+Remount and try CoW again
+pwrite64: No space left on device
+Check scratch fs
index 6ae3105310f90b8566405eb14c6bc4328125d8fd..09a782898e973c575691fe94d5931e3c7beaba49 100644 (file)
 168 auto quick clone
 169 rw metadata auto quick
 170 auto quick clone
+171 auto quick clone
+172 auto quick clone
+173 auto quick clone
+174 auto quick clone
 184 metadata auto quick
 192 atime auto
 193 metadata auto quick