filesetup.c revision b2a151925a91f38aeb298d693687a47269ad4e94
1#include <unistd.h>
2#include <fcntl.h>
3#include <string.h>
4#include <assert.h>
5#include <sys/stat.h>
6#include <sys/mman.h>
7
8#include "fio.h"
9#include "os.h"
10
11static int create_file(struct thread_data *td, struct fio_file *f)
12{
13	unsigned long long left;
14	unsigned int bs;
15	struct stat st;
16	char *b;
17	int r;
18
19	if (td->filetype != FIO_TYPE_FILE)
20		return 0;
21
22	if (stat(f->file_name, &st) == -1) {
23		if (!td->create_file) {
24			td_verror(td, ENOENT);
25			return 1;
26		}
27	} else if (st.st_size >= (off_t) f->file_size)
28		return 0;
29
30	f->fd = open(f->file_name, O_WRONLY | O_CREAT | O_TRUNC, 0644);
31	if (f->fd < 0) {
32		td_verror(td, errno);
33		return 1;
34	}
35
36	if (ftruncate(f->fd, f->file_size) == -1) {
37		td_verror(td, errno);
38		goto err;
39	}
40
41	b = malloc(td->max_bs);
42	memset(b, 0, td->max_bs);
43
44	left = f->file_size;
45	while (left && !td->terminate) {
46		bs = td->max_bs;
47		if (bs > left)
48			bs = left;
49
50		r = write(f->fd, b, bs);
51
52		if (r == (int) bs) {
53			left -= bs;
54			continue;
55		} else {
56			if (r < 0)
57				td_verror(td, errno);
58			else
59				td_verror(td, EIO);
60
61			break;
62		}
63	}
64
65	if (td->terminate)
66		unlink(f->file_name);
67	else if (td->create_fsync)
68		fsync(f->fd);
69
70	free(b);
71	close(f->fd);
72	f->fd = -1;
73	return 0;
74err:
75	close(f->fd);
76	f->fd = -1;
77	return 1;
78}
79
80static int create_files(struct thread_data *td)
81{
82	struct fio_file *f;
83	int i, err;
84
85	/*
86	 * unless specifically asked for overwrite, let normal io extend it
87	 */
88	if (!td->overwrite) {
89		td->io_size = td->total_file_size;
90		for_each_file(td, f, i)
91			f->file_size = td->total_file_size / td->nr_files;
92
93		return 0;
94	}
95
96	if (!td->total_file_size) {
97		log_err("Need size for create\n");
98		td_verror(td, EINVAL);
99		return 1;
100	}
101
102	temp_stall_ts = 1;
103	fprintf(f_out, "%s: Laying out IO file(s) (%LuMiB)\n",
104					td->name, td->total_file_size >> 20);
105
106	err = 0;
107	for_each_file(td, f, i) {
108		f->file_size = td->total_file_size / td->nr_files;
109		err = create_file(td, f);
110		if (err)
111			break;
112
113		td->io_size += f->file_size;
114	}
115
116	temp_stall_ts = 0;
117	return err;
118}
119
120static int file_size(struct thread_data *td, struct fio_file *f)
121{
122	struct stat st;
123
124	if (td->overwrite) {
125		if (fstat(f->fd, &st) == -1) {
126			td_verror(td, errno);
127			return 1;
128		}
129
130		f->real_file_size = st.st_size;
131
132		if (!f->file_size || f->file_size > f->real_file_size)
133			f->file_size = f->real_file_size;
134	}
135
136	f->file_size -= f->file_offset;
137	return 0;
138}
139
140static int bdev_size(struct thread_data *td, struct fio_file *f)
141{
142	unsigned long long bytes;
143	int r;
144
145	r = blockdev_size(f->fd, &bytes);
146	if (r) {
147		td_verror(td, r);
148		return 1;
149	}
150
151	f->real_file_size = bytes;
152
153	/*
154	 * no extend possibilities, so limit size to device size if too large
155	 */
156	if (!f->file_size || f->file_size > f->real_file_size)
157		f->file_size = f->real_file_size;
158
159	f->file_size -= f->file_offset;
160	return 0;
161}
162
163static int get_file_size(struct thread_data *td, struct fio_file *f)
164{
165	int ret = 0;
166
167	if (td->filetype == FIO_TYPE_FILE)
168		ret = file_size(td, f);
169	else if (td->filetype == FIO_TYPE_BD)
170		ret = bdev_size(td, f);
171	else
172		f->real_file_size = -1;
173
174	if (ret)
175		return ret;
176
177	if (f->file_offset > f->real_file_size) {
178		log_err("%s: offset extends end (%Lu > %Lu)\n", td->name, f->file_offset, f->real_file_size);
179		return 1;
180	}
181
182	td->io_size += f->file_size;
183	return 0;
184}
185
186static int __setup_file_mmap(struct thread_data *td, struct fio_file *f)
187{
188	int flags;
189
190	if (td_rw(td))
191		flags = PROT_READ | PROT_WRITE;
192	else if (td_write(td)) {
193		flags = PROT_WRITE;
194
195		if (td->verify != VERIFY_NONE)
196			flags |= PROT_READ;
197	} else
198		flags = PROT_READ;
199
200	f->mmap = mmap(NULL, f->file_size, flags, MAP_SHARED, f->fd, f->file_offset);
201	if (f->mmap == MAP_FAILED) {
202		f->mmap = NULL;
203		td_verror(td, errno);
204		return 1;
205	}
206
207	if (td->invalidate_cache) {
208		if (madvise(f->mmap, f->file_size, MADV_DONTNEED) < 0) {
209			td_verror(td, errno);
210			return 1;
211		}
212	}
213
214	if (td->sequential) {
215		if (madvise(f->mmap, f->file_size, MADV_SEQUENTIAL) < 0) {
216			td_verror(td, errno);
217			return 1;
218		}
219	} else {
220		if (madvise(f->mmap, f->file_size, MADV_RANDOM) < 0) {
221			td_verror(td, errno);
222			return 1;
223		}
224	}
225
226	return 0;
227}
228
229static int setup_files_mmap(struct thread_data *td)
230{
231	struct fio_file *f;
232	int i, err = 0;
233
234	for_each_file(td, f, i) {
235		err = __setup_file_mmap(td, f);
236		if (err)
237			break;
238	}
239
240	return err;
241}
242
243static int __setup_file_plain(struct thread_data *td, struct fio_file *f)
244{
245	if (td->invalidate_cache) {
246		if (fadvise(f->fd, f->file_offset, f->file_size, POSIX_FADV_DONTNEED) < 0) {
247			td_verror(td, errno);
248			return 1;
249		}
250	}
251
252	if (td->sequential) {
253		if (fadvise(f->fd, f->file_offset, f->file_size, POSIX_FADV_SEQUENTIAL) < 0) {
254			td_verror(td, errno);
255			return 1;
256		}
257	} else {
258		if (fadvise(f->fd, f->file_offset, f->file_size, POSIX_FADV_RANDOM) < 0) {
259			td_verror(td, errno);
260			return 1;
261		}
262	}
263
264	return 0;
265}
266
267static int setup_files_plain(struct thread_data *td)
268{
269	struct fio_file *f;
270	int i, err = 0;
271
272	for_each_file(td, f, i) {
273		err = __setup_file_plain(td, f);
274		if (err)
275			break;
276	}
277
278	return err;
279}
280
281static int setup_file(struct thread_data *td, struct fio_file *f)
282{
283	int flags = 0;
284
285	if (td->odirect)
286		flags |= OS_O_DIRECT;
287
288	if (td_write(td) || td_rw(td)) {
289		if (td->filetype == FIO_TYPE_FILE) {
290			if (!td->overwrite)
291				flags |= O_TRUNC;
292
293			flags |= O_CREAT;
294		}
295		if (td->sync_io)
296			flags |= O_SYNC;
297
298		flags |= O_RDWR;
299
300		f->fd = open(f->file_name, flags, 0600);
301	} else {
302		if (td->filetype == FIO_TYPE_CHAR)
303			flags |= O_RDWR;
304		else
305			flags |= O_RDONLY;
306
307		f->fd = open(f->file_name, flags);
308	}
309
310	if (f->fd == -1) {
311		td_verror(td, errno);
312		return 1;
313	}
314
315	if (get_file_size(td, f))
316		return 1;
317
318	return 0;
319}
320
321int setup_files(struct thread_data *td)
322{
323	struct fio_file *f;
324	int i, err;
325
326	/*
327	 * if ioengine defines a setup() method, it's responsible for
328	 * setting up everything in the td->files[] area.
329	 */
330	if (td->io_ops->setup)
331		return td->io_ops->setup(td);
332
333	if (create_files(td))
334		return 1;
335
336	for_each_file(td, f, i) {
337		err = setup_file(td, f);
338		if (err)
339			break;
340	}
341
342	if (td->io_size == 0) {
343		log_err("%s: no io blocks\n", td->name);
344		td_verror(td, EINVAL);
345		return 1;
346	}
347
348	if (!td->zone_size)
349		td->zone_size = td->io_size;
350
351	td->total_io_size = td->io_size * td->loops;
352
353	if (td->io_ops->flags & FIO_MMAPIO)
354		return setup_files_mmap(td);
355	else
356		return setup_files_plain(td);
357}
358
359void close_files(struct thread_data *td)
360{
361	int i;
362
363	for (i = 0; i < td->nr_files; i++) {
364		struct fio_file *f = &td->files[i];
365
366		if (f->fd != -1) {
367			close(f->fd);
368			f->fd = -1;
369		}
370		if (f->mmap) {
371			munmap(f->mmap, f->file_size);
372			f->mmap = NULL;
373		}
374	}
375}
376