qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Michael Roth <mdroth@linux.vnet.ibm.com>
To: qemu-stable@nongnu.org
Cc: aliguori@us.ibm.com, qemu-devel@nongnu.org
Subject: [Qemu-devel] [PATCH 36/43] iscsi: fix deadlock during login
Date: Mon,  3 Dec 2012 16:44:33 -0600	[thread overview]
Message-ID: <1354574681-28954-4-git-send-email-mdroth@linux.vnet.ibm.com> (raw)
In-Reply-To: <1354572547-21271-1-git-send-email-mdroth@linux.vnet.ibm.com>

From: Peter Lieven <pl@dlhnet.de>

If the connection is interrupted before the first login is successfully
completed qemu-kvm is waiting forever in qemu_aio_wait().

This is fixed by performing an sync login to the target. If the
connection breaks after the first successful login errors are
handled internally by libiscsi.

Signed-off-by: Peter Lieven <pl@kamp.de>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit e829b0bb054ed3389e5b22dad61875e51674e629)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 block/iscsi.c |  251 ++++++++++++++++-----------------------------------------
 1 file changed, 70 insertions(+), 181 deletions(-)

diff --git a/block/iscsi.c b/block/iscsi.c
index 817196a..1836c71 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -65,13 +65,6 @@ typedef struct IscsiAIOCB {
 #endif
 } IscsiAIOCB;
 
