diff --git a/test/zdtm/static/Makefile b/test/zdtm/static/Makefile index edac92c83..000488133 100644 --- a/test/zdtm/static/Makefile +++ b/test/zdtm/static/Makefile @@ -308,6 +308,8 @@ TST_FILE = \ ghost_holes02 \ ghost_holes_large00 \ ghost_holes_large01 \ + ghost_multi_hole00 \ + ghost_multi_hole01 \ unlink_largefile \ mtime_mmap \ fifo \ diff --git a/test/zdtm/static/ghost_multi_hole00.c b/test/zdtm/static/ghost_multi_hole00.c new file mode 100644 index 000000000..0f78d4f14 --- /dev/null +++ b/test/zdtm/static/ghost_multi_hole00.c @@ -0,0 +1,122 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "zdtmtst.h" + +const char *test_doc = "Test ghost with a lot of holes(every 8K length contains only 4K data)"; +const char *test_author = "Liang-Chun Chen "; + +char *filename; +TEST_OPTION(filename, string, "file name", 1); + +/* Buffer that is suitable for hole size */ +#define BUFSIZE 4096 +static unsigned char buf4k[BUFSIZE]; + +#ifndef SEEK_DATA +#define SEEK_DATA 3 +#define SEEK_HOLE 4 +#endif + +#define FILE_SIZE (1 << 23) /* 8Mb */ + +#define FILE_INTERVAL (1 << 13) /* 8Kb */ + +int main(int argc, char **argv) +{ + int fd, off; + struct stat st; + uint32_t crc; + + test_init(argc, argv); + + fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, 0644); + if (fd < 0) { + pr_perror("can't open %s", filename); + exit(1); + } + + if (unlink(filename) < 0) { + pr_perror("can't unlink %s", filename); + goto failed; + } + + for (off = 0; off < FILE_SIZE; off += FILE_INTERVAL) { + crc = ~0; + datagen(buf4k, BUFSIZE, &crc); + if (pwrite(fd, &buf4k, BUFSIZE, off) != BUFSIZE) { + perror("pwrite"); + goto failed; + } + + /* + * In some file system, such as xfs, + * only pwrite might not able to create highly sparse file, + * so we need to forcibly allocate hole inside the file. + */ + if (fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, off + BUFSIZE, BUFSIZE)) { + perror("fallocate"); + goto failed; + } + } + + if (ftruncate(fd, FILE_SIZE)) { + pr_perror("Can't fixup file size"); + goto failed; + } + + test_daemon(); + test_waitsig(); + + if (fstat(fd, &st) < 0) { + fail("can't stat after"); + goto failed; + } + + if (st.st_size != FILE_SIZE) { + fail("file size changed to %ld", (long)st.st_size); + goto failed; + } + + test_msg("Size %u OK\n", FILE_SIZE); + + /* Data*/ + for (off = 0; off < FILE_SIZE; off += FILE_INTERVAL) { + if (pread(fd, buf4k, BUFSIZE, off) != BUFSIZE) { + fail("pread failed @ %u", off / FILE_INTERVAL); + goto failed; + } + + crc = ~0; + if (datachk(buf4k, BUFSIZE, &crc)) { + fail("datachk failed @ %u", off / FILE_INTERVAL); + goto failed; + } + + test_msg("Data @%du OK\n", off / FILE_INTERVAL); + } + + /* Hole */ + for (off = 0; off < FILE_SIZE; off += FILE_INTERVAL) { + if (lseek(fd, off, SEEK_HOLE) != off + BUFSIZE) { + fail("failed to find hole @ %u", off / FILE_SIZE); + goto failed; + } + test_msg("Hole @%du OK\n", off / FILE_INTERVAL); + } + + close(fd); + pass(); + return 0; + +failed: + close(fd); + return 1; +} diff --git a/test/zdtm/static/ghost_multi_hole00.desc b/test/zdtm/static/ghost_multi_hole00.desc new file mode 100644 index 000000000..3981e8180 --- /dev/null +++ b/test/zdtm/static/ghost_multi_hole00.desc @@ -0,0 +1 @@ +{'dopts': '--ghost-limit 8M --no-ghost-fiemap'} diff --git a/test/zdtm/static/ghost_multi_hole01.c b/test/zdtm/static/ghost_multi_hole01.c new file mode 120000 index 000000000..c75006a6b --- /dev/null +++ b/test/zdtm/static/ghost_multi_hole01.c @@ -0,0 +1 @@ +ghost_multi_hole00.c \ No newline at end of file diff --git a/test/zdtm/static/ghost_multi_hole01.desc b/test/zdtm/static/ghost_multi_hole01.desc new file mode 100644 index 000000000..d1dc68a54 --- /dev/null +++ b/test/zdtm/static/ghost_multi_hole01.desc @@ -0,0 +1 @@ +{'dopts': '--ghost-limit 8M --ghost-fiemap'}