summaryrefslogtreecommitdiff
path: root/tests/xfs/420
blob: d38772c9d9b4a183faa73073d156bbe9605f807e (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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#! /bin/bash
# SPDX-License-Identifier: GPL-2.0
# Copyright (c) 2017, Oracle and/or its affiliates.  All Rights Reserved.
#
# FS QA Test No. 420
#
# Test SEEK_HOLE/SEEK_DATA into a region that is marked CoW'd for
# speculative preallocation in the CoW fork and isn't backed by
# data fork extents.
#
# - Set a huge cowextsize hint.
# - Create a file "DD      " (two data blocks, six hole blocks)
# - Reflink copy this file to a second file.
# - Write to the first block of the second file to create a single
#   large CoW reservation covering the whole file.
# - Write to block 3, which should be a hole in the data fork.
# - Display the SEEK_HOLE/SEEK_DATA info for the second file to confirm
#   that we see the data in blocks 0-1, the hole at block 2, the data
#   at block 3, and the hole for the rest of the file.
#
# Basically we want to create a file with the following data/CoW forks:
#
# data: DD------
#  cow: dddddddd
#       ^--^---------- these blocks are dirty
#
# And then check that SEEK_HOLE and SEEK_DATA actually find that second
# dirty block even though we've never had a data fork extent mapping the
# second dirty block.  We need the huge cowextsize so that the hole
# area receives preallocation in the CoW fork.
#
. ./common/preamble
_begin_fstest auto quick clone punch seek

# Import common functions.
. ./common/filter
. ./common/reflink

# real QA test starts here
_supported_fs xfs
_require_scratch_reflink
_require_cp_reflink
_require_xfs_io_command "cowextsize"
_require_xfs_io_command "fpunch"

echo "Format and mount"
_scratch_mkfs > $seqres.full 2>&1
_scratch_mount >> $seqres.full 2>&1

testdir=$SCRATCH_MNT/test-$seq
mkdir $testdir

# pagecache readahead can sometimes cause extra pages to be inserted into the
# file mapping where we have an unwritten extent in the COW fork.  Call lseek
# on each $blksz offset that interests us (as opposed to the whole file) so
# that these extra pages are not disclosed.
#
# The important thing we're testing is that SEEK_DATA reports block 3 as data
# when the COW fork has an unwritten mapping and the data fork has a hole.
exercise_lseek() {
	echo "Seek holes and data in file1"
	$XFS_IO_PROG -c "seek -d 0" $testdir/file1
	$XFS_IO_PROG -c "seek -h $((2 * blksz))" $testdir/file1 | sed -e '/Whence/d'
	echo "Seek holes and data in file2"
	$XFS_IO_PROG -c "seek -d 0" $testdir/file2
	$XFS_IO_PROG -c "seek -h $((2 * blksz))" $testdir/file2 | sed -e '/Whence/d'
	$XFS_IO_PROG -c "seek -d $((3 * blksz))" $testdir/file2 | sed -e '/Whence/d'
	$XFS_IO_PROG -c "seek -h $((4 * blksz))" $testdir/file2 | sed -e '/Whence/d'
}

blksz=65536
nr=8
filesize=$((blksz * nr))

echo "Create the original files"
$XFS_IO_PROG -c "cowextsize" $testdir >> $seqres.full
$XFS_IO_PROG -c "cowextsize $filesize" $testdir >> $seqres.full
$XFS_IO_PROG -c "cowextsize" $testdir >> $seqres.full
$XFS_IO_PROG -f -c "pwrite -S 0x61 0 $((blksz * 2))" -c "truncate $filesize" -c "fpunch $((blksz * 2)) $((blksz * (nr - 2) ))" $testdir/file1 >> $seqres.full
_cp_reflink $testdir/file1 $testdir/file2 >> $seqres.full
$XFS_IO_PROG -f -c "pwrite -S 0 0 $filesize" -c "pwrite -S 0x61 0 $((blksz * 2))" $testdir/file3 >> $seqres.full
_scratch_cycle_mount

echo "Compare files"
md5sum $testdir/file1 | _filter_scratch
md5sum $testdir/file2 | _filter_scratch
md5sum $testdir/file3 | _filter_scratch
# drop caches to make sure the page cache for the unwritten extents is clean
echo 1 > /proc/sys/vm/drop_caches

echo "CoW the shared part then write into the empty part" | tee -a $seqres.full
$XFS_IO_PROG -c "cowextsize" $testdir/file1 >> $seqres.full
$XFS_IO_PROG -c "cowextsize" $testdir/file2 >> $seqres.full
$XFS_IO_PROG -c "pwrite -S 0x63 0 $blksz" $testdir/file2 >> $seqres.full
$XFS_IO_PROG -c "pwrite -S 0x63 $((blksz * 3)) $blksz" $testdir/file2 >> $seqres.full

$XFS_IO_PROG -c "pwrite -S 0x63 0 $blksz" $testdir/file3 >> $seqres.full
$XFS_IO_PROG -c "pwrite -S 0x63 $((blksz * 3)) $blksz" $testdir/file3 >> $seqres.full

$XFS_IO_PROG -c "bmap -ev" -c "bmap -cv" $testdir/file1 >> $seqres.full 2>&1
$XFS_IO_PROG -c "bmap -ev" -c "bmap -cv" $testdir/file2 >> $seqres.full 2>&1
$XFS_IO_PROG -c "bmap -ev" -c "bmap -cv" $testdir/file3 >> $seqres.full 2>&1

exercise_lseek

echo "Compare files"
md5sum $testdir/file1 | _filter_scratch
md5sum $testdir/file2 | _filter_scratch
md5sum $testdir/file3 | _filter_scratch
# drop caches to make sure the page cache for the unwritten extents is clean
echo 1 > /proc/sys/vm/drop_caches

echo "sync filesystem" | tee -a $seqres.full
sync

$XFS_IO_PROG -c "bmap -ev" -c "bmap -cv" $testdir/file1 >> $seqres.full 2>&1
$XFS_IO_PROG -c "bmap -ev" -c "bmap -cv" $testdir/file2 >> $seqres.full 2>&1
$XFS_IO_PROG -c "bmap -ev" -c "bmap -cv" $testdir/file3 >> $seqres.full 2>&1

exercise_lseek

echo "Compare files"
md5sum $testdir/file1 | _filter_scratch
md5sum $testdir/file2 | _filter_scratch
md5sum $testdir/file3 | _filter_scratch
# drop caches to make sure the page cache for the unwritten extents is clean
echo 1 > /proc/sys/vm/drop_caches

echo "Remount" | tee -a $seqres.full
_scratch_cycle_mount

$XFS_IO_PROG -c "bmap -ev" -c "bmap -cv" $testdir/file1 >> $seqres.full 2>&1
$XFS_IO_PROG -c "bmap -ev" -c "bmap -cv" $testdir/file2 >> $seqres.full 2>&1
$XFS_IO_PROG -c "bmap -ev" -c "bmap -cv" $testdir/file3 >> $seqres.full 2>&1

exercise_lseek

echo "Compare files"
md5sum $testdir/file1 | _filter_scratch
md5sum $testdir/file2 | _filter_scratch
md5sum $testdir/file3 | _filter_scratch

# success, all done
status=0
exit