reflink: ensure that we can handle reflinking a lot of extents
[xfstests-dev.git] / tests / generic / 251
1 #!/bin/bash
2 # FS QA Test No. 251
3 #
4 # This test was created in order to verify filesystem FITRIM implementation.
5 # By many concurrent copy and remove operations and checking that files
6 # does not change after copied into SCRATCH_MNT test if FITRIM implementation
7 # corrupts the filesystem (data/metadata).
8 #
9 #-----------------------------------------------------------------------
10 # Copyright 2010 (C) Red Hat, Inc., Lukas Czerner <lczerner@redhat.com>
11 #
12 # This program is free software; you can redistribute it and/or
13 # modify it under the terms of the GNU General Public License as
14 # published by the Free Software Foundation.
15 #
16 # This program is distributed in the hope that it would be useful,
17 # but WITHOUT ANY WARRANTY; without even the implied warranty of
18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 # GNU General Public License for more details.
20 #
21 # You should have received a copy of the GNU General Public License
22 # along with this program; if not, write the Free Software Foundation,
23 # Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
24 #-----------------------------------------------------------------------
25
26 seq=`basename $0`
27 seqres=$RESULT_DIR/$seq
28 echo "QA output created by $seq"
29
30 here=`pwd`
31 tmp=`mktemp -d`
32 status=1    # failure is the default!
33 trap "_cleanup; exit \$status" 0 1 3
34 trap "_destroy; exit \$status" 2 15
35 chpid=0
36 mypid=$$
37
38 # get standard environment, filters and checks
39 . ./common/rc
40 . ./common/filter
41
42 # real QA test starts here
43 _supported_fs generic
44 _supported_os Linux
45 _require_scratch
46 _scratch_mkfs >/dev/null 2>&1
47 _scratch_mount
48 _require_batched_discard $SCRATCH_MNT
49
50 _cleanup()
51 {
52         rm -rf $tmp
53 }
54
55 _destroy()
56 {
57         kill $pids $fstrim_pid 2> /dev/null
58         wait $pids $fstrim_pid 2> /dev/null
59         rm -rf $tmp
60 }
61
62 _destroy_fstrim()
63 {
64         kill $fpid 2> /dev/null
65         wait $fpid 2> /dev/null
66 }
67
68 _fail()
69 {
70         echo "$1"
71         kill $mypid 2> /dev/null
72 }
73
74 _guess_max_minlen()
75 {
76         mmlen=100000
77         while [ $mmlen -gt 1 ]; do
78                 $FSTRIM_PROG -l $(($mmlen*2))k -m ${mmlen}k $SCRATCH_MNT &> /dev/null && break
79                 mmlen=$(($mmlen/2))
80         done
81         echo $mmlen
82 }
83
84 ##
85 # Background FSTRIM loop. We are trimming the device in the loop and for
86 # test coverage, we are doing whole device trim followed by several smaller
87 # trims.
88 ##
89 fstrim_loop()
90 {
91         trap "_destroy_fstrim; exit \$status" 2 15
92         fsize=$($DF_PROG | grep $SCRATCH_MNT | grep $SCRATCH_DEV  | awk '{print $3}')
93         mmlen=$(_guess_max_minlen)
94
95         while true ; do
96                 step=$((RANDOM*$RANDOM+4))
97                 minlen=$(((RANDOM*($RANDOM%2+1))%$mmlen))
98                 start=$RANDOM
99                 if [ $((RANDOM%10)) -gt 7 ]; then
100                         $FSTRIM_PROG $SCRATCH_MNT &
101                         fpid=$!
102                         wait $fpid
103                 fi
104                 while [ $start -lt $fsize ] ; do
105                         $FSTRIM_PROG -m ${minlen}k -o ${start}k -l ${step}k $SCRATCH_MNT &
106                         fpid=$!
107                         wait $fpid
108                         start=$(( $start + $step ))
109                 done
110         done
111 }
112
113 function check_sums() {
114         (
115         cd $SCRATCH_MNT/$p
116         find -P . -xdev -type f -print0 | xargs -0 md5sum | sort -o $tmp/stress.$$.$p
117         )
118
119         diff $tmp/content.sums $tmp/stress.$$.$p
120         if [ $? -ne 0 ]; then
121                 _fail "!!!Checksums has changed - Filesystem possibly corrupted!!!\n"
122         fi
123         rm -f $tmp/stress.$$.$p
124 }
125
126 function run_process() {
127         local p=$1
128         repeat=10
129
130         sleep $((5*$p))s &
131         export chpid=$! && wait $chpid &> /dev/null
132         chpid=0
133
134         while [ $repeat -gt 0 ]; do
135
136                 # Remove old directories.
137                 rm -rf $SCRATCH_MNT/$p
138                 export chpid=$! && wait $chpid &> /dev/null
139
140                 # Copy content -> partition.
141                 mkdir $SCRATCH_MNT/$p
142                 cp -axT $content/ $SCRATCH_MNT/$p/
143                 export chpid=$! && wait $chpid &> /dev/null
144
145                 check_sums
146                 repeat=$(( $repeat - 1 ))
147         done
148 }
149
150 nproc=20
151 content=$here
152
153 mkdir -p $tmp
154
155 (
156 cd $content
157 find -P . -xdev -type f -print0 | xargs -0 md5sum | sort -o $tmp/content.sums
158 )
159
160 echo -n "Running the test: "
161 pids=""
162 fstrim_loop &
163 fstrim_pid=$!
164 p=1
165 while [ $p -le $nproc ]; do
166         run_process $p &
167         pids="$pids $!"
168         p=$(($p+1))
169 done
170 echo "done."
171
172 wait $pids
173 kill $fstrim_pid
174 wait $fstrim_pid
175
176 status=0
177
178 exit