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:]]+/ {
127 # Filters fiemap output to only print the
128 # file offset column and whether or not
129 # it is an extent or a hole
130 _filter_hole_fiemap()
137 $5 ~ /0x[[:xdigit:]]+/ {
138 print $1, $2, "extent";
143 # 10000 Unwritten preallocated extent
144 # 01000 Doesn't begin on stripe unit
145 # 00100 Doesn't end on stripe unit
146 # 00010 Doesn't begin on stripe width
147 # 00001 Doesn't end on stripe width
155 $7 ~ /1[01][01][01][01]/ {
156 print $1, $2, "unwritten";
159 $7 ~ /0[01][01][01][01]/ {
171 # test the different corner cases for zeroing a range:
174 # 2. into allocated space
175 # 3. into unwritten space
177 # 5. hole -> unwritten
179 # 7. data -> unwritten
180 # 8. unwritten -> hole
181 # 9. unwritten -> data
182 # 10. hole -> data -> hole
183 # 11. data -> hole -> data
184 # 12. unwritten -> data -> unwritten
185 # 13. data -> unwritten -> data
186 # 14. data -> hole @ EOF
187 # 15. data -> hole @ 0
188 # 16. data -> cache cold ->hole
189 # 17. data -> hole in single block file
191 # Test file is removed, created and sync'd between tests.
193 # Use -k flag to keep the file between tests. This will
194 # test the handling of pre-existing holes.
196 # Use the -d flag to not sync the file between tests.
197 # This will test the handling of delayed extents
199 # Use the -u flag to not run unwritten tests.
200 # This will eliminate some unnecessary information.
202 _test_generic_punch()
209 while getopts 'dku' OPTION
223 shift $(($OPTIND - 1))
227 zero_cmd=$3 #if not testing zero just set to punch
232 # The punch hole tests needs multiple of the largest extent size being
233 # tested, with multiple=16 it can test extent size upto 64k.
235 _4k="$((multiple * 4))k"
236 _8k="$((multiple * 8))k"
237 _12k="$((multiple * 12))k"
238 _20k="$((multiple * 20))k"
240 # initial test state must be defined, otherwise the first test can fail
241 # due ot stale file state left from previous tests.
244 echo " 1. into a hole"
245 $XFS_IO_PROG -f -c "truncate $_20k" \
246 -c "$zero_cmd $_4k $_8k" \
247 -c "$map_cmd -v" $testfile | $filter_cmd
248 [ $? -ne 0 ] && die_now
249 _md5_checksum $testfile
251 echo " 2. into allocated space"
252 if [ "$remove_testfile" ]; then
255 $XFS_IO_PROG -f -c "truncate $_20k" \
256 -c "pwrite 0 $_20k" $sync_cmd \
257 -c "$zero_cmd $_4k $_8k" \
258 -c "$map_cmd -v" $testfile | $filter_cmd
259 [ $? -ne 0 ] && die_now
260 _md5_checksum $testfile
262 if [ "$unwritten_tests" ]; then
263 echo " 3. into unwritten space"
264 if [ "$remove_testfile" ]; then
267 $XFS_IO_PROG -f -c "truncate $_20k" \
268 -c "$alloc_cmd 0 $_20k" \
269 -c "$zero_cmd $_4k $_8k" \
270 -c "$map_cmd -v" $testfile | $filter_cmd
271 [ $? -ne 0 ] && die_now
272 _md5_checksum $testfile
275 echo " 4. hole -> data"
276 if [ "$remove_testfile" ]; then
279 $XFS_IO_PROG -f -c "truncate $_20k" \
280 -c "pwrite $_8k $_8k" $sync_cmd \
281 -c "$zero_cmd $_4k $_8k" \
282 -c "$map_cmd -v" $testfile | $filter_cmd
283 [ $? -ne 0 ] && die_now
284 _md5_checksum $testfile
286 if [ "$unwritten_tests" ]; then
287 echo " 5. hole -> unwritten"
288 if [ "$remove_testfile" ]; then
291 $XFS_IO_PROG -f -c "truncate $_20k" \
292 -c "$alloc_cmd $_8k $_8k" \
293 -c "$zero_cmd $_4k $_8k" \
294 -c "$map_cmd -v" $testfile | $filter_cmd
295 [ $? -ne 0 ] && die_now
296 _md5_checksum $testfile
299 echo " 6. data -> hole"
300 if [ "$remove_testfile" ]; then
303 $XFS_IO_PROG -f -c "truncate $_20k" \
304 -c "pwrite 0 $_8k" $sync_cmd \
305 -c "$zero_cmd $_4k $_8k" \
306 -c "$map_cmd -v" $testfile | $filter_cmd
307 [ $? -ne 0 ] && die_now
308 _md5_checksum $testfile
310 if [ "$unwritten_tests" ]; then
311 echo " 7. data -> unwritten"
312 if [ "$remove_testfile" ]; then
315 $XFS_IO_PROG -f -c "truncate $_20k" \
316 -c "pwrite 0 $_8k" $sync_cmd \
317 -c "$alloc_cmd $_8k $_8k" \
318 -c "$zero_cmd $_4k $_8k" \
319 -c "$map_cmd -v" $testfile | $filter_cmd
320 [ $? -ne 0 ] && die_now
321 _md5_checksum $testfile
323 echo " 8. unwritten -> hole"
324 if [ "$remove_testfile" ]; then
327 $XFS_IO_PROG -f -c "truncate $_20k" \
328 -c "$alloc_cmd 0 $_8k" \
329 -c "$zero_cmd $_4k $_8k" \
330 -c "$map_cmd -v" $testfile | $filter_cmd
331 [ $? -ne 0 ] && die_now
332 _md5_checksum $testfile
334 echo " 9. unwritten -> data"
335 if [ "$remove_testfile" ]; then
338 $XFS_IO_PROG -f -c "truncate $_20k" \
339 -c "$alloc_cmd 0 $_8k" \
340 -c "pwrite $_8k $_8k" $sync_cmd \
341 -c "$zero_cmd $_4k $_8k" \
342 -c "$map_cmd -v" $testfile | $filter_cmd
343 [ $? -ne 0 ] && die_now
344 _md5_checksum $testfile
347 echo " 10. hole -> data -> hole"
348 if [ "$remove_testfile" ]; then
351 $XFS_IO_PROG -f -c "truncate $_20k" \
352 -c "pwrite $_8k $_4k" $sync_cmd \
353 -c "$zero_cmd $_4k $_12k" \
354 -c "$map_cmd -v" $testfile | $filter_cmd
355 [ $? -ne 0 ] && die_now
356 _md5_checksum $testfile
358 echo " 11. data -> hole -> data"
359 if [ "$remove_testfile" ]; then
362 $XFS_IO_PROG -f -c "truncate $_20k" \
363 -c "$alloc_cmd 0 $_20k" \
365 -c "pwrite $_12k $_8k" $sync_cmd \
366 -c "$punch_cmd $_8k $_4k" \
367 -c "$zero_cmd $_4k $_12k" \
368 -c "$map_cmd -v" $testfile | $filter_cmd
369 [ $? -ne 0 ] && die_now
370 _md5_checksum $testfile
372 if [ "$unwritten_tests" ]; then
373 echo " 12. unwritten -> data -> unwritten"
374 if [ "$remove_testfile" ]; then
377 $XFS_IO_PROG -f -c "truncate $_20k" \
378 -c "$alloc_cmd 0 $_20k" \
379 -c "pwrite $_8k $_4k" $sync_cmd \
380 -c "$zero_cmd $_4k $_12k" \
381 -c "$map_cmd -v" $testfile | $filter_cmd
382 [ $? -ne 0 ] && die_now
383 _md5_checksum $testfile
385 echo " 13. data -> unwritten -> data"
386 if [ "$remove_testfile" ]; then
389 $XFS_IO_PROG -f -c "truncate $_20k" \
390 -c "$alloc_cmd 0 $_20k" \
391 -c "pwrite 0k $_4k" $sync_cmd \
392 -c "pwrite $_12k $_8k" -c "fsync" \
393 -c "$zero_cmd $_4k $_12k" \
394 -c "$map_cmd -v" $testfile | $filter_cmd
395 [ $? -ne 0 ] && die_now
396 _md5_checksum $testfile
399 # Don't need to check EOF case for collapse range.
400 # VFS layer return invalid error in this case,
401 # So it is not a proper case for collapse range test of each local fs.
402 if [ "$zero_cmd" != "fcollapse" ]; then
403 echo " 14. data -> hole @ EOF"
405 $XFS_IO_PROG -f -c "truncate $_20k" \
406 -c "pwrite 0 $_20k" $sync_cmd \
407 -c "$zero_cmd $_12k $_8k" \
408 -c "$map_cmd -v" $testfile | $filter_cmd
409 [ $? -ne 0 ] && die_now
410 _md5_checksum $testfile
413 if [ "$zero_cmd" == "fcollapse" ]; then
414 echo " 14. data -> hole @ 0"
416 echo " 15. data -> hole @ 0"
419 if [ "$remove_testfile" ]; then
422 $XFS_IO_PROG -f -c "truncate $_20k" \
423 -c "pwrite 0 $_20k" $sync_cmd \
424 -c "$zero_cmd 0 $_8k" \
425 -c "$map_cmd -v" $testfile | $filter_cmd
426 [ $? -ne 0 ] && die_now
427 _md5_checksum $testfile
429 # If zero_cmd is fcollpase, don't check unaligned offsets
430 if [ "$zero_cmd" == "fcollapse" ]; then
434 # If zero_cmd is finsert, don't check unaligned offsets
435 if [ "$zero_cmd" == "finsert" ]; then
439 echo " 16. data -> cache cold ->hole"
440 if [ "$remove_testfile" ]; then
444 cp $testfile $testfile.2
446 $XFS_IO_PROG -f -c "truncate $_20k" \
447 -c "pwrite $_8k $_12k" -c "fsync" $testfile.2 \
449 $XFS_IO_PROG -f -c "truncate $_20k" \
450 -c "pwrite 0 $_20k" $sync_cmd \
451 -c "$zero_cmd 0k $_8k" \
453 -c "$map_cmd -v" $testfile | $filter_cmd
454 diff $testfile $testfile.2
455 [ $? -ne 0 ] && die_now
457 _md5_checksum $testfile
459 # different file sizes mean we can't use md5sum to check the hole is
460 # valid. Hence use hexdump to dump the contents and chop off the last
461 # line of output that indicates the file size. We also have to fudge
462 # the extent size as that will change with file size, too - that's what
463 # the sed line noise does - it will always result in an output of [0..7]
464 # so it matches 4k block size...
465 echo " 17. data -> hole in single block file"
466 if [ "$remove_testfile" ]; then
469 block_size=`_get_block_size $TEST_DIR`
470 $XFS_IO_PROG -f -c "truncate $block_size" \
471 -c "pwrite 0 $block_size" $sync_cmd \
472 -c "$zero_cmd 128 128" \
473 -c "$map_cmd -v" $testfile | $filter_cmd | \
474 sed -e "s/\.\.[0-9]*\]/..7\]/"
475 [ $? -ne 0 ] && die_now
476 od -x $testfile | head -n -1
479 _test_block_boundaries()
486 while getopts 'dk' OPTION
498 shift $(($OPTIND - 1))
513 # Block size multiplied by 2
516 # Block size divided by 2
520 $XFS_IO_PROG -f -t -c "pwrite -S 0x41 0 $bs" \
521 -c "pwrite -S 0x42 $bs $bs" \
523 -c "pread -v 0 $bs_t2" \
524 $testfile | $filter_cmd
526 echo "zero 0, $bs_m1"
527 $XFS_IO_PROG -f -t -c "pwrite -S 0x41 0 $bs" \
528 -c "pwrite -S 0x42 $bs $bs" \
529 -c "$zero_cmd 0 $bs_m1" \
530 -c "pread -v 0 $bs_t2" \
531 $testfile | $filter_cmd
534 $XFS_IO_PROG -f -t -c "pwrite -S 0x41 0 $bs" \
535 -c "pwrite -S 0x42 $bs $bs" \
536 -c "$zero_cmd 0 $bs" \
537 -c "pread -v 0 $bs_t2" \
538 $testfile | $filter_cmd
540 echo "zero 0, $bs_p1"
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_p1" \
544 -c "pread -v 0 $bs_t2" \
545 $testfile | $filter_cmd
547 echo "zero $bs_m1, $bs"
548 $XFS_IO_PROG -f -t -c "pwrite -S 0x41 0 $bs" \
549 -c "pwrite -S 0x42 $bs $bs" \
550 -c "$zero_cmd $bs_m1 $bs" \
551 -c "pread -v 0 $bs_t2" \
552 $testfile | $filter_cmd
554 echo "zero $bs_m1, $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 $bs_m1 $bs_p1" \
558 -c "pread -v 0 $bs_t2" \
559 $testfile | $filter_cmd
561 echo "zero $bs_m1, $bs_p2"
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_p2" \
565 -c "pread -v 0 $bs_t2" \
566 $testfile | $filter_cmd
570 $XFS_IO_PROG -f -t -c "pwrite -S 0x41 0 $bs" \
571 -c "pwrite -S 0x42 $bs $bs" \
572 -c "$zero_cmd $bs $bs" \
573 -c "pread -v 0 $bs_t2" \
574 $testfile | $filter_cmd
577 echo "zero $bs_d2 , $bs"
578 $XFS_IO_PROG -f -t -c "pwrite -S 0x41 0 $bs" \
579 -c "pwrite -S 0x42 $bs $bs" \
580 -c "$zero_cmd $bs_d2 $bs" \
581 -c "pread -v 0 $bs_t2" \
582 $testfile | $filter_cmd