9ae3a8
From 9e46b4be497106cff27fd67c5c3cc79023e21762 Mon Sep 17 00:00:00 2001
9ae3a8
From: Fam Zheng <famz@redhat.com>
9ae3a8
Date: Fri, 4 Apr 2014 05:55:57 +0200
9ae3a8
Subject: [PATCH 02/12] iscsi: correctly propagate errors in iscsi_open
9ae3a8
9ae3a8
RH-Author: Fam Zheng <famz@redhat.com>
9ae3a8
Message-id: <1396590962-25815-3-git-send-email-famz@redhat.com>
9ae3a8
Patchwork-id: 58339
9ae3a8
O-Subject: [RHEL-7 0day qemu-kvm PATCH 2/7] iscsi: correctly propagate errors in iscsi_open
9ae3a8
Bugzilla: 1083413
9ae3a8
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
9ae3a8
RH-Acked-by: Markus Armbruster <armbru@redhat.com>
9ae3a8
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
9ae3a8
RH-Acked-by: Jeffrey Cody <jcody@redhat.com>
9ae3a8
9ae3a8
From: Paolo Bonzini <pbonzini@redhat.com>
9ae3a8
9ae3a8
Before:
9ae3a8
    $ ./qemu-io-old
9ae3a8
    qemu-io-old> open -r -o file.driver=iscsi,file.filename=foo
9ae3a8
    Failed to parse URL : foo
9ae3a8
    qemu-io-old: can't open device (null): Could not open 'foo': Invalid argument
9ae3a8
9ae3a8
After:
9ae3a8
    $ ./qemu-io
9ae3a8
    qemu-io> open -r -o file.driver=iscsi,file.filename=foo
9ae3a8
    qemu-io: can't open device (null): Failed to parse URL : foo
9ae3a8
9ae3a8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
9ae3a8
Reviewed-by: Fam Zheng <famz@redhat.com>
9ae3a8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9ae3a8
(cherry picked from commit f2917853f715b0ef55df29eb2ffea29dc69ce814)
9ae3a8
Signed-off-by: Fam Zheng <famz@redhat.com>
9ae3a8
9ae3a8
Conflicts:
9ae3a8
	block/iscsi.c
9ae3a8
        Because 84d18f065fb041a1c0d78d20320d740ae0673c8a (Use
9ae3a8
        error_is_set() only when necessary) is not backpored, which
9ae3a8
        converted "if (error_is_set(&local_err))" to "if (local_err)".
9ae3a8
9ae3a8
Signed-off-by: Fam Zheng <famz@redhat.com>
9ae3a8
---
9ae3a8
 block/iscsi.c | 105 ++++++++++++++++++++++++++++++----------------------------
9ae3a8
 1 file changed, 54 insertions(+), 51 deletions(-)
9ae3a8
9ae3a8
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
9ae3a8
---
9ae3a8
 block/iscsi.c |  105 +++++++++++++++++++++++++++++---------------------------
9ae3a8
 1 files changed, 54 insertions(+), 51 deletions(-)
9ae3a8
9ae3a8
diff --git a/block/iscsi.c b/block/iscsi.c
9ae3a8
index 082956c..537d2cb 100644
9ae3a8
--- a/block/iscsi.c
9ae3a8
+++ b/block/iscsi.c
9ae3a8
@@ -1036,7 +1036,8 @@ retry:
9ae3a8
 
9ae3a8
 #endif /* SCSI_SENSE_ASCQ_CAPACITY_DATA_HAS_CHANGED */
9ae3a8
 
