[PATCH] Total io size / eta fix
[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 static 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;
74 err:
75         close(f->fd);
76         f->fd = -1;
77         return 1;
78 }
79
80 static 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                 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);
109                 if (err)
110                         break;
111         }
112
113         td->io_size = td->total_file_size;
114         temp_stall_ts = 0;
115         return err;
116 }
117
118 static 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
138 static 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
161 static 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
180         return 0;
181 }
182
183 int 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
207 static 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
228         if (td->invalidate_cache && file_invalidate_cache(td, f))
229                 return 1;
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
246 static 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
260 static int __setup_file_plain(struct thread_data *td, struct fio_file *f)
261 {
262         if (td->invalidate_cache && file_invalidate_cache(td, f))
263                 return 1;
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
280 static 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
294 static int setup_file(struct thread_data *td, struct fio_file *f)
295 {
296         int flags = 0;
297
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
334 int 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
372 void close_files(struct thread_data *td)
373 {
374         struct fio_file *f;
375         int i;
376
377         for_each_file(td, f, i) {
378                 if (f->fd != -1) {
379                         if (td->unlink && td->filetype == FIO_TYPE_FILE)
380                                 unlink(f->file_name);
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 }