From: Anand Jain <anand.jain@oracle.com>
To: fdmanana@kernel.org, fstests@vger.kernel.org
Cc: linux-btrfs@vger.kernel.org, Filipe Manana <fdmanana@suse.com>
Subject: Re: [PATCH] generic: test concurrent direct IO writes and fsync using same fd
Date: Tue, 3 Sep 2024 20:42:52 +0800 [thread overview]
Message-ID: <99345f2f-250a-4717-863c-d61d573b08cb@oracle.com> (raw)
In-Reply-To: <fa20c58b1a711d9da9899b895a5237f8737163af.1724972803.git.fdmanana@suse.com>
On 30/8/24 7:10 am, fdmanana@kernel.org wrote:
> From: Filipe Manana <fdmanana@suse.com>
>
> Test that a program that has 2 threads using the same file descriptor and
> concurrently doing direct IO writes and fsync doesn't trigger any crash
> or deadlock.
>
> This is motivated by a bug found in btrfs fixed by the following patch:
>
> "btrfs: fix race between direct IO write and fsync when using same fd"
>
> Signed-off-by: Filipe Manana <fdmanana@suse.com>
> ---
-----------------------------
FSTYP -- btrfs
PLATFORM -- Linux/aarch64 dev2 6.11.0-rc5+ #7 SMP PREEMPT_DYNAMIC
Mon Sep 2 18:46:19 +08 2024
MKFS_OPTIONS -- /dev/loop1
MOUNT_OPTIONS -- /dev/loop1 /mnt/scratch
generic/363 10s ... umount: /mnt/test: target is busy.
_check_btrfs_filesystem: filesystem on /dev/loop0 is inconsistent
(see /Volumes/work/ws/fstests/results//generic/363.full for details)
Trying to repair broken TEST_DEV file system
_check_dmesg: something found in dmesg (see
/Volumes/work/ws/fstests/results//generic/363.dmesg)
-----------------------------
I managed to reproduce it in two iterations.
For now, the test case is fine as it is without the require_debug part,
since it doesn’t always reproduce every time even with it.
Reviewed-by: Anand Jain <anand.jain@oracle.com>
Thanks, Anand
> .gitignore | 1 +
> src/Makefile | 2 +-
> src/dio-write-fsync-same-fd.c | 106 ++++++++++++++++++++++++++++++++++
> tests/generic/363 | 30 ++++++++++
> tests/generic/363.out | 2 +
> 5 files changed, 140 insertions(+), 1 deletion(-)
> create mode 100644 src/dio-write-fsync-same-fd.c
> create mode 100755 tests/generic/363
> create mode 100644 tests/generic/363.out
>
> diff --git a/.gitignore b/.gitignore
> index 36083e9d..57519263 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -76,6 +76,7 @@ tags
> /src/dio-buf-fault
> /src/dio-interleaved
> /src/dio-invalidate-cache
> +/src/dio-write-fsync-same-fd
> /src/dirhash_collide
> /src/dirperf
> /src/dirstress
> diff --git a/src/Makefile b/src/Makefile
> index b3da59a0..b9ad6b5f 100644
> --- a/src/Makefile
> +++ b/src/Makefile
> @@ -20,7 +20,7 @@ TARGETS = dirstress fill fill2 getpagesize holes lstat64 \
> t_get_file_time t_create_short_dirs t_create_long_dirs t_enospc \
> t_mmap_writev_overlap checkpoint_journal mmap-rw-fault allocstale \
> t_mmap_cow_memory_failure fake-dump-rootino dio-buf-fault rewinddir-test \
> - readdir-while-renames dio-append-buf-fault
> + readdir-while-renames dio-append-buf-fault dio-write-fsync-same-fd
>
> LINUX_TARGETS = xfsctl bstat t_mtab getdevicesize preallo_rw_pattern_reader \
> preallo_rw_pattern_writer ftrunc trunc fs_perms testx looptest \
> diff --git a/src/dio-write-fsync-same-fd.c b/src/dio-write-fsync-same-fd.c
> new file mode 100644
> index 00000000..79472a9e
> --- /dev/null
> +++ b/src/dio-write-fsync-same-fd.c
> @@ -0,0 +1,106 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2024 SUSE Linux Products GmbH. All Rights Reserved.
> + */
> +
> +/*
> + * Test two threads working with the same file descriptor, one doing direct IO
> + * writes into the file and the other just doing fsync calls. We want to verify
> + * that there are no crashes or deadlocks.
> + *
> + * This program never finishes, it starts two infinite loops to write and fsync
> + * the file. It's meant to be called with the 'timeout' program from coreutils.
> + */
> +
> +/* Get the O_DIRECT definition. */
> +#ifndef _GNU_SOURCE
> +#define _GNU_SOURCE
> +#endif
> +
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <unistd.h>
> +#include <stdint.h>
> +#include <fcntl.h>
> +#include <errno.h>
> +#include <string.h>
> +#include <pthread.h>
> +
> +static int fd;
> +
> +static ssize_t do_write(int fd, const void *buf, size_t count, off_t offset)
> +{
> + while (count > 0) {
> + ssize_t ret;
> +
> + ret = pwrite(fd, buf, count, offset);
> + if (ret < 0) {
> + if (errno == EINTR)
> + continue;
> + return ret;
> + }
> + count -= ret;
> + buf += ret;
> + }
> + return 0;
> +}
> +
> +static void *fsync_loop(void *arg)
> +{
> + while (1) {
> + int ret;
> +
> + ret = fsync(fd);
> + if (ret != 0) {
> + perror("Fsync failed");
> + exit(6);
> + }
> + }
> +}
> +
> +int main(int argc, char *argv[])
> +{
> + long pagesize;
> + void *write_buf;
> + pthread_t fsyncer;
> + int ret;
> +
> + if (argc != 2) {
> + fprintf(stderr, "Use: %s <file path>\n", argv[0]);
> + return 1;
> + }
> +
> + fd = open(argv[1], O_WRONLY | O_CREAT | O_TRUNC | O_DIRECT, 0666);
> + if (fd == -1) {
> + perror("Failed to open/create file");
> + return 1;
> + }
> +
> + pagesize = sysconf(_SC_PAGE_SIZE);
> + if (pagesize == -1) {
> + perror("Failed to get page size");
> + return 2;
> + }
> +
> + ret = posix_memalign(&write_buf, pagesize, pagesize);
> + if (ret) {
> + perror("Failed to allocate buffer");
> + return 3;
> + }
> +
> + ret = pthread_create(&fsyncer, NULL, fsync_loop, NULL);
> + if (ret != 0) {
> + fprintf(stderr, "Failed to create writer thread: %d\n", ret);
> + return 4;
> + }
> +
> + while (1) {
> + ret = do_write(fd, write_buf, pagesize, 0);
> + if (ret != 0) {
> + perror("Write failed");
> + exit(5);
> + }
> + }
> +
> + return 0;
> +}
> diff --git a/tests/generic/363 b/tests/generic/363
> new file mode 100755
> index 00000000..21159e24
> --- /dev/null
> +++ b/tests/generic/363
> @@ -0,0 +1,30 @@
> +#! /bin/bash
> +# SPDX-License-Identifier: GPL-2.0
> +# Copyright (C) 2024 SUSE Linux Products GmbH. All Rights Reserved.
> +#
> +# FS QA Test 363
> +#
> +# Test that a program that has 2 threads using the same file descriptor and
> +# concurrently doing direct IO writes and fsync doesn't trigger any crash or
> +# deadlock.
> +#
> +. ./common/preamble
> +_begin_fstest auto quick
> +
> +_require_test
> +_require_odirect
> +_require_test_program dio-write-fsync-same-fd
> +_require_command "$TIMEOUT_PROG" timeout
> +
> +[ $FSTYP == "btrfs" ] && \
> + _fixed_by_kernel_commit xxxxxxxxxxxx \
> + "btrfs: fix race between direct IO write and fsync when using same fd"
> +
> +# On error the test program writes messages to stderr, causing a golden output
> +# mismatch and making the test fail.
> +$TIMEOUT_PROG 10s $here/src/dio-write-fsync-same-fd $TEST_DIR/dio-write-fsync-same-fd
> +
> +# success, all done
> +echo "Silence is golden"
> +status=0
> +exit
> diff --git a/tests/generic/363.out b/tests/generic/363.out
> new file mode 100644
> index 00000000..d03d2dc2
> --- /dev/null
> +++ b/tests/generic/363.out
> @@ -0,0 +1,2 @@
> +QA output created by 363
> +Silence is golden
prev parent reply other threads:[~2024-09-03 12:43 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-08-29 23:10 [PATCH] generic: test concurrent direct IO writes and fsync using same fd fdmanana
2024-09-02 20:28 ` Zorro Lang
2024-09-02 21:45 ` Filipe Manana
2024-09-03 4:09 ` Zorro Lang
2024-09-03 9:41 ` Filipe Manana
2024-09-03 10:02 ` Qu Wenruo
2024-09-04 11:13 ` Zorro Lang
2024-09-04 14:18 ` Filipe Manana
2024-09-03 12:42 ` Anand Jain [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=99345f2f-250a-4717-863c-d61d573b08cb@oracle.com \
--to=anand.jain@oracle.com \
--cc=fdmanana@kernel.org \
--cc=fdmanana@suse.com \
--cc=fstests@vger.kernel.org \
--cc=linux-btrfs@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox