fix man page; fix read work
[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>
7cb57176 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};
7cb57176 22
6e7d7dfb 23static struct fio_option options[] = {
24 {
a7c386f4 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,
6e7d7dfb 32 },
33 {
a7c386f4 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,
6e7d7dfb 41 },
42 {
a7c386f4 43 .name = NULL,
6e7d7dfb 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;
a7c386f4 52 struct stat sb = {0, };
7cb57176 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 }
7cb57176 71 glfs_set_logging (g->fs, "/tmp/fio_gfapi.log", 7);
6e7d7dfb 72 /* default to tcp */
7cb57176 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){
7cb57176 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 }
7cb57176 89 dprint(FD_FILE, "fio setup %p\n", g->fs);
6e7d7dfb 90 td->io_ops->data = g;
91cleanup:
7cb57176 92 if (r){
93 if (g){
a7c386f4 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 {
a7c386f4 117 return 0;
6aa56500 118 }
6e7d7dfb 119 if (fio_file_size_known(f))
a7c386f4 120 return 0;
6e7d7dfb 121
122 ret = glfs_lstat (g->fs, f->file_name, &buf);
7cb57176 123 if (ret < 0){
a7c386f4 124 log_err("glfs_lstat failed.\n");
125 return ret;
7cb57176 126 }
6e7d7dfb 127
128 f->real_file_size = buf.st_size;
129 fio_file_set_size_known(f);
130
131 return 0;
132
133}
134
135static int fio_gf_open_file(struct thread_data *td, struct fio_file *f)
136{
a8a93dee 137
7cb57176 138 int flags = 0;
139 int ret = 0;
140 struct gf_data *g = td->io_ops->data;
a7c386f4 141 struct stat sb = {0, };
6e7d7dfb 142
143 if (td_write(td)) {
a7c386f4 144 if (!read_only)
145 flags = O_RDWR;
6e7d7dfb 146 } else if (td_read(td)) {
a7c386f4 147 if (!read_only)
148 flags = O_RDWR;
149 else
150 flags = O_RDONLY;
6e7d7dfb 151 }
a7c386f4 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);
7cb57176 155 if (!g->fd){
a7c386f4 156 log_err("glfs_creat failed.\n");
157 ret = errno;
7cb57176 158 }
a7c386f4 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);
163 if (ret){
164 log_err("failed fio extend file %s to %ld\n", f->file_name, f->real_file_size);
165 }
166 }
167
7cb57176 168 dprint(FD_FILE, "fio %p created %s\n", g->fs, f->file_name);
a8a93dee 169 f->fd = -1;
7cb57176 170 f->shadow_fd = -1;
171
172 return ret;
6e7d7dfb 173}
174
175static int fio_gf_close_file(struct thread_data *td, struct fio_file *f)
176{
177 int ret = 0;
178 struct gf_data *g = td->io_ops->data;
179
180 dprint(FD_FILE, "fd close %s\n", f->file_name);
181
7cb57176 182 if (g->fd && glfs_close(g->fd) < 0)
183 ret = errno;
184
185 if (g->fs)
186 glfs_fini(g->fs);
6e7d7dfb 187
188 g->fd = NULL;
7cb57176 189 free(g);
190 td->io_ops->data = NULL;
6e7d7dfb 191 f->engine_data = 0;
192
193 return ret;
194}
195
196#define LAST_POS(f) ((f)->engine_data)
197static int fio_gf_prep(struct thread_data *td, struct io_u *io_u)
198{
199 struct fio_file *f = io_u->file;
200 struct gf_data *g = td->io_ops->data;
201
7cb57176 202 dprint(FD_FILE, "fio prep\n");
203
6e7d7dfb 204 if (!ddir_rw(io_u->ddir))
205 return 0;
206
207 if (LAST_POS(f) != -1ULL && LAST_POS(f) == io_u->offset)
208 return 0;
209
210 if (glfs_lseek(g->fd, io_u->offset, SEEK_SET) < 0) {
211 td_verror(td, errno, "lseek");
212 return 1;
213 }
214
215 return 0;
216}
217
218static int fio_gf_queue(struct thread_data *td, struct io_u *io_u)
219{
220 struct gf_data *g = td->io_ops->data;
221 int ret = 0;
222
7cb57176 223 dprint(FD_FILE, "fio queue len %lu\n", io_u->xfer_buflen);
6e7d7dfb 224 fio_ro_check(td, io_u);
225
226 if (io_u->ddir == DDIR_READ)
a7c386f4 227 ret = glfs_read(g->fd, io_u->xfer_buf, io_u->xfer_buflen, 0);
6e7d7dfb 228 else if (io_u->ddir == DDIR_WRITE)
a7c386f4 229 ret = glfs_write(g->fd, io_u->xfer_buf, io_u->xfer_buflen, 0);
6e7d7dfb 230 else {
a7c386f4 231 log_err("unsupported operation.\n");
232 return -EINVAL;
6e7d7dfb 233 }
a7c386f4 234 dprint(FD_FILE, "fio len %lu ret %d\n", io_u->xfer_buflen, ret);
6e7d7dfb 235 if (io_u->file && ret >= 0 && ddir_rw(io_u->ddir))
a7c386f4 236 LAST_POS(io_u->file) = io_u->offset + ret;
6e7d7dfb 237
238 if (ret != (int) io_u->xfer_buflen) {
a7c386f4 239 if (ret >= 0) {
240 io_u->resid = io_u->xfer_buflen - ret;
241 io_u->error = 0;
242 return FIO_Q_COMPLETED;
243 } else
244 io_u->error = errno;
6e7d7dfb 245 }
246
7cb57176 247 if (io_u->error){
a7c386f4 248 log_err("IO failed.\n");
249 td_verror(td, io_u->error, "xfer");
7cb57176 250 }
6e7d7dfb 251
252 return FIO_Q_COMPLETED;
253
254}
255
256static struct ioengine_ops ioengine = {
257 .name = "gfapi",
258 .version = FIO_IOOPS_VERSION,
a7c386f4 259 .init = fio_gf_setup,
260 .cleanup = fio_gf_cleanup,
6e7d7dfb 261 .prep = fio_gf_prep,
262 .queue = fio_gf_queue,
263 .open_file = fio_gf_open_file,
264 .close_file = fio_gf_close_file,
a7c386f4 265 .get_file_size = fio_gf_get_file_size,
266 .options = options,
6e7d7dfb 267 .option_struct_size = sizeof(struct gf_options),
7cb57176 268 .flags = FIO_SYNCIO | FIO_DISKLESSIO,
6e7d7dfb 269};
270
271static void fio_init fio_gf_register(void)
272{
273 register_ioengine(&ioengine);
274}
275
276static void fio_exit fio_gf_unregister(void)
277{
278 unregister_ioengine(&ioengine);
279}