qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Stefan Hajnoczi <stefanha@redhat.com>
To: qemu-devel@nongnu.org
Cc: Peter Maydell <peter.maydell@linaro.org>,
	Fam Zheng <famz@redhat.com>, Alexander Graf <agraf@suse.de>,
	Stefan Hajnoczi <stefanha@redhat.com>
Subject: [Qemu-devel] [PULL 08/42] curl: implement .bdrv_detach/attach_aio_context()
Date: Fri,  6 Jun 2014 18:13:29 +0200	[thread overview]
Message-ID: <1402071243-16702-9-git-send-email-stefanha@redhat.com> (raw)
In-Reply-To: <1402071243-16702-1-git-send-email-stefanha@redhat.com>

The curl block driver uses fd handlers, timers, and BHs.  The fd
handlers and timers are managed on behalf of libcurl, which controls
them using callback functions that the block driver implements.

The simplest way to implement .bdrv_detach/attach_aio_context() is to
clean up libcurl in the old event loop and initialize it again in the
new event loop.  We do not need to keep track of anything since there
are no pending requests when the AioContext is changed.

Also make sure to use aio_set_fd_handler() instead of
qemu_aio_set_fd_handler() and aio_bh_new() instead of qemu_bh_new() so
the current AioContext is passed in.

Cc: Alexander Graf <agraf@suse.de>
Cc: Fam Zheng <famz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
---
 block/curl.c | 192 +++++++++++++++++++++++++++++++++++------------------------
 1 file changed, 115 insertions(+), 77 deletions(-)

diff --git a/block/curl.c b/block/curl.c
index f491b0b..8c84141 100644
--- a/block/curl.c
+++ b/block/curl.c
@@ -110,6 +110,7 @@ typedef struct BDRVCURLState {
     size_t readahead_size;
     bool sslverify;
     bool accept_range;
+    AioContext *aio_context;
 } BDRVCURLState;
 
 static void curl_clean_state(CURLState *s);
@@ -134,25 +135,29 @@ static int curl_timer_cb(CURLM *multi, long timeout_ms, void *opaque)
 #endif
 
 static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action,
-                        void *s, void *sp)
+                        void *userp, void *sp)
 {
+    BDRVCURLState *s;
     CURLState *state = NULL;
     curl_easy_getinfo(curl, CURLINFO_PRIVATE, (char **)&state);
     state->sock_fd = fd;
+    s = state->s;
 
     DPRINTF("CURL (AIO): Sock action %d on fd %d\n", action, fd);
     switch (action) {
         case CURL_POLL_IN:
-            qemu_aio_set_fd_handler(fd, curl_multi_read, NULL, state);
+            aio_set_fd_handler(s->aio_context, fd, curl_multi_read,
+                               NULL, state);
             break;
         case CURL_POLL_OUT:
-            qemu_aio_set_fd_handler(fd, NULL, curl_multi_do, state);
+            aio_set_fd_handler(s->aio_context, fd, NULL, curl_multi_do, state);
             break;
         case CURL_POLL_INOUT:
-            qemu_aio_set_fd_handler(fd, curl_multi_read, curl_multi_do, state);
+            aio_set_fd_handler(s->aio_context, fd, curl_multi_read,
+                               curl_multi_do, state);
             break;
         case CURL_POLL_REMOVE:
-            qemu_aio_set_fd_handler(fd, NULL, NULL, NULL);
+            aio_set_fd_handler(s->aio_context, fd, NULL, NULL, NULL);
             break;
     }
 
@@ -365,7 +370,7 @@ static CURLState *curl_init_state(BDRVCURLState *s)
             break;
         }
         if (!state) {
-            qemu_aio_wait();
+            aio_poll(state->s->aio_context, true);
         }
     } while(!state);
 
@@ -422,6 +427,51 @@ static void curl_parse_filename(const char *filename, QDict *options,
     qdict_put(options, CURL_BLOCK_OPT_URL, qstring_from_str(filename));
 }
 
