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
main(int ac,char ** av)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 */
setup(void)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
cleanup(void)188 void cleanup(void)
189 {
190 if (close(fd) == -1)
191 tst_resm(TWARN | TERRNO, "close failed");
192
193 tst_rmdir();
194
195 }
196