generic: test MADV_POPULATE_READ with IO errors
[xfstests-dev.git] / common / filter
1 ##/bin/bash
2 # SPDX-License-Identifier: GPL-2.0
3 # Copyright (c) 2000-2001 Silicon Graphics, Inc.  All Rights Reserved.
4 #
5 # standard filters
6
7 # Checks that given_value is in range of correct_value +/- tolerance.
8 # Tolerance can be an absolute value or a percentage of the correct value
9 # (see examples with tolerances below).
10 # Outputs suitable message to stdout if it's not in range.
11 #
12 # A verbose option, -v, may be used as the LAST argument
13
14 # e.g. 
15 # foo: 0.0298 = 0.03 +/- 5%
16 # _within_tolerance "foo" 0.0298 0.03 5%  
17
18 # foo: 0.0298 = 0.03 +/- 0.01
19 # _within_tolerance "foo" 0.0298 0.03 0.01
20 #
21 # foo: 0.0298 = 0.03 -0.01 +0.002
22 # _within_tolerance "foo" 0.0298 0.03 0.01 0.002
23 #
24 # foo: verbose output of 0.0298 = 0.03 +/- 5% 
25 # _within_tolerance "foo" 0.0298 0.03 5% -v 
26 _within_tolerance()
27 {
28   _name=$1
29   _given_val=$2
30   _correct_val=$3
31   _mintol=$4
32   _maxtol=$_mintol
33   _verbose=0
34   _debug=false
35
36   # maxtol arg is optional
37   # verbose arg is optional
38   if [ $# -ge 5 ]
39   then 
40      if [ "$5" = "-v" ]
41      then
42         _verbose=1
43      else
44         _maxtol=$5
45      fi
46   fi
47   if [ $# -ge 6 ]
48   then
49      [ "$6" = "-v" ] && _verbose=1
50   fi
51
52   # find min with or without %
53   _mintolerance=`echo $_mintol | sed -e 's/%//'` 
54   if [ $_mintol = $_mintolerance ]
55   then 
56       _min=`echo "scale=5; $_correct_val-$_mintolerance" | bc`
57   else
58       _min=`echo "scale=5; $_correct_val-$_mintolerance*0.01*$_correct_val" | bc`
59   fi
60
61   # find max with or without %
62   _maxtolerance=`echo $_maxtol | sed -e 's/%//'` 
63   if [ $_maxtol = $_maxtolerance ]
64   then 
65       _max=`echo "scale=5; $_correct_val+$_maxtolerance" | bc`
66   else
67       _max=`echo "scale=5; $_correct_val+$_maxtolerance*0.01*$_correct_val" | bc`
68   fi
69
70   $_debug && echo "min = $_min"
71   $_debug && echo "max = $_max"
72
73   cat <<EOF >$tmp.bc.1
74 scale=5;
75 if ($_min <= $_given_val) 1;
76 if ($_min > $_given_val) 0; 
77 EOF
78
79   cat <<EOF >$tmp.bc.2
80 scale=5;
81 if ($_given_val <= $_max) 1;
82 if ($_given_val > $_max) 0;
83 EOF
84
85   _above_min=`bc <$tmp.bc.1`
86   _below_max=`bc <$tmp.bc.2`
87
88   rm -f $tmp.bc.[12]
89
90   _in_range=`expr $_above_min \& $_below_max` 
91
92   # fix up min, max precision for output
93   # can vary for 5.3, 6.2
94
95   # remove any trailing zeroes from min, max if they have fractional parts
96   _min=`echo $_min | sed -e '/\./s/0*$//' -e 's/\.$//'`
97   _max=`echo $_max | sed -e '/\./s/0*$//' -e 's/\.$//'`
98
99   if [ $_in_range -eq 1 ] 
100   then
101         [ $_verbose -eq 1 ] && echo $_name is in range
102         return 0
103   else
104         [ $_verbose -eq 1 ] && echo $_name has value of $_given_val
105         [ $_verbose -eq 1 ] && echo $_name is NOT in range $_min .. $_max       
106         return 1
107   fi
108 }
109
110 # ctime(3) dates
111 #
112 _filter_date()
113 {
114     sed \
115         -e 's/[A-Z][a-z][a-z] [A-z][a-z][a-z]  *[0-9][0-9]* [0-9][0-9]:[0-9][0-9]:[0-9][0-9] [0-9][0-9][0-9][0-9]$/DATE/'
116 }
117
118 # prints filtered output on stdout, values (use eval) on stderr
119 # Non XFS filesystems always return a 4k block size and a 256 byte inode.
120 _filter_mkfs()
121 {
122     case $FSTYP in
123     xfs)
124         _xfs_filter_mkfs "$@"
125         ;;
126     *)
127         cat - >/dev/null
128         perl -e 'print STDERR "dbsize=4096\nisize=256\n"'
129         return ;;
130     esac
131 }
132
133 # prints the bits we care about in growfs
134
135 _filter_growfs()
136 {
137     perl -ne '
138     if (/^data\s+=\s+bsize=(\d+)\s+blocks=(\d+), imaxpct=(\d+)/) {
139         print "xfs_growfs --BlockSize=$1 --Blocks=$2\n";
140     }
141     elsif (/^data/) {
142         print;
143     }'
144 }
145
146 _filter_dd()
147 {
148     $AWK_PROG '
149         /records in/                { next }
150         /records out/               { next }
151         /No space left on device/   { print "   !!! disk full (expected)" 
152                                       next }
153                                     { print "   *** " $0 }
154     '
155 }
156
157 common_line_filter()
158 {
159     perl -ne 'if (/.*:(.*)/) {
160         if ( "$last_line" ne "$1" ) { print "$_"; $first_match=1; }
161         elsif ( $first_match==1 ) { print "*\n"; $first_match=0; }
162         $last_line="$1";
163     }
164     else {
165         print $_; $last_line=$_;
166     }'
167 }
168
169 _filter_xfs_io()
170 {
171     # Apart from standard numeric values, we also filter out 'inf', 'nan', and
172     # '-nan' which can result from division in some cases
173     sed -e "s/[0-9/.]* [GMKiBbytes]*, [0-9]* ops\; [0-9/:. sec]* ([infa0-9/.-]* [EPGMKiBbytes]*\/sec and [infa0-9/.-]* ops\/sec)/XXX Bytes, X ops\; XX:XX:XX.X (XXX YYY\/sec and XXX ops\/sec)/"
174 }
175
176 # Also filter out the offset part of xfs_io output
177 # Some test cases may be affected by underlaying extent/chunk layout change,
178 # so wipe out this part to avoid golden output difference
179 _filter_xfs_io_offset()
180 {
181     # filter out " at offset XXX" and offset of "pread -v"
182     _filter_xfs_io | sed -e "s/ at offset [0-9]*$//" -e "s/^[0-9a-f]\+:/XXXXXXXX:/"
183 }
184
185 # stderr filter for xfs_io to handle change of error output format (e.g.
186 # pwrite64 -> pwrite).
187 _filter_xfs_io_error()
188 {
189         sed -e "s/^\(.*\)64\(: .*$\)/\1\2/"
190 }
191
192 _filter_xfs_io_unique()
193 {
194     common_line_filter | _filter_xfs_io
195 }
196
197 _filter_xfs_io_units_modified()
198 {
199         UNIT=$1
200         UNIT_SIZE=$2
201
202         $AWK_PROG -v unit="$UNIT" -v unit_size=$UNIT_SIZE '
203                 /wrote/ {
204                         split($2, bytes, "/")
205
206                         bytes_written = strtonum(bytes[1])
207
208                         offset = strtonum($NF)
209
210                         unit_start = offset / unit_size
211                         unit_start = int(unit_start)
212                         unit_end = (offset + bytes_written - 1) / unit_size
213                         unit_end = int(unit_end)
214
215                         printf("%ss modified: [%d - %d]\n", unit, unit_start, unit_end)
216
217                         next
218                 }
219         '
220 }
221
222 _filter_xfs_io_blocks_modified()
223 {
224         BLOCK_SIZE=$(_get_block_size $SCRATCH_MNT)
225
226         _filter_xfs_io_units_modified "Block" $BLOCK_SIZE
227 }
228
229 _filter_xfs_io_pages_modified()
230 {
231         PAGE_SIZE=$(get_page_size)
232
233         _filter_xfs_io_units_modified "Page" $PAGE_SIZE
234 }
235
236 _filter_xfs_io_numbers()
237 {
238         _filter_xfs_io | sed -E 's/[0-9]+/XXXX/g'
239 }
240
241 _filter_test_dir()
242 {
243         # TEST_DEV may be a prefix of TEST_DIR (e.g. /mnt, /mnt/ovl-mnt)
244         # so substitute TEST_DIR first
245         sed -e "s,\B$TEST_DIR,TEST_DIR,g" \
246             -e "s,\B$TEST_DEV,TEST_DEV,g"
247 }
248
249 _filter_scratch()
250 {
251         # SCRATCH_DEV may be a prefix of SCRATCH_MNT (e.g. /mnt, /mnt/ovl-mnt)
252         # so substitute SCRATCH_MNT first
253         sed -e "s,\B$SCRATCH_MNT,SCRATCH_MNT,g" \
254             -e "s,\B$SCRATCH_DEV,SCRATCH_DEV,g" \
255             -e "/.use_space/d"
256 }
257
258 _filter_testdir_and_scratch()
259 {
260         # filter both $TEST_DIR and $SCRATCH_MNT, but always filter the longer
261         # string first if the other string is a substring of the first one
262         if echo "$TEST_DIR" | grep -q "$SCRATCH_MNT"; then
263                 _filter_test_dir | _filter_scratch
264         else
265                 _filter_scratch | _filter_test_dir
266         fi
267 }
268
269 # Turn any device in the scratch pool into SCRATCH_DEV
270 _filter_scratch_pool()
271 {
272         FILTER_STRINGS=`echo $SCRATCH_DEV_POOL | sed -e 's/\s\+/\\\|/g'`
273         sed -e "s,$FILTER_STRINGS,SCRATCH_DEV,g"
274 }
275
276 _filter_spaces()
277 {
278         sed -e "s/\s\+/ /g"
279 }
280
281 _filter_quota()
282 {
283         # Long dev name might be split onto its own line; last
284         # seds remove that newline if present
285         _filter_testdir_and_scratch | _filter_spaces | \
286         sed -e 'N;s/SCRATCH_DEV\n/SCRATCH_DEV/g' | \
287         sed -e 'N;s/TEST_DEV\n/TEST_DEV/g'
288 }
289
290 _filter_project_quota()
291 {
292         # Project ID 0 is always present on disk but was not reported
293         # until the GETNEXTQUOTA ioctl came into use.  Filter it out.
294         # But if you specify a name for ID 0, that means you want to
295         # deal with it by yourself, this function won't filter it out.
296         _filter_quota | grep -v "^\#0 \|^(null) "
297 }
298
299 # Account for different "ln" failure messages
300 _filter_ln()
301 {
302         sed -e "s,\(creating symbolic link .*\) to .*: ,\1: ," \
303             -e "s,failed to create,creating,"
304 }
305
306 # If given an arg, filter *that* UUID string
307 # Otherwise look for something that looks like a generic UUID
308 _filter_uuid()
309 {
310         if [ ! -z $1 ]; then
311                 UUID=$1
312                 sed -e "s/\(uuid[ :=]\+\) $UUID/\1 <EXACTUUID>/i"
313         else
314                 sed -e "s/\(uuid[ :=]\+\) [0-9a-f-][0-9a-f-]*/\1 <UUID>/ig"
315         fi
316 }
317
318 # In mixed group the added disks may have zero used size
319 _filter_zero_size()
320 {
321         sed -e "s/0\.00/<SIZE>/g"
322 }
323
324 # Filter out sizes like 6.14MB etc
325 _filter_size()
326 {
327         sed -e "s/[0-9\.]\+\s\?[b|k|m|g|t][i]\?[b]\?/<SIZE>/ig"
328 }
329
330 # Convert string read from stdin like 128K to bytes and print it to stdout
331 _filter_size_to_bytes()
332 {
333         read size
334         suffix=${size:${#size}-1}
335         mul=1
336         case $suffix in
337                 k|K) mul=1024 ;;
338                 m|M) mul=$((1024*1024)) ;;
339                 g|G) mul=$((1024*1024*1024)) ;;
340                 t|T) mul=$((1024*1024*1024*1024)) ;;
341         esac
342         echo $((${size:0:${#size}-1}*$mul))
343 }
344
345 # Print trimmed bytes of fstrim
346 # Starting from util-linux v2.23 fstrim usees human readable sizes in
347 # verbose output
348 _filter_fstrim()
349 {
350         egrep -o "[0-9]+ bytes" | $AWK_PROG '{print $1}'
351 }
352
353 # Remove the ending dot appended to mount error message, util-linux 2.30
354 # starts to do so.
355 _filter_ending_dot()
356 {
357         sed -e "s/\.$//"
358 }
359
360 # Older mount output referred to "block device" when mounting RO devices. It's
361 # gone in newer versions. v2.30 changed the output again. This filter is to
362 # unify all read-only mount messages across all util-linux versions.
363 #
364 # for a successful ro mount:
365 # ancient:         mount: block device <device> is write-protected, mounting read-only
366 # prior to v2.30:  mount: <device> is write-protected, mounting read-only
367 # v2.30 and later: mount: <mountpoint>: WARNING: device write-protected, mounted read-only.
368 #
369 # a failed ro mount:
370 # ancient (two-line message):
371 # mount: block device <device> is write-protected, mounting read-only
372 # mount: cannot mount block device <device> read-only
373 # prior to v2.30 (two-line message):
374 # mount: <device> is write-protected, mounting read-only
375 # mount: cannot mount <device> read-only
376 # v2.30 and later (single-line message):
377 # mount: <mountpoint>: cannot mount <device> read-only.
378 #
379 # a failed rw remount:
380 # ancient:         mount: cannot remount block device <device> read-write, is write-protected
381 # prior to v2.30:  mount: cannot remount <device> read-write, is write-protected
382 # v2.30 and later: mount: <mountpoint>: cannot remount <device> read-write, is write-protected.
383 #
384 # Now use _filter_ro_mount to unify all these differences across old & new
385 # util-linux versions. So the filtered format would be:
386 #
387 # successful ro mount:
388 # mount: device write-protected, mounting read-only
389 #
390 # failed ro mount:
391 # mount: device write-protected, mounting read-only
392 # mount: cannot mount device read-only
393 #
394 # failed rw remount:
395 # mount: cannot remount device read-write, is write-protected
396 _filter_ro_mount() {
397         perl -ne '
398         if (/write-protected, mount.*read-only/) {
399                 # filter successful ro mount, and first line of prior to v2.30
400                 # format failed ro mount
401                 print "mount: device write-protected, mounting read-only\n";
402         } elsif (/mount: .*: cannot mount.*read-only/) {
403                 # filter v2.30 format failed ro mount, convert single-line
404                 # message to two-line message
405                 print "mount: device write-protected, mounting read-only\n";
406                 print "mount: cannot mount device read-only\n";
407         } elsif (/^mount: cannot mount .* read-only$/) {
408                 # filter prior to v2.30 format failed ro mount
409                 print "mount: cannot mount device read-only\n";
410         } elsif (/mount:.* cannot remount .* read-write.*/) {
411                 # filter failed rw remount
412                 print "mount: cannot remount device read-write, is write-protected\n";
413         } else {
414                 print "$_";
415         }' | _filter_ending_dot
416 }
417
418 # Filter a failed mount output due to EUCLEAN and USTALE, util-linux changed
419 # the message several times.
420 #
421 # prior to v2.21:
422 # mount: Structure needs cleaning
423 # v2.21 to v2.29:
424 # mount: mount <device> on <mountpoint> failed: Structure needs cleaning
425 # v2.30 and later:
426 # mount: <mountpoint>: mount(2) system call failed: Structure needs cleaning.
427 #
428 # This is also true for ESTALE error. So let's remove all the changing parts
429 # and keep the 'prior to v2.21' format:
430 # mount: Structure needs cleaning
431 # mount: Stale file handle
432 _filter_error_mount()
433 {
434         sed -e "s/mount:\(.*failed:\)/mount:/" | _filter_ending_dot
435 }
436
437 # Similar to _filter_error_mount, filter a busy mount output.
438 # Turn both old (prior to util-linux v2.30) and new (v2.30 and later) format to
439 # a simple one. e.g.
440 # old: mount: <device> is already mounted or <mountpoint> busy
441 # new: mount: <mountpoint>: <device> already mounted or mount point busy.
442 # filtered: mount: device already mounted or mount point busy
443 _filter_busy_mount()
444 {
445         sed -e "s/.*: .* already mounted or .* busy/mount: device already mounted or mount point busy/" | \
446                 _filter_ending_dot
447 }
448
449 _filter_od()
450 {
451         BLOCK_SIZE=$(_get_block_size $SCRATCH_MNT)
452         $AWK_PROG -v block_size=$BLOCK_SIZE '
453                 /^[0-9]+/ {
454                         offset = strtonum("0"$1);
455                         $1 = sprintf("%o", offset / block_size);
456                         print $0;
457                 }
458                 /\*/
459         '
460 }
461
462 # Remove quotes from failed mknod calls. Starting with Coreutils v8.25,
463 # mknod errors print unquoted filenames
464 _filter_mknod()
465 {
466         sed -e "s/mknod: [\`']\(.*\)': File exists/mknod: \1: File exists/"
467 }
468
469 # Remove leading "rename" in "mv -v" output
470 _filter_mv()
471 {
472         sed -e "s/^renamed //"
473 }
474
475 # New stat(1) uses statx(2)
476 _filter_stat()
477 {
478         sed -e "s/\<cannot stat\>/cannot statx/"
479 }
480
481 _filter_lostfound()
482 {
483         sed -e '/^lost+found$/d'
484 }
485
486 _filter_ovl_dirs()
487 {
488         sed -e "s,$OVL_LOWER,OVL_LOWER,g" \
489             -e "s,$OVL_UPPER,OVL_UPPER,g" \
490             -e "s,$OVL_WORK,OVL_WORK,g"
491 }
492
493 # interpret filefrag output,
494 # eg. "physical 1234, length 10, logical 5678" -> "1234#10#5678"
495 _filter_filefrag()
496 {
497         perl -ne '
498         if (/blocks? of (\d+) bytes/) {
499                 $blocksize = $1;
500                 next
501         }
502         ($ext, $logical, $physical, $length) =
503                 (/^\s*(\d+):\s+(\d+)..\s+\d+:\s+(\d+)..\s+\d+:\s+(\d+):/)
504         or next;
505         ($flags) = /.*:\s*(\S*)$/;
506         print $physical * $blocksize, "#",
507               $length * $blocksize, "#",
508               $logical * $blocksize, "#",
509               $flags, "\n"'
510 }
511
512 # Clean up the extents list output of 'xfs_io -c fiemap', e.g.
513 #
514 #       file:
515 #               0: [0..79]: 628365312..628365391
516 #               1: [80..159]: hole
517 #               2: [160..319]: 628365472..628365631
518 # =>
519 #       0  79   628365312  628365391
520 #       160  319   628365472  628365631
521 #
522 # The fields are:
523 #
524 #       first_logical_block last_logical_block first_physical_block last_physical_block
525 #
526 # Blocks are 512 bytes, and holes are omitted.
527 #
528 _filter_xfs_io_fiemap()
529 {
530          grep -E '^[[:space:]]+[0-9]+:' \
531                  | grep -v '\<hole\>' \
532                  | sed -E 's/^[[:space:]]+[0-9]+://' \
533                  | tr '][.:' ' '
534 }
535
536 # We generate WARNINGs on purpose when applications mix buffered/mmap IO with
537 # direct IO on the same file. This is a helper for _check_dmesg() to filter out
538 # such warnings.
539 _filter_aiodio_dmesg()
540 {
541         local warn1="WARNING:.*fs/xfs/xfs_file\.c:.*xfs_file_dio_aio_write.*"
542         local warn2="WARNING:.*fs/xfs/xfs_file\.c:.*xfs_file_dio_aio_read.*"
543         local warn3="WARNING:.*fs/xfs/xfs_file\.c:.*xfs_file_read_iter.*"
544         local warn4="WARNING:.*fs/xfs/xfs_file\.c:.*xfs_file_aio_read.*"
545         local warn5="WARNING:.*fs/iomap\.c:.*iomap_dio_rw.*"
546         local warn6="WARNING:.*fs/xfs/xfs_aops\.c:.*__xfs_get_blocks.*"
547         local warn7="WARNING:.*fs/iomap\.c:.*iomap_dio_actor.*"
548         local warn8="WARNING:.*fs/iomap\.c:.*iomap_dio_complete.*"
549         local warn9="WARNING:.*fs/direct-io\.c:.*dio_complete.*"
550         local warn10="WARNING:.*fs/iomap/direct-io\.c:.*iomap_dio_actor.*"
551         sed -e "s#$warn1#Intentional warnings in xfs_file_dio_aio_write#" \
552             -e "s#$warn2#Intentional warnings in xfs_file_dio_aio_read#" \
553             -e "s#$warn3#Intentional warnings in xfs_file_read_iter#" \
554             -e "s#$warn4#Intentional warnings in xfs_file_aio_read#" \
555             -e "s#$warn5#Intentional warnings in iomap_dio_rw#" \
556             -e "s#$warn6#Intentional warnings in __xfs_get_blocks#" \
557             -e "s#$warn7#Intentional warnings in iomap_dio_actor#" \
558             -e "s#$warn8#Intentional warnings in iomap_dio_complete#" \
559             -e "s#$warn9#Intentional warnings in dio_complete#" \
560             -e "s#$warn10#Intentional warnings in iomap_dio_actor#"
561 }
562
563 # We generate assert related WARNINGs on purpose and make sure test doesn't fail
564 # because of these warnings. This is a helper for _check_dmesg() to filter out
565 # them.
566 _filter_assert_dmesg()
567 {
568         local warn1="WARNING:.*fs/xfs/xfs_message\.c:.*asswarn.*"
569         local warn2="WARNING:.*fs/xfs/xfs_message\.c:.*assfail.*"
570         sed -e "s#$warn1#Intentional warnings in asswarn#" \
571             -e "s#$warn2#Intentional warnings in assfail#"
572 }
573
574 # With version 2.41 of libcap, the output format of getcap changed.
575 # More specifically such change was added by the following commit:
576 #
577 # commit 177cd418031b1acfcf73fe3b1af9f3279828681c
578 # Author: Andrew G. Morgan <morgan@kernel.org>
579 # Date:   Tue Jul 21 22:58:05 2020 -0700
580 #
581 #     A more compact form for the text representation of capabilities.
582 #
583 #     While this does not change anything about the supported range of
584 #     equivalent text specifications for capabilities, as accepted by
585 #     cap_from_text(), this does alter the preferred output format of
586 #     cap_to_text() to be two characters shorter in most cases. That is,
587 #     what used to be summarized as:
588 #
589 #        "= cap_foo+..."
590 #
591 #     is now converted to the equivalent text:
592 #
593 #        "cap_foo=..."
594 #
595 #     which is also more intuitive.
596 #
597 _filter_getcap()
598 {
599         sed -e "s/= //" -e "s/\+/=/g"
600 }
601
602 # Filter user/group/project id numbers out of quota reports, and standardize
603 # the block counts to use filesystem block size.  Callers must set the id and
604 # bsize variables before calling this function.
605 _filter_quota_report()
606 {
607         test -n "$id" || echo "id must be set"
608         test -n "$bsize" || echo "block size must be set"
609
610         tr -s '[:space:]' | \
611         perl -npe '
612                 s/^\#'$id' /[NAME] /g;
613                 s/^\#0 \d+ /[ROOT] 0 /g;
614                 s/6 days/7 days/g' |
615         perl -npe '
616                 $val = 0;
617                 if ($ENV{'LARGE_SCRATCH_DEV'}) {
618                         $val = $ENV{'NUM_SPACE_FILES'};
619                 }
620                 s/(^\[ROOT\] \S+ \S+ \S+ \S+ \[--------\] )(\S+)/$1@{[$2 - $val]}/g' |
621         sed -e 's/ 65535 \[--------\]/ 00 \[--------\]/g' |
622         perl -npe '
623                 s|^(.*?) (\d+) (\d+) (\d+)|$1 @{[$2 * 1024 /'$bsize']} @{[$3 * 1024 /'$bsize']} @{[$4 * 1024 /'$bsize']}|'
624 }
625
626 #
627 # Bash 5.1+ adds "line 1: " when reporting an error when running a
628 # command via the -c option.  For example, "bash -c 'echo foo > /'"
629 # will result in the error "bash: line 1: /: Is a directory" when
630 # earlier versions of bash would omit the "line 1: " annotation.
631 #
632 _filter_bash()
633 {
634         sed -e "s/^bash: line 1: /bash: /"
635 }
636
637 #
638 # blkzone report added zone capacity to be printed from v2.37.
639 # This filter will add an extra column 'cap' with the same value of
640 # 'len'(zone size) for blkzone version < 2.37
641 #
642 # Before: start: 0x000100000, len 0x040000, wptr 0x000000 ..
643 # After: start: 0x000100000, len 0x040000, cap 0x040000, wptr 0x000000 ..
644 _filter_blkzone_report()
645 {
646         $AWK_PROG -F "," 'BEGIN{OFS=",";} $3 !~ /cap/ {$2=$2","$2;} {print;}' |\
647         sed -e 's/len/cap/2'
648 }
649
650 # make sure this script returns success
651 /bin/true