9ae3a8
-static int parse_chap(struct iscsi_context *iscsi, const char *target)
9ae3a8
+static void parse_chap(struct iscsi_context *iscsi, const char *target,
9ae3a8
+                       Error **errp)
9ae3a8
 {
9ae3a8
     QemuOptsList *list;
9ae3a8
     QemuOpts *opts;
9ae3a8
@@ -1045,37 +1046,35 @@ static int parse_chap(struct iscsi_context *iscsi, const char *target)
9ae3a8
 
9ae3a8
     list = qemu_find_opts("iscsi");
9ae3a8
     if (!list) {
9ae3a8
-        return 0;
9ae3a8
+        return;
9ae3a8
     }
9ae3a8
 
9ae3a8
     opts = qemu_opts_find(list, target);
9ae3a8
     if (opts == NULL) {
9ae3a8
         opts = QTAILQ_FIRST(&list->head);
9ae3a8
         if (!opts) {
9ae3a8
-            return 0;
9ae3a8
+            return;
9ae3a8
         }
9ae3a8
     }
9ae3a8
 
9ae3a8
     user = qemu_opt_get(opts, "user");
9ae3a8
     if (!user) {
9ae3a8
-        return 0;
9ae3a8
+        return;
9ae3a8
     }
9ae3a8
 
9ae3a8
     password = qemu_opt_get(opts, "password");
9ae3a8
     if (!password) {
9ae3a8
-        error_report("CHAP username specified but no password was given");
9ae3a8
-        return -1;
9ae3a8
+        error_setg(errp, "CHAP username specified but no password was given");
9ae3a8
+        return;
9ae3a8
     }
9ae3a8
 
9ae3a8
     if (iscsi_set_initiator_username_pwd(iscsi, user, password)) {
9ae3a8
-        error_report("Failed to set initiator username and password");
9ae3a8
-        return -1;
9ae3a8
+        error_setg(errp, "Failed to set initiator username and password");
9ae3a8
     }
9ae3a8
-
9ae3a8
-    return 0;
9ae3a8
 }
9ae3a8
 
9ae3a8
-static void parse_header_digest(struct iscsi_context *iscsi, const char *target)
9ae3a8
+static void parse_header_digest(struct iscsi_context *iscsi, const char *target,
9ae3a8
+                                Error **errp)
9ae3a8
 {
9ae3a8
     QemuOptsList *list;
9ae3a8
     QemuOpts *opts;
9ae3a8
@@ -1108,7 +1107,7 @@ static void parse_header_digest(struct iscsi_context *iscsi, const char *target)
9ae3a8
     } else if (!strcmp(digest, "NONE-CRC32C")) {
9ae3a8
         iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C);
9ae3a8
     } else {
9ae3a8
-        error_report("Invalid header-digest setting : %s", digest);
9ae3a8
+        error_setg(errp, "Invalid header-digest setting : %s", digest);
9ae3a8
     }
9ae3a8
 }
9ae3a8
 
9ae3a8
@@ -1166,12 +1165,11 @@ static void iscsi_nop_timed_event(void *opaque)
9ae3a8
 }
9ae3a8
 #endif
9ae3a8
 
