Blame SOURCES/kvm-curl-Handle-success-in-multi_check_completion.patch

016a62
From 23f5a846f6702c456cf7cc9490e50cfd23368910 Mon Sep 17 00:00:00 2001
016a62
From: Max Reitz <mreitz@redhat.com>
016a62
Date: Tue, 19 Nov 2019 15:29:59 +0000
016a62
Subject: [PATCH 7/8] curl: Handle success in multi_check_completion
016a62
MIME-Version: 1.0
016a62
Content-Type: text/plain; charset=UTF-8
016a62
Content-Transfer-Encoding: 8bit
016a62
016a62
RH-Author: Max Reitz <mreitz@redhat.com>
016a62
Message-id: <20191119153000.101646-7-mreitz@redhat.com>
016a62
Patchwork-id: 92520
016a62
O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 6/7] curl: Handle success in multi_check_completion
016a62
Bugzilla: 1744602
016a62
RH-Acked-by: Maxim Levitsky <mlevitsk@redhat.com>
016a62
RH-Acked-by: Philippe Mathieu-Daudé <philmd@redhat.com>
016a62
RH-Acked-by: Stefano Garzarella <sgarzare@redhat.com>
016a62
016a62
Background: As of cURL 7.59.0, it verifies that several functions are
016a62
not called from within a callback.  Among these functions is
016a62
curl_multi_add_handle().
016a62
016a62
curl_read_cb() is a callback from cURL and not a coroutine.  Waking up
016a62
acb->co will lead to entering it then and there, which means the current
016a62
request will settle and the caller (if it runs in the same coroutine)
016a62
may then issue the next request.  In such a case, we will enter
016a62
curl_setup_preadv() effectively from within curl_read_cb().
016a62
016a62
Calling curl_multi_add_handle() will then fail and the new request will
016a62
not be processed.
016a62
016a62
Fix this by not letting curl_read_cb() wake up acb->co.  Instead, leave
016a62
the whole business of settling the AIOCB objects to
016a62
curl_multi_check_completion() (which is called from our timer callback
016a62
and our FD handler, so not from any cURL callbacks).
016a62
016a62
Reported-by: Natalie Gavrielov <ngavrilo@redhat.com>
016a62
Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1740193
016a62
Cc: qemu-stable@nongnu.org
016a62
Signed-off-by: Max Reitz <mreitz@redhat.com>
016a62
Message-id: 20190910124136.10565-7-mreitz@redhat.com
016a62
Reviewed-by: John Snow <jsnow@redhat.com>
016a62
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
016a62
Signed-off-by: Max Reitz <mreitz@redhat.com>
016a62
(cherry picked from commit bfb23b480a49114315877aacf700b49453e0f9d9)
016a62
Signed-off-by: Max Reitz <mreitz@redhat.com>
016a62
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
016a62
---
016a62
 block/curl.c | 69 +++++++++++++++++++++++++-----------------------------------
016a62
 1 file changed, 29 insertions(+), 40 deletions(-)
