[PATCH] Unlink write file if !overwrite and it exists
[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 == WRITE && !td->overwrite) {
111                                 unlink(f->file_name);
112                                 file_there = 0;
113                         }
114
115                         need_create += !file_there;
116                 }
117         }
118
119         if (!need_create)
120                 return 0;
121
122         if (!td->total_file_size) {
123                 log_err("Need size for create\n");
124                 td_verror(td, EINVAL);
125                 return 1;
126         }
127
128         temp_stall_ts = 1;
129         fprintf(f_out, "%s: Laying out IO file(s) (%u x %LuMiB == %LuMiB)\n",
130                                 td->name, td->nr_uniq_files,
131                                 (td->total_file_size >> 20) / td->nr_uniq_files,
132                                 td->total_file_size >> 20);
133
134         err = 0;
135         for_each_file(td, f, i) {
136                 /*
137                  * Only unlink files that we created.
138                  */
139                 f->unlink = 0;
140                 if (file_ok(td, f)) {
141                         f->unlink = td->unlink;
142                         err = create_file(td, f);
143                         if (err)
144                                 break;
145                 }
146         }
147
148         temp_stall_ts = 0;
149         return err;
150 }
151
152 static int file_size(struct thread_data *td, struct fio_file *f)
153 {
154         struct stat st;
155
156         if (td->overwrite) {
157                 if (fstat(f->fd, &st) == -1) {
158                         td_verror(td, errno);
159                         return 1;
160                 }
161
162                 f->real_file_size = st.st_size;
163
164                 if (!f->file_size || f->file_size > f->real_file_size)
165                         f->file_size = f->real_file_size;
166         } else
167                 f->real_file_size = f->file_size;
168
169         return 0;
170 }
171
172 static int bdev_size(struct thread_data *td, struct fio_file *f)
173 {
174         unsigned long long bytes;
175         int r;
176
177         r = blockdev_size(f->fd, &bytes);
178         if (r) {
179                 td_verror(td, r);
180                 return 1;
181         }
182
183         f->real_file_size = bytes;
184
185         /*
186          * no extend possibilities, so limit size to device size if too large
187          */
188         if (!f->file_size || f->file_size > f->real_file_size)
189                 f->file_size = f->real_file_size;
190
191         f->file_size -= f->file_offset;
192         return 0;
193 }
194
195 static int get_file_size(struct thread_data *td, struct fio_file *f)
196 {
197         int ret = 0;
198
199         if (td->filetype == FIO_TYPE_FILE)
200                 ret = file_size(td, f);
201         else if (td->filetype == FIO_TYPE_BD)
202                 ret = bdev_size(td, f);
203         else
204                 f->real_file_size = -1;
205
206         if (ret)
207                 return ret;
208
209         if (f->file_offset > f->real_file_size) {
210                 log_err("%s: offset extends end (%Lu > %Lu)\n", td->name, f->file_offset, f->real_file_size);
211                 return 1;
212         }
213
214         return 0;
215 }
216
217 int file_invalidate_cache(struct thread_data *td, struct fio_file *f)
218 {
219         int ret = 0;
220
221         /*
222          * FIXME: add blockdev flushing too
223          */
224         if (td->io_ops->flags & FIO_MMAPIO)
225                 ret = madvise(f->mmap, f->file_size, MADV_DONTNEED);
226         else if (td->filetype == FIO_TYPE_FILE)
227                 ret = fadvise(f->fd, f->file_offset, f->file_size, POSIX_FADV_DONTNEED);
228         else if (td->filetype == FIO_TYPE_BD)
229                 ret = blockdev_invalidate_cache(f->fd);
230         else if (td->filetype == FIO_TYPE_CHAR)
231                 ret = 0;
232
233         if (ret < 0) {
234                 td_verror(td, errno);
235                 return 1;
236         }
237
238         return 0;
239 }
240
241 static int __setup_file_mmap(struct thread_data *td, struct fio_file *f)
242 {
243         int flags;
244
245         if (td_rw(td))
246                 flags = PROT_READ | PROT_WRITE;
247         else if (td_write(td)) {
248                 flags = PROT_WRITE;
249
250                 if (td->verify != VERIFY_NONE)
251                         flags |= PROT_READ;
252         } else
253                 flags = PROT_READ;
254
255         f->mmap = mmap(NULL, f->file_size, flags, MAP_SHARED, f->fd, f->file_offset);
256         if (f->mmap == MAP_FAILED) {
257                 f->mmap = NULL;
258                 td_verror(td, errno);
259                 return 1;
260         }
261
262         if (td->invalidate_cache && file_invalidate_cache(td, f))
263                 return 1;
264
265         if (td->sequential) {
266                 if (madvise(f->mmap, f->file_size, MADV_SEQUENTIAL) < 0) {
267                         td_verror(td, errno);
268                         return 1;
269                 }
270         } else {
271                 if (madvise(f->mmap, f->file_size, MADV_RANDOM) < 0) {
272                         td_verror(td, errno);
273                         return 1;
274                 }
275         }
276
277         return 0;
278 }
279
280 static int setup_files_mmap(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_mmap(td, f);
287                 if (err)
288                         break;
289         }
290
291         return err;
292 }
293
294 static int __setup_file_plain(struct thread_data *td, struct fio_file *f)
295 {
296         if (td->invalidate_cache && file_invalidate_cache(td, f))
297                 return 1;
298
299         if (td->sequential) {
300                 if (fadvise(f->fd, f->file_offset, f->file_size, POSIX_FADV_SEQUENTIAL) < 0) {
301                         td_verror(td, errno);
302                         return 1;
303                 }
304         } else {
305                 if (fadvise(f->fd, f->file_offset, f->file_size, POSIX_FADV_RANDOM) < 0) {
306                         td_verror(td, errno);
307                         return 1;
308                 }
309         }
310
311         return 0;
312 }
313
314 static int setup_files_plain(struct thread_data *td)
315 {
316         struct fio_file *f;
317         int i, err = 0;
318
319         for_each_file(td, f, i) {
320                 err = __setup_file_plain(td, f);
321                 if (err)
322                         break;
323         }
324
325         return err;
326 }
327
328 static int setup_file(struct thread_data *td, struct fio_file *f)
329 {
330         int flags = 0;
331
332         if (td->odirect)
333                 flags |= OS_O_DIRECT;
334         if (td->sync_io)
335                 flags |= O_SYNC;
336
337         if (td_write(td) || td_rw(td)) {
338                 flags |= O_RDWR;
339
340                 if (td->filetype == FIO_TYPE_FILE) {
341                         if (!td->overwrite)
342                                 flags |= O_TRUNC;
343
344                         flags |= O_CREAT;
345                 }
346
347                 f->fd = open(f->file_name, flags, 0600);
348         } else {
349                 if (td->filetype == FIO_TYPE_CHAR)
350                         flags |= O_RDWR;
351                 else
352                         flags |= O_RDONLY;
353
354                 f->fd = open(f->file_name, flags);
355         }
356
357         if (f->fd == -1) {
358                 td_verror(td, errno);
359                 return 1;
360         }
361
362         if (get_file_size(td, f))
363                 return 1;
364
365         return 0;
366 }
367
368 int open_files(struct thread_data *td)
369 {
370         struct fio_file *f;
371         int i, err = 0;
372
373         for_each_file(td, f, i) {
374                 err = setup_file(td, f);
375                 if (err)
376                         break;
377         }
378
379         if (!err)
380                 return 0;
381
382         for_each_file(td, f, i) {
383                 if (f->fd != -1) {
384                         close(f->fd);
385                         f->fd = -1;
386                 }
387         }
388
389         return err;
390 }
391
392 int setup_files(struct thread_data *td)
393 {
394         struct fio_file *f;
395         int err, i;
396
397         /*
398          * if ioengine defines a setup() method, it's responsible for
399          * setting up everything in the td->files[] area.
400          */
401         if (td->io_ops->setup)
402                 return td->io_ops->setup(td);
403
404         if (create_files(td))
405                 return 1;
406
407         err = open_files(td);
408         if (err)
409                 return err;
410
411         /*
412          * Recalculate the total file size now that files are set up.
413          */
414         td->total_file_size = 0;
415         for_each_file(td, f, i)
416                 td->total_file_size += f->file_size;
417
418         td->io_size = td->total_file_size;
419         if (td->io_size == 0) {
420                 log_err("%s: no io blocks\n", td->name);
421                 td_verror(td, EINVAL);
422                 return 1;
423         }
424
425         if (!td->zone_size)
426                 td->zone_size = td->io_size;
427
428         td->total_io_size = td->io_size * td->loops;
429
430         if (td->io_ops->flags & FIO_MMAPIO)
431                 err = setup_files_mmap(td);
432         else
433                 err = setup_files_plain(td);
434
435         for_each_file(td, f, i) {
436                 if (f->fd != -1) {
437                         close(f->fd);
438                         f->fd = -1;
439                 }
440         }
441
442         return err;
443 }
444
445 void close_files(struct thread_data *td)
446 {
447         struct fio_file *f;
448         int i;
449
450         for_each_file(td, f, i) {
451                 if (!td->filename && f->unlink &&
452                     td->filetype == FIO_TYPE_FILE) {
453                         unlink(f->file_name);
454                         free(f->file_name);
455                         f->file_name = NULL;
456                 }
457                 if (f->fd != -1) {
458                         close(f->fd);
459                         f->fd = -1;
460                 }
461                 if (f->mmap) {
462                         munmap(f->mmap, f->file_size);
463                         f->mmap = NULL;
464                 }
465         }
466
467         td->filename = NULL;
468         free(td->files);
469         td->files = NULL;
470         td->nr_files = 0;
471 }