qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH 2/2] rbd: disable unsupported librbd functions a


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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]