From patchwork Mon Dec 3 22:44:33 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Roth X-Patchwork-Id: 203475 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id CA7322C00A8 for ; Tue, 4 Dec 2012 09:50:39 +1100 (EST) Received: from localhost ([::1]:52804 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TfeqT-0002DZ-JY for incoming@patchwork.ozlabs.org; Mon, 03 Dec 2012 17:50:37 -0500 Received: from eggs.gnu.org ([208.118.235.92]:56374) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Tfeq6-0002Az-Nd for qemu-devel@nongnu.org; Mon, 03 Dec 2012 17:50:16 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Tfeq3-0003t1-Pm for qemu-devel@nongnu.org; Mon, 03 Dec 2012 17:50:14 -0500 Received: from mail-ie0-f173.google.com ([209.85.223.173]:36741) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Tfepy-0003k8-14; Mon, 03 Dec 2012 17:50:06 -0500 Received: by mail-ie0-f173.google.com with SMTP id e13so4925101iej.4 for ; Mon, 03 Dec 2012 14:50:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references; bh=InBKDiPeT4x0LRxj3lIK1T2BmQf0XauuYMzY8776Aww=; b=So06RYa3zJvL9ZVQXARK5/9WK26y/aYmhPzL9JiAxziKYwyZT7/1ji7N1nIomqp7Lt fJ5HaSNZLGyMLTSQVZvsbVnpXlXXImxIeFPQRMn2Kp+rUHvNbscHFuW5n0W9thh2RZI8 VPLj6Eb2is7lEl8n59siycwgHiYkpg4gtgmf+aSZA3nARef7yKlB5PQ6Cvy2QY7oEa/1 GPCQXVlwk5uAH1jPMH8fa1PT6xJhBMQ/Rbl3CkKetL/IitAuxYoAEX4X2q8MA8jhjqdP NMQZA+ah2gus19O1YBXwnQEnLNmsFTgsgYUvbrP9/IvOphf3VCEYrVeOo2CmF821qiGu Brug== Received: by 10.43.83.1 with SMTP id ae1mr9466603icc.24.1354575004361; Mon, 03 Dec 2012 14:50:04 -0800 (PST) Received: from localhost ([32.97.110.59]) by mx.google.com with ESMTPS id ez8sm8920663igb.17.2012.12.03.14.50.03 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 03 Dec 2012 14:50:03 -0800 (PST) From: Michael Roth To: qemu-stable@nongnu.org Date: Mon, 3 Dec 2012 16:44:33 -0600 Message-Id: <1354574681-28954-4-git-send-email-mdroth@linux.vnet.ibm.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1354572547-21271-1-git-send-email-mdroth@linux.vnet.ibm.com> References: <1354572547-21271-1-git-send-email-mdroth@linux.vnet.ibm.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 209.85.223.173 Cc: aliguori@us.ibm.com, qemu-devel@nongnu.org Subject: [Qemu-devel] [PATCH 36/43] iscsi: fix deadlock during login X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: Peter Lieven 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 Signed-off-by: Paolo Bonzini (cherry picked from commit e829b0bb054ed3389e5b22dad61875e51674e629) Signed-off-by: Michael Roth --- 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) {