common/fuzzy: if the fuzz verb is random, keep fuzzing until we get a new value
[xfstests-dev.git] / common / filestreams
1 ##/bin/bash
2 #
3 # Copyright (c) 2007 Silicon Graphics, Inc.  All Rights Reserved.
4 #
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License as
7 # published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it would be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write the Free Software Foundation,
16 # Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17 #
18 #
19 # Core of filestreams tests.
20 #
21
22 _check_filestreams_support()
23 {
24         [ -f /proc/sys/fs/xfs/filestream_centisecs ]
25 }
26
27 _set_stream_timeout_centisecs()
28 {
29         echo $1 > /proc/sys/fs/xfs/filestream_centisecs
30 }
31
32 _do_stream()
33 {
34         local directory_name=$1
35         local files=$2
36         local file_size=$3
37         local bsize=$4
38         local iflag=$5
39         local dio=$6
40         local blocks_in_file=`expr $file_size / $bsize`
41
42         mkdir $directory_name
43         if [ "$iflag" = "1" ]; then
44                 $XFS_IO_PROG -x -c "chattr +S" $directory_name \
45                         || _fail "chattr of filestream flag"
46         fi
47         cd $directory_name
48
49         local dd_cmd="dd"
50         [ "$dio" = "1" ] && dd_cmd="$dd_cmd oflag=direct"
51         dd_cmd="$dd_cmd if=/dev/zero bs=${bsize} count=${blocks_in_file}"
52
53         local i=1
54         while [ $i -le $files ]; do
55                 $dd_cmd of=frame-${i} 2>&1 | grep -v records | grep -v secs
56                 i=`expr $i + 1`
57         done
58 }
59
60 _filter_agno()
61 {
62         # the ag number is in column 4 of xfs_bmap output
63         perl -ne '
64                 $ag = (split /\s+/)[4] ;
65                 if ($ag =~ /\d+/) {print "$ag "} ;
66         '
67 }
68
69 _get_stream_ags()
70 {
71         local directory_name=$1
72         local stream_ags=`xfs_bmap -vp ${directory_name}/* | _filter_agno`
73         echo $stream_ags
74 }
75
76 _check_for_dupes()
77 {
78         # check for duplicate numbers between two space seperated vars
79         local num_str_one=$1
80         local num_str_two=$2
81
82         local this_num_one
83         local this_num_two
84         for this_num_one in $num_str_one; do
85                 for this_num_two in $num_str_two; do
86                         if [ "$this_num_one" == "$this_num_two" ]; then
87                                 echo "duplicate AG $this_num_one found" \
88                                         >> $seqres.full
89                                 return 1
90                         fi
91                 done
92         done
93         return 0
94 }
95
96 _test_streams() {
97
98         echo "# testing $* ...."
99         local agcount="$1"
100         local agsize="$2" # in MB
101         local stream_count="$3"
102         local stream_files="$4"
103         local stream_file_size=`expr $5 \* 1024 \* 1024`
104         local use_iflag="$6"
105         local use_directio="$7"
106         local expected_result="$8"      # "fail" if failure is expected
107
108         local size=`expr $agsize \* 1024 \* 1024 \* $agcount`
109         _scratch_mkfs_xfs -dsize=$size,agcount=$agcount >/dev/null 2>&1 \
110                 || _fail "mkfs failed"
111
112         if [ "$use_iflag" = "0" ]; then
113                 # mount using filestreams mount option
114                 _scratch_mount "-o filestreams" \
115                         || _fail "filestreams mount failed"
116         else
117                 # test will set inode flag
118                 _scratch_mount || _fail "mount failed"
119         fi
120
121         cd $SCRATCH_MNT
122
123         # start $stream_count streams
124         # each stream writes ($stream_files x $stream_file_size)M
125         echo "# streaming"
126         local stream_pids=""
127         local stream_index=1
128         while [ $stream_index -le $stream_count ]; do
129                 _do_stream stream${stream_index}-dir $stream_files \
130                         $stream_file_size 1048576 $use_iflag $use_directio &
131                 stream_pids="$stream_pids $!"
132                 stream_index=`expr $stream_index + 1`
133         done
134
135         # wait for streams to finish
136         # XXX wait here not needed? -dgc
137         wait $stream_pids
138
139         # sync the buffered streams out in parallel
140         # _get_stream_ags does a xfs_bmap which syncs delayed allocations
141         echo "# sync AGs..."
142         local ag_sync_pids=""
143         stream_index=1
144         while [ $stream_index -le $stream_count ]; do
145                 _get_stream_ags stream${stream_index}-dir > /dev/null 2>&1 &
146                 ag_sync_pids="$ag_sync_pids $!"
147                 stream_index=`expr $stream_index + 1`
148         done
149
150         # wait for syncs to finish
151         wait $ag_sync_pids
152
153         # confirm streams are in seperate AGs
154         echo "# checking stream AGs..."
155         local this_stream_ags=""
156         local ags_seen=""
157         local num_streams_with_matching_ags=0
158         stream_index=1
159         while [ $stream_index -le $stream_count ]; do
160                 this_stream_ags=`_get_stream_ags stream${stream_index}-dir`
161                 echo "stream $stream_index AGs: $this_stream_ags" >> $seqres.full
162                 _check_for_dupes "$ags_seen" "$this_stream_ags"
163                 if [ $? -ne 0 ]; then
164                         # this stream is not in seperate AGs to previous streams
165                         num_streams_with_matching_ags=`expr $num_streams_with_matching_ags + 1`
166                 fi
167                 ags_seen="$ags_seen $this_stream_ags"
168                 stream_index=`expr $stream_index + 1`
169         done
170
171         _cleanup_streams_umount
172         if [ "$expected_result" != "fail" ]; then
173                 if [ $num_streams_with_matching_ags -eq 0 ]; then
174                         # all streams in seperate AGs, as expected
175                         echo "+ passed, streams are in seperate AGs"
176                 else
177                         # streams with matching AGs, should be seperate
178                         _fail "- failed, $num_streams_with_matching_ags streams with matching AGs"
179                 fi
180         else
181                 # expecting streams to have overlapped
182                 if [ $num_streams_with_matching_ags -eq 0 ]; then
183                         # all streams in seperate AGs, should have overlapped
184                         _fail "- streams are in seperate AGs, expected _matching_"
185                 else
186                         # streams with matching AGs, as expected
187                         echo "+ expected failure, matching AGs"
188                 fi
189         fi
190         return 0
191 }
192
193 _cleanup_streams_umount()
194 {
195         cd /
196         rm -rf ${SCRATCH_MNT}/stream*
197         _scratch_unmount 2>/dev/null
198 }