generic: unaligned direct AIO write test
[xfstests-dev.git] / tests / generic / 538
1 #! /bin/bash
2 # SPDX-License-Identifier: GPL-2.0
3 # Copyright (c) 2019 Red Hat, Inc.  All Rights Reserved.
4 #
5 # FS QA Test No. 538
6 #
7 # Non-block-aligned direct AIO write test with an initial truncate i_size.
8 #
9 # Uncover "ext4: Fix data corruption caused by unaligned direct AIO":
10 # (Ext4 needs to serialize unaligned direct AIO because the zeroing of
11 # partial blocks of two competing unaligned AIOs can result in data
12 # corruption.
13 #
14 # However it decides not to serialize if the potentially unaligned aio is
15 # past i_size with the rationale that no pending writes are possible past
16 # i_size. Unfortunately if the i_size is not block aligned and the second
17 # unaligned write lands past i_size, but still into the same block, it has
18 # the potential of corrupting the previous unaligned write to the same
19 # block.)
20 #
21 seq=`basename $0`
22 seqres=$RESULT_DIR/$seq
23 echo "QA output created by $seq"
24
25 here=`pwd`
26 tmp=/tmp/$$
27 status=1        # failure is the default!
28 trap "_cleanup; exit \$status" 0 1 2 3 15
29
30 _cleanup()
31 {
32         cd /
33         rm -f $tmp.*
34 }
35
36 # get standard environment, filters and checks
37 . ./common/rc
38 . ./common/filter
39
40 # remove previous $seqres.full before test
41 rm -f $seqres.full
42
43 # real QA test starts here
44 _supported_fs generic
45 _supported_os Linux
46 _require_test
47 _require_aiodio aio-dio-write-verify
48
49 localfile=$TEST_DIR/${seq}-aio-dio-write-verify-testfile
50 diosize=`_min_dio_alignment $TEST_DEV`
51 blocksize=`_get_block_size $TEST_DIR`
52 bufsize=$((blocksize * 2))
53 truncsize=$((bufsize+diosize))
54
55 # Need smaller logical block size to do non-block-aligned test
56 if [ $diosize -ge $blocksize ];then
57         _notrun "Need device logical block size($diosize) < fs block size($blocksize)"
58 fi
59
60 rm -rf $localfile 2>/dev/null
61 # block-aligned aiodio write verification at first
62 $AIO_TEST -a size=$bufsize,off=0 -a size=$bufsize,off=$bufsize $localfile
63
64 # non-block-aligned aiodio write verification
65 #          **************** **************** ****************
66 #          *   block 1&2  * *  block 3&4   * *  block 5&6   *
67 #          **************** **************** ****************
68 # existing 0000000000000000 0000000000000000 0000000000000000
69 # truncate ---------------->|
70 # write 1   ZZZZZZZZZZZZZZZ Z
71 # write 2  |<----            ZZZZZZZZZZZZZZZ Z ---->|
72 #
73 # "Write 1" writes 2 blocks data at off=$diosize.
74 # "Write 2" seeks from 0 to "Write 1" end + block size, shift $diosize bytes each
75 # time, writes 2 blocksize data too.
76 # Verify there's not corruption each time.
77 i=0
78 while [ $((diosize * i)) -lt $((diosize + bufsize + blocksize)) ];do
79         position=$((diosize * i++))
80         # non-block-aligned AIO write on different i_size file
81         $AIO_TEST -t $truncsize -a size=$bufsize,off=$diosize \
82                   -a size=$bufsize,off=$position \
83                   $localfile
84         if [ $? -ne 0 ];then
85                 echo "FAIL: [$truncsize, $bufsize, $diosize, $position]"
86                 echo "-------------------------------------------------"
87         fi
88         rm -f $localfile
89 done
90
91 echo "Silence is golden"
92
93 # success, all done
94 status=0
95 exit