Commit | Line | Data |
---|---|---|
e615ceaf DM |
1 | /* |
2 | * falloc: ioengine for git://git.kernel.dk/fio.git | |
3 | * | |
4 | * IO engine that does regular fallocate to simulate data transfer | |
5 | * as fio ioengine. | |
6 | * DDIR_READ does fallocate(,mode = FALLOC_FL_KEEP_SIZE,) | |
de8f6de9 | 7 | * DDIR_WRITE does fallocate(,mode = 0) : fallocate with size extension |
e615ceaf DM |
8 | * DDIR_TRIM does fallocate(,mode = FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE) |
9 | * | |
10 | */ | |
11 | #include <stdio.h> | |
e615ceaf | 12 | #include <errno.h> |
e615ceaf DM |
13 | #include <fcntl.h> |
14 | ||
15 | #include "../fio.h" | |
16 | #include "../filehash.h" | |
17 | ||
18 | /* | |
19 | * generic_open_file is not appropriate because does not allow to perform | |
20 | * TRIM in to file | |
21 | */ | |
10aa136b | 22 | static int open_file(struct thread_data *td, struct fio_file *f) |
e615ceaf DM |
23 | { |
24 | int from_hash = 0; | |
25 | ||
26 | dprint(FD_FILE, "fd open %s\n", f->file_name); | |
27 | ||
dcfc77d3 DM |
28 | if (f->filetype != FIO_TYPE_FILE && f->filetype != FIO_TYPE_BLOCK) { |
29 | log_err("fio: only files and blockdev are supported fallocate \n"); | |
e615ceaf DM |
30 | return 1; |
31 | } | |
32 | if (!strcmp(f->file_name, "-")) { | |
33 | log_err("fio: can't read/write to stdin/out\n"); | |
34 | return 1; | |
35 | } | |
36 | ||
37 | open_again: | |
38 | from_hash = file_lookup_open(f, O_CREAT|O_RDWR); | |
39 | ||
40 | if (f->fd == -1) { | |
41 | char buf[FIO_VERROR_SIZE]; | |
0b783341 JA |
42 | int e = errno; |
43 | ||
98ffb8f3 | 44 | snprintf(buf, sizeof(buf), "open(%s)", f->file_name); |
0b783341 | 45 | td_verror(td, e, buf); |
e615ceaf DM |
46 | } |
47 | ||
48 | if (!from_hash && f->fd != -1) { | |
49 | if (add_file_hash(f)) { | |
50 | int fio_unused ret; | |
51 | ||
52 | /* | |
53 | * OK to ignore, we haven't done anything with it | |
54 | */ | |
55 | ret = generic_close_file(td, f); | |
56 | goto open_again; | |
57 | } | |
58 | } | |
59 | ||
60 | return 0; | |
61 | } | |
62 | ||
63 | #ifndef FALLOC_FL_KEEP_SIZE | |
64 | #define FALLOC_FL_KEEP_SIZE 0x01 /* default is extend size */ | |
65 | #endif | |
66 | #ifndef FALLOC_FL_PUNCH_HOLE | |
67 | #define FALLOC_FL_PUNCH_HOLE 0x02 /* de-allocates range */ | |
2e4ef4fb JA |
68 | #endif |
69 | ||
70 | static enum fio_q_status fio_fallocate_queue(struct thread_data *td, | |
71 | struct io_u *io_u) | |
e615ceaf DM |
72 | { |
73 | struct fio_file *f = io_u->file; | |
74 | int ret; | |
75 | int flags = 0; | |
76 | ||
77 | fio_ro_check(td, io_u); | |
78 | ||
79 | if (io_u->ddir == DDIR_READ) | |
80 | flags = FALLOC_FL_KEEP_SIZE; | |
81 | else if (io_u->ddir == DDIR_WRITE) | |
82 | flags = 0; | |
83 | else if (io_u->ddir == DDIR_TRIM) | |
84 | flags = FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE; | |
85 | ||
86 | ret = fallocate(f->fd, flags, io_u->offset, io_u->xfer_buflen); | |
87 | ||
e12d2800 | 88 | if (ret) |
e615ceaf | 89 | io_u->error = errno; |
e615ceaf | 90 | |
e615ceaf DM |
91 | return FIO_Q_COMPLETED; |
92 | } | |
93 | ||
94 | static struct ioengine_ops ioengine = { | |
95 | .name = "falloc", | |
96 | .version = FIO_IOOPS_VERSION, | |
97 | .queue = fio_fallocate_queue, | |
98 | .open_file = open_file, | |
99 | .close_file = generic_close_file, | |
100 | .get_file_size = generic_get_file_size, | |
101 | .flags = FIO_SYNCIO | |
102 | }; | |
103 | ||
104 | static void fio_init fio_syncio_register(void) | |
105 | { | |
106 | register_ioengine(&ioengine); | |
107 | } | |
108 | ||
109 | static void fio_exit fio_syncio_unregister(void) | |
110 | { | |
111 | unregister_ioengine(&ioengine); | |
112 | } |