xfstests: kill useless test owner fields
[xfstests-dev.git] / 298
1 #! /bin/bash
2 # FS QA Test No. 298
3 #
4 # Test that filesystem sends discard requests only on free blocks
5 #
6 #-----------------------------------------------------------------------
7 # Copyright (c) 2013 Red Hat, Inc., Tomas Racek <tracek@redhat.com>
8 #
9 # This program is free software; you can redistribute it and/or
10 # modify it under the terms of the GNU General Public License as
11 # published by the Free Software Foundation.
12 #
13 # This program is distributed in the hope that it would be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 # GNU General Public License for more details.
17 #
18 # You should have received a copy of the GNU General Public License
19 # along with this program; if not, write the Free Software Foundation,
20 # Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21 #-----------------------------------------------------------------------
22 #
23
24 seq=`basename $0`
25 echo "QA output created by $seq"
26
27 status=1        # failure is the default!
28 trap "_cleanup; exit \$status" 0 1 2 3 15
29
30 . common.config
31 . common.rc
32
33 _supported_fs ext4 xfs
34 _supported_os Linux
35 _require_fstrim
36 _require_fs_space $TEST_DIR 307200
37 [ "$FSTYP" = "ext4" ] && _require_dumpe2fs
38
39 _cleanup()
40 {
41         $UMOUNT_PROG $loop_dev &> /dev/null
42         _destroy_loop_device $loop_dev
43         if [ $status -eq 0 ]; then
44                 rm -rf $tmp
45                 rm $img_file
46         fi
47 }
48
49 get_holes()
50 {
51         $XFS_IO_PROG -c fiemap $1 | grep hole | $SED_PROG 's/.*\[\(.*\)\.\.\(.*\)\].*/\1 \2/'
52 }
53
54 get_free_sectors()
55 {
56         case $FSTYP in
57         ext4)
58         $DUMPE2FS_PROG $img_file  2>&1 | grep " Free blocks" | cut -d ":" -f2- | \
59                 tr ',' '\n' | $SED_PROG 's/^ //' | \
60                 $AWK_PROG -v spb=$sectors_per_block 'BEGIN{FS="-"};
61                      NF {
62                         if($2 != "") # range of blocks
63                                 print spb * $1, spb * ($2 + 1) - 1;
64                         else            # just single block
65                                 print spb * $1, spb * ($1 + 1) - 1;
66                      }'
67         ;;
68         xfs)
69         agsize=`xfs_info $loop_mnt | $SED_PROG -n 's/.*agsize=\(.*\) blks.*/\1/p'`
70         # Convert free space (agno, block, length) to (start sector, end sector)
71         $UMOUNT_PROG $loop_mnt
72         $XFS_DB_PROG -c "freesp -d" $img_file | $SED_PROG '/^.*from/,$d'| \
73                  $AWK_PROG -v spb=$sectors_per_block -v agsize=$agsize \
74                 '{ print spb * ($1 * agsize + $2), spb * ($1 * agsize + $2 + $3) - 1 }'
75         ;;
76         esac
77 }
78
79 merge_ranges()
80 {
81         # Merges consecutive ranges from two input files
82         file1=$1
83         file2=$2
84
85         tmp_file=$tmp/sectors.tmp
86
87         cat $file1 $file2 | sort -n > $tmp_file
88
89         read line < $tmp_file
90         start=${line% *}
91         end=${line#* }
92
93         # Continue from second line
94         sed -i "1d" $tmp_file
95         while read line; do
96                 curr_start=${line% *}
97                 curr_end=${line#* }
98
99                 if [ `expr $end + 1` -ge $curr_start ]; then
100                         if [ $curr_end -gt $end ]; then
101                                 end=$curr_end
102                         fi
103                 else
104                         echo $start $end
105                         start=$curr_start
106                         end=$curr_end
107                 fi
108         done < $tmp_file
109
110         # Print last line
111         echo $start $end
112
113         rm $tmp_file
114 }
115
116 here=`pwd`
117 tmp=`mktemp -d`
118
119 img_file=$TEST_DIR/$$.fs
120 dd if=/dev/zero of=$img_file bs=1M count=300 &> /dev/null
121
122 loop_dev=$(_create_loop_device $img_file)
123 loop_mnt=$tmp/loop_mnt
124
125 fiemap_ref="$tmp/reference"
126 fiemap_after="$tmp/after"
127 free_sectors="$tmp/free_sectors"
128 merged_sectors="$tmp/merged_free_sectors"
129
130 mkdir $loop_mnt
131
132 [ "$FSTYP" = "xfs" ] && MKFS_OPTIONS="-f $MKFS_OPTIONS"
133
134 $MKFS_PROG -t $FSTYP $MKFS_OPTIONS $loop_dev &> /dev/null
135 $MOUNT_PROG $loop_dev $loop_mnt
136
137 echo -n "Generating garbage on loop..."
138 for i in `seq 1 10`; do
139         mkdir $loop_mnt/$i
140         cp -r $here/* $loop_mnt/$i
141 done
142
143 # Get reference fiemap, this can contain i.e. uninitialized inode table
144 sync
145 get_holes $img_file > $fiemap_ref
146
147 # Delete some files
148 find $loop_mnt -type f -print | $AWK_PROG \
149         'BEGIN {srand()}; {if(rand() > 0.7) print $1;}' | xargs rm
150 echo "done."
151
152 echo -n "Running fstrim..."
153 $FSTRIM_PROG $loop_mnt &> /dev/null
154 echo "done."
155
156 echo -n "Detecting interesting holes in image..."
157 # Get after-trim fiemap
158 sync
159 get_holes $img_file > $fiemap_after
160 echo "done."
161
162 echo -n "Comparing holes to the reported space from FS..."
163 # Get block size
164 block_size=$(stat -f -c "%S" $loop_mnt/)
165 sectors_per_block=`expr $block_size / 512`
166
167 # Obtain free space from filesystem
168 get_free_sectors > $free_sectors
169 # Merge original holes with free sectors
170 merge_ranges $fiemap_ref $free_sectors > $merged_sectors
171
172 # Check that all holes after fstrim call were already present before or
173 # that they match free space reported from FS
174 while read line; do
175         from=${line% *}
176         to=${line#* }
177         if ! $AWK_PROG -v s=$from -v e=$to \
178                 '{ if ($1 <= s && e <= $2) found = 1};
179                 END { if(found) exit 0; else exit 1}' $merged_sectors
180         then
181                 echo "Sectors $from-$to are not marked as free!"
182                 exit
183         fi
184 done < $fiemap_after
185 echo "done."
186
187 status=0
188 exit