aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Gruenbacher <agruenba@redhat.com>2023-06-07 16:53:34 +0200
committerZorro Lang <zlang@kernel.org>2023-06-10 15:35:59 +0800
commit6e9aa61ef3865c27f9a2583f5ac83e40bcb08268 (patch)
tree8ec651fc56ac30873e919d1d9ebc9e5f5c3364a6
parent596db5ee91823292e64c842c64010571a3d6ca74 (diff)
downloadxfstests-dev-6e9aa61ef3865c27f9a2583f5ac83e40bcb08268.tar.gz
generic: Add mmap + DIO write test
This is the same as generic/647, but with an additional test that writes a memory-mapped page onto itself using direct I/O. For direct I/O writes, the kernel will invalidate the page cache before and after carrying out the write. This puts filesystems that fault in pages on demand and then carry out the write with page faults disabled into a position in which they will not be able to make any progress. Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> Reviewed-by: Darrick J. Wong <djwong@kernel.org> Signed-off-by: Zorro Lang <zlang@kernel.org>
-rw-r--r--src/mmap-rw-fault.c33
-rwxr-xr-xtests/generic/72942
-rw-r--r--tests/generic/729.out2
3 files changed, 74 insertions, 3 deletions
diff --git a/src/mmap-rw-fault.c b/src/mmap-rw-fault.c
index 82f9d9781e..161d9f7983 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/729 b/tests/generic/729
new file mode 100755
index 0000000000..66242ed25f
--- /dev/null
+++ b/tests/generic/729
@@ -0,0 +1,42 @@
+#! /bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (c) 2023 Red Hat, Inc. All Rights Reserved.
+#
+# FS QA Test No. 729
+#
+# 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 page and then carry out the direct I/O write
+# with page faults disabled 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/729.out b/tests/generic/729.out
new file mode 100644
index 0000000000..0f175ae2f9
--- /dev/null
+++ b/tests/generic/729.out
@@ -0,0 +1,2 @@
+QA output created by 729
+Silence is golden