Merge branch 'master' of git://github.com/rootfs/fio
[fio.git] / engines / glusterfs.c
CommitLineData
6e7d7dfb 1/*
2 * glusterfs engine
3 *
cc47f094 4 * common Glusterfs's gfapi interface
6e7d7dfb 5 *
6 */
7
cc47f094 8#include "gfapi.h"
6e7d7dfb 9
cc47f094 10struct fio_option gfapi_options[] = {
6e7d7dfb 11 {
a7c386f4 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,
6e7d7dfb 19 },
20 {
a7c386f4 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,
6e7d7dfb 28 },
29 {
a7c386f4 30 .name = NULL,
6e7d7dfb 31 },
32};
33
cc47f094 34int fio_gf_setup(struct thread_data *td)
6e7d7dfb 35{
36 int r = 0;
37 struct gf_data *g = NULL;
38 struct gf_options *opt = td->eo;
a7c386f4 39 struct stat sb = {0, };
7cb57176 40
41 dprint(FD_IO, "fio setup\n");
6e7d7dfb 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 }
cc47f094 51 g->fs = NULL; g->fd = NULL; g->aio_events = NULL;
6e7d7dfb 52
53 g->fs = glfs_new (opt->gf_vol);
54 if (!g->fs){
55 log_err("glfs_new failed.\n");
56 goto cleanup;
57 }
7cb57176 58 glfs_set_logging (g->fs, "/tmp/fio_gfapi.log", 7);
6e7d7dfb 59 /* default to tcp */
7cb57176 60 r = glfs_set_volfile_server(g->fs, "tcp", opt->gf_brick, 0);
6e7d7dfb 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){
7cb57176 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");
6e7d7dfb 74 goto cleanup;
75 }
7cb57176 76 dprint(FD_FILE, "fio setup %p\n", g->fs);
6e7d7dfb 77 td->io_ops->data = g;
78cleanup:
7cb57176 79 if (r){
80 if (g){
a7c386f4 81 if (g->fs){
82 glfs_fini(g->fs);
83 }
84 free(g);
cc47f094 85 td->io_ops->data = NULL;
6e7d7dfb 86 }
6e7d7dfb 87 }
88 return r;
89}
90
cc47f094 91void fio_gf_cleanup(struct thread_data *td)
6e7d7dfb 92{
cc47f094 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 }
6e7d7dfb 105}
106
cc47f094 107int fio_gf_get_file_size(struct thread_data *td, struct fio_file *f)
6e7d7dfb 108{
109 struct stat buf;
110 int ret;
111 struct gf_data *g = td->io_ops->data;
112
6aa56500 113 dprint(FD_FILE, "get file size %s\n", f->file_name);
114
115 if (!g || !g->fs)
116 {
a7c386f4 117 return 0;
6aa56500 118 }
6e7d7dfb 119 if (fio_file_size_known(f))
a7c386f4 120 return 0;
6e7d7dfb 121
122 ret = glfs_lstat (g->fs, f->file_name, &buf);
7cb57176 123 if (ret < 0){
a7c386f4 124 log_err("glfs_lstat failed.\n");
125 return ret;
7cb57176 126 }
6e7d7dfb 127
128 f->real_file_size = buf.st_size;
129 fio_file_set_size_known(f);
130
131 return 0;
132
133}
134
cc47f094 135int fio_gf_open_file(struct thread_data *td, struct fio_file *f)
6e7d7dfb 136{
a8a93dee 137
7cb57176 138 int flags = 0;
139 int ret = 0;
140 struct gf_data *g = td->io_ops->data;
a7c386f4 141 struct stat sb = {0, };
6e7d7dfb 142
143 if (td_write(td)) {
a7c386f4 144 if (!read_only)
145 flags = O_RDWR;
6e7d7dfb 146 } else if (td_read(td)) {
a7c386f4 147 if (!read_only)
148 flags = O_RDWR;
149 else
150 flags = O_RDONLY;
6e7d7dfb 151 }
a7c386f4 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);
7cb57176 155 if (!g->fd){
a7c386f4 156 log_err("glfs_creat failed.\n");
157 ret = errno;
7cb57176 158 }
91b7a38d 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 }
a7c386f4 224 }
225 }
6fa14b99 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
7cb57176 239 dprint(FD_FILE, "fio %p created %s\n", g->fs, f->file_name);
a8a93dee 240 f->fd = -1;
7cb57176 241 f->shadow_fd = -1;
242
243 return ret;
6e7d7dfb 244}
245
cc47f094 246int fio_gf_close_file(struct thread_data *td, struct fio_file *f)
6e7d7dfb 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
cc47f094 253 if (g){
254 if (g->fd && glfs_close(g->fd) < 0)
255 ret = errno;
7cb57176 256
cc47f094 257 if (g->fs)
258 glfs_fini(g->fs);
6e7d7dfb 259
cc47f094 260 g->fd = NULL;
261 free(g);
262 }
7cb57176 263 td->io_ops->data = NULL;
6e7d7dfb 264 f->engine_data = 0;
265
266 return ret;
267}
268