curl: never invoke callbacks with s->mutex held

All curl callbacks go through curl_multi_do, and hence are called with
s->mutex held.  Note that with comments, and make curl_read_cb drop the
lock before invoking the callback.

Likewise for curl_find_buf, where the callback can be invoked by the
caller.

Cc: qemu-stable@nongnu.org
Reviewed-by: Jeff Cody <jcody@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Message-id: 20170515100059.15795-3-pbonzini@redhat.com
Signed-off-by: Jeff Cody <jcody@redhat.com>
This commit is contained in:
Paolo Bonzini 2017-05-15 12:00:54 +02:00 committed by Jeff Cody
parent 675a775633
commit 34db05e7ff

View File

@ -148,6 +148,7 @@ static void curl_multi_do(void *arg);
static void curl_multi_read(void *arg); static void curl_multi_read(void *arg);
#ifdef NEED_CURL_TIMER_CALLBACK #ifdef NEED_CURL_TIMER_CALLBACK
/* Called from curl_multi_do_locked, with s->mutex held. */
static int curl_timer_cb(CURLM *multi, long timeout_ms, void *opaque) static int curl_timer_cb(CURLM *multi, long timeout_ms, void *opaque)
{ {
BDRVCURLState *s = opaque; BDRVCURLState *s = opaque;
@ -164,6 +165,7 @@ static int curl_timer_cb(CURLM *multi, long timeout_ms, void *opaque)
} }
#endif #endif
/* Called from curl_multi_do_locked, with s->mutex held. */
static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action, static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action,
void *userp, void *sp) void *userp, void *sp)
{ {
@ -213,6 +215,7 @@ static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action,
return 0; return 0;
} }
/* Called from curl_multi_do_locked, with s->mutex held. */
static size_t curl_header_cb(void *ptr, size_t size, size_t nmemb, void *opaque) static size_t curl_header_cb(void *ptr, size_t size, size_t nmemb, void *opaque)
{ {
BDRVCURLState *s = opaque; BDRVCURLState *s = opaque;
@ -227,6 +230,7 @@ static size_t curl_header_cb(void *ptr, size_t size, size_t nmemb, void *opaque)
return realsize; return realsize;
} }
/* Called from curl_multi_do_locked, with s->mutex held. */
static size_t curl_read_cb(void *ptr, size_t size, size_t nmemb, void *opaque) static size_t curl_read_cb(void *ptr, size_t size, size_t nmemb, void *opaque)
{ {
CURLState *s = ((CURLState*)opaque); CURLState *s = ((CURLState*)opaque);
@ -265,7 +269,9 @@ static size_t curl_read_cb(void *ptr, size_t size, size_t nmemb, void *opaque)
request_length - offset); request_length - offset);
} }
qemu_mutex_unlock(&s->s->mutex);
acb->common.cb(acb->common.opaque, 0); acb->common.cb(acb->common.opaque, 0);
qemu_mutex_lock(&s->s->mutex);
qemu_aio_unref(acb); qemu_aio_unref(acb);
s->acb[i] = NULL; s->acb[i] = NULL;
} }
@ -306,8 +312,6 @@ static int curl_find_buf(BDRVCURLState *s, size_t start, size_t len,
if (clamped_len < len) { if (clamped_len < len) {
qemu_iovec_memset(acb->qiov, clamped_len, 0, len - clamped_len); qemu_iovec_memset(acb->qiov, clamped_len, 0, len - clamped_len);
} }
acb->common.cb(acb->common.opaque, 0);
return FIND_RET_OK; return FIND_RET_OK;
} }
@ -854,8 +858,8 @@ static void curl_readv_bh_cb(void *p)
// we can just call the callback and be done. // we can just call the callback and be done.
switch (curl_find_buf(s, start, acb->nb_sectors * BDRV_SECTOR_SIZE, acb)) { switch (curl_find_buf(s, start, acb->nb_sectors * BDRV_SECTOR_SIZE, acb)) {
case FIND_RET_OK: case FIND_RET_OK:
qemu_aio_unref(acb); ret = 0;
// fall through goto out;
case FIND_RET_WAIT: case FIND_RET_WAIT:
goto out; goto out;
default: default: