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