Merge pull request #3 from lxbsz/wip-52438
[ffsb.git] / fh.c
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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
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
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
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
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
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
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
136 void fhread(int fd, void *buf, uint64_t size, ffsb_thread_t *ft, ffsb_fs_t *fs)
137 {
138         ssize_t realsize;
139         struct timeval start, end;
140         int need_stats = ft_needs_stats(ft, SYS_READ) ||
141                 fs_needs_stats(fs, SYS_READ);
142
143         assert(size <= SIZE_MAX);
144         if (need_stats)
145                 gettimeofday(&start, NULL);
146         realsize = read(fd, buf, size);
147
148         if (need_stats) {
149                 gettimeofday(&end, NULL);
150                 do_stats(&start, &end, ft, fs, SYS_READ);
151         }
152
153         if (realsize != size) {
154                 printf("Read %lld instead of %llu bytes.\n",
155                        (unsigned long long)realsize, (unsigned long long)size);
156                 perror("read");
157                 exit(1);
158         }
159 }
160
161 void fhwrite(int fd, void *buf, uint32_t size, ffsb_thread_t *ft, ffsb_fs_t *fs)
162 {
163         ssize_t realsize;
164         struct timeval start, end;
165         int need_stats = ft_needs_stats(ft, SYS_WRITE) ||
166                 fs_needs_stats(fs, SYS_WRITE);
167
168         assert(size <= SIZE_MAX);
169         if (need_stats)
170                 gettimeofday(&start, NULL);
171
172         realsize = write(fd, buf, size);
173
174         if (need_stats) {
175                 gettimeofday(&end, NULL);
176                 do_stats(&start, &end, ft, fs, SYS_WRITE);
177         }
178
179         if (realsize != size) {
180                 printf("Wrote %zd instead of %d bytes.\n"
181                           "Probably out of disk space\n", realsize, size);
182                 perror("write");
183                 exit(1);
184         }
185 }
186
187 void fhseek(int fd, uint64_t offset, int whence, ffsb_thread_t *ft,
188             ffsb_fs_t *fs)
189 {
190         uint64_t res;
191         struct timeval start, end;
192         int need_stats = ft_needs_stats(ft, SYS_LSEEK) ||
193                 fs_needs_stats(fs, SYS_LSEEK);
194
195         if ((whence == SEEK_CUR) && (offset == 0))
196                 return;
197
198         if (need_stats)
199                 gettimeofday(&start, NULL);
200
201         res = lseek64(fd, offset, whence);
202
203         if (need_stats) {
204                 gettimeofday(&end, NULL);
205                 do_stats(&start, &end, ft, fs, SYS_LSEEK);
206         }
207         if ((whence == SEEK_SET) && (res != offset))
208                 perror("seek");
209
210         if (res == -1) {
211                 if (whence == SEEK_SET)
212                         fprintf(stderr, "tried to seek to %"PRIu64"\n", offset);
213                 else
214                         fprintf(stderr, "tried to seek from current "
215                                 "position to %"PRIu64"\n", offset);
216
217                 perror("seek");
218                 exit(1);
219         }
220 }
221
222 void fhclose(int fd, ffsb_thread_t *ft, ffsb_fs_t *fs)
223 {
224         struct timeval start, end;
225         int need_stats = ft_needs_stats(ft, SYS_CLOSE) ||
226                 fs_needs_stats(fs, SYS_CLOSE);
227
228         if (need_stats)
229                 gettimeofday(&start, NULL);
230
231         close(fd);
232
233         if (need_stats) {
234                 gettimeofday(&end, NULL);
235                 do_stats(&start, &end, ft, fs, SYS_CLOSE);
236         }
237 }
238
239 void fhstat(char *name, ffsb_thread_t *ft, ffsb_fs_t *fs)
240 {
241         struct timeval start, end;
242         struct stat tmp_stat;
243
244         int need_stats = ft_needs_stats(ft, SYS_STAT) ||
245                 fs_needs_stats(fs, SYS_CLOSE);
246
247         if (need_stats)
248                 gettimeofday(&start, NULL);
249
250         if (stat(name, &tmp_stat)) {
251                 fprintf (stderr, "stat call failed for file %s\n", name);
252                 exit(1);
253         }
254
255         if (need_stats) {
256                 gettimeofday(&end, NULL);
257                 do_stats(&start, &end, ft, fs, SYS_STAT);
258         }
259
260
261 int writefile_helper(int fd, uint64_t size, uint32_t blocksize, char *buf,
262                      struct ffsb_thread *ft, struct ffsb_fs *fs)
263 {
264         uint64_t iterations, a;
265         uint64_t last;
266
267         iterations = size / blocksize;
268         last = size % blocksize;
269
270         for (a = 0; a < iterations; a++)
271                 fhwrite(fd, buf, blocksize, ft, fs);
272
273         if (last) {
274                 a++;
275                 fhwrite(fd, buf, last, ft, fs);
276         }
277         return a;
278 }