Pass O_DIRECT/O_SYNC to glfs_open if requested.
[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;
52         g->fd = NULL;
53         g->aio_events = NULL;
54
55         g->fs = glfs_new(opt->gf_vol);
56         if (!g->fs) {
57                 log_err("glfs_new failed.\n");
58                 goto cleanup;
59         }
60         glfs_set_logging(g->fs, "/tmp/fio_gfapi.log", 7);
61         /* default to tcp */
62         r = glfs_set_volfile_server(g->fs, "tcp", opt->gf_brick, 0);
63         if (r) {
64                 log_err("glfs_set_volfile_server failed.\n");
65                 goto cleanup;
66         }
67         r = glfs_init(g->fs);
68         if (r) {
69                 log_err("glfs_init failed. Is glusterd running on brick?\n");
70                 goto cleanup;
71         }
72         sleep(2);
73         r = glfs_lstat(g->fs, ".", &sb);
74         if (r) {
75                 log_err("glfs_lstat failed.\n");
76                 goto cleanup;
77         }
78         dprint(FD_FILE, "fio setup %p\n", g->fs);
79         td->io_ops->data = g;
80 cleanup:
81         if (r) {
82                 if (g) {
83                         if (g->fs) {
84                                 glfs_fini(g->fs);
85                         }
86                         free(g);
87                         td->io_ops->data = NULL;
88                 }
89         }
90         return r;
91 }
92
93 void fio_gf_cleanup(struct thread_data *td)
94 {
95         struct gf_data *g = td->io_ops->data;
96
97         if (g) {
98                 if (g->aio_events)
99                         free(g->aio_events);
100                 if (g->fd)
101                         glfs_close(g->fd);
102                 if (g->fs)
103                         glfs_fini(g->fs);
104                 free(g);
105                 td->io_ops->data = NULL;
106         }
107 }
108
109 int fio_gf_get_file_size(struct thread_data *td, struct fio_file *f)
110 {
111         struct stat buf;
112         int ret;
113         struct gf_data *g = td->io_ops->data;
114
115         dprint(FD_FILE, "get file size %s\n", f->file_name);
116
117         if (!g || !g->fs) {
118                 return 0;
119         }
120         if (fio_file_size_known(f))
121                 return 0;
122
123         ret = glfs_lstat(g->fs, f->file_name, &buf);
124         if (ret < 0) {
125                 log_err("glfs_lstat failed.\n");
126                 return ret;
127         }
128
129         f->real_file_size = buf.st_size;
130         fio_file_set_size_known(f);
131
132         return 0;
133
134 }
135
136 int fio_gf_open_file(struct thread_data *td, struct fio_file *f)
137 {
138
139         int flags = 0;
140         int ret = 0;
141         struct gf_data *g = td->io_ops->data;
142         struct stat sb = { 0, };
143
144         if (td_write(td)) {
145                 if (!read_only)
146                         flags = O_RDWR;
147         } else if (td_read(td)) {
148                 if (!read_only)
149                         flags = O_RDWR;
150                 else
151                         flags = O_RDONLY;
152         }
153
154         if (td->o.odirect)
155                 flags |= OS_O_DIRECT;
156         if (td->o.sync_io)
157                 flags |= O_SYNC;
158
159         dprint(FD_FILE, "fio file %s open mode %s td rw %s\n", f->file_name,
160                flags & O_RDONLY ? "ro" : "rw", td_read(td) ? "read" : "write");
161         g->fd = glfs_creat(g->fs, f->file_name, flags, 0644);
162         if (!g->fd) {
163                 log_err("glfs_creat failed.\n");
164                 ret = errno;
165         }
166         /* file for read doesn't exist or shorter than required, create/extend it */
167         if (td_read(td)) {
168                 if (glfs_lstat(g->fs, f->file_name, &sb)
169                     || sb.st_size < f->real_file_size) {
170                         dprint(FD_FILE, "fio extend file %s from %ld to %ld\n",
171                                f->file_name, sb.st_size, f->real_file_size);
172                         ret = glfs_ftruncate(g->fd, f->real_file_size);
173                         if (ret) {
174                                 log_err("failed fio extend file %s to %ld\n",
175                                         f->file_name, f->real_file_size);
176                         } else {
177                                 unsigned long long left;
178                                 unsigned int bs;
179                                 char *b;
180                                 int r;
181
182                                 /* fill the file, copied from extend_file */
183                                 b = malloc(td->o.max_bs[DDIR_WRITE]);
184
185                                 left = f->real_file_size;
186                                 while (left && !td->terminate) {
187                                         bs = td->o.max_bs[DDIR_WRITE];
188                                         if (bs > left)
189                                                 bs = left;
190
191                                         fill_io_buffer(td, b, bs, bs);
192
193                                         r = glfs_write(g->fd, b, bs, 0);
194                                         dprint(FD_IO,
195                                                "fio write %d of %ld file %s\n",
196                                                r, f->real_file_size,
197                                                f->file_name);
198
199                                         if (r > 0) {
200                                                 left -= r;
201                                                 continue;
202                                         } else {
203                                                 if (r < 0) {
204                                                         int __e = errno;
205
206                                                         if (__e == ENOSPC) {
207                                                                 if (td->o.
208                                                                     fill_device)
209                                                                         break;
210                                                                 log_info
211                                                                     ("fio: ENOSPC on laying out "
212                                                                      "file, stopping\n");
213                                                                 break;
214                                                         }
215                                                         td_verror(td, errno,
216                                                                   "write");
217                                                 } else
218                                                         td_verror(td, EIO,
219                                                                   "write");
220
221                                                 break;
222                                         }
223                                 }
224
225                                 if (b)
226                                         free(b);
227                                 glfs_lseek(g->fd, 0, SEEK_SET);
228
229                                 if (td->terminate) {
230                                         dprint(FD_FILE, "terminate unlink %s\n",
231                                                f->file_name);
232                                         unlink(f->file_name);
233                                 } else if (td->o.create_fsync) {
234                                         if (glfs_fsync(g->fd) < 0) {
235                                                 dprint(FD_FILE,
236                                                        "failed to sync, close %s\n",
237                                                        f->file_name);
238                                                 td_verror(td, errno, "fsync");
239                                                 glfs_close(g->fd);
240                                                 g->fd = NULL;
241                                                 return 1;
242                                         }
243                                 }
244                         }
245                 }
246         }
247 #if defined(GFAPI_USE_FADVISE)
248         {
249                 int r = 0;
250                 if (td_random(td)) {
251                         r = glfs_fadvise(g->fd, 0, f->real_file_size,
252                                          POSIX_FADV_RANDOM);
253                 } else {
254                         r = glfs_fadvise(g->fd, 0, f->real_file_size,
255                                          POSIX_FADV_SEQUENTIAL);
256                 }
257                 if (r) {
258                         dprint(FD_FILE, "fio %p fadvise %s status %d\n", g->fs,
259                                f->file_name, r);
260                 }
261         }
262 #endif
263         dprint(FD_FILE, "fio %p created %s\n", g->fs, f->file_name);
264         f->fd = -1;
265         f->shadow_fd = -1;
266
267         return ret;
268 }
269
270 int fio_gf_close_file(struct thread_data *td, struct fio_file *f)
271 {
272         int ret = 0;
273         struct gf_data *g = td->io_ops->data;
274
275         dprint(FD_FILE, "fd close %s\n", f->file_name);
276
277         if (g) {
278                 if (g->fd && glfs_close(g->fd) < 0)
279                         ret = errno;
280
281                 if (g->fs)
282                         glfs_fini(g->fs);
283
284                 g->fd = NULL;
285                 free(g);
286         }
287         td->io_ops->data = NULL;
288         f->engine_data = 0;
289
290         return ret;
291 }