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
|