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; 80 return 0; 81cleanup: 82 if (g->fs) 83 glfs_fini(g->fs); 84 free(g); 85 td->io_ops->data = NULL; 86 return r; 87} 88 89void 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 105int 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 132int 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 267int 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 283int 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} 306