X-Git-Url: https://git.kernel.dk/?p=fio.git;a=blobdiff_plain;f=engines%2Fglusterfs.c;h=2abc283fc048f1580271cb257e1831454e5a3f18;hp=6aed265a36ddc344f5172f40263fe3b6abde314f;hb=565e784df05c2529479eed8a38701a33b01894bd;hpb=334d5177e087b9864540691f3a34d4ceacc55416;ds=sidebyside diff --git a/engines/glusterfs.c b/engines/glusterfs.c index 6aed265a..2abc283f 100644 --- a/engines/glusterfs.c +++ b/engines/glusterfs.c @@ -1,248 +1,306 @@ /* * glusterfs engine * - * IO engine using Glusterfs's gfapi interface + * common Glusterfs's gfapi interface * */ -#include - -#include "../fio.h" - -struct gf_options { - struct thread_data *td; - char *gf_vol; - char *gf_brick; +#include "gfapi.h" +#include "../optgroup.h" + +struct fio_option gfapi_options[] = { + { + .name = "volume", + .lname = "Glusterfs volume", + .type = FIO_OPT_STR_STORE, + .help = "Name of the Glusterfs volume", + .off1 = offsetof(struct gf_options, gf_vol), + .category = FIO_OPT_C_ENGINE, + .group = FIO_OPT_G_GFAPI, + }, + { + .name = "brick", + .lname = "Glusterfs brick name", + .type = FIO_OPT_STR_STORE, + .help = "Name of the Glusterfs brick to connect", + .off1 = offsetof(struct gf_options, gf_brick), + .category = FIO_OPT_C_ENGINE, + .group = FIO_OPT_G_GFAPI, + }, + { + .name = NULL, + }, }; -struct gf_data { - glfs_t *fs; - glfs_fd_t *fd; -}; -static struct fio_option options[] = { - { - .name = "volume", - .lname = "Glusterfs volume", - .type = FIO_OPT_STR_STORE, - .help = "Name of the Glusterfs volume", - .off1 = offsetof(struct gf_options, gf_vol), - .category = FIO_OPT_C_ENGINE, - .group = FIO_OPT_G_GFAPI, - }, - { - .name = "brick", - .lname = "Glusterfs brick name", - .type = FIO_OPT_STR_STORE, - .help = "Name of the Glusterfs brick to connect", - .off1 = offsetof(struct gf_options, gf_brick), - .category = FIO_OPT_C_ENGINE, - .group = FIO_OPT_G_GFAPI, - }, - { - .name = NULL, - }, -}; - -static int fio_gf_setup(struct thread_data *td) +int fio_gf_setup(struct thread_data *td) { int r = 0; struct gf_data *g = NULL; struct gf_options *opt = td->eo; + struct stat sb = { 0, }; + + dprint(FD_IO, "fio setup\n"); - if (td->io_ops->data) - return 0; + if (td->io_ops_data) + return 0; g = malloc(sizeof(struct gf_data)); - if (!g){ - log_err("malloc failed.\n"); - return -ENOMEM; + if (!g) { + log_err("malloc failed.\n"); + return -ENOMEM; } - g->fs = NULL; g->fd = NULL; + g->fs = NULL; + g->fd = NULL; + g->aio_events = NULL; - g->fs = glfs_new (opt->gf_vol); - if (!g->fs){ - log_err("glfs_new failed.\n"); - goto cleanup; + g->fs = glfs_new(opt->gf_vol); + if (!g->fs) { + log_err("glfs_new failed.\n"); + goto cleanup; } - + glfs_set_logging(g->fs, "/tmp/fio_gfapi.log", 7); /* default to tcp */ - r = glfs_set_volfile_server(g->fs, "tcp", opt->gf_brick, 24007); - if (r){ - log_err("glfs_set_volfile_server failed.\n"); - goto cleanup; + r = glfs_set_volfile_server(g->fs, "tcp", opt->gf_brick, 0); + if (r) { + log_err("glfs_set_volfile_server failed.\n"); + goto cleanup; } r = glfs_init(g->fs); - if (r){ - log_err("glfs_init failed.\n"); - goto cleanup; + if (r) { + log_err("glfs_init failed. Is glusterd running on brick?\n"); + goto cleanup; + } + sleep(2); + r = glfs_lstat(g->fs, ".", &sb); + if (r) { + log_err("glfs_lstat failed.\n"); + goto cleanup; } - glfs_set_logging (g->fs, "/dev/stderr", 7); - - td->io_ops->data = g; + dprint(FD_FILE, "fio setup %p\n", g->fs); + td->io_ops_data = g; + return 0; cleanup: - if (g){ - if (g->fs){ + if (g->fs) glfs_fini(g->fs); - } - free(g); - } + free(g); + td->io_ops_data = NULL; return r; } -static void fio_gf_cleanup(struct thread_data *td) +void fio_gf_cleanup(struct thread_data *td) { - struct gf_data *g = td->io_ops->data; - - if (g){ - if (g->fs){ - glfs_fini(g->fs); - } - free(g); + struct gf_data *g = td->io_ops_data; + + if (g) { + if (g->aio_events) + free(g->aio_events); + if (g->fd) + glfs_close(g->fd); + if (g->fs) + glfs_fini(g->fs); + free(g); + td->io_ops_data = NULL; } } -static int fio_gf_get_file_size(struct thread_data *td, struct fio_file *f) +int fio_gf_get_file_size(struct thread_data *td, struct fio_file *f) { - struct stat buf; - int ret; - struct gf_data *g = td->io_ops->data; - - dprint(FD_FILE, "get file size %s\n", f->file_name); + struct stat buf; + int ret; + struct gf_data *g = td->io_ops_data; - if (!g || !g->fs) - { - return 0; - } + dprint(FD_FILE, "get file size %s\n", f->file_name); - if (fio_file_size_known(f)) - return 0; + if (!g || !g->fs) { + return 0; + } + if (fio_file_size_known(f)) + return 0; - ret = glfs_lstat (g->fs, f->file_name, &buf); - if (ret < 0) - return ret; + ret = glfs_lstat(g->fs, f->file_name, &buf); + if (ret < 0) { + log_err("glfs_lstat failed.\n"); + return ret; + } - f->real_file_size = buf.st_size; - fio_file_set_size_known(f); + f->real_file_size = buf.st_size; + fio_file_set_size_known(f); - return 0; + return 0; } -static int fio_gf_open_file(struct thread_data *td, struct fio_file *f) +int fio_gf_open_file(struct thread_data *td, struct fio_file *f) { - struct gf_data *g = td->io_ops->data; - int flags = 0; - - dprint(FD_FILE, "fd open %s\n", f->file_name); - - if (td_write(td)) { - if (!read_only) - flags = O_RDWR; - } else if (td_read(td)) { - if (!read_only) - flags = O_RDWR; - else - flags = O_RDONLY; - } - if (td->o.create_on_open) - flags |= O_CREAT; - - g->fd = glfs_open(g->fs, f->file_name, flags); - f->fd = -1; - return 0; -} -static int fio_gf_close_file(struct thread_data *td, struct fio_file *f) -{ + int flags = 0; int ret = 0; - struct gf_data *g = td->io_ops->data; + struct gf_data *g = td->io_ops_data; + struct stat sb = { 0, }; + + if (td_write(td)) { + if (!read_only) + flags = O_RDWR; + } else if (td_read(td)) { + if (!read_only) + flags = O_RDWR; + else + flags = O_RDONLY; + } - dprint(FD_FILE, "fd close %s\n", f->file_name); + if (td->o.odirect) + flags |= OS_O_DIRECT; + if (td->o.sync_io) + flags |= O_SYNC; - if (!g->fd && glfs_close(g->fd) < 0) + dprint(FD_FILE, "fio file %s open mode %s td rw %s\n", f->file_name, + flags & O_RDONLY ? "ro" : "rw", td_read(td) ? "read" : "write"); + g->fd = glfs_creat(g->fs, f->file_name, flags, 0644); + if (!g->fd) { ret = errno; - - g->fd = NULL; - f->engine_data = 0; - + log_err("glfs_creat failed.\n"); + return ret; + } + /* file for read doesn't exist or shorter than required, create/extend it */ + if (td_read(td)) { + if (glfs_lstat(g->fs, f->file_name, &sb) + || sb.st_size < f->real_file_size) { + dprint(FD_FILE, "fio extend file %s from %ld to %ld\n", + f->file_name, sb.st_size, f->real_file_size); + ret = glfs_ftruncate(g->fd, f->real_file_size); + if (ret) { + log_err("failed fio extend file %s to %ld\n", + f->file_name, f->real_file_size); + } else { + unsigned long long left; + unsigned int bs; + char *b; + int r; + + /* fill the file, copied from extend_file */ + b = malloc(td->o.max_bs[DDIR_WRITE]); + + left = f->real_file_size; + while (left && !td->terminate) { + bs = td->o.max_bs[DDIR_WRITE]; + if (bs > left) + bs = left; + + fill_io_buffer(td, b, bs, bs); + + r = glfs_write(g->fd, b, bs, 0); + dprint(FD_IO, + "fio write %d of %ld file %s\n", + r, f->real_file_size, + f->file_name); + + if (r > 0) { + left -= r; + continue; + } else { + if (r < 0) { + int __e = errno; + + if (__e == ENOSPC) { + if (td->o. + fill_device) + break; + log_info + ("fio: ENOSPC on laying out " + "file, stopping\n"); + break; + } + td_verror(td, errno, + "write"); + } else + td_verror(td, EIO, + "write"); + + break; + } + } + + if (b) + free(b); + glfs_lseek(g->fd, 0, SEEK_SET); + + if (td->terminate && td->o.unlink) { + dprint(FD_FILE, "terminate unlink %s\n", + f->file_name); + glfs_unlink(g->fs, f->file_name); + } else if (td->o.create_fsync) { + if (glfs_fsync(g->fd) < 0) { + dprint(FD_FILE, + "failed to sync, close %s\n", + f->file_name); + td_verror(td, errno, "fsync"); + glfs_close(g->fd); + g->fd = NULL; + return 1; + } + } + } + } + } +#if defined(GFAPI_USE_FADVISE) + { + int r = 0; + if (td_random(td)) { + r = glfs_fadvise(g->fd, 0, f->real_file_size, + POSIX_FADV_RANDOM); + } else { + r = glfs_fadvise(g->fd, 0, f->real_file_size, + POSIX_FADV_SEQUENTIAL); + } + if (r) { + dprint(FD_FILE, "fio %p fadvise %s status %d\n", g->fs, + f->file_name, r); + } + } +#endif + dprint(FD_FILE, "fio %p created %s\n", g->fs, f->file_name); + f->fd = -1; + f->shadow_fd = -1; + td->o.open_files ++; return ret; } -#define LAST_POS(f) ((f)->engine_data) -static int fio_gf_prep(struct thread_data *td, struct io_u *io_u) +int fio_gf_close_file(struct thread_data *td, struct fio_file *f) { - struct fio_file *f = io_u->file; - struct gf_data *g = td->io_ops->data; - - if (!ddir_rw(io_u->ddir)) - return 0; + int ret = 0; + struct gf_data *g = td->io_ops_data; - if (LAST_POS(f) != -1ULL && LAST_POS(f) == io_u->offset) - return 0; + dprint(FD_FILE, "fd close %s\n", f->file_name); - if (glfs_lseek(g->fd, io_u->offset, SEEK_SET) < 0) { - td_verror(td, errno, "lseek"); - return 1; + if (g) { + if (g->fd && glfs_close(g->fd) < 0) + ret = errno; + g->fd = NULL; } - return 0; + return ret; } -static int fio_gf_queue(struct thread_data *td, struct io_u *io_u) +int fio_gf_unlink_file(struct thread_data *td, struct fio_file *f) { - struct gf_data *g = td->io_ops->data; - int ret = 0; - - fio_ro_check(td, io_u); - - if (io_u->ddir == DDIR_READ) - ret = glfs_read(g->fd, io_u->xfer_buf, io_u->xfer_buflen, 0); - else if (io_u->ddir == DDIR_WRITE) - ret = glfs_write(g->fd, io_u->xfer_buf, io_u->xfer_buflen, 0); - else { - log_err("unsupported operation.\n"); - return -EINVAL; - } - if (io_u->file && ret >= 0 && ddir_rw(io_u->ddir)) - LAST_POS(io_u->file) = io_u->offset + ret; - - if (ret != (int) io_u->xfer_buflen) { - if (ret >= 0) { - io_u->resid = io_u->xfer_buflen - ret; - io_u->error = 0; - return FIO_Q_COMPLETED; - } else - io_u->error = errno; - } - - if (io_u->error) - td_verror(td, io_u->error, "xfer"); - - return FIO_Q_COMPLETED; + int ret = 0; + struct gf_data *g = td->io_ops_data; -} + dprint(FD_FILE, "fd unlink %s\n", f->file_name); -static struct ioengine_ops ioengine = { - .name = "gfapi", - .version = FIO_IOOPS_VERSION, - .setup = fio_gf_setup, - .cleanup = fio_gf_cleanup, - .prep = fio_gf_prep, - .queue = fio_gf_queue, - .open_file = fio_gf_open_file, - .close_file = fio_gf_close_file, - .get_file_size = fio_gf_get_file_size, - .options = options, - .option_struct_size = sizeof(struct gf_options), - .flags = FIO_SYNCIO, -}; + if (g) { + if (g->fd && glfs_close(g->fd) < 0) + ret = errno; -static void fio_init fio_gf_register(void) -{ - register_ioengine(&ioengine); -} + glfs_unlink(g->fs, f->file_name); -static void fio_exit fio_gf_unregister(void) -{ - unregister_ioengine(&ioengine); + if (g->fs) + glfs_fini(g->fs); + + g->fd = NULL; + free(g); + } + td->io_ops_data = NULL; + + return ret; }