Add unlink hook to ioengine API, gluster ioengine
[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         return 0;
81 cleanup:
82         if (g->fs)
83                 glfs_fini(g->fs);
84         free(g);
85         td->io_ops->data = NULL;
86         return r;
87 }
88
89 void fio_gf_cleanup(struct thread_data *td)
90 {
91         struct gf_data *g = td->io_ops->data;
92
93         if (g) {
94                 if (g->aio_events)
95                         free(g->aio_events);
96                 if (g->fd)
97                         glfs_close(g->fd);
98                 if (g->fs)
99                         glfs_fini(g->fs);
100                 free(g);
101                 td->io_ops->data = NULL;
102         }
103 }
104
105 int fio_gf_get_file_size(struct thread_data *td, struct fio_file *f)
106 {
107         struct stat buf;
108         int ret;
109         struct gf_data *g = td->io_ops->data;
110
111         dprint(FD_FILE, "get file size %s\n", f->file_name);
112
113         if (!g || !g->fs) {
114                 return 0;
115         }
116         if (fio_file_size_known(f))
117                 return 0;
118
119         ret = glfs_lstat(g->fs, f->file_name, &buf);
120         if (ret < 0) {
121                 log_err("glfs_lstat failed.\n");
122                 return ret;
123         }
124
125         f->real_file_size = buf.st_size;
126         fio_file_set_size_known(f);
127
128         return 0;
129
130 }
131
132 int fio_gf_open_file(struct thread_data *td, struct fio_file *f)
133 {
134
135         int flags = 0;
136         int ret = 0;
137         struct gf_data *g = td->io_ops->data;
138         struct stat sb = { 0, };
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
150         if (td->o.odirect)
151                 flags |= OS_O_DIRECT;
152         if (td->o.sync_io)
153                 flags |= O_SYNC;
154
155         dprint(FD_FILE, "fio file %s open mode %s td rw %s\n", f->file_name,
156                flags & O_RDONLY ? "ro" : "rw", td_read(td) ? "read" : "write");
157         g->fd = glfs_creat(g->fs, f->file_name, flags, 0644);
158         if (!g->fd) {
159                 ret = errno;
160                 log_err("glfs_creat failed.\n");
161                 return ret;
162         }
163         /* file for read doesn't exist or shorter than required, create/extend it */
164         if (td_read(td)) {
165                 if (glfs_lstat(g->fs, f->file_name, &sb)
166                     || sb.st_size < f->real_file_size) {
167                         dprint(FD_FILE, "fio extend file %s from %ld to %ld\n",
168                                f->file_name, sb.st_size, f->real_file_size);
169                         ret = glfs_ftruncate(g->fd, f->real_file_size);
170                         if (ret) {
171                                 log_err("failed fio extend file %s to %ld\n",
172                                         f->file_name, f->real_file_size);
173                         } else {
174                                 unsigned long long left;
175                                 unsigned int bs;
176                                 char *b;
177                                 int r;
178
179                                 /* fill the file, copied from extend_file */
180                                 b = malloc(td->o.max_bs[DDIR_WRITE]);
181
182                                 left = f->real_file_size;
183                                 while (left && !td->terminate) {
184                                         bs = td->o.max_bs[DDIR_WRITE];
185                                         if (bs > left)
186                                                 bs = left;
187
188                                         fill_io_buffer(td, b, bs, bs);
189
190                                         r = glfs_write(g->fd, b, bs, 0);
191                                         dprint(FD_IO,
192                                                "fio write %d of %ld file %s\n",
193                                                r, f->real_file_size,
194                                                f->file_name);
195
196                                         if (r > 0) {
197                                                 left -= r;
198                                                 continue;
199                                         } else {
200                                                 if (r < 0) {
201                                                         int __e = errno;
202
203                                                         if (__e == ENOSPC) {
204                                                                 if (td->o.
205                                                                     fill_device)
206                                                                         break;
207                                                                 log_info
208                                                                     ("fio: ENOSPC on laying out "
209                                                                      "file, stopping\n");
210                                                                 break;
211                                                         }
212                                                         td_verror(td, errno,
213                                                                   "write");
214                                                 } else
215                                                         td_verror(td, EIO,
216                                                                   "write");
217
218                                                 break;
219                                         }
220                                 }
221
222                                 if (b)
223                                         free(b);
224                                 glfs_lseek(g->fd, 0, SEEK_SET);
225
226                                 if (td->terminate && td->o.unlink) {
227                                         dprint(FD_FILE, "terminate unlink %s\n",
228                                                f->file_name);
229                                         glfs_unlink(g->fs, f->file_name);
230                                 } else if (td->o.create_fsync) {
231                                         if (glfs_fsync(g->fd) < 0) {
232                                                 dprint(FD_FILE,
233                                                        "failed to sync, close %s\n",
234                                                        f->file_name);
235                                                 td_verror(td, errno, "fsync");
236                                                 glfs_close(g->fd);
237                                                 g->fd = NULL;
238                                                 return 1;
239                                         }
240                                 }
241                         }
242                 }
243         }
244 #if defined(GFAPI_USE_FADVISE)
245         {
246                 int r = 0;
247                 if (td_random(td)) {
248                         r = glfs_fadvise(g->fd, 0, f->real_file_size,
249                                          POSIX_FADV_RANDOM);
250                 } else {
251                         r = glfs_fadvise(g->fd, 0, f->real_file_size,
252                                          POSIX_FADV_SEQUENTIAL);
253                 }
254                 if (r) {
255                         dprint(FD_FILE, "fio %p fadvise %s status %d\n", g->fs,
256                                f->file_name, r);
257                 }
258         }
259 #endif
260         dprint(FD_FILE, "fio %p created %s\n", g->fs, f->file_name);
261         f->fd = -1;
262         f->shadow_fd = -1;
263         td->o.open_files ++;
264         return ret;
265 }
266
267 int fio_gf_close_file(struct thread_data *td, struct fio_file *f)
268 {
269         int ret = 0;
270         struct gf_data *g = td->io_ops->data;
271
272         dprint(FD_FILE, "fd close %s\n", f->file_name);
273
274         if (g) {
275                 if (g->fd && glfs_close(g->fd) < 0)
276                         ret = errno;
277                 g->fd = NULL;
278         }
279
280         return ret;
281 }
282
283 int fio_gf_unlink_file(struct thread_data *td, struct fio_file *f)
284 {
285         int ret = 0;
286         struct gf_data *g = td->io_ops->data;
287
288         dprint(FD_FILE, "fd unlink %s\n", f->file_name);
289
290         if (g) {
291                 if (g->fd && glfs_close(g->fd) < 0)
292                         ret = errno;
293
294                 glfs_unlink(g->fs, f->file_name);
295
296                 if (g->fs)
297                         glfs_fini(g->fs);
298
299                 g->fd = NULL;
300                 free(g);
301         }
302         td->io_ops->data = NULL;
303
304         return ret;
305 }