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 dprint(FD_FILE, "get file size %s\n", f->file_name);
117 if (fio_file_size_known(f))
120 ret = glfs_lstat (g->fs, f->file_name, &buf);
124 f->real_file_size = buf.st_size;
125 fio_file_set_size_known(f);
131 static int fio_gf_open_file(struct thread_data *td, struct fio_file *f)
133 struct gf_data *g = td->io_ops->data;
136 dprint(FD_FILE, "fd open %s\n", f->file_name);
141 } else if (td_read(td)) {
147 if (td->o.create_on_open)
150 g->fd = glfs_open(g->fs, f->file_name, flags);
155 static int fio_gf_close_file(struct thread_data *td, struct fio_file *f)
158 struct gf_data *g = td->io_ops->data;
160 dprint(FD_FILE, "fd close %s\n", f->file_name);
162 if (!g->fd && glfs_close(g->fd) < 0)
171 #define LAST_POS(f) ((f)->engine_data)
172 static int fio_gf_prep(struct thread_data *td, struct io_u *io_u)
174 struct fio_file *f = io_u->file;
175 struct gf_data *g = td->io_ops->data;
177 if (!ddir_rw(io_u->ddir))
180 if (LAST_POS(f) != -1ULL && LAST_POS(f) == io_u->offset)
183 if (glfs_lseek(g->fd, io_u->offset, SEEK_SET) < 0) {
184 td_verror(td, errno, "lseek");
191 static int fio_gf_queue(struct thread_data *td, struct io_u *io_u)
193 struct gf_data *g = td->io_ops->data;
196 fio_ro_check(td, io_u);
198 if (io_u->ddir == DDIR_READ)
199 ret = glfs_read(g->fd, io_u->xfer_buf, io_u->xfer_buflen, 0);
200 else if (io_u->ddir == DDIR_WRITE)
201 ret = glfs_write(g->fd, io_u->xfer_buf, io_u->xfer_buflen, 0);
203 log_err("unsupported operation.\n");
206 if (io_u->file && ret >= 0 && ddir_rw(io_u->ddir))
207 LAST_POS(io_u->file) = io_u->offset + ret;
209 if (ret != (int) io_u->xfer_buflen) {
211 io_u->resid = io_u->xfer_buflen - ret;
213 return FIO_Q_COMPLETED;
219 td_verror(td, io_u->error, "xfer");
221 return FIO_Q_COMPLETED;
225 static struct ioengine_ops ioengine = {
227 .version = FIO_IOOPS_VERSION,
228 .setup = fio_gf_setup,
229 .cleanup = fio_gf_cleanup,
231 .queue = fio_gf_queue,
232 .open_file = fio_gf_open_file,
233 .close_file = fio_gf_close_file,
234 .get_file_size = fio_gf_get_file_size,
236 .option_struct_size = sizeof(struct gf_options),
240 static void fio_init fio_gf_register(void)
242 register_ioengine(&ioengine);
245 static void fio_exit fio_gf_unregister(void)
247 unregister_ioengine(&ioengine);