fix man page; fix read work
[fio.git] / engines / glusterfs.c
1 /*
2  * glusterfs engine
3  *
4  * IO engine using Glusterfs's gfapi interface
5  *
6  */
7
8 #include <glusterfs/api/glfs.h>
9 #include <glusterfs/api/glfs-handles.h>
10 #include "../fio.h"
11
12 struct gf_options {
13     struct thread_data *td;
14     char *gf_vol;
15     char *gf_brick;
16 };
17
18 struct gf_data {
19     glfs_t *fs;
20     glfs_fd_t *fd;
21 };
22
23 static 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
47 static 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;
52     struct stat sb = {0, };
53
54         dprint(FD_IO, "fio setup\n");
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         }
71         glfs_set_logging (g->fs, "/tmp/fio_gfapi.log", 7);
72         /* default to tcp */
73         r = glfs_set_volfile_server(g->fs, "tcp", opt->gf_brick, 0);
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){
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");
87             goto cleanup;
88         }
89         dprint(FD_FILE, "fio setup %p\n", g->fs);
90         td->io_ops->data = g;
91 cleanup:
92         if (r){
93             if (g){
94             if (g->fs){
95                 glfs_fini(g->fs);
96             }
97             free(g);
98             }
99         }
100         return r;
101 }
102
103 static void fio_gf_cleanup(struct thread_data *td)
104 {
105 }
106
107 static 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
113     dprint(FD_FILE, "get file size %s\n", f->file_name);
114
115     if (!g || !g->fs)
116     {
117         return 0;
118     }
119     if (fio_file_size_known(f))
120         return 0;
121
122     ret = glfs_lstat (g->fs, f->file_name, &buf);
123     if (ret < 0){
124         log_err("glfs_lstat failed.\n");
125         return ret;
126     }
127
128     f->real_file_size = buf.st_size;
129     fio_file_set_size_known(f);
130
131     return 0;
132
133 }
134
135 static int fio_gf_open_file(struct thread_data *td, struct fio_file *f)
136 {
137
138     int flags = 0;
139     int ret = 0;
140     struct gf_data *g = td->io_ops->data;
141     struct stat sb = {0, };
142
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     }
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);    
155     if (!g->fd){
156         log_err("glfs_creat failed.\n");
157         ret = errno;
158     }
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
168     dprint(FD_FILE, "fio %p created %s\n", g->fs, f->file_name);
169     f->fd = -1;
170     f->shadow_fd = -1;    
171
172     return ret;
173 }
174
175 static 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
182         if (g->fd && glfs_close(g->fd) < 0)
183             ret = errno;
184
185         if (g->fs)
186             glfs_fini(g->fs);
187
188         g->fd = NULL;
189         free(g);
190         td->io_ops->data = NULL;
191         f->engine_data = 0;
192
193         return ret;
194 }
195
196 #define LAST_POS(f)     ((f)->engine_data)
197 static 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
202         dprint(FD_FILE, "fio prep\n");
203
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
218 static 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
223     dprint(FD_FILE, "fio queue len %lu\n", io_u->xfer_buflen);
224     fio_ro_check(td, io_u);
225
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);
230     else {          
231         log_err("unsupported operation.\n");
232         return -EINVAL;
233     }
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;
237
238     if (ret != (int) io_u->xfer_buflen) {
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;
245     }
246
247     if (io_u->error){
248         log_err("IO failed.\n");
249         td_verror(td, io_u->error, "xfer");
250     }
251
252     return FIO_Q_COMPLETED;
253
254 }
255
256 static struct ioengine_ops ioengine = {
257         .name               = "gfapi",
258         .version            = FIO_IOOPS_VERSION,
259         .init           = fio_gf_setup,
260         .cleanup        = fio_gf_cleanup,
261         .prep               = fio_gf_prep,
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,
266         .options        = options,
267         .option_struct_size = sizeof(struct gf_options),
268         .flags              = FIO_SYNCIO | FIO_DISKLESSIO,
269 };
270
271 static void fio_init fio_gf_register(void)
272 {
273     register_ioengine(&ioengine);
274 }
275
276 static void fio_exit fio_gf_unregister(void)
277 {
278     unregister_ioengine(&ioengine);
279 }