9ae3a8
-static int iscsi_readcapacity_sync(IscsiLun *iscsilun)
9ae3a8
+static void iscsi_readcapacity_sync(IscsiLun *iscsilun, Error **errp)
9ae3a8
 {
9ae3a8
     struct scsi_task *task = NULL;
9ae3a8
     struct scsi_readcapacity10 *rc10 = NULL;
9ae3a8
     struct scsi_readcapacity16 *rc16 = NULL;
9ae3a8
-    int ret = 0;
9ae3a8
     int retries = ISCSI_CMD_RETRIES; 
9ae3a8
 
9ae3a8
     do {
9ae3a8
@@ -1186,8 +1184,7 @@ static int iscsi_readcapacity_sync(IscsiLun *iscsilun)
9ae3a8
             if (task != NULL && task->status == SCSI_STATUS_GOOD) {
9ae3a8
                 rc16 = scsi_datain_unmarshall(task);
9ae3a8
                 if (rc16 == NULL) {
9ae3a8
-                    error_report("iSCSI: Failed to unmarshall readcapacity16 data.");
9ae3a8
-                    ret = -EINVAL;
9ae3a8
+                    error_setg(errp, "iSCSI: Failed to unmarshall readcapacity16 data.");
9ae3a8
                 } else {
9ae3a8
                     iscsilun->block_size = rc16->block_length;
9ae3a8
                     iscsilun->num_blocks = rc16->returned_lba + 1;
9ae3a8
@@ -1201,8 +1198,7 @@ static int iscsi_readcapacity_sync(IscsiLun *iscsilun)
9ae3a8
             if (task != NULL && task->status == SCSI_STATUS_GOOD) {
9ae3a8
                 rc10 = scsi_datain_unmarshall(task);
9ae3a8
                 if (rc10 == NULL) {
9ae3a8
-                    error_report("iSCSI: Failed to unmarshall readcapacity10 data.");
9ae3a8
-                    ret = -EINVAL;
9ae3a8
+                    error_setg(errp, "iSCSI: Failed to unmarshall readcapacity10 data.");
9ae3a8
                 } else {
9ae3a8
                     iscsilun->block_size = rc10->block_size;
9ae3a8
                     if (rc10->lba == 0) {
9ae3a8
@@ -1215,20 +1211,18 @@ static int iscsi_readcapacity_sync(IscsiLun *iscsilun)
9ae3a8
             }
9ae3a8
             break;
9ae3a8
         default:
9ae3a8
-            return 0;
9ae3a8
+            return;
9ae3a8
         }
9ae3a8
     } while (task != NULL && task->status == SCSI_STATUS_CHECK_CONDITION
9ae3a8
              && task->sense.key == SCSI_SENSE_UNIT_ATTENTION
9ae3a8
              && retries-- > 0);
9ae3a8
 
9ae3a8
     if (task == NULL || task->status != SCSI_STATUS_GOOD) {
9ae3a8
-        error_report("iSCSI: failed to send readcapacity10 command.");
9ae3a8
-        ret = -EINVAL;
9ae3a8
+        error_setg(errp, "iSCSI: failed to send readcapacity10 command.");
9ae3a8
     }
9ae3a8
     if (task) {
9ae3a8
         scsi_free_scsi_task(task);
9ae3a8
     }
9ae3a8
-    return ret;
9ae3a8
 }
9ae3a8
 
9ae3a8
 /* TODO Convert to fine grained options */
9ae3a8
@@ -1246,7 +1240,7 @@ static QemuOptsList runtime_opts = {
9ae3a8
 };
9ae3a8
 
9ae3a8
 static struct scsi_task *iscsi_do_inquiry(struct iscsi_context *iscsi, int lun,
9ae3a8
-                                          int evpd, int pc)
9ae3a8
+                                          int evpd, int pc, Error **errp)
9ae3a8
 {
9ae3a8
     int full_size;
9ae3a8
     struct scsi_task *task = NULL;
9ae3a8
@@ -1268,8 +1262,8 @@ static struct scsi_task *iscsi_do_inquiry(struct iscsi_context *iscsi, int lun,
9ae3a8
     return task;
9ae3a8
 
9ae3a8
 fail:
9ae3a8
-    error_report("iSCSI: Inquiry command failed : %s",
9ae3a8
-                 iscsi_get_error(iscsi));
9ae3a8
+    error_setg(errp, "iSCSI: Inquiry command failed : %s",
9ae3a8
+               iscsi_get_error(iscsi));
9ae3a8
     if (task) {
9ae3a8
         scsi_free_scsi_task(task);
9ae3a8
         return NULL;
9ae3a8
@@ -1296,27 +1290,25 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
9ae3a8
     int ret;
9ae3a8
 
9ae3a8
     if ((BDRV_SECTOR_SIZE % 512) != 0) {
9ae3a8
-        error_report("iSCSI: Invalid BDRV_SECTOR_SIZE. "
9ae3a8
-                     "BDRV_SECTOR_SIZE(%lld) is not a multiple "
9ae3a8
-                     "of 512", BDRV_SECTOR_SIZE);
9ae3a8
+        error_setg(errp, "iSCSI: Invalid BDRV_SECTOR_SIZE. "
9ae3a8
+                   "BDRV_SECTOR_SIZE(%lld) is not a multiple "
9ae3a8
+                   "of 512", BDRV_SECTOR_SIZE);
9ae3a8
         return -EINVAL;
9ae3a8
     }
9ae3a8
 
9ae3a8
     opts = qemu_opts_create_nofail(&runtime_opts);
9ae3a8
     qemu_opts_absorb_qdict(opts, options, &local_err);
9ae3a8
-    if (error_is_set(&local_err)) {
9ae3a8
-        qerror_report_err(local_err);
9ae3a8
-        error_free(local_err);
9ae3a8
+    if (local_err) {
9ae3a8
+        error_propagate(errp, local_err);
9ae3a8
         ret = -EINVAL;
9ae3a8
         goto out;
9ae3a8
     }
9ae3a8
 
9ae3a8
     filename = qemu_opt_get(opts, "filename");
9ae3a8
 
9ae3a8
-
9ae3a8
     iscsi_url = iscsi_parse_full_url(iscsi, filename);
9ae3a8
     if (iscsi_url == NULL) {
9ae3a8
-        error_report("Failed to parse URL : %s", filename);
9ae3a8
+        error_setg(errp, "Failed to parse URL : %s", filename);
9ae3a8
         ret = -EINVAL;
9ae3a8
         goto out;
9ae3a8
     }
9ae3a8
@@ -1327,13 +1319,13 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
9ae3a8
 
9ae3a8
     iscsi = iscsi_create_context(initiator_name);
9ae3a8
     if (iscsi == NULL) {
9ae3a8
-        error_report("iSCSI: Failed to create iSCSI context.");
9ae3a8
+        error_setg(errp, "iSCSI: Failed to create iSCSI context.");
9ae3a8
         ret = -ENOMEM;
9ae3a8
         goto out;
9ae3a8
     }
9ae3a8
 
9ae3a8
     if (iscsi_set_targetname(iscsi, iscsi_url->target)) {
9ae3a8
-        error_report("iSCSI: Failed to set target name.");
9ae3a8
+        error_setg(errp, "iSCSI: Failed to set target name.");
9ae3a8
         ret = -EINVAL;
9ae3a8
         goto out;
9ae3a8
     }
9ae3a8
@@ -1342,21 +1334,22 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
9ae3a8
         ret = iscsi_set_initiator_username_pwd(iscsi, iscsi_url->user,
9ae3a8
                                               iscsi_url->passwd);
9ae3a8
         if (ret != 0) {
9ae3a8
-            error_report("Failed to set initiator username and password");
9ae3a8
+            error_setg(errp, "Failed to set initiator username and password");
9ae3a8
             ret = -EINVAL;
9ae3a8
             goto out;
9ae3a8
         }
9ae3a8
     }
9ae3a8
 
9ae3a8
     /* check if we got CHAP username/password via the options */
9ae3a8
-    if (parse_chap(iscsi, iscsi_url->target) != 0) {
9ae3a8
-        error_report("iSCSI: Failed to set CHAP user/password");
9ae3a8
+    parse_chap(iscsi, iscsi_url->target, &local_err);
9ae3a8
+    if (local_err != NULL) {
9ae3a8
+        error_propagate(errp, local_err);
9ae3a8
         ret = -EINVAL;
9ae3a8
         goto out;
9ae3a8
     }
9ae3a8
 
9ae3a8
     if (iscsi_set_session_type(iscsi, ISCSI_SESSION_NORMAL) != 0) {
9ae3a8
-        error_report("iSCSI: Failed to set session type to normal.");
9ae3a8
+        error_setg(errp, "iSCSI: Failed to set session type to normal.");
9ae3a8
         ret = -EINVAL;
9ae3a8
         goto out;
9ae3a8
     }
9ae3a8
@@ -1364,10 +1357,15 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
9ae3a8
     iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C);
9ae3a8
 
9ae3a8
     /* check if we got HEADER_DIGEST via the options */
9ae3a8
-    parse_header_digest(iscsi, iscsi_url->target);
9ae3a8
+    parse_header_digest(iscsi, iscsi_url->target, &local_err);
9ae3a8
+    if (local_err != NULL) {
9ae3a8
+        error_propagate(errp, local_err);
9ae3a8
+        ret = -EINVAL;
9ae3a8
+        goto out;
9ae3a8
+    }
9ae3a8
 
9ae3a8
     if (iscsi_full_connect_sync(iscsi, iscsi_url->portal, iscsi_url->lun) != 0) {
9ae3a8
-        error_report("iSCSI: Failed to connect to LUN : %s",
9ae3a8
+        error_setg(errp, "iSCSI: Failed to connect to LUN : %s",
9ae3a8
             iscsi_get_error(iscsi));
9ae3a8
         ret = -EINVAL;
9ae3a8
         goto out;
9ae3a8
@@ -1379,14 +1377,14 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
9ae3a8
     task = iscsi_inquiry_sync(iscsi, iscsilun->lun, 0, 0, 36);
9ae3a8
 
9ae3a8
     if (task == NULL || task->status != SCSI_STATUS_GOOD) {
9ae3a8
-        error_report("iSCSI: failed to send inquiry command.");
9ae3a8
+        error_setg(errp, "iSCSI: failed to send inquiry command.");
9ae3a8
         ret = -EINVAL;
9ae3a8
         goto out;
9ae3a8
     }
9ae3a8
 
9ae3a8
     inq = scsi_datain_unmarshall(task);
9ae3a8
     if (inq == NULL) {
9ae3a8
-        error_report("iSCSI: Failed to unmarshall inquiry data.");
9ae3a8
+        error_setg(errp, "iSCSI: Failed to unmarshall inquiry data.");
9ae3a8
         ret = -EINVAL;
9ae3a8
         goto out;
9ae3a8
     }
9ae3a8
@@ -1394,7 +1392,9 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
9ae3a8
     iscsilun->type = inq->periperal_device_type;
9ae3a8
     iscsilun->has_write_same = true;
9ae3a8
 
9ae3a8
-    if ((ret = iscsi_readcapacity_sync(iscsilun)) != 0) {
9ae3a8
+    iscsi_readcapacity_sync(iscsilun, &local_err);
9ae3a8
+    if (local_err != NULL) {
9ae3a8
+        error_propagate(errp, local_err);
9ae3a8
         goto out;
9ae3a8
     }
9ae3a8
     bs->total_sectors = sector_lun2qemu(iscsilun->num_blocks, iscsilun);
9ae3a8
@@ -1411,14 +1411,15 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
9ae3a8
     if (iscsilun->lbpme) {
9ae3a8
         struct scsi_inquiry_logical_block_provisioning *inq_lbp;
9ae3a8
         task = iscsi_do_inquiry(iscsilun->iscsi, iscsilun->lun, 1,
9ae3a8
-                                SCSI_INQUIRY_PAGECODE_LOGICAL_BLOCK_PROVISIONING);
9ae3a8
+                                SCSI_INQUIRY_PAGECODE_LOGICAL_BLOCK_PROVISIONING,
9ae3a8
+                                errp);
9ae3a8
         if (task == NULL) {
9ae3a8
             ret = -EINVAL;
9ae3a8
             goto out;
9ae3a8
         }
9ae3a8
         inq_lbp = scsi_datain_unmarshall(task);
9ae3a8
         if (inq_lbp == NULL) {
9ae3a8
-            error_report("iSCSI: failed to unmarshall inquiry datain blob");
9ae3a8
+            error_setg(errp, "iSCSI: failed to unmarshall inquiry datain blob");
9ae3a8
             ret = -EINVAL;
9ae3a8
             goto out;
9ae3a8
         }
9ae3a8
@@ -1431,14 +1432,14 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
9ae3a8
     if (iscsilun->lbp.lbpu || iscsilun->lbp.lbpws) {
9ae3a8
         struct scsi_inquiry_block_limits *inq_bl;
9ae3a8
         task = iscsi_do_inquiry(iscsilun->iscsi, iscsilun->lun, 1,
9ae3a8
-                                SCSI_INQUIRY_PAGECODE_BLOCK_LIMITS);
9ae3a8
+                                SCSI_INQUIRY_PAGECODE_BLOCK_LIMITS, errp);
9ae3a8
         if (task == NULL) {
9ae3a8
             ret = -EINVAL;
9ae3a8
             goto out;
9ae3a8
         }
9ae3a8
         inq_bl = scsi_datain_unmarshall(task);
9ae3a8
         if (inq_bl == NULL) {
9ae3a8
-            error_report("iSCSI: failed to unmarshall inquiry datain blob");
9ae3a8
+            error_setg(errp, "iSCSI: failed to unmarshall inquiry datain blob");
9ae3a8
             ret = -EINVAL;
9ae3a8
             goto out;
9ae3a8
         }
9ae3a8
@@ -1529,14 +1530,16 @@ static int iscsi_reopen_prepare(BDRVReopenState *state,
9ae3a8
 static int iscsi_truncate(BlockDriverState *bs, int64_t offset)
9ae3a8
 {
9ae3a8
     IscsiLun *iscsilun = bs->opaque;
9ae3a8
-    int ret = 0;
9ae3a8
+    Error *local_err = NULL;
9ae3a8
 
9ae3a8
     if (iscsilun->type != TYPE_DISK) {
9ae3a8
         return -ENOTSUP;
9ae3a8
     }
9ae3a8
 
9ae3a8
-    if ((ret = iscsi_readcapacity_sync(iscsilun)) != 0) {
9ae3a8
-        return ret;
9ae3a8
+    iscsi_readcapacity_sync(iscsilun, &local_err);
9ae3a8
+    if (local_err != NULL) {
9ae3a8
+        error_free(local_err);
9ae3a8
+        return -EIO;
9ae3a8
     }
9ae3a8
 
9ae3a8
     if (offset > iscsi_getlength(bs)) {
9ae3a8
-- 
9ae3a8
1.7.1
9ae3a8