[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-stable] [PATCH 41/51] block/curl: Implement the libcurl timer call
From: |
Michael Roth |
Subject: |
[Qemu-stable] [PATCH 41/51] block/curl: Implement the libcurl timer callback interface |
Date: |
Fri, 21 Feb 2014 02:17:17 -0600 |
From: Peter Maydell <address@hidden>
libcurl versions 7.16.0 and later have a timer callback interface which
must be implemented in order for libcurl to make forward progress (it
will sometimes rely on being called back on the timeout if there are
no file descriptors registered). Implement the callback, and use a
QEMU AIO timer to ensure we prod libcurl again when it asks us to.
Based on Peter's original patch plus my fix to add curl_multi_timeout_do.
Should compile just fine even on older versions of libcurl.
I also tried copy-on-read and streaming:
$ ./qemu-img create -f qcow2 -o \
backing_file=http://download.fedoraproject.org/pub/fedora/linux/releases/20/Live/x86_64/Fedora-Live-Desktop-x86_64-20-1.iso
\
foo.qcow2 1G
$ x86_64-softmmu/qemu-system-x86_64 \
-drive if=none,file=foo.qcow2,copy-on-read=on,id=cd \
-device ide-cd,drive=cd --enable-kvm -m 1024
Direct http usage is probably too slow, but with copy-on-read ultimately
the image does boot!
After some time, streaming gets canceled by an EIO, which needs further
investigation.
Signed-off-by: Peter Maydell <address@hidden>
Signed-off-by: Paolo Bonzini <address@hidden>
Signed-off-by: Kevin Wolf <address@hidden>
(cherry picked from commit 031fd1be5618c347f9aeb44ec294f14a541e42b2)
Signed-off-by: Michael Roth <address@hidden>
---
block/curl.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 70 insertions(+), 11 deletions(-)
diff --git a/block/curl.c b/block/curl.c
index 5a46f97..1c04dcc 100644
--- a/block/curl.c
+++ b/block/curl.c
@@ -34,6 +34,11 @@
#define DPRINTF(fmt, ...) do { } while (0)
#endif
+#if LIBCURL_VERSION_NUM >= 0x071000
+/* The multi interface timer callback was introduced in 7.16.0 */
+#define NEED_CURL_TIMER_CALLBACK
+#endif
+
#define PROTOCOLS (CURLPROTO_HTTP | CURLPROTO_HTTPS | \
CURLPROTO_FTP | CURLPROTO_FTPS | \
CURLPROTO_TFTP)
@@ -77,6 +82,7 @@ typedef struct CURLState
typedef struct BDRVCURLState {
CURLM *multi;
+ QEMUTimer timer;
size_t len;
CURLState states[CURL_NUM_STATES];
char *url;
@@ -87,6 +93,23 @@ typedef struct BDRVCURLState {
static void curl_clean_state(CURLState *s);
static void curl_multi_do(void *arg);
+#ifdef NEED_CURL_TIMER_CALLBACK
+static int curl_timer_cb(CURLM *multi, long timeout_ms, void *opaque)
+{
+ BDRVCURLState *s = opaque;
+
+ DPRINTF("CURL: timer callback timeout_ms %ld\n", timeout_ms);
+ if (timeout_ms == -1) {
+ timer_del(&s->timer);
+ } else {
+ int64_t timeout_ns = (int64_t)timeout_ms * 1000 * 1000;
+ timer_mod(&s->timer,
+ qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + timeout_ns);
+ }
+ return 0;
+}
+#endif
+
static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action,
void *s, void *sp)
{
@@ -209,20 +232,10 @@ static int curl_find_buf(BDRVCURLState *s, size_t start,
size_t len,
return FIND_RET_NONE;
}
-static void curl_multi_do(void *arg)
+static void curl_multi_read(BDRVCURLState *s)
{
- BDRVCURLState *s = (BDRVCURLState *)arg;
- int running;
- int r;
int msgs_in_queue;
- if (!s->multi)
- return;
-
- do {
- r = curl_multi_socket_all(s->multi, &running);
- } while(r == CURLM_CALL_MULTI_PERFORM);
-
/* Try to find done transfers, so we can free the easy
* handle again. */
do {
@@ -266,6 +279,41 @@ static void curl_multi_do(void *arg)
} while(msgs_in_queue);
}
+static void curl_multi_do(void *arg)
+{
+ BDRVCURLState *s = (BDRVCURLState *)arg;
+ int running;
+ int r;
+
+ if (!s->multi) {
+ return;
+ }
+
+ do {
+ r = curl_multi_socket_all(s->multi, &running);
+ } while(r == CURLM_CALL_MULTI_PERFORM);
+
+ curl_multi_read(s);
+}
+
+static void curl_multi_timeout_do(void *arg)
+{
+#ifdef NEED_CURL_TIMER_CALLBACK
+ BDRVCURLState *s = (BDRVCURLState *)arg;
+ int running;
+
+ if (!s->multi) {
+ return;
+ }
+
+ curl_multi_socket_action(s->multi, CURL_SOCKET_TIMEOUT, 0, &running);
+
+ curl_multi_read(s);
+#else
+ abort();
+#endif
+}
+
static CURLState *curl_init_state(BDRVCURLState *s)
{
CURLState *state = NULL;
@@ -473,12 +521,20 @@ 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_SOCKETDATA, s);
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_multi_do(s);
qemu_opts_del(opts);
@@ -597,6 +653,9 @@ static void curl_close(BlockDriverState *bs)
}
if (s->multi)
curl_multi_cleanup(s->multi);
+
+ timer_del(&s->timer);
+
g_free(s->url);
}
--
1.7.9.5
- [Qemu-stable] [PATCH 32/51] tcg/optimize: fix known-zero bits for right shift ops, (continued)
- [Qemu-stable] [PATCH 32/51] tcg/optimize: fix known-zero bits for right shift ops, Michael Roth, 2014/02/21
- [Qemu-stable] [PATCH 31/51] Fix QEMU build on OpenBSD on x86 archs, Michael Roth, 2014/02/21
- [Qemu-stable] [PATCH 34/51] block/iscsi: use a bh to schedule co reentrance, Michael Roth, 2014/02/21
- [Qemu-stable] [PATCH 33/51] hpet: fix build with CONFIG_HPET off, Michael Roth, 2014/02/21
- [Qemu-stable] [PATCH 35/51] qemu_opts_parse(): always check return value, Michael Roth, 2014/02/21
- [Qemu-stable] [PATCH 38/51] mainstone: Fix duplicate array values for key 'space', Michael Roth, 2014/02/21
- [Qemu-stable] [PATCH 36/51] s390x/kvm: Fix diagnose handling., Michael Roth, 2014/02/21
- [Qemu-stable] [PATCH 37/51] seccomp: exit if seccomp_init() fails, Michael Roth, 2014/02/21
- [Qemu-stable] [PATCH 39/51] migration: qmp_migrate(): keep working after syntax error, Michael Roth, 2014/02/21
- [Qemu-stable] [PATCH 40/51] vfio-pci: Release all MSI-X vectors when disabled, Michael Roth, 2014/02/21
- [Qemu-stable] [PATCH 41/51] block/curl: Implement the libcurl timer callback interface,
Michael Roth <=
- [Qemu-stable] [PATCH 43/51] scsi: Assign cancel_io vector for scsi_disk_emulate_ops, Michael Roth, 2014/02/21
- [Qemu-stable] [PATCH 42/51] scsi: Support TEST UNIT READY in the dummy LUN0, Michael Roth, 2014/02/21
- [Qemu-stable] [PATCH 44/51] virtio-scsi: Cleanup of I/Os that never started, Michael Roth, 2014/02/21
- [Qemu-stable] [PATCH 45/51] virtio-scsi: Prevent assertion on missed events, Michael Roth, 2014/02/21
- [Qemu-stable] [PATCH 47/51] i386: Add missing include file for QEMU_PACKED, Michael Roth, 2014/02/21
- [Qemu-stable] [PATCH 46/51] KVM: Retry KVM_CREATE_VM on EINTR, Michael Roth, 2014/02/21
- [Qemu-stable] [PATCH 48/51] linux-user: Fix trampoline code for CRIS, Michael Roth, 2014/02/21
- [Qemu-stable] [PATCH 50/51] memory: fix limiting of translation at a page boundary, Michael Roth, 2014/02/21
- [Qemu-stable] [PATCH 51/51] tcg-arm: The shift count of op_rotl_i32 is in args[2] not args[1]., Michael Roth, 2014/02/21
- Re: [Qemu-stable] Patch Round-up for stable 1.7.1, freeze on 2013-02-27, Paolo Bonzini, 2014/02/21