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 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, 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 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 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 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 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 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