From 5f350952eff89948bfbf1eb6ac4d3d08a9109581 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 7 Nov 2006 15:20:59 +0100 Subject: [PATCH] [PATCH] Link in known io engines No real point in using dlopen() to find engines we know about. We still support loading external modules, just give the name as the full path to such a file. Signed-off-by: Jens Axboe --- Makefile | 12 +++-- engines/Makefile | 25 ----------- engines/fio-engine-cpu.c | 16 +++++-- engines/fio-engine-libaio.c | 19 ++++++-- engines/fio-engine-mmap.c | 17 +++++-- engines/fio-engine-posixaio.c | 19 ++++++-- engines/fio-engine-sg.c | 19 ++++++-- engines/fio-engine-splice.c | 19 ++++++-- engines/fio-engine-sync.c | 17 +++++-- fio.h | 5 +++ init.c | 1 + ioengines.c | 85 ++++++++++++++++++++++++++++------- list.h | 3 ++ 13 files changed, 188 insertions(+), 69 deletions(-) delete mode 100644 engines/Makefile diff --git a/Makefile b/Makefile index ad9aa3bd..1ebad6af 100644 --- a/Makefile +++ b/Makefile @@ -5,6 +5,14 @@ SCRIPTS = fio_generate_plots OBJS = fio.o ioengines.o init.o stat.o log.o time.o md5.o crc32.o \ filesetup.o eta.o verify.o memory.o io_u.o parse.o +OBJS += engines/fio-engine-cpu.o +OBJS += engines/fio-engine-libaio.o +OBJS += engines/fio-engine-mmap.o +OBJS += engines/fio-engine-posixaio.o +OBJS += engines/fio-engine-sg.o +OBJS += engines/fio-engine-splice.o +OBJS += engines/fio-engine-sync.o + INSTALL = install prefix = /usr/local bindir = $(prefix)/bin @@ -15,10 +23,9 @@ FIO_INST_DIR = $(subst ','\'',$(prefix)) CFLAGS += '-D_INST_PREFIX="$(FIO_INST_DIR)"' all: depend $(PROGS) $(SCRIPTS) - @$(MAKE) -C engines fio: $(OBJS) - $(CC) $(CFLAGS) -o $@ $(filter %.o,$^) -lpthread -lm -ldl + $(CC) $(CFLAGS) -o $@ $(filter %.o,$^) -lpthread -lm -ldl -laio -lrt clean: -rm -f *.o .depend cscope.out $(PROGS) engines/*.o @@ -33,7 +40,6 @@ install: $(PROGS) $(SCRIPTS) $(INSTALL) -m755 -d $(DESTDIR)$(bindir) $(INSTALL) $(PROGS) $(SCRIPTS) $(DESTDIR)$(bindir) $(INSTALL) -m755 -d $(DESTDIR) $(libdir) - $(INSTALL) engines/*.o $(libdir) ifneq ($(wildcard .depend),) include .depend diff --git a/engines/Makefile b/engines/Makefile deleted file mode 100644 index 963a93ee..00000000 --- a/engines/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -CC = gcc -CFLAGS = -W -Wall -O2 -g -shared -rdynamic -fPIC -ALL_CFLAGS = $(CFLAGS) -I.. -D_GNU_SOURCE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -OBJS = fio-engine-sync.o fio-engine-splice.o fio-engine-mmap.o fio-engine-libaio.o fio-engine-posixaio.o fio-engine-sg.o fio-engine-cpu.o - -all: depend $(OBJS) - -depend: - @$(CC) -MM $(ALL_CFLAGS) *.c 1> .depend - -clean: - -rm -f *.o $(OBJS) .depend - -%.o: %.c - $(CC) $(ALL_CFLAGS) -o $*.o $< - -fio-engine-libaio.o: fio-engine-libaio.c - $(CC) $(ALL_CFLAGS) -laio -o $*.o $< - -fio-engine-posixaio.o: fio-engine-posixaio.c - $(CC) $(ALL_CFLAGS) -lrt -o $*.o $< - -ifneq ($(wildcard .depend),) -include .depend -endif diff --git a/engines/fio-engine-cpu.c b/engines/fio-engine-cpu.c index 4ba12c64..f65f91d9 100644 --- a/engines/fio-engine-cpu.c +++ b/engines/fio-engine-cpu.c @@ -1,5 +1,5 @@ -#include "fio.h" -#include "os.h" +#include "../fio.h" +#include "../os.h" static int fio_cpuio_setup(struct thread_data fio_unused *td) { @@ -19,10 +19,20 @@ static int fio_cpuio_init(struct thread_data *td) return 0; } -struct ioengine_ops ioengine = { +static struct ioengine_ops ioengine = { .name = "cpuio", .version = FIO_IOOPS_VERSION, .init = fio_cpuio_init, .setup = fio_cpuio_setup, .flags = FIO_CPUIO, }; + +static void fio_init fio_cpuio_register(void) +{ + register_ioengine(&ioengine); +} + +static void fio_exit fio_cpuio_unregister(void) +{ + unregister_ioengine(&ioengine); +} diff --git a/engines/fio-engine-libaio.c b/engines/fio-engine-libaio.c index 12ddc98b..45e69e90 100644 --- a/engines/fio-engine-libaio.c +++ b/engines/fio-engine-libaio.c @@ -7,8 +7,9 @@ #include #include #include -#include "fio.h" -#include "os.h" + +#include "../fio.h" +#include "../os.h" #ifdef FIO_HAVE_LIBAIO @@ -130,7 +131,7 @@ static int fio_libaio_init(struct thread_data *td) return 0; } -struct ioengine_ops ioengine = { +static struct ioengine_ops ioengine = { .name = "libaio", .version = FIO_IOOPS_VERSION, .init = fio_libaio_init, @@ -155,10 +156,20 @@ static int fio_libaio_init(struct thread_data fio_unused *td) return 1; } -struct ioengine_ops ioengine = { +static struct ioengine_ops ioengine = { .name = "libaio", .version = FIO_IOOPS_VERSION, .init = fio_libaio_init, }; #endif + +static void fio_init fio_libaio_register(void) +{ + register_ioengine(&ioengine); +} + +static void fio_exit fio_libaio_unregister(void) +{ + unregister_ioengine(&ioengine); +} diff --git a/engines/fio-engine-mmap.c b/engines/fio-engine-mmap.c index 483a704e..20dcfd22 100644 --- a/engines/fio-engine-mmap.c +++ b/engines/fio-engine-mmap.c @@ -8,8 +8,9 @@ #include #include #include -#include "fio.h" -#include "os.h" + +#include "../fio.h" +#include "../os.h" struct mmapio_data { struct io_u *last_io_u; @@ -88,7 +89,7 @@ static int fio_mmapio_init(struct thread_data *td) return 0; } -struct ioengine_ops ioengine = { +static struct ioengine_ops ioengine = { .name = "mmap", .version = FIO_IOOPS_VERSION, .init = fio_mmapio_init, @@ -98,3 +99,13 @@ struct ioengine_ops ioengine = { .cleanup = fio_mmapio_cleanup, .flags = FIO_SYNCIO | FIO_MMAPIO, }; + +static void fio_init fio_mmapio_register(void) +{ + register_ioengine(&ioengine); +} + +static void fio_exit fio_mmapio_unregister(void) +{ + unregister_ioengine(&ioengine); +} diff --git a/engines/fio-engine-posixaio.c b/engines/fio-engine-posixaio.c index 894a410a..ef4d78eb 100644 --- a/engines/fio-engine-posixaio.c +++ b/engines/fio-engine-posixaio.c @@ -7,8 +7,9 @@ #include #include #include -#include "fio.h" -#include "os.h" + +#include "../fio.h" +#include "../os.h" #ifdef FIO_HAVE_POSIXAIO @@ -179,7 +180,7 @@ static int fio_posixaio_init(struct thread_data *td) return 0; } -struct ioengine_ops ioengine = { +static struct ioengine_ops ioengine = { .name = "posixaio", .version = FIO_IOOPS_VERSION, .init = fio_posixaio_init, @@ -204,10 +205,20 @@ static int fio_posixaio_init(struct thread_data fio_unused *td) return 1; } -struct ioengine_ops ioengine = { +static struct ioengine_ops ioengine = { .name = "posixaio", .version = FIO_IOOPS_VERSION, .init = fio_posixaio_init, }; #endif + +static void fio_init fio_posixaio_register(void) +{ + register_ioengine(&ioengine); +} + +static void fio_exit fio_posixaio_unregister(void) +{ + unregister_ioengine(&ioengine); +} diff --git a/engines/fio-engine-sg.c b/engines/fio-engine-sg.c index 2762e0ba..9c5037f5 100644 --- a/engines/fio-engine-sg.c +++ b/engines/fio-engine-sg.c @@ -8,8 +8,9 @@ #include #include #include -#include "fio.h" -#include "os.h" + +#include "../fio.h" +#include "../os.h" #ifdef FIO_HAVE_SGIO @@ -313,7 +314,7 @@ err: return 1; } -struct ioengine_ops ioengine = { +static struct ioengine_ops ioengine = { .name = "sg", .version = FIO_IOOPS_VERSION, .init = fio_sgio_init, @@ -338,10 +339,20 @@ static int fio_sgio_init(struct thread_data fio_unused *td) return 1; } -struct ioengine_ops ioengine = { +static struct ioengine_ops ioengine = { .name = "sgio", .version = FIO_IOOPS_VERSION, .init = fio_sgio_init, }; #endif + +static void fio_init fio_sgio_register(void) +{ + register_ioengine(&ioengine); +} + +static void fio_exit fio_sgio_unregister(void) +{ + unregister_ioengine(&ioengine); +} diff --git a/engines/fio-engine-splice.c b/engines/fio-engine-splice.c index 3b02fbfd..fa4a6ee1 100644 --- a/engines/fio-engine-splice.c +++ b/engines/fio-engine-splice.c @@ -8,8 +8,9 @@ #include #include #include -#include "fio.h" -#include "os.h" + +#include "../fio.h" +#include "../os.h" #ifdef FIO_HAVE_SPLICE @@ -181,7 +182,7 @@ static int fio_spliceio_init(struct thread_data *td) return 0; } -struct ioengine_ops ioengine = { +static struct ioengine_ops ioengine = { .name = "splice", .version = FIO_IOOPS_VERSION, .init = fio_spliceio_init, @@ -205,10 +206,20 @@ static int fio_spliceio_init(struct thread_data fio_unused *td) return 1; } -struct ioengine_ops ioengine = { +static struct ioengine_ops ioengine = { .name = "splice", .version = FIO_IOOPS_VERSION, .init = fio_spliceio_init, }; #endif + +static void fio_init fio_spliceio_register(void) +{ + register_ioengine(&ioengine); +} + +static void fio_exit fio_spliceio_unregister(void) +{ + unregister_ioengine(&ioengine); +} diff --git a/engines/fio-engine-sync.c b/engines/fio-engine-sync.c index 43f42ca2..5919830e 100644 --- a/engines/fio-engine-sync.c +++ b/engines/fio-engine-sync.c @@ -7,8 +7,9 @@ #include #include #include -#include "fio.h" -#include "os.h" + +#include "../fio.h" +#include "../os.h" struct syncio_data { struct io_u *last_io_u; @@ -97,7 +98,7 @@ static int fio_syncio_init(struct thread_data *td) return 0; } -struct ioengine_ops ioengine = { +static struct ioengine_ops ioengine = { .name = "sync", .version = FIO_IOOPS_VERSION, .init = fio_syncio_init, @@ -108,3 +109,13 @@ struct ioengine_ops ioengine = { .cleanup = fio_syncio_cleanup, .flags = FIO_SYNCIO, }; + +static void fio_init fio_syncio_register(void) +{ + register_ioengine(&ioengine); +} + +static void fio_exit fio_syncio_unregister(void) +{ + unregister_ioengine(&ioengine); +} diff --git a/fio.h b/fio.h index f859608c..9f5201b6 100644 --- a/fio.h +++ b/fio.h @@ -565,6 +565,7 @@ static inline void fio_sem_up(volatile int *sem) } while (0) struct ioengine_ops { + struct list_head list; char name[16]; int version; int flags; @@ -583,12 +584,16 @@ struct ioengine_ops { #define FIO_IOOPS_VERSION 3 extern struct ioengine_ops *load_ioengine(struct thread_data *, const char *); +extern int register_ioengine(struct ioengine_ops *); +extern void unregister_ioengine(struct ioengine_ops *); extern void close_ioengine(struct thread_data *); /* * Mark unused variables passed to ops functions as unused, to silence gcc */ #define fio_unused __attribute((__unused__)) +#define fio_init __attribute__((constructor)) +#define fio_exit __attribute__((destructor)) #define for_each_td(td, i) \ for ((i) = 0, (td) = &threads[0]; (i) < (int) thread_number; (i)++, (td)++) diff --git a/init.c b/init.c index 3749c962..00f95765 100644 --- a/init.c +++ b/init.c @@ -849,6 +849,7 @@ static int str_ioengine_cb(void *data, const char *str) return 0; log_err("fio: ioengine: { linuxaio, aio, libaio }, posixaio, sync, mmap, sgio, splice, cpu\n"); + log_err("fio: or specify path to dynamic ioengine module\n"); return 1; } diff --git a/ioengines.c b/ioengines.c index 96a96360..a71357c6 100644 --- a/ioengines.c +++ b/ioengines.c @@ -18,8 +18,15 @@ #include "fio.h" #include "os.h" +static LIST_HEAD(engine_list); + static int check_engine_ops(struct ioengine_ops *ops) { + if (ops->version != FIO_IOOPS_VERSION) { + log_err("bad ioops version %d (want %d)\n", ops->version, FIO_IOOPS_VERSION); + return 1; + } + /* * cpu thread doesn't need to provide anything */ @@ -42,21 +49,48 @@ static int check_engine_ops(struct ioengine_ops *ops) return 0; } -struct ioengine_ops *load_ioengine(struct thread_data *td, const char *name) +void unregister_ioengine(struct ioengine_ops *ops) { - char engine[16], engine_lib[256]; - struct ioengine_ops *ops, *ret; - void *dlhandle; + list_del(&ops->list); + INIT_LIST_HEAD(&ops->list); +} + +int register_ioengine(struct ioengine_ops *ops) +{ + if (check_engine_ops(ops)) + return 1; + + INIT_LIST_HEAD(&ops->list); + list_add_tail(&ops->list, &engine_list); + return 0; +} + +static struct ioengine_ops *find_ioengine(const char *name) +{ + struct ioengine_ops *ops; + struct list_head *entry; + char engine[16]; strncpy(engine, name, sizeof(engine) - 1); - /* - * linux libaio has alias names, so convert to what we want - */ if (!strncmp(engine, "linuxaio", 8) || !strncmp(engine, "aio", 3)) strcpy(engine, "libaio"); - sprintf(engine_lib, "%s/lib/fio/fio-engine-%s.o", fio_inst_prefix, engine); + list_for_each(entry, &engine_list) { + ops = list_entry(entry, struct ioengine_ops, list); + if (!strcmp(engine, ops->name)) + return ops; + } + + return NULL; +} + +static struct ioengine_ops *dlopen_ioengine(struct thread_data *td, + const char *engine_lib) +{ + struct ioengine_ops *ops; + void *dlhandle; + dlerror(); dlhandle = dlopen(engine_lib, RTLD_LAZY); if (!dlhandle) { @@ -71,24 +105,41 @@ struct ioengine_ops *load_ioengine(struct thread_data *td, const char *name) return NULL; } - if (ops->version != FIO_IOOPS_VERSION) { - log_err("bad ioops version %d (want %d)\n", ops->version, FIO_IOOPS_VERSION); - dlclose(dlhandle); + ops->dlhandle = dlhandle; + return ops; +} + +struct ioengine_ops *load_ioengine(struct thread_data *td, const char *name) +{ + struct ioengine_ops *ops, *ret; + char engine[16]; + + strncpy(engine, name, sizeof(engine) - 1); + + /* + * linux libaio has alias names, so convert to what we want + */ + if (!strncmp(engine, "linuxaio", 8) || !strncmp(engine, "aio", 3)) + strcpy(engine, "libaio"); + + ops = find_ioengine(engine); + if (!ops) + ops = dlopen_ioengine(td, name); + + if (!ops) { + log_err("fio: engine %s not loadable\n", name); return NULL; } /* * Check that the required methods are there. */ - if (check_engine_ops(ops)) { - dlclose(dlhandle); + if (check_engine_ops(ops)) return NULL; - } ret = malloc(sizeof(*ret)); memcpy(ret, ops, sizeof(*ret)); ret->data = NULL; - ret->dlhandle = dlhandle; return ret; } @@ -98,7 +149,9 @@ void close_ioengine(struct thread_data *td) if (td->io_ops->cleanup) td->io_ops->cleanup(td); - dlclose(td->io_ops->dlhandle); + if (td->io_ops->dlhandle) + dlclose(td->io_ops->dlhandle); + free(td->io_ops); td->io_ops = NULL; } diff --git a/list.h b/list.h index 2e0a7ad7..cedbafaa 100644 --- a/list.h +++ b/list.h @@ -28,6 +28,9 @@ struct list_head { #define LIST_HEAD_INIT(name) { &(name), &(name) } +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + #define INIT_LIST_HEAD(ptr) do { \ (ptr)->next = (ptr); (ptr)->prev = (ptr); \ } while (0) -- 2.25.1