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;
111 dprint(FD_FILE, "get file size %s\n", f->file_name);
118 >>>>>>> parent of 6aa5650... make glfs call per thread based
119 if (fio_file_size_known(f))
122 ret = glfs_lstat (g->fs, f->file_name, &buf);
126 f->real_file_size = buf.st_size;
127 fio_file_set_size_known(f);
133 static int fio_gf_open_file(struct thread_data *td, struct fio_file *f)
135 struct gf_data *g = td->io_ops->data;
138 dprint(FD_FILE, "fd open %s\n", f->file_name);
143 } else if (td_read(td)) {
149 if (td->o.create_on_open)
152 g->fd = glfs_open(g->fs, f->file_name, flags);
157 static int fio_gf_close_file(struct thread_data *td, struct fio_file *f)
160 struct gf_data *g = td->io_ops->data;
162 dprint(FD_FILE, "fd close %s\n", f->file_name);
164 if (!g->fd && glfs_close(g->fd) < 0)
173 #define LAST_POS(f) ((f)->engine_data)
174 static int fio_gf_prep(struct thread_data *td, struct io_u *io_u)
176 struct fio_file *f = io_u->file;
177 struct gf_data *g = td->io_ops->data;
179 if (!ddir_rw(io_u->ddir))
182 if (LAST_POS(f) != -1ULL && LAST_POS(f) == io_u->offset)
185 if (glfs_lseek(g->fd, io_u->offset, SEEK_SET) < 0) {
186 td_verror(td, errno, "lseek");
193 static int fio_gf_queue(struct thread_data *td, struct io_u *io_u)
195 struct gf_data *g = td->io_ops->data;
198 fio_ro_check(td, io_u);
200 if (io_u->ddir == DDIR_READ)
201 ret = glfs_read(g->fd, io_u->xfer_buf, io_u->xfer_buflen, 0);
202 else if (io_u->ddir == DDIR_WRITE)
203 ret = glfs_write(g->fd, io_u->xfer_buf, io_u->xfer_buflen, 0);
205 log_err("unsupported operation.\n");
208 if (io_u->file && ret >= 0 && ddir_rw(io_u->ddir))
209 LAST_POS(io_u->file) = io_u->offset + ret;
211 if (ret != (int) io_u->xfer_buflen) {
213 io_u->resid = io_u->xfer_buflen - ret;
215 return FIO_Q_COMPLETED;
221 td_verror(td, io_u->error, "xfer");
223 return FIO_Q_COMPLETED;
227 static struct ioengine_ops ioengine = {
229 .version = FIO_IOOPS_VERSION,
230 .setup = fio_gf_setup,
231 .cleanup = fio_gf_cleanup,
233 .queue = fio_gf_queue,
234 .open_file = fio_gf_open_file,
235 .close_file = fio_gf_close_file,
236 .get_file_size = fio_gf_get_file_size,
238 .option_struct_size = sizeof(struct gf_options),
242 static void fio_init fio_gf_register(void)
244 register_ioengine(&ioengine);
247 static void fio_exit fio_gf_unregister(void)
249 unregister_ioengine(&ioengine);