+static void curl_detach_aio_context(BlockDriverState *bs)
+{
+    BDRVCURLState *s = bs->opaque;
+    int i;
+
+    for (i = 0; i < CURL_NUM_STATES; i++) {
+        if (s->states[i].in_use) {
+            curl_clean_state(&s->states[i]);
+        }
+        if (s->states[i].curl) {
+            curl_easy_cleanup(s->states[i].curl);
+            s->states[i].curl = NULL;
+        }
+        if (s->states[i].orig_buf) {
+            g_free(s->states[i].orig_buf);
+            s->states[i].orig_buf = NULL;
+        }
+    }
+    if (s->multi) {
+        curl_multi_cleanup(s->multi);
+        s->multi = NULL;
+    }
+
+    timer_del(&s->timer);
+}
+
+static void curl_attach_aio_context(BlockDriverState *bs,
+                                    AioContext *new_context)
+{
+    BDRVCURLState *s = bs->opaque;
+
+    aio_timer_init(new_context, &s->timer,
+                   QEMU_CLOCK_REALTIME, SCALE_NS,
+                   curl_multi_timeout_do, s);
+
+    assert(!s->multi);
+    s->multi = curl_multi_init();
+    s->aio_context = new_context;
+    curl_multi_setopt(s->multi, CURLMOPT_SOCKETFUNCTION, curl_sock_cb);
+#ifdef NEED_CURL_TIMER_CALLBACK
+    curl_multi_setopt(s->multi, CURLMOPT_TIMERDATA, s);
+    curl_multi_setopt(s->multi, CURLMOPT_TIMERFUNCTION, curl_timer_cb);
+#endif
+}
+
 static QemuOptsList runtime_opts = {
     .name = "curl",
     .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
@@ -491,6 +541,7 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
     }
 
     DPRINTF("CURL: Opening %s\n", file);
+    s->aio_context = bdrv_get_aio_context(bs);
     s->url = g_strdup(file);
     state = curl_init_state(s);
     if (!state)
@@ -523,19 +574,7 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
     curl_easy_cleanup(state->curl);
     state->curl = NULL;
 
-    aio_timer_init(bdrv_get_aio_context(bs), &s->timer,
-                   QEMU_CLOCK_REALTIME, SCALE_NS,
-                   curl_multi_timeout_do, s);
-
-    // Now we know the file exists and its size, so let's
-    // initialize the multi interface!
-
-    s->multi = curl_multi_init();
-    curl_multi_setopt(s->multi, CURLMOPT_SOCKETFUNCTION, curl_sock_cb);
-#ifdef NEED_CURL_TIMER_CALLBACK
-    curl_multi_setopt(s->multi, CURLMOPT_TIMERDATA, s);
-    curl_multi_setopt(s->multi, CURLMOPT_TIMERFUNCTION, curl_timer_cb);
-#endif
+    curl_attach_aio_context(bs, bdrv_get_aio_context(bs));
 
     qemu_opts_del(opts);
     return 0;
@@ -630,7 +669,7 @@ static BlockDriverAIOCB *curl_aio_readv(BlockDriverState *bs,
     acb->sector_num = sector_num;
     acb->nb_sectors = nb_sectors;
 
-    acb->bh = qemu_bh_new(curl_readv_bh_cb, acb);
+    acb->bh = aio_bh_new(bdrv_get_aio_context(bs), curl_readv_bh_cb, acb);
     qemu_bh_schedule(acb->bh);
     return &acb->common;
 }
