4 * IO engine using Glusterfs's gfapi interface
8 #include <glusterfs/api/glfs.h>
9 #include <glusterfs/api/glfs-handles.h>
13 struct thread_data *td;
23 static struct fio_option options[] = {
26 .lname = "Glusterfs volume",
27 .type = FIO_OPT_STR_STORE,
28 .help = "Name of the Glusterfs volume",
29 .off1 = offsetof(struct gf_options, gf_vol),
30 .category = FIO_OPT_C_ENGINE,
31 .group = FIO_OPT_G_GFAPI,
35 .lname = "Glusterfs brick name",
36 .type = FIO_OPT_STR_STORE,
37 .help = "Name of the Glusterfs brick to connect",
38 .off1 = offsetof(struct gf_options, gf_brick),
39 .category = FIO_OPT_C_ENGINE,
40 .group = FIO_OPT_G_GFAPI,
47 static int fio_gf_setup(struct thread_data *td)
50 struct gf_data *g = NULL;
51 struct gf_options *opt = td->eo;
52 struct stat sb = {0, };
54 dprint(FD_IO, "fio setup\n");
59 g = malloc(sizeof(struct gf_data));
61 log_err("malloc failed.\n");
64 g->fs = NULL; g->fd = NULL;
66 g->fs = glfs_new (opt->gf_vol);
68 log_err("glfs_new failed.\n");
71 glfs_set_logging (g->fs, "/tmp/fio_gfapi.log", 7);
73 r = glfs_set_volfile_server(g->fs, "tcp", opt->gf_brick, 0);
75 log_err("glfs_set_volfile_server failed.\n");
80 log_err("glfs_init failed. Is glusterd running on brick?\n");
84 r = glfs_lstat (g->fs, ".", &sb);
86 log_err("glfs_lstat failed.\n");
89 dprint(FD_FILE, "fio setup %p\n", g->fs);
103 static void fio_gf_cleanup(struct thread_data *td)
107 static int fio_gf_get_file_size(struct thread_data *td, struct fio_file *f)
111 struct gf_data *g = td->io_ops->data;
113 dprint(FD_FILE, "get file size %s\n", f->file_name);
119 if (fio_file_size_known(f))
122 ret = glfs_lstat (g->fs, f->file_name, &buf);
124 log_err("glfs_lstat failed.\n");
128 f->real_file_size = buf.st_size;
129 fio_file_set_size_known(f);
135 static int fio_gf_open_file(struct thread_data *td, struct fio_file *f)
140 struct gf_data *g = td->io_ops->data;
141 struct stat sb = {0, };
146 } else if (td_read(td)) {
152 dprint(FD_FILE, "fio file %s open mode %s td rw %s\n", f->file_name,
153 flags == O_RDONLY? "ro":"rw", td_read(td)? "read":"write");
154 g->fd = glfs_creat(g->fs, f->file_name, flags, 0644);
156 log_err("glfs_creat failed.\n");
159 /* file for read doesn't exist, create one */
160 if (td_read(td) && glfs_lstat (g->fs, "f->file_name", &sb)){
161 dprint(FD_FILE, "fio extend file %s to %ld\n", f->file_name, f->real_file_size);
162 ret = glfs_ftruncate (g->fd, f->real_file_size);
164 log_err("failed fio extend file %s to %ld\n", f->file_name, f->real_file_size);
168 dprint(FD_FILE, "fio %p created %s\n", g->fs, f->file_name);
175 static int fio_gf_close_file(struct thread_data *td, struct fio_file *f)
178 struct gf_data *g = td->io_ops->data;
180 dprint(FD_FILE, "fd close %s\n", f->file_name);
182 if (g->fd && glfs_close(g->fd) < 0)
190 td->io_ops->data = NULL;
196 #define LAST_POS(f) ((f)->engine_data)
197 static int fio_gf_prep(struct thread_data *td, struct io_u *io_u)
199 struct fio_file *f = io_u->file;
200 struct gf_data *g = td->io_ops->data;
202 dprint(FD_FILE, "fio prep\n");
204 if (!ddir_rw(io_u->ddir))
207 if (LAST_POS(f) != -1ULL && LAST_POS(f) == io_u->offset)
210 if (glfs_lseek(g->fd, io_u->offset, SEEK_SET) < 0) {
211 td_verror(td, errno, "lseek");
218 static int fio_gf_queue(struct thread_data *td, struct io_u *io_u)
220 struct gf_data *g = td->io_ops->data;
223 dprint(FD_FILE, "fio queue len %lu\n", io_u->xfer_buflen);
224 fio_ro_check(td, io_u);
226 if (io_u->ddir == DDIR_READ)
227 ret = glfs_read(g->fd, io_u->xfer_buf, io_u->xfer_buflen, 0);
228 else if (io_u->ddir == DDIR_WRITE)
229 ret = glfs_write(g->fd, io_u->xfer_buf, io_u->xfer_buflen, 0);
231 log_err("unsupported operation.\n");
234 dprint(FD_FILE, "fio len %lu ret %d\n", io_u->xfer_buflen, ret);
235 if (io_u->file && ret >= 0 && ddir_rw(io_u->ddir))
236 LAST_POS(io_u->file) = io_u->offset + ret;
238 if (ret != (int) io_u->xfer_buflen) {
240 io_u->resid = io_u->xfer_buflen - ret;
242 return FIO_Q_COMPLETED;
248 log_err("IO failed.\n");
249 td_verror(td, io_u->error, "xfer");
252 return FIO_Q_COMPLETED;
256 static struct ioengine_ops ioengine = {
258 .version = FIO_IOOPS_VERSION,
259 .init = fio_gf_setup,
260 .cleanup = fio_gf_cleanup,
262 .queue = fio_gf_queue,
263 .open_file = fio_gf_open_file,
264 .close_file = fio_gf_close_file,
265 .get_file_size = fio_gf_get_file_size,
267 .option_struct_size = sizeof(struct gf_options),
268 .flags = FIO_SYNCIO | FIO_DISKLESSIO,
271 static void fio_init fio_gf_register(void)
273 register_ioengine(&ioengine);
276 static void fio_exit fio_gf_unregister(void)
278 unregister_ioengine(&ioengine);