generic: Test that SEEK_HOLE can find a punched hole

Added a test case to seek_sanity_test and a test to run it.

Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Reviewed-by: Eryu Guan <guaneryu@gmail.com>
Signed-off-by: Eryu Guan <guaneryu@gmail.com>
This commit is contained in:
Amir Goldstein
2019-04-03 08:59:26 +03:00
committed by Eryu Guan
parent 3408108774
commit f3c1bca7fb
4 changed files with 108 additions and 4 deletions
+59 -4
View File
@@ -16,6 +16,7 @@
#include <unistd.h> #include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
#include <assert.h> #include <assert.h>
#include "global.h"
#ifndef SEEK_DATA #ifndef SEEK_DATA
#define SEEK_DATA 3 #define SEEK_DATA 3
@@ -26,6 +27,7 @@ static blksize_t alloc_size;
int allow_default_behavior = 1; int allow_default_behavior = 1;
int default_behavior = 0; int default_behavior = 0;
int unwritten_extents = 0; int unwritten_extents = 0;
int punch_hole = 0;
char *base_file_path; char *base_file_path;
static void get_file_system(int fd) static void get_file_system(int fd)
@@ -118,8 +120,9 @@ static int do_fallocate(int fd, off_t offset, off_t length, int mode)
ret = fallocate(fd, mode, offset, length); ret = fallocate(fd, mode, offset, length);
if (ret) if (ret)
fprintf(stderr, " ERROR %d: Failed to preallocate " fprintf(stderr, " ERROR %d: Failed to %s of %ld bytes\n",
"space to %ld bytes\n", errno, (long) length); errno, (mode & FALLOC_FL_PUNCH_HOLE) ? "punch hole" :
"preallocate space", (long) length);
return ret; return ret;
} }
@@ -262,6 +265,52 @@ out:
return ret; return ret;
} }
/*
* Make sure hole size is properly reported when punched in the middle of a file
*/
static int test21(int fd, int testnum)
{
char *buf = NULL;
int bufsz, filsz;
int ret = 0;
if (!punch_hole) {
fprintf(stdout, "Test skipped as fs doesn't support punch hole.\n");
goto out;
}
if (default_behavior) {
fprintf(stdout, "Test skipped as fs doesn't support seeking a punched hole.\n");
goto out;
}
bufsz = alloc_size * 3;
buf = do_malloc(bufsz);
if (!buf) {
ret = -1;
goto out;
}
memset(buf, 'a', bufsz);
ret = do_pwrite(fd, buf, bufsz, 0);
if (ret)
goto out;
filsz = bufsz;
ret = do_fallocate(fd, alloc_size, alloc_size,
FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE);
if (ret < 0)
goto out;
ret += do_lseek(testnum, 1, fd, filsz, SEEK_DATA, 0, 0);
ret += do_lseek(testnum, 2, fd, filsz, SEEK_HOLE, 0, alloc_size);
ret += do_lseek(testnum, 3, fd, filsz, SEEK_DATA, alloc_size, alloc_size * 2);
out:
if (buf)
free(buf);
return ret;
}
/* /*
* Make sure hole size is properly reported when starting in the middle of a * Make sure hole size is properly reported when starting in the middle of a
* hole in ext? doubly indirect tree * hole in ext? doubly indirect tree
@@ -1050,6 +1099,7 @@ struct testrec seek_tests[] = {
{ 18, test18, "Test file with negative SEEK_{HOLE,DATA} offsets" }, { 18, test18, "Test file with negative SEEK_{HOLE,DATA} offsets" },
{ 19, test19, "Test file SEEK_DATA from middle of a large hole" }, { 19, test19, "Test file SEEK_DATA from middle of a large hole" },
{ 20, test20, "Test file SEEK_DATA from middle of a huge hole" }, { 20, test20, "Test file SEEK_DATA from middle of a huge hole" },
{ 21, test21, "Test file SEEK_HOLE that was created by PUNCH_HOLE" },
}; };
static int run_test(struct testrec *tr) static int run_test(struct testrec *tr)
@@ -1127,15 +1177,20 @@ static int test_basic_support(void)
} }
ftruncate(fd, 0); ftruncate(fd, 0);
if (fallocate(fd, 0, 0, alloc_size) == -1) { if (fallocate(fd, 0, 0, alloc_size * 2) == -1) {
if (errno == EOPNOTSUPP) if (errno == EOPNOTSUPP)
fprintf(stderr, "File system does not support fallocate."); fprintf(stderr, "File system does not support fallocate.\n");
else { else {
fprintf(stderr, "ERROR %d: Failed to preallocate " fprintf(stderr, "ERROR %d: Failed to preallocate "
"space to %ld bytes. Aborting.\n", errno, (long) alloc_size); "space to %ld bytes. Aborting.\n", errno, (long) alloc_size);
ret = -1; ret = -1;
} }
goto out; goto out;
} else if (fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
0, alloc_size) == -1) {
fprintf(stderr, "File system does not support punch hole.\n");
} else {
punch_hole = 1;
} }
pos = lseek(fd, 0, SEEK_DATA); pos = lseek(fd, 0, SEEK_DATA);
+46
View File
@@ -0,0 +1,46 @@
#! /bin/bash
# SPDX-License-Identifier: GPL-2.0
# Copyright (C) 2019, CTERA Networks. All Rights Reserved.
#
# FS QA Test No. 539
#
# Check that SEEK_HOLE can find a punched hole.
#
seq=`basename $0`
seqres=$RESULT_DIR/$seq
echo "QA output created by $seq"
here=`pwd`
tmp=/tmp/$$
status=1 # failure is the default!
trap "_cleanup; exit \$status" 0 1 2 3 15
# get standard environment, filters and checks
. ./common/rc
_supported_fs generic
_supported_os Linux
_require_test
_require_seek_data_hole
_require_xfs_io_command "fpunch"
base_test_file=$TEST_DIR/seek_sanity_testfile.$seq
_require_test_program "seek_sanity_test"
_cleanup()
{
cd /
rm -f $tmp.*
rm -f $base_test_file*
}
echo "Silence is golden"
_run_seek_sanity_test -s 21 -e 21 $base_test_file > $seqres.full 2>&1 ||
_fail "seek sanity check failed!"
# success, all done
status=0
exit
+2
View File
@@ -0,0 +1,2 @@
QA output created by 539
Silence is golden
+1
View File
@@ -541,3 +541,4 @@
536 auto quick rw shutdown 536 auto quick rw shutdown
537 auto quick trim 537 auto quick trim
538 auto quick aio 538 auto quick aio
539 auto quick punch seek