Merge branch 'master' of git://github.com/rootfs/fio
[fio.git] / engines / glusterfs.c
1 /*
2  * glusterfs engine
3  *
4  * common Glusterfs's gfapi interface
5  *
6  */
7
8 #include "gfapi.h"
9
10 struct fio_option gfapi_options[] = {
11     {
12         .name     = "volume",
13         .lname    = "Glusterfs volume",
14         .type     = FIO_OPT_STR_STORE,
15         .help     = "Name of the Glusterfs volume",
16         .off1     = offsetof(struct gf_options, gf_vol),
17         .category = FIO_OPT_C_ENGINE,
18         .group    = FIO_OPT_G_GFAPI,
19     },
20     {
21         .name     = "brick",
22         .lname    = "Glusterfs brick name",
23         .type     = FIO_OPT_STR_STORE,
24         .help     = "Name of the Glusterfs brick to connect",
25         .off1     = offsetof(struct gf_options, gf_brick),
26         .category = FIO_OPT_C_ENGINE,
27         .group    = FIO_OPT_G_GFAPI,
28     },
29     {
30         .name = NULL,
31     },
32 };
33
34 int fio_gf_setup(struct thread_data *td)
35 {
36         int r = 0;
37         struct gf_data *g = NULL;
38         struct gf_options *opt = td->eo;
39     struct stat sb = {0, };
40
41         dprint(FD_IO, "fio setup\n");
42
43         if (td->io_ops->data)
44             return 0;
45
46         g = malloc(sizeof(struct gf_data));
47         if (!g){
48             log_err("malloc failed.\n");
49             return -ENOMEM;
50         }
51         g->fs = NULL; g->fd = NULL; g->aio_events = NULL;
52
53         g->fs = glfs_new (opt->gf_vol);
54         if (!g->fs){
55             log_err("glfs_new failed.\n");
56             goto cleanup;
57         }
58         glfs_set_logging (g->fs, "/tmp/fio_gfapi.log", 7);
59         /* default to tcp */
60         r = glfs_set_volfile_server(g->fs, "tcp", opt->gf_brick, 0);
61         if (r){
62             log_err("glfs_set_volfile_server failed.\n");
63             goto cleanup;
64         }
65         r = glfs_init(g->fs);
66         if (r){
67             log_err("glfs_init failed. Is glusterd running on brick?\n");
68             goto cleanup;
69         }
70         sleep(2);
71         r = glfs_lstat (g->fs, ".", &sb);
72         if (r){
73             log_err("glfs_lstat failed.\n");
74             goto cleanup;
75         }
76         dprint(FD_FILE, "fio setup %p\n", g->fs);
77         td->io_ops->data = g;
78 cleanup:
79         if (r){
80             if (g){
81             if (g->fs){
82                 glfs_fini(g->fs);
83             }
84             free(g);
85             td->io_ops->data = NULL;
86             }
87         }
88         return r;
89 }
90
91 void fio_gf_cleanup(struct thread_data *td)
92 {
93         struct gf_data *g = td->io_ops->data;
94
95         if (g) {
96         if (g->aio_events)
97             free(g->aio_events);
98         if (g->fd)
99             glfs_close(g->fd);
100         if (g->fs)
101             glfs_fini(g->fs);
102         free(g);
103         td->io_ops->data = NULL;
104         }
105 }
106
107 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 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 or shorter than required, create/extend it */
160     if (td_read(td)){
161         if (glfs_lstat (g->fs, f->file_name, &sb) || sb.st_size < f->real_file_size){
162             dprint(FD_FILE, "fio extend file %s from %ld to %ld\n", f->file_name, sb.st_size, f->real_file_size);
163             ret = glfs_ftruncate (g->fd, f->real_file_size);
164             if (ret){
165                 log_err("failed fio extend file %s to %ld\n", f->file_name, f->real_file_size);
166             }else{
167                 unsigned long long left;
168                 unsigned int bs;
169                 char *b;
170                 int r;
171
172                 /* fill the file, copied from extend_file */
173                 b = malloc(td->o.max_bs[DDIR_WRITE]);
174
175                 left = f->real_file_size;
176                 while (left && !td->terminate) {
177                     bs = td->o.max_bs[DDIR_WRITE];
178                     if (bs > left)
179                         bs = left;
180
181                     fill_io_buffer(td, b, bs, bs);
182
183                     r = glfs_write(g->fd, b, bs, 0);
184                     dprint(FD_IO, "fio write %d of %ld file %s\n", r, f->real_file_size, f->file_name);
185
186                     if (r > 0) {
187                         left -= r;
188                         continue;
189                     } else {
190                         if (r < 0) {
191                             int __e = errno;
192
193                             if (__e == ENOSPC) {
194                                 if (td->o.fill_device)
195                                     break;
196                                 log_info("fio: ENOSPC on laying out "
197                                          "file, stopping\n");
198                                 break;
199                             }
200                             td_verror(td, errno, "write");
201                         } else
202                             td_verror(td, EIO, "write");
203
204                         break;
205                     }
206                 }
207
208                 if (b) free(b);
209                 glfs_lseek(g->fd, 0, SEEK_SET);
210
211                 if (td->terminate) {
212                     dprint(FD_FILE, "terminate unlink %s\n", f->file_name);
213                     unlink(f->file_name);
214                 } else if (td->o.create_fsync) {
215                     if (glfs_fsync(g->fd) < 0) {
216                         dprint(FD_FILE, "failed to sync, close %s\n", f->file_name);
217                         td_verror(td, errno, "fsync");
218                         glfs_close(g->fd);
219                         g->fd = NULL;
220                         return 1;
221                     }
222                 }
223             }
224         }
225     }
226 #if defined(GFAPI_USE_FADVISE)
227     {
228         int r = 0; 
229         if (td_random(td)){
230             r = glfs_fadvise(g->fd, 0, f->real_file_size, POSIX_FADV_RANDOM);
231         }else{
232             r = glfs_fadvise(g->fd, 0, f->real_file_size, POSIX_FADV_SEQUENTIAL);
233         }
234         if (r){
235             dprint(FD_FILE, "fio %p fadvise %s status %d\n", g->fs, f->file_name, r);
236         }
237     }
238 #endif
239     dprint(FD_FILE, "fio %p created %s\n", g->fs, f->file_name);
240     f->fd = -1;
241     f->shadow_fd = -1;    
242
243     return ret;
244 }
245
246 int fio_gf_close_file(struct thread_data *td, struct fio_file *f)
247 {
248         int ret = 0;
249         struct gf_data *g = td->io_ops->data;
250
251         dprint(FD_FILE, "fd close %s\n", f->file_name);
252
253     if (g){
254         if (g->fd && glfs_close(g->fd) < 0)
255             ret = errno;
256
257         if (g->fs)
258             glfs_fini(g->fs);
259
260         g->fd = NULL;
261         free(g);
262     }
263         td->io_ops->data = NULL;
264         f->engine_data = 0;
265
266         return ret;
267 }
268