filesetup.c revision ea966f8188915643670fd0a13d1bf37d45936da5
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
12static int root_warn;
13
14static int extend_file(struct thread_data *td, struct fio_file *f)
15{
16	int r, new_layout = 0, unlink_file = 0, flags;
17	unsigned long long left;
18	unsigned int bs;
19	char *b;
20
21	/*
22	 * check if we need to lay the file out complete again. fio
23	 * does that for operations involving reads, or for writes
24	 * where overwrite is set
25	 */
26	if (td_read(td) || (td_write(td) && td->o.overwrite))
27		new_layout = 1;
28	if (td_write(td) && !td->o.overwrite)
29		unlink_file = 1;
30
31	if ((unlink_file || new_layout) && (f->flags & FIO_FILE_EXISTS)) {
32		if (unlink(f->file_name) < 0) {
33			td_verror(td, errno, "unlink");
34			return 1;
35		}
36	}
37
38	flags = O_WRONLY | O_CREAT;
39	if (new_layout)
40		flags |= O_TRUNC;
41
42	f->fd = open(f->file_name, flags, 0644);
43	if (f->fd < 0) {
44		td_verror(td, errno, "open");
45		return 1;
46	}
47
48	if (ftruncate(f->fd, f->real_file_size) == -1) {
49		td_verror(td, errno, "ftruncate");
50		goto err;
51	}
52
53	if (!new_layout)
54		goto done;
55
56	if (posix_fallocate(f->fd, 0, f->real_file_size) < 0) {
57		td_verror(td, errno, "posix_fallocate");
58		goto err;
59	}
60
61	b = malloc(td->o.max_bs[DDIR_WRITE]);
62	memset(b, 0, td->o.max_bs[DDIR_WRITE]);
63
64	left = f->real_file_size;
65	while (left && !td->terminate) {
66		bs = td->o.max_bs[DDIR_WRITE];
67		if (bs > left)
68			bs = left;
69
70		r = write(f->fd, b, bs);
71
72		if (r == (int) bs) {
73			left -= bs;
74			continue;
75		} else {
76			if (r < 0)
77				td_verror(td, errno, "write");
78			else
79				td_verror(td, EIO, "write");
80
81			break;
82		}
83	}
84
85	if (td->terminate)
86		unlink(f->file_name);
87	else if (td->o.create_fsync)
88		fsync(f->fd);
89
90	free(b);
91done:
92	close(f->fd);
93	f->fd = -1;
94	return 0;
95err:
96	close(f->fd);
97	f->fd = -1;
98	return 1;
99}
100
101static unsigned long long get_rand_file_size(struct thread_data *td)
102{
103	unsigned long long ret;
104	long r;
105
106	r = os_random_long(&td->file_size_state);
107	ret = td->o.file_size_low + (unsigned long long) ((double) (td->o.file_size_high - td->o.file_size_low) * (r / (RAND_MAX + 1.0)));
108	ret -= (ret % td->o.rw_min_bs);
109	return ret;
110}
111
112static int file_size(struct thread_data *td, struct fio_file *f)
113{
114	struct stat st;
115
116	if (fstat(f->fd, &st) == -1) {
117		td_verror(td, errno, "fstat");
118		return 1;
119	}
120
121	f->real_file_size = st.st_size;
122	return 0;
123}
124
125static int bdev_size(struct thread_data *td, struct fio_file *f)
126{
127	unsigned long long bytes;
128	int r;
129
130	r = blockdev_size(f->fd, &bytes);
131	if (r) {
132		td_verror(td, r, "blockdev_size");
133		return 1;
134	}
135
136	f->real_file_size = bytes;
137	return 0;
138}
139
140static int get_file_size(struct thread_data *td, struct fio_file *f)
141{
142	int ret = 0;
143
144	if (f->flags & FIO_SIZE_KNOWN)
145		return 0;
146
147	if (f->filetype == FIO_TYPE_FILE)
148		ret = file_size(td, f);
149	else if (f->filetype == FIO_TYPE_BD)
150		ret = bdev_size(td, f);
151	else
152		f->real_file_size = -1;
153
154	if (ret)
155		return ret;
156
157	if (f->file_offset > f->real_file_size) {
158		log_err("%s: offset extends end (%Lu > %Lu)\n", td->o.name, f->file_offset, f->real_file_size);
159		return 1;
160	}
161
162	f->flags |= FIO_SIZE_KNOWN;
163	return 0;
164}
165
166int file_invalidate_cache(struct thread_data *td, struct fio_file *f)
167{
168	int ret = 0;
169
170	if (td->o.odirect)
171		return 0;
172
173	/*
174	 * FIXME: add blockdev flushing too
175	 */
176	if (f->mmap)
177		ret = madvise(f->mmap, f->io_size, MADV_DONTNEED);
178	else if (f->filetype == FIO_TYPE_FILE)
179		ret = fadvise(f->fd, f->file_offset, f->io_size, POSIX_FADV_DONTNEED);
180	else if (f->filetype == FIO_TYPE_BD) {
181		ret = blockdev_invalidate_cache(f->fd);
182		if (ret < 0 && errno == EACCES && geteuid()) {
183			if (!root_warn) {
184				log_err("fio: only root may flush block devices. Cache flush bypassed!\n");
185				root_warn = 1;
186			}
187			ret = 0;
188		}
189	} else if (f->filetype == FIO_TYPE_CHAR || f->filetype == FIO_TYPE_PIPE)
190		ret = 0;
191
192	if (ret < 0) {
193		td_verror(td, errno, "invalidate_cache");
194		return 1;
195	}
196
197	return ret;
198}
199
200void generic_close_file(struct thread_data fio_unused *td, struct fio_file *f)
201{
202	close(f->fd);
203	f->fd = -1;
204}
205
206int generic_open_file(struct thread_data *td, struct fio_file *f)
207{
208	int is_std = 0;
209	int flags = 0;
210
211	if (!strcmp(f->file_name, "-")) {
212		if (td_rw(td)) {
213			log_err("fio: can't read/write to stdin/out\n");
214			return 1;
215		}
216		is_std = 1;
217
218		/*
219		 * move output logging to stderr, if we are writing to stdout
220		 */
221		if (td_write(td))
222			f_out = stderr;
223	}
224
225	if (td->o.odirect)
226		flags |= OS_O_DIRECT;
227	if (td->o.sync_io)
228		flags |= O_SYNC;
229
230	if (td_write(td)) {
231		flags |= O_RDWR;
232
233		if (f->filetype == FIO_TYPE_FILE)
234			flags |= O_CREAT;
235
236		if (is_std)
237			f->fd = dup(STDOUT_FILENO);
238		else
239			f->fd = open(f->file_name, flags, 0600);
240	} else {
241		if (f->filetype == FIO_TYPE_CHAR)
242			flags |= O_RDWR;
243		else
244			flags |= O_RDONLY;
245
246		if (is_std)
247			f->fd = dup(STDIN_FILENO);
248		else
249			f->fd = open(f->file_name, flags);
250	}
251
252	if (f->fd == -1) {
253		char buf[FIO_VERROR_SIZE];
254		int __e = errno;
255
256		snprintf(buf, sizeof(buf) - 1, "open(%s)", f->file_name);
257
258		td_verror(td, __e, buf);
259	}
260
261	if (get_file_size(td, f))
262		goto err;
263
264	return 0;
265err:
266	close(f->fd);
267	return 1;
268}
269
270int open_files(struct thread_data *td)
271{
272	struct fio_file *f;
273	unsigned int i;
274	int err = 0;
275
276	for_each_file(td, f, i) {
277		err = td_io_open_file(td, f);
278		if (err) {
279			if (td->error == EMFILE) {
280				log_err("fio: limited open files to: %d\n", td->nr_open_files);
281				td->o.open_files = td->nr_open_files;
282				err = 0;
283				clear_error(td);
284			}
285			break;
286		}
287
288		if (td->o.open_files == td->nr_open_files)
289			break;
290	}
291
292	if (!err)
293		return 0;
294
295	for_each_file(td, f, i)
296		td_io_close_file(td, f);
297
298	return err;
299}
300
301/*
302 * open/close all files, so that ->real_file_size gets set
303 */
304static int get_file_sizes(struct thread_data *td)
305{
306	struct fio_file *f;
307	unsigned int i;
308	int err = 0;
309
310	for_each_file(td, f, i) {
311		if (td->io_ops->open_file(td, f)) {
312			if (td->error != ENOENT) {
313				log_err("%s\n", td->verror);
314				err = 1;
315			}
316			clear_error(td);
317		} else {
318			if (td->io_ops->close_file)
319				td->io_ops->close_file(td, f);
320		}
321
322		if (f->real_file_size == -1ULL && td->o.size)
323			f->real_file_size = td->o.size / td->o.nr_files;
324	}
325
326	return err;
327}
328
329/*
330 * Open the files and setup files sizes, creating files if necessary.
331 */
332int setup_files(struct thread_data *td)
333{
334	unsigned long long total_size, extend_size;
335	struct fio_file *f;
336	unsigned int i;
337	int err = 0, need_extend;
338
339	/*
340	 * if ioengine defines a setup() method, it's responsible for
341	 * opening the files and setting f->real_file_size to indicate
342	 * the valid range for that file.
343	 */
344	if (td->io_ops->setup)
345		err = td->io_ops->setup(td);
346	else
347		err = get_file_sizes(td);
348
349	if (err)
350		return err;
351
352	/*
353	 * check sizes. if the files/devices do not exist and the size
354	 * isn't passed to fio, abort.
355	 */
356	total_size = 0;
357	for_each_file(td, f, i) {
358		if (f->real_file_size == -1ULL)
359			total_size = -1ULL;
360		else
361			total_size += f->real_file_size;
362	}
363
364	/*
365	 * device/file sizes are zero and no size given, punt
366	 */
367	if ((!total_size || total_size == -1ULL) && !td->o.size) {
368		log_err("%s: you need to specify size=\n", td->o.name);
369		td_verror(td, EINVAL, "total_file_size");
370		return 1;
371	}
372
373	/*
374	 * now file sizes are known, so we can set ->io_size. if size= is
375	 * not given, ->io_size is just equal to ->real_file_size. if size
376	 * is given, ->io_size is size / nr_files.
377	 */
378	extend_size = total_size = 0;
379	need_extend = 0;
380	for_each_file(td, f, i) {
381		f->file_offset = td->o.start_offset;
382
383		if (!td->o.file_size_low) {
384			/*
385			 * no file size range given, file size is equal to
386			 * total size divided by number of files. if that is
387			 * zero, set it to the real file size.
388			 */
389			f->io_size = td->o.size / td->o.nr_files;
390			if (!f->io_size) {
391				if (f->file_offset > f->real_file_size)
392					goto err_offset;
393				f->io_size = f->real_file_size - f->file_offset;
394			}
395		} else if (f->real_file_size < td->o.file_size_low ||
396			   f->real_file_size > td->o.file_size_high) {
397			if (f->file_offset > td->o.file_size_low)
398				goto err_offset;
399			/*
400			 * file size given. if it's fixed, use that. if it's a
401			 * range, generate a random size in-between.
402			 */
403			if (td->o.file_size_low == td->o.file_size_high)
404				f->io_size = td->o.file_size_low - f->file_offset;
405			else
406				f->io_size = get_rand_file_size(td) - f->file_offset;
407		} else if (f->file_offset > f->real_file_size)
408			goto err_offset;
409		else
410			f->io_size = f->real_file_size - f->file_offset;
411
412		if (f->io_size == -1ULL)
413			total_size = -1ULL;
414		else
415			total_size += f->io_size;
416
417		if (f->filetype == FIO_TYPE_FILE &&
418		    (f->io_size + f->file_offset) > f->real_file_size &&
419		    !(td->io_ops->flags & FIO_DISKLESSIO)) {
420			need_extend++;
421			extend_size += (f->io_size + f->file_offset);
422			f->flags |= FIO_FILE_EXTEND;
423		}
424	}
425
426	if (!td->o.size || td->o.size > total_size)
427		td->o.size = total_size;
428
429	/*
430	 * See if we need to extend some files
431	 */
432	if (need_extend) {
433		temp_stall_ts = 1;
434		log_info("%s: Laying out IO file(s) (%u file(s) / %LuMiB)\n",
435			td->o.name, need_extend, extend_size >> 20);
436
437		for_each_file(td, f, i) {
438			if (!(f->flags & FIO_FILE_EXTEND))
439				continue;
440
441			assert(f->filetype == FIO_TYPE_FILE);
442			f->flags &= ~FIO_FILE_EXTEND;
443			f->real_file_size = (f->io_size + f->file_offset);
444			err = extend_file(td, f);
445			if (err)
446				break;
447		}
448		temp_stall_ts = 0;
449	}
450
451	if (err)
452		return err;
453
454	if (!td->o.zone_size)
455		td->o.zone_size = td->o.size;
456
457	/*
458	 * iolog already set the total io size, if we read back
459	 * stored entries.
460	 */
461	if (!td->o.read_iolog_file)
462		td->total_io_size = td->o.size * td->o.loops;
463	return 0;
464err_offset:
465	log_err("%s: you need to specify valid offset=\n", td->o.name);
466	return 1;
467}
468
469int init_random_map(struct thread_data *td)
470{
471	int num_maps, blocks;
472	struct fio_file *f;
473	unsigned int i;
474
475	if (td->o.norandommap)
476		return 0;
477
478	for_each_file(td, f, i) {
479		blocks = (f->real_file_size + td->o.rw_min_bs - 1) / td->o.rw_min_bs;
480		num_maps = (blocks + BLOCKS_PER_MAP-1)/ BLOCKS_PER_MAP;
481		f->file_map = malloc(num_maps * sizeof(long));
482		if (!f->file_map) {
483			log_err("fio: failed allocating random map. If running a large number of jobs, try the 'norandommap' option\n");
484			return 1;
485		}
486		f->num_maps = num_maps;
487		memset(f->file_map, 0, num_maps * sizeof(long));
488	}
489
490	return 0;
491}
492
493void close_files(struct thread_data *td)
494{
495	struct fio_file *f;
496	unsigned int i;
497
498	for_each_file(td, f, i) {
499		if (td->o.unlink && f->filetype == FIO_TYPE_FILE)
500			unlink(f->file_name);
501
502		td_io_close_file(td, f);
503
504		free(f->file_name);
505		f->file_name = NULL;
506
507		if (f->file_map) {
508			free(f->file_map);
509			f->file_map = NULL;
510		}
511	}
512
513	td->o.filename = NULL;
514	free(td->files);
515	td->files = NULL;
516	td->o.nr_files = 0;
517}
518
519static void get_file_type(struct fio_file *f)
520{
521	struct stat sb;
522
523	if (!strcmp(f->file_name, "-"))
524		f->filetype = FIO_TYPE_PIPE;
525	else
526		f->filetype = FIO_TYPE_FILE;
527
528	if (!lstat(f->file_name, &sb)) {
529		if (S_ISBLK(sb.st_mode))
530			f->filetype = FIO_TYPE_BD;
531		else if (S_ISCHR(sb.st_mode))
532			f->filetype = FIO_TYPE_CHAR;
533		else if (S_ISFIFO(sb.st_mode))
534			f->filetype = FIO_TYPE_PIPE;
535	}
536}
537
538int add_file(struct thread_data *td, const char *fname)
539{
540	int cur_files = td->files_index;
541	char file_name[PATH_MAX];
542	struct fio_file *f;
543	int len = 0;
544
545	td->files = realloc(td->files, (cur_files + 1) * sizeof(*f));
546
547	f = &td->files[cur_files];
548	memset(f, 0, sizeof(*f));
549	f->fd = -1;
550
551	/*
552	 * init function, io engine may not be loaded yet
553	 */
554	if (td->io_ops && (td->io_ops->flags & FIO_DISKLESSIO))
555		f->real_file_size = -1ULL;
556
557	if (td->o.directory)
558		len = sprintf(file_name, "%s/", td->o.directory);
559
560	sprintf(file_name + len, "%s", fname);
561	f->file_name = strdup(file_name);
562
563	get_file_type(f);
564
565	td->files_index++;
566	if (f->filetype == FIO_TYPE_FILE)
567		td->nr_normal_files++;
568
569	return cur_files;
570}
571
572void get_file(struct fio_file *f)
573{
574	assert(f->flags & FIO_FILE_OPEN);
575	f->references++;
576}
577
578void put_file(struct thread_data *td, struct fio_file *f)
579{
580	if (!(f->flags & FIO_FILE_OPEN))
581		return;
582
583	assert(f->references);
584	if (--f->references)
585		return;
586
587	if (should_fsync(td) && td->o.fsync_on_close)
588		fsync(f->fd);
589
590	if (td->io_ops->close_file)
591		td->io_ops->close_file(td, f);
592
593	td->nr_open_files--;
594	f->flags &= ~FIO_FILE_OPEN;
595}
596
597static int recurse_dir(struct thread_data *td, const char *dirname)
598{
599	struct dirent *dir;
600	int ret = 0;
601	DIR *D;
602
603	D = opendir(dirname);
604	if (!D) {
605		char buf[FIO_VERROR_SIZE];
606
607		snprintf(buf, FIO_VERROR_SIZE - 1, "opendir(%s)", dirname);
608		td_verror(td, errno, buf);
609		return 1;
610	}
611
612	while ((dir = readdir(D)) != NULL) {
613		char full_path[PATH_MAX];
614		struct stat sb;
615
616		if (!strcmp(dir->d_name, ".") || !strcmp(dir->d_name, ".."))
617			continue;
618
619		sprintf(full_path, "%s/%s", dirname, dir->d_name);
620
621		if (lstat(full_path, &sb) == -1) {
622			if (errno != ENOENT) {
623				td_verror(td, errno, "stat");
624				return 1;
625			}
626		}
627
628		if (S_ISREG(sb.st_mode)) {
629			add_file(td, full_path);
630			td->o.nr_files++;
631			continue;
632		}
633		if (!S_ISDIR(sb.st_mode))
634			continue;
635
636		if ((ret = recurse_dir(td, full_path)) != 0)
637			break;
638	}
639
640	closedir(D);
641	return ret;
642}
643
644int add_dir_files(struct thread_data *td, const char *path)
645{
646	int ret = recurse_dir(td, path);
647
648	if (!ret)
649		log_info("fio: opendir added %d files\n", td->o.nr_files);
650
651	return ret;
652}
653
654void dup_files(struct thread_data *td, struct thread_data *org)
655{
656	struct fio_file *f;
657	unsigned int i;
658	size_t bytes;
659
660	if (!org->files)
661		return;
662
663	bytes = org->files_index * sizeof(*f);
664	td->files = malloc(bytes);
665	memcpy(td->files, org->files, bytes);
666
667	for_each_file(td, f, i) {
668		if (f->file_name)
669			f->file_name = strdup(f->file_name);
670	}
671}
672
673/*
674 * Returns the index that matches the filename, or -1 if not there
675 */
676int get_fileno(struct thread_data *td, const char *fname)
677{
678	struct fio_file *f;
679	unsigned int i;
680
681	for_each_file(td, f, i)
682		if (!strcmp(f->file_name, fname))
683			return i;
684
685	return -1;
686}
687
688/*
689 * For log usage, where we add/open/close files automatically
690 */
691void free_release_files(struct thread_data *td)
692{
693	close_files(td);
694	td->files_index = 0;
695	td->nr_normal_files = 0;
696}
697