blob: 2bd3e4e93c77621f2b2db94858fc14d9476fb494 [file] [log] [blame]
chenh0e55d6b2014-03-27 15:19:43 -04001/*
2 * glusterfs engine
3 *
4 * IO engine using Glusterfs's gfapi interface
5 *
6 */
7
8#include <glusterfs/api/glfs.h>
chenh0ac466f2014-03-28 15:30:54 -04009#include <glusterfs/api/glfs-handles.h>
chenh0e55d6b2014-03-27 15:19:43 -040010#include "../fio.h"
11
12struct gf_options {
13 struct thread_data *td;
14 char *gf_vol;
15 char *gf_brick;
16};
17
18struct gf_data {
19 glfs_t *fs;
20 glfs_fd_t *fd;
21};
chenh0ac466f2014-03-28 15:30:54 -040022
chenh0e55d6b2014-03-27 15:19:43 -040023static struct fio_option options[] = {
24 {
chenh321fc5a2014-03-31 11:32:29 -040025 .name = "volume",
26 .lname = "Glusterfs volume",
27 .type = FIO_OPT_STR_STORE,
28 .help = "Name of the Glusterfs volume",
29 .off1 = offsetof(struct gf_options, gf_vol),
30 .category = FIO_OPT_C_ENGINE,
31 .group = FIO_OPT_G_GFAPI,
chenh0e55d6b2014-03-27 15:19:43 -040032 },
33 {
chenh321fc5a2014-03-31 11:32:29 -040034 .name = "brick",
35 .lname = "Glusterfs brick name",
36 .type = FIO_OPT_STR_STORE,
37 .help = "Name of the Glusterfs brick to connect",
38 .off1 = offsetof(struct gf_options, gf_brick),
39 .category = FIO_OPT_C_ENGINE,
40 .group = FIO_OPT_G_GFAPI,
chenh0e55d6b2014-03-27 15:19:43 -040041 },
42 {
chenh321fc5a2014-03-31 11:32:29 -040043 .name = NULL,
chenh0e55d6b2014-03-27 15:19:43 -040044 },
45};
46
47static int fio_gf_setup(struct thread_data *td)
48{
49 int r = 0;
50 struct gf_data *g = NULL;
51 struct gf_options *opt = td->eo;
chenh321fc5a2014-03-31 11:32:29 -040052 struct stat sb = {0, };
chenh0ac466f2014-03-28 15:30:54 -040053
54 dprint(FD_IO, "fio setup\n");
chenh0e55d6b2014-03-27 15:19:43 -040055
56 if (td->io_ops->data)
57 return 0;
58
59 g = malloc(sizeof(struct gf_data));
60 if (!g){
61 log_err("malloc failed.\n");
62 return -ENOMEM;
63 }
64 g->fs = NULL; g->fd = NULL;
65
66 g->fs = glfs_new (opt->gf_vol);
67 if (!g->fs){
68 log_err("glfs_new failed.\n");
69 goto cleanup;
70 }
chenh0ac466f2014-03-28 15:30:54 -040071 glfs_set_logging (g->fs, "/tmp/fio_gfapi.log", 7);
chenh0e55d6b2014-03-27 15:19:43 -040072 /* default to tcp */
chenh0ac466f2014-03-28 15:30:54 -040073 r = glfs_set_volfile_server(g->fs, "tcp", opt->gf_brick, 0);
chenh0e55d6b2014-03-27 15:19:43 -040074 if (r){
75 log_err("glfs_set_volfile_server failed.\n");
76 goto cleanup;
77 }
78 r = glfs_init(g->fs);
79 if (r){
chenh0ac466f2014-03-28 15:30:54 -040080 log_err("glfs_init failed. Is glusterd running on brick?\n");
chenh0e55d6b2014-03-27 15:19:43 -040081 goto cleanup;
82 }
chenh0ac466f2014-03-28 15:30:54 -040083 sleep(2);
84 r = glfs_lstat (g->fs, ".", &sb);
85 if (r){
86 log_err("glfs_lstat failed.\n");
87 goto cleanup;
88 }
89 dprint(FD_FILE, "fio setup %p\n", g->fs);
chenh0e55d6b2014-03-27 15:19:43 -040090 td->io_ops->data = g;
91cleanup:
chenh0ac466f2014-03-28 15:30:54 -040092 if (r){
93 if (g){
chenh321fc5a2014-03-31 11:32:29 -040094 if (g->fs){
95 glfs_fini(g->fs);
96 }
97 free(g);
chenh0e55d6b2014-03-27 15:19:43 -040098 }
chenh0e55d6b2014-03-27 15:19:43 -040099 }
100 return r;
101}
102
103static void fio_gf_cleanup(struct thread_data *td)
104{
chenh0e55d6b2014-03-27 15:19:43 -0400105}
106
107static 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
chenh1368c1c2014-03-28 15:01:42 -0400113 dprint(FD_FILE, "get file size %s\n", f->file_name);
114
115 if (!g || !g->fs)
116 {
chenh321fc5a2014-03-31 11:32:29 -0400117 return 0;
chenh1368c1c2014-03-28 15:01:42 -0400118 }
chenh0e55d6b2014-03-27 15:19:43 -0400119 if (fio_file_size_known(f))
chenh321fc5a2014-03-31 11:32:29 -0400120 return 0;
chenh0e55d6b2014-03-27 15:19:43 -0400121
122 ret = glfs_lstat (g->fs, f->file_name, &buf);
chenh0ac466f2014-03-28 15:30:54 -0400123 if (ret < 0){
chenh321fc5a2014-03-31 11:32:29 -0400124 log_err("glfs_lstat failed.\n");
125 return ret;
chenh0ac466f2014-03-28 15:30:54 -0400126 }
chenh0e55d6b2014-03-27 15:19:43 -0400127
128 f->real_file_size = buf.st_size;
129 fio_file_set_size_known(f);
130
131 return 0;
132
133}
134
135static int fio_gf_open_file(struct thread_data *td, struct fio_file *f)
136{
chenh0ac466f2014-03-28 15:30:54 -0400137
chenh05c4b422014-03-28 15:07:51 -0400138 int flags = 0;
chenh0ac466f2014-03-28 15:30:54 -0400139 int ret = 0;
140 struct gf_data *g = td->io_ops->data;
chenh321fc5a2014-03-31 11:32:29 -0400141 struct stat sb = {0, };
chenh0e55d6b2014-03-27 15:19:43 -0400142
chenh0e55d6b2014-03-27 15:19:43 -0400143 if (td_write(td)) {
chenh321fc5a2014-03-31 11:32:29 -0400144 if (!read_only)
145 flags = O_RDWR;
chenh0e55d6b2014-03-27 15:19:43 -0400146 } else if (td_read(td)) {
chenh321fc5a2014-03-31 11:32:29 -0400147 if (!read_only)
148 flags = O_RDWR;
149 else
150 flags = O_RDONLY;
chenh0e55d6b2014-03-27 15:19:43 -0400151 }
chenh321fc5a2014-03-31 11:32:29 -0400152 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);
chenh0ac466f2014-03-28 15:30:54 -0400155 if (!g->fd){
chenh321fc5a2014-03-31 11:32:29 -0400156 log_err("glfs_creat failed.\n");
157 ret = errno;
chenh0ac466f2014-03-28 15:30:54 -0400158 }
chenh533362e2014-04-01 15:45:57 -0400159 /* 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 }
chenh321fc5a2014-03-31 11:32:29 -0400224 }
225 }
chenh0ac466f2014-03-28 15:30:54 -0400226 dprint(FD_FILE, "fio %p created %s\n", g->fs, f->file_name);
chenh05c4b422014-03-28 15:07:51 -0400227 f->fd = -1;
chenh0ac466f2014-03-28 15:30:54 -0400228 f->shadow_fd = -1;
229
230 return ret;
chenh0e55d6b2014-03-27 15:19:43 -0400231}
232
233static int fio_gf_close_file(struct thread_data *td, struct fio_file *f)
234{
235 int ret = 0;
236 struct gf_data *g = td->io_ops->data;
237
238 dprint(FD_FILE, "fd close %s\n", f->file_name);
239
chenh0ac466f2014-03-28 15:30:54 -0400240 if (g->fd && glfs_close(g->fd) < 0)
241 ret = errno;
242
243 if (g->fs)
244 glfs_fini(g->fs);
chenh0e55d6b2014-03-27 15:19:43 -0400245
246 g->fd = NULL;
chenh0ac466f2014-03-28 15:30:54 -0400247 free(g);
248 td->io_ops->data = NULL;
chenh0e55d6b2014-03-27 15:19:43 -0400249 f->engine_data = 0;
250
251 return ret;
252}
253
254#define LAST_POS(f) ((f)->engine_data)
255static int fio_gf_prep(struct thread_data *td, struct io_u *io_u)
256{
257 struct fio_file *f = io_u->file;
258 struct gf_data *g = td->io_ops->data;
259
chenh0ac466f2014-03-28 15:30:54 -0400260 dprint(FD_FILE, "fio prep\n");
261
chenh0e55d6b2014-03-27 15:19:43 -0400262 if (!ddir_rw(io_u->ddir))
263 return 0;
264
265 if (LAST_POS(f) != -1ULL && LAST_POS(f) == io_u->offset)
266 return 0;
267
268 if (glfs_lseek(g->fd, io_u->offset, SEEK_SET) < 0) {
269 td_verror(td, errno, "lseek");
270 return 1;
271 }
272
273 return 0;
274}
275
276static int fio_gf_queue(struct thread_data *td, struct io_u *io_u)
277{
278 struct gf_data *g = td->io_ops->data;
279 int ret = 0;
280
chenh0ac466f2014-03-28 15:30:54 -0400281 dprint(FD_FILE, "fio queue len %lu\n", io_u->xfer_buflen);
chenh0e55d6b2014-03-27 15:19:43 -0400282 fio_ro_check(td, io_u);
283
284 if (io_u->ddir == DDIR_READ)
chenh321fc5a2014-03-31 11:32:29 -0400285 ret = glfs_read(g->fd, io_u->xfer_buf, io_u->xfer_buflen, 0);
chenh0e55d6b2014-03-27 15:19:43 -0400286 else if (io_u->ddir == DDIR_WRITE)
chenh321fc5a2014-03-31 11:32:29 -0400287 ret = glfs_write(g->fd, io_u->xfer_buf, io_u->xfer_buflen, 0);
chenh0e55d6b2014-03-27 15:19:43 -0400288 else {
chenh321fc5a2014-03-31 11:32:29 -0400289 log_err("unsupported operation.\n");
290 return -EINVAL;
chenh0e55d6b2014-03-27 15:19:43 -0400291 }
chenh321fc5a2014-03-31 11:32:29 -0400292 dprint(FD_FILE, "fio len %lu ret %d\n", io_u->xfer_buflen, ret);
chenh0e55d6b2014-03-27 15:19:43 -0400293 if (io_u->file && ret >= 0 && ddir_rw(io_u->ddir))
chenh321fc5a2014-03-31 11:32:29 -0400294 LAST_POS(io_u->file) = io_u->offset + ret;
chenh0e55d6b2014-03-27 15:19:43 -0400295
296 if (ret != (int) io_u->xfer_buflen) {
chenh321fc5a2014-03-31 11:32:29 -0400297 if (ret >= 0) {
298 io_u->resid = io_u->xfer_buflen - ret;
299 io_u->error = 0;
300 return FIO_Q_COMPLETED;
301 } else
302 io_u->error = errno;
chenh0e55d6b2014-03-27 15:19:43 -0400303 }
304
chenh0ac466f2014-03-28 15:30:54 -0400305 if (io_u->error){
chenh321fc5a2014-03-31 11:32:29 -0400306 log_err("IO failed.\n");
307 td_verror(td, io_u->error, "xfer");
chenh0ac466f2014-03-28 15:30:54 -0400308 }
chenh0e55d6b2014-03-27 15:19:43 -0400309
310 return FIO_Q_COMPLETED;
311
312}
313
314static struct ioengine_ops ioengine = {
315 .name = "gfapi",
316 .version = FIO_IOOPS_VERSION,
chenh321fc5a2014-03-31 11:32:29 -0400317 .init = fio_gf_setup,
318 .cleanup = fio_gf_cleanup,
chenh0e55d6b2014-03-27 15:19:43 -0400319 .prep = fio_gf_prep,
320 .queue = fio_gf_queue,
321 .open_file = fio_gf_open_file,
322 .close_file = fio_gf_close_file,
chenh321fc5a2014-03-31 11:32:29 -0400323 .get_file_size = fio_gf_get_file_size,
324 .options = options,
chenh0e55d6b2014-03-27 15:19:43 -0400325 .option_struct_size = sizeof(struct gf_options),
chenh0ac466f2014-03-28 15:30:54 -0400326 .flags = FIO_SYNCIO | FIO_DISKLESSIO,
chenh0e55d6b2014-03-27 15:19:43 -0400327};
328
329static void fio_init fio_gf_register(void)
330{
331 register_ioengine(&ioengine);
332}
333
334static void fio_exit fio_gf_unregister(void)
335{
336 unregister_ioengine(&ioengine);
337}