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