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

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