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