summaryrefslogtreecommitdiff
path: root/tests/generic/564
blob: 7ed5ccc1b19ac26fb26453dc2ea0798e2628675a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#! /bin/bash
# SPDX-License-Identifier: GPL-2.0
# Copyright (c) 2018 Red Hat, Inc.  All Rights Reserved.
#
# FS QA Test No. 564
#
# Exercise copy_file_range() syscall error conditions.
#
# This is a regression test for kernel commit:
#   96e6e8f4a68d ("vfs: add missing checks to copy_file_range")
#
. ./common/preamble
_begin_fstest auto quick copy_range

_register_cleanup "_cleanup" BUS

# Override the default cleanup function.
_cleanup()
{
	cd /
	rm -rf $tmp.*
	[ -z "$loopdev" ] || _destroy_loop_device $loopdev
}

# Import common functions.
. ./common/filter

# real QA test starts here
_supported_fs generic

_require_test
_require_loop
# for mkfifo
_require_mknod

#
# This test effectively requires xfs_io with these commits
#  2a42470b xfs_io: copy_file_range length is a size_t
#  1a05efba io: open pipes in non-blocking mode
#
# Without those commits test will hang on old kernel when copying
# very large size and when copying from a pipe.
#
# We require a new xfs_io feature of passing an open file as the
# copy source, as an indication that the test can run without hanging
# with large size argument and to avoid opening pipe in blocking mode.
#
# Test both basic copy_range and copy_range -f availability
_require_xfs_io_command "copy_range"
_require_xfs_io_command "copy_range" "-f"

testdir="$TEST_DIR/test-$seq"
rm -rf $testdir
mkdir $testdir

$XFS_IO_PROG -f -c "pwrite -S 0x61 0 128k" $testdir/file >> $seqres.full 2>&1

echo source range overlaps destination range in same file returns EINVAL
$XFS_IO_PROG -f -c "copy_range -s 32k -d 48k -l 32k $testdir/file" $testdir/file

echo
echo destination file O_RDONLY returns EBADF
$XFS_IO_PROG -f -r -c "copy_range -l 32k $testdir/file" $testdir/copy

echo
echo destination file O_APPEND returns EBADF
$XFS_IO_PROG -f -a -c "copy_range -l 32k $testdir/file" $testdir/copy

echo
echo source/destination as directory returns EISDIR
$XFS_IO_PROG -c "copy_range -l 32k $testdir/file" $testdir
$XFS_IO_PROG -f -c "copy_range -l 32k $testdir" $testdir/copy

echo
echo source/destination as blkdev returns EINVAL
$XFS_IO_PROG -f -c "truncate 128k" $testdir/img >> $seqres.full 2>&1
loopdev=`_create_loop_device $testdir/img`
$XFS_IO_PROG -c "copy_range -l 32k $testdir/file" $loopdev
$XFS_IO_PROG -f -c "copy_range -l 32k $loopdev" $testdir/copy
_destroy_loop_device $loopdev
loopdev=

echo
echo source/destination as chardev returns EINVAL
$XFS_IO_PROG -c "copy_range -l 32k $testdir/file" /dev/null
$XFS_IO_PROG -f -c "copy_range -l 32k /dev/zero" $testdir/copy

echo
echo source/destination as FIFO returns EINVAL
mkfifo $testdir/fifo
$XFS_IO_PROG -c "copy_range -l 32k $testdir/file" $testdir/fifo
# Pass input pipe as non-blocking open file to avoid old xfs_io (<4.20)
# opening the pipe in blocking mode and causing the test to hang
$XFS_IO_PROG -r -n -f -c "open $testdir/copy" -C "copy_range -l 32k -f 0" $testdir/fifo

max_off=$((8 * 2**60 - 65536 - 1))
min_off=65537

echo
echo length beyond 8EiB wraps around 0 returns EOVERFLOW
$XFS_IO_PROG -f -c "copy_range -l 10e -s $max_off $testdir/file" $testdir/copy
$XFS_IO_PROG -f -c "copy_range -l 10e -d $max_off $testdir/file" $testdir/copy

echo
echo source range beyond 8TiB returns 0
$XFS_IO_PROG -c "copy_range -s $max_off -l $min_off -d 0 $testdir/file" $testdir/copy

echo
echo destination range beyond 8TiB returns EFBIG
$XFS_IO_PROG -c "copy_range -l $min_off -s 0 -d $max_off $testdir/file" $testdir/copy

echo
echo destination larger than rlimit returns EFBIG
rm -f $testdir/copy
$XFS_IO_PROG -c "truncate 128k" $testdir/file

# need a wrapper so the "File size limit exceeded" error can be filtered
do_rlimit_copy()
{
	$XFS_IO_PROG -f -c "copy_range -l 32k -s 0 -d 16m $testdir/file" $testdir/copy
}

ulimit -f $((8 * 1024))
ulimit -c 0
do_rlimit_copy 2>&1 | grep -o "File size limit exceeded"
ulimit -f unlimited

# success, all done
status=0
exit