Blame SOURCES/kvm-block-nbd-client-split-channel-errors-from-export-er.patch

7711c0
From 00ecc208207488fec5d793b13b1a967d8af2acfd Mon Sep 17 00:00:00 2001
7711c0
From: John Snow <jsnow@redhat.com>
7711c0
Date: Wed, 27 Mar 2019 17:22:58 +0100
7711c0
Subject: [PATCH 120/163] block/nbd-client: split channel errors from export
7711c0
 errors
7711c0
7711c0
RH-Author: John Snow <jsnow@redhat.com>
7711c0
Message-id: <20190327172308.31077-46-jsnow@redhat.com>
7711c0
Patchwork-id: 85208
7711c0
O-Subject: [RHEL-7.7 qemu-kvm-rhev PATCH 45/55] block/nbd-client: split channel errors from export errors
7711c0
Bugzilla: 1691009
7711c0
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
7711c0
RH-Acked-by: Max Reitz <mreitz@redhat.com>
7711c0
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
7711c0
7711c0
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7711c0
7711c0
To implement nbd reconnect in further patches, we need to distinguish
7711c0
error codes, returned by nbd server, from channel errors, to reconnect
7711c0
only in the latter case.
7711c0
7711c0
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7711c0
Reviewed-by: Eric Blake <eblake@redhat.com>
7711c0
Message-Id: <20190201130138.94525-2-vsementsov@virtuozzo.com>
7711c0
Signed-off-by: Eric Blake <eblake@redhat.com>
7711c0
(cherry picked from commit 7f86068dc1aceec8f6151a3a713e57e680f73b45)
7711c0
Signed-off-by: John Snow <jsnow@redhat.com>
7711c0
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
7711c0
---
7711c0
 block/nbd-client.c | 83 +++++++++++++++++++++++++++++++-----------------------
7711c0
 1 file changed, 47 insertions(+), 36 deletions(-)
7711c0
7711c0
diff --git a/block/nbd-client.c b/block/nbd-client.c
7711c0
index 5c97052..f5b9aaa 100644
7711c0
--- a/block/nbd-client.c
7711c0
+++ b/block/nbd-client.c
7711c0
@@ -503,11 +503,11 @@ static coroutine_fn int nbd_co_do_receive_one_chunk(
7711c0
  */
7711c0
 static coroutine_fn int nbd_co_receive_one_chunk(
7711c0
         NBDClientSession *s, uint64_t handle, bool only_structured,
7711c0
-        QEMUIOVector *qiov, NBDReply *reply, void **payload, Error **errp)
7711c0
+        int *request_ret, QEMUIOVector *qiov, NBDReply *reply, void **payload,
7711c0
+        Error **errp)
7711c0
 {
7711c0
-    int request_ret;
7711c0
     int ret = nbd_co_do_receive_one_chunk(s, handle, only_structured,
7711c0
-                                          &request_ret, qiov, payload, errp);
7711c0
+                                          request_ret, qiov, payload, errp);
7711c0
 
7711c0
     if (ret < 0) {
7711c0
         s->quit = true;
7711c0
@@ -517,7 +517,6 @@ static coroutine_fn int nbd_co_receive_one_chunk(
7711c0
             *reply = s->reply;
7711c0
         }
7711c0
         s->reply.handle = 0;
7711c0
-        ret = request_ret;
7711c0
     }
7711c0
 
