From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Message-ID: <52FC4620.3030205@kernel.dk> Date: Wed, 12 Feb 2014 21:12:16 -0700 From: Jens Axboe MIME-Version: 1.0 Subject: Re: [PATCH 1/2] Introduce get_ioengine for external engines References: <1392232426-16152-1-git-send-email-d.gollub@telekom.de> In-Reply-To: <1392232426-16152-1-git-send-email-d.gollub@telekom.de> Content-Type: text/plain; charset="utf-8"; format="flowed" Content-Transfer-Encoding: 8bit To: Daniel Gollub , fio@vger.kernel.org Cc: Daniel Gollub List-ID: On 2014-02-12 12:13, Daniel Gollub wrote: > This makes life easier for plugins written in C++ > since they do not need to deal with struct initilization issues > with the ioengine_ops symbol. > > With g++ a non-static ioengine_ops in global scope like this: > > struct ioengine_ops ioengine = { > .name = "null", > .version = FIO_IOOPS_VERSION, > .queue = fio_null_queue, > .commit = fio_null_commit, > }; > > Results in: > > cpp_null2.cc: At global scope: > cpp_null2.cc:112:1: error: C99 designator ‘name’ outside aggregate initializer > cpp_null2.cc:112:1: sorry, unimplemented: non-trivial designated initializers not supported > cpp_null2.cc:112:1: sorry, unimplemented: non-trivial designated initializers not supported > cpp_null2.cc:112:1: sorry, unimplemented: non-trivial designated initializers not supported > cpp_null2.cc:112:1: sorry, unimplemented: non-trivial designated initializers not supported > $ > > Example get_iongine() symbol usage: > > ---8<--- > extern "C" { > void get_ioengine(struct ioengine_ops **ioengine_ptr) { > struct ioengine_ops *ioengine; > *ioengine_ptr = (struct ioengine_ops *) malloc(sizeof(struct ioengine_ops)); > ioengine = *ioengine_ptr; > > strcpy(ioengine->name, "cpp_null"); > ioengine->version = FIO_IOOPS_VERSION; > ioengine->queue = fio_null_queue; > ioengine->commit = fio_null_commit; > ioengine->getevents = fio_null_getevents; > ioengine->event = fio_null_event; > ioengine->init = fio_null_init; > ioengine->cleanup = fio_null_cleanup; > ioengine->open_file = fio_null_open; > ioengine->flags = FIO_DISKLESSIO; > } > } > --->8--- > > Signed-off-by: Daniel Gollub > --- > ioengines.c | 14 ++++++++++++++ > 1 file changed, 14 insertions(+) > > diff --git a/ioengines.c b/ioengines.c > index d71e372..c080da3 100644 > --- a/ioengines.c > +++ b/ioengines.c > @@ -90,6 +90,7 @@ static struct ioengine_ops *dlopen_ioengine(struct thread_data *td, > { > struct ioengine_ops *ops; > void *dlhandle; > + typedef void (*get_ioengine_t)(struct ioengine_ops **); > > dprint(FD_IO, "dload engine %s\n", engine_lib); > > @@ -107,6 +108,19 @@ static struct ioengine_ops *dlopen_ioengine(struct thread_data *td, > ops = dlsym(dlhandle, engine_lib); > if (!ops) > ops = dlsym(dlhandle, "ioengine"); > + > + /* > + * For some external engines (like C++ ones) it is not that trivial > + * to provide a non-static ionengine structure that we can reference. > + * Instead we call a method which allocates the required ioengine > + * structure. > + */ > + if (!ops) { > + get_ioengine_t get_ioengine = dlsym(dlhandle, "get_ioengine"); > + if (get_ioengine) > + get_ioengine(&ops); > + } > + > if (!ops) { > td_vmsg(td, -1, dlerror(), "dlsym"); > dlclose(dlhandle); > This looks fine, but lets put that typedef in ioengine.h instead. -- Jens Axboe