Pass O_DIRECT/O_SYNC to glfs_open if requested.
[fio.git] / engines / glusterfs.c
... / ...
CommitLineData
1/*
2 * glusterfs engine
3 *
4 * common Glusterfs's gfapi interface
5 *
6 */
7
8#include "gfapi.h"
9
10struct 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
34int 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;
80cleanup:
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
93void 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
109int 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
136int 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
270int 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}