filesetup.c revision 13f8e2d2e3e5ec7d8c18b70fb2a2e2a026190020
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) 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 b = malloc(td->max_bs); 48 memset(b, 0, td->max_bs); 49 50 left = f->file_size; 51 while (left && !td->terminate) { 52 bs = td->max_bs; 53 if (bs > left) 54 bs = left; 55 56 r = write(f->fd, b, bs); 57 58 if (r == (int) bs) { 59 left -= bs; 60 continue; 61 } else { 62 if (r < 0) 63 td_verror(td, errno); 64 else 65 td_verror(td, EIO); 66 67 break; 68 } 69 } 70 71 if (td->terminate) 72 unlink(f->file_name); 73 else if (td->create_fsync) 74 fsync(f->fd); 75 76 free(b); 77 close(f->fd); 78 f->fd = -1; 79 return 0; 80err: 81 close(f->fd); 82 f->fd = -1; 83 return 1; 84} 85 86static int create_files(struct thread_data *td) 87{ 88 struct fio_file *f; 89 int i, err, need_create; 90 91 /* 92 * unless specifically asked for overwrite, let normal io extend it 93 */ 94 if (!td->overwrite) { 95 for_each_file(td, f, i) 96 f->file_size = td->total_file_size / td->nr_files; 97 98 return 0; 99 } 100 101 need_create = 0; 102 if (td->filetype == FIO_TYPE_FILE) 103 for_each_file(td, f, i) 104 need_create += file_ok(td, f); 105 106 if (!need_create) 107 return 0; 108 109 if (!td->total_file_size) { 110 log_err("Need size for create\n"); 111 td_verror(td, EINVAL); 112 return 1; 113 } 114 115 temp_stall_ts = 1; 116 fprintf(f_out, "%s: Laying out IO file(s) (%d x %LuMiB == %LuMiB)\n", 117 td->name, td->nr_uniq_files, 118 (td->total_file_size >> 20) / td->nr_uniq_files, 119 td->total_file_size >> 20); 120 121 err = 0; 122 for_each_file(td, f, i) { 123 if (file_ok(td, f)) { 124 err = create_file(td, f); 125 if (err) 126 break; 127 } 128 } 129 130 temp_stall_ts = 0; 131 return err; 132} 133 134static int file_size(struct thread_data *td, struct fio_file *f) 135{ 136 struct stat st; 137 138 if (td->overwrite) { 139 if (fstat(f->fd, &st) == -1) { 140 td_verror(td, errno); 141 return 1; 142 } 143 144 f->real_file_size = st.st_size; 145 146 if (!f->file_size || f->file_size > f->real_file_size) 147 f->file_size = f->real_file_size; 148 } 149 150 f->file_size -= f->file_offset; 151 return 0; 152} 153 154static int bdev_size(struct thread_data *td, struct fio_file *f) 155{ 156 unsigned long long bytes; 157 int r; 158 159 r = blockdev_size(f->fd, &bytes); 160 if (r) { 161 td_verror(td, r); 162 return 1; 163 } 164 165 f->real_file_size = bytes; 166 167 /* 168 * no extend possibilities, so limit size to device size if too large 169 */ 170 if (!f->file_size || f->file_size > f->real_file_size) 171 f->file_size = f->real_file_size; 172 173 f->file_size -= f->file_offset; 174 return 0; 175} 176 177static int get_file_size(struct thread_data *td, struct fio_file *f) 178{ 179 int ret = 0; 180 181 if (td->filetype == FIO_TYPE_FILE) 182 ret = file_size(td, f); 183 else if (td->filetype == FIO_TYPE_BD) 184 ret = bdev_size(td, f); 185 else 186 f->real_file_size = -1; 187 188 if (ret) 189 return ret; 190 191 if (f->file_offset > f->real_file_size) { 192 log_err("%s: offset extends end (%Lu > %Lu)\n", td->name, f->file_offset, f->real_file_size); 193 return 1; 194 } 195 196 return 0; 197} 198 199int file_invalidate_cache(struct thread_data *td, struct fio_file *f) 200{ 201 int ret = 0; 202 203 /* 204 * FIXME: add blockdev flushing too 205 */ 206 if (td->io_ops->flags & FIO_MMAPIO) 207 ret = madvise(f->mmap, f->file_size, MADV_DONTNEED); 208 else if (td->filetype == FIO_TYPE_FILE) 209 ret = fadvise(f->fd, f->file_offset, f->file_size, POSIX_FADV_DONTNEED); 210 else if (td->filetype == FIO_TYPE_BD) 211 ret = blockdev_invalidate_cache(f->fd); 212 else if (td->filetype == FIO_TYPE_CHAR) 213 ret = 0; 214 215 if (ret < 0) { 216 td_verror(td, errno); 217 return 1; 218 } 219 220 return 0; 221} 222 223static int __setup_file_mmap(struct thread_data *td, struct fio_file *f) 224{ 225 int flags; 226 227 if (td_rw(td)) 228 flags = PROT_READ | PROT_WRITE; 229 else if (td_write(td)) { 230 flags = PROT_WRITE; 231 232 if (td->verify != VERIFY_NONE) 233 flags |= PROT_READ; 234 } else 235 flags = PROT_READ; 236 237 f->mmap = mmap(NULL, f->file_size, flags, MAP_SHARED, f->fd, f->file_offset); 238 if (f->mmap == MAP_FAILED) { 239 f->mmap = NULL; 240 td_verror(td, errno); 241 return 1; 242 } 243 244 if (td->invalidate_cache && file_invalidate_cache(td, f)) 245 return 1; 246 247 if (td->sequential) { 248 if (madvise(f->mmap, f->file_size, MADV_SEQUENTIAL) < 0) { 249 td_verror(td, errno); 250 return 1; 251 } 252 } else { 253 if (madvise(f->mmap, f->file_size, MADV_RANDOM) < 0) { 254 td_verror(td, errno); 255 return 1; 256 } 257 } 258 259 return 0; 260} 261 262static int setup_files_mmap(struct thread_data *td) 263{ 264 struct fio_file *f; 265 int i, err = 0; 266 267 for_each_file(td, f, i) { 268 err = __setup_file_mmap(td, f); 269 if (err) 270 break; 271 } 272 273 return err; 274} 275 276static int __setup_file_plain(struct thread_data *td, struct fio_file *f) 277{ 278 if (td->invalidate_cache && file_invalidate_cache(td, f)) 279 return 1; 280 281 if (td->sequential) { 282 if (fadvise(f->fd, f->file_offset, f->file_size, POSIX_FADV_SEQUENTIAL) < 0) { 283 td_verror(td, errno); 284 return 1; 285 } 286 } else { 287 if (fadvise(f->fd, f->file_offset, f->file_size, POSIX_FADV_RANDOM) < 0) { 288 td_verror(td, errno); 289 return 1; 290 } 291 } 292 293 return 0; 294} 295 296static int setup_files_plain(struct thread_data *td) 297{ 298 struct fio_file *f; 299 int i, err = 0; 300 301 for_each_file(td, f, i) { 302 err = __setup_file_plain(td, f); 303 if (err) 304 break; 305 } 306 307 return err; 308} 309 310static int setup_file(struct thread_data *td, struct fio_file *f) 311{ 312 int flags = 0; 313 314 if (td->odirect) 315 flags |= OS_O_DIRECT; 316 317 if (td_write(td) || td_rw(td)) { 318 if (td->filetype == FIO_TYPE_FILE) { 319 if (!td->overwrite) 320 flags |= O_TRUNC; 321 322 flags |= O_CREAT; 323 } 324 if (td->sync_io) 325 flags |= O_SYNC; 326 327 flags |= O_RDWR; 328 329 f->fd = open(f->file_name, flags, 0600); 330 } else { 331 if (td->filetype == FIO_TYPE_CHAR) 332 flags |= O_RDWR; 333 else 334 flags |= O_RDONLY; 335 336 f->fd = open(f->file_name, flags); 337 } 338 339 if (f->fd == -1) { 340 td_verror(td, errno); 341 return 1; 342 } 343 344 if (get_file_size(td, f)) 345 return 1; 346 347 return 0; 348} 349 350int setup_files(struct thread_data *td) 351{ 352 struct fio_file *f; 353 int i, err; 354 355 /* 356 * if ioengine defines a setup() method, it's responsible for 357 * setting up everything in the td->files[] area. 358 */ 359 if (td->io_ops->setup) 360 return td->io_ops->setup(td); 361 362 if (create_files(td)) 363 return 1; 364 365 err = 0; 366 for_each_file(td, f, i) { 367 err = setup_file(td, f); 368 if (err) 369 break; 370 } 371 372 if (err) 373 return err; 374 375 /* 376 * Recalculate the total file size now that files are set up. 377 */ 378 td->total_file_size = 0; 379 for_each_file(td, f, i) 380 td->total_file_size += f->file_size; 381 382 td->io_size = td->total_file_size; 383 if (td->io_size == 0) { 384 log_err("%s: no io blocks\n", td->name); 385 td_verror(td, EINVAL); 386 return 1; 387 } 388 389 if (!td->zone_size) 390 td->zone_size = td->io_size; 391 392 td->total_io_size = td->io_size * td->loops; 393 394 if (td->io_ops->flags & FIO_MMAPIO) 395 return setup_files_mmap(td); 396 else 397 return setup_files_plain(td); 398} 399 400void close_files(struct thread_data *td) 401{ 402 struct fio_file *f; 403 int i; 404 405 for_each_file(td, f, i) { 406 if (f->fd != -1) { 407 if (td->unlink && td->filetype == FIO_TYPE_FILE) 408 unlink(f->file_name); 409 free(f->file_name); 410 f->file_name = NULL; 411 close(f->fd); 412 f->fd = -1; 413 } 414 if (f->mmap) { 415 munmap(f->mmap, f->file_size); 416 f->mmap = NULL; 417 } 418 } 419 420 free(td->files); 421 td->files = NULL; 422 td->nr_files = 0; 423} 424