blob: 2af6c2fc560b99237b6ca24344f4a8c55426289c [file] [log] [blame]
Jens Axboe53cdc682006-10-18 11:50:58 +02001#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
Jens Axboe25205e92006-10-19 20:50:14 +020011/*
12 * Check if the file exists and it's large enough.
13 */
14static int file_ok(struct thread_data *td, struct fio_file *f)
Jens Axboe53cdc682006-10-18 11:50:58 +020015{
Jens Axboeb2a15192006-10-18 14:10:42 +020016 struct stat st;
Jens Axboe53cdc682006-10-18 11:50:58 +020017
Jens Axboeb2a15192006-10-18 14:10:42 +020018 if (td->filetype != FIO_TYPE_FILE)
19 return 0;
20
Jens Axboe25205e92006-10-19 20:50:14 +020021 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
29static 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;
Jens Axboeb2a15192006-10-18 14:10:42 +020035
Jens Axboe53cdc682006-10-18 11:50:58 +020036 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
Jens Axboe40f82982006-10-25 11:21:05 +020047 if (posix_fallocate(f->fd, 0, f->file_size) < 0) {
48 td_verror(td, errno);
49 goto err;
50 }
51
Jens Axboea00735e2006-11-03 08:58:08 +010052 b = malloc(td->max_bs[DDIR_WRITE]);
53 memset(b, 0, td->max_bs[DDIR_WRITE]);
Jens Axboe53cdc682006-10-18 11:50:58 +020054
55 left = f->file_size;
56 while (left && !td->terminate) {
Jens Axboea00735e2006-11-03 08:58:08 +010057 bs = td->max_bs[DDIR_WRITE];
Jens Axboe53cdc682006-10-18 11:50:58 +020058 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;
85err:
86 close(f->fd);
87 f->fd = -1;
88 return 1;
89}
90
91static int create_files(struct thread_data *td)
92{
93 struct fio_file *f;
Jens Axboe25205e92006-10-19 20:50:14 +020094 int i, err, need_create;
Jens Axboe53cdc682006-10-18 11:50:58 +020095
Jens Axboef6971252006-11-15 10:00:31 +010096 for_each_file(td, f, i)
97 f->file_size = td->total_file_size / td->nr_files;
98
Jens Axboe53cdc682006-10-18 11:50:58 +020099 /*
100 * unless specifically asked for overwrite, let normal io extend it
101 */
Jens Axboef6971252006-11-15 10:00:31 +0100102 if (!td->overwrite)
Jens Axboe53cdc682006-10-18 11:50:58 +0200103 return 0;
Jens Axboe53cdc682006-10-18 11:50:58 +0200104
Jens Axboef1027062006-10-20 10:14:01 +0200105 need_create = 0;
Jens Axboeeff68612007-01-14 05:56:44 +0100106 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 }
Jens Axboef1027062006-10-20 10:14:01 +0200118
119 if (!need_create)
120 return 0;
121
Jens Axboe53cdc682006-10-18 11:50:58 +0200122 if (!td->total_file_size) {
123 log_err("Need size for create\n");
124 td_verror(td, EINVAL);
125 return 1;
126 }
127
Jens Axboe25205e92006-10-19 20:50:14 +0200128 temp_stall_ts = 1;
Jens Axboe1e97cce2006-12-05 11:44:16 +0100129 fprintf(f_out, "%s: Laying out IO file(s) (%u x %LuMiB == %LuMiB)\n",
Jens Axboe13f8e2d2006-10-24 09:29:45 +0200130 td->name, td->nr_uniq_files,
131 (td->total_file_size >> 20) / td->nr_uniq_files,
Jens Axboe25205e92006-10-19 20:50:14 +0200132 td->total_file_size >> 20);
133
134 err = 0;
135 for_each_file(td, f, i) {
Jens Axboe9b031dc2006-12-15 16:01:54 +0100136 /*
137 * Only unlink files that we created.
138 */
139 f->unlink = 0;
Jens Axboe25205e92006-10-19 20:50:14 +0200140 if (file_ok(td, f)) {
Jens Axboe9b031dc2006-12-15 16:01:54 +0100141 f->unlink = td->unlink;
Jens Axboe25205e92006-10-19 20:50:14 +0200142 err = create_file(td, f);
143 if (err)
144 break;
145 }
146 }
147
Jens Axboe53cdc682006-10-18 11:50:58 +0200148 temp_stall_ts = 0;
149 return err;
150}
151
152static 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;
Jens Axboe745508d2007-01-08 10:25:51 +0100166 } else
167 f->real_file_size = f->file_size;
Jens Axboe53cdc682006-10-18 11:50:58 +0200168
Jens Axboe53cdc682006-10-18 11:50:58 +0200169 return 0;
170}
171
172static 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
195static 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
Jens Axboe53cdc682006-10-18 11:50:58 +0200214 return 0;
215}
216
Jens Axboee5b401d2006-10-18 16:03:40 +0200217int 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
Jens Axboe53cdc682006-10-18 11:50:58 +0200241static 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
Jens Axboee5b401d2006-10-18 16:03:40 +0200262 if (td->invalidate_cache && file_invalidate_cache(td, f))
263 return 1;
Jens Axboe53cdc682006-10-18 11:50:58 +0200264
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
280static 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
294static int __setup_file_plain(struct thread_data *td, struct fio_file *f)
295{
Jens Axboee5b401d2006-10-18 16:03:40 +0200296 if (td->invalidate_cache && file_invalidate_cache(td, f))
297 return 1;
Jens Axboe53cdc682006-10-18 11:50:58 +0200298
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
314static 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
328static int setup_file(struct thread_data *td, struct fio_file *f)
329{
Jens Axboe53cdc682006-10-18 11:50:58 +0200330 int flags = 0;
331
Jens Axboe53cdc682006-10-18 11:50:58 +0200332 if (td->odirect)
333 flags |= OS_O_DIRECT;
Jens Axboe7abf8332006-11-23 15:01:19 +0100334 if (td->sync_io)
335 flags |= O_SYNC;
Jens Axboe53cdc682006-10-18 11:50:58 +0200336
337 if (td_write(td) || td_rw(td)) {
Jens Axboe7abf8332006-11-23 15:01:19 +0100338 flags |= O_RDWR;
339
Jens Axboe53cdc682006-10-18 11:50:58 +0200340 if (td->filetype == FIO_TYPE_FILE) {
341 if (!td->overwrite)
342 flags |= O_TRUNC;
343
344 flags |= O_CREAT;
345 }
Jens Axboe53cdc682006-10-18 11:50:58 +0200346
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
Jens Axboe21972cd2006-11-23 12:39:16 +0100368int 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
Jens Axboe7abf8332006-11-23 15:01:19 +0100379 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
Jens Axboe21972cd2006-11-23 12:39:16 +0100389 return err;
390}
391
Jens Axboe53cdc682006-10-18 11:50:58 +0200392int setup_files(struct thread_data *td)
393{
394 struct fio_file *f;
Jens Axboe21972cd2006-11-23 12:39:16 +0100395 int err, i;
Jens Axboe53cdc682006-10-18 11:50:58 +0200396
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
Jens Axboe21972cd2006-11-23 12:39:16 +0100407 err = open_files(td);
Jens Axboef1027062006-10-20 10:14:01 +0200408 if (err)
409 return err;
410
Jens Axboe0a7eb122006-10-20 10:36:42 +0200411 /*
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
Jens Axboef1027062006-10-20 10:14:01 +0200418 td->io_size = td->total_file_size;
Jens Axboe53cdc682006-10-18 11:50:58 +0200419 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)
Jens Axboe21972cd2006-11-23 12:39:16 +0100431 err = setup_files_mmap(td);
Jens Axboe53cdc682006-10-18 11:50:58 +0200432 else
Jens Axboe21972cd2006-11-23 12:39:16 +0100433 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;
Jens Axboe53cdc682006-10-18 11:50:58 +0200443}
444
445void close_files(struct thread_data *td)
446{
Jens Axboe0ab8db82006-10-18 17:16:23 +0200447 struct fio_file *f;
Jens Axboe53cdc682006-10-18 11:50:58 +0200448 int i;
449
Jens Axboe0ab8db82006-10-18 17:16:23 +0200450 for_each_file(td, f, i) {
Jens Axboe9b031dc2006-12-15 16:01:54 +0100451 if (!td->filename && f->unlink &&
Jens Axboe02bcaa82006-11-24 10:42:00 +0100452 td->filetype == FIO_TYPE_FILE) {
Jens Axboe132ad462006-11-23 12:23:12 +0100453 unlink(f->file_name);
454 free(f->file_name);
455 f->file_name = NULL;
456 }
Jens Axboe21972cd2006-11-23 12:39:16 +0100457 if (f->fd != -1) {
458 close(f->fd);
459 f->fd = -1;
460 }
Jens Axboe53cdc682006-10-18 11:50:58 +0200461 if (f->mmap) {
462 munmap(f->mmap, f->file_size);
463 f->mmap = NULL;
464 }
465 }
Jens Axboeb4a6a592006-10-20 13:54:47 +0200466
Jens Axboe132ad462006-11-23 12:23:12 +0100467 td->filename = NULL;
Jens Axboeb4a6a592006-10-20 13:54:47 +0200468 free(td->files);
469 td->files = NULL;
470 td->nr_files = 0;
Jens Axboe53cdc682006-10-18 11:50:58 +0200471}