From patchwork Thu Mar 29 09:31:30 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Hajnoczi X-Patchwork-Id: 149380 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 B1627B6FA2 for ; Thu, 29 Mar 2012 20:32:11 +1100 (EST) Received: from localhost ([::1]:57932 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SDBiC-0000dU-Sw for incoming@patchwork.ozlabs.org; Thu, 29 Mar 2012 05:32:08 -0400 Received: from eggs.gnu.org ([208.118.235.92]:53279) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SDBhv-0000bK-Kf for qemu-devel@nongnu.org; Thu, 29 Mar 2012 05:31:54 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1SDBhq-0004cl-0w for qemu-devel@nongnu.org; Thu, 29 Mar 2012 05:31:51 -0400 Received: from e06smtp13.uk.ibm.com ([195.75.94.109]:58663) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SDBhp-0004bS-OA for qemu-devel@nongnu.org; Thu, 29 Mar 2012 05:31:45 -0400 Received: from /spool/local by e06smtp13.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Thu, 29 Mar 2012 10:31:41 +0100 Received: from d06nrmr1307.portsmouth.uk.ibm.com (9.149.38.129) by e06smtp13.uk.ibm.com (192.168.101.143) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Thu, 29 Mar 2012 10:31:36 +0100 Received: from d06av06.portsmouth.uk.ibm.com (d06av06.portsmouth.uk.ibm.com [9.149.37.217]) by d06nrmr1307.portsmouth.uk.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id q2T9VZlW2826292 for ; Thu, 29 Mar 2012 10:31:35 +0100 Received: from d06av06.portsmouth.uk.ibm.com (loopback [127.0.0.1]) by d06av06.portsmouth.uk.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id q2T9VYSO025675 for ; Thu, 29 Mar 2012 03:31:35 -0600 Received: from localhost (dyn-9-174-218-67.manchester-maybrook.uk.ibm.com [9.174.218.67]) by d06av06.portsmouth.uk.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with ESMTP id q2T9VYKd025657; Thu, 29 Mar 2012 03:31:34 -0600 From: Stefan Hajnoczi To: Date: Thu, 29 Mar 2012 10:31:30 +0100 Message-Id: <1333013491-24749-2-git-send-email-stefanha@linux.vnet.ibm.com> X-Mailer: git-send-email 1.7.9.1 In-Reply-To: <1333013491-24749-1-git-send-email-stefanha@linux.vnet.ibm.com> References: <1333013491-24749-1-git-send-email-stefanha@linux.vnet.ibm.com> x-cbid: 12032909-2966-0000-0000-000003A6441A X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 195.75.94.109 Cc: Kevin Wolf , Richard Davies , Chris Webb , Stefan Hajnoczi , Michael Tokarev , Zhi Yong Wu , Paolo Bonzini Subject: [Qemu-devel] [PATCH v2 1/2] ide: convert ide_sector_read() to asynchronous I/O 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 The IDE PIO interface currently uses bdrv_read() to perform reads synchronously. Synchronous I/O in the vcpu thread is bad because it prevents the guest from executing code - it makes the guest unresponsive. This patch converts IDE PIO to use bdrv_aio_readv(). We simply need to use the BUSY_STAT status so the guest knows to wait while we are busy. The only external user of ide_sector_read() is restart behavior on I/O errors and it is not affected by this change. We still need to restart I/O in the same way. Migration is also unaffected if I understand the code correctly. We continue to use the same transfer function and the BUSY_STAT status should never be migrated since we flush I/O before migrating device state. Signed-off-by: Stefan Hajnoczi --- hw/ide/core.c | 76 ++++++++++++++++++++++++++++++++++++++-------------- hw/ide/internal.h | 3 ++ 2 files changed, 58 insertions(+), 21 deletions(-) diff --git a/hw/ide/core.c b/hw/ide/core.c index 4d568ac..47bc958 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -457,40 +457,68 @@ static void ide_rw_error(IDEState *s) { ide_set_irq(s->bus); } +static void ide_sector_read_cb(void *opaque, int ret) +{ + IDEState *s = opaque; + int n; + + s->pio_aiocb = NULL; + s->status &= ~BUSY_STAT; + + bdrv_acct_done(s->bs, &s->acct); + if (ret != 0) { + if (ide_handle_rw_error(s, -ret, BM_STATUS_PIO_RETRY | + BM_STATUS_RETRY_READ)) { + return; + } + } + + n = s->nsector; + if (n > s->req_nb_sectors) { + n = s->req_nb_sectors; + } + + /* Allow the guest to read the io_buffer */ + ide_transfer_start(s, s->io_buffer, n * BDRV_SECTOR_SIZE, ide_sector_read); + + ide_set_irq(s->bus); + + ide_set_sector(s, ide_get_sector(s) + n); + s->nsector -= n; +} + void ide_sector_read(IDEState *s) { int64_t sector_num; - int ret, n; + int n; s->status = READY_STAT | SEEK_STAT; s->error = 0; /* not needed by IDE spec, but needed by Windows */ sector_num = ide_get_sector(s); n = s->nsector; + if (n == 0) { - /* no more sector to read from disk */ ide_transfer_stop(s); - } else { + return; + } + + s->status |= BUSY_STAT; + + if (n > s->req_nb_sectors) { + n = s->req_nb_sectors; + } + #if defined(DEBUG_IDE) - printf("read sector=%" PRId64 "\n", sector_num); + printf("sector=%" PRId64 "\n", sector_num); #endif - if (n > s->req_nb_sectors) - n = s->req_nb_sectors; - bdrv_acct_start(s->bs, &s->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_READ); - ret = bdrv_read(s->bs, sector_num, s->io_buffer, n); - bdrv_acct_done(s->bs, &s->acct); - if (ret != 0) { - if (ide_handle_rw_error(s, -ret, - BM_STATUS_PIO_RETRY | BM_STATUS_RETRY_READ)) - { - return; - } - } - ide_transfer_start(s, s->io_buffer, 512 * n, ide_sector_read); - ide_set_irq(s->bus); - ide_set_sector(s, sector_num + n); - s->nsector -= n; - } + s->iov.iov_base = s->io_buffer; + s->iov.iov_len = n * BDRV_SECTOR_SIZE; + qemu_iovec_init_external(&s->qiov, &s->iov, 1); + + bdrv_acct_start(s->bs, &s->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_READ); + s->pio_aiocb = bdrv_aio_readv(s->bs, sector_num, &s->qiov, n, + ide_sector_read_cb, s); } static void dma_buf_commit(IDEState *s) @@ -1750,6 +1778,12 @@ static void ide_reset(IDEState *s) #ifdef DEBUG_IDE printf("ide: reset\n"); #endif + + if (s->pio_aiocb) { + bdrv_aio_cancel(s->pio_aiocb); + s->pio_aiocb = NULL; + } + if (s->drive_kind == IDE_CFATA) s->mult_sectors = 0; else diff --git a/hw/ide/internal.h b/hw/ide/internal.h index c808a0d..8f9259b 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -383,6 +383,9 @@ struct IDEState { int cd_sector_size; int atapi_dma; /* true if dma is requested for the packet cmd */ BlockAcctCookie acct; + BlockDriverAIOCB *pio_aiocb; + struct iovec iov; + QEMUIOVector qiov; /* ATA DMA state */ int io_buffer_size; QEMUSGList sg;