1 /*
2 * Copyright (c) International Business Machines Corp., 2001-2004
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
12 * the GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 #define FILE_OFFSET_BITS 64
20
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <fcntl.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <assert.h>
27 #include <inttypes.h>
28 #include <assert.h>
29
30 #include "ffsb.h"
31 #include "fh.h"
32
33 #include "config.h"
34
35 /* !!! ugly */
36 #ifndef HAVE_OPEN64
37 #define open64 open
38 #endif
39
40 #ifndef HAVE_FSEEKO64
41 #define lseek64 lseek
42 #endif
43
44 /* All these functions read the global mainconfig->bufferedio variable
45 * to determine if they are to do buffered i/o or normal.
46 *
47 * ha, well, they're supposed to anyway...!!! TODO -SR 2006/05/14
48 */
49
do_stats(struct timeval * start,struct timeval * end,ffsb_thread_t * ft,ffsb_fs_t * fs,syscall_t sys)50 static void do_stats(struct timeval *start, struct timeval *end,
51 ffsb_thread_t * ft, ffsb_fs_t * fs, syscall_t sys)
52 {
53 struct timeval diff;
54 uint32_t value = 0;
55
56 if (!ft && !fs)
57 return;
58
59 timersub(end, start, &diff);
60
61 value = 1000000 * diff.tv_sec + diff.tv_usec;
62
63 if (ft && ft_needs_stats(ft, sys))
64 ft_add_stat(ft, sys, value);
65 if (fs && fs_needs_stats(fs, sys))
66 fs_add_stat(fs, sys, value);
67 }
68
fhopenhelper(char * filename,char * bufflags,int flags,ffsb_thread_t * ft,ffsb_fs_t * fs)69 static int fhopenhelper(char *filename, char *bufflags, int flags,
70 ffsb_thread_t * ft, ffsb_fs_t * fs)
71 {
72 int fd = 0;
73 struct timeval start, end;
74 int need_stats = ft_needs_stats(ft, SYS_OPEN) ||
75 fs_needs_stats(fs, SYS_OPEN);
76
77 flags |= O_LARGEFILE;
78
79 if (need_stats)
80 gettimeofday(&start, NULL);
81
82 fd = open64(filename, flags, S_IRWXU);
83 if (fd < 0) {
84 perror(filename);
85 exit(0);
86 }
87
88 if (need_stats) {
89 gettimeofday(&end, NULL);
90 do_stats(&start, &end, ft, fs, SYS_OPEN);
91 }
92
93 return fd;
94 }
95
fhopenread(char * filename,ffsb_thread_t * ft,ffsb_fs_t * fs)96 int fhopenread(char *filename, ffsb_thread_t * ft, ffsb_fs_t * fs)
97 {
98 int flags = O_RDONLY;
99 int directio = fs_get_directio(fs);
100
101 if (directio)
102 flags |= O_DIRECT;
103 return fhopenhelper(filename, "r", flags, ft, fs);
104 }
105
fhopenappend(char * filename,ffsb_thread_t * ft,ffsb_fs_t * fs)106 int fhopenappend(char *filename, ffsb_thread_t * ft, ffsb_fs_t * fs)
107 {
108 int flags = O_APPEND | O_WRONLY;
109 int directio = fs_get_directio(fs);
110
111 if (directio)
112 flags |= O_DIRECT;
113 return fhopenhelper(filename, "a", flags, ft, fs);
114 }
115
fhopenwrite(char * filename,ffsb_thread_t * ft,ffsb_fs_t * fs)116 int fhopenwrite(char *filename, ffsb_thread_t * ft, ffsb_fs_t * fs)
117 {
118 int flags = O_WRONLY;
119 int directio = fs_get_directio(fs);
120
121 if (directio)
122 flags |= O_DIRECT;
123 return fhopenhelper(filename, "w", flags, ft, fs);
124 }
125
fhopencreate(char * filename,ffsb_thread_t * ft,ffsb_fs_t * fs)126 int fhopencreate(char *filename, ffsb_thread_t * ft, ffsb_fs_t * fs)
127 {
128 int flags = O_CREAT | O_RDWR | O_TRUNC;
129 int directio = fs_get_directio(fs);
130
131 if (directio)
132 flags |= O_DIRECT;
133 return fhopenhelper(filename, "rw", flags, ft, fs);
134 }
135
fhread(int fd,void * buf,uint64_t size,ffsb_thread_t * ft,ffsb_fs_t * fs)136 void fhread(int fd, void *buf, uint64_t size, ffsb_thread_t * ft,
137 ffsb_fs_t * fs)
138 {
139 ssize_t realsize;
140 struct timeval start, end;
141 int need_stats = ft_needs_stats(ft, SYS_READ) ||
142 fs_needs_stats(fs, SYS_READ);
143
144 assert(size <= SIZE_MAX);
145 if (need_stats)
146 gettimeofday(&start, NULL);
147 realsize = read(fd, buf, size);
148
149 if (need_stats) {
150 gettimeofday(&end, NULL);
151 do_stats(&start, &end, ft, fs, SYS_READ);
152 }
153
154 if (realsize != size) {
155 printf("Read %lld instead of %llu bytes.\n",
156 (unsigned long long)realsize, (unsigned long long)size);
157 perror("read");
158 exit(1);
159 }
160 }
161
fhwrite(int fd,void * buf,uint32_t size,ffsb_thread_t * ft,ffsb_fs_t * fs)162 void fhwrite(int fd, void *buf, uint32_t size, ffsb_thread_t * ft,
163 ffsb_fs_t * fs)
164 {
165 ssize_t realsize;
166 struct timeval start, end;
167 int need_stats = ft_needs_stats(ft, SYS_WRITE) ||
168 fs_needs_stats(fs, SYS_WRITE);
169
170 assert(size <= SIZE_MAX);
171 if (need_stats)
172 gettimeofday(&start, NULL);
173
174 realsize = write(fd, buf, size);
175
176 if (need_stats) {
177 gettimeofday(&end, NULL);
178 do_stats(&start, &end, ft, fs, SYS_WRITE);
179 }
180
181 if (realsize != size) {
182 printf("Wrote %d instead of %d bytes.\n"
183 "Probably out of disk space\n", realsize, size);
184 perror("write");
185 exit(1);
186 }
187 }
188
fhseek(int fd,uint64_t offset,int whence,ffsb_thread_t * ft,ffsb_fs_t * fs)189 void fhseek(int fd, uint64_t offset, int whence, ffsb_thread_t * ft,
190 ffsb_fs_t * fs)
191 {
192 uint64_t res;
193 struct timeval start, end;
194 int need_stats = ft_needs_stats(ft, SYS_LSEEK) ||
195 fs_needs_stats(fs, SYS_LSEEK);
196
197 if ((whence == SEEK_CUR) && (offset == 0))
198 return;
199
200 if (need_stats)
201 gettimeofday(&start, NULL);
202
203 res = lseek64(fd, offset, whence);
204
205 if (need_stats) {
206 gettimeofday(&end, NULL);
207 do_stats(&start, &end, ft, fs, SYS_LSEEK);
208 }
209 if ((whence == SEEK_SET) && (res != offset))
210 perror("seek");
211
212 if (res == -1) {
213 if (whence == SEEK_SET)
214 fprintf(stderr, "tried to seek to %lld\n", offset);
215 else
216 fprintf(stderr, "tried to seek from current "
217 "position to %lld\n", offset);
218
219 perror("seek");
220 exit(1);
221 }
222 }
223
fhclose(int fd,ffsb_thread_t * ft,ffsb_fs_t * fs)224 void fhclose(int fd, ffsb_thread_t * ft, ffsb_fs_t * fs)
225 {
226 struct timeval start, end;
227 int need_stats = ft_needs_stats(ft, SYS_CLOSE) ||
228 fs_needs_stats(fs, SYS_CLOSE);
229
230 if (need_stats)
231 gettimeofday(&start, NULL);
232
233 close(fd);
234
235 if (need_stats) {
236 gettimeofday(&end, NULL);
237 do_stats(&start, &end, ft, fs, SYS_CLOSE);
238 }
239 }
240
fhstat(char * name,ffsb_thread_t * ft,ffsb_fs_t * fs)241 void fhstat(char *name, ffsb_thread_t * ft, ffsb_fs_t * fs)
242 {
243 struct timeval start, end;
244 struct stat tmp_stat;
245
246 int need_stats = ft_needs_stats(ft, SYS_STAT) ||
247 fs_needs_stats(fs, SYS_CLOSE);
248
249 if (need_stats)
250 gettimeofday(&start, NULL);
251
252 if (stat(name, &tmp_stat)) {
253 fprintf(stderr, "stat call failed for file %s\n", name);
254 exit(1);
255 }
256
257 if (need_stats) {
258 gettimeofday(&end, NULL);
259 do_stats(&start, &end, ft, fs, SYS_STAT);
260 }
261 }
262
writefile_helper(int fd,uint64_t size,uint32_t blocksize,char * buf,struct ffsb_thread * ft,struct ffsb_fs * fs)263 int writefile_helper(int fd, uint64_t size, uint32_t blocksize, char *buf,
264 struct ffsb_thread *ft, struct ffsb_fs *fs)
265 {
266 uint64_t iterations, a;
267 uint64_t last;
268
269 iterations = size / blocksize;
270 last = size % blocksize;
271
272 for (a = 0; a < iterations; a++)
273 fhwrite(fd, buf, blocksize, ft, fs);
274
275 if (last) {
276 a++;
277 fhwrite(fd, buf, last, ft, fs);
278 }
279 return a;
280 }
281