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