@@ -638,25 +677,9 @@ static BlockDriverAIOCB *curl_aio_readv(BlockDriverState *bs,
 static void curl_close(BlockDriverState *bs)
 {
     BDRVCURLState *s = bs->opaque;
-    int i;
 
     DPRINTF("CURL: Close\n");
-    for (i=0; i<CURL_NUM_STATES; i++) {
-        if (s->states[i].in_use)
-            curl_clean_state(&s->states[i]);
-        if (s->states[i].curl) {
-            curl_easy_cleanup(s->states[i].curl);
-            s->states[i].curl = NULL;
-        }
-        if (s->states[i].orig_buf) {
-            g_free(s->states[i].orig_buf);
-            s->states[i].orig_buf = NULL;
-        }
-    }
-    if (s->multi)
-        curl_multi_cleanup(s->multi);
-
-    timer_del(&s->timer);
+    curl_detach_aio_context(bs);
 
     g_free(s->url);
 }
@@ -668,68 +691,83 @@ static int64_t curl_getlength(BlockDriverState *bs)
 }
 
 static BlockDriver bdrv_http = {
-    .format_name            = "http",
-    .protocol_name          = "http",
+    .format_name                = "http",
+    .protocol_name              = "http",
+
+    .instance_size              = sizeof(BDRVCURLState),
+    .bdrv_parse_filename        = curl_parse_filename,
+    .bdrv_file_open             = curl_open,
+    .bdrv_close                 = curl_close,
+    .bdrv_getlength             = curl_getlength,
 
-    .instance_size          = sizeof(BDRVCURLState),
-    .bdrv_parse_filename    = curl_parse_filename,
-    .bdrv_file_open         = curl_open,
-    .bdrv_close             = curl_close,
-    .bdrv_getlength         = curl_getlength,
+    .bdrv_aio_readv             = curl_aio_readv,
 
-    .bdrv_aio_readv         = curl_aio_readv,
+    .bdrv_detach_aio_context    = curl_detach_aio_context,
+    .bdrv_attach_aio_context    = curl_attach_aio_context,
 };
 
 static BlockDriver bdrv_https = {
-    .format_name            = "https",
-    .protocol_name          = "https",
+    .format_name                = "https",
+    .protocol_name              = "https",
 
-    .instance_size          = sizeof(BDRVCURLState),
-    .bdrv_parse_filename    = curl_parse_filename,
-    .bdrv_file_open         = curl_open,
-    .bdrv_close             = curl_close,
-    .bdrv_getlength         = curl_getlength,
+    .instance_size              = sizeof(BDRVCURLState),
+    .bdrv_parse_filename        = curl_parse_filename,
+    .bdrv_file_open             = curl_open,
+    .bdrv_close                 = curl_close,
+    .bdrv_getlength             = curl_getlength,
 
-    .bdrv_aio_readv         = curl_aio_readv,
+    .bdrv_aio_readv             = curl_aio_readv,
+
+    .bdrv_detach_aio_context    = curl_detach_aio_context,
+    .bdrv_attach_aio_context    = curl_attach_aio_context,
 };
 
 static BlockDriver bdrv_ftp = {
-    .format_name            = "ftp",
-    .protocol_name          = "ftp",
+    .format_name                = "ftp",
+    .protocol_name              = "ftp",
+
+    .instance_size              = sizeof(BDRVCURLState),
+    .bdrv_parse_filename        = curl_parse_filename,
+    .bdrv_file_open             = curl_open,
+    .bdrv_close                 = curl_close,
+    .bdrv_getlength             = curl_getlength,
 
-    .instance_size          = sizeof(BDRVCURLState),
-    .bdrv_parse_filename    = curl_parse_filename,
-    .bdrv_file_open         = curl_open,
-    .bdrv_close             = curl_close,
-    .bdrv_getlength         = curl_getlength,
+    .bdrv_aio_readv             = curl_aio_readv,
 
-    .bdrv_aio_readv         = curl_aio_readv,
+    .bdrv_detach_aio_context    = curl_detach_aio_context,
+    .bdrv_attach_aio_context    = curl_attach_aio_context,
 };
 
 static BlockDriver bdrv_ftps = {
-    .format_name            = "ftps",
-    .protocol_name          = "ftps",
+    .format_name                = "ftps",
+    .protocol_name              = "ftps",
 
-    .instance_size          = sizeof(BDRVCURLState),
-    .bdrv_parse_filename    = curl_parse_filename,
-    .bdrv_file_open         = curl_open,
-    .bdrv_close             = curl_close,
-    .bdrv_getlength         = curl_getlength,
+    .instance_size              = sizeof(BDRVCURLState),
+    .bdrv_parse_filename        = curl_parse_filename,
+    .bdrv_file_open             = curl_open,
+    .bdrv_close                 = curl_close,
+    .bdrv_getlength             = curl_getlength,
 
-    .bdrv_aio_readv         = curl_aio_readv,
+    .bdrv_aio_readv             = curl_aio_readv,
+
+    .bdrv_detach_aio_context    = curl_detach_aio_context,
+    .bdrv_attach_aio_context    = curl_attach_aio_context,
 };
 
 static BlockDriver bdrv_tftp = {
-    .format_name            = "tftp",
-    .protocol_name          = "tftp",
+    .format_name                = "tftp",
+    .protocol_name              = "tftp",
+
+    .instance_size              = sizeof(BDRVCURLState),
+    .bdrv_parse_filename        = curl_parse_filename,
+    .bdrv_file_open             = curl_open,
+    .bdrv_close                 = curl_close,
+    .bdrv_getlength             = curl_getlength,
 
-    .instance_size          = sizeof(BDRVCURLState),
-    .bdrv_parse_filename    = curl_parse_filename,
-    .bdrv_file_open         = curl_open,
-    .bdrv_close             = curl_close,
-    .bdrv_getlength         = curl_getlength,
+    .bdrv_aio_readv             = curl_aio_readv,
 
-    .bdrv_aio_readv         = curl_aio_readv,
+    .bdrv_detach_aio_context    = curl_detach_aio_context,
+    .bdrv_attach_aio_context    = curl_attach_aio_context,
 };
 
 static void curl_block_init(void)
