[PATCH] Don't segfault on missing argument data
[fio.git] / engines / fio-engine-sync.c
1 /*
2  * regular read/write sync io engine
3  *
4  */
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <unistd.h>
8 #include <errno.h>
9 #include <assert.h>
10
11 #include "../fio.h"
12 #include "../os.h"
13
14 struct syncio_data {
15         struct io_u *last_io_u;
16 };
17
18 static int fio_syncio_getevents(struct thread_data *td, int fio_unused min,
19                                 int max, struct timespec fio_unused *t)
20 {
21         assert(max <= 1);
22
23         /*
24          * we can only have one finished io_u for sync io, since the depth
25          * is always 1
26          */
27         if (list_empty(&td->io_u_busylist))
28                 return 0;
29
30         return 1;
31 }
32
33 static struct io_u *fio_syncio_event(struct thread_data *td, int event)
34 {
35         struct syncio_data *sd = td->io_ops->data;
36
37         assert(event == 0);
38
39         return sd->last_io_u;
40 }
41
42 static int fio_syncio_prep(struct thread_data *td, struct io_u *io_u)
43 {
44         struct fio_file *f = io_u->file;
45
46         if (io_u->ddir == DDIR_SYNC)
47                 return 0;
48
49         if (lseek(f->fd, io_u->offset, SEEK_SET) == -1) {
50                 td_verror(td, errno);
51                 return 1;
52         }
53
54         return 0;
55 }
56
57 static int fio_syncio_queue(struct thread_data *td, struct io_u *io_u)
58 {
59         struct syncio_data *sd = td->io_ops->data;
60         struct fio_file *f = io_u->file;
61         unsigned int ret;
62
63         if (io_u->ddir == DDIR_READ)
64                 ret = read(f->fd, io_u->buf, io_u->buflen);
65         else if (io_u->ddir == DDIR_WRITE)
66                 ret = write(f->fd, io_u->buf, io_u->buflen);
67         else
68                 ret = fsync(f->fd);
69
70         if (ret != io_u->buflen) {
71                 if (ret > 0) {
72                         io_u->resid = io_u->buflen - ret;
73                         io_u->error = EIO;
74                 } else
75                         io_u->error = errno;
76         }
77
78         if (!io_u->error)
79                 sd->last_io_u = io_u;
80
81         return io_u->error;
82 }
83
84 static void fio_syncio_cleanup(struct thread_data *td)
85 {
86         if (td->io_ops->data) {
87                 free(td->io_ops->data);
88                 td->io_ops->data = NULL;
89         }
90 }
91
92 static int fio_syncio_init(struct thread_data *td)
93 {
94         struct syncio_data *sd = malloc(sizeof(*sd));
95
96         sd->last_io_u = NULL;
97         td->io_ops->data = sd;
98         return 0;
99 }
100
101 static struct ioengine_ops ioengine = {
102         .name           = "sync",
103         .version        = FIO_IOOPS_VERSION,
104         .init           = fio_syncio_init,
105         .prep           = fio_syncio_prep,
106         .queue          = fio_syncio_queue,
107         .getevents      = fio_syncio_getevents,
108         .event          = fio_syncio_event,
109         .cleanup        = fio_syncio_cleanup,
110         .flags          = FIO_SYNCIO,
111 };
112
113 static void fio_init fio_syncio_register(void)
114 {
115         register_ioengine(&ioengine);
116 }
117
118 static void fio_exit fio_syncio_unregister(void)
119 {
120         unregister_ioengine(&ioengine);
121 }