016a62
016a62
diff --git a/block/curl.c b/block/curl.c
016a62
index f776615..b5899e1 100644
016a62
--- a/block/curl.c
016a62
+++ b/block/curl.c
016a62
@@ -238,7 +238,6 @@ static size_t curl_read_cb(void *ptr, size_t size, size_t nmemb, void *opaque)
016a62
 {
016a62
     CURLState *s = ((CURLState*)opaque);
016a62
     size_t realsize = size * nmemb;
016a62
-    int i;
016a62
 
016a62
     DPRINTF("CURL: Just reading %zd bytes\n", realsize);
016a62
 
016a62
@@ -254,32 +253,6 @@ static size_t curl_read_cb(void *ptr, size_t size, size_t nmemb, void *opaque)
016a62
     memcpy(s->orig_buf + s->buf_off, ptr, realsize);
016a62
     s->buf_off += realsize;
016a62
 
016a62
-    for(i=0; i
016a62
-        CURLAIOCB *acb = s->acb[i];
016a62
-
016a62
-        if (!acb)
016a62
-            continue;
016a62
-
016a62
-        if ((s->buf_off >= acb->end)) {
016a62
-            size_t request_length = acb->bytes;
016a62
-
016a62
-            qemu_iovec_from_buf(acb->qiov, 0, s->orig_buf + acb->start,
016a62
-                                acb->end - acb->start);
016a62
-
016a62
-            if (acb->end - acb->start < request_length) {
016a62
-                size_t offset = acb->end - acb->start;
016a62
-                qemu_iovec_memset(acb->qiov, offset, 0,
016a62
-                                  request_length - offset);
016a62
-            }
016a62
-
016a62
-            acb->ret = 0;
016a62
-            s->acb[i] = NULL;
016a62
-            qemu_mutex_unlock(&s->s->mutex);
016a62
-            aio_co_wake(acb->co);
016a62
-            qemu_mutex_lock(&s->s->mutex);
016a62
-        }
016a62
-    }
016a62
-
016a62
 read_end:
016a62
     /* curl will error out if we do not return this value */
016a62
     return size * nmemb;
016a62
@@ -360,13 +333,14 @@ static void curl_multi_check_completion(BDRVCURLState *s)
016a62
             break;
016a62
 
016a62
         if (msg->msg == CURLMSG_DONE) {
016a62
+            int i;
016a62
             CURLState *state = NULL;
016a62
+            bool error = msg->data.result != CURLE_OK;
016a62
+
016a62
             curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE,
016a62
                               (char **)&state);
016a62
 
016a62
-            /* ACBs for successful messages get completed in curl_read_cb */
016a62
-            if (msg->data.result != CURLE_OK) {
016a62
-                int i;
016a62
+            if (error) {
016a62
                 static int errcount = 100;
016a62
 
016a62
                 /* Don't lose the original error message from curl, since
016a62
@@ -378,20 +352,35 @@ static void curl_multi_check_completion(BDRVCURLState *s)
016a62
                         error_report("curl: further errors suppressed");
016a62
                     }
016a62
                 }
016a62
+            }
016a62
 
016a62
-                for (i = 0; i < CURL_NUM_ACB; i++) {
016a62
-                    CURLAIOCB *acb = state->acb[i];
016a62
+            for (i = 0; i < CURL_NUM_ACB; i++) {
016a62
+                CURLAIOCB *acb = state->acb[i];
016a62
 
016a62
-                    if (acb == NULL) {
016a62
-                        continue;
016a62
-                    }
016a62
+                if (acb == NULL) {
016a62
+                    continue;
016a62
+                }
016a62
+
016a62
+                if (!error) {
016a62
+                    /* Assert that we have read all data */
016a62
+                    assert(state->buf_off >= acb->end);
016a62
+
016a62
+                    qemu_iovec_from_buf(acb->qiov, 0,
016a62
+                                        state->orig_buf + acb->start,
016a62
+                                        acb->end - acb->start);
016a62
 
016a62
-                    acb->ret = -EIO;
016a62
-                    state->acb[i] = NULL;
016a62
-                    qemu_mutex_unlock(&s->mutex);
016a62
-                    aio_co_wake(acb->co);
016a62
-                    qemu_mutex_lock(&s->mutex);
016a62
+                    if (acb->end - acb->start < acb->bytes) {
016a62
+                        size_t offset = acb->end - acb->start;
016a62
+                        qemu_iovec_memset(acb->qiov, offset, 0,
016a62
+                                          acb->bytes - offset);
016a62
+                    }
016a62
                 }
016a62
+
016a62
+                acb->ret = error ? -EIO : 0;
016a62
+                state->acb[i] = NULL;
016a62
+                qemu_mutex_unlock(&s->mutex);
016a62
+                aio_co_wake(acb->co);
016a62
+                qemu_mutex_lock(&s->mutex);
016a62
             }
016a62
 
016a62
             curl_clean_state(state);
016a62
-- 
016a62
1.8.3.1
016a62