| // 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; | |
| } |