respond to get file size
[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>
a8a93dee 9
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};
22static struct fio_option options[] = {
23 {
24 .name = "volume",
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,
31 },
32 {
33 .name = "brick",
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,
40 },
41 {
42 .name = NULL,
43 },
44};
45
46static int fio_gf_setup(struct thread_data *td)
47{
48 int r = 0;
49 struct gf_data *g = NULL;
50 struct gf_options *opt = td->eo;
51
52 if (td->io_ops->data)
53 return 0;
54
55 g = malloc(sizeof(struct gf_data));
56 if (!g){
57 log_err("malloc failed.\n");
58 return -ENOMEM;
59 }
60 g->fs = NULL; g->fd = NULL;
61
62 g->fs = glfs_new (opt->gf_vol);
63 if (!g->fs){
64 log_err("glfs_new failed.\n");
65 goto cleanup;
66 }
a8a93dee 67
6e7d7dfb 68 /* default to tcp */
a8a93dee 69 r = glfs_set_volfile_server(g->fs, "tcp", opt->gf_brick, 24007);
6e7d7dfb 70 if (r){
71 log_err("glfs_set_volfile_server failed.\n");
72 goto cleanup;
73 }
74 r = glfs_init(g->fs);
75 if (r){
a8a93dee 76 log_err("glfs_init failed.\n");
6e7d7dfb 77 goto cleanup;
78 }
a8a93dee 79 glfs_set_logging (g->fs, "/dev/stderr", 7);
80
6e7d7dfb 81 td->io_ops->data = g;
82cleanup:
a8a93dee 83 if (g){
84 if (g->fs){
85 glfs_fini(g->fs);
6e7d7dfb 86 }
a8a93dee 87 free(g);
6e7d7dfb 88 }
89 return r;
90}
91
92static void fio_gf_cleanup(struct thread_data *td)
93{
a8a93dee 94 struct gf_data *g = td->io_ops->data;
95
96 if (g){
97 if (g->fs){
98 glfs_fini(g->fs);
99 }
100 free(g);
101 }
6e7d7dfb 102}
103
104static int fio_gf_get_file_size(struct thread_data *td, struct fio_file *f)
105{
106 struct stat buf;
107 int ret;
108 struct gf_data *g = td->io_ops->data;
109
a8a93dee 110<<<<<<< HEAD
6aa56500 111 dprint(FD_FILE, "get file size %s\n", f->file_name);
112
113 if (!g || !g->fs)
114 {
a8a93dee 115 return 0;
6aa56500 116 }
a8a93dee 117=======
118>>>>>>> parent of 6aa5650... make glfs call per thread based
6e7d7dfb 119 if (fio_file_size_known(f))
120 return 0;
121
122 ret = glfs_lstat (g->fs, f->file_name, &buf);
a8a93dee 123 if (ret < 0)
6e7d7dfb 124 return ret;
125
126 f->real_file_size = buf.st_size;
127 fio_file_set_size_known(f);
128
129 return 0;
130
131}
132
133static int fio_gf_open_file(struct thread_data *td, struct fio_file *f)
134{
6aa56500 135 struct gf_data *g = td->io_ops->data;
a8a93dee 136 int flags = 0;
137
138 dprint(FD_FILE, "fd open %s\n", f->file_name);
6e7d7dfb 139
140 if (td_write(td)) {
141 if (!read_only)
142 flags = O_RDWR;
143 } else if (td_read(td)) {
144 if (!read_only)
145 flags = O_RDWR;
146 else
147 flags = O_RDONLY;
148 }
a8a93dee 149 if (td->o.create_on_open)
150 flags |= O_CREAT;
6aa56500 151
a8a93dee 152 g->fd = glfs_open(g->fs, f->file_name, flags);
153 f->fd = -1;
154 return 0;
6e7d7dfb 155}
156
157static int fio_gf_close_file(struct thread_data *td, struct fio_file *f)
158{
159 int ret = 0;
160 struct gf_data *g = td->io_ops->data;
161
162 dprint(FD_FILE, "fd close %s\n", f->file_name);
163
a8a93dee 164 if (!g->fd && glfs_close(g->fd) < 0)
165 ret = errno;
6e7d7dfb 166
167 g->fd = NULL;
168 f->engine_data = 0;
169
170 return ret;
171}
172
173#define LAST_POS(f) ((f)->engine_data)
174static int fio_gf_prep(struct thread_data *td, struct io_u *io_u)
175{
176 struct fio_file *f = io_u->file;
177 struct gf_data *g = td->io_ops->data;
178
179 if (!ddir_rw(io_u->ddir))
180 return 0;
181
182 if (LAST_POS(f) != -1ULL && LAST_POS(f) == io_u->offset)
183 return 0;
184
185 if (glfs_lseek(g->fd, io_u->offset, SEEK_SET) < 0) {
186 td_verror(td, errno, "lseek");
187 return 1;
188 }
189
190 return 0;
191}
192
193static int fio_gf_queue(struct thread_data *td, struct io_u *io_u)
194{
195 struct gf_data *g = td->io_ops->data;
196 int ret = 0;
197
198 fio_ro_check(td, io_u);
199
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);
204 else {
205 log_err("unsupported operation.\n");
206 return -EINVAL;
207 }
208 if (io_u->file && ret >= 0 && ddir_rw(io_u->ddir))
209 LAST_POS(io_u->file) = io_u->offset + ret;
210
211 if (ret != (int) io_u->xfer_buflen) {
212 if (ret >= 0) {
213 io_u->resid = io_u->xfer_buflen - ret;
214 io_u->error = 0;
215 return FIO_Q_COMPLETED;
216 } else
217 io_u->error = errno;
218 }
219
a8a93dee 220 if (io_u->error)
6e7d7dfb 221 td_verror(td, io_u->error, "xfer");
222
223 return FIO_Q_COMPLETED;
224
225}
226
227static struct ioengine_ops ioengine = {
228 .name = "gfapi",
229 .version = FIO_IOOPS_VERSION,
a8a93dee 230 .setup = fio_gf_setup,
6e7d7dfb 231 .cleanup = fio_gf_cleanup,
232 .prep = fio_gf_prep,
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,
237 .options = options,
238 .option_struct_size = sizeof(struct gf_options),
a8a93dee 239 .flags = FIO_SYNCIO,
6e7d7dfb 240};
241
242static void fio_init fio_gf_register(void)
243{
244 register_ioengine(&ioengine);
245}
246
247static void fio_exit fio_gf_unregister(void)
248{
249 unregister_ioengine(&ioengine);
250}