|
From: | Josh Durgin |
Subject: | Re: [Qemu-devel] [PATCH 2/2] rbd: disable unsupported librbd functions at runtime |
Date: | Thu, 04 Apr 2013 09:50:23 -0700 |
User-agent: | Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130221 Thunderbird/17.0.3 |
On 04/04/2013 03:10 AM, Kevin Wolf wrote:
Am 04.04.2013 um 10:35 hat Josh Durgin geschrieben:QEMU may be compiled against a newer version of librbd, but run and dynamically linked with an older version that does not support these functions. Declare them as weak symbols so they can be checked for existence at runtime. Only rbd_aio_discard, rbd_aio_flush, and rbd_flush were added after the initial version of librbd, so only they need to be checked. Signed-off-by: Josh Durgin <address@hidden> --- block/rbd.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/block/rbd.c b/block/rbd.c index 037d82b..69a339a 100644 --- a/block/rbd.c +++ b/block/rbd.c @@ -44,6 +44,15 @@ * leading "\". */ +/* + * Treat newer librbd functions as weak symbols so we can detect + * whether they're supported at runtime, and disable their use + * if they aren't available. + */ +#pragma weak rbd_aio_discard +#pragma weak rbd_aio_flush +#pragma weak rbd_flush + /* rbd_aio_discard added in 0.1.2 */ #if LIBRBD_VERSION_CODE >= LIBRBD_VERSION(0, 1, 2) #define LIBRBD_SUPPORTS_DISCARD @@ -970,6 +979,7 @@ static BlockDriver bdrv_rbd = { .bdrv_aio_readv = qemu_rbd_aio_readv, .bdrv_aio_writev = qemu_rbd_aio_writev, + /* select which of these to use at runtime in bdrv_rbd_init */ .bdrv_aio_flush = qemu_rbd_aio_flush, .bdrv_co_flush_to_disk = qemu_rbd_co_flush, @@ -985,6 +995,15 @@ static BlockDriver bdrv_rbd = { static void bdrv_rbd_init(void) { + if (!rbd_flush || rbd_aio_flush) { + bdrv_rbd.bdrv_co_flush_to_disk = NULL; + } + if (!rbd_aio_flush) { + bdrv_rbd.bdrv_aio_flush = NULL; + } + if (!rbd_aio_discard) { + bdrv_rbd.bdrv_aio_discard = NULL; + } bdrv_register(&bdrv_rbd); }After searching the net a bit and trying out some things myself, I'm afraid that this approach doesn't work. It does seem to do the right thing when build and runtime version are the same, but new build -> old runtime segfaults (because the symbol doesn't become NULL) and old build -> new runtime segfaults (because the symbol stays NULL). Unless I missed some build option that is different in qemu than in my test program.
It worked when downgrading the runtime version of librbd for me, so maybe something about qemu's build was different. This patch wouldn't allow newer functions in a runtime version to be used though, since they would be disabled if qemu were built against an older version.
So it looks as if you had to use dlsym() instead.
I tried this initially, using glib's portable wrappers, but found that it would require using the dlopen'd version only - not linking at build time against librbd at all. I thought this might be too big a change, but now it seems like the best way to go. Using this approach, upgrading from a version of librbd that doesn't support e.g. rbd_aio_flush to one that does would not require recompiling qemu to be able to use the new function. In general, librbd would not be needed at compile time for qemu to be able to use it, which would make the rbd block driver much easier to install on distros where rbd isn't enabled at build time. If you don't mind this approach, I'll post another version using only dlopen'd (via glib) librbd/librados. Thanks for the reviews, Josh
[Prev in Thread] | Current Thread | [Next in Thread] |