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