X-Git-Url: https://git.kernel.dk/?p=fio.git;a=blobdiff_plain;f=engines%2Fglusterfs.c;h=f2b84a2ab70b00013d13aafdbbaa73fc385071bc;hp=b233b207eb49dec4e5477b16d83de48d1a7f31b0;hb=04ba61dfa67784d4dfcc22a2b3de7ede28e22e40;hpb=b29c813fc632d486d8c9c7858c26ab31e0b89e8d diff --git a/engines/glusterfs.c b/engines/glusterfs.c index b233b207..f2b84a2a 100644 --- a/engines/glusterfs.c +++ b/engines/glusterfs.c @@ -6,6 +6,7 @@ */ #include "gfapi.h" +#include "../optgroup.h" struct fio_option gfapi_options[] = { { @@ -26,73 +27,190 @@ struct fio_option gfapi_options[] = { .category = FIO_OPT_C_ENGINE, .group = FIO_OPT_G_GFAPI, }, + { + .name = "single-instance", + .lname = "Single glusterfs instance", + .type = FIO_OPT_BOOL, + .help = "Only one glusterfs instance", + .off1 = offsetof(struct gf_options, gf_single_instance), + .category = FIO_OPT_C_ENGINE, + .group = FIO_OPT_G_GFAPI, + }, { .name = NULL, }, }; -int fio_gf_setup(struct thread_data *td) +struct glfs_info { + struct flist_head list; + char *volume; + char *brick; + glfs_t *fs; + int refcount; +}; + +static pthread_mutex_t glfs_lock = PTHREAD_MUTEX_INITIALIZER; +static FLIST_HEAD(glfs_list_head); + +static glfs_t *fio_gf_new_fs(char *volume, char *brick) { int r = 0; - struct gf_data *g = NULL; - struct gf_options *opt = td->eo; + glfs_t *fs; struct stat sb = { 0, }; - dprint(FD_IO, "fio setup\n"); - - if (td->io_ops->data) - return 0; - - g = malloc(sizeof(struct gf_data)); - if (!g) { - log_err("malloc failed.\n"); - return -ENOMEM; - } - g->fs = NULL; - g->fd = NULL; - g->aio_events = NULL; - - g->fs = glfs_new(opt->gf_vol); - if (!g->fs) { + fs = glfs_new(volume); + if (!fs) { log_err("glfs_new failed.\n"); - goto cleanup; + goto out; } - glfs_set_logging(g->fs, "/tmp/fio_gfapi.log", 7); + glfs_set_logging(fs, "/tmp/fio_gfapi.log", 7); /* default to tcp */ - r = glfs_set_volfile_server(g->fs, "tcp", opt->gf_brick, 0); + r = glfs_set_volfile_server(fs, "tcp", brick, 0); if (r) { log_err("glfs_set_volfile_server failed.\n"); - goto cleanup; + goto out; } - r = glfs_init(g->fs); + r = glfs_init(fs); if (r) { log_err("glfs_init failed. Is glusterd running on brick?\n"); - goto cleanup; + goto out; } sleep(2); - r = glfs_lstat(g->fs, ".", &sb); + r = glfs_lstat(fs, ".", &sb); if (r) { log_err("glfs_lstat failed.\n"); - goto cleanup; + goto out; } - dprint(FD_FILE, "fio setup %p\n", g->fs); - td->io_ops->data = g; -cleanup: + +out: if (r) { - if (g) { - if (g->fs) { - glfs_fini(g->fs); - } - free(g); - td->io_ops->data = NULL; + glfs_fini(fs); + fs = NULL; + } + return fs; +} + +static glfs_t *fio_gf_get_glfs(struct gf_options *opt, + char *volume, char *brick) +{ + struct glfs_info *glfs = NULL; + struct glfs_info *tmp; + struct flist_head *entry; + + if (!opt->gf_single_instance) + return fio_gf_new_fs(volume, brick); + + pthread_mutex_lock (&glfs_lock); + + flist_for_each(entry, &glfs_list_head) { + tmp = flist_entry(entry, struct glfs_info, list); + if (!strcmp(volume, tmp->volume) && + !strcmp(brick, tmp->brick)) { + glfs = tmp; + break; + } + } + + if (glfs) { + glfs->refcount++; + } else { + glfs = malloc(sizeof(*glfs)); + if (!glfs) + goto out; + INIT_FLIST_HEAD(&glfs->list); + glfs->refcount = 0; + glfs->volume = strdup(volume); + glfs->brick = strdup(brick); + glfs->fs = fio_gf_new_fs(volume, brick); + if (!glfs->fs) { + free(glfs); + glfs = NULL; + goto out; + } + + flist_add_tail(&glfs->list, &glfs_list_head); + glfs->refcount = 1; + } + +out: + pthread_mutex_unlock (&glfs_lock); + + if (glfs) + return glfs->fs; + return NULL; +} + +static void fio_gf_put_glfs(struct gf_options *opt, glfs_t *fs) +{ + struct glfs_info *glfs = NULL; + struct glfs_info *tmp; + struct flist_head *entry; + + if (!opt->gf_single_instance) { + glfs_fini(fs); + return; + } + + pthread_mutex_lock (&glfs_lock); + + flist_for_each(entry, &glfs_list_head) { + tmp = flist_entry(entry, struct glfs_info, list); + if (tmp->fs == fs) { + glfs = tmp; + break; } } - return r; + + if (!glfs) { + log_err("glfs not found to fini.\n"); + } else { + glfs->refcount--; + + if (glfs->refcount == 0) { + glfs_fini(glfs->fs); + free(glfs->volume); + free(glfs->brick); + flist_del(&glfs->list); + } + } + + pthread_mutex_unlock (&glfs_lock); +} + +int fio_gf_setup(struct thread_data *td) +{ + struct gf_data *g = NULL; + struct gf_options *opt = td->eo; + + dprint(FD_IO, "fio setup\n"); + + if (td->io_ops_data) + return 0; + + g = malloc(sizeof(struct gf_data)); + if (!g) { + log_err("malloc failed.\n"); + return -ENOMEM; + } + g->fd = NULL; + g->aio_events = NULL; + + g->fs = fio_gf_get_glfs(opt, opt->gf_vol, opt->gf_brick); + if (!g->fs) + goto cleanup; + + dprint(FD_FILE, "fio setup %p\n", g->fs); + td->io_ops_data = g; + return 0; +cleanup: + free(g); + td->io_ops_data = NULL; + return -EIO; } void fio_gf_cleanup(struct thread_data *td) { - struct gf_data *g = td->io_ops->data; + struct gf_data *g = td->io_ops_data; if (g) { if (g->aio_events) @@ -100,9 +218,9 @@ void fio_gf_cleanup(struct thread_data *td) if (g->fd) glfs_close(g->fd); if (g->fs) - glfs_fini(g->fs); + fio_gf_put_glfs(td->eo, g->fs); free(g); - td->io_ops->data = NULL; + td->io_ops_data = NULL; } } @@ -110,7 +228,7 @@ 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; + struct gf_data *g = td->io_ops_data; dprint(FD_FILE, "get file size %s\n", f->file_name); @@ -138,7 +256,7 @@ int fio_gf_open_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)) { @@ -150,22 +268,33 @@ int fio_gf_open_file(struct thread_data *td, struct fio_file *f) else flags = O_RDONLY; } + + if (td->o.odirect) + flags |= OS_O_DIRECT; + if (td->o.sync_io) + flags |= O_SYNC; + 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"); + flags & O_RDONLY ? "ro" : "rw", td_read(td) ? "read" : "write"); g->fd = glfs_creat(g->fs, f->file_name, flags, 0644); if (!g->fd) { - log_err("glfs_creat failed.\n"); ret = errno; + 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); + dprint(FD_FILE, "fio extend file %s from %jd to %" PRIu64 "\n", + f->file_name, (intmax_t) sb.st_size, f->real_file_size); +#if defined(CONFIG_GF_NEW_API) + ret = glfs_ftruncate(g->fd, f->real_file_size, NULL, NULL); +#else ret = glfs_ftruncate(g->fd, f->real_file_size); +#endif if (ret) { - log_err("failed fio extend file %s to %ld\n", + log_err("failed fio extend file %s to %" PRIu64 "\n", f->file_name, f->real_file_size); } else { unsigned long long left; @@ -186,7 +315,7 @@ int fio_gf_open_file(struct thread_data *td, struct fio_file *f) r = glfs_write(g->fd, b, bs, 0); dprint(FD_IO, - "fio write %d of %ld file %s\n", + "fio write %d of %" PRIu64 " file %s\n", r, f->real_file_size, f->file_name); @@ -220,12 +349,16 @@ int fio_gf_open_file(struct thread_data *td, struct fio_file *f) free(b); glfs_lseek(g->fd, 0, SEEK_SET); - if (td->terminate) { + if (td->terminate && td->o.unlink) { dprint(FD_FILE, "terminate unlink %s\n", f->file_name); - unlink(f->file_name); + glfs_unlink(g->fs, f->file_name); } else if (td->o.create_fsync) { +#if defined(CONFIG_GF_NEW_API) + if (glfs_fsync(g->fd, NULL, NULL) < 0) { +#else if (glfs_fsync(g->fd) < 0) { +#endif dprint(FD_FILE, "failed to sync, close %s\n", f->file_name); @@ -257,20 +390,38 @@ int fio_gf_open_file(struct thread_data *td, struct fio_file *f) 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; } int fio_gf_close_file(struct thread_data *td, struct fio_file *f) { int ret = 0; - struct gf_data *g = td->io_ops->data; + struct gf_data *g = td->io_ops_data; dprint(FD_FILE, "fd close %s\n", f->file_name); if (g) { if (g->fd && glfs_close(g->fd) < 0) ret = errno; + g->fd = NULL; + } + + return ret; +} + +int fio_gf_unlink_file(struct thread_data *td, struct fio_file *f) +{ + int ret = 0; + struct gf_data *g = td->io_ops_data; + + dprint(FD_FILE, "fd unlink %s\n", f->file_name); + + if (g) { + if (g->fd && glfs_close(g->fd) < 0) + ret = errno; + + glfs_unlink(g->fs, f->file_name); if (g->fs) glfs_fini(g->fs); @@ -278,8 +429,7 @@ int fio_gf_close_file(struct thread_data *td, struct fio_file *f) g->fd = NULL; free(g); } - td->io_ops->data = NULL; - f->engine_data = 0; + td->io_ops_data = NULL; return ret; }