filesetup.c revision 4d9345ae968ca92ace3dab06c25a9b73159cb329
1#include <unistd.h> 2#include <fcntl.h> 3#include <string.h> 4#include <assert.h> 5#include <sys/stat.h> 6#include <sys/mman.h> 7 8#include "fio.h" 9#include "os.h" 10 11/* 12 * Check if the file exists and it's large enough. 13 */ 14static int file_ok(struct thread_data *td, struct fio_file *f) 15{ 16 struct stat st; 17 18 if (td->filetype != FIO_TYPE_FILE || (td->io_ops->flags & FIO_NULLIO)) 19 return 0; 20 21 if (stat(f->file_name, &st) == -1) 22 return 1; 23 else if (st.st_size < (off_t) f->file_size) 24 return 1; 25 26 return 0; 27} 28 29static int create_file(struct thread_data *td, struct fio_file *f) 30{ 31 unsigned long long left; 32 unsigned int bs; 33 char *b; 34 int r; 35 36 f->fd = open(f->file_name, O_WRONLY | O_CREAT | O_TRUNC, 0644); 37 if (f->fd < 0) { 38 td_verror(td, errno); 39 return 1; 40 } 41 42 if (ftruncate(f->fd, f->file_size) == -1) { 43 td_verror(td, errno); 44 goto err; 45 } 46 47 if (posix_fallocate(f->fd, 0, f->file_size) < 0) { 48 td_verror(td, errno); 49 goto err; 50 } 51 52 b = malloc(td->max_bs[DDIR_WRITE]); 53 memset(b, 0, td->max_bs[DDIR_WRITE]); 54 55 left = f->file_size; 56 while (left && !td->terminate) { 57 bs = td->max_bs[DDIR_WRITE]; 58 if (bs > left) 59 bs = left; 60 61 r = write(f->fd, b, bs); 62 63 if (r == (int) bs) { 64 left -= bs; 65 continue; 66 } else { 67 if (r < 0) 68 td_verror(td, errno); 69 else 70 td_verror(td, EIO); 71 72 break; 73 } 74 } 75 76 if (td->terminate) 77 unlink(f->file_name); 78 else if (td->create_fsync) 79 fsync(f->fd); 80 81 free(b); 82 close(f->fd); 83 f->fd = -1; 84 return 0; 85err: 86 close(f->fd); 87 f->fd = -1; 88 return 1; 89} 90 91static int create_files(struct thread_data *td) 92{ 93 struct fio_file *f; 94 int i, err, need_create; 95 96 for_each_file(td, f, i) 97 f->file_size = td->total_file_size / td->nr_files; 98 99 /* 100 * unless specifically asked for overwrite, let normal io extend it 101 */ 102 if (!td->overwrite) 103 return 0; 104 105 need_create = 0; 106 if (td->filetype == FIO_TYPE_FILE) { 107 for_each_file(td, f, i) { 108 int file_there = !file_ok(td, f); 109 110 if (file_there && td->ddir == DDIR_WRITE && 111 !td->overwrite) { 112 unlink(f->file_name); 113 file_there = 0; 114 } 115 116 need_create += !file_there; 117 } 118 } 119 120 if (!need_create) 121 return 0; 122 123 if (!td->total_file_size) { 124 log_err("Need size for create\n"); 125 td_verror(td, EINVAL); 126 return 1; 127 } 128 129 temp_stall_ts = 1; 130 fprintf(f_out, "%s: Laying out IO file(s) (%u x %LuMiB == %LuMiB)\n", 131 td->name, td->nr_uniq_files, 132 (td->total_file_size >> 20) / td->nr_uniq_files, 133 td->total_file_size >> 20); 134 135 err = 0; 136 for_each_file(td, f, i) { 137 /* 138 * Only unlink files that we created. 139 */ 140 f->unlink = 0; 141 if (file_ok(td, f)) { 142 f->unlink = td->unlink; 143 err = create_file(td, f); 144 if (err) 145 break; 146 } 147 } 148 149 temp_stall_ts = 0; 150 return err; 151} 152 153static int file_size(struct thread_data *td, struct fio_file *f) 154{ 155 struct stat st; 156 157 if (td->overwrite) { 158 if (fstat(f->fd, &st) == -1) { 159 td_verror(td, errno); 160 return 1; 161 } 162 163 f->real_file_size = st.st_size; 164 165 if (!f->file_size || f->file_size > f->real_file_size) 166 f->file_size = f->real_file_size; 167 } else 168 f->real_file_size = f->file_size; 169 170 return 0; 171} 172 173static int bdev_size(struct thread_data *td, struct fio_file *f) 174{ 175 unsigned long long bytes; 176 int r; 177 178 r = blockdev_size(f->fd, &bytes); 179 if (r) { 180 td_verror(td, r); 181 return 1; 182 } 183 184 f->real_file_size = bytes; 185 186 /* 187 * no extend possibilities, so limit size to device size if too large 188 */ 189 if (!f->file_size || f->file_size > f->real_file_size) 190 f->file_size = f->real_file_size; 191 192 f->file_size -= f->file_offset; 193 return 0; 194} 195 196static int get_file_size(struct thread_data *td, struct fio_file *f) 197{ 198 int ret = 0; 199 200 if (td->filetype == FIO_TYPE_FILE) 201 ret = file_size(td, f); 202 else if (td->filetype == FIO_TYPE_BD) 203 ret = bdev_size(td, f); 204 else 205 f->real_file_size = -1; 206 207 if (ret) 208 return ret; 209 210 if (f->file_offset > f->real_file_size) { 211 log_err("%s: offset extends end (%Lu > %Lu)\n", td->name, f->file_offset, f->real_file_size); 212 return 1; 213 } 214 215 return 0; 216} 217 218int file_invalidate_cache(struct thread_data *td, struct fio_file *f) 219{ 220 int ret = 0; 221 222 /* 223 * FIXME: add blockdev flushing too 224 */ 225 if (td->io_ops->flags & FIO_MMAPIO) 226 ret = madvise(f->mmap, f->file_size, MADV_DONTNEED); 227 else if (td->filetype == FIO_TYPE_FILE) 228 ret = fadvise(f->fd, f->file_offset, f->file_size, POSIX_FADV_DONTNEED); 229 else if (td->filetype == FIO_TYPE_BD) 230 ret = blockdev_invalidate_cache(f->fd); 231 else if (td->filetype == FIO_TYPE_CHAR) 232 ret = 0; 233 234 if (ret < 0) { 235 td_verror(td, errno); 236 return 1; 237 } 238 239 return 0; 240} 241 242static int __setup_file_mmap(struct thread_data *td, struct fio_file *f) 243{ 244 int flags; 245 246 if (td_rw(td)) 247 flags = PROT_READ | PROT_WRITE; 248 else if (td_write(td)) { 249 flags = PROT_WRITE; 250 251 if (td->verify != VERIFY_NONE) 252 flags |= PROT_READ; 253 } else 254 flags = PROT_READ; 255 256 f->mmap = mmap(NULL, f->file_size, flags, MAP_SHARED, f->fd, f->file_offset); 257 if (f->mmap == MAP_FAILED) { 258 f->mmap = NULL; 259 td_verror(td, errno); 260 return 1; 261 } 262 263 if (td->invalidate_cache && file_invalidate_cache(td, f)) 264 return 1; 265 266 if (td->sequential) { 267 if (madvise(f->mmap, f->file_size, MADV_SEQUENTIAL) < 0) { 268 td_verror(td, errno); 269 return 1; 270 } 271 } else { 272 if (madvise(f->mmap, f->file_size, MADV_RANDOM) < 0) { 273 td_verror(td, errno); 274 return 1; 275 } 276 } 277 278 return 0; 279} 280 281static int setup_files_mmap(struct thread_data *td) 282{ 283 struct fio_file *f; 284 int i, err = 0; 285 286 for_each_file(td, f, i) { 287 err = __setup_file_mmap(td, f); 288 if (err) 289 break; 290 } 291 292 return err; 293} 294 295static int __setup_file_plain(struct thread_data *td, struct fio_file *f) 296{ 297 if (td->invalidate_cache && file_invalidate_cache(td, f)) 298 return 1; 299 300 if (td->sequential) { 301 if (fadvise(f->fd, f->file_offset, f->file_size, POSIX_FADV_SEQUENTIAL) < 0) { 302 td_verror(td, errno); 303 return 1; 304 } 305 } else { 306 if (fadvise(f->fd, f->file_offset, f->file_size, POSIX_FADV_RANDOM) < 0) { 307 td_verror(td, errno); 308 return 1; 309 } 310 } 311 312 return 0; 313} 314 315static int setup_files_plain(struct thread_data *td) 316{ 317 struct fio_file *f; 318 int i, err = 0; 319 320 for_each_file(td, f, i) { 321 err = __setup_file_plain(td, f); 322 if (err) 323 break; 324 } 325 326 return err; 327} 328 329static int setup_file(struct thread_data *td, struct fio_file *f) 330{ 331 int flags = 0; 332 333 if (td->io_ops->flags & FIO_NETIO) 334 return 0; 335 336 /* 337 * we need a valid file descriptor, but don't create a real file. 338 * lets just dup stdout, seems like a sensible approach. 339 */ 340 if (td->io_ops->flags & FIO_NULLIO) 341 f->fd = dup(STDOUT_FILENO); 342 else { 343 if (td->odirect) 344 flags |= OS_O_DIRECT; 345 if (td->sync_io) 346 flags |= O_SYNC; 347 348 if (td_write(td) || td_rw(td)) { 349 flags |= O_RDWR; 350 351 if (td->filetype == FIO_TYPE_FILE) { 352 if (!td->overwrite) 353 flags |= O_TRUNC; 354 355 flags |= O_CREAT; 356 } 357 358 f->fd = open(f->file_name, flags, 0600); 359 } else { 360 if (td->filetype == FIO_TYPE_CHAR) 361 flags |= O_RDWR; 362 else 363 flags |= O_RDONLY; 364 365 f->fd = open(f->file_name, flags); 366 } 367 } 368 369 if (f->fd == -1) { 370 td_verror(td, errno); 371 return 1; 372 } 373 374 if (get_file_size(td, f)) 375 return 1; 376 377 return 0; 378} 379 380int open_files(struct thread_data *td) 381{ 382 struct fio_file *f; 383 int i, err = 0; 384 385 for_each_file(td, f, i) { 386 err = setup_file(td, f); 387 if (err) 388 break; 389 } 390 391 if (!err) 392 return 0; 393 394 for_each_file(td, f, i) { 395 if (f->fd != -1) { 396 close(f->fd); 397 f->fd = -1; 398 } 399 } 400 401 return err; 402} 403 404int setup_files(struct thread_data *td) 405{ 406 struct fio_file *f; 407 int err, i; 408 409 /* 410 * if ioengine defines a setup() method, it's responsible for 411 * setting up everything in the td->files[] area. 412 */ 413 if (td->io_ops->setup) 414 return td->io_ops->setup(td); 415 416 if (create_files(td)) 417 return 1; 418 419 err = open_files(td); 420 if (err) 421 return err; 422 423 /* 424 * Recalculate the total file size now that files are set up. 425 */ 426 td->total_file_size = 0; 427 for_each_file(td, f, i) 428 td->total_file_size += f->file_size; 429 430 td->io_size = td->total_file_size; 431 if (td->io_size == 0) { 432 log_err("%s: no io blocks\n", td->name); 433 td_verror(td, EINVAL); 434 return 1; 435 } 436 437 if (!td->zone_size) 438 td->zone_size = td->io_size; 439 440 td->total_io_size = td->io_size * td->loops; 441 442 if (td->io_ops->flags & FIO_MMAPIO) 443 err = setup_files_mmap(td); 444 else 445 err = setup_files_plain(td); 446 447 for_each_file(td, f, i) { 448 if (f->fd != -1) { 449 close(f->fd); 450 f->fd = -1; 451 } 452 } 453 454 return err; 455} 456 457void close_files(struct thread_data *td) 458{ 459 struct fio_file *f; 460 int i; 461 462 for_each_file(td, f, i) { 463 if (!td->filename && f->unlink && 464 td->filetype == FIO_TYPE_FILE) { 465 unlink(f->file_name); 466 free(f->file_name); 467 f->file_name = NULL; 468 } 469 if (f->fd != -1) { 470 close(f->fd); 471 f->fd = -1; 472 } 473 if (f->mmap) { 474 munmap(f->mmap, f->file_size); 475 f->mmap = NULL; 476 } 477 } 478 479 td->filename = NULL; 480 free(td->files); 481 td->files = NULL; 482 td->nr_files = 0; 483} 484