1 /* 2 * glusterfs engine 3 * 4 * common Glusterfs's gfapi interface 5 * 6 */ 7 8 #include "gfapi.h" 9 #include "../optgroup.h" 10 11 struct fio_option gfapi_options[] = { 12 { 13 .name = "volume", 14 .lname = "Glusterfs volume", 15 .type = FIO_OPT_STR_STORE, 16 .help = "Name of the Glusterfs volume", 17 .off1 = offsetof(struct gf_options, gf_vol), 18 .category = FIO_OPT_C_ENGINE, 19 .group = FIO_OPT_G_GFAPI, 20 }, 21 { 22 .name = "brick", 23 .lname = "Glusterfs brick name", 24 .type = FIO_OPT_STR_STORE, 25 .help = "Name of the Glusterfs brick to connect", 26 .off1 = offsetof(struct gf_options, gf_brick), 27 .category = FIO_OPT_C_ENGINE, 28 .group = FIO_OPT_G_GFAPI, 29 }, 30 { 31 .name = NULL, 32 }, 33 }; 34 35 int fio_gf_setup(struct thread_data *td) 36 { 37 int r = 0; 38 struct gf_data *g = NULL; 39 struct gf_options *opt = td->eo; 40 struct stat sb = { 0, }; 41 42 dprint(FD_IO, "fio setup\n"); 43 44 if (td->io_ops_data) 45 return 0; 46 47 g = malloc(sizeof(struct gf_data)); 48 if (!g) { 49 log_err("malloc failed.\n"); 50 return -ENOMEM; 51 } 52 g->fs = NULL; 53 g->fd = NULL; 54 g->aio_events = NULL; 55 56 g->fs = glfs_new(opt->gf_vol); 57 if (!g->fs) { 58 log_err("glfs_new failed.\n"); 59 goto cleanup; 60 } 61 glfs_set_logging(g->fs, "/tmp/fio_gfapi.log", 7); 62 /* default to tcp */ 63 r = glfs_set_volfile_server(g->fs, "tcp", opt->gf_brick, 0); 64 if (r) { 65 log_err("glfs_set_volfile_server failed.\n"); 66 goto cleanup; 67 } 68 r = glfs_init(g->fs); 69 if (r) { 70 log_err("glfs_init failed. Is glusterd running on brick?\n"); 71 goto cleanup; 72 } 73 sleep(2); 74 r = glfs_lstat(g->fs, ".", &sb); 75 if (r) { 76 log_err("glfs_lstat failed.\n"); 77 goto cleanup; 78 } 79 dprint(FD_FILE, "fio setup %p\n", g->fs); 80 td->io_ops_data = g; 81 return 0; 82 cleanup: 83 if (g->fs) 84 glfs_fini(g->fs); 85 free(g); 86 td->io_ops_data = NULL; 87 return r; 88 } 89 90 void fio_gf_cleanup(struct thread_data *td) 91 { 92 struct gf_data *g = td->io_ops_data; 93 94 if (g) { 95 if (g->aio_events) 96 free(g->aio_events); 97 if (g->fd) 98 glfs_close(g->fd); 99 if (g->fs) 100 glfs_fini(g->fs); 101 free(g); 102 td->io_ops_data = NULL; 103 } 104 } 105 106 int fio_gf_get_file_size(struct thread_data *td, struct fio_file *f) 107 { 108 struct stat buf; 109 int ret; 110 struct gf_data *g = td->io_ops_data; 111 112 dprint(FD_FILE, "get file size %s\n", f->file_name); 113 114 if (!g || !g->fs) { 115 return 0; 116 } 117 if (fio_file_size_known(f)) 118 return 0; 119 120 ret = glfs_lstat(g->fs, f->file_name, &buf); 121 if (ret < 0) { 122 log_err("glfs_lstat failed.\n"); 123 return ret; 124 } 125 126 f->real_file_size = buf.st_size; 127 fio_file_set_size_known(f); 128 129 return 0; 130 131 } 132 133 int fio_gf_open_file(struct thread_data *td, struct fio_file *f) 134 { 135 136 int flags = 0; 137 int ret = 0; 138 struct gf_data *g = td->io_ops_data; 139 struct stat sb = { 0, }; 140 141 if (td_write(td)) { 142 if (!read_only) 143 flags = O_RDWR; 144 } else if (td_read(td)) { 145 if (!read_only) 146 flags = O_RDWR; 147 else 148 flags = O_RDONLY; 149 } 150 151 if (td->o.odirect) 152 flags |= OS_O_DIRECT; 153 if (td->o.sync_io) 154 flags |= O_SYNC; 155 156 dprint(FD_FILE, "fio file %s open mode %s td rw %s\n", f->file_name, 157 flags & O_RDONLY ? "ro" : "rw", td_read(td) ? "read" : "write"); 158 g->fd = glfs_creat(g->fs, f->file_name, flags, 0644); 159 if (!g->fd) { 160 ret = errno; 161 log_err("glfs_creat failed.\n"); 162 return ret; 163 } 164 /* file for read doesn't exist or shorter than required, create/extend it */ 165 if (td_read(td)) { 166 if (glfs_lstat(g->fs, f->file_name, &sb) 167 || sb.st_size < f->real_file_size) { 168 dprint(FD_FILE, "fio extend file %s from %ld to %ld\n", 169 f->file_name, sb.st_size, f->real_file_size); 170 ret = glfs_ftruncate(g->fd, f->real_file_size); 171 if (ret) { 172 log_err("failed fio extend file %s to %ld\n", 173 f->file_name, f->real_file_size); 174 } else { 175 unsigned long long left; 176 unsigned int bs; 177 char *b; 178 int r; 179 180 /* fill the file, copied from extend_file */ 181 b = malloc(td->o.max_bs[DDIR_WRITE]); 182 183 left = f->real_file_size; 184 while (left && !td->terminate) { 185 bs = td->o.max_bs[DDIR_WRITE]; 186 if (bs > left) 187 bs = left; 188 189 fill_io_buffer(td, b, bs, bs); 190 191 r = glfs_write(g->fd, b, bs, 0); 192 dprint(FD_IO, 193 "fio write %d of %ld file %s\n", 194 r, f->real_file_size, 195 f->file_name); 196 197 if (r > 0) { 198 left -= r; 199 continue; 200 } else { 201 if (r < 0) { 202 int __e = errno; 203 204 if (__e == ENOSPC) { 205 if (td->o. 206 fill_device) 207 break; 208 log_info 209 ("fio: ENOSPC on laying out " 210 "file, stopping\n"); 211 break; 212 } 213 td_verror(td, errno, 214 "write"); 215 } else 216 td_verror(td, EIO, 217 "write"); 218 219 break; 220 } 221 } 222 223 if (b) 224 free(b); 225 glfs_lseek(g->fd, 0, SEEK_SET); 226 227 if (td->terminate && td->o.unlink) { 228 dprint(FD_FILE, "terminate unlink %s\n", 229 f->file_name); 230 glfs_unlink(g->fs, f->file_name); 231 } else if (td->o.create_fsync) { 232 if (glfs_fsync(g->fd) < 0) { 233 dprint(FD_FILE, 234 "failed to sync, close %s\n", 235 f->file_name); 236 td_verror(td, errno, "fsync"); 237 glfs_close(g->fd); 238 g->fd = NULL; 239 return 1; 240 } 241 } 242 } 243 } 244 } 245 #if defined(GFAPI_USE_FADVISE) 246 { 247 int r = 0; 248 if (td_random(td)) { 249 r = glfs_fadvise(g->fd, 0, f->real_file_size, 250 POSIX_FADV_RANDOM); 251 } else { 252 r = glfs_fadvise(g->fd, 0, f->real_file_size, 253 POSIX_FADV_SEQUENTIAL); 254 } 255 if (r) { 256 dprint(FD_FILE, "fio %p fadvise %s status %d\n", g->fs, 257 f->file_name, r); 258 } 259 } 260 #endif 261 dprint(FD_FILE, "fio %p created %s\n", g->fs, f->file_name); 262 f->fd = -1; 263 f->shadow_fd = -1; 264 td->o.open_files ++; 265 return ret; 266 } 267 268 int fio_gf_close_file(struct thread_data *td, struct fio_file *f) 269 { 270 int ret = 0; 271 struct gf_data *g = td->io_ops_data; 272 273 dprint(FD_FILE, "fd close %s\n", f->file_name); 274 275 if (g) { 276 if (g->fd && glfs_close(g->fd) < 0) 277 ret = errno; 278 g->fd = NULL; 279 } 280 281 return ret; 282 } 283 284 int fio_gf_unlink_file(struct thread_data *td, struct fio_file *f) 285 { 286 int ret = 0; 287 struct gf_data *g = td->io_ops_data; 288 289 dprint(FD_FILE, "fd unlink %s\n", f->file_name); 290 291 if (g) { 292 if (g->fd && glfs_close(g->fd) < 0) 293 ret = errno; 294 295 glfs_unlink(g->fs, f->file_name); 296 297 if (g->fs) 298 glfs_fini(g->fs); 299 300 g->fd = NULL; 301 free(g); 302 } 303 td->io_ops_data = NULL; 304 305 return ret; 306 } 307