7711c0
     if (s->read_reply_co) {
7711c0
@@ -529,22 +528,17 @@ static coroutine_fn int nbd_co_receive_one_chunk(
7711c0
 
7711c0
 typedef struct NBDReplyChunkIter {
7711c0
     int ret;
7711c0
-    bool fatal;
7711c0
+    int request_ret;
7711c0
     Error *err;
7711c0
     bool done, only_structured;
7711c0
 } NBDReplyChunkIter;
7711c0
 
7711c0
-static void nbd_iter_error(NBDReplyChunkIter *iter, bool fatal,
7711c0
-                           int ret, Error **local_err)
7711c0
+static void nbd_iter_channel_error(NBDReplyChunkIter *iter,
7711c0
+                                   int ret, Error **local_err)
7711c0
 {
7711c0
     assert(ret < 0);
7711c0
 
7711c0
-    if ((fatal && !iter->fatal) || iter->ret == 0) {
7711c0
-        if (iter->ret != 0) {
7711c0
-            error_free(iter->err);
7711c0
-            iter->err = NULL;
7711c0
-        }
7711c0
-        iter->fatal = fatal;
7711c0
+    if (!iter->ret) {
7711c0
         iter->ret = ret;
7711c0
         error_propagate(&iter->err, *local_err);
7711c0
     } else {
7711c0
@@ -554,6 +548,15 @@ static void nbd_iter_error(NBDReplyChunkIter *iter, bool fatal,
7711c0
     *local_err = NULL;
7711c0
 }
7711c0
 
7711c0
+static void nbd_iter_request_error(NBDReplyChunkIter *iter, int ret)
7711c0
+{
7711c0
+    assert(ret < 0);
7711c0
+
7711c0
+    if (!iter->request_ret) {
7711c0
+        iter->request_ret = ret;
7711c0
+    }
7711c0
+}
7711c0
+
7711c0
 /* NBD_FOREACH_REPLY_CHUNK
7711c0
  */
7711c0
 #define NBD_FOREACH_REPLY_CHUNK(s, iter, handle, structured, \
7711c0
@@ -569,13 +572,13 @@ static bool nbd_reply_chunk_iter_receive(NBDClientSession *s,
7711c0
                                          QEMUIOVector *qiov, NBDReply *reply,
7711c0
                                          void **payload)
7711c0
 {
7711c0
-    int ret;
7711c0
+    int ret, request_ret;
7711c0
     NBDReply local_reply;
7711c0
     NBDStructuredReplyChunk *chunk;
7711c0
     Error *local_err = NULL;
7711c0
     if (s->quit) {
7711c0
         error_setg(&local_err, "Connection closed");
7711c0
-        nbd_iter_error(iter, true, -EIO, &local_err);
7711c0
+        nbd_iter_channel_error(iter, -EIO, &local_err);
7711c0
         goto break_loop;
7711c0
     }
7711c0
 
7711c0
@@ -589,10 +592,12 @@ static bool nbd_reply_chunk_iter_receive(NBDClientSession *s,
7711c0
     }
7711c0
 
7711c0
     ret = nbd_co_receive_one_chunk(s, handle, iter->only_structured,
7711c0
-                                   qiov, reply, payload, &local_err);
7711c0
+                                   &request_ret, qiov, reply, payload,
7711c0
+                                   &local_err);
7711c0
     if (ret < 0) {
7711c0
-        /* If it is a fatal error s->quit is set by nbd_co_receive_one_chunk */
7711c0
-        nbd_iter_error(iter, s->quit, ret, &local_err);
7711c0
+        nbd_iter_channel_error(iter, ret, &local_err);
7711c0
+    } else if (request_ret < 0) {
7711c0
+        nbd_iter_request_error(iter, request_ret);
7711c0
     }
7711c0
 
7711c0
     /* Do not execute the body of NBD_FOREACH_REPLY_CHUNK for simple reply. */
7711c0
@@ -629,7 +634,7 @@ break_loop:
7711c0
 }
7711c0
 
7711c0
 static int nbd_co_receive_return_code(NBDClientSession *s, uint64_t handle,
7711c0
-                                      Error **errp)
7711c0
+                                      int *request_ret, Error **errp)
7711c0
 {
7711c0
     NBDReplyChunkIter iter;
7711c0
 
7711c0
@@ -638,12 +643,13 @@ static int nbd_co_receive_return_code(NBDClientSession *s, uint64_t handle,
7711c0
     }
7711c0
 
7711c0
     error_propagate(errp, iter.err);
7711c0
+    *request_ret = iter.request_ret;
7711c0
     return iter.ret;
7711c0
 }
7711c0
 
7711c0
 static int nbd_co_receive_cmdread_reply(NBDClientSession *s, uint64_t handle,
7711c0
                                         uint64_t offset, QEMUIOVector *qiov,
7711c0
-                                        Error **errp)
7711c0
+                                        int *request_ret, Error **errp)
7711c0
 {
7711c0
     NBDReplyChunkIter iter;
7711c0
     NBDReply reply;
7711c0
@@ -668,7 +674,7 @@ static int nbd_co_receive_cmdread_reply(NBDClientSession *s, uint64_t handle,
7711c0
                                                 offset, qiov, &local_err);
7711c0
             if (ret < 0) {
7711c0
                 s->quit = true;
7711c0
-                nbd_iter_error(&iter, true, ret, &local_err);
7711c0
+                nbd_iter_channel_error(&iter, ret, &local_err);
7711c0
             }
7711c0
             break;
7711c0
         default:
7711c0
@@ -678,7 +684,7 @@ static int nbd_co_receive_cmdread_reply(NBDClientSession *s, uint64_t handle,
7711c0
                 error_setg(&local_err,
7711c0
                            "Unexpected reply type: %d (%s) for CMD_READ",
7711c0
                            chunk->type, nbd_reply_type_lookup(chunk->type));
7711c0
-                nbd_iter_error(&iter, true, -EINVAL, &local_err);
7711c0
+                nbd_iter_channel_error(&iter, -EINVAL, &local_err);
7711c0
             }
7711c0
         }
7711c0
 
7711c0
@@ -687,12 +693,14 @@ static int nbd_co_receive_cmdread_reply(NBDClientSession *s, uint64_t handle,
7711c0
     }
7711c0
 
7711c0
     error_propagate(errp, iter.err);
7711c0
+    *request_ret = iter.request_ret;
7711c0
     return iter.ret;
7711c0
 }
7711c0
 
7711c0
 static int nbd_co_receive_blockstatus_reply(NBDClientSession *s,
7711c0
                                             uint64_t handle, uint64_t length,
7711c0
-                                            NBDExtent *extent, Error **errp)
7711c0
+                                            NBDExtent *extent,
7711c0
+                                            int *request_ret, Error **errp)
7711c0
 {
7711c0
     NBDReplyChunkIter iter;
7711c0
     NBDReply reply;
7711c0
@@ -714,7 +722,7 @@ static int nbd_co_receive_blockstatus_reply(NBDClientSession *s,
7711c0
             if (received) {
7711c0
                 s->quit = true;
7711c0
                 error_setg(&local_err, "Several BLOCK_STATUS chunks in reply");
7711c0
-                nbd_iter_error(&iter, true, -EINVAL, &local_err);
7711c0
+                nbd_iter_channel_error(&iter, -EINVAL, &local_err);
7711c0
             }
7711c0
             received = true;
7711c0
 
7711c0
@@ -723,7 +731,7 @@ static int nbd_co_receive_blockstatus_reply(NBDClientSession *s,
7711c0
                                                 &local_err);
7711c0
             if (ret < 0) {
7711c0
                 s->quit = true;
7711c0
-                nbd_iter_error(&iter, true, ret, &local_err);
7711c0
+                nbd_iter_channel_error(&iter, ret, &local_err);
7711c0
             }
7711c0
             break;
7711c0
         default:
7711c0
@@ -733,7 +741,7 @@ static int nbd_co_receive_blockstatus_reply(NBDClientSession *s,
7711c0
                            "Unexpected reply type: %d (%s) "
7711c0
                            "for CMD_BLOCK_STATUS",
7711c0
                            chunk->type, nbd_reply_type_lookup(chunk->type));
7711c0
-                nbd_iter_error(&iter, true, -EINVAL, &local_err);
7711c0
+                nbd_iter_channel_error(&iter, -EINVAL, &local_err);
7711c0
             }
7711c0
         }
