diff --git a/src/mmap-rw-fault.c b/src/mmap-rw-fault.c index 82f9d9781e06396cc10462a95ab989d8c775d86c..161d9f7983debd7409c3ae1f6d1e456957453983 100644 --- a/src/mmap-rw-fault.c +++ b/src/mmap-rw-fault.c @@ -20,6 +20,7 @@ #include <string.h> #include <errno.h> #include <err.h> +#include <getopt.h> char *filename; unsigned int page_size; @@ -109,11 +110,29 @@ static ssize_t do_write(int fd, const void *buf, size_t count, off_t offset) return count2; } +static void usage(const char *argv0) +{ + fprintf(stderr, "Usage: %s [-2] {filename}\n", argv0); + exit(2); +} + int main(int argc, char *argv[]) { - if (argc != 2) - errx(1, "no test filename argument given"); - filename = argv[1]; + int opt, opt_2 = 0; + + while ((opt = getopt(argc, argv, "2")) != -1) { + switch(opt) { + case '2': + opt_2 = 1; + break; + default: + usage(argv[0]); + } + } + + if (optind + 1 != argc) + usage(argv[0]); + filename = argv[optind]; page_size = ret = sysconf(_SC_PAGE_SIZE); if (ret == -1) @@ -179,6 +198,14 @@ int main(int argc, char *argv[]) errx(1, "pread (D_DIRECT) from hole is broken"); done(); + if (opt_2) { + init('f', O_RDWR | O_DIRECT); + ret = do_write(fd, addr + page_size, page_size, page_size); + if (ret != page_size) + err(1, "pwrite %s (O_DIRECT): %ld != %u", filename, ret, page_size); + done(); + } + if (unlink(filename)) err(1, "unlink %s", filename); diff --git a/tests/generic/728 b/tests/generic/728 new file mode 100755 index 0000000000000000000000000000000000000000..13a88dc04f7d767b22c3d433d3f2e408d354e5fb --- /dev/null +++ b/tests/generic/728 @@ -0,0 +1,41 @@ +#! /bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Copyright (c) 2023 Red Hat, Inc. All Rights Reserved. +# +# FS QA Test 728 +# +# Trigger page faults in the same file during read and write +# +# This is generic/647 with an additional test that writes a memory-mapped page +# onto itself using direct I/O. +# +# The kernel will invalidate the page cache +# before carrying out the write, so filesystems that fault in the target page before carrying out the direct I/O write will never make any progress. +# +. ./common/preamble +_begin_fstest auto quick + +# Override the default cleanup function. +_cleanup() +{ + cd / + rm -f $tmp.* + rm -f $TEST_DIR/mmap-rw-fault.tmp +} + +# Import common functions. +. ./common/filter + +# real QA test starts here + +_supported_fs generic +_require_test +_require_odirect +_require_test_program mmap-rw-fault + +echo "Silence is golden" + +$here/src/mmap-rw-fault -2 $TEST_DIR/mmap-rw-fault.tmp + +status=$? +exit diff --git a/tests/generic/728.out b/tests/generic/728.out new file mode 100644 index 0000000000000000000000000000000000000000..ab39f45fe5da771d9029805e9b88e2f1fa6fe2d4 --- /dev/null +++ b/tests/generic/728.out @@ -0,0 +1,2 @@ +QA output created by 728 +Silence is golden