curl: split curl_find_state/curl_init_state

If curl_easy_init fails, a CURLState is left with s->in_use = 1.  Split
curl_init_state in two, so that we can distinguish the two failures and
call curl_clean_state if needed.

While at it, simplify curl_find_state, removing a dummy loop.  The
aio_poll loop is moved to the sole caller that needs it.

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-5-pbonzini@redhat.com
Signed-off-by: Jeff Cody <jcody@redhat.com>
This commit is contained in:
Paolo Bonzini 2017-05-15 12:00:56 +02:00 committed by Jeff Cody
parent 456af34629
commit 3ce6a729b5

View File

@ -456,34 +456,27 @@ static void curl_multi_timeout_do(void *arg)
} }
/* Called with s->mutex held. */ /* Called with s->mutex held. */
static CURLState *curl_init_state(BlockDriverState *bs, BDRVCURLState *s) static CURLState *curl_find_state(BDRVCURLState *s)
{ {
CURLState *state = NULL; CURLState *state = NULL;
int i, j; int i;
do {
for (i=0; i<CURL_NUM_STATES; i++) {
for (j=0; j<CURL_NUM_ACB; j++)
if (s->states[i].acb[j])
continue;
if (s->states[i].in_use)
continue;
for (i = 0; i < CURL_NUM_STATES; i++) {
if (!s->states[i].in_use) {
state = &s->states[i]; state = &s->states[i];
state->in_use = 1; state->in_use = 1;
break; break;
} }
if (!state) { }
qemu_mutex_unlock(&s->mutex); return state;
aio_poll(bdrv_get_aio_context(bs), true); }
qemu_mutex_lock(&s->mutex);
}
} while(!state);
static int curl_init_state(BDRVCURLState *s, CURLState *state)
{
if (!state->curl) { if (!state->curl) {
state->curl = curl_easy_init(); state->curl = curl_easy_init();
if (!state->curl) { if (!state->curl) {
return NULL; return -EIO;
} }
curl_easy_setopt(state->curl, CURLOPT_URL, s->url); curl_easy_setopt(state->curl, CURLOPT_URL, s->url);
curl_easy_setopt(state->curl, CURLOPT_SSL_VERIFYPEER, curl_easy_setopt(state->curl, CURLOPT_SSL_VERIFYPEER,
@ -536,7 +529,7 @@ static CURLState *curl_init_state(BlockDriverState *bs, BDRVCURLState *s)
QLIST_INIT(&state->sockets); QLIST_INIT(&state->sockets);
state->s = s; state->s = s;
return state; return 0;
} }
/* Called with s->mutex held. */ /* Called with s->mutex held. */
@ -778,13 +771,18 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
s->aio_context = bdrv_get_aio_context(bs); s->aio_context = bdrv_get_aio_context(bs);
s->url = g_strdup(file); s->url = g_strdup(file);
qemu_mutex_lock(&s->mutex); qemu_mutex_lock(&s->mutex);
state = curl_init_state(bs, s); state = curl_find_state(s);
qemu_mutex_unlock(&s->mutex); qemu_mutex_unlock(&s->mutex);
if (!state) if (!state) {
goto out_noclean; goto out_noclean;
}
// Get file size // Get file size
if (curl_init_state(s, state) < 0) {
goto out;
}
s->accept_range = false; s->accept_range = false;
curl_easy_setopt(state->curl, CURLOPT_NOBODY, 1); curl_easy_setopt(state->curl, CURLOPT_NOBODY, 1);
curl_easy_setopt(state->curl, CURLOPT_HEADERFUNCTION, curl_easy_setopt(state->curl, CURLOPT_HEADERFUNCTION,
@ -879,8 +877,18 @@ static void curl_readv_bh_cb(void *p)
} }
// No cache found, so let's start a new request // No cache found, so let's start a new request
state = curl_init_state(acb->common.bs, s); for (;;) {
if (!state) { state = curl_find_state(s);
if (state) {
break;
}
qemu_mutex_unlock(&s->mutex);
aio_poll(bdrv_get_aio_context(bs), true);
qemu_mutex_lock(&s->mutex);
}
if (curl_init_state(s, state) < 0) {
curl_clean_state(state);
ret = -EIO; ret = -EIO;
goto out; goto out;
} }