1 /* 2 * 3 * Copyright (c) International Business Machines Corp., 2001 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 13 * the GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 */ 19 20 /* 21 * NAME 22 * fsync02.c 23 * 24 * DESCRIPTION 25 * Create a sparse file, fsync it, and time the fsync 26 * 27 * ALGORITHM 28 * 1. Create a file. 29 * 2. Write to the file at equally spaced intervals up to a max block 30 * 3. Check if the time limit was exceeded. 31 * 32 * USAGE: <for command-line> 33 * fsync02 [-c n] [-f] [-i n] [-I x] [-P x] [-t] 34 * where, -c n : Run n copies concurrently. 35 * -f : Turn off functionality Testing. 36 * -i n : Execute test n times. 37 * -I x : Execute test for x seconds. 38 * -P x : Pause for x seconds between iterations. 39 * -t : Turn on syscall timing. 40 * 41 * HISTORY 42 * 07/2001 Ported by Wayne Boyer 43 * 44 * RESTRICTIONS 45 * None 46 */ 47 48 #include <stdio.h> 49 #include <unistd.h> 50 #include <sys/types.h> 51 #include <sys/statvfs.h> 52 #include <fcntl.h> 53 #include <errno.h> 54 #include <sys/resource.h> 55 #include "test.h" 56 #include <time.h> 57 58 #define BLOCKSIZE 8192 59 #define MAXBLKS 262144 60 #define TIME_LIMIT 120 61 62 char *TCID = "fsync02"; 63 int TST_TOTAL = 1; 64 65 void setup(void); 66 void cleanup(void); 67 68 char tempfile[40] = ""; 69 int fd, pid; 70 off_t max_blks = MAXBLKS; 71 72 struct statvfs stat_buf; 73 74 int main(int ac, char **av) 75 { 76 int lc; 77 78 off_t offsetret, offset; 79 char pbuf[BUFSIZ]; 80 int ret, max_block = 0; 81 int i; 82 time_t time_start, time_end; 83 double time_delta; 84 int data_blocks = 0; 85 long int random_number; 86 87 tst_parse_opts(ac, av, NULL, NULL); 88 89 setup(); 90 91 for (lc = 0; TEST_LOOPING(lc); lc++) { 92 93 tst_count = 0; 94 95 while (max_block <= data_blocks) { 96 random_number = random(); 97 max_block = random_number % max_blks; 98 data_blocks = random_number % 1000 + 1; 99 } 100 101 for (i = 1; i <= data_blocks; i++) { 102 offset = i * ((BLOCKSIZE * max_block) / data_blocks); 103 offset -= BUFSIZ; 104 if ((offsetret = lseek(fd, offset, SEEK_SET)) != offset) 105 tst_brkm(TBROK | TERRNO, cleanup, 106 "lseek failed: %ld, %ld", offsetret, 107 offset); 108 if ((ret = write(fd, pbuf, BUFSIZ)) != BUFSIZ) 109 tst_brkm(TBROK, cleanup, "write failed"); 110 } 111 if (time(&time_start) == -1) 112 tst_brkm(TBROK | TERRNO, cleanup, 113 "getting start time failed"); 114 115 TEST(fsync(fd)); 116 117 if (time(&time_end) == -1) 118 tst_brkm(TBROK | TERRNO, cleanup, 119 "getting end time failed"); 120 121 if (TEST_RETURN == -1) { 122 tst_resm(TFAIL | TTERRNO, "fsync failed"); 123 continue; 124 } 125 126 if (time_end < time_start) 127 tst_resm(TBROK, 128 "timer broken end %ld < start %ld", 129 time_end, time_start); 130 131 if ((time_delta = 132 difftime(time_end, time_start)) > TIME_LIMIT) 133 tst_resm(TFAIL, 134 "fsync took too long: %lf seconds; " 135 "max_block: %d; data_blocks: %d", 136 time_delta, max_block, data_blocks); 137 else 138 tst_resm(TPASS, "fsync succeeded in an " 139 "acceptable amount of time"); 140 141 if (ftruncate(fd, 0) == -1) 142 tst_brkm(TBROK, cleanup, "ftruncate failed"); 143 } 144 145 sync(); 146 cleanup(); 147 tst_exit(); 148 } 149 150 /* 151 * setup() - performs all ONE TIME setup for this test. 152 */ 153 void setup(void) 154 { 155 /* free blocks avail to non-superuser */ 156 unsigned long f_bavail; 157 158 tst_sig(NOFORK, DEF_HANDLER, cleanup); 159 160 TEST_PAUSE; 161 162 /* make a temporary directory and cd to it */ 163 tst_tmpdir(); 164 165 sprintf(tempfile, "%s.%d", TCID, pid = getpid()); 166 srand48(pid); 167 168 if ((fd = open(tempfile, O_RDWR | O_CREAT | O_TRUNC, 0777)) == -1) 169 tst_brkm(TBROK, cleanup, "open failed"); 170 171 if (fstatvfs(fd, &stat_buf) != 0) 172 tst_brkm(TBROK, cleanup, "fstatvfs failed"); 173 174 f_bavail = (stat_buf.f_bavail * stat_buf.f_frsize) / BLOCKSIZE; 175 if (f_bavail && (f_bavail < MAXBLKS)) 176 max_blks = f_bavail; 177 178 #ifdef LARGEFILE 179 if ((fcntl(fd, F_SETFL, O_LARGEFILE)) == -1) 180 tst_brkm(TBROK | TERRNO, cleanup, 181 "fcntl(.., O_LARGEFILE) failed"); 182 183 if (write(fd, pbuf, BUFSIZ) != BUFSIZ) 184 tst_brkm(TBROK | TERRNO, cleanup, "write(fd, pbuf, ..) failed"); 185 #endif 186 } 187 188 void cleanup(void) 189 { 190 if (close(fd) == -1) 191 tst_resm(TWARN | TERRNO, "close failed"); 192 193 tst_rmdir(); 194 195 } 196