fix get file size problem
[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 {
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;
7cb57176 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 }
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){
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 {
a8a93dee 117 return 0;
6aa56500 118 }
6e7d7dfb 119 if (fio_file_size_known(f))
120 return 0;
121
122 ret = glfs_lstat (g->fs, f->file_name, &buf);
7cb57176 123 if (ret < 0){
124 log_err("glfs_lstat failed.\n");
6e7d7dfb 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;
6e7d7dfb 141
7cb57176 142 dprint(FD_FILE, "fio open %s\n", f->file_name);
6e7d7dfb 143 if (td_write(td)) {
144 if (!read_only)
145 flags = O_RDWR;
146 } else if (td_read(td)) {
147 if (!read_only)
148 flags = O_RDWR;
149 else
150 flags = O_RDONLY;
151 }
7cb57176 152 g->fd = glfs_creat(g->fs, f->file_name, flags, 0644);
153 if (!g->fd){
154 log_err("glfs_creat failed.\n");
155 ret = errno;
156 }
157 dprint(FD_FILE, "fio %p created %s\n", g->fs, f->file_name);
a8a93dee 158 f->fd = -1;
7cb57176 159 f->shadow_fd = -1;
160
161 return ret;
6e7d7dfb 162}
163
164static int fio_gf_close_file(struct thread_data *td, struct fio_file *f)
165{
166 int ret = 0;
167 struct gf_data *g = td->io_ops->data;
168
169 dprint(FD_FILE, "fd close %s\n", f->file_name);
170
7cb57176 171 if (g->fd && glfs_close(g->fd) < 0)
172 ret = errno;
173
174 if (g->fs)
175 glfs_fini(g->fs);
6e7d7dfb 176
177 g->fd = NULL;
7cb57176 178 free(g);
179 td->io_ops->data = NULL;
6e7d7dfb 180 f->engine_data = 0;
181
182 return ret;
183}
184
185#define LAST_POS(f) ((f)->engine_data)
186static int fio_gf_prep(struct thread_data *td, struct io_u *io_u)
187{
188 struct fio_file *f = io_u->file;
189 struct gf_data *g = td->io_ops->data;
190
7cb57176 191 dprint(FD_FILE, "fio prep\n");
192
6e7d7dfb 193 if (!ddir_rw(io_u->ddir))
194 return 0;
195
196 if (LAST_POS(f) != -1ULL && LAST_POS(f) == io_u->offset)
197 return 0;
198
199 if (glfs_lseek(g->fd, io_u->offset, SEEK_SET) < 0) {
200 td_verror(td, errno, "lseek");
201 return 1;
202 }
203
204 return 0;
205}
206
207static int fio_gf_queue(struct thread_data *td, struct io_u *io_u)
208{
209 struct gf_data *g = td->io_ops->data;
210 int ret = 0;
211
7cb57176 212 dprint(FD_FILE, "fio queue len %lu\n", io_u->xfer_buflen);
6e7d7dfb 213 fio_ro_check(td, io_u);
214
215 if (io_u->ddir == DDIR_READ)
216 ret = glfs_read(g->fd, io_u->xfer_buf, io_u->xfer_buflen, 0);
217 else if (io_u->ddir == DDIR_WRITE)
218 ret = glfs_write(g->fd, io_u->xfer_buf, io_u->xfer_buflen, 0);
219 else {
220 log_err("unsupported operation.\n");
221 return -EINVAL;
222 }
7cb57176 223
6e7d7dfb 224 if (io_u->file && ret >= 0 && ddir_rw(io_u->ddir))
225 LAST_POS(io_u->file) = io_u->offset + ret;
226
227 if (ret != (int) io_u->xfer_buflen) {
228 if (ret >= 0) {
229 io_u->resid = io_u->xfer_buflen - ret;
230 io_u->error = 0;
231 return FIO_Q_COMPLETED;
232 } else
233 io_u->error = errno;
234 }
235
7cb57176 236 if (io_u->error){
237 log_err("IO failed.\n");
6e7d7dfb 238 td_verror(td, io_u->error, "xfer");
7cb57176 239 }
6e7d7dfb 240
241 return FIO_Q_COMPLETED;
242
243}
244
245static struct ioengine_ops ioengine = {
246 .name = "gfapi",
247 .version = FIO_IOOPS_VERSION,
7cb57176 248 .init = fio_gf_setup,
6e7d7dfb 249 .cleanup = fio_gf_cleanup,
250 .prep = fio_gf_prep,
251 .queue = fio_gf_queue,
252 .open_file = fio_gf_open_file,
253 .close_file = fio_gf_close_file,
254 .get_file_size = fio_gf_get_file_size,
255 .options = options,
256 .option_struct_size = sizeof(struct gf_options),
7cb57176 257 .flags = FIO_SYNCIO | FIO_DISKLESSIO,
6e7d7dfb 258};
259
260static void fio_init fio_gf_register(void)
261{
262 register_ioengine(&ioengine);
263}
264
265static void fio_exit fio_gf_unregister(void)
266{
267 unregister_ioengine(&ioengine);
268}