2 # SPDX-License-Identifier: GPL-2.0
3 # Copyright (c) 2007 Silicon Graphics, Inc. All Rights Reserved.
5 # common functions for excersizing hole punches with extent size hints etc.
8 echo "# spawning test file with $*"
10 local file_size=`expr $2 \* $blksize`
11 local extent_size_hint=`expr $3 \* $blksize`
13 local reserve_space=$5
15 if [ $extent_size_hint -ne 0 ]; then
16 echo "+ setting extent size hint to $extent_size_hint"
18 -c "extsize $extent_size_hint" \
21 # print extent size hint for $test_file
26 if [ "$reserve_space" == "noresv" ]; then
27 echo "+ not using resvsp at file creation"
29 -c "truncate $file_size" \
33 -c "truncate $file_size" \
34 -c "resvsp 0 $file_size" \
40 echo "# writing with $*"
42 local write_offset=`expr $2 \* $blksize`
43 local write_size=`expr $3 \* $blksize`
47 -c "pwrite $write_offset $write_size" \
52 echo "# showing file state $*"
64 [[ -z $block_size ]] && block_size=512
66 awk -v block_size="$block_size" -F: '
71 split(range, bounds, "[\\[ \\.\\]]");
75 if (type != prev_type) {
77 printf("%u]:%s\n", (low * 512 / block_size) - 1,
79 printf("%u: [%u..", out_count++,
80 (low * 512) / block_size);
86 printf("%u]:%s\n", ((high + 1) * 512 / block_size) - 1,
100 $5 ~ /0x[[:xdigit:]]*8[[:xdigit:]][[:xdigit:]]/ {
101 print $1, $2, "unwritten";
104 $5 ~ /0x[[:xdigit:]]+/ {
105 print $1, $2, "data";
107 _coalesce_extents $block_size
110 _filter_fiemap_flags()
117 $5 ~ /0x[[:xdigit:]]*8[[:xdigit:]][[:xdigit:]]/ {
118 print $1, $2, "unwritten";
121 $5 ~ /0x[[:xdigit:]]+/ {
122 flags = strtonum($5);
126 if (and(flags, 0x2000)) {
130 if (and(flags, 0x1)) {
132 flag_str = flag_str"|";
134 flag_str = flag_str"last";
136 print $1, $2, flag_str
141 # Filters fiemap output to only print the
142 # file offset column and whether or not
143 # it is an extent or a hole
144 _filter_hole_fiemap()
151 $5 ~ /0x[[:xdigit:]]+/ {
152 print $1, $2, "extent";
157 # 10000 Unwritten preallocated extent
158 # 01000 Doesn't begin on stripe unit
159 # 00100 Doesn't end on stripe unit
160 # 00010 Doesn't begin on stripe width
161 # 00001 Doesn't end on stripe width
169 $7 ~ /1[01][01][01][01]/ {
170 print $1, $2, "unwritten";
173 $7 ~ /0[01][01][01][01]/ {
185 # test the different corner cases for zeroing a range:
188 # 2. into allocated space
189 # 3. into unwritten space
191 # 5. hole -> unwritten
193 # 7. data -> unwritten
194 # 8. unwritten -> hole
195 # 9. unwritten -> data
196 # 10. hole -> data -> hole
197 # 11. data -> hole -> data
198 # 12. unwritten -> data -> unwritten
199 # 13. data -> unwritten -> data
200 # 14. data -> hole @ EOF
201 # 15. data -> hole @ 0
202 # 16. data -> cache cold ->hole
203 # 17. data -> hole in single block file
205 # Test file is removed, created and sync'd between tests.
207 # Use -k flag to keep the file between tests. This will
208 # test the handling of pre-existing holes.
210 # Use the -d flag to not sync the file between tests.
211 # This will test the handling of delayed extents
213 # Use the -u flag to not run unwritten tests.
214 # This will eliminate some unnecessary information.
216 _test_generic_punch()
223 while getopts 'dku' OPTION
237 shift $(($OPTIND - 1))
241 zero_cmd=$3 #if not testing zero just set to punch
246 # The punch hole tests needs multiple of the largest extent size being
247 # tested, with multiple=16 it can test extent size upto 64k.
249 _4k="$((multiple * 4))k"
250 _8k="$((multiple * 8))k"
251 _12k="$((multiple * 12))k"
252 _20k="$((multiple * 20))k"
254 # initial test state must be defined, otherwise the first test can fail
255 # due ot stale file state left from previous tests.
258 echo " 1. into a hole"
259 $XFS_IO_PROG -f -c "truncate $_20k" \
260 -c "$zero_cmd $_4k $_8k" \
261 -c "$map_cmd -v" $testfile | $filter_cmd
262 [ $? -ne 0 ] && die_now
263 _md5_checksum $testfile
265 echo " 2. into allocated space"
266 if [ "$remove_testfile" ]; then
269 $XFS_IO_PROG -f -c "truncate $_20k" \
270 -c "pwrite 0 $_20k" $sync_cmd \
271 -c "$zero_cmd $_4k $_8k" \
272 -c "$map_cmd -v" $testfile | $filter_cmd
273 [ $? -ne 0 ] && die_now
274 _md5_checksum $testfile
276 if [ "$unwritten_tests" ]; then
277 echo " 3. into unwritten space"
278 if [ "$remove_testfile" ]; then
281 $XFS_IO_PROG -f -c "truncate $_20k" \
282 -c "$alloc_cmd 0 $_20k" \
283 -c "$zero_cmd $_4k $_8k" \
284 -c "$map_cmd -v" $testfile | $filter_cmd
285 [ $? -ne 0 ] && die_now
286 _md5_checksum $testfile
289 echo " 4. hole -> data"
290 if [ "$remove_testfile" ]; then
293 $XFS_IO_PROG -f -c "truncate $_20k" \
294 -c "pwrite $_8k $_8k" $sync_cmd \
295 -c "$zero_cmd $_4k $_8k" \
296 -c "$map_cmd -v" $testfile | $filter_cmd
297 [ $? -ne 0 ] && die_now
298 _md5_checksum $testfile
300 if [ "$unwritten_tests" ]; then
301 echo " 5. hole -> unwritten"
302 if [ "$remove_testfile" ]; then
305 $XFS_IO_PROG -f -c "truncate $_20k" \
306 -c "$alloc_cmd $_8k $_8k" \
307 -c "$zero_cmd $_4k $_8k" \
308 -c "$map_cmd -v" $testfile | $filter_cmd
309 [ $? -ne 0 ] && die_now
310 _md5_checksum $testfile
313 echo " 6. data -> hole"
314 if [ "$remove_testfile" ]; then
317 $XFS_IO_PROG -f -c "truncate $_20k" \
318 -c "pwrite 0 $_8k" $sync_cmd \
319 -c "$zero_cmd $_4k $_8k" \
320 -c "$map_cmd -v" $testfile | $filter_cmd
321 [ $? -ne 0 ] && die_now
322 _md5_checksum $testfile
324 if [ "$unwritten_tests" ]; then
325 echo " 7. data -> unwritten"
326 if [ "$remove_testfile" ]; then
329 $XFS_IO_PROG -f -c "truncate $_20k" \
330 -c "pwrite 0 $_8k" $sync_cmd \
331 -c "$alloc_cmd $_8k $_8k" \
332 -c "$zero_cmd $_4k $_8k" \
333 -c "$map_cmd -v" $testfile | $filter_cmd
334 [ $? -ne 0 ] && die_now
335 _md5_checksum $testfile
337 echo " 8. unwritten -> hole"
338 if [ "$remove_testfile" ]; then
341 $XFS_IO_PROG -f -c "truncate $_20k" \
342 -c "$alloc_cmd 0 $_8k" \
343 -c "$zero_cmd $_4k $_8k" \
344 -c "$map_cmd -v" $testfile | $filter_cmd
345 [ $? -ne 0 ] && die_now
346 _md5_checksum $testfile
348 echo " 9. unwritten -> data"
349 if [ "$remove_testfile" ]; then
352 $XFS_IO_PROG -f -c "truncate $_20k" \
353 -c "$alloc_cmd 0 $_8k" \
354 -c "pwrite $_8k $_8k" $sync_cmd \
355 -c "$zero_cmd $_4k $_8k" \
356 -c "$map_cmd -v" $testfile | $filter_cmd
357 [ $? -ne 0 ] && die_now
358 _md5_checksum $testfile
361 echo " 10. hole -> data -> hole"
362 if [ "$remove_testfile" ]; then
365 $XFS_IO_PROG -f -c "truncate $_20k" \
366 -c "pwrite $_8k $_4k" $sync_cmd \
367 -c "$zero_cmd $_4k $_12k" \
368 -c "$map_cmd -v" $testfile | $filter_cmd
369 [ $? -ne 0 ] && die_now
370 _md5_checksum $testfile
372 echo " 11. data -> hole -> data"
373 if [ "$remove_testfile" ]; then
376 $XFS_IO_PROG -f -c "truncate $_20k" \
377 -c "$alloc_cmd 0 $_20k" \
379 -c "pwrite $_12k $_8k" $sync_cmd \
380 -c "$punch_cmd $_8k $_4k" \
381 -c "$zero_cmd $_4k $_12k" \
382 -c "$map_cmd -v" $testfile | $filter_cmd
383 [ $? -ne 0 ] && die_now
384 _md5_checksum $testfile
386 if [ "$unwritten_tests" ]; then
387 echo " 12. unwritten -> data -> unwritten"
388 if [ "$remove_testfile" ]; then
391 $XFS_IO_PROG -f -c "truncate $_20k" \
392 -c "$alloc_cmd 0 $_20k" \
393 -c "pwrite $_8k $_4k" $sync_cmd \
394 -c "$zero_cmd $_4k $_12k" \
395 -c "$map_cmd -v" $testfile | $filter_cmd
396 [ $? -ne 0 ] && die_now
397 _md5_checksum $testfile
399 echo " 13. data -> unwritten -> data"
400 if [ "$remove_testfile" ]; then
403 $XFS_IO_PROG -f -c "truncate $_20k" \
404 -c "$alloc_cmd 0 $_20k" \
405 -c "pwrite 0k $_4k" $sync_cmd \
406 -c "pwrite $_12k $_8k" -c "fsync" \
407 -c "$zero_cmd $_4k $_12k" \
408 -c "$map_cmd -v" $testfile | $filter_cmd
409 [ $? -ne 0 ] && die_now
410 _md5_checksum $testfile
413 # Don't need to check EOF case for collapse range.
414 # VFS layer return invalid error in this case,
415 # So it is not a proper case for collapse range test of each local fs.
416 if [ "$zero_cmd" != "fcollapse" ]; then
417 echo " 14. data -> hole @ EOF"
419 $XFS_IO_PROG -f -c "truncate $_20k" \
420 -c "pwrite 0 $_20k" $sync_cmd \
421 -c "$zero_cmd $_12k $_8k" \
422 -c "$map_cmd -v" $testfile | $filter_cmd
423 [ $? -ne 0 ] && die_now
424 _md5_checksum $testfile
427 if [ "$zero_cmd" == "fcollapse" ]; then
428 echo " 14. data -> hole @ 0"
430 echo " 15. data -> hole @ 0"
433 if [ "$remove_testfile" ]; then
436 $XFS_IO_PROG -f -c "truncate $_20k" \
437 -c "pwrite 0 $_20k" $sync_cmd \
438 -c "$zero_cmd 0 $_8k" \
439 -c "$map_cmd -v" $testfile | $filter_cmd
440 [ $? -ne 0 ] && die_now
441 _md5_checksum $testfile
443 # If zero_cmd is fcollpase, don't check unaligned offsets
444 if [ "$zero_cmd" == "fcollapse" ]; then
448 # If zero_cmd is finsert, don't check unaligned offsets
449 if [ "$zero_cmd" == "finsert" ]; then
453 echo " 16. data -> cache cold ->hole"
454 if [ "$remove_testfile" ]; then
458 cp $testfile $testfile.2
460 $XFS_IO_PROG -f -c "truncate $_20k" \
461 -c "pwrite $_8k $_12k" -c "fsync" $testfile.2 \
463 $XFS_IO_PROG -f -c "truncate $_20k" \
464 -c "pwrite 0 $_20k" $sync_cmd \
465 -c "$zero_cmd 0k $_8k" \
467 -c "$map_cmd -v" $testfile | $filter_cmd
468 diff $testfile $testfile.2
469 [ $? -ne 0 ] && die_now
471 _md5_checksum $testfile
473 # different file sizes mean we can't use md5sum to check the hole is
474 # valid. Hence use hexdump to dump the contents and chop off the last
475 # line of output that indicates the file size. We also have to fudge
476 # the extent size as that will change with file size, too - that's what
477 # the sed line noise does - it will always result in an output of [0..7]
478 # so it matches 4k block size...
479 echo " 17. data -> hole in single block file"
480 if [ "$remove_testfile" ]; then
483 block_size=`_get_block_size $TEST_DIR`
484 $XFS_IO_PROG -f -c "truncate $block_size" \
485 -c "pwrite 0 $block_size" $sync_cmd \
486 -c "$zero_cmd 128 128" \
487 -c "$map_cmd -v" $testfile | $filter_cmd | \
488 sed -e "s/\.\.[0-9]*\]/..7\]/"
489 [ $? -ne 0 ] && die_now
490 od -x $testfile | head -n -1
493 _test_block_boundaries()
500 while getopts 'dk' OPTION
512 shift $(($OPTIND - 1))
527 # Block size multiplied by 2
530 # Block size divided by 2
534 $XFS_IO_PROG -f -t -c "pwrite -S 0x41 0 $bs" \
535 -c "pwrite -S 0x42 $bs $bs" \
537 -c "pread -v 0 $bs_t2" \
538 $testfile | $filter_cmd
540 echo "zero 0, $bs_m1"
541 $XFS_IO_PROG -f -t -c "pwrite -S 0x41 0 $bs" \
542 -c "pwrite -S 0x42 $bs $bs" \
543 -c "$zero_cmd 0 $bs_m1" \
544 -c "pread -v 0 $bs_t2" \
545 $testfile | $filter_cmd
548 $XFS_IO_PROG -f -t -c "pwrite -S 0x41 0 $bs" \
549 -c "pwrite -S 0x42 $bs $bs" \
550 -c "$zero_cmd 0 $bs" \
551 -c "pread -v 0 $bs_t2" \
552 $testfile | $filter_cmd
554 echo "zero 0, $bs_p1"
555 $XFS_IO_PROG -f -t -c "pwrite -S 0x41 0 $bs" \
556 -c "pwrite -S 0x42 $bs $bs" \
557 -c "$zero_cmd 0 $bs_p1" \
558 -c "pread -v 0 $bs_t2" \
559 $testfile | $filter_cmd
561 echo "zero $bs_m1, $bs"
562 $XFS_IO_PROG -f -t -c "pwrite -S 0x41 0 $bs" \
563 -c "pwrite -S 0x42 $bs $bs" \
564 -c "$zero_cmd $bs_m1 $bs" \
565 -c "pread -v 0 $bs_t2" \
566 $testfile | $filter_cmd
568 echo "zero $bs_m1, $bs_p1"
569 $XFS_IO_PROG -f -t -c "pwrite -S 0x41 0 $bs" \
570 -c "pwrite -S 0x42 $bs $bs" \
571 -c "$zero_cmd $bs_m1 $bs_p1" \
572 -c "pread -v 0 $bs_t2" \
573 $testfile | $filter_cmd
575 echo "zero $bs_m1, $bs_p2"
576 $XFS_IO_PROG -f -t -c "pwrite -S 0x41 0 $bs" \
577 -c "pwrite -S 0x42 $bs $bs" \
578 -c "$zero_cmd $bs_m1 $bs_p2" \
579 -c "pread -v 0 $bs_t2" \
580 $testfile | $filter_cmd
584 $XFS_IO_PROG -f -t -c "pwrite -S 0x41 0 $bs" \
585 -c "pwrite -S 0x42 $bs $bs" \
586 -c "$zero_cmd $bs $bs" \
587 -c "pread -v 0 $bs_t2" \
588 $testfile | $filter_cmd
591 echo "zero $bs_d2 , $bs"
592 $XFS_IO_PROG -f -t -c "pwrite -S 0x41 0 $bs" \
593 -c "pwrite -S 0x42 $bs $bs" \
594 -c "$zero_cmd $bs_d2 $bs" \
595 -c "pread -v 0 $bs_t2" \
596 $testfile | $filter_cmd