Update terse output
[fio.git] / filesetup.c
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
11 int open_file(struct thread_data *td, struct fio_file *f, int flags, int perm)
12 {
13         if (flags & O_CREAT)
14                 f->fd = open(f->file_name, flags, perm);
15         else
16                 f->fd = open(f->file_name, flags);
17
18         if (f->fd != -1) {
19                 td->nr_open_files++;
20                 return 0;
21         }
22
23         return 1;
24 }
25
26 void close_file(struct thread_data *td, struct fio_file *f)
27 {
28         if (f->fd != -1) {
29                 close(f->fd);
30                 f->fd = -1;
31                 td->nr_open_files--;
32         }
33 }
34
35 /*
36  * Check if the file exists and it's large enough.
37  */
38 static int file_ok(struct thread_data *td, struct fio_file *f)
39 {
40         struct stat st;
41
42         if (td->filetype != FIO_TYPE_FILE)
43                 return 0;
44
45         if (lstat(f->file_name, &st) == -1)
46                 return 1;
47
48         /*
49          * if it's a special file, size is always ok for now
50          */
51         if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode))
52                 return 0;
53         if (st.st_size < (off_t) f->file_size)
54                 return 1;
55
56         return 0;
57 }
58
59 static int create_file(struct thread_data *td, struct fio_file *f)
60 {
61         unsigned long long left;
62         unsigned int bs;
63         char *b;
64         int r;
65
66         f->fd = open(f->file_name, O_WRONLY | O_CREAT | O_TRUNC, 0644);
67         if (f->fd < 0) {
68                 td_verror(td, errno, "open");
69                 return 1;
70         }
71
72         if (ftruncate(f->fd, f->file_size) == -1) {
73                 td_verror(td, errno, "ftruncate");
74                 goto err;
75         }
76
77         if (posix_fallocate(f->fd, 0, f->file_size) < 0) {
78                 td_verror(td, errno, "posix_fallocate");
79                 goto err;
80         }
81
82         b = malloc(td->max_bs[DDIR_WRITE]);
83         memset(b, 0, td->max_bs[DDIR_WRITE]);
84
85         left = f->file_size;
86         while (left && !td->terminate) {
87                 bs = td->max_bs[DDIR_WRITE];
88                 if (bs > left)
89                         bs = left;
90
91                 r = write(f->fd, b, bs);
92
93                 if (r == (int) bs) {
94                         left -= bs;
95                         continue;
96                 } else {
97                         if (r < 0)
98                                 td_verror(td, errno, "write");
99                         else
100                                 td_verror(td, EIO, "write");
101
102                         break;
103                 }
104         }
105
106         if (td->terminate)
107                 unlink(f->file_name);
108         else if (td->create_fsync)
109                 fsync(f->fd);
110
111         free(b);
112         close(f->fd);
113         f->fd = -1;
114         return 0;
115 err:
116         close(f->fd);
117         f->fd = -1;
118         return 1;
119 }
120
121 static int create_files(struct thread_data *td)
122 {
123         struct fio_file *f;
124         int i, err, need_create;
125
126         for_each_file(td, f, i)
127                 f->file_size = td->total_file_size / td->nr_files;
128
129         /*
130          * unless specifically asked for overwrite, let normal io extend it
131          */
132         if (!td->overwrite)
133                 return 0;
134
135         need_create = 0;
136         if (td->filetype == FIO_TYPE_FILE) {
137                 for_each_file(td, f, i) {
138                         int file_there = !file_ok(td, f);
139
140                         if (file_there && td_write(td) && !td->overwrite) {
141                                 unlink(f->file_name);
142                                 file_there = 0;
143                         }
144
145                         need_create += !file_there;
146                 }
147         }
148
149         if (!need_create)
150                 return 0;
151
152         if (!td->total_file_size) {
153                 log_err("Need size for create\n");
154                 td_verror(td, EINVAL, "file_size");
155                 return 1;
156         }
157
158         temp_stall_ts = 1;
159         fprintf(f_out, "%s: Laying out IO file(s) (%u x %LuMiB == %LuMiB)\n",
160                                 td->name, td->nr_uniq_files,
161                                 (td->total_file_size >> 20) / td->nr_uniq_files,
162                                 td->total_file_size >> 20);
163
164         err = 0;
165         for_each_file(td, f, i) {
166                 /*
167                  * Only unlink files that we created.
168                  */
169                 f->unlink = 0;
170                 if (file_ok(td, f)) {
171                         f->unlink = td->unlink;
172                         err = create_file(td, f);
173                         if (err)
174                                 break;
175                 }
176         }
177
178         temp_stall_ts = 0;
179         return err;
180 }
181
182 static int file_size(struct thread_data *td, struct fio_file *f)
183 {
184         struct stat st;
185
186         if (td->overwrite) {
187                 if (fstat(f->fd, &st) == -1) {
188                         td_verror(td, errno, "fstat");
189                         return 1;
190                 }
191
192                 f->real_file_size = st.st_size;
193
194                 if (!f->file_size || f->file_size > f->real_file_size)
195                         f->file_size = f->real_file_size;
196         } else
197                 f->real_file_size = f->file_size;
198
199         return 0;
200 }
201
202 static int bdev_size(struct thread_data *td, struct fio_file *f)
203 {
204         unsigned long long bytes;
205         int r;
206
207         r = blockdev_size(f->fd, &bytes);
208         if (r) {
209                 td_verror(td, r, "blockdev_size");
210                 return 1;
211         }
212
213         f->real_file_size = bytes;
214
215         /*
216          * no extend possibilities, so limit size to device size if too large
217          */
218         if (!f->file_size || f->file_size > f->real_file_size)
219                 f->file_size = f->real_file_size;
220
221         f->file_size -= f->file_offset;
222         return 0;
223 }
224
225 static int get_file_size(struct thread_data *td, struct fio_file *f)
226 {
227         int ret = 0;
228
229         if (td->filetype == FIO_TYPE_FILE)
230                 ret = file_size(td, f);
231         else if (td->filetype == FIO_TYPE_BD)
232                 ret = bdev_size(td, f);
233         else
234                 f->real_file_size = -1;
235
236         if (ret)
237                 return ret;
238
239         if (f->file_offset > f->real_file_size) {
240                 log_err("%s: offset extends end (%Lu > %Lu)\n", td->name, f->file_offset, f->real_file_size);
241                 return 1;
242         }
243
244         return 0;
245 }
246
247 int file_invalidate_cache(struct thread_data *td, struct fio_file *f)
248 {
249         int ret = 0;
250
251         /*
252          * FIXME: add blockdev flushing too
253          */
254         if (td->io_ops->flags & FIO_MMAPIO)
255                 ret = madvise(f->mmap, f->file_size, MADV_DONTNEED);
256         else if (td->filetype == FIO_TYPE_FILE) {
257                 if (!td->odirect)
258                         ret = fadvise(f->fd, f->file_offset, f->file_size, POSIX_FADV_DONTNEED);
259         } else if (td->filetype == FIO_TYPE_BD) {
260                 if (!td->odirect)
261                         ret = blockdev_invalidate_cache(f->fd);
262         } else if (td->filetype == FIO_TYPE_CHAR)
263                 ret = 0;
264
265         if (ret < 0) {
266                 td_verror(td, errno, "invalidate_cache");
267                 return 1;
268         }
269
270         return ret;
271 }
272
273 static int __setup_file_mmap(struct thread_data *td, struct fio_file *f)
274 {
275         int flags;
276
277         if (td_rw(td))
278                 flags = PROT_READ | PROT_WRITE;
279         else if (td_write(td)) {
280                 flags = PROT_WRITE;
281
282                 if (td->verify != VERIFY_NONE)
283                         flags |= PROT_READ;
284         } else
285                 flags = PROT_READ;
286
287         f->mmap = mmap(NULL, f->file_size, flags, MAP_SHARED, f->fd, f->file_offset);
288         if (f->mmap == MAP_FAILED) {
289                 f->mmap = NULL;
290                 td_verror(td, errno, "mmap");
291                 return 1;
292         }
293
294         if (td->invalidate_cache && file_invalidate_cache(td, f))
295                 return 1;
296
297         if (!td_random(td)) {
298                 if (madvise(f->mmap, f->file_size, MADV_SEQUENTIAL) < 0) {
299                         td_verror(td, errno, "madvise");
300                         return 1;
301                 }
302         } else {
303                 if (madvise(f->mmap, f->file_size, MADV_RANDOM) < 0) {
304                         td_verror(td, errno, "madvise");
305                         return 1;
306                 }
307         }
308
309         return 0;
310 }
311
312 static int setup_files_mmap(struct thread_data *td)
313 {
314         struct fio_file *f;
315         int i, err = 0;
316
317         for_each_file(td, f, i) {
318                 err = __setup_file_mmap(td, f);
319                 if (err)
320                         break;
321         }
322
323         return err;
324 }
325
326 static int __setup_file_plain(struct thread_data *td, struct fio_file *f)
327 {
328         if (td->invalidate_cache && file_invalidate_cache(td, f))
329                 return 1;
330
331         if (!td_random(td)) {
332                 if (fadvise(f->fd, f->file_offset, f->file_size, POSIX_FADV_SEQUENTIAL) < 0) {
333                         td_verror(td, errno, "fadvise");
334                         return 1;
335                 }
336         } else {
337                 if (fadvise(f->fd, f->file_offset, f->file_size, POSIX_FADV_RANDOM) < 0) {
338                         td_verror(td, errno, "fadvise");
339                         return 1;
340                 }
341         }
342
343         return 0;
344 }
345
346 static int setup_files_plain(struct thread_data *td)
347 {
348         struct fio_file *f;
349         int i, err = 0;
350
351         for_each_file(td, f, i) {
352                 err = __setup_file_plain(td, f);
353                 if (err)
354                         break;
355         }
356
357         return err;
358 }
359
360 static int setup_file(struct thread_data *td, struct fio_file *f)
361 {
362         int flags = 0;
363
364         if (td->io_ops->flags & FIO_SELFOPEN)
365                 return 0;
366
367         if (td->odirect)
368                 flags |= OS_O_DIRECT;
369         if (td->sync_io)
370                 flags |= O_SYNC;
371
372         if (td_write(td) || td_rw(td)) {
373                 flags |= O_RDWR;
374
375                 if (td->filetype == FIO_TYPE_FILE) {
376                         if (!td->overwrite)
377                                 flags |= O_TRUNC;
378
379                         flags |= O_CREAT;
380                 }
381
382                 open_file(td, f, flags, 0600);
383         } else {
384                 if (td->filetype == FIO_TYPE_CHAR)
385                         flags |= O_RDWR;
386                 else
387                         flags |= O_RDONLY;
388
389                 open_file(td, f, flags, 0);
390         }
391
392         if (f->fd == -1) {
393                 int __e = errno;
394
395                 td_verror(td, __e, "open");
396                 if (__e == EINVAL && td->odirect)
397                         log_err("fio: destination does not support O_DIRECT\n");
398                 return 1;
399         }
400
401         if (get_file_size(td, f)) {
402                 close_file(td, f);
403                 return 1;
404         }
405
406         return 0;
407 }
408
409 int open_files(struct thread_data *td)
410 {
411         struct fio_file *f;
412         int i, err = 0;
413
414         for_each_file(td, f, i) {
415                 err = setup_file(td, f);
416                 if (err)
417                         break;
418         }
419
420         if (!err)
421                 return 0;
422
423         for_each_file(td, f, i)
424                 close_file(td, f);
425
426         return err;
427 }
428
429 int setup_files(struct thread_data *td)
430 {
431         struct fio_file *f;
432         int err, i;
433
434         /*
435          * if ioengine defines a setup() method, it's responsible for
436          * setting up everything in the td->files[] area.
437          */
438         if (td->io_ops->setup)
439                 return td->io_ops->setup(td);
440
441         if (create_files(td))
442                 return 1;
443
444         err = open_files(td);
445         if (err)
446                 return err;
447
448         /*
449          * Recalculate the total file size now that files are set up.
450          */
451         td->total_file_size = 0;
452         for_each_file(td, f, i)
453                 td->total_file_size += f->file_size;
454
455         td->io_size = td->total_file_size;
456         if (td->io_size == 0) {
457                 log_err("%s: no io blocks\n", td->name);
458                 td_verror(td, EINVAL, "total_file_size");
459                 return 1;
460         }
461
462         if (!td->zone_size)
463                 td->zone_size = td->io_size;
464
465         td->total_io_size = td->io_size * td->loops;
466
467         if (td->io_ops->flags & FIO_MMAPIO)
468                 err = setup_files_mmap(td);
469         else
470                 err = setup_files_plain(td);
471
472         for_each_file(td, f, i)
473                 close_file(td, f);
474
475         return err;
476 }
477
478 void close_files(struct thread_data *td)
479 {
480         struct fio_file *f;
481         int i;
482
483         for_each_file(td, f, i) {
484                 if (!td->filename && f->unlink &&
485                     td->filetype == FIO_TYPE_FILE) {
486                         unlink(f->file_name);
487                         free(f->file_name);
488                         f->file_name = NULL;
489                 }
490
491                 close_file(td, f);
492
493                 if (f->mmap) {
494                         munmap(f->mmap, f->file_size);
495                         f->mmap = NULL;
496                 }
497         }
498
499         td->filename = NULL;
500         free(td->files);
501         td->files = NULL;
502         td->nr_files = 0;
503 }