respond to get file size
[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
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 static 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
46 static 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         }
67
68         /* default to tcp */
69         r = glfs_set_volfile_server(g->fs, "tcp", opt->gf_brick, 24007);
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){
76             log_err("glfs_init failed.\n");
77             goto cleanup;
78         }
79         glfs_set_logging (g->fs, "/dev/stderr", 7);
80         
81         td->io_ops->data = g;
82 cleanup:
83         if (g){
84             if (g->fs){
85                 glfs_fini(g->fs);
86             }
87             free(g);
88         }
89         return r;
90 }
91
92 static void fio_gf_cleanup(struct thread_data *td)
93 {
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         }
102 }
103
104 static 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
110 <<<<<<< HEAD
111     dprint(FD_FILE, "get file size %s\n", f->file_name);
112
113     if (!g || !g->fs)
114     {
115         return 0;
116     }
117 =======
118 >>>>>>> parent of 6aa5650... make glfs call per thread based
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         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
133 static int fio_gf_open_file(struct thread_data *td, struct fio_file *f)
134 {
135     struct gf_data *g = td->io_ops->data;
136     int flags = 0;
137
138     dprint(FD_FILE, "fd open %s\n", f->file_name);
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     }
149     if (td->o.create_on_open)
150         flags |= O_CREAT;
151
152     g->fd = glfs_open(g->fs, f->file_name, flags);
153     f->fd = -1;
154     return 0;
155 }
156
157 static 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
164         if (!g->fd && glfs_close(g->fd) < 0)
165                 ret = errno;
166
167         g->fd = NULL;
168         f->engine_data = 0;
169
170         return ret;
171 }
172
173 #define LAST_POS(f)     ((f)->engine_data)
174 static 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
193 static 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
220     if (io_u->error)
221         td_verror(td, io_u->error, "xfer");
222
223     return FIO_Q_COMPLETED;
224
225 }
226
227 static struct ioengine_ops ioengine = {
228         .name               = "gfapi",
229         .version            = FIO_IOOPS_VERSION,
230         .setup              = fio_gf_setup,
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),
239         .flags              = FIO_SYNCIO,
240 };
241
242 static void fio_init fio_gf_register(void)
243 {
244     register_ioengine(&ioengine);
245 }
246
247 static void fio_exit fio_gf_unregister(void)
248 {
249     unregister_ioengine(&ioengine);
250 }