-- 
1.9.3

  parent reply	other threads:[~2014-06-06 16:14 UTC|newest]

Thread overview: 44+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-06-06 16:13 [Qemu-devel] [PULL 00/42] Block patches Stefan Hajnoczi
2014-06-06 16:13 ` [Qemu-devel] [PULL 01/42] aio: fix qemu_bh_schedule() bh->ctx race condition Stefan Hajnoczi
2014-06-06 16:13 ` [Qemu-devel] [PULL 02/42] block: use BlockDriverState AioContext Stefan Hajnoczi
2014-06-06 16:13 ` [Qemu-devel] [PULL 03/42] block: acquire AioContext in bdrv_*_all() Stefan Hajnoczi
2014-06-06 16:13 ` [Qemu-devel] [PULL 04/42] block: acquire AioContext in bdrv_drain_all() Stefan Hajnoczi
2014-06-06 16:13 ` [Qemu-devel] [PULL 05/42] block: add bdrv_set_aio_context() Stefan Hajnoczi
2014-06-06 16:13 ` [Qemu-devel] [PULL 06/42] blkdebug: use BlockDriverState's AioContext Stefan Hajnoczi
2014-06-06 16:13 ` [Qemu-devel] [PULL 07/42] blkverify: implement .bdrv_detach/attach_aio_context() Stefan Hajnoczi
2014-06-06 16:13 ` Stefan Hajnoczi [this message]
2014-06-06 16:13 ` [Qemu-devel] [PULL 09/42] gluster: use BlockDriverState's AioContext Stefan Hajnoczi
2014-06-06 16:13 ` [Qemu-devel] [PULL 10/42] iscsi: implement .bdrv_detach/attach_aio_context() Stefan Hajnoczi
2014-06-06 16:13 ` [Qemu-devel] [PULL 11/42] nbd: " Stefan Hajnoczi
2014-06-06 16:13 ` [Qemu-devel] [PULL 12/42] nfs: " Stefan Hajnoczi
2014-06-06 16:13 ` [Qemu-devel] [PULL 13/42] qed: use BlockDriverState's AioContext Stefan Hajnoczi
2014-06-06 16:13 ` [Qemu-devel] [PULL 14/42] quorum: implement .bdrv_detach/attach_aio_context() Stefan Hajnoczi
2014-06-06 16:13 ` [Qemu-devel] [PULL 15/42] block/raw-posix: " Stefan Hajnoczi
2014-06-06 16:13 ` [Qemu-devel] [PULL 16/42] block/linux-aio: fix memory and fd leak Stefan Hajnoczi
2014-06-06 16:13 ` [Qemu-devel] [PULL 17/42] block/raw-win32: create one QEMUWin32AIOState per BDRVRawState Stefan Hajnoczi
2014-06-06 16:13 ` [Qemu-devel] [PULL 18/42] block/raw-win32: implement .bdrv_detach/attach_aio_context() Stefan Hajnoczi
2014-06-06 16:13 ` [Qemu-devel] [PULL 19/42] rbd: use BlockDriverState's AioContext Stefan Hajnoczi
2014-06-06 16:13 ` [Qemu-devel] [PULL 20/42] sheepdog: implement .bdrv_detach/attach_aio_context() Stefan Hajnoczi
2014-06-06 16:13 ` [Qemu-devel] [PULL 21/42] ssh: use BlockDriverState's AioContext Stefan Hajnoczi
2014-06-06 16:13 ` [Qemu-devel] [PULL 22/42] vmdk: implement .bdrv_detach/attach_aio_context() Stefan Hajnoczi
2014-06-06 16:13 ` [Qemu-devel] [PULL 23/42] dataplane: use the QEMU block layer for I/O Stefan Hajnoczi
2014-06-06 16:13 ` [Qemu-devel] [PULL 24/42] dataplane: delete IOQueue since it is no longer used Stefan Hajnoczi
2014-06-06 16:13 ` [Qemu-devel] [PULL 25/42] dataplane: implement async flush Stefan Hajnoczi
2014-06-06 16:13 ` [Qemu-devel] [PULL 26/42] raw-posix: drop raw_get_aio_fd() since it is no longer used Stefan Hajnoczi
2014-06-06 16:13 ` [Qemu-devel] [PULL 27/42] block: Move declaration of bdrv_get_aio_context to block.h Stefan Hajnoczi
2014-06-06 16:13 ` [Qemu-devel] [PULL 28/42] virtio-blk: Allow config-wce in dataplane Stefan Hajnoczi
2014-06-06 16:13 ` [Qemu-devel] [PULL 29/42] virtio-blk: Factor out virtio_blk_handle_scsi_req from virtio_blk_handle_scsi Stefan Hajnoczi
2014-06-06 16:13 ` [Qemu-devel] [PULL 30/42] dataplane: Support VIRTIO_BLK_T_SCSI_CMD Stefan Hajnoczi
2014-06-06 16:13 ` [Qemu-devel] [PULL 31/42] throttle: add throttle_detach/attach_aio_context() Stefan Hajnoczi
2014-06-06 16:13 ` [Qemu-devel] [PULL 32/42] throttle: add detach/attach test case Stefan Hajnoczi
2014-06-06 16:13 ` [Qemu-devel] [PULL 33/42] blockdev: acquire AioContext in block_set_io_throttle Stefan Hajnoczi
2014-06-06 16:13 ` [Qemu-devel] [PULL 34/42] block: fix wrong order in live block migration setup Stefan Hajnoczi
2014-06-06 16:13 ` [Qemu-devel] [PULL 35/42] qemu-img: Document check exit codes Stefan Hajnoczi
2014-06-06 16:13 ` [Qemu-devel] [PULL 36/42] rbd: Fix leaks in rbd_start_aio() error path Stefan Hajnoczi
2014-06-06 16:13 ` [Qemu-devel] [PULL 37/42] sheepdog: fix vdi object update after live snapshot Stefan Hajnoczi
2014-06-06 16:13 ` [Qemu-devel] [PULL 38/42] sheepdog: reload only header in a case of " Stefan Hajnoczi
2014-06-06 16:14 ` [Qemu-devel] [PULL 39/42] qapi: Extract qapi/common.json definitions Stefan Hajnoczi
2014-06-06 16:14 ` [Qemu-devel] [PULL 40/42] qapi: create two block related json modules Stefan Hajnoczi
2014-06-06 16:14 ` [Qemu-devel] [PULL 41/42] qapi: Extract qapi/block-core.json definitions Stefan Hajnoczi
2014-06-06 16:14 ` [Qemu-devel] [PULL 42/42] qapi: Extract qapi/block.json definitions Stefan Hajnoczi
2014-06-09 12:04 ` [Qemu-devel] [PULL 00/42] Block patches Peter Maydell

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1402071243-16702-9-git-send-email-stefanha@redhat.com \
    --to=stefanha@redhat.com \
    --cc=agraf@suse.de \
    --cc=famz@redhat.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).