make glfs call per thread based
[fio.git] / engines / glusterfs.c
CommitLineData
6e7d7dfb 1/*
2 * glusterfs engine
3 *
4 * IO engine using Glusterfs's gfapi interface
5 *
6 */
7
8#include <glusterfs/api/glfs.h>
6aa56500 9#include <glusterfs/api/glfs-handles.h>
6e7d7dfb 10#include "../fio.h"
11
12struct gf_options {
13 struct thread_data *td;
14 char *gf_vol;
15 char *gf_brick;
16};
17
18struct gf_data {
19 glfs_t *fs;
20 glfs_fd_t *fd;
21};
6aa56500 22
6e7d7dfb 23static struct fio_option options[] = {
24 {
25 .name = "volume",
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,
32 },
33 {
34 .name = "brick",
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,
41 },
42 {
43 .name = NULL,
44 },
45};
46
47static int fio_gf_setup(struct thread_data *td)
48{
49 int r = 0;
50 struct gf_data *g = NULL;
51 struct gf_options *opt = td->eo;
6aa56500 52 struct stat sb = {0, };
53
54 dprint(FD_IO, "fio setup\n");
6e7d7dfb 55
56 if (td->io_ops->data)
57 return 0;
58
59 g = malloc(sizeof(struct gf_data));
60 if (!g){
61 log_err("malloc failed.\n");
62 return -ENOMEM;
63 }
64 g->fs = NULL; g->fd = NULL;
65
66 g->fs = glfs_new (opt->gf_vol);
67 if (!g->fs){
68 log_err("glfs_new failed.\n");
69 goto cleanup;
70 }
6aa56500 71 glfs_set_logging (g->fs, "/tmp/fio_gfapi.log", 7);
6e7d7dfb 72 /* default to tcp */
6aa56500 73 r = glfs_set_volfile_server(g->fs, "tcp", opt->gf_brick, 0);
6e7d7dfb 74 if (r){
75 log_err("glfs_set_volfile_server failed.\n");
76 goto cleanup;
77 }
78 r = glfs_init(g->fs);
79 if (r){
6aa56500 80 log_err("glfs_init failed. Is glusterd running on brick?\n");
81 goto cleanup;
82 }
83 sleep(2);
84 r = glfs_lstat (g->fs, ".", &sb);
85 if (r){
86 log_err("glfs_lstat failed.\n");
6e7d7dfb 87 goto cleanup;
88 }
6aa56500 89 dprint(FD_FILE, "fio setup %p\n", g->fs);
6e7d7dfb 90 td->io_ops->data = g;
91cleanup:
6aa56500 92 if (r){
93 if (g){
94 if (g->fs){
95 glfs_fini(g->fs);
96 }
97 free(g);
6e7d7dfb 98 }
6e7d7dfb 99 }
100 return r;
101}
102
103static void fio_gf_cleanup(struct thread_data *td)
104{
6e7d7dfb 105}
106
107static int fio_gf_get_file_size(struct thread_data *td, struct fio_file *f)
108{
109 struct stat buf;
110 int ret;
111 struct gf_data *g = td->io_ops->data;
112
6aa56500 113 dprint(FD_FILE, "get file size %s\n", f->file_name);
114
115 if (!g || !g->fs)
116 {
117 f->real_file_size = 0;
118 fio_file_set_size_known(f);
119 }
6e7d7dfb 120 if (fio_file_size_known(f))
121 return 0;
122
123 ret = glfs_lstat (g->fs, f->file_name, &buf);
6aa56500 124 if (ret < 0){
125 log_err("glfs_lstat failed.\n");
6e7d7dfb 126 return ret;
6aa56500 127 }
6e7d7dfb 128
129 f->real_file_size = buf.st_size;
130 fio_file_set_size_known(f);
131
132 return 0;
133
134}
135
136static int fio_gf_open_file(struct thread_data *td, struct fio_file *f)
137{
6e7d7dfb 138
6aa56500 139 int flags = 0;
140 int ret = 0;
141 struct gf_data *g = td->io_ops->data;
6e7d7dfb 142
6aa56500 143 dprint(FD_FILE, "fio open %s\n", f->file_name);
6e7d7dfb 144 if (td_write(td)) {
145 if (!read_only)
146 flags = O_RDWR;
147 } else if (td_read(td)) {
148 if (!read_only)
149 flags = O_RDWR;
150 else
151 flags = O_RDONLY;
152 }
6aa56500 153 g->fd = glfs_creat(g->fs, f->file_name, flags, 0644);
154 if (!g->fd){
155 log_err("glfs_creat failed.\n");
156 ret = errno;
157 }
158 dprint(FD_FILE, "fio %p created %s\n", g->fs, f->file_name);
6e7d7dfb 159 f->fd = -1;
6aa56500 160 f->shadow_fd = -1;
161
162 return ret;
6e7d7dfb 163}
164
165static int fio_gf_close_file(struct thread_data *td, struct fio_file *f)
166{
167 int ret = 0;
168 struct gf_data *g = td->io_ops->data;
169
170 dprint(FD_FILE, "fd close %s\n", f->file_name);
171
6aa56500 172 if (g->fd && glfs_close(g->fd) < 0)
173 ret = errno;
174
175 if (g->fs)
176 glfs_fini(g->fs);
6e7d7dfb 177
178 g->fd = NULL;
6aa56500 179 free(g);
180 td->io_ops->data = NULL;
6e7d7dfb 181 f->engine_data = 0;
182
183 return ret;
184}
185
186#define LAST_POS(f) ((f)->engine_data)
187static int fio_gf_prep(struct thread_data *td, struct io_u *io_u)
188{
189 struct fio_file *f = io_u->file;
190 struct gf_data *g = td->io_ops->data;
191
6aa56500 192 dprint(FD_FILE, "fio prep\n");
193
6e7d7dfb 194 if (!ddir_rw(io_u->ddir))
195 return 0;
196
197 if (LAST_POS(f) != -1ULL && LAST_POS(f) == io_u->offset)
198 return 0;
199
200 if (glfs_lseek(g->fd, io_u->offset, SEEK_SET) < 0) {
201 td_verror(td, errno, "lseek");
202 return 1;
203 }
204
205 return 0;
206}
207
208static int fio_gf_queue(struct thread_data *td, struct io_u *io_u)
209{
210 struct gf_data *g = td->io_ops->data;
211 int ret = 0;
212
6aa56500 213 dprint(FD_FILE, "fio queue len %lu\n", io_u->xfer_buflen);
6e7d7dfb 214 fio_ro_check(td, io_u);
215
216 if (io_u->ddir == DDIR_READ)
217 ret = glfs_read(g->fd, io_u->xfer_buf, io_u->xfer_buflen, 0);
218 else if (io_u->ddir == DDIR_WRITE)
219 ret = glfs_write(g->fd, io_u->xfer_buf, io_u->xfer_buflen, 0);
220 else {
221 log_err("unsupported operation.\n");
222 return -EINVAL;
223 }
6aa56500 224
6e7d7dfb 225 if (io_u->file && ret >= 0 && ddir_rw(io_u->ddir))
226 LAST_POS(io_u->file) = io_u->offset + ret;
227
228 if (ret != (int) io_u->xfer_buflen) {
229 if (ret >= 0) {
230 io_u->resid = io_u->xfer_buflen - ret;
231 io_u->error = 0;
232 return FIO_Q_COMPLETED;
233 } else
234 io_u->error = errno;
235 }
236
6aa56500 237 if (io_u->error){
238 log_err("IO failed.\n");
6e7d7dfb 239 td_verror(td, io_u->error, "xfer");
6aa56500 240 }
6e7d7dfb 241
242 return FIO_Q_COMPLETED;
243
244}
245
246static struct ioengine_ops ioengine = {
247 .name = "gfapi",
248 .version = FIO_IOOPS_VERSION,
6aa56500 249 .init = fio_gf_setup,
6e7d7dfb 250 .cleanup = fio_gf_cleanup,
251 .prep = fio_gf_prep,
252 .queue = fio_gf_queue,
253 .open_file = fio_gf_open_file,
254 .close_file = fio_gf_close_file,
255 .get_file_size = fio_gf_get_file_size,
256 .options = options,
257 .option_struct_size = sizeof(struct gf_options),
6aa56500 258 .flags = FIO_SYNCIO | FIO_DISKLESSIO,
6e7d7dfb 259};
260
261static void fio_init fio_gf_register(void)
262{
263 register_ioengine(&ioengine);
264}
265
266static void fio_exit fio_gf_unregister(void)
267{
268 unregister_ioengine(&ioengine);
269}