Add documentation for the random number generator
[fio.git] / filesetup.c
1 #include <unistd.h>
2 #include <fcntl.h>
3 #include <string.h>
4 #include <assert.h>
5 #include <dirent.h>
6 #include <sys/stat.h>
7 #include <sys/mman.h>
8 #include <sys/types.h>
9
10 #include "fio.h"
11 #include "smalloc.h"
12 #include "filehash.h"
13
14 static int root_warn;
15
16 static inline void clear_error(struct thread_data *td)
17 {
18         td->error = 0;
19         td->verror[0] = '\0';
20 }
21
22 /*
23  * Leaves f->fd open on success, caller must close
24  */
25 static int extend_file(struct thread_data *td, struct fio_file *f)
26 {
27         int r, new_layout = 0, unlink_file = 0, flags;
28         unsigned long long left;
29         unsigned int bs;
30         char *b;
31
32         if (read_only) {
33                 log_err("fio: refusing extend of file due to read-only\n");
34                 return 0;
35         }
36
37         /*
38          * check if we need to lay the file out complete again. fio
39          * does that for operations involving reads, or for writes
40          * where overwrite is set
41          */
42         if (td_read(td) || (td_write(td) && td->o.overwrite) ||
43             (td_write(td) && td->io_ops->flags & FIO_NOEXTEND))
44                 new_layout = 1;
45         if (td_write(td) && !td->o.overwrite)
46                 unlink_file = 1;
47
48         if (unlink_file || new_layout) {
49                 dprint(FD_FILE, "layout unlink %s\n", f->file_name);
50                 if ((unlink(f->file_name) < 0) && (errno != ENOENT)) {
51                         td_verror(td, errno, "unlink");
52                         return 1;
53                 }
54         }
55
56         flags = O_WRONLY | O_CREAT;
57         if (new_layout)
58                 flags |= O_TRUNC;
59
60         dprint(FD_FILE, "open file %s, flags %x\n", f->file_name, flags);
61         f->fd = open(f->file_name, flags, 0644);
62         if (f->fd < 0) {
63                 td_verror(td, errno, "open");
64                 return 1;
65         }
66
67 #ifdef FIO_HAVE_FALLOCATE
68         if (td->o.fallocate && !td->o.fill_device) {
69                 dprint(FD_FILE, "fallocate file %s size %llu\n", f->file_name,
70                                                         f->real_file_size);
71
72                 r = posix_fallocate(f->fd, 0, f->real_file_size);
73                 if (r < 0) {
74                         log_err("fio: posix_fallocate fails: %s\n",
75                                         strerror(-r));
76                 }
77         }
78 #endif
79         
80         if (!new_layout)
81                 goto done;
82
83         /*
84          * The size will be -1ULL when fill_device is used, so don't truncate
85          * or fallocate this file, just write it
86          */
87         if (!td->o.fill_device) {
88                 dprint(FD_FILE, "truncate file %s, size %llu\n", f->file_name,
89                                                         f->real_file_size);
90                 if (ftruncate(f->fd, f->real_file_size) == -1) {
91                         td_verror(td, errno, "ftruncate");
92                         goto err;
93                 }
94         }
95
96         b = malloc(td->o.max_bs[DDIR_WRITE]);
97         memset(b, 0, td->o.max_bs[DDIR_WRITE]);
98
99         left = f->real_file_size;
100         while (left && !td->terminate) {
101                 bs = td->o.max_bs[DDIR_WRITE];
102                 if (bs > left)
103                         bs = left;
104
105                 r = write(f->fd, b, bs);
106
107                 if (r > 0) {
108                         left -= r;
109                         continue;
110                 } else {
111                         if (r < 0) {
112                                 int __e = errno;
113
114                                 if (__e == ENOSPC) {
115                                         if (td->o.fill_device)
116                                                 break;
117                                         log_info("fio: ENOSPC on laying out "
118                                                  "file, stopping\n");
119                                         break;
120                                 }
121                                 td_verror(td, errno, "write");
122                         } else
123                                 td_verror(td, EIO, "write");
124
125                         break;
126                 }
127         }
128
129         if (td->terminate) {
130                 dprint(FD_FILE, "terminate unlink %s\n", f->file_name);
131                 unlink(f->file_name);
132         } else if (td->o.create_fsync) {
133                 if (fsync(f->fd) < 0) {
134                         td_verror(td, errno, "fsync");
135                         goto err;
136                 }
137         }
138         if (td->o.fill_device && !td_write(td)) {
139                 fio_file_clear_size_known(f);
140                 if (td_io_get_file_size(td, f))
141                         goto err;
142                 if (f->io_size > f->real_file_size)
143                         f->io_size = f->real_file_size;
144         }
145
146         free(b);
147 done:
148         return 0;
149 err:
150         close(f->fd);
151         f->fd = -1;
152         return 1;
153 }
154
155 static int pre_read_file(struct thread_data *td, struct fio_file *f)
156 {
157         int r, did_open = 0, old_runstate;
158         unsigned long long left;
159         unsigned int bs;
160         char *b;
161
162         if (td->io_ops->flags & FIO_PIPEIO)
163                 return 0;
164
165         if (!fio_file_open(f)) {
166                 if (td->io_ops->open_file(td, f)) {
167                         log_err("fio: cannot pre-read, failed to open file\n");
168                         return 1;
169                 }
170                 did_open = 1;
171         }
172
173         old_runstate = td->runstate;
174         td_set_runstate(td, TD_PRE_READING);
175
176         bs = td->o.max_bs[DDIR_READ];
177         b = malloc(bs);
178         memset(b, 0, bs);
179
180         lseek(f->fd, f->file_offset, SEEK_SET);
181         left = f->io_size;
182
183         while (left && !td->terminate) {
184                 if (bs > left)
185                         bs = left;
186
187                 r = read(f->fd, b, bs);
188
189                 if (r == (int) bs) {
190                         left -= bs;
191                         continue;
192                 } else {
193                         td_verror(td, EIO, "pre_read");
194                         break;
195                 }
196         }
197
198         td_set_runstate(td, old_runstate);
199
200         if (did_open)
201                 td->io_ops->close_file(td, f);
202         free(b);
203         return 0;
204 }
205
206 static unsigned long long get_rand_file_size(struct thread_data *td)
207 {
208         unsigned long long ret, sized;
209         long r;
210
211         r = os_random_long(&td->file_size_state);
212         sized = td->o.file_size_high - td->o.file_size_low;
213         ret = (unsigned long long) ((double) sized * (r / (OS_RAND_MAX + 1.0)));
214         ret += td->o.file_size_low;
215         ret -= (ret % td->o.rw_min_bs);
216         return ret;
217 }
218
219 static int file_size(struct thread_data *td, struct fio_file *f)
220 {
221         struct stat st;
222
223         if (stat(f->file_name, &st) == -1) {
224                 td_verror(td, errno, "fstat");
225                 return 1;
226         }
227
228         f->real_file_size = st.st_size;
229         return 0;
230 }
231
232 static int bdev_size(struct thread_data *td, struct fio_file *f)
233 {
234         unsigned long long bytes;
235         int r;
236
237         if (td->io_ops->open_file(td, f)) {
238                 log_err("fio: failed opening blockdev %s for size check\n",
239                         f->file_name);
240                 return 1;
241         }
242
243         r = blockdev_size(f->fd, &bytes);
244         if (r) {
245                 td_verror(td, r, "blockdev_size");
246                 goto err;
247         }
248
249         if (!bytes) {
250                 log_err("%s: zero sized block device?\n", f->file_name);
251                 goto err;
252         }
253
254         f->real_file_size = bytes;
255         td->io_ops->close_file(td, f);
256         return 0;
257 err:
258         td->io_ops->close_file(td, f);
259         return 1;
260 }
261
262 static int get_file_size(struct thread_data *td, struct fio_file *f)
263 {
264         int ret = 0;
265
266         if (fio_file_size_known(f))
267                 return 0;
268
269         if (f->filetype == FIO_TYPE_FILE)
270                 ret = file_size(td, f);
271         else if (f->filetype == FIO_TYPE_BD)
272                 ret = bdev_size(td, f);
273         else
274                 f->real_file_size = -1;
275
276         if (ret)
277                 return ret;
278
279         if (f->file_offset > f->real_file_size) {
280                 log_err("%s: offset extends end (%Lu > %Lu)\n", td->o.name,
281                                         f->file_offset, f->real_file_size);
282                 return 1;
283         }
284
285         fio_file_set_size_known(f);
286         return 0;
287 }
288
289 static int __file_invalidate_cache(struct thread_data *td, struct fio_file *f,
290                                    unsigned long long off,
291                                    unsigned long long len)
292 {
293         int ret = 0;
294
295         if (len == -1ULL)
296                 len = f->io_size;
297         if (off == -1ULL)
298                 off = f->file_offset;
299
300         if (len == -1ULL || off == -1ULL)
301                 return 0;
302
303         dprint(FD_IO, "invalidate cache %s: %llu/%llu\n", f->file_name, off,
304                                                                 len);
305
306         /*
307          * FIXME: add blockdev flushing too
308          */
309         if (f->mmap_ptr) {
310                 ret = madvise(f->mmap_ptr, f->mmap_sz, MADV_DONTNEED);
311 #ifdef FIO_MADV_FREE
312                 (void) madvise(f->mmap_ptr, f->mmap_sz, FIO_MADV_FREE);
313 #endif
314         } else if (f->filetype == FIO_TYPE_FILE) {
315                 ret = fadvise(f->fd, off, len, POSIX_FADV_DONTNEED);
316         } else if (f->filetype == FIO_TYPE_BD) {
317                 ret = blockdev_invalidate_cache(f->fd);
318                 if (ret < 0 && errno == EACCES && geteuid()) {
319                         if (!root_warn) {
320                                 log_err("fio: only root may flush block "
321                                         "devices. Cache flush bypassed!\n");
322                                 root_warn = 1;
323                         }
324                         ret = 0;
325                 }
326         } else if (f->filetype == FIO_TYPE_CHAR || f->filetype == FIO_TYPE_PIPE)
327                 ret = 0;
328
329         if (ret < 0) {
330                 td_verror(td, errno, "invalidate_cache");
331                 return 1;
332         } else if (ret > 0) {
333                 td_verror(td, ret, "invalidate_cache");
334                 return 1;
335         }
336
337         return ret;
338
339 }
340
341 int file_invalidate_cache(struct thread_data *td, struct fio_file *f)
342 {
343         if (!fio_file_open(f))
344                 return 0;
345
346         return __file_invalidate_cache(td, f, -1ULL, -1ULL);
347 }
348
349 int generic_close_file(struct thread_data fio_unused *td, struct fio_file *f)
350 {
351         int ret = 0;
352
353         dprint(FD_FILE, "fd close %s\n", f->file_name);
354
355         remove_file_hash(f);
356
357         if (close(f->fd) < 0)
358                 ret = errno;
359
360         f->fd = -1;
361         return ret;
362 }
363
364 static int file_lookup_open(struct fio_file *f, int flags)
365 {
366         struct fio_file *__f;
367         int from_hash;
368
369         __f = lookup_file_hash(f->file_name);
370         if (__f) {
371                 dprint(FD_FILE, "found file in hash %s\n", f->file_name);
372                 /*
373                  * racy, need the __f->lock locked
374                  */
375                 f->lock = __f->lock;
376                 f->lock_owner = __f->lock_owner;
377                 f->lock_batch = __f->lock_batch;
378                 f->lock_ddir = __f->lock_ddir;
379                 from_hash = 1;
380         } else {
381                 dprint(FD_FILE, "file not found in hash %s\n", f->file_name);
382                 from_hash = 0;
383         }
384
385         f->fd = open(f->file_name, flags, 0600);
386         return from_hash;
387 }
388
389 int generic_open_file(struct thread_data *td, struct fio_file *f)
390 {
391         int is_std = 0;
392         int flags = 0;
393         int from_hash = 0;
394
395         dprint(FD_FILE, "fd open %s\n", f->file_name);
396
397         if (!strcmp(f->file_name, "-")) {
398                 if (td_rw(td)) {
399                         log_err("fio: can't read/write to stdin/out\n");
400                         return 1;
401                 }
402                 is_std = 1;
403
404                 /*
405                  * move output logging to stderr, if we are writing to stdout
406                  */
407                 if (td_write(td))
408                         f_out = stderr;
409         }
410
411         if (td->o.odirect)
412                 flags |= OS_O_DIRECT;
413         if (td->o.sync_io)
414                 flags |= O_SYNC;
415         if (f->filetype != FIO_TYPE_FILE)
416                 flags |= FIO_O_NOATIME;
417         if (td->o.create_on_open)
418                 flags |= O_CREAT;
419
420 open_again:
421         if (td_write(td)) {
422                 if (!read_only)
423                         flags |= O_RDWR;
424
425                 if (f->filetype == FIO_TYPE_FILE)
426                         flags |= O_CREAT;
427
428                 if (is_std)
429                         f->fd = dup(STDOUT_FILENO);
430                 else
431                         from_hash = file_lookup_open(f, flags);
432         } else {
433                 if (f->filetype == FIO_TYPE_CHAR && !read_only)
434                         flags |= O_RDWR;
435                 else
436                         flags |= O_RDONLY;
437
438                 if (is_std)
439                         f->fd = dup(STDIN_FILENO);
440                 else
441                         from_hash = file_lookup_open(f, flags);
442         }
443
444         if (f->fd == -1) {
445                 char buf[FIO_VERROR_SIZE];
446                 int __e = errno;
447
448                 if (__e == EPERM && (flags & FIO_O_NOATIME)) {
449                         flags &= ~FIO_O_NOATIME;
450                         goto open_again;
451                 }
452
453                 snprintf(buf, sizeof(buf) - 1, "open(%s)", f->file_name);
454
455                 td_verror(td, __e, buf);
456         }
457
458         if (!from_hash && f->fd != -1) {
459                 if (add_file_hash(f)) {
460                         int ret;
461
462                         /*
463                          * OK to ignore, we haven't done anything with it
464                          */
465                         ret = generic_close_file(td, f);
466                         goto open_again;
467                 }
468         }
469
470         return 0;
471 }
472
473 int generic_get_file_size(struct thread_data *td, struct fio_file *f)
474 {
475         return get_file_size(td, f);
476 }
477
478 /*
479  * open/close all files, so that ->real_file_size gets set
480  */
481 static int get_file_sizes(struct thread_data *td)
482 {
483         struct fio_file *f;
484         unsigned int i;
485         int err = 0;
486
487         for_each_file(td, f, i) {
488                 dprint(FD_FILE, "get file size for %p/%d/%p\n", f, i,
489                                                                 f->file_name);
490
491                 if (td_io_get_file_size(td, f)) {
492                         if (td->error != ENOENT) {
493                                 log_err("%s\n", td->verror);
494                                 err = 1;
495                         }
496                         clear_error(td);
497                 }
498
499                 if (f->real_file_size == -1ULL && td->o.size)
500                         f->real_file_size = td->o.size / td->o.nr_files;
501         }
502
503         return err;
504 }
505
506 /*
507  * Open the files and setup files sizes, creating files if necessary.
508  */
509 int setup_files(struct thread_data *td)
510 {
511         unsigned long long total_size, extend_size;
512         struct fio_file *f;
513         unsigned int i;
514         int err = 0, need_extend;
515
516         dprint(FD_FILE, "setup files\n");
517
518         if (td->o.read_iolog_file)
519                 return 0;
520
521         /*
522          * if ioengine defines a setup() method, it's responsible for
523          * opening the files and setting f->real_file_size to indicate
524          * the valid range for that file.
525          */
526         if (td->io_ops->setup)
527                 err = td->io_ops->setup(td);
528         else
529                 err = get_file_sizes(td);
530
531         if (err)
532                 return err;
533
534         /*
535          * check sizes. if the files/devices do not exist and the size
536          * isn't passed to fio, abort.
537          */
538         total_size = 0;
539         for_each_file(td, f, i) {
540                 if (f->real_file_size == -1ULL)
541                         total_size = -1ULL;
542                 else
543                         total_size += f->real_file_size;
544         }
545
546         /*
547          * device/file sizes are zero and no size given, punt
548          */
549         if ((!total_size || total_size == -1ULL) && !td->o.size &&
550             !(td->io_ops->flags & FIO_NOIO) && !td->o.fill_device) {
551                 log_err("%s: you need to specify size=\n", td->o.name);
552                 td_verror(td, EINVAL, "total_file_size");
553                 return 1;
554         }
555
556         /*
557          * now file sizes are known, so we can set ->io_size. if size= is
558          * not given, ->io_size is just equal to ->real_file_size. if size
559          * is given, ->io_size is size / nr_files.
560          */
561         extend_size = total_size = 0;
562         need_extend = 0;
563         for_each_file(td, f, i) {
564                 f->file_offset = td->o.start_offset;
565
566                 if (!td->o.file_size_low) {
567                         /*
568                          * no file size range given, file size is equal to
569                          * total size divided by number of files. if that is
570                          * zero, set it to the real file size.
571                          */
572                         f->io_size = td->o.size / td->o.nr_files;
573                         if (!f->io_size)
574                                 f->io_size = f->real_file_size - f->file_offset;
575                 } else if (f->real_file_size < td->o.file_size_low ||
576                            f->real_file_size > td->o.file_size_high) {
577                         if (f->file_offset > td->o.file_size_low)
578                                 goto err_offset;
579                         /*
580                          * file size given. if it's fixed, use that. if it's a
581                          * range, generate a random size in-between.
582                          */
583                         if (td->o.file_size_low == td->o.file_size_high) {
584                                 f->io_size = td->o.file_size_low
585                                                 - f->file_offset;
586                         } else {
587                                 f->io_size = get_rand_file_size(td)
588                                                 - f->file_offset;
589                         }
590                 } else
591                         f->io_size = f->real_file_size - f->file_offset;
592
593                 if (f->io_size == -1ULL)
594                         total_size = -1ULL;
595                 else
596                         total_size += f->io_size;
597
598                 if (f->filetype == FIO_TYPE_FILE &&
599                     (f->io_size + f->file_offset) > f->real_file_size &&
600                     !(td->io_ops->flags & FIO_DISKLESSIO)) {
601                         if (!td->o.create_on_open) {
602                                 need_extend++;
603                                 extend_size += (f->io_size + f->file_offset);
604                         } else
605                                 f->real_file_size = f->io_size + f->file_offset;
606                         fio_file_set_extend(f);
607                 }
608         }
609
610         if (!td->o.size || td->o.size > total_size)
611                 td->o.size = total_size;
612
613         /*
614          * See if we need to extend some files
615          */
616         if (need_extend) {
617                 temp_stall_ts = 1;
618                 if (!terse_output)
619                         log_info("%s: Laying out IO file(s) (%u file(s) /"
620                                  " %LuMB)\n", td->o.name, need_extend,
621                                         extend_size >> 20);
622
623                 for_each_file(td, f, i) {
624                         unsigned long long old_len = -1ULL, extend_len = -1ULL;
625
626                         if (!fio_file_extend(f))
627                                 continue;
628
629                         assert(f->filetype == FIO_TYPE_FILE);
630                         fio_file_clear_extend(f);
631                         if (!td->o.fill_device) {
632                                 old_len = f->real_file_size;
633                                 extend_len = f->io_size + f->file_offset -
634                                                 old_len;
635                         }
636                         f->real_file_size = (f->io_size + f->file_offset);
637                         err = extend_file(td, f);
638                         if (err)
639                                 break;
640
641                         err = __file_invalidate_cache(td, f, old_len,
642                                                                 extend_len);
643                         close(f->fd);
644                         f->fd = -1;
645                         if (err)
646                                 break;
647                 }
648                 temp_stall_ts = 0;
649         }
650
651         if (err)
652                 return err;
653
654         if (!td->o.zone_size)
655                 td->o.zone_size = td->o.size;
656
657         /*
658          * iolog already set the total io size, if we read back
659          * stored entries.
660          */
661         if (!td->o.read_iolog_file)
662                 td->total_io_size = td->o.size * td->o.loops;
663         return 0;
664 err_offset:
665         log_err("%s: you need to specify valid offset=\n", td->o.name);
666         return 1;
667 }
668
669 int pre_read_files(struct thread_data *td)
670 {
671         struct fio_file *f;
672         unsigned int i;
673
674         dprint(FD_FILE, "pre_read files\n");
675
676         for_each_file(td, f, i) {
677                 pre_read_file(td, f);
678         }
679
680         return 1;
681 }
682
683 int init_random_map(struct thread_data *td)
684 {
685         unsigned long long blocks, num_maps;
686         struct fio_file *f;
687         unsigned int i;
688
689         if (td->o.norandommap || !td_random(td))
690                 return 0;
691
692         for_each_file(td, f, i) {
693                 blocks = (f->real_file_size + td->o.rw_min_bs - 1) /
694                                 (unsigned long long) td->o.rw_min_bs;
695                 num_maps = (blocks + BLOCKS_PER_MAP - 1) /
696                                 (unsigned long long) BLOCKS_PER_MAP;
697                 f->file_map = smalloc(num_maps * sizeof(int));
698                 if (f->file_map) {
699                         f->num_maps = num_maps;
700                         continue;
701                 }
702                 if (!td->o.softrandommap) {
703                         log_err("fio: failed allocating random map. If running"
704                                 " a large number of jobs, try the 'norandommap'"
705                                 " option or set 'softrandommap'. Or give"
706                                 " a larger --alloc-size to fio.\n");
707                         return 1;
708                 }
709
710                 log_info("fio: file %s failed allocating random map. Running "
711                          "job without.\n", f->file_name);
712                 f->num_maps = 0;
713         }
714
715         return 0;
716 }
717
718 void close_files(struct thread_data *td)
719 {
720         struct fio_file *f;
721         unsigned int i;
722
723         for_each_file(td, f, i) {
724                 if (fio_file_open(f))
725                         td_io_close_file(td, f);
726         }
727 }
728
729 void close_and_free_files(struct thread_data *td)
730 {
731         struct fio_file *f;
732         unsigned int i;
733
734         dprint(FD_FILE, "close files\n");
735
736         for_each_file(td, f, i) {
737                 if (td->o.unlink && f->filetype == FIO_TYPE_FILE) {
738                         dprint(FD_FILE, "free unlink %s\n", f->file_name);
739                         unlink(f->file_name);
740                 }
741
742                 if (fio_file_open(f))
743                         td_io_close_file(td, f);
744
745                 remove_file_hash(f);
746
747                 sfree(f->file_name);
748                 f->file_name = NULL;
749
750                 if (f->file_map) {
751                         sfree(f->file_map);
752                         f->file_map = NULL;
753                 }
754                 sfree(f);
755         }
756
757         td->o.filename = NULL;
758         free(td->files);
759         td->files_index = 0;
760         td->files = NULL;
761         td->o.nr_files = 0;
762 }
763
764 static void get_file_type(struct fio_file *f)
765 {
766         struct stat sb;
767
768         if (!strcmp(f->file_name, "-"))
769                 f->filetype = FIO_TYPE_PIPE;
770         else
771                 f->filetype = FIO_TYPE_FILE;
772
773         if (!stat(f->file_name, &sb)) {
774                 if (S_ISBLK(sb.st_mode))
775                         f->filetype = FIO_TYPE_BD;
776                 else if (S_ISCHR(sb.st_mode))
777                         f->filetype = FIO_TYPE_CHAR;
778                 else if (S_ISFIFO(sb.st_mode))
779                         f->filetype = FIO_TYPE_PIPE;
780         }
781 }
782
783 int add_file(struct thread_data *td, const char *fname)
784 {
785         int cur_files = td->files_index;
786         char file_name[PATH_MAX];
787         struct fio_file *f;
788         int len = 0;
789
790         dprint(FD_FILE, "add file %s\n", fname);
791
792         f = smalloc(sizeof(*f));
793         if (!f) {
794                 log_err("fio: smalloc OOM\n");
795                 assert(0);
796         }
797
798         f->fd = -1;
799
800         if (td->files_size <= td->files_index) {
801                 int new_size = td->o.nr_files + 1;
802
803                 dprint(FD_FILE, "resize file array to %d files\n", new_size);
804
805                 td->files = realloc(td->files, new_size * sizeof(f));
806                 td->files_size = new_size;
807         }
808         td->files[cur_files] = f;
809
810         /*
811          * init function, io engine may not be loaded yet
812          */
813         if (td->io_ops && (td->io_ops->flags & FIO_DISKLESSIO))
814                 f->real_file_size = -1ULL;
815
816         if (td->o.directory)
817                 len = sprintf(file_name, "%s/", td->o.directory);
818
819         sprintf(file_name + len, "%s", fname);
820         f->file_name = smalloc_strdup(file_name);
821         if (!f->file_name) {
822                 log_err("fio: smalloc OOM\n");
823                 assert(0);
824         }
825
826         get_file_type(f);
827
828         switch (td->o.file_lock_mode) {
829         case FILE_LOCK_NONE:
830                 break;
831         case FILE_LOCK_READWRITE:
832                 f->lock = fio_mutex_rw_init();
833                 break;
834         case FILE_LOCK_EXCLUSIVE:
835                 f->lock = fio_mutex_init(1);
836                 break;
837         default:
838                 log_err("fio: unknown lock mode: %d\n", td->o.file_lock_mode);
839                 assert(0);
840         }
841
842         td->files_index++;
843         if (f->filetype == FIO_TYPE_FILE)
844                 td->nr_normal_files++;
845
846         dprint(FD_FILE, "file %p \"%s\" added at %d\n", f, f->file_name,
847                                                         cur_files);
848
849         return cur_files;
850 }
851
852 void get_file(struct fio_file *f)
853 {
854         dprint(FD_FILE, "get file %s, ref=%d\n", f->file_name, f->references);
855         assert(fio_file_open(f));
856         f->references++;
857 }
858
859 int put_file(struct thread_data *td, struct fio_file *f)
860 {
861         int f_ret = 0, ret = 0;
862
863         dprint(FD_FILE, "put file %s, ref=%d\n", f->file_name, f->references);
864
865         if (!fio_file_open(f)) {
866                 assert(f->fd == -1);
867                 return 0;
868         }
869
870         assert(f->references);
871         if (--f->references)
872                 return 0;
873
874         if (should_fsync(td) && td->o.fsync_on_close)
875                 f_ret = fsync(f->fd);
876
877         if (td->io_ops->close_file)
878                 ret = td->io_ops->close_file(td, f);
879
880         if (!ret)
881                 ret = f_ret;
882
883         td->nr_open_files--;
884         fio_file_clear_open(f);
885         assert(f->fd == -1);
886         return ret;
887 }
888
889 void lock_file(struct thread_data *td, struct fio_file *f, enum fio_ddir ddir)
890 {
891         if (!f->lock || td->o.file_lock_mode == FILE_LOCK_NONE)
892                 return;
893
894         if (f->lock_owner == td && f->lock_batch--)
895                 return;
896
897         if (td->o.file_lock_mode == FILE_LOCK_READWRITE) {
898                 if (ddir == DDIR_READ)
899                         fio_mutex_down_read(f->lock);
900                 else
901                         fio_mutex_down_write(f->lock);
902         } else if (td->o.file_lock_mode == FILE_LOCK_EXCLUSIVE)
903                 fio_mutex_down(f->lock);
904
905         f->lock_owner = td;
906         f->lock_batch = td->o.lockfile_batch;
907         f->lock_ddir = ddir;
908 }
909
910 void unlock_file(struct thread_data *td, struct fio_file *f)
911 {
912         if (!f->lock || td->o.file_lock_mode == FILE_LOCK_NONE)
913                 return;
914         if (f->lock_batch)
915                 return;
916
917         if (td->o.file_lock_mode == FILE_LOCK_READWRITE) {
918                 const int is_read = f->lock_ddir == DDIR_READ;
919                 int val = fio_mutex_getval(f->lock);
920
921                 if ((is_read && val == 1) || (!is_read && val == -1))
922                         f->lock_owner = NULL;
923
924                 if (is_read)
925                         fio_mutex_up_read(f->lock);
926                 else
927                         fio_mutex_up_write(f->lock);
928         } else if (td->o.file_lock_mode == FILE_LOCK_EXCLUSIVE) {
929                 int val = fio_mutex_getval(f->lock);
930
931                 if (val == 0)
932                         f->lock_owner = NULL;
933
934                 fio_mutex_up(f->lock);
935         }
936 }
937
938 void unlock_file_all(struct thread_data *td, struct fio_file *f)
939 {
940         if (f->lock_owner != td)
941                 return;
942
943         f->lock_batch = 0;
944         unlock_file(td, f);
945 }
946
947 static int recurse_dir(struct thread_data *td, const char *dirname)
948 {
949         struct dirent *dir;
950         int ret = 0;
951         DIR *D;
952
953         D = opendir(dirname);
954         if (!D) {
955                 char buf[FIO_VERROR_SIZE];
956
957                 snprintf(buf, FIO_VERROR_SIZE - 1, "opendir(%s)", dirname);
958                 td_verror(td, errno, buf);
959                 return 1;
960         }
961
962         while ((dir = readdir(D)) != NULL) {
963                 char full_path[PATH_MAX];
964                 struct stat sb;
965
966                 if (!strcmp(dir->d_name, ".") || !strcmp(dir->d_name, ".."))
967                         continue;
968
969                 sprintf(full_path, "%s/%s", dirname, dir->d_name);
970
971                 if (lstat(full_path, &sb) == -1) {
972                         if (errno != ENOENT) {
973                                 td_verror(td, errno, "stat");
974                                 return 1;
975                         }
976                 }
977
978                 if (S_ISREG(sb.st_mode)) {
979                         add_file(td, full_path);
980                         td->o.nr_files++;
981                         continue;
982                 }
983                 if (!S_ISDIR(sb.st_mode))
984                         continue;
985
986                 ret = recurse_dir(td, full_path);
987                 if (ret)
988                         break;
989         }
990
991         closedir(D);
992         return ret;
993 }
994
995 int add_dir_files(struct thread_data *td, const char *path)
996 {
997         int ret = recurse_dir(td, path);
998
999         if (!ret)
1000                 log_info("fio: opendir added %d files\n", td->o.nr_files);
1001
1002         return ret;
1003 }
1004
1005 void dup_files(struct thread_data *td, struct thread_data *org)
1006 {
1007         struct fio_file *f;
1008         unsigned int i;
1009
1010         dprint(FD_FILE, "dup files: %d\n", org->files_index);
1011
1012         if (!org->files)
1013                 return;
1014
1015         td->files = malloc(org->files_index * sizeof(f));
1016
1017         for_each_file(org, f, i) {
1018                 struct fio_file *__f;
1019
1020                 __f = smalloc(sizeof(*__f));
1021                 if (!__f) {
1022                         log_err("fio: smalloc OOM\n");
1023                         assert(0);
1024                 }
1025                 __f->fd = -1;
1026
1027                 if (f->file_name) {
1028                         __f->file_name = smalloc_strdup(f->file_name);
1029                         if (!__f->file_name) {
1030                                 log_err("fio: smalloc OOM\n");
1031                                 assert(0);
1032                         }
1033
1034                         __f->filetype = f->filetype;
1035                 }
1036
1037                 td->files[i] = __f;
1038         }
1039 }
1040
1041 /*
1042  * Returns the index that matches the filename, or -1 if not there
1043  */
1044 int get_fileno(struct thread_data *td, const char *fname)
1045 {
1046         struct fio_file *f;
1047         unsigned int i;
1048
1049         for_each_file(td, f, i)
1050                 if (!strcmp(f->file_name, fname))
1051                         return i;
1052
1053         return -1;
1054 }
1055
1056 /*
1057  * For log usage, where we add/open/close files automatically
1058  */
1059 void free_release_files(struct thread_data *td)
1060 {
1061         close_files(td);
1062         td->files_index = 0;
1063         td->nr_normal_files = 0;
1064 }