[PATCH] Link in known io engines
authorJens Axboe <jens.axboe@oracle.com>
Tue, 7 Nov 2006 14:20:59 +0000 (15:20 +0100)
committerJens Axboe <jens.axboe@oracle.com>
Tue, 7 Nov 2006 14:20:59 +0000 (15:20 +0100)
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 <jens.axboe@oracle.com>
13 files changed:
Makefile
engines/Makefile [deleted file]
engines/fio-engine-cpu.c
engines/fio-engine-libaio.c
engines/fio-engine-mmap.c
engines/fio-engine-posixaio.c
engines/fio-engine-sg.c
engines/fio-engine-splice.c
engines/fio-engine-sync.c
fio.h
init.c
ioengines.c
list.h

index ad9aa3b..1ebad6a 100644 (file)
--- 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 (file)
index 963a93e..0000000
+++ /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
index 4ba12c6..f65f91d 100644 (file)
@@ -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);
+}
index 12ddc98..45e69e9 100644 (file)
@@ -7,8 +7,9 @@
 #include <unistd.h>
 #include <errno.h>
 #include <assert.h>
-#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);
+}
index 483a704..20dcfd2 100644 (file)
@@ -8,8 +8,9 @@
 #include <errno.h>
 #include <assert.h>
 #include <sys/mman.h>
-#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);
+}
index 894a410..ef4d78e 100644 (file)
@@ -7,8 +7,9 @@
 #include <unistd.h>
 #include <errno.h>
 #include <assert.h>
-#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);
+}
index 2762e0b..9c5037f 100644 (file)
@@ -8,8 +8,9 @@
 #include <errno.h>
 #include <assert.h>
 #include <sys/poll.h>
-#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);
+}
index 3b02fbf..fa4a6ee 100644 (file)
@@ -8,8 +8,9 @@
 #include <errno.h>
 #include <assert.h>
 #include <sys/poll.h>
-#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);
+}
index 43f42ca..5919830 100644 (file)
@@ -7,8 +7,9 @@
 #include <unistd.h>
 #include <errno.h>
 #include <assert.h>
-#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 f859608..9f5201b 100644 (file)
--- 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 3749c96..00f9576 100644 (file)
--- 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;
 }
 
index 96a9636..a71357c 100644 (file)
 #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 2e0a7ad..cedbafa 100644 (file)
--- 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)