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