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