4 * IO engine using Glusterfs's gfapi interface
8 #include <glusterfs/api/glfs.h>
13 struct thread_data *td;
22 static struct fio_option options[] = {
25 .lname = "Glusterfs volume",
26 .type = FIO_OPT_STR_STORE,
27 .help = "Name of the Glusterfs volume",
28 .off1 = offsetof(struct gf_options, gf_vol),
29 .category = FIO_OPT_C_ENGINE,
30 .group = FIO_OPT_G_GFAPI,
34 .lname = "Glusterfs brick name",
35 .type = FIO_OPT_STR_STORE,
36 .help = "Name of the Glusterfs brick to connect",
37 .off1 = offsetof(struct gf_options, gf_brick),
38 .category = FIO_OPT_C_ENGINE,
39 .group = FIO_OPT_G_GFAPI,
46 static int fio_gf_setup(struct thread_data *td)
49 struct gf_data *g = NULL;
50 struct gf_options *opt = td->eo;
55 g = malloc(sizeof(struct gf_data));
57 log_err("malloc failed.\n");
60 g->fs = NULL; g->fd = NULL;
62 g->fs = glfs_new (opt->gf_vol);
64 log_err("glfs_new failed.\n");
69 r = glfs_set_volfile_server(g->fs, "tcp", opt->gf_brick, 24007);
71 log_err("glfs_set_volfile_server failed.\n");
76 log_err("glfs_init failed.\n");
79 glfs_set_logging (g->fs, "/dev/stderr", 7);
92 static void fio_gf_cleanup(struct thread_data *td)
94 struct gf_data *g = td->io_ops->data;
104 static int fio_gf_get_file_size(struct thread_data *td, struct fio_file *f)
108 struct gf_data *g = td->io_ops->data;
110 if (fio_file_size_known(f))
113 ret = glfs_lstat (g->fs, f->file_name, &buf);
117 f->real_file_size = buf.st_size;
118 fio_file_set_size_known(f);
124 static int fio_gf_open_file(struct thread_data *td, struct fio_file *f)
126 struct gf_data *g = td->io_ops->data;
129 dprint(FD_FILE, "fd open %s\n", f->file_name);
134 } else if (td_read(td)) {
140 if (td->o.create_on_open)
143 g->fd = glfs_open(g->fs, f->file_name, flags);
148 static int fio_gf_close_file(struct thread_data *td, struct fio_file *f)
151 struct gf_data *g = td->io_ops->data;
153 dprint(FD_FILE, "fd close %s\n", f->file_name);
155 if (!g->fd && glfs_close(g->fd) < 0)
164 #define LAST_POS(f) ((f)->engine_data)
165 static int fio_gf_prep(struct thread_data *td, struct io_u *io_u)
167 struct fio_file *f = io_u->file;
168 struct gf_data *g = td->io_ops->data;
170 if (!ddir_rw(io_u->ddir))
173 if (LAST_POS(f) != -1ULL && LAST_POS(f) == io_u->offset)
176 if (glfs_lseek(g->fd, io_u->offset, SEEK_SET) < 0) {
177 td_verror(td, errno, "lseek");
184 static int fio_gf_queue(struct thread_data *td, struct io_u *io_u)
186 struct gf_data *g = td->io_ops->data;
189 fio_ro_check(td, io_u);
191 if (io_u->ddir == DDIR_READ)
192 ret = glfs_read(g->fd, io_u->xfer_buf, io_u->xfer_buflen, 0);
193 else if (io_u->ddir == DDIR_WRITE)
194 ret = glfs_write(g->fd, io_u->xfer_buf, io_u->xfer_buflen, 0);
196 log_err("unsupported operation.\n");
199 if (io_u->file && ret >= 0 && ddir_rw(io_u->ddir))
200 LAST_POS(io_u->file) = io_u->offset + ret;
202 if (ret != (int) io_u->xfer_buflen) {
204 io_u->resid = io_u->xfer_buflen - ret;
206 return FIO_Q_COMPLETED;
212 td_verror(td, io_u->error, "xfer");
214 return FIO_Q_COMPLETED;
218 static struct ioengine_ops ioengine = {
220 .version = FIO_IOOPS_VERSION,
221 .setup = fio_gf_setup,
222 .cleanup = fio_gf_cleanup,
224 .queue = fio_gf_queue,
225 .open_file = fio_gf_open_file,
226 .close_file = fio_gf_close_file,
227 .get_file_size = fio_gf_get_file_size,
229 .option_struct_size = sizeof(struct gf_options),
233 static void fio_init fio_gf_register(void)
235 register_ioengine(&ioengine);
238 static void fio_exit fio_gf_unregister(void)
240 unregister_ioengine(&ioengine);