-struct IscsiTask {
-    IscsiLun *iscsilun;
-    BlockDriverState *bs;
-    int status;
-    int complete;
-};
-
 static void
 iscsi_bh_cb(void *p)
 {
@@ -384,7 +377,7 @@ iscsi_aio_readv(BlockDriverState *bs, int64_t sector_num,
         *(uint16_t *)&acb->task->cdb[7] = htons(num_sectors);
         break;
     }
-    
+
     if (iscsi_scsi_command_async(iscsi, iscsilun->lun, acb->task,
                                  iscsi_aio_read16_cb,
                                  NULL,
@@ -669,163 +662,6 @@ iscsi_getlength(BlockDriverState *bs)
     return len;
 }
 
-static void
-iscsi_readcapacity16_cb(struct iscsi_context *iscsi, int status,
-                        void *command_data, void *opaque)
-{
-    struct IscsiTask *itask = opaque;
-    struct scsi_readcapacity16 *rc16;
-    struct scsi_task *task = command_data;
-
-    if (status != 0) {
-        error_report("iSCSI: Failed to read capacity of iSCSI lun. %s",
-                     iscsi_get_error(iscsi));
-        itask->status   = 1;
-        itask->complete = 1;
-        scsi_free_scsi_task(task);
-        return;
-    }
-
-    rc16 = scsi_datain_unmarshall(task);
-    if (rc16 == NULL) {
-        error_report("iSCSI: Failed to unmarshall readcapacity16 data.");
-        itask->status   = 1;
-        itask->complete = 1;
-        scsi_free_scsi_task(task);
-        return;
-    }
-
-    itask->iscsilun->block_size = rc16->block_length;
-    itask->iscsilun->num_blocks = rc16->returned_lba + 1;
-    itask->bs->total_sectors    = itask->iscsilun->num_blocks *
-                               itask->iscsilun->block_size / BDRV_SECTOR_SIZE ;
-
-    itask->status   = 0;
-    itask->complete = 1;
-    scsi_free_scsi_task(task);
-}
-
-static void
-iscsi_readcapacity10_cb(struct iscsi_context *iscsi, int status,
-                        void *command_data, void *opaque)
-{
-    struct IscsiTask *itask = opaque;
-    struct scsi_readcapacity10 *rc10;
-    struct scsi_task *task = command_data;
-
-    if (status != 0) {
-        error_report("iSCSI: Failed to read capacity of iSCSI lun. %s",
-                     iscsi_get_error(iscsi));
-        itask->status   = 1;
-        itask->complete = 1;
-        scsi_free_scsi_task(task);
-        return;
-    }
-
-    rc10 = scsi_datain_unmarshall(task);
-    if (rc10 == NULL) {
-        error_report("iSCSI: Failed to unmarshall readcapacity10 data.");
-        itask->status   = 1;
-        itask->complete = 1;
-        scsi_free_scsi_task(task);
-        return;
-    }
-
-    itask->iscsilun->block_size = rc10->block_size;
-    if (rc10->lba == 0) {
-        /* blank disk loaded */
-        itask->iscsilun->num_blocks = 0;
-    } else {
-        itask->iscsilun->num_blocks = rc10->lba + 1;
-    }
-    itask->bs->total_sectors    = itask->iscsilun->num_blocks *
-                               itask->iscsilun->block_size / BDRV_SECTOR_SIZE ;
-
-    itask->status   = 0;
-    itask->complete = 1;
-    scsi_free_scsi_task(task);
-}
-
-static void
-iscsi_inquiry_cb(struct iscsi_context *iscsi, int status, void *command_data,
-                 void *opaque)
-{
-    struct IscsiTask *itask = opaque;
-    struct scsi_task *task = command_data;
-    struct scsi_inquiry_standard *inq;
-
-    if (status != 0) {
-        itask->status   = 1;
-        itask->complete = 1;
-        scsi_free_scsi_task(task);
-        return;
-    }
-
-    inq = scsi_datain_unmarshall(task);
-    if (inq == NULL) {
-        error_report("iSCSI: Failed to unmarshall inquiry data.");
-        itask->status   = 1;
-        itask->complete = 1;
-        scsi_free_scsi_task(task);
-        return;
-    }
-
-    itask->iscsilun->type = inq->periperal_device_type;
-
-    scsi_free_scsi_task(task);
-
-    switch (itask->iscsilun->type) {
-    case TYPE_DISK:
-        task = iscsi_readcapacity16_task(iscsi, itask->iscsilun->lun,
-                                   iscsi_readcapacity16_cb, opaque);
-        if (task == NULL) {
-            error_report("iSCSI: failed to send readcapacity16 command.");
-            itask->status   = 1;
-            itask->complete = 1;
-            return;
-        }
-        break;
-    case TYPE_ROM:
-        task = iscsi_readcapacity10_task(iscsi, itask->iscsilun->lun,
-                                   0, 0,
-                                   iscsi_readcapacity10_cb, opaque);
-        if (task == NULL) {
-            error_report("iSCSI: failed to send readcapacity16 command.");
-            itask->status   = 1;
-            itask->complete = 1;
-            return;
-        }
-        break;
-    default:
-        itask->status   = 0;
-        itask->complete = 1;
-    }
-}
-
-static void
-iscsi_connect_cb(struct iscsi_context *iscsi, int status, void *command_data,
-                 void *opaque)
-{
-    struct IscsiTask *itask = opaque;
-    struct scsi_task *task;
-
-    if (status != 0) {
-        itask->status   = 1;
-        itask->complete = 1;
-        return;
-    }
-
-    task = iscsi_inquiry_task(iscsi, itask->iscsilun->lun,
-                              0, 0, 36,
-                              iscsi_inquiry_cb, opaque);
-    if (task == NULL) {
-        error_report("iSCSI: failed to send inquiry command.");
-        itask->status   = 1;
-        itask->complete = 1;
-        return;
-    }
-}
-
 static int parse_chap(struct iscsi_context *iscsi, const char *target)
 {
     QemuOptsList *list;
@@ -938,7 +774,10 @@ static int iscsi_open(BlockDriverState *bs, const char *filename, int flags)
     IscsiLun *iscsilun = bs->opaque;
     struct iscsi_context *iscsi = NULL;
     struct iscsi_url *iscsi_url = NULL;
-    struct IscsiTask task;
+    struct scsi_task *task = NULL;
+    struct scsi_inquiry_standard *inq = NULL;
+    struct scsi_readcapacity10 *rc10 = NULL;
+    struct scsi_readcapacity16 *rc16 = NULL;
     char *initiator_name = NULL;
     int ret;
 
@@ -1001,33 +840,80 @@ static int iscsi_open(BlockDriverState *bs, const char *filename, int flags)
     /* check if we got HEADER_DIGEST via the options */
     parse_header_digest(iscsi, iscsi_url->target);
 
-    task.iscsilun = iscsilun;
-    task.status = 0;
-    task.complete = 0;
-    task.bs = bs;
+    if (iscsi_full_connect_sync(iscsi, iscsi_url->portal, iscsi_url->lun) != 0) {
+        error_report("iSCSI: Failed to connect to LUN : %s",
+            iscsi_get_error(iscsi));
+        ret = -EINVAL;
+        goto out;
+    }
 
     iscsilun->iscsi = iscsi;
     iscsilun->lun   = iscsi_url->lun;
 
-    if (iscsi_full_connect_async(iscsi, iscsi_url->portal, iscsi_url->lun,
-                                 iscsi_connect_cb, &task)
-        != 0) {
-        error_report("iSCSI: Failed to start async connect.");
+    task = iscsi_inquiry_sync(iscsi, iscsilun->lun, 0, 0, 36);
+
+    if (task == NULL || task->status != SCSI_STATUS_GOOD) {
+        error_report("iSCSI: failed to send inquiry command.");
         ret = -EINVAL;
         goto out;
     }
 
-    while (!task.complete) {
-        iscsi_set_events(iscsilun);
-        qemu_aio_wait();
-    }
-    if (task.status != 0) {
-        error_report("iSCSI: Failed to connect to LUN : %s",
-                     iscsi_get_error(iscsi));
+    inq = scsi_datain_unmarshall(task);
+    if (inq == NULL) {
+        error_report("iSCSI: Failed to unmarshall inquiry data.");
         ret = -EINVAL;
         goto out;
     }
 
+    iscsilun->type = inq->periperal_device_type;
+
+    scsi_free_scsi_task(task);
+
+    switch (iscsilun->type) {
+    case TYPE_DISK:
+        task = iscsi_readcapacity16_sync(iscsi, iscsilun->lun);
+        if (task == NULL || task->status != SCSI_STATUS_GOOD) {
+            error_report("iSCSI: failed to send readcapacity16 command.");
+            ret = -EINVAL;
+            goto out;
+        }
+        rc16 = scsi_datain_unmarshall(task);
+        if (rc16 == NULL) {
+            error_report("iSCSI: Failed to unmarshall readcapacity16 data.");
+            ret = -EINVAL;
+            goto out;
+        }
+        iscsilun->block_size = rc16->block_length;
+        iscsilun->num_blocks = rc16->returned_lba + 1;
+        break;
+    case TYPE_ROM:
+        task = iscsi_readcapacity10_sync(iscsi, iscsilun->lun, 0, 0);
+        if (task == NULL || task->status != SCSI_STATUS_GOOD) {
+            error_report("iSCSI: failed to send readcapacity10 command.");
+            ret = -EINVAL;
+            goto out;
+        }
+        rc10 = scsi_datain_unmarshall(task);
+        if (rc10 == NULL) {
+            error_report("iSCSI: Failed to unmarshall readcapacity10 data.");
+            ret = -EINVAL;
+            goto out;
+        }
+        iscsilun->block_size = rc10->block_size;
+        if (rc10->lba == 0) {
+            /* blank disk loaded */
+            iscsilun->num_blocks = 0;
+        } else {
+            iscsilun->num_blocks = rc10->lba + 1;
+        }
+        break;
+    default:
+        break;
+    }
+
+    bs->total_sectors    = iscsilun->num_blocks *
+                           iscsilun->block_size / BDRV_SECTOR_SIZE ;
+
     /* Medium changer or tape. We dont have any emulation for this so this must
      * be sg ioctl compatible. We force it to be sg, otherwise qemu will try
      * to read from the device to guess the image format.
@@ -1046,6 +932,9 @@ out:
     if (iscsi_url != NULL) {
         iscsi_destroy_url(iscsi_url);
     }
+    if (task != NULL) {
+        scsi_free_scsi_task(task);
+    }
 
     if (ret) {
         if (iscsi != NULL) {
-- 
1.7.9.5

  parent reply	other threads:[~2012-12-03 22:50 UTC|newest]

Thread overview: 45+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-12-03 22:08 [Qemu-devel] Patch Round-up for stable 1.2.2, freeze Wednesday Michael Roth
2012-12-03 22:08 ` [Qemu-devel] [PATCH 01/43] configure: Fix CONFIG_QEMU_HELPERDIR generation Michael Roth
2012-12-03 22:08 ` [Qemu-devel] [PATCH 02/43] fix CONFIG_QEMU_HELPERDIR generation again Michael Roth
2012-12-03 22:08 ` [Qemu-devel] [PATCH 03/43] ui/vnc: Only report/use TIGHT_PNG encoding if enabled Michael Roth
2012-12-03 22:08 ` [Qemu-devel] [PATCH 04/43] vnc: fix "info vnc" with "-vnc ..., reverse=on" Michael Roth
2012-12-03 22:08 ` [Qemu-devel] [PATCH 05/43] uhci: Raise interrupt when requested even for non active tds Michael Roth
2012-12-03 22:08 ` [Qemu-devel] [PATCH 06/43] hw/qxl: qxl_dirty_surfaces: use uintptr_t Michael Roth
2012-12-03 22:08 ` [Qemu-devel] [PATCH 07/43] qxl: always update displaysurface on resize Michael Roth
2012-12-03 22:08 ` [Qemu-devel] [PATCH 08/43] rtc: fix overflow in mktimegm Michael Roth
2012-12-03 22:08 ` [Qemu-devel] [PATCH 09/43] hw: Fix return value check for bdrv_read, bdrv_write Michael Roth
2012-12-03 22:08 ` [Qemu-devel] [PATCH 10/43] target-i386: Allow tsc-frequency to be larger then 2.147G Michael Roth
2012-12-03 22:08 ` [Qemu-devel] [PATCH 11/43] e1000: drop check_rxov, always treat RX ring with RDH == RDT as empty Michael Roth
2012-12-03 22:08 ` [Qemu-devel] [PATCH 12/43] memory: fix rendering of a region obscured by another Michael Roth
2012-12-03 22:08 ` [Qemu-devel] [PATCH 13/43] s390x: fix -initrd in virtio machine Michael Roth
2012-12-03 22:08 ` [Qemu-devel] [PATCH 14/43] PPC: Bamboo: Fix memory size DT property Michael Roth
2012-12-03 22:08 ` [Qemu-devel] [PATCH 15/43] target-sparc64: disable VGA cirrus Michael Roth
2012-12-03 22:08 ` [Qemu-devel] [PATCH 16/43] xhci: fix usb name in caps Michael Roth
2012-12-03 22:08 ` [Qemu-devel] [PATCH 17/43] tools: initialize main loop before block layer Michael Roth
2012-12-03 22:08 ` [Qemu-devel] [PATCH 18/43] m68k: Return semihosting errno values correctly Michael Roth
2012-12-03 22:08 ` [Qemu-devel] [PATCH 19/43] nbd: fixes to read-only handling Michael Roth
2012-12-03 22:08 ` [Qemu-devel] [PATCH 20/43] mips/malta: fix CBUS UART interrupt pin Michael Roth
2012-12-03 22:08 ` [Qemu-devel] [PATCH 21/43] target-mips: fix wrong microMIPS opcode encoding Michael Roth
2012-12-03 22:08 ` [Qemu-devel] [PATCH 22/43] tcg/arm: fix TLB access in qemu-ld/st ops Michael Roth
2013-01-17 16:55   ` Peter Maydell
2012-12-03 22:08 ` [Qemu-devel] [PATCH 23/43] tcg/arm: fix cross-endian qemu_st16 Michael Roth
2012-12-03 22:08 ` [Qemu-devel] [PATCH 24/43] target-openrisc: remove conflicting definitions from cpu.h Michael Roth
2012-12-03 22:08 ` [Qemu-devel] [PATCH 25/43] configure: avoid compiler warning in pipe2 detection Michael Roth
2012-12-03 22:08 ` [Qemu-devel] [PATCH 26/43] qcow2: Fix refcount table size calculation Michael Roth
2012-12-03 22:08 ` [Qemu-devel] [PATCH 27/43] tci: Fix type of tci_read_label Michael Roth
2012-12-03 22:25 ` [Qemu-devel] [PATCH 28/43] block: Fix regression for MinGW (assertion caused by short string) Michael Roth
2012-12-03 22:25   ` [Qemu-devel] [PATCH 29/43] qom: dynamic_cast of NULL is always NULL Michael Roth
2012-12-03 22:25   ` [Qemu-devel] [PATCH 30/43] hmp: do not crash on invalid SCSI hotplug Michael Roth
2012-12-03 22:25   ` [Qemu-devel] [PATCH 31/43] PPC: Fix missing TRACE exception Michael Roth
2012-12-03 22:25   ` [Qemu-devel] [PATCH 32/43] qom: fix refcount of non-heap-allocated objects Michael Roth
2012-12-03 22:44 ` [Qemu-devel] [PATCH 33/43] qapi: handle visitor->type_size() in QapiDeallocVisitor Michael Roth
2012-12-03 22:44 ` [Qemu-devel] [PATCH 34/43] qapi: fix qapi_dealloc_type_size parameter type Michael Roth
2012-12-03 22:44 ` [Qemu-devel] [PATCH 35/43] iscsi: fix segfault in url parsing Michael Roth
2012-12-03 22:44 ` Michael Roth [this message]
2012-12-03 22:44 ` [Qemu-devel] [PATCH 37/43] iscsi: do not assume device is zero initialized Michael Roth
2012-12-03 22:44 ` [Qemu-devel] [PATCH 38/43] virtio-scsi: Fix some endian bugs with virtio-scsi Michael Roth
2012-12-03 22:44 ` [Qemu-devel] [PATCH 39/43] virtio-scsi: Fix subtle (guest) endian bug Michael Roth
2012-12-03 22:44 ` [Qemu-devel] [PATCH 40/43] qxl: reload memslots after migration, when qxl is in UNDEFINED mode Michael Roth
2012-12-03 22:44 ` [Qemu-devel] [PATCH 41/43] usb: fail usbdevice_create() when there is no USB bus Michael Roth
2012-12-03 22:44 ` [Qemu-devel] [PATCH 42/43] stream: fix ratelimit_set_speed Michael Roth
2012-12-03 22:44 ` [Qemu-devel] [PATCH 43/43] e1000: Discard packets that are too long if !SBP and !LPE Michael Roth

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1354574681-28954-4-git-send-email-mdroth@linux.vnet.ibm.com \
    --to=mdroth@linux.vnet.ibm.com \
    --cc=aliguori@us.ibm.com \
    --cc=qemu-devel@nongnu.org \
    --cc=qemu-stable@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).