7711c0
 
7711c0
@@ -748,14 +756,16 @@ static int nbd_co_receive_blockstatus_reply(NBDClientSession *s,
7711c0
             iter.ret = -EIO;
7711c0
         }
7711c0
     }
7711c0
+
7711c0
     error_propagate(errp, iter.err);
7711c0
+    *request_ret = iter.request_ret;
7711c0
     return iter.ret;
7711c0
 }
7711c0
 
7711c0
 static int nbd_co_request(BlockDriverState *bs, NBDRequest *request,
7711c0
                           QEMUIOVector *write_qiov)
7711c0
 {
7711c0
-    int ret;
7711c0
+    int ret, request_ret;
7711c0
     Error *local_err = NULL;
7711c0
     NBDClientSession *client = nbd_get_client_session(bs);
7711c0
 
7711c0
@@ -771,7 +781,8 @@ static int nbd_co_request(BlockDriverState *bs, NBDRequest *request,
7711c0
         return ret;
7711c0
     }
7711c0
 
7711c0
-    ret = nbd_co_receive_return_code(client, request->handle, &local_err);
7711c0
+    ret = nbd_co_receive_return_code(client, request->handle,
7711c0
+                                     &request_ret, &local_err);
7711c0
     if (local_err) {
7711c0
         trace_nbd_co_request_fail(request->from, request->len, request->handle,
7711c0
                                   request->flags, request->type,
7711c0
@@ -779,13 +790,13 @@ static int nbd_co_request(BlockDriverState *bs, NBDRequest *request,
7711c0
                                   ret, error_get_pretty(local_err));
7711c0
         error_free(local_err);
7711c0
     }
7711c0
-    return ret;
7711c0
+    return ret ? ret : request_ret;
7711c0
 }
7711c0
 
7711c0
 int nbd_client_co_preadv(BlockDriverState *bs, uint64_t offset,
7711c0
                          uint64_t bytes, QEMUIOVector *qiov, int flags)
7711c0
 {
7711c0
-    int ret;
7711c0
+    int ret, request_ret;
7711c0
     Error *local_err = NULL;
7711c0
     NBDClientSession *client = nbd_get_client_session(bs);
7711c0
     NBDRequest request = {
7711c0
@@ -806,7 +817,7 @@ int nbd_client_co_preadv(BlockDriverState *bs, uint64_t offset,
7711c0
     }
7711c0
 
7711c0
     ret = nbd_co_receive_cmdread_reply(client, request.handle, offset, qiov,
7711c0
-                                       &local_err);
7711c0
+                                       &request_ret, &local_err);
7711c0
     if (local_err) {
7711c0
         trace_nbd_co_request_fail(request.from, request.len, request.handle,
7711c0
                                   request.flags, request.type,
7711c0
@@ -814,7 +825,7 @@ int nbd_client_co_preadv(BlockDriverState *bs, uint64_t offset,
7711c0
                                   ret, error_get_pretty(local_err));
7711c0
         error_free(local_err);
7711c0
     }
7711c0
-    return ret;
7711c0
+    return ret ? ret : request_ret;
7711c0
 }
7711c0
 
7711c0
 int nbd_client_co_pwritev(BlockDriverState *bs, uint64_t offset,
7711c0
@@ -908,7 +919,7 @@ int coroutine_fn nbd_client_co_block_status(BlockDriverState *bs,
7711c0
                                             int64_t *pnum, int64_t *map,
7711c0
                                             BlockDriverState **file)
7711c0
 {
7711c0
-    int64_t ret;
7711c0
+    int ret, request_ret;
7711c0
     NBDExtent extent = { 0 };
7711c0
     NBDClientSession *client = nbd_get_client_session(bs);
7711c0
     Error *local_err = NULL;
7711c0
@@ -933,7 +944,7 @@ int coroutine_fn nbd_client_co_block_status(BlockDriverState *bs,
7711c0
     }
7711c0
 
7711c0
     ret = nbd_co_receive_blockstatus_reply(client, request.handle, bytes,
7711c0
-                                           &extent, &local_err);
7711c0
+                                           &extent, &request_ret, &local_err);
7711c0
     if (local_err) {
7711c0
         trace_nbd_co_request_fail(request.from, request.len, request.handle,
7711c0
                                   request.flags, request.type,
7711c0
@@ -941,8 +952,8 @@ int coroutine_fn nbd_client_co_block_status(BlockDriverState *bs,
7711c0
                                   ret, error_get_pretty(local_err));
7711c0
         error_free(local_err);
7711c0
     }
7711c0
-    if (ret < 0) {
7711c0
-        return ret;
7711c0
+    if (ret < 0 || request_ret < 0) {
7711c0
+        return ret ? ret : request_ret;
7711c0
     }
7711c0
 
7711c0
     assert(extent.length);
7711c0
-- 
7711c0
1.8.3.1
7711c0