reflink: test that CoW writes fail when we're out of space

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>
This commit is contained in:
Darrick J. Wong
2015-11-17 08:40:08 +11:00
committed by Dave Chinner
parent 5fb5ee48b3
commit db4284f312
9 changed files with 472 additions and 0 deletions
+107
View File
@@ -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
+10
View File
@@ -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
+107
View File
@@ -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
+10
View File
@@ -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
+109
View File
@@ -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
+8
View File
@@ -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
+107
View File
@@ -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
+10
View File
@@ -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
+4
View File
@@ -173,6 +173,10 @@
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