[PATCH] Total io size / eta fix
[fio.git] / filesetup.c
CommitLineData
53cdc686
JA
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;
b2a15192 15 struct stat st;
53cdc686
JA
16 char *b;
17 int r;
18
b2a15192
JA
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
53cdc686
JA
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) {
53cdc686
JA
89 for_each_file(td, f, i)
90 f->file_size = td->total_file_size / td->nr_files;
91
92 return 0;
93 }
94
95 if (!td->total_file_size) {
96 log_err("Need size for create\n");
97 td_verror(td, EINVAL);
98 return 1;
99 }
100
101 temp_stall_ts = 1;
102 fprintf(f_out, "%s: Laying out IO file(s) (%LuMiB)\n",
103 td->name, td->total_file_size >> 20);
104
105 err = 0;
106 for_each_file(td, f, i) {
107 f->file_size = td->total_file_size / td->nr_files;
108 err = create_file(td, f);
b2a15192 109 if (err)
53cdc686 110 break;
53cdc686
JA
111 }
112
74939e38 113 td->io_size = td->total_file_size;
53cdc686
JA
114 temp_stall_ts = 0;
115 return err;
116}
117
118static int file_size(struct thread_data *td, struct fio_file *f)
119{
120 struct stat st;
121
122 if (td->overwrite) {
123 if (fstat(f->fd, &st) == -1) {
124 td_verror(td, errno);
125 return 1;
126 }
127
128 f->real_file_size = st.st_size;
129
130 if (!f->file_size || f->file_size > f->real_file_size)
131 f->file_size = f->real_file_size;
132 }
133
134 f->file_size -= f->file_offset;
135 return 0;
136}
137
138static int bdev_size(struct thread_data *td, struct fio_file *f)
139{
140 unsigned long long bytes;
141 int r;
142
143 r = blockdev_size(f->fd, &bytes);
144 if (r) {
145 td_verror(td, r);
146 return 1;
147 }
148
149 f->real_file_size = bytes;
150
151 /*
152 * no extend possibilities, so limit size to device size if too large
153 */
154 if (!f->file_size || f->file_size > f->real_file_size)
155 f->file_size = f->real_file_size;
156
157 f->file_size -= f->file_offset;
158 return 0;
159}
160
161static int get_file_size(struct thread_data *td, struct fio_file *f)
162{
163 int ret = 0;
164
165 if (td->filetype == FIO_TYPE_FILE)
166 ret = file_size(td, f);
167 else if (td->filetype == FIO_TYPE_BD)
168 ret = bdev_size(td, f);
169 else
170 f->real_file_size = -1;
171
172 if (ret)
173 return ret;
174
175 if (f->file_offset > f->real_file_size) {
176 log_err("%s: offset extends end (%Lu > %Lu)\n", td->name, f->file_offset, f->real_file_size);
177 return 1;
178 }
179
53cdc686
JA
180 return 0;
181}
182
e5b401d4
JA
183int file_invalidate_cache(struct thread_data *td, struct fio_file *f)
184{
185 int ret = 0;
186
187 /*
188 * FIXME: add blockdev flushing too
189 */
190 if (td->io_ops->flags & FIO_MMAPIO)
191 ret = madvise(f->mmap, f->file_size, MADV_DONTNEED);
192 else if (td->filetype == FIO_TYPE_FILE)
193 ret = fadvise(f->fd, f->file_offset, f->file_size, POSIX_FADV_DONTNEED);
194 else if (td->filetype == FIO_TYPE_BD)
195 ret = blockdev_invalidate_cache(f->fd);
196 else if (td->filetype == FIO_TYPE_CHAR)
197 ret = 0;
198
199 if (ret < 0) {
200 td_verror(td, errno);
201 return 1;
202 }
203
204 return 0;
205}
206
53cdc686
JA
207static int __setup_file_mmap(struct thread_data *td, struct fio_file *f)
208{
209 int flags;
210
211 if (td_rw(td))
212 flags = PROT_READ | PROT_WRITE;
213 else if (td_write(td)) {
214 flags = PROT_WRITE;
215
216 if (td->verify != VERIFY_NONE)
217 flags |= PROT_READ;
218 } else
219 flags = PROT_READ;
220
221 f->mmap = mmap(NULL, f->file_size, flags, MAP_SHARED, f->fd, f->file_offset);
222 if (f->mmap == MAP_FAILED) {
223 f->mmap = NULL;
224 td_verror(td, errno);
225 return 1;
226 }
227
e5b401d4
JA
228 if (td->invalidate_cache && file_invalidate_cache(td, f))
229 return 1;
53cdc686
JA
230
231 if (td->sequential) {
232 if (madvise(f->mmap, f->file_size, MADV_SEQUENTIAL) < 0) {
233 td_verror(td, errno);
234 return 1;
235 }
236 } else {
237 if (madvise(f->mmap, f->file_size, MADV_RANDOM) < 0) {
238 td_verror(td, errno);
239 return 1;
240 }
241 }
242
243 return 0;
244}
245
246static int setup_files_mmap(struct thread_data *td)
247{
248 struct fio_file *f;
249 int i, err = 0;
250
251 for_each_file(td, f, i) {
252 err = __setup_file_mmap(td, f);
253 if (err)
254 break;
255 }
256
257 return err;
258}
259
260static int __setup_file_plain(struct thread_data *td, struct fio_file *f)
261{
e5b401d4
JA
262 if (td->invalidate_cache && file_invalidate_cache(td, f))
263 return 1;
53cdc686
JA
264
265 if (td->sequential) {
266 if (fadvise(f->fd, f->file_offset, f->file_size, POSIX_FADV_SEQUENTIAL) < 0) {
267 td_verror(td, errno);
268 return 1;
269 }
270 } else {
271 if (fadvise(f->fd, f->file_offset, f->file_size, POSIX_FADV_RANDOM) < 0) {
272 td_verror(td, errno);
273 return 1;
274 }
275 }
276
277 return 0;
278}
279
280static int setup_files_plain(struct thread_data *td)
281{
282 struct fio_file *f;
283 int i, err = 0;
284
285 for_each_file(td, f, i) {
286 err = __setup_file_plain(td, f);
287 if (err)
288 break;
289 }
290
291 return err;
292}
293
294static int setup_file(struct thread_data *td, struct fio_file *f)
295{
53cdc686
JA
296 int flags = 0;
297
53cdc686
JA
298 if (td->odirect)
299 flags |= OS_O_DIRECT;
300
301 if (td_write(td) || td_rw(td)) {
302 if (td->filetype == FIO_TYPE_FILE) {
303 if (!td->overwrite)
304 flags |= O_TRUNC;
305
306 flags |= O_CREAT;
307 }
308 if (td->sync_io)
309 flags |= O_SYNC;
310
311 flags |= O_RDWR;
312
313 f->fd = open(f->file_name, flags, 0600);
314 } else {
315 if (td->filetype == FIO_TYPE_CHAR)
316 flags |= O_RDWR;
317 else
318 flags |= O_RDONLY;
319
320 f->fd = open(f->file_name, flags);
321 }
322
323 if (f->fd == -1) {
324 td_verror(td, errno);
325 return 1;
326 }
327
328 if (get_file_size(td, f))
329 return 1;
330
331 return 0;
332}
333
334int setup_files(struct thread_data *td)
335{
336 struct fio_file *f;
337 int i, err;
338
339 /*
340 * if ioengine defines a setup() method, it's responsible for
341 * setting up everything in the td->files[] area.
342 */
343 if (td->io_ops->setup)
344 return td->io_ops->setup(td);
345
346 if (create_files(td))
347 return 1;
348
349 for_each_file(td, f, i) {
350 err = setup_file(td, f);
351 if (err)
352 break;
353 }
354
355 if (td->io_size == 0) {
356 log_err("%s: no io blocks\n", td->name);
357 td_verror(td, EINVAL);
358 return 1;
359 }
360
361 if (!td->zone_size)
362 td->zone_size = td->io_size;
363
364 td->total_io_size = td->io_size * td->loops;
365
366 if (td->io_ops->flags & FIO_MMAPIO)
367 return setup_files_mmap(td);
368 else
369 return setup_files_plain(td);
370}
371
372void close_files(struct thread_data *td)
373{
0ab8db89 374 struct fio_file *f;
53cdc686
JA
375 int i;
376
0ab8db89 377 for_each_file(td, f, i) {
53cdc686 378 if (f->fd != -1) {
f6cbb269
JA
379 if (td->unlink && td->filetype == FIO_TYPE_FILE)
380 unlink(f->file_name);
53cdc686
JA
381 close(f->fd);
382 f->fd = -1;
383 }
384 if (f->mmap) {
385 munmap(f->mmap, f->file_size);
386 f->mmap = NULL;
387 }
388 }
389}