From patchwork Wed Mar 23 10:26:30 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Denis V. Lunev" X-Patchwork-Id: 8648931 Return-Path: X-Original-To: patchwork-qemu-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 9AB549F38C for ; Wed, 23 Mar 2016 10:28:38 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id E8534203B1 for ; Wed, 23 Mar 2016 10:28:37 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 236F5203AC for ; Wed, 23 Mar 2016 10:28:37 +0000 (UTC) Received: from localhost ([::1]:42443 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aig1k-0007c7-IQ for patchwork-qemu-devel@patchwork.kernel.org; Wed, 23 Mar 2016 06:28:36 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:37279) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aig0C-0004yO-Lt for qemu-devel@nongnu.org; Wed, 23 Mar 2016 06:27:02 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1aig09-00009j-Ct for qemu-devel@nongnu.org; Wed, 23 Mar 2016 06:27:00 -0400 Received: from mailhub.sw.ru ([195.214.232.25]:3861 helo=relay.sw.ru) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aig08-00006X-W6 for qemu-devel@nongnu.org; Wed, 23 Mar 2016 06:26:57 -0400 Received: from irbis.sw.ru ([10.30.2.139]) by relay.sw.ru (8.13.4/8.13.4) with ESMTP id u2NAQbng021776; Wed, 23 Mar 2016 13:26:40 +0300 (MSK) From: "Denis V. Lunev" To: qemu-devel@nongnu.org Date: Wed, 23 Mar 2016 13:26:30 +0300 Message-Id: <1458728792-15779-2-git-send-email-den@openvz.org> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1458728792-15779-1-git-send-email-den@openvz.org> References: <1458728792-15779-1-git-send-email-den@openvz.org> X-detected-operating-system: by eggs.gnu.org: OpenBSD 3.x X-Received-From: 195.214.232.25 Cc: den@openvz.org, John Snow , Pavel Butsykin Subject: [Qemu-devel] [PATCH 1/3] ide: don't loose pending dma state 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+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Pavel Butsykin If the migration occurs after the IDE DMA has been set up but before it has been initiated, the state gets lost upon save/restore. Specifically, ->dma_cb callback gets cleared, so, when the guest eventually starts bus mastering, the DMA never completes, causing the guest to time out the operation. OTOH all the infrastructure is already in place to restart the DMA if the migration happens while the DMA is in progress. So reuse that infrastructure, by calling the DMA callback with an artificial error code in pre_save if the callback is already set but DMAING is clear. The callback then sets bus->error_status to indicate the need for restart; however since DMAING is clear the state upon restore will be exactly "ready forDMA" as before the save. This patch only fixes the IDE DMA case; the ATAPI DMA is left with a stub for now since its restart hadn't been implemented yet. It will be addressed in the followup patch. Signed-off-by: Pavel Butsykin Reviewed-by: Roman Kagan Signed-off-by: Denis V. Lunev CC: John Snow Reviewed-by: John Snow --- hw/ide/atapi.c | 9 ++++++++- hw/ide/core.c | 9 ++++++++- hw/ide/internal.h | 7 +++++++ hw/ide/pci.c | 3 +++ 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c index 1fe58ab..268220d 100644 --- a/hw/ide/atapi.c +++ b/hw/ide/atapi.c @@ -381,7 +381,14 @@ static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret) IDEState *s = opaque; int data_offset, n; - if (ret < 0) { + if (ret < 0) { /* XXX: handle -ESTATESAVE for migration */ + if (ret == -ESTATESAVE) { + /* + * This case is not really an error + * but a request to save the state. + */ + return; + } ide_atapi_io_error(s, ret); goto eot; } diff --git a/hw/ide/core.c b/hw/ide/core.c index 241e840..872e11f 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -810,7 +810,14 @@ static void ide_dma_cb(void *opaque, int ret) else if (s->dma_cmd == IDE_DMA_TRIM) op |= IDE_RETRY_TRIM; - if (ide_handle_rw_error(s, -ret, op)) { + if (ret == -ESTATESAVE) { + /* + * This case is not really an error + * but a request to save the state. + */ + s->bus->error_status = op; + return; + } else if (ide_handle_rw_error(s, -ret, op)) { return; } } diff --git a/hw/ide/internal.h b/hw/ide/internal.h index 86bde26..dcd8627 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -513,6 +513,13 @@ struct IDEDevice { #define IDE_RETRY_TRIM 0x80 #define IDE_RETRY_HBA 0x100 +/* + * a code to trigger entering error path and save/restore the "ready to DMA" + * state just like DMA-ing state. (Ab)use EINPROGRESS as it's not supposed to + * come from the block layer + */ +#define ESTATESAVE EINPROGRESS + static inline IDEState *idebus_active_if(IDEBus *bus) { return bus->ifs + bus->unit; diff --git a/hw/ide/pci.c b/hw/ide/pci.c index 92ffee7..e1f89fa 100644 --- a/hw/ide/pci.c +++ b/hw/ide/pci.c @@ -308,6 +308,9 @@ static void ide_bmdma_pre_save(void *opaque) BMDMAState *bm = opaque; uint8_t abused_bits = BM_MIGRATION_COMPAT_STATUS_BITS; + if (!(bm->status & BM_STATUS_DMAING) && bm->dma_cb) { + bm->dma_cb(bmdma_active_if(bm), -ESTATESAVE); + } bm->migration_retry_unit = bm->bus->retry_unit; bm->migration_retry_sector_num = bm->bus->retry_sector_num; bm->migration_retry_nsector = bm->bus->retry_nsector;