1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright (c) 2004 Daniel McNeil <daniel@osdl.org> 4 * 2004 Open Source Development Lab 5 * 2004 Marty Ridgeway <mridge@us.ibm.com> 6 * Copyright (C) 2021 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com> 7 */ 8 9/*\ 10 * [Description] 11 * 12 * Appends zeroed data to a file using O_DIRECT while a child processes are 13 * doing buffered reads after seeking to the end of the file and checks if the 14 * buffer reads always see zero. 15 */ 16 17#define _GNU_SOURCE 18 19#include "tst_test.h" 20#include "common.h" 21 22static volatile int *run_child; 23 24static char *str_numchildren; 25static char *str_writesize; 26static char *str_appends; 27 28static int numchildren; 29static long long writesize; 30static int appends; 31 32static void setup(void) 33{ 34 numchildren = 16; 35 writesize = 64 * 1024; 36 appends = 1000; 37 38 if (tst_parse_int(str_numchildren, &numchildren, 1, INT_MAX)) 39 tst_brk(TBROK, "Invalid number of children '%s'", str_numchildren); 40 41 if (tst_parse_filesize(str_writesize, &writesize, 1, LLONG_MAX)) 42 tst_brk(TBROK, "Invalid write file size '%s'", str_writesize); 43 44 if (tst_parse_int(str_appends, &appends, 1, INT_MAX)) 45 tst_brk(TBROK, "Invalid number of appends '%s'", str_appends); 46 47 run_child = SAFE_MMAP(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); 48} 49 50static void cleanup(void) 51{ 52 if (run_child) { 53 *run_child = 0; 54 SAFE_MUNMAP((void *)run_child, sizeof(int)); 55 } 56} 57 58static void run(void) 59{ 60 char *filename = "dio_append"; 61 int status; 62 int i; 63 64 *run_child = 1; 65 66 for (i = 0; i < numchildren; i++) { 67 if (!SAFE_FORK()) { 68 io_read_eof(filename, run_child); 69 return; 70 } 71 } 72 73 tst_res(TINFO, "Parent append to file"); 74 75 io_append(filename, 0, O_DIRECT | O_WRONLY | O_CREAT, writesize, appends); 76 77 if (!tst_remaining_runtime()) 78 tst_res(TINFO, "Test out of runtime, exiting"); 79 80 if (SAFE_WAITPID(-1, &status, WNOHANG)) 81 tst_res(TFAIL, "Non zero bytes read"); 82 else 83 tst_res(TPASS, "All bytes read were zeroed"); 84 85 *run_child = 0; 86 87 SAFE_UNLINK(filename); 88} 89 90static struct tst_test test = { 91 .test_all = run, 92 .setup = setup, 93 .cleanup = cleanup, 94 .needs_tmpdir = 1, 95 .forks_child = 1, 96 .max_runtime = 1800, 97 .options = (struct tst_option[]) { 98 {"n:", &str_numchildren, "Number of processes (default 16)"}, 99 {"w:", &str_writesize, "Write size for each append (default 64K)"}, 100 {"c:", &str_appends, "Number of appends (default 1000)"}, 101 {} 102 }, 103 .skip_filesystems = (const char *[]) { 104 "tmpfs", 105 NULL 106 }, 107}; 108