[PATCH Various 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 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 static int __setup_file_mmap(struct thread_data *td, struct fio_file *f)
187 {
188         int flags;
189
190         if (td_rw(td))
191                 flags = PROT_READ | PROT_WRITE;
192         else if (td_write(td)) {
193                 flags = PROT_WRITE;
194
195                 if (td->verify != VERIFY_NONE)
196                         flags |= PROT_READ;
197         } else
198                 flags = PROT_READ;
199
200         f->mmap = mmap(NULL, f->file_size, flags, MAP_SHARED, f->fd, f->file_offset);
201         if (f->mmap == MAP_FAILED) {
202                 f->mmap = NULL;
203                 td_verror(td, errno);
204                 return 1;
205         }
206
207         if (td->invalidate_cache) {
208                 if (madvise(f->mmap, f->file_size, MADV_DONTNEED) < 0) {
209                         td_verror(td, errno);
210                         return 1;
211                 }
212         }
213
214         if (td->sequential) {
215                 if (madvise(f->mmap, f->file_size, MADV_SEQUENTIAL) < 0) {
216                         td_verror(td, errno);
217                         return 1;
218                 }
219         } else {
220                 if (madvise(f->mmap, f->file_size, MADV_RANDOM) < 0) {
221                         td_verror(td, errno);
222                         return 1;
223                 }
224         }
225
226         return 0;
227 }
228
229 static int setup_files_mmap(struct thread_data *td)
230 {
231         struct fio_file *f;
232         int i, err = 0;
233
234         for_each_file(td, f, i) {
235                 err = __setup_file_mmap(td, f);
236                 if (err)
237                         break;
238         }
239
240         return err;
241 }
242
243 static int __setup_file_plain(struct thread_data *td, struct fio_file *f)
244 {
245         if (td->invalidate_cache) {
246                 if (fadvise(f->fd, f->file_offset, f->file_size, POSIX_FADV_DONTNEED) < 0) {
247                         td_verror(td, errno);
248                         return 1;
249                 }
250         }
251
252         if (td->sequential) {
253                 if (fadvise(f->fd, f->file_offset, f->file_size, POSIX_FADV_SEQUENTIAL) < 0) {
254                         td_verror(td, errno);
255                         return 1;
256                 }
257         } else {
258                 if (fadvise(f->fd, f->file_offset, f->file_size, POSIX_FADV_RANDOM) < 0) {
259                         td_verror(td, errno);
260                         return 1;
261                 }
262         }
263
264         return 0;
265 }
266
267 static int setup_files_plain(struct thread_data *td)
268 {
269         struct fio_file *f;
270         int i, err = 0;
271
272         for_each_file(td, f, i) {
273                 err = __setup_file_plain(td, f);
274                 if (err)
275                         break;
276         }
277
278         return err;
279 }
280
281 static int setup_file(struct thread_data *td, struct fio_file *f)
282 {
283         int flags = 0;
284
285         if (td->odirect)
286                 flags |= OS_O_DIRECT;
287
288         if (td_write(td) || td_rw(td)) {
289                 if (td->filetype == FIO_TYPE_FILE) {
290                         if (!td->overwrite)
291                                 flags |= O_TRUNC;
292
293                         flags |= O_CREAT;
294                 }
295                 if (td->sync_io)
296                         flags |= O_SYNC;
297
298                 flags |= O_RDWR;
299
300                 f->fd = open(f->file_name, flags, 0600);
301         } else {
302                 if (td->filetype == FIO_TYPE_CHAR)
303                         flags |= O_RDWR;
304                 else
305                         flags |= O_RDONLY;
306
307                 f->fd = open(f->file_name, flags);
308         }
309
310         if (f->fd == -1) {
311                 td_verror(td, errno);
312                 return 1;
313         }
314
315         if (get_file_size(td, f))
316                 return 1;
317
318         return 0;
319 }
320
321 int setup_files(struct thread_data *td)
322 {
323         struct fio_file *f;
324         int i, err;
325
326         /*
327          * if ioengine defines a setup() method, it's responsible for
328          * setting up everything in the td->files[] area.
329          */
330         if (td->io_ops->setup)
331                 return td->io_ops->setup(td);
332
333         if (create_files(td))
334                 return 1;
335
336         for_each_file(td, f, i) {
337                 err = setup_file(td, f);
338                 if (err)
339                         break;
340         }
341
342         if (td->io_size == 0) {
343                 log_err("%s: no io blocks\n", td->name);
344                 td_verror(td, EINVAL);
345                 return 1;
346         }
347
348         if (!td->zone_size)
349                 td->zone_size = td->io_size;
350
351         td->total_io_size = td->io_size * td->loops;
352
353         if (td->io_ops->flags & FIO_MMAPIO)
354                 return setup_files_mmap(td);
355         else
356                 return setup_files_plain(td);
357 }
358
359 void close_files(struct thread_data *td)
360 {
361         int i;
362
363         for (i = 0; i < td->nr_files; i++) {
364                 struct fio_file *f = &td->files[i];
365
366                 if (f->fd != -1) {
367                         close(f->fd);
368                         f->fd = -1;
369                 }
370                 if (f->mmap) {
371                         munmap(f->mmap, f->file_size);
372                         f->mmap = NULL;
373                 }
374         }
375 }