From patchwork Mon Jan 14 13:51:30 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anthony PERARD X-Patchwork-Id: 10762721 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D9F7F14E5 for ; Mon, 14 Jan 2019 14:11:40 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C96B928D31 for ; Mon, 14 Jan 2019 14:11:40 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id BD7D928CEC; Mon, 14 Jan 2019 14:11:40 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 6766F28D2F for ; Mon, 14 Jan 2019 14:11:40 +0000 (UTC) Received: from localhost ([127.0.0.1]:35387 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gj2xn-00086x-KA for patchwork-qemu-devel@patchwork.kernel.org; Mon, 14 Jan 2019 09:11:39 -0500 Received: from eggs.gnu.org ([209.51.188.92]:45938) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gj2j1-0004hh-QD for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:56:24 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gj2et-0002OO-ED for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:52:09 -0500 Received: from smtp03.citrix.com ([162.221.156.55]:65429) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gj2et-0002N4-6M for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:52:07 -0500 X-IronPort-AV: E=Sophos;i="5.56,477,1539648000"; d="scan'208";a="75506436" From: Anthony PERARD To: Date: Mon, 14 Jan 2019 13:51:30 +0000 Message-ID: <20190114135154.16826-2-anthony.perard@citrix.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190114135154.16826-1-anthony.perard@citrix.com> References: <20190114135154.16826-1-anthony.perard@citrix.com> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 162.221.156.55 Subject: [Qemu-devel] [PULL 01/25] hw/xen/xen_pt_graphics: Don't trust the BIOS ROM contents so much X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Anthony PERARD , xen-devel@lists.xenproject.org, Peter Maydell Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Peter Maydell Coverity (CID 796599) points out that xen_pt_setup_vga() trusts the rom->size field in the BIOS ROM from a PCI passthrough VGA device, and uses it as an index into the memory which contains the BIOS image. A corrupt BIOS ROM could therefore cause us to index off the end of the buffer. Check that the size is within bounds before we use it. We are also trusting the pcioffset field, and assuming that the whole rom_header is present; Coverity doesn't notice these, but check them too. Signed-off-by: Peter Maydell Acked-by: Anthony PERARD Signed-off-by: Anthony PERARD --- hw/xen/xen_pt_graphics.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/hw/xen/xen_pt_graphics.c b/hw/xen/xen_pt_graphics.c index 135c8df1e7..60d6b4a556 100644 --- a/hw/xen/xen_pt_graphics.c +++ b/hw/xen/xen_pt_graphics.c @@ -185,8 +185,19 @@ void xen_pt_setup_vga(XenPCIPassthroughState *s, XenHostPCIDevice *dev, return; } + if (bios_size < sizeof(struct rom_header)) { + error_setg(errp, "VGA: VBIOS image corrupt (too small)"); + return; + } + /* Currently we fixed this address as a primary. */ rom = (struct rom_header *)bios; + + if (rom->pcioffset + sizeof(struct pci_data) > bios_size) { + error_setg(errp, "VGA: VBIOS image corrupt (bad pcioffset field)"); + return; + } + pd = (void *)(bios + (unsigned char)rom->pcioffset); /* We may need to fixup Device Identification. */ @@ -194,6 +205,11 @@ void xen_pt_setup_vga(XenPCIPassthroughState *s, XenHostPCIDevice *dev, pd->device = s->real_device.device_id; len = rom->size * 512; + if (len > bios_size) { + error_setg(errp, "VGA: VBIOS image corrupt (bad size field)"); + return; + } + /* Then adjust the bios checksum */ for (c = (char *)bios; c < ((char *)bios + len); c++) { checksum += *c; From patchwork Mon Jan 14 13:51:31 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Anthony PERARD X-Patchwork-Id: 10762705 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id CF71F6C2 for ; Mon, 14 Jan 2019 14:09:13 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BDB0728A4B for ; Mon, 14 Jan 2019 14:09:13 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B213E28A89; Mon, 14 Jan 2019 14:09:13 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 6291D28A4B for ; Mon, 14 Jan 2019 14:09:13 +0000 (UTC) Received: from localhost ([127.0.0.1]:34758 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gj2vQ-00068b-J3 for patchwork-qemu-devel@patchwork.kernel.org; Mon, 14 Jan 2019 09:09:12 -0500 Received: from eggs.gnu.org ([209.51.188.92]:45938) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gj2j5-0004hh-So for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:56:28 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gj2es-0002Nv-Ch for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:52:07 -0500 Received: from smtp03.citrix.com ([162.221.156.55]:65429) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gj2es-0002N4-5F for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:52:06 -0500 X-IronPort-AV: E=Sophos;i="5.56,477,1539648000"; d="scan'208";a="75506433" From: Anthony PERARD To: Date: Mon, 14 Jan 2019 13:51:31 +0000 Message-ID: <20190114135154.16826-3-anthony.perard@citrix.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190114135154.16826-1-anthony.perard@citrix.com> References: <20190114135154.16826-1-anthony.perard@citrix.com> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 162.221.156.55 Subject: [Qemu-devel] [PULL 02/25] xen/pt: allow passthrough of devices with bogus interrupt pin X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Anthony PERARD , xen-devel@lists.xenproject.org, Peter Maydell Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Zhao Yan For some pci device, even its PCI_INTERRUPT_PIN is not 0, it actually doesn't support INTx mode, so its machine irq read from host sysfs is 0. In that case, report PCI_INTERRUPT_PIN as 0 to guest and let passthrough continue. Reviewed-by: Roger Pau Monné Signed-off-by: Zhao Yan Acked-by: Anthony PERARD Signed-off-by: Anthony PERARD --- hw/xen/xen_pt.c | 6 ++++++ hw/xen/xen_pt_config_init.c | 4 +++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/hw/xen/xen_pt.c b/hw/xen/xen_pt.c index f1f3a3727c..815dc46ba7 100644 --- a/hw/xen/xen_pt.c +++ b/hw/xen/xen_pt.c @@ -847,6 +847,12 @@ static void xen_pt_realize(PCIDevice *d, Error **errp) } machine_irq = s->real_device.irq; + if (machine_irq == 0) { + XEN_PT_LOG(d, "machine irq is 0\n"); + cmd |= PCI_COMMAND_INTX_DISABLE; + goto out; + } + rc = xc_physdev_map_pirq(xen_xc, xen_domid, machine_irq, &pirq); if (rc < 0) { error_setg_errno(errp, errno, "Mapping machine irq %u to" diff --git a/hw/xen/xen_pt_config_init.c b/hw/xen/xen_pt_config_init.c index 47f9010c75..9fd953a689 100644 --- a/hw/xen/xen_pt_config_init.c +++ b/hw/xen/xen_pt_config_init.c @@ -300,7 +300,9 @@ static int xen_pt_irqpin_reg_init(XenPCIPassthroughState *s, XenPTRegInfo *reg, uint32_t real_offset, uint32_t *data) { - *data = xen_pt_pci_read_intx(s); + if (s->real_device.irq) { + *data = xen_pt_pci_read_intx(s); + } return 0; } From patchwork Mon Jan 14 13:51:32 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anthony PERARD X-Patchwork-Id: 10762687 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D1FCC14E5 for ; Mon, 14 Jan 2019 14:05:44 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BA0FE28CA4 for ; Mon, 14 Jan 2019 14:05:44 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id AB45E28CCA; Mon, 14 Jan 2019 14:05:44 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 4D51728CA4 for ; Mon, 14 Jan 2019 14:05:42 +0000 (UTC) Received: from localhost ([127.0.0.1]:34016 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gj2s1-0003eh-Bz for patchwork-qemu-devel@patchwork.kernel.org; Mon, 14 Jan 2019 09:05:41 -0500 Received: from eggs.gnu.org ([209.51.188.92]:45840) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gj2iz-0004go-Vi for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:56:28 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gj2eu-0002Om-0N for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:52:12 -0500 Received: from smtp03.citrix.com ([162.221.156.55]:65429) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gj2et-0002N4-LH for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:52:07 -0500 X-IronPort-AV: E=Sophos;i="5.56,477,1539648000"; d="scan'208";a="75506441" From: Anthony PERARD To: Date: Mon, 14 Jan 2019 13:51:32 +0000 Message-ID: <20190114135154.16826-4-anthony.perard@citrix.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190114135154.16826-1-anthony.perard@citrix.com> References: <20190114135154.16826-1-anthony.perard@citrix.com> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 162.221.156.55 Subject: [Qemu-devel] [PULL 03/25] xen: re-name XenDevice to XenLegacyDevice... X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Anthony PERARD , xen-devel@lists.xenproject.org, Peter Maydell Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Paul Durrant ...and xen_backend.h to xen-legacy-backend.h Rather than attempting to convert the existing backend infrastructure to be QOM compliant (which would be hard to do in an incremental fashion), subsequent patches will introduce a completely new framework for Xen PV backends. Hence it is necessary to re-name parts of existing code to avoid name clashes. The re-named 'legacy' infrastructure will be removed once all backends have been ported to the new framework. This patch is purely cosmetic. No functional change. Signed-off-by: Paul Durrant Acked-by: Anthony Perard Signed-off-by: Anthony PERARD --- hw/9pfs/xen-9p-backend.c | 16 ++-- hw/block/xen_disk.c | 24 +++--- hw/char/xen_console.c | 12 +-- hw/display/xenfb.c | 25 +++--- hw/i386/xen/xen-hvm.c | 2 +- hw/i386/xen/xen-mapcache.c | 2 +- hw/i386/xen/xen_platform.c | 2 +- hw/net/xen_nic.c | 14 ++-- hw/usb/xen-usb.c | 25 +++--- hw/xen/Makefile.objs | 2 +- hw/xen/xen-common.c | 2 +- .../{xen_backend.c => xen-legacy-backend.c} | 79 +++++++++++-------- hw/xen/xen_devconfig.c | 2 +- hw/xen/xen_pt.c | 2 +- hw/xen/xen_pt_config_init.c | 2 +- hw/xen/xen_pt_graphics.c | 2 +- hw/xen/xen_pt_msi.c | 2 +- hw/xen/xen_pvdev.c | 20 ++--- hw/xenpv/xen_domainbuild.c | 2 +- hw/xenpv/xen_machine_pv.c | 2 +- .../{xen_backend.h => xen-legacy-backend.h} | 43 +++++----- include/hw/xen/xen_pvdev.h | 38 ++++----- 22 files changed, 169 insertions(+), 151 deletions(-) rename hw/xen/{xen_backend.c => xen-legacy-backend.c} (89%) rename include/hw/xen/{xen_backend.h => xen-legacy-backend.h} (61%) diff --git a/hw/9pfs/xen-9p-backend.c b/hw/9pfs/xen-9p-backend.c index 9015fe7773..25ab04d95a 100644 --- a/hw/9pfs/xen-9p-backend.c +++ b/hw/9pfs/xen-9p-backend.c @@ -12,7 +12,7 @@ #include "hw/hw.h" #include "hw/9pfs/9p.h" -#include "hw/xen/xen_backend.h" +#include "hw/xen/xen-legacy-backend.h" #include "hw/9pfs/xen-9pfs.h" #include "qapi/error.h" #include "qemu/config-file.h" @@ -45,7 +45,7 @@ typedef struct Xen9pfsRing { } Xen9pfsRing; typedef struct Xen9pfsDev { - struct XenDevice xendev; /* must be first */ + struct XenLegacyDevice xendev; /* must be first */ V9fsState state; char *path; char *security_model; @@ -56,7 +56,7 @@ typedef struct Xen9pfsDev { Xen9pfsRing *rings; } Xen9pfsDev; -static void xen_9pfs_disconnect(struct XenDevice *xendev); +static void xen_9pfs_disconnect(struct XenLegacyDevice *xendev); static void xen_9pfs_in_sg(Xen9pfsRing *ring, struct iovec *in_sg, @@ -243,7 +243,7 @@ static const V9fsTransport xen_9p_transport = { .push_and_notify = xen_9pfs_push_and_notify, }; -static int xen_9pfs_init(struct XenDevice *xendev) +static int xen_9pfs_init(struct XenLegacyDevice *xendev) { return 0; } @@ -305,7 +305,7 @@ static void xen_9pfs_evtchn_event(void *opaque) qemu_bh_schedule(ring->bh); } -static void xen_9pfs_disconnect(struct XenDevice *xendev) +static void xen_9pfs_disconnect(struct XenLegacyDevice *xendev) { Xen9pfsDev *xen_9pdev = container_of(xendev, Xen9pfsDev, xendev); int i; @@ -321,7 +321,7 @@ static void xen_9pfs_disconnect(struct XenDevice *xendev) } } -static int xen_9pfs_free(struct XenDevice *xendev) +static int xen_9pfs_free(struct XenLegacyDevice *xendev) { Xen9pfsDev *xen_9pdev = container_of(xendev, Xen9pfsDev, xendev); int i; @@ -354,7 +354,7 @@ static int xen_9pfs_free(struct XenDevice *xendev) return 0; } -static int xen_9pfs_connect(struct XenDevice *xendev) +static int xen_9pfs_connect(struct XenLegacyDevice *xendev) { Error *err = NULL; int i; @@ -467,7 +467,7 @@ static int xen_9pfs_connect(struct XenDevice *xendev) return -1; } -static void xen_9pfs_alloc(struct XenDevice *xendev) +static void xen_9pfs_alloc(struct XenLegacyDevice *xendev) { xenstore_write_be_str(xendev, "versions", VERSIONS); xenstore_write_be_int(xendev, "max-rings", MAX_RINGS); diff --git a/hw/block/xen_disk.c b/hw/block/xen_disk.c index 2a254b99d0..477dfcca9f 100644 --- a/hw/block/xen_disk.c +++ b/hw/block/xen_disk.c @@ -25,7 +25,7 @@ #include #include "hw/hw.h" -#include "hw/xen/xen_backend.h" +#include "hw/xen/xen-legacy-backend.h" #include "xen_blkif.h" #include "sysemu/blockdev.h" #include "sysemu/iothread.h" @@ -63,7 +63,7 @@ struct ioreq { #define MAX_RING_PAGE_ORDER 4 struct XenBlkDev { - struct XenDevice xendev; /* must be first */ + struct XenLegacyDevice xendev; /* must be first */ char *params; char *mode; char *type; @@ -179,7 +179,7 @@ static void ioreq_release(struct ioreq *ioreq, bool finish) static int ioreq_parse(struct ioreq *ioreq) { struct XenBlkDev *blkdev = ioreq->blkdev; - struct XenDevice *xendev = &blkdev->xendev; + struct XenLegacyDevice *xendev = &blkdev->xendev; size_t len; int i; @@ -243,7 +243,7 @@ static int ioreq_parse(struct ioreq *ioreq) static int ioreq_grant_copy(struct ioreq *ioreq) { struct XenBlkDev *blkdev = ioreq->blkdev; - struct XenDevice *xendev = &blkdev->xendev; + struct XenLegacyDevice *xendev = &blkdev->xendev; XenGrantCopySegment segs[BLKIF_MAX_SEGMENTS_PER_REQUEST]; int i, count, rc; int64_t file_blk = blkdev->file_blk; @@ -289,7 +289,7 @@ static void qemu_aio_complete(void *opaque, int ret) { struct ioreq *ioreq = opaque; struct XenBlkDev *blkdev = ioreq->blkdev; - struct XenDevice *xendev = &blkdev->xendev; + struct XenLegacyDevice *xendev = &blkdev->xendev; aio_context_acquire(blkdev->ctx); @@ -608,7 +608,7 @@ static void blk_bh(void *opaque) aio_context_release(blkdev->ctx); } -static void blk_alloc(struct XenDevice *xendev) +static void blk_alloc(struct XenLegacyDevice *xendev) { struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev); Error *err = NULL; @@ -628,7 +628,7 @@ static void blk_alloc(struct XenDevice *xendev) static void blk_parse_discard(struct XenBlkDev *blkdev) { - struct XenDevice *xendev = &blkdev->xendev; + struct XenLegacyDevice *xendev = &blkdev->xendev; int enable; blkdev->feature_discard = true; @@ -642,7 +642,7 @@ static void blk_parse_discard(struct XenBlkDev *blkdev) } } -static int blk_init(struct XenDevice *xendev) +static int blk_init(struct XenLegacyDevice *xendev) { struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev); int info = 0; @@ -737,7 +737,7 @@ static int blk_init(struct XenDevice *xendev) return -1; } -static int blk_connect(struct XenDevice *xendev) +static int blk_connect(struct XenLegacyDevice *xendev) { struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev); int index, qflags; @@ -941,7 +941,7 @@ static int blk_connect(struct XenDevice *xendev) return 0; } -static void blk_disconnect(struct XenDevice *xendev) +static void blk_disconnect(struct XenLegacyDevice *xendev) { struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev); @@ -966,7 +966,7 @@ static void blk_disconnect(struct XenDevice *xendev) } } -static int blk_free(struct XenDevice *xendev) +static int blk_free(struct XenLegacyDevice *xendev) { struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev); struct ioreq *ioreq; @@ -992,7 +992,7 @@ static int blk_free(struct XenDevice *xendev) return 0; } -static void blk_event(struct XenDevice *xendev) +static void blk_event(struct XenLegacyDevice *xendev) { struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev); diff --git a/hw/char/xen_console.c b/hw/char/xen_console.c index b1a1e66d5a..dc6ff0e5b3 100644 --- a/hw/char/xen_console.c +++ b/hw/char/xen_console.c @@ -26,7 +26,7 @@ #include "qapi/error.h" #include "hw/hw.h" #include "chardev/char-fe.h" -#include "hw/xen/xen_backend.h" +#include "hw/xen/xen-legacy-backend.h" #include @@ -39,7 +39,7 @@ struct buffer { }; struct XenConsole { - struct XenDevice xendev; /* must be first */ + struct XenLegacyDevice xendev; /* must be first */ struct buffer buffer; char console[XEN_BUFSIZE]; int ring_ref; @@ -173,7 +173,7 @@ static void xencons_send(struct XenConsole *con) /* -------------------------------------------------------------------- */ -static int con_init(struct XenDevice *xendev) +static int con_init(struct XenLegacyDevice *xendev) { struct XenConsole *con = container_of(xendev, struct XenConsole, xendev); char *type, *dom, label[32]; @@ -222,7 +222,7 @@ static int con_init(struct XenDevice *xendev) return ret; } -static int con_initialise(struct XenDevice *xendev) +static int con_initialise(struct XenLegacyDevice *xendev) { struct XenConsole *con = container_of(xendev, struct XenConsole, xendev); int limit; @@ -259,7 +259,7 @@ static int con_initialise(struct XenDevice *xendev) return 0; } -static void con_disconnect(struct XenDevice *xendev) +static void con_disconnect(struct XenLegacyDevice *xendev) { struct XenConsole *con = container_of(xendev, struct XenConsole, xendev); @@ -276,7 +276,7 @@ static void con_disconnect(struct XenDevice *xendev) } } -static void con_event(struct XenDevice *xendev) +static void con_event(struct XenLegacyDevice *xendev) { struct XenConsole *con = container_of(xendev, struct XenConsole, xendev); diff --git a/hw/display/xenfb.c b/hw/display/xenfb.c index 0330dc6f61..6202f1150e 100644 --- a/hw/display/xenfb.c +++ b/hw/display/xenfb.c @@ -30,7 +30,7 @@ #include "hw/hw.h" #include "ui/input.h" #include "ui/console.h" -#include "hw/xen/xen_backend.h" +#include "hw/xen/xen-legacy-backend.h" #include #include @@ -46,7 +46,7 @@ /* -------------------------------------------------------------------- */ struct common { - struct XenDevice xendev; /* must be first */ + struct XenLegacyDevice xendev; /* must be first */ void *page; }; @@ -342,14 +342,14 @@ static QemuInputHandler xenfb_rel_mouse = { .sync = xenfb_mouse_sync, }; -static int input_init(struct XenDevice *xendev) +static int input_init(struct XenLegacyDevice *xendev) { xenstore_write_be_int(xendev, "feature-abs-pointer", 1); xenstore_write_be_int(xendev, "feature-raw-pointer", 1); return 0; } -static int input_initialise(struct XenDevice *xendev) +static int input_initialise(struct XenLegacyDevice *xendev) { struct XenInput *in = container_of(xendev, struct XenInput, c.xendev); int rc; @@ -361,7 +361,7 @@ static int input_initialise(struct XenDevice *xendev) return 0; } -static void input_connected(struct XenDevice *xendev) +static void input_connected(struct XenLegacyDevice *xendev) { struct XenInput *in = container_of(xendev, struct XenInput, c.xendev); @@ -395,7 +395,7 @@ static void input_connected(struct XenDevice *xendev) } } -static void input_disconnect(struct XenDevice *xendev) +static void input_disconnect(struct XenLegacyDevice *xendev) { struct XenInput *in = container_of(xendev, struct XenInput, c.xendev); @@ -410,7 +410,7 @@ static void input_disconnect(struct XenDevice *xendev) common_unbind(&in->c); } -static void input_event(struct XenDevice *xendev) +static void input_event(struct XenLegacyDevice *xendev) { struct XenInput *xenfb = container_of(xendev, struct XenInput, c.xendev); struct xenkbd_page *page = xenfb->c.page; @@ -867,7 +867,7 @@ static void xenfb_handle_events(struct XenFB *xenfb) page->out_cons = cons; } -static int fb_init(struct XenDevice *xendev) +static int fb_init(struct XenLegacyDevice *xendev) { #ifdef XENFB_TYPE_RESIZE xenstore_write_be_int(xendev, "feature-resize", 1); @@ -875,7 +875,7 @@ static int fb_init(struct XenDevice *xendev) return 0; } -static int fb_initialise(struct XenDevice *xendev) +static int fb_initialise(struct XenLegacyDevice *xendev) { struct XenFB *fb = container_of(xendev, struct XenFB, c.xendev); struct xenfb_page *fb_page; @@ -912,7 +912,7 @@ static int fb_initialise(struct XenDevice *xendev) return 0; } -static void fb_disconnect(struct XenDevice *xendev) +static void fb_disconnect(struct XenLegacyDevice *xendev) { struct XenFB *fb = container_of(xendev, struct XenFB, c.xendev); @@ -935,7 +935,8 @@ static void fb_disconnect(struct XenDevice *xendev) fb->bug_trigger = 0; } -static void fb_frontend_changed(struct XenDevice *xendev, const char *node) +static void fb_frontend_changed(struct XenLegacyDevice *xendev, + const char *node) { struct XenFB *fb = container_of(xendev, struct XenFB, c.xendev); @@ -953,7 +954,7 @@ static void fb_frontend_changed(struct XenDevice *xendev, const char *node) } } -static void fb_event(struct XenDevice *xendev) +static void fb_event(struct XenLegacyDevice *xendev) { struct XenFB *xenfb = container_of(xendev, struct XenFB, c.xendev); diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c index 8c8562f359..e579adb8b9 100644 --- a/hw/i386/xen/xen-hvm.c +++ b/hw/i386/xen/xen-hvm.c @@ -16,7 +16,7 @@ #include "hw/i386/pc.h" #include "hw/i386/apic-msidef.h" #include "hw/xen/xen_common.h" -#include "hw/xen/xen_backend.h" +#include "hw/xen/xen-legacy-backend.h" #include "qapi/error.h" #include "qapi/qapi-commands-misc.h" #include "qemu/error-report.h" diff --git a/hw/i386/xen/xen-mapcache.c b/hw/i386/xen/xen-mapcache.c index 02e823c5a2..349f72d00c 100644 --- a/hw/i386/xen/xen-mapcache.c +++ b/hw/i386/xen/xen-mapcache.c @@ -14,7 +14,7 @@ #include -#include "hw/xen/xen_backend.h" +#include "hw/xen/xen-legacy-backend.h" #include "qemu/bitmap.h" #include diff --git a/hw/i386/xen/xen_platform.c b/hw/i386/xen/xen_platform.c index deb7a0c374..16afb54fee 100644 --- a/hw/i386/xen/xen_platform.c +++ b/hw/i386/xen/xen_platform.c @@ -30,7 +30,7 @@ #include "hw/pci/pci.h" #include "hw/irq.h" #include "hw/xen/xen_common.h" -#include "hw/xen/xen_backend.h" +#include "hw/xen/xen-legacy-backend.h" #include "trace.h" #include "exec/address-spaces.h" #include "sysemu/block-backend.h" diff --git a/hw/net/xen_nic.c b/hw/net/xen_nic.c index 46a8dbfc90..37cda8e4be 100644 --- a/hw/net/xen_nic.c +++ b/hw/net/xen_nic.c @@ -28,14 +28,14 @@ #include "net/net.h" #include "net/checksum.h" #include "net/util.h" -#include "hw/xen/xen_backend.h" +#include "hw/xen/xen-legacy-backend.h" #include /* ------------------------------------------------------------- */ struct XenNetDev { - struct XenDevice xendev; /* must be first */ + struct XenLegacyDevice xendev; /* must be first */ char *mac; int tx_work; int tx_ring_ref; @@ -276,7 +276,7 @@ static NetClientInfo net_xen_info = { .receive = net_rx_packet, }; -static int net_init(struct XenDevice *xendev) +static int net_init(struct XenLegacyDevice *xendev) { struct XenNetDev *netdev = container_of(xendev, struct XenNetDev, xendev); @@ -308,7 +308,7 @@ static int net_init(struct XenDevice *xendev) return 0; } -static int net_connect(struct XenDevice *xendev) +static int net_connect(struct XenLegacyDevice *xendev) { struct XenNetDev *netdev = container_of(xendev, struct XenNetDev, xendev); int rx_copy; @@ -363,7 +363,7 @@ static int net_connect(struct XenDevice *xendev) return 0; } -static void net_disconnect(struct XenDevice *xendev) +static void net_disconnect(struct XenLegacyDevice *xendev) { struct XenNetDev *netdev = container_of(xendev, struct XenNetDev, xendev); @@ -379,14 +379,14 @@ static void net_disconnect(struct XenDevice *xendev) } } -static void net_event(struct XenDevice *xendev) +static void net_event(struct XenLegacyDevice *xendev) { struct XenNetDev *netdev = container_of(xendev, struct XenNetDev, xendev); net_tx_packets(netdev); qemu_flush_queued_packets(qemu_get_queue(netdev->nic)); } -static int net_free(struct XenDevice *xendev) +static int net_free(struct XenLegacyDevice *xendev) { struct XenNetDev *netdev = container_of(xendev, struct XenNetDev, xendev); diff --git a/hw/usb/xen-usb.c b/hw/usb/xen-usb.c index 5758a105a2..b20d0cfadf 100644 --- a/hw/usb/xen-usb.c +++ b/hw/usb/xen-usb.c @@ -27,7 +27,7 @@ #include "qemu/option.h" #include "hw/sysbus.h" #include "hw/usb.h" -#include "hw/xen/xen_backend.h" +#include "hw/xen/xen-legacy-backend.h" #include "monitor/qdev.h" #include "qapi/qmp/qdict.h" #include "qapi/qmp/qstring.h" @@ -99,7 +99,7 @@ struct usbback_hotplug { }; struct usbback_info { - struct XenDevice xendev; /* must be first */ + struct XenLegacyDevice xendev; /* must be first */ USBBus bus; void *urb_sring; void *conn_sring; @@ -142,7 +142,7 @@ static int usbback_gnttab_map(struct usbback_req *usbback_req) unsigned int nr_segs, i, prot; uint32_t ref[USBIF_MAX_SEGMENTS_PER_REQUEST]; struct usbback_info *usbif = usbback_req->usbif; - struct XenDevice *xendev = &usbif->xendev; + struct XenLegacyDevice *xendev = &usbif->xendev; struct usbif_request_segment *seg; void *addr; @@ -220,7 +220,7 @@ static int usbback_gnttab_map(struct usbback_req *usbback_req) static int usbback_init_packet(struct usbback_req *usbback_req) { - struct XenDevice *xendev = &usbback_req->usbif->xendev; + struct XenLegacyDevice *xendev = &usbback_req->usbif->xendev; USBPacket *packet = &usbback_req->packet; USBDevice *dev = usbback_req->stub->dev; USBEndpoint *ep; @@ -279,7 +279,7 @@ static void usbback_do_response(struct usbback_req *usbback_req, int32_t status, { struct usbback_info *usbif; struct usbif_urb_response *res; - struct XenDevice *xendev; + struct XenLegacyDevice *xendev; unsigned int notify; usbif = usbback_req->usbif; @@ -824,7 +824,7 @@ static void usbback_process_port(struct usbback_info *usbif, unsigned port) g_free(busid); } -static void usbback_disconnect(struct XenDevice *xendev) +static void usbback_disconnect(struct XenLegacyDevice *xendev) { struct usbback_info *usbif; unsigned int i; @@ -853,7 +853,7 @@ static void usbback_disconnect(struct XenDevice *xendev) TR_BUS(xendev, "finished\n"); } -static int usbback_connect(struct XenDevice *xendev) +static int usbback_connect(struct XenLegacyDevice *xendev) { struct usbback_info *usbif; struct usbif_urb_sring *urb_sring; @@ -913,7 +913,8 @@ static int usbback_connect(struct XenDevice *xendev) return 0; } -static void usbback_backend_changed(struct XenDevice *xendev, const char *node) +static void usbback_backend_changed(struct XenLegacyDevice *xendev, + const char *node) { struct usbback_info *usbif; unsigned int i; @@ -926,7 +927,7 @@ static void usbback_backend_changed(struct XenDevice *xendev, const char *node) } } -static int usbback_init(struct XenDevice *xendev) +static int usbback_init(struct XenLegacyDevice *xendev) { struct usbback_info *usbif; @@ -1005,7 +1006,7 @@ static USBPortOps xen_usb_port_ops = { static USBBusOps xen_usb_bus_ops = { }; -static void usbback_alloc(struct XenDevice *xendev) +static void usbback_alloc(struct XenLegacyDevice *xendev) { struct usbback_info *usbif; USBPort *p; @@ -1027,7 +1028,7 @@ static void usbback_alloc(struct XenDevice *xendev) usbif->bh = qemu_bh_new(usbback_bh, usbif); } -static int usbback_free(struct XenDevice *xendev) +static int usbback_free(struct XenLegacyDevice *xendev) { struct usbback_info *usbif; struct usbback_req *usbback_req; @@ -1066,7 +1067,7 @@ static int usbback_free(struct XenDevice *xendev) return 0; } -static void usbback_event(struct XenDevice *xendev) +static void usbback_event(struct XenLegacyDevice *xendev) { struct usbback_info *usbif; diff --git a/hw/xen/Makefile.objs b/hw/xen/Makefile.objs index 9ea5c73423..3f64a44051 100644 --- a/hw/xen/Makefile.objs +++ b/hw/xen/Makefile.objs @@ -1,5 +1,5 @@ # xen backend driver support -common-obj-$(CONFIG_XEN) += xen_backend.o xen_devconfig.o xen_pvdev.o xen-common.o +common-obj-$(CONFIG_XEN) += xen-legacy-backend.o xen_devconfig.o xen_pvdev.o xen-common.o obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen-host-pci-device.o obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen_pt.o xen_pt_config_init.o xen_pt_graphics.o xen_pt_msi.o diff --git a/hw/xen/xen-common.c b/hw/xen/xen-common.c index 18a9045556..0e9e58f04d 100644 --- a/hw/xen/xen-common.c +++ b/hw/xen/xen-common.c @@ -10,7 +10,7 @@ #include "qemu/osdep.h" #include "qemu/error-report.h" -#include "hw/xen/xen_backend.h" +#include "hw/xen/xen-legacy-backend.h" #include "chardev/char.h" #include "sysemu/accel.h" #include "migration/misc.h" diff --git a/hw/xen/xen_backend.c b/hw/xen/xen-legacy-backend.c similarity index 89% rename from hw/xen/xen_backend.c rename to hw/xen/xen-legacy-backend.c index 0bc6b1de60..41419763c8 100644 --- a/hw/xen/xen_backend.c +++ b/hw/xen/xen-legacy-backend.c @@ -30,7 +30,7 @@ #include "hw/boards.h" #include "qemu/log.h" #include "qapi/error.h" -#include "hw/xen/xen_backend.h" +#include "hw/xen/xen-legacy-backend.h" #include "hw/xen/xen_pvdev.h" #include "monitor/qdev.h" @@ -42,49 +42,54 @@ BusState *xen_sysbus; /* ------------------------------------------------------------- */ /* public */ -struct xs_handle *xenstore = NULL; +struct xs_handle *xenstore; const char *xen_protocol; /* private */ static bool xen_feature_grant_copy; static int debug; -int xenstore_write_be_str(struct XenDevice *xendev, const char *node, const char *val) +int xenstore_write_be_str(struct XenLegacyDevice *xendev, const char *node, + const char *val) { return xenstore_write_str(xendev->be, node, val); } -int xenstore_write_be_int(struct XenDevice *xendev, const char *node, int ival) +int xenstore_write_be_int(struct XenLegacyDevice *xendev, const char *node, + int ival) { return xenstore_write_int(xendev->be, node, ival); } -int xenstore_write_be_int64(struct XenDevice *xendev, const char *node, int64_t ival) +int xenstore_write_be_int64(struct XenLegacyDevice *xendev, const char *node, + int64_t ival) { return xenstore_write_int64(xendev->be, node, ival); } -char *xenstore_read_be_str(struct XenDevice *xendev, const char *node) +char *xenstore_read_be_str(struct XenLegacyDevice *xendev, const char *node) { return xenstore_read_str(xendev->be, node); } -int xenstore_read_be_int(struct XenDevice *xendev, const char *node, int *ival) +int xenstore_read_be_int(struct XenLegacyDevice *xendev, const char *node, + int *ival) { return xenstore_read_int(xendev->be, node, ival); } -char *xenstore_read_fe_str(struct XenDevice *xendev, const char *node) +char *xenstore_read_fe_str(struct XenLegacyDevice *xendev, const char *node) { return xenstore_read_str(xendev->fe, node); } -int xenstore_read_fe_int(struct XenDevice *xendev, const char *node, int *ival) +int xenstore_read_fe_int(struct XenLegacyDevice *xendev, const char *node, + int *ival) { return xenstore_read_int(xendev->fe, node, ival); } -int xenstore_read_fe_uint64(struct XenDevice *xendev, const char *node, +int xenstore_read_fe_uint64(struct XenLegacyDevice *xendev, const char *node, uint64_t *uval) { return xenstore_read_uint64(xendev->fe, node, uval); @@ -92,7 +97,7 @@ int xenstore_read_fe_uint64(struct XenDevice *xendev, const char *node, /* ------------------------------------------------------------- */ -int xen_be_set_state(struct XenDevice *xendev, enum xenbus_state state) +int xen_be_set_state(struct XenLegacyDevice *xendev, enum xenbus_state state) { int rc; @@ -106,7 +111,7 @@ int xen_be_set_state(struct XenDevice *xendev, enum xenbus_state state) return 0; } -void xen_be_set_max_grant_refs(struct XenDevice *xendev, +void xen_be_set_max_grant_refs(struct XenLegacyDevice *xendev, unsigned int nr_refs) { assert(xendev->ops->flags & DEVOPS_FLAG_NEED_GNTDEV); @@ -117,7 +122,7 @@ void xen_be_set_max_grant_refs(struct XenDevice *xendev, } } -void *xen_be_map_grant_refs(struct XenDevice *xendev, uint32_t *refs, +void *xen_be_map_grant_refs(struct XenLegacyDevice *xendev, uint32_t *refs, unsigned int nr_refs, int prot) { void *ptr; @@ -135,7 +140,7 @@ void *xen_be_map_grant_refs(struct XenDevice *xendev, uint32_t *refs, return ptr; } -void xen_be_unmap_grant_refs(struct XenDevice *xendev, void *ptr, +void xen_be_unmap_grant_refs(struct XenLegacyDevice *xendev, void *ptr, unsigned int nr_refs) { assert(xendev->ops->flags & DEVOPS_FLAG_NEED_GNTDEV); @@ -146,7 +151,7 @@ void xen_be_unmap_grant_refs(struct XenDevice *xendev, void *ptr, } } -static int compat_copy_grant_refs(struct XenDevice *xendev, +static int compat_copy_grant_refs(struct XenLegacyDevice *xendev, bool to_domain, XenGrantCopySegment segs[], unsigned int nr_segs) @@ -195,7 +200,7 @@ static int compat_copy_grant_refs(struct XenDevice *xendev, return 0; } -int xen_be_copy_grant_refs(struct XenDevice *xendev, +int xen_be_copy_grant_refs(struct XenLegacyDevice *xendev, bool to_domain, XenGrantCopySegment segs[], unsigned int nr_segs) @@ -259,10 +264,11 @@ int xen_be_copy_grant_refs(struct XenDevice *xendev, /* * get xen backend device, allocate a new one if it doesn't exist. */ -static struct XenDevice *xen_be_get_xendev(const char *type, int dom, int dev, - struct XenDevOps *ops) +static struct XenLegacyDevice *xen_be_get_xendev(const char *type, int dom, + int dev, + struct XenDevOps *ops) { - struct XenDevice *xendev; + struct XenLegacyDevice *xendev; xendev = xen_pv_find_xendev(type, dom, dev); if (xendev) { @@ -314,7 +320,8 @@ static struct XenDevice *xen_be_get_xendev(const char *type, int dom, int dev, * Node specifies the changed field. node = NULL means * update all fields (used for initialization). */ -static void xen_be_backend_changed(struct XenDevice *xendev, const char *node) +static void xen_be_backend_changed(struct XenLegacyDevice *xendev, + const char *node) { if (node == NULL || strcmp(node, "online") == 0) { if (xenstore_read_be_int(xendev, "online", &xendev->online) == -1) { @@ -330,7 +337,8 @@ static void xen_be_backend_changed(struct XenDevice *xendev, const char *node) } } -static void xen_be_frontend_changed(struct XenDevice *xendev, const char *node) +static void xen_be_frontend_changed(struct XenLegacyDevice *xendev, + const char *node) { int fe_state; @@ -373,7 +381,7 @@ static void xen_be_frontend_changed(struct XenDevice *xendev, const char *node) * only affects the xendev->be_state variable as xenbus should * already be put into that state by xend. */ -static int xen_be_try_setup(struct XenDevice *xendev) +static int xen_be_try_setup(struct XenLegacyDevice *xendev) { char token[XEN_BUFSIZE]; int be_state; @@ -417,7 +425,7 @@ static int xen_be_try_setup(struct XenDevice *xendev) * * Goes to InitWait on success. */ -static int xen_be_try_init(struct XenDevice *xendev) +static int xen_be_try_init(struct XenLegacyDevice *xendev) { int rc = 0; @@ -446,7 +454,7 @@ static int xen_be_try_init(struct XenDevice *xendev) * * Goes to Connected on success. */ -static int xen_be_try_initialise(struct XenDevice *xendev) +static int xen_be_try_initialise(struct XenLegacyDevice *xendev) { int rc = 0; @@ -487,7 +495,7 @@ static int xen_be_try_initialise(struct XenDevice *xendev) * frontend being Connected. Note that this may be called more * than once since the backend state is not modified. */ -static void xen_be_try_connected(struct XenDevice *xendev) +static void xen_be_try_connected(struct XenLegacyDevice *xendev) { if (!xendev->ops->connected) { return; @@ -510,7 +518,8 @@ static void xen_be_try_connected(struct XenDevice *xendev) * * Goes to Closed when done. */ -static void xen_be_disconnect(struct XenDevice *xendev, enum xenbus_state state) +static void xen_be_disconnect(struct XenLegacyDevice *xendev, + enum xenbus_state state) { if (xendev->be_state != XenbusStateClosing && xendev->be_state != XenbusStateClosed && @@ -529,7 +538,7 @@ static void xen_be_disconnect(struct XenDevice *xendev, enum xenbus_state state) /* * Try to reset xendev, for reconnection by another frontend instance. */ -static int xen_be_try_reset(struct XenDevice *xendev) +static int xen_be_try_reset(struct XenLegacyDevice *xendev) { if (xendev->fe_state != XenbusStateInitialising) { return -1; @@ -543,7 +552,7 @@ static int xen_be_try_reset(struct XenDevice *xendev) /* * state change dispatcher function */ -void xen_be_check_state(struct XenDevice *xendev) +void xen_be_check_state(struct XenLegacyDevice *xendev) { int rc = 0; @@ -587,7 +596,7 @@ void xen_be_check_state(struct XenDevice *xendev) static int xenstore_scan(const char *type, int dom, struct XenDevOps *ops) { - struct XenDevice *xendev; + struct XenLegacyDevice *xendev; char path[XEN_BUFSIZE], token[XEN_BUFSIZE]; char **dev = NULL; unsigned int cdev, j; @@ -620,7 +629,7 @@ static int xenstore_scan(const char *type, int dom, struct XenDevOps *ops) void xenstore_update_be(char *watch, char *type, int dom, struct XenDevOps *ops) { - struct XenDevice *xendev; + struct XenLegacyDevice *xendev; char path[XEN_BUFSIZE], *bepath; unsigned int len, dev; @@ -628,9 +637,9 @@ void xenstore_update_be(char *watch, char *type, int dom, if (strncmp(path, watch, len) != 0) { return; } - if (sscanf(watch+len, "/%u/%255s", &dev, path) != 2) { + if (sscanf(watch + len, "/%u/%255s", &dev, path) != 2) { strcpy(path, ""); - if (sscanf(watch+len, "/%u", &dev) != 1) { + if (sscanf(watch + len, "/%u", &dev) != 1) { dev = -1; } } @@ -651,7 +660,7 @@ void xenstore_update_be(char *watch, char *type, int dom, } } -void xenstore_update_fe(char *watch, struct XenDevice *xendev) +void xenstore_update_fe(char *watch, struct XenLegacyDevice *xendev) { char *node; unsigned int len; @@ -753,7 +762,7 @@ void xen_be_register_common(void) #endif } -int xen_be_bind_evtchn(struct XenDevice *xendev) +int xen_be_bind_evtchn(struct XenLegacyDevice *xendev) { if (xendev->local_port != -1) { return 0; @@ -789,7 +798,7 @@ static const TypeInfo xendev_type_info = { .name = TYPE_XENBACKEND, .parent = TYPE_XENSYSDEV, .class_init = xendev_class_init, - .instance_size = sizeof(struct XenDevice), + .instance_size = sizeof(struct XenLegacyDevice), }; static void xen_sysbus_class_init(ObjectClass *klass, void *data) diff --git a/hw/xen/xen_devconfig.c b/hw/xen/xen_devconfig.c index 3500d88a3e..315dbc9c51 100644 --- a/hw/xen/xen_devconfig.c +++ b/hw/xen/xen_devconfig.c @@ -1,5 +1,5 @@ #include "qemu/osdep.h" -#include "hw/xen/xen_backend.h" +#include "hw/xen/xen-legacy-backend.h" #include "qemu/option.h" #include "sysemu/blockdev.h" diff --git a/hw/xen/xen_pt.c b/hw/xen/xen_pt.c index 815dc46ba7..5539d56c3a 100644 --- a/hw/xen/xen_pt.c +++ b/hw/xen/xen_pt.c @@ -59,7 +59,7 @@ #include "hw/pci/pci.h" #include "hw/xen/xen.h" #include "hw/i386/pc.h" -#include "hw/xen/xen_backend.h" +#include "hw/xen/xen-legacy-backend.h" #include "xen_pt.h" #include "qemu/range.h" #include "exec/address-spaces.h" diff --git a/hw/xen/xen_pt_config_init.c b/hw/xen/xen_pt_config_init.c index 9fd953a689..31ec5add1d 100644 --- a/hw/xen/xen_pt_config_init.c +++ b/hw/xen/xen_pt_config_init.c @@ -15,7 +15,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "qemu/timer.h" -#include "hw/xen/xen_backend.h" +#include "hw/xen/xen-legacy-backend.h" #include "xen_pt.h" #define XEN_PT_MERGE_VALUE(value, data, val_mask) \ diff --git a/hw/xen/xen_pt_graphics.c b/hw/xen/xen_pt_graphics.c index 60d6b4a556..b69732729b 100644 --- a/hw/xen/xen_pt_graphics.c +++ b/hw/xen/xen_pt_graphics.c @@ -5,7 +5,7 @@ #include "qapi/error.h" #include "xen_pt.h" #include "xen-host-pci-device.h" -#include "hw/xen/xen_backend.h" +#include "hw/xen/xen-legacy-backend.h" static unsigned long igd_guest_opregion; static unsigned long igd_host_opregion; diff --git a/hw/xen/xen_pt_msi.c b/hw/xen/xen_pt_msi.c index cc514f9157..fb4b887b92 100644 --- a/hw/xen/xen_pt_msi.c +++ b/hw/xen/xen_pt_msi.c @@ -11,7 +11,7 @@ #include "qemu/osdep.h" -#include "hw/xen/xen_backend.h" +#include "hw/xen/xen-legacy-backend.h" #include "xen_pt.h" #include "hw/i386/apic-msidef.h" diff --git a/hw/xen/xen_pvdev.c b/hw/xen/xen_pvdev.c index f026556f62..6ef09cbf9d 100644 --- a/hw/xen/xen_pvdev.c +++ b/hw/xen/xen_pvdev.c @@ -20,7 +20,7 @@ #include "qemu/osdep.h" #include "qemu/log.h" #include "hw/qdev-core.h" -#include "hw/xen/xen_backend.h" +#include "hw/xen/xen-legacy-backend.h" #include "hw/xen/xen_pvdev.h" /* private */ @@ -34,7 +34,7 @@ struct xs_dirs { static QTAILQ_HEAD(, xs_dirs) xs_cleanup = QTAILQ_HEAD_INITIALIZER(xs_cleanup); -static QTAILQ_HEAD(, XenDevice) xendevs = +static QTAILQ_HEAD(, XenLegacyDevice) xendevs = QTAILQ_HEAD_INITIALIZER(xendevs); /* ------------------------------------------------------------- */ @@ -195,7 +195,7 @@ const char *xenbus_strstate(enum xenbus_state state) * 2 == noisy debug messages (logfile only). * 3 == will flood your log (logfile only). */ -void xen_pv_printf(struct XenDevice *xendev, int msg_level, +void xen_pv_printf(struct XenLegacyDevice *xendev, int msg_level, const char *fmt, ...) { va_list args; @@ -230,7 +230,7 @@ void xen_pv_printf(struct XenDevice *xendev, int msg_level, void xen_pv_evtchn_event(void *opaque) { - struct XenDevice *xendev = opaque; + struct XenLegacyDevice *xendev = opaque; evtchn_port_t port; port = xenevtchn_pending(xendev->evtchndev); @@ -247,7 +247,7 @@ void xen_pv_evtchn_event(void *opaque) } } -void xen_pv_unbind_evtchn(struct XenDevice *xendev) +void xen_pv_unbind_evtchn(struct XenLegacyDevice *xendev) { if (xendev->local_port == -1) { return; @@ -258,16 +258,16 @@ void xen_pv_unbind_evtchn(struct XenDevice *xendev) xendev->local_port = -1; } -int xen_pv_send_notify(struct XenDevice *xendev) +int xen_pv_send_notify(struct XenLegacyDevice *xendev) { return xenevtchn_notify(xendev->evtchndev, xendev->local_port); } /* ------------------------------------------------------------- */ -struct XenDevice *xen_pv_find_xendev(const char *type, int dom, int dev) +struct XenLegacyDevice *xen_pv_find_xendev(const char *type, int dom, int dev) { - struct XenDevice *xendev; + struct XenLegacyDevice *xendev; QTAILQ_FOREACH(xendev, &xendevs, next) { if (xendev->dom != dom) { @@ -287,7 +287,7 @@ struct XenDevice *xen_pv_find_xendev(const char *type, int dom, int dev) /* * release xen backend device. */ -void xen_pv_del_xendev(struct XenDevice *xendev) +void xen_pv_del_xendev(struct XenLegacyDevice *xendev) { if (xendev->ops->free) { xendev->ops->free(xendev); @@ -312,7 +312,7 @@ void xen_pv_del_xendev(struct XenDevice *xendev) qdev_unplug(&xendev->qdev, NULL); } -void xen_pv_insert_xendev(struct XenDevice *xendev) +void xen_pv_insert_xendev(struct XenLegacyDevice *xendev) { QTAILQ_INSERT_TAIL(&xendevs, xendev, next); } diff --git a/hw/xenpv/xen_domainbuild.c b/hw/xenpv/xen_domainbuild.c index 2859280a6a..1d9926e8d6 100644 --- a/hw/xenpv/xen_domainbuild.c +++ b/hw/xenpv/xen_domainbuild.c @@ -1,6 +1,6 @@ #include "qemu/osdep.h" #include "qemu/units.h" -#include "hw/xen/xen_backend.h" +#include "hw/xen/xen-legacy-backend.h" #include "xen_domainbuild.h" #include "qemu/timer.h" #include "qemu/log.h" diff --git a/hw/xenpv/xen_machine_pv.c b/hw/xenpv/xen_machine_pv.c index 44d67b87c4..8c86fb7031 100644 --- a/hw/xenpv/xen_machine_pv.c +++ b/hw/xenpv/xen_machine_pv.c @@ -26,7 +26,7 @@ #include "qemu/error-report.h" #include "hw/hw.h" #include "hw/boards.h" -#include "hw/xen/xen_backend.h" +#include "hw/xen/xen-legacy-backend.h" #include "xen_domainbuild.h" #include "sysemu/block-backend.h" diff --git a/include/hw/xen/xen_backend.h b/include/hw/xen/xen-legacy-backend.h similarity index 61% rename from include/hw/xen/xen_backend.h rename to include/hw/xen/xen-legacy-backend.h index 9c17fdd85d..20cb47b5bf 100644 --- a/include/hw/xen/xen_backend.h +++ b/include/hw/xen/xen-legacy-backend.h @@ -11,7 +11,7 @@ #define TYPE_XENBACKEND "xen-backend" #define XENBACKEND_DEVICE(obj) \ - OBJECT_CHECK(XenDevice, (obj), TYPE_XENBACKEND) + OBJECT_CHECK(XenLegacyDevice, (obj), TYPE_XENBACKEND) /* variables */ extern struct xs_handle *xenstore; @@ -20,32 +20,37 @@ extern DeviceState *xen_sysdev; extern BusState *xen_sysbus; int xenstore_mkdir(char *path, int p); -int xenstore_write_be_str(struct XenDevice *xendev, const char *node, const char *val); -int xenstore_write_be_int(struct XenDevice *xendev, const char *node, int ival); -int xenstore_write_be_int64(struct XenDevice *xendev, const char *node, int64_t ival); -char *xenstore_read_be_str(struct XenDevice *xendev, const char *node); -int xenstore_read_be_int(struct XenDevice *xendev, const char *node, int *ival); -void xenstore_update_fe(char *watch, struct XenDevice *xendev); +int xenstore_write_be_str(struct XenLegacyDevice *xendev, const char *node, + const char *val); +int xenstore_write_be_int(struct XenLegacyDevice *xendev, const char *node, + int ival); +int xenstore_write_be_int64(struct XenLegacyDevice *xendev, const char *node, + int64_t ival); +char *xenstore_read_be_str(struct XenLegacyDevice *xendev, const char *node); +int xenstore_read_be_int(struct XenLegacyDevice *xendev, const char *node, + int *ival); +void xenstore_update_fe(char *watch, struct XenLegacyDevice *xendev); void xenstore_update_be(char *watch, char *type, int dom, struct XenDevOps *ops); -char *xenstore_read_fe_str(struct XenDevice *xendev, const char *node); -int xenstore_read_fe_int(struct XenDevice *xendev, const char *node, int *ival); -int xenstore_read_fe_uint64(struct XenDevice *xendev, const char *node, +char *xenstore_read_fe_str(struct XenLegacyDevice *xendev, const char *node); +int xenstore_read_fe_int(struct XenLegacyDevice *xendev, const char *node, + int *ival); +int xenstore_read_fe_uint64(struct XenLegacyDevice *xendev, const char *node, uint64_t *uval); -void xen_be_check_state(struct XenDevice *xendev); +void xen_be_check_state(struct XenLegacyDevice *xendev); /* xen backend driver bits */ int xen_be_init(void); void xen_be_register_common(void); int xen_be_register(const char *type, struct XenDevOps *ops); -int xen_be_set_state(struct XenDevice *xendev, enum xenbus_state state); -int xen_be_bind_evtchn(struct XenDevice *xendev); -void xen_be_set_max_grant_refs(struct XenDevice *xendev, +int xen_be_set_state(struct XenLegacyDevice *xendev, enum xenbus_state state); +int xen_be_bind_evtchn(struct XenLegacyDevice *xendev); +void xen_be_set_max_grant_refs(struct XenLegacyDevice *xendev, unsigned int nr_refs); -void *xen_be_map_grant_refs(struct XenDevice *xendev, uint32_t *refs, +void *xen_be_map_grant_refs(struct XenLegacyDevice *xendev, uint32_t *refs, unsigned int nr_refs, int prot); -void xen_be_unmap_grant_refs(struct XenDevice *xendev, void *ptr, +void xen_be_unmap_grant_refs(struct XenLegacyDevice *xendev, void *ptr, unsigned int nr_refs); typedef struct XenGrantCopySegment { @@ -59,17 +64,17 @@ typedef struct XenGrantCopySegment { size_t len; } XenGrantCopySegment; -int xen_be_copy_grant_refs(struct XenDevice *xendev, +int xen_be_copy_grant_refs(struct XenLegacyDevice *xendev, bool to_domain, XenGrantCopySegment segs[], unsigned int nr_segs); -static inline void *xen_be_map_grant_ref(struct XenDevice *xendev, +static inline void *xen_be_map_grant_ref(struct XenLegacyDevice *xendev, uint32_t ref, int prot) { return xen_be_map_grant_refs(xendev, &ref, 1, prot); } -static inline void xen_be_unmap_grant_ref(struct XenDevice *xendev, +static inline void xen_be_unmap_grant_ref(struct XenLegacyDevice *xendev, void *ptr) { return xen_be_unmap_grant_refs(xendev, ptr, 1); diff --git a/include/hw/xen/xen_pvdev.h b/include/hw/xen/xen_pvdev.h index d473e9b34d..83e5174d90 100644 --- a/include/hw/xen/xen_pvdev.h +++ b/include/hw/xen/xen_pvdev.h @@ -6,7 +6,7 @@ #define XEN_BUFSIZE 1024 -struct XenDevice; +struct XenLegacyDevice; /* driver uses grant tables -> open gntdev device (xendev->gnttabdev) */ #define DEVOPS_FLAG_NEED_GNTDEV 1 @@ -16,19 +16,21 @@ struct XenDevice; struct XenDevOps { size_t size; uint32_t flags; - void (*alloc)(struct XenDevice *xendev); - int (*init)(struct XenDevice *xendev); - int (*initialise)(struct XenDevice *xendev); - void (*connected)(struct XenDevice *xendev); - void (*event)(struct XenDevice *xendev); - void (*disconnect)(struct XenDevice *xendev); - int (*free)(struct XenDevice *xendev); - void (*backend_changed)(struct XenDevice *xendev, const char *node); - void (*frontend_changed)(struct XenDevice *xendev, const char *node); + void (*alloc)(struct XenLegacyDevice *xendev); + int (*init)(struct XenLegacyDevice *xendev); + int (*initialise)(struct XenLegacyDevice *xendev); + void (*connected)(struct XenLegacyDevice *xendev); + void (*event)(struct XenLegacyDevice *xendev); + void (*disconnect)(struct XenLegacyDevice *xendev); + int (*free)(struct XenLegacyDevice *xendev); + void (*backend_changed)(struct XenLegacyDevice *xendev, + const char *node); + void (*frontend_changed)(struct XenLegacyDevice *xendev, + const char *node); int (*backend_register)(void); }; -struct XenDevice { +struct XenLegacyDevice { DeviceState qdev; const char *type; int dom; @@ -49,7 +51,7 @@ struct XenDevice { xengnttab_handle *gnttabdev; struct XenDevOps *ops; - QTAILQ_ENTRY(XenDevice) next; + QTAILQ_ENTRY(XenLegacyDevice) next; }; /* ------------------------------------------------------------- */ @@ -66,14 +68,14 @@ void xenstore_update(void *unused); const char *xenbus_strstate(enum xenbus_state state); void xen_pv_evtchn_event(void *opaque); -void xen_pv_insert_xendev(struct XenDevice *xendev); -void xen_pv_del_xendev(struct XenDevice *xendev); -struct XenDevice *xen_pv_find_xendev(const char *type, int dom, int dev); +void xen_pv_insert_xendev(struct XenLegacyDevice *xendev); +void xen_pv_del_xendev(struct XenLegacyDevice *xendev); +struct XenLegacyDevice *xen_pv_find_xendev(const char *type, int dom, int dev); -void xen_pv_unbind_evtchn(struct XenDevice *xendev); -int xen_pv_send_notify(struct XenDevice *xendev); +void xen_pv_unbind_evtchn(struct XenLegacyDevice *xendev); +int xen_pv_send_notify(struct XenLegacyDevice *xendev); -void xen_pv_printf(struct XenDevice *xendev, int msg_level, +void xen_pv_printf(struct XenLegacyDevice *xendev, int msg_level, const char *fmt, ...) GCC_FMT_ATTR(3, 4); #endif /* QEMU_HW_XEN_PVDEV_H */ From patchwork Mon Jan 14 13:51:33 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anthony PERARD X-Patchwork-Id: 10762723 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 8E2606C2 for ; Mon, 14 Jan 2019 14:12:26 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7ADA828CED for ; Mon, 14 Jan 2019 14:12:26 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6C41928CF6; Mon, 14 Jan 2019 14:12:26 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id AFF7528CED for ; Mon, 14 Jan 2019 14:12:25 +0000 (UTC) Received: from localhost ([127.0.0.1]:35570 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gj2yW-0000E5-RI for patchwork-qemu-devel@patchwork.kernel.org; Mon, 14 Jan 2019 09:12:24 -0500 Received: from eggs.gnu.org ([209.51.188.92]:46039) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gj2j3-0004p7-DW for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:56:28 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gj2et-0002Oc-Ne for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:52:08 -0500 Received: from smtp03.citrix.com ([162.221.156.55]:65436) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gj2et-0002O0-ET for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:52:07 -0500 X-IronPort-AV: E=Sophos;i="5.56,477,1539648000"; d="scan'208";a="75506439" From: Anthony PERARD To: Date: Mon, 14 Jan 2019 13:51:33 +0000 Message-ID: <20190114135154.16826-5-anthony.perard@citrix.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190114135154.16826-1-anthony.perard@citrix.com> References: <20190114135154.16826-1-anthony.perard@citrix.com> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 162.221.156.55 Subject: [Qemu-devel] [PULL 04/25] xen: introduce new 'XenBus' and 'XenDevice' object hierarchy X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Anthony PERARD , xen-devel@lists.xenproject.org, Peter Maydell Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Paul Durrant This patch adds the basic boilerplate for a 'XenBus' object that will act as a parent to 'XenDevice' PV backends. A new 'XenBridge' object is also added to connect XenBus to the system bus. The XenBus object is instantiated by a new xen_bus_init() function called from the same sites as the legacy xen_be_init() function. Subsequent patches will flesh-out the functionality of these objects. Signed-off-by: Paul Durrant Reviewed-by: Anthony Perard Signed-off-by: Anthony PERARD --- hw/i386/xen/xen-hvm.c | 3 + hw/xen/Makefile.objs | 2 +- hw/xen/trace-events | 6 ++ hw/xen/xen-bus.c | 127 ++++++++++++++++++++++++++++++++++++++ hw/xenpv/xen_machine_pv.c | 3 + include/hw/xen/xen-bus.h | 55 +++++++++++++++++ 6 files changed, 195 insertions(+), 1 deletion(-) create mode 100644 hw/xen/xen-bus.c create mode 100644 include/hw/xen/xen-bus.h diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c index e579adb8b9..2939122e7c 100644 --- a/hw/i386/xen/xen-hvm.c +++ b/hw/i386/xen/xen-hvm.c @@ -17,6 +17,7 @@ #include "hw/i386/apic-msidef.h" #include "hw/xen/xen_common.h" #include "hw/xen/xen-legacy-backend.h" +#include "hw/xen/xen-bus.h" #include "qapi/error.h" #include "qapi/qapi-commands-misc.h" #include "qemu/error-report.h" @@ -1484,6 +1485,8 @@ void xen_hvm_init(PCMachineState *pcms, MemoryRegion **ram_memory) QLIST_INIT(&state->dev_list); device_listener_register(&state->device_listener); + xen_bus_init(); + /* Initialize backend core & drivers */ if (xen_be_init() != 0) { error_report("xen backend core setup failed"); diff --git a/hw/xen/Makefile.objs b/hw/xen/Makefile.objs index 3f64a44051..d9d6d7b4f9 100644 --- a/hw/xen/Makefile.objs +++ b/hw/xen/Makefile.objs @@ -1,5 +1,5 @@ # xen backend driver support -common-obj-$(CONFIG_XEN) += xen-legacy-backend.o xen_devconfig.o xen_pvdev.o xen-common.o +common-obj-$(CONFIG_XEN) += xen-legacy-backend.o xen_devconfig.o xen_pvdev.o xen-common.o xen-bus.o obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen-host-pci-device.o obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen_pt.o xen_pt_config_init.o xen_pt_graphics.o xen_pt_msi.o diff --git a/hw/xen/trace-events b/hw/xen/trace-events index c7e7a3b523..0172cd4e26 100644 --- a/hw/xen/trace-events +++ b/hw/xen/trace-events @@ -12,3 +12,9 @@ xen_unmap_portio_range(uint32_t id, uint64_t start_addr, uint64_t end_addr) "id: xen_map_pcidev(uint32_t id, uint8_t bus, uint8_t dev, uint8_t func) "id: %u bdf: %02x.%02x.%02x" xen_unmap_pcidev(uint32_t id, uint8_t bus, uint8_t dev, uint8_t func) "id: %u bdf: %02x.%02x.%02x" xen_domid_restrict(int err) "err: %u" + +# include/hw/xen/xen-bus.c +xen_bus_realize(void) "" +xen_bus_unrealize(void) "" +xen_device_realize(const char *type) "type: %s" +xen_device_unrealize(const char *type) "type: %s" diff --git a/hw/xen/xen-bus.c b/hw/xen/xen-bus.c new file mode 100644 index 0000000000..bc04da748b --- /dev/null +++ b/hw/xen/xen-bus.c @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2018 Citrix Systems Inc. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/xen/xen-bus.h" +#include "qapi/error.h" +#include "trace.h" + +static void xen_bus_unrealize(BusState *bus, Error **errp) +{ + trace_xen_bus_unrealize(); +} + +static void xen_bus_realize(BusState *bus, Error **errp) +{ + trace_xen_bus_realize(); +} + +static void xen_bus_class_init(ObjectClass *class, void *data) +{ + BusClass *bus_class = BUS_CLASS(class); + + bus_class->realize = xen_bus_realize; + bus_class->unrealize = xen_bus_unrealize; +} + +static const TypeInfo xen_bus_type_info = { + .name = TYPE_XEN_BUS, + .parent = TYPE_BUS, + .instance_size = sizeof(XenBus), + .class_size = sizeof(XenBusClass), + .class_init = xen_bus_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_HOTPLUG_HANDLER }, + { } + }, +}; + +static void xen_device_unrealize(DeviceState *dev, Error **errp) +{ + XenDevice *xendev = XEN_DEVICE(dev); + XenDeviceClass *xendev_class = XEN_DEVICE_GET_CLASS(xendev); + const char *type = object_get_typename(OBJECT(xendev)); + + trace_xen_device_unrealize(type); + + if (xendev_class->unrealize) { + xendev_class->unrealize(xendev, errp); + } +} + +static void xen_device_realize(DeviceState *dev, Error **errp) +{ + XenDevice *xendev = XEN_DEVICE(dev); + XenDeviceClass *xendev_class = XEN_DEVICE_GET_CLASS(xendev); + const char *type = object_get_typename(OBJECT(xendev)); + Error *local_err = NULL; + + trace_xen_device_realize(type); + + if (xendev_class->realize) { + xendev_class->realize(xendev, &local_err); + if (local_err) { + error_propagate(errp, local_err); + goto unrealize; + } + } + + return; + +unrealize: + xen_device_unrealize(dev, &error_abort); +} + +static void xen_device_class_init(ObjectClass *class, void *data) +{ + DeviceClass *dev_class = DEVICE_CLASS(class); + + dev_class->realize = xen_device_realize; + dev_class->unrealize = xen_device_unrealize; + dev_class->bus_type = TYPE_XEN_BUS; +} + +static const TypeInfo xen_device_type_info = { + .name = TYPE_XEN_DEVICE, + .parent = TYPE_DEVICE, + .instance_size = sizeof(XenDevice), + .abstract = true, + .class_size = sizeof(XenDeviceClass), + .class_init = xen_device_class_init, +}; + +typedef struct XenBridge { + SysBusDevice busdev; +} XenBridge; + +#define TYPE_XEN_BRIDGE "xen-bridge" + +static const TypeInfo xen_bridge_type_info = { + .name = TYPE_XEN_BRIDGE, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(XenBridge), +}; + +static void xen_register_types(void) +{ + type_register_static(&xen_bridge_type_info); + type_register_static(&xen_bus_type_info); + type_register_static(&xen_device_type_info); +} + +type_init(xen_register_types) + +void xen_bus_init(void) +{ + DeviceState *dev = qdev_create(NULL, TYPE_XEN_BRIDGE); + BusState *bus = qbus_create(TYPE_XEN_BUS, dev, NULL); + + qdev_init_nofail(dev); + qbus_set_bus_hotplug_handler(bus, &error_abort); +} diff --git a/hw/xenpv/xen_machine_pv.c b/hw/xenpv/xen_machine_pv.c index 8c86fb7031..608e591bcc 100644 --- a/hw/xenpv/xen_machine_pv.c +++ b/hw/xenpv/xen_machine_pv.c @@ -27,6 +27,7 @@ #include "hw/hw.h" #include "hw/boards.h" #include "hw/xen/xen-legacy-backend.h" +#include "hw/xen/xen-bus.h" #include "xen_domainbuild.h" #include "sysemu/block-backend.h" @@ -93,6 +94,8 @@ static void xen_init_pv(MachineState *machine) xen_config_dev_nic(nd_table + i); } + xen_bus_init(); + /* config cleanup hook */ atexit(xen_config_cleanup); } diff --git a/include/hw/xen/xen-bus.h b/include/hw/xen/xen-bus.h new file mode 100644 index 0000000000..0cb12464ce --- /dev/null +++ b/include/hw/xen/xen-bus.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2018 Citrix Systems Inc. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef HW_XEN_BUS_H +#define HW_XEN_BUS_H + +#include "hw/sysbus.h" + +typedef struct XenDevice { + DeviceState qdev; +} XenDevice; + +typedef void (*XenDeviceRealize)(XenDevice *xendev, Error **errp); +typedef void (*XenDeviceUnrealize)(XenDevice *xendev, Error **errp); + +typedef struct XenDeviceClass { + /*< private >*/ + DeviceClass parent_class; + /*< public >*/ + XenDeviceRealize realize; + XenDeviceUnrealize unrealize; +} XenDeviceClass; + +#define TYPE_XEN_DEVICE "xen-device" +#define XEN_DEVICE(obj) \ + OBJECT_CHECK(XenDevice, (obj), TYPE_XEN_DEVICE) +#define XEN_DEVICE_CLASS(class) \ + OBJECT_CLASS_CHECK(XenDeviceClass, (class), TYPE_XEN_DEVICE) +#define XEN_DEVICE_GET_CLASS(obj) \ + OBJECT_GET_CLASS(XenDeviceClass, (obj), TYPE_XEN_DEVICE) + +typedef struct XenBus { + BusState qbus; +} XenBus; + +typedef struct XenBusClass { + /*< private >*/ + BusClass parent_class; +} XenBusClass; + +#define TYPE_XEN_BUS "xen-bus" +#define XEN_BUS(obj) \ + OBJECT_CHECK(XenBus, (obj), TYPE_XEN_BUS) +#define XEN_BUS_CLASS(class) \ + OBJECT_CLASS_CHECK(XenBusClass, (class), TYPE_XEN_BUS) +#define XEN_BUS_GET_CLASS(obj) \ + OBJECT_GET_CLASS(XenBusClass, (obj), TYPE_XEN_BUS) + +void xen_bus_init(void); + +#endif /* HW_XEN_BUS_H */ From patchwork Mon Jan 14 13:51:34 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anthony PERARD X-Patchwork-Id: 10762673 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 3C1FE1390 for ; Mon, 14 Jan 2019 13:57:55 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2998C28BAF for ; Mon, 14 Jan 2019 13:57:55 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1D5FF28BC2; Mon, 14 Jan 2019 13:57:55 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 278D828BDA for ; Mon, 14 Jan 2019 13:57:54 +0000 (UTC) Received: from localhost ([127.0.0.1]:60551 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gj2kT-000616-E6 for patchwork-qemu-devel@patchwork.kernel.org; Mon, 14 Jan 2019 08:57:53 -0500 Received: from eggs.gnu.org ([209.51.188.92]:45938) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gj2il-0004hh-5L for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:56:08 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gj2fW-0002dO-Um for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:52:50 -0500 Received: from smtp03.citrix.com ([162.221.156.55]:65464) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gj2fW-0002cK-Ib for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:52:46 -0500 X-IronPort-AV: E=Sophos;i="5.56,477,1539648000"; d="scan'208";a="75506461" From: Anthony PERARD To: Date: Mon, 14 Jan 2019 13:51:34 +0000 Message-ID: <20190114135154.16826-6-anthony.perard@citrix.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190114135154.16826-1-anthony.perard@citrix.com> References: <20190114135154.16826-1-anthony.perard@citrix.com> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 162.221.156.55 Subject: [Qemu-devel] [PULL 05/25] xen: introduce 'xen-block', 'xen-disk' and 'xen-cdrom' X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Anthony PERARD , xen-devel@lists.xenproject.org, Peter Maydell Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Paul Durrant This patch adds new XenDevice-s: 'xen-disk' and 'xen-cdrom', both derived from a common 'xen-block' parent type. These will eventually replace the 'xen_disk' (note the underscore rather than hyphen) legacy PV backend but it is illustrative to build up the implementation incrementally, along with the XenBus/XenDevice framework. Subsequent patches will therefore add to these devices' implementation as new features are added to the framework. After this patch has been applied it is possible to instantiate new 'xen-disk' or 'xen-cdrom' devices with a single 'vdev' parameter, which accepts values adhering to the Xen VBD naming scheme [1]. For example, a command-line instantiation of a xen-disk can be done with an argument similar to the following: -device xen-disk,vdev=hda The implementation of the vdev parameter formulates the appropriate VBD number for use in the PV protocol. [1] https://xenbits.xen.org/docs/unstable/man/xen-vbd-interface.7.html Signed-off-by: Paul Durrant Reviewed-by: Anthony Perard Signed-off-by: Anthony PERARD --- MAINTAINERS | 2 +- hw/block/Makefile.objs | 1 + hw/block/trace-events | 8 + hw/block/xen-block.c | 343 +++++++++++++++++++++++++++++++++++++ include/hw/xen/xen-block.h | 73 ++++++++ 5 files changed, 426 insertions(+), 1 deletion(-) create mode 100644 hw/block/xen-block.c create mode 100644 include/hw/xen/xen-block.h diff --git a/MAINTAINERS b/MAINTAINERS index 87f90721b9..7514550c06 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -414,7 +414,7 @@ F: hw/9pfs/xen-9p-backend.c F: hw/char/xen_console.c F: hw/display/xenfb.c F: hw/net/xen_nic.c -F: hw/block/xen_* +F: hw/block/xen* F: hw/xen/ F: hw/xenpv/ F: hw/i386/xen/ diff --git a/hw/block/Makefile.objs b/hw/block/Makefile.objs index 53ce5751ae..f34813a377 100644 --- a/hw/block/Makefile.objs +++ b/hw/block/Makefile.objs @@ -4,6 +4,7 @@ common-obj-$(CONFIG_SSI_M25P80) += m25p80.o common-obj-$(CONFIG_NAND) += nand.o common-obj-$(CONFIG_PFLASH_CFI01) += pflash_cfi01.o common-obj-$(CONFIG_PFLASH_CFI02) += pflash_cfi02.o +common-obj-$(CONFIG_XEN) += xen-block.o common-obj-$(CONFIG_XEN) += xen_disk.o common-obj-$(CONFIG_ECC) += ecc.o common-obj-$(CONFIG_ONENAND) += onenand.o diff --git a/hw/block/trace-events b/hw/block/trace-events index 335c092450..4afbd62a88 100644 --- a/hw/block/trace-events +++ b/hw/block/trace-events @@ -127,3 +127,11 @@ xen_disk_init(char *name) "%s" xen_disk_connect(char *name) "%s" xen_disk_disconnect(char *name) "%s" xen_disk_free(char *name) "%s" + +# hw/block/xen-block.c +xen_block_realize(const char *type, uint32_t disk, uint32_t partition) "%s d%up%u" +xen_block_unrealize(const char *type, uint32_t disk, uint32_t partition) "%s d%up%u" +xen_disk_realize(void) "" +xen_disk_unrealize(void) "" +xen_cdrom_realize(void) "" +xen_cdrom_unrealize(void) "" diff --git a/hw/block/xen-block.c b/hw/block/xen-block.c new file mode 100644 index 0000000000..8e78b6a034 --- /dev/null +++ b/hw/block/xen-block.c @@ -0,0 +1,343 @@ +/* + * Copyright (c) 2018 Citrix Systems Inc. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "qemu/cutils.h" +#include "qapi/error.h" +#include "qapi/visitor.h" +#include "hw/hw.h" +#include "hw/xen/xen-block.h" +#include "trace.h" + +static void xen_block_unrealize(XenDevice *xendev, Error **errp) +{ + XenBlockDevice *blockdev = XEN_BLOCK_DEVICE(xendev); + XenBlockDeviceClass *blockdev_class = + XEN_BLOCK_DEVICE_GET_CLASS(xendev); + const char *type = object_get_typename(OBJECT(blockdev)); + XenBlockVdev *vdev = &blockdev->props.vdev; + + if (vdev->type == XEN_BLOCK_VDEV_TYPE_INVALID) { + return; + } + + trace_xen_block_unrealize(type, vdev->disk, vdev->partition); + + if (blockdev_class->unrealize) { + blockdev_class->unrealize(blockdev, errp); + } +} + +static void xen_block_realize(XenDevice *xendev, Error **errp) +{ + XenBlockDevice *blockdev = XEN_BLOCK_DEVICE(xendev); + XenBlockDeviceClass *blockdev_class = + XEN_BLOCK_DEVICE_GET_CLASS(xendev); + const char *type = object_get_typename(OBJECT(blockdev)); + XenBlockVdev *vdev = &blockdev->props.vdev; + Error *local_err = NULL; + + if (vdev->type == XEN_BLOCK_VDEV_TYPE_INVALID) { + error_setg(errp, "vdev property not set"); + return; + } + + trace_xen_block_realize(type, vdev->disk, vdev->partition); + + if (blockdev_class->realize) { + blockdev_class->realize(blockdev, &local_err); + if (local_err) { + error_propagate(errp, local_err); + } + } +} + +static char *disk_to_vbd_name(unsigned int disk) +{ + char *name, *prefix = (disk >= 26) ? + disk_to_vbd_name((disk / 26) - 1) : g_strdup(""); + + name = g_strdup_printf("%s%c", prefix, 'a' + disk % 26); + g_free(prefix); + + return name; +} + +static void xen_block_get_vdev(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + DeviceState *dev = DEVICE(obj); + Property *prop = opaque; + XenBlockVdev *vdev = qdev_get_prop_ptr(dev, prop); + char *str; + + switch (vdev->type) { + case XEN_BLOCK_VDEV_TYPE_DP: + str = g_strdup_printf("d%lup%lu", vdev->disk, vdev->partition); + break; + + case XEN_BLOCK_VDEV_TYPE_XVD: + case XEN_BLOCK_VDEV_TYPE_HD: + case XEN_BLOCK_VDEV_TYPE_SD: { + char *name = disk_to_vbd_name(vdev->disk); + + str = g_strdup_printf("%s%s%lu", + (vdev->type == XEN_BLOCK_VDEV_TYPE_XVD) ? + "xvd" : + (vdev->type == XEN_BLOCK_VDEV_TYPE_HD) ? + "hd" : + "sd", + name, vdev->partition); + g_free(name); + break; + } + default: + error_setg(errp, "invalid vdev type"); + return; + } + + visit_type_str(v, name, &str, errp); + g_free(str); +} + +static unsigned int vbd_name_to_disk(const char *name, const char **endp) +{ + unsigned int disk = 0; + + while (*name != '\0') { + if (!g_ascii_isalpha(*name) || !g_ascii_islower(*name)) { + break; + } + + disk *= 26; + disk += *name++ - 'a' + 1; + } + *endp = name; + + return disk - 1; +} + +static void xen_block_set_vdev(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + DeviceState *dev = DEVICE(obj); + Property *prop = opaque; + XenBlockVdev *vdev = qdev_get_prop_ptr(dev, prop); + Error *local_err = NULL; + char *str, *p; + const char *end; + + if (dev->realized) { + qdev_prop_set_after_realize(dev, name, errp); + return; + } + + visit_type_str(v, name, &str, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + + p = strchr(str, 'd'); + if (!p) { + goto invalid; + } + + *p++ = '\0'; + if (*str == '\0') { + vdev->type = XEN_BLOCK_VDEV_TYPE_DP; + } else if (strcmp(str, "xv") == 0) { + vdev->type = XEN_BLOCK_VDEV_TYPE_XVD; + } else if (strcmp(str, "h") == 0) { + vdev->type = XEN_BLOCK_VDEV_TYPE_HD; + } else if (strcmp(str, "s") == 0) { + vdev->type = XEN_BLOCK_VDEV_TYPE_SD; + } else { + goto invalid; + } + + if (vdev->type == XEN_BLOCK_VDEV_TYPE_DP) { + if (qemu_strtoul(p, &end, 10, &vdev->disk)) { + goto invalid; + } + + if (*end == 'p') { + p = (char *) ++end; + if (*end == '\0') { + goto invalid; + } + } + } else { + vdev->disk = vbd_name_to_disk(p, &end); + } + + if (*end != '\0') { + p = (char *)end; + + if (qemu_strtoul(p, &end, 10, &vdev->partition)) { + goto invalid; + } + + if (*end != '\0') { + goto invalid; + } + } else { + vdev->partition = 0; + } + + switch (vdev->type) { + case XEN_BLOCK_VDEV_TYPE_DP: + case XEN_BLOCK_VDEV_TYPE_XVD: + if (vdev->disk < (1 << 4) && vdev->partition < (1 << 4)) { + vdev->number = (202 << 8) | (vdev->disk << 4) | + vdev->partition; + } else if (vdev->disk < (1 << 20) && vdev->partition < (1 << 8)) { + vdev->number = (1 << 28) | (vdev->disk << 8) | + vdev->partition; + } else { + goto invalid; + } + break; + + case XEN_BLOCK_VDEV_TYPE_HD: + if ((vdev->disk == 0 || vdev->disk == 1) && + vdev->partition < (1 << 6)) { + vdev->number = (3 << 8) | (vdev->disk << 6) | vdev->partition; + } else if ((vdev->disk == 2 || vdev->disk == 3) && + vdev->partition < (1 << 6)) { + vdev->number = (22 << 8) | ((vdev->disk - 2) << 6) | + vdev->partition; + } else { + goto invalid; + } + break; + + case XEN_BLOCK_VDEV_TYPE_SD: + if (vdev->disk < (1 << 4) && vdev->partition < (1 << 4)) { + vdev->number = (8 << 8) | (vdev->disk << 4) | vdev->partition; + } else { + goto invalid; + } + break; + + default: + goto invalid; + } + + g_free(str); + return; + +invalid: + error_setg(errp, "invalid virtual disk specifier"); + + vdev->type = XEN_BLOCK_VDEV_TYPE_INVALID; + g_free(str); +} + +/* + * This property deals with 'vdev' names adhering to the Xen VBD naming + * scheme described in: + * + * https://xenbits.xen.org/docs/unstable/man/xen-vbd-interface.7.html + */ +const PropertyInfo xen_block_prop_vdev = { + .name = "str", + .description = "Virtual Disk specifier: d*p*/xvd*/hd*/sd*", + .get = xen_block_get_vdev, + .set = xen_block_set_vdev, +}; + +static Property xen_block_props[] = { + DEFINE_PROP("vdev", XenBlockDevice, props.vdev, + xen_block_prop_vdev, XenBlockVdev), + DEFINE_PROP_END_OF_LIST() +}; + +static void xen_block_class_init(ObjectClass *class, void *data) +{ + DeviceClass *dev_class = DEVICE_CLASS(class); + XenDeviceClass *xendev_class = XEN_DEVICE_CLASS(class); + + xendev_class->realize = xen_block_realize; + xendev_class->unrealize = xen_block_unrealize; + + dev_class->props = xen_block_props; +} + +static const TypeInfo xen_block_type_info = { + .name = TYPE_XEN_BLOCK_DEVICE, + .parent = TYPE_XEN_DEVICE, + .instance_size = sizeof(XenBlockDevice), + .abstract = true, + .class_size = sizeof(XenBlockDeviceClass), + .class_init = xen_block_class_init, +}; + +static void xen_disk_unrealize(XenBlockDevice *blockdev, Error **errp) +{ + trace_xen_disk_unrealize(); +} + +static void xen_disk_realize(XenBlockDevice *blockdev, Error **errp) +{ + trace_xen_disk_realize(); +} + +static void xen_disk_class_init(ObjectClass *class, void *data) +{ + DeviceClass *dev_class = DEVICE_CLASS(class); + XenBlockDeviceClass *blockdev_class = XEN_BLOCK_DEVICE_CLASS(class); + + blockdev_class->realize = xen_disk_realize; + blockdev_class->unrealize = xen_disk_unrealize; + + dev_class->desc = "Xen Disk Device"; +} + +static const TypeInfo xen_disk_type_info = { + .name = TYPE_XEN_DISK_DEVICE, + .parent = TYPE_XEN_BLOCK_DEVICE, + .instance_size = sizeof(XenDiskDevice), + .class_init = xen_disk_class_init, +}; + +static void xen_cdrom_unrealize(XenBlockDevice *blockdev, Error **errp) +{ + trace_xen_cdrom_unrealize(); +} + +static void xen_cdrom_realize(XenBlockDevice *blockdev, Error **errp) +{ + trace_xen_cdrom_realize(); +} + +static void xen_cdrom_class_init(ObjectClass *class, void *data) +{ + DeviceClass *dev_class = DEVICE_CLASS(class); + XenBlockDeviceClass *blockdev_class = XEN_BLOCK_DEVICE_CLASS(class); + + blockdev_class->realize = xen_cdrom_realize; + blockdev_class->unrealize = xen_cdrom_unrealize; + + dev_class->desc = "Xen CD-ROM Device"; +} + +static const TypeInfo xen_cdrom_type_info = { + .name = TYPE_XEN_CDROM_DEVICE, + .parent = TYPE_XEN_BLOCK_DEVICE, + .instance_size = sizeof(XenCDRomDevice), + .class_init = xen_cdrom_class_init, +}; + +static void xen_block_register_types(void) +{ + type_register_static(&xen_block_type_info); + type_register_static(&xen_disk_type_info); + type_register_static(&xen_cdrom_type_info); +} + +type_init(xen_block_register_types) diff --git a/include/hw/xen/xen-block.h b/include/hw/xen/xen-block.h new file mode 100644 index 0000000000..29413256e9 --- /dev/null +++ b/include/hw/xen/xen-block.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018 Citrix Systems Inc. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef HW_XEN_BLOCK_H +#define HW_XEN_BLOCK_H + +#include "hw/xen/xen-bus.h" + +typedef enum XenBlockVdevType { + XEN_BLOCK_VDEV_TYPE_INVALID, + XEN_BLOCK_VDEV_TYPE_DP, + XEN_BLOCK_VDEV_TYPE_XVD, + XEN_BLOCK_VDEV_TYPE_HD, + XEN_BLOCK_VDEV_TYPE_SD, + XEN_BLOCK_VDEV_TYPE__MAX +} XenBlockVdevType; + +typedef struct XenBlockVdev { + XenBlockVdevType type; + unsigned long disk; + unsigned long partition; + unsigned long number; +} XenBlockVdev; + +typedef struct XenBlockProperties { + XenBlockVdev vdev; +} XenBlockProperties; + +typedef struct XenBlockDevice { + XenDevice xendev; + XenBlockProperties props; +} XenBlockDevice; + +typedef void (*XenBlockDeviceRealize)(XenBlockDevice *blockdev, Error **errp); +typedef void (*XenBlockDeviceUnrealize)(XenBlockDevice *blockdev, Error **errp); + +typedef struct XenBlockDeviceClass { + /*< private >*/ + XenDeviceClass parent_class; + /*< public >*/ + XenBlockDeviceRealize realize; + XenBlockDeviceUnrealize unrealize; +} XenBlockDeviceClass; + +#define TYPE_XEN_BLOCK_DEVICE "xen-block" +#define XEN_BLOCK_DEVICE(obj) \ + OBJECT_CHECK(XenBlockDevice, (obj), TYPE_XEN_BLOCK_DEVICE) +#define XEN_BLOCK_DEVICE_CLASS(class) \ + OBJECT_CLASS_CHECK(XenBlockDeviceClass, (class), TYPE_XEN_BLOCK_DEVICE) +#define XEN_BLOCK_DEVICE_GET_CLASS(obj) \ + OBJECT_GET_CLASS(XenBlockDeviceClass, (obj), TYPE_XEN_BLOCK_DEVICE) + +typedef struct XenDiskDevice { + XenBlockDevice blockdev; +} XenDiskDevice; + +#define TYPE_XEN_DISK_DEVICE "xen-disk" +#define XEN_DISK_DEVICE(obj) \ + OBJECT_CHECK(XenDiskDevice, (obj), TYPE_XEN_DISK_DEVICE) + +typedef struct XenCDRomDevice { + XenBlockDevice blockdev; +} XenCDRomDevice; + +#define TYPE_XEN_CDROM_DEVICE "xen-cdrom" +#define XEN_CDROM_DEVICE(obj) \ + OBJECT_CHECK(XenCDRomDevice, (obj), TYPE_XEN_CDROM_DEVICE) + +#endif /* HW_XEN_BLOCK_H */ From patchwork Mon Jan 14 13:51:35 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anthony PERARD X-Patchwork-Id: 10762679 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 2C5E31390 for ; Mon, 14 Jan 2019 14:01:02 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1906228C21 for ; Mon, 14 Jan 2019 14:01:02 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1686428C59; Mon, 14 Jan 2019 14:01:02 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 9725628BAF for ; Mon, 14 Jan 2019 14:01:00 +0000 (UTC) Received: from localhost ([127.0.0.1]:33065 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gj2nT-00006v-Mv for patchwork-qemu-devel@patchwork.kernel.org; Mon, 14 Jan 2019 09:00:59 -0500 Received: from eggs.gnu.org ([209.51.188.92]:45840) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gj2in-0004go-D8 for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:56:11 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gj2fX-0002e3-KP for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:52:49 -0500 Received: from smtp03.citrix.com ([162.221.156.55]:65464) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gj2fX-0002cK-A1 for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:52:47 -0500 X-IronPort-AV: E=Sophos;i="5.56,477,1539648000"; d="scan'208";a="75506462" From: Anthony PERARD To: Date: Mon, 14 Jan 2019 13:51:35 +0000 Message-ID: <20190114135154.16826-7-anthony.perard@citrix.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190114135154.16826-1-anthony.perard@citrix.com> References: <20190114135154.16826-1-anthony.perard@citrix.com> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 162.221.156.55 Subject: [Qemu-devel] [PULL 06/25] xen: create xenstore areas for XenDevice-s X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Anthony PERARD , xen-devel@lists.xenproject.org, Peter Maydell Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Paul Durrant This patch adds a new source module, xen-bus-helper.c, which builds on basic libxenstore primitives to provide functions to create (setting permissions appropriately) and destroy xenstore areas, and functions to 'printf' and 'scanf' nodes therein. The main xen-bus code then uses these primitives [1] to initialize and destroy the frontend and backend areas for a XenDevice during realize and unrealize respectively. The 'xen-block' implementation is extended with a 'get_name' method that returns the VBD number. This number is required to 'name' the xenstore areas. NOTE: An exit handler is also added to make sure the xenstore areas are cleaned up if QEMU terminates without devices being unrealized. [1] The 'scanf' functions are actually not yet needed, but they will be needed by code delivered in subsequent patches. Signed-off-by: Paul Durrant Reviewed-by: Anthony Perard Signed-off-by: Anthony PERARD --- hw/block/xen-block.c | 9 + hw/xen/Makefile.objs | 2 +- hw/xen/trace-events | 12 +- hw/xen/xen-bus-helper.c | 150 +++++++++++++++ hw/xen/xen-bus.c | 321 +++++++++++++++++++++++++++++++- include/hw/xen/xen-bus-helper.h | 39 ++++ include/hw/xen/xen-bus.h | 12 ++ 7 files changed, 540 insertions(+), 5 deletions(-) create mode 100644 hw/xen/xen-bus-helper.c create mode 100644 include/hw/xen/xen-bus-helper.h diff --git a/hw/block/xen-block.c b/hw/block/xen-block.c index 8e78b6a034..d27a2865bc 100644 --- a/hw/block/xen-block.c +++ b/hw/block/xen-block.c @@ -13,6 +13,14 @@ #include "hw/xen/xen-block.h" #include "trace.h" +static char *xen_block_get_name(XenDevice *xendev, Error **errp) +{ + XenBlockDevice *blockdev = XEN_BLOCK_DEVICE(xendev); + XenBlockVdev *vdev = &blockdev->props.vdev; + + return g_strdup_printf("%lu", vdev->number); +} + static void xen_block_unrealize(XenDevice *xendev, Error **errp) { XenBlockDevice *blockdev = XEN_BLOCK_DEVICE(xendev); @@ -262,6 +270,7 @@ static void xen_block_class_init(ObjectClass *class, void *data) DeviceClass *dev_class = DEVICE_CLASS(class); XenDeviceClass *xendev_class = XEN_DEVICE_CLASS(class); + xendev_class->get_name = xen_block_get_name; xendev_class->realize = xen_block_realize; xendev_class->unrealize = xen_block_unrealize; diff --git a/hw/xen/Makefile.objs b/hw/xen/Makefile.objs index d9d6d7b4f9..77c0868190 100644 --- a/hw/xen/Makefile.objs +++ b/hw/xen/Makefile.objs @@ -1,5 +1,5 @@ # xen backend driver support -common-obj-$(CONFIG_XEN) += xen-legacy-backend.o xen_devconfig.o xen_pvdev.o xen-common.o xen-bus.o +common-obj-$(CONFIG_XEN) += xen-legacy-backend.o xen_devconfig.o xen_pvdev.o xen-common.o xen-bus.o xen-bus-helper.o obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen-host-pci-device.o obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen_pt.o xen_pt_config_init.o xen_pt_graphics.o xen_pt_msi.o diff --git a/hw/xen/trace-events b/hw/xen/trace-events index 0172cd4e26..75dc226d75 100644 --- a/hw/xen/trace-events +++ b/hw/xen/trace-events @@ -16,5 +16,13 @@ xen_domid_restrict(int err) "err: %u" # include/hw/xen/xen-bus.c xen_bus_realize(void) "" xen_bus_unrealize(void) "" -xen_device_realize(const char *type) "type: %s" -xen_device_unrealize(const char *type) "type: %s" +xen_device_realize(const char *type, char *name) "type: %s name: %s" +xen_device_unrealize(const char *type, char *name) "type: %s name: %s" +xen_device_backend_state(const char *type, char *name, const char *state) "type: %s name: %s -> %s" +xen_device_frontend_state(const char *type, char *name, const char *state) "type: %s name: %s -> %s" + +# include/hw/xen/xen-bus-helper.c +xs_node_create(const char *node) "%s" +xs_node_destroy(const char *node) "%s" +xs_node_vprintf(char *path, char *value) "%s %s" +xs_node_vscanf(char *path, char *value) "%s %s" diff --git a/hw/xen/xen-bus-helper.c b/hw/xen/xen-bus-helper.c new file mode 100644 index 0000000000..15b3ad8d78 --- /dev/null +++ b/hw/xen/xen-bus-helper.c @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2018 Citrix Systems Inc. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/xen/xen.h" +#include "hw/xen/xen-bus.h" +#include "hw/xen/xen-bus-helper.h" +#include "qapi/error.h" + +#include + +struct xs_state { + enum xenbus_state statenum; + const char *statestr; +}; +#define XS_STATE(state) { state, #state } + +static struct xs_state xs_state[] = { + XS_STATE(XenbusStateUnknown), + XS_STATE(XenbusStateInitialising), + XS_STATE(XenbusStateInitWait), + XS_STATE(XenbusStateInitialised), + XS_STATE(XenbusStateConnected), + XS_STATE(XenbusStateClosing), + XS_STATE(XenbusStateClosed), + XS_STATE(XenbusStateReconfiguring), + XS_STATE(XenbusStateReconfigured), +}; + +#undef XS_STATE + +const char *xs_strstate(enum xenbus_state state) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(xs_state); i++) { + if (xs_state[i].statenum == state) { + return xs_state[i].statestr; + } + } + + return "INVALID"; +} + +void xs_node_create(struct xs_handle *xsh, xs_transaction_t tid, + const char *node, struct xs_permissions perms[], + unsigned int nr_perms, Error **errp) +{ + trace_xs_node_create(node); + + if (!xs_write(xsh, tid, node, "", 0)) { + error_setg_errno(errp, errno, "failed to create node '%s'", node); + return; + } + + if (!xs_set_permissions(xsh, tid, node, perms, nr_perms)) { + error_setg_errno(errp, errno, "failed to set node '%s' permissions", + node); + } +} + +void xs_node_destroy(struct xs_handle *xsh, xs_transaction_t tid, + const char *node, Error **errp) +{ + trace_xs_node_destroy(node); + + if (!xs_rm(xsh, tid, node)) { + error_setg_errno(errp, errno, "failed to destroy node '%s'", node); + } +} + +void xs_node_vprintf(struct xs_handle *xsh, xs_transaction_t tid, + const char *node, const char *key, Error **errp, + const char *fmt, va_list ap) +{ + char *path, *value; + int len; + + path = (strlen(node) != 0) ? g_strdup_printf("%s/%s", node, key) : + g_strdup(key); + len = g_vasprintf(&value, fmt, ap); + + trace_xs_node_vprintf(path, value); + + if (!xs_write(xsh, tid, path, value, len)) { + error_setg_errno(errp, errno, "failed to write '%s' to '%s'", + value, path); + } + + g_free(value); + g_free(path); +} + +void xs_node_printf(struct xs_handle *xsh, xs_transaction_t tid, + const char *node, const char *key, Error **errp, + const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + xs_node_vprintf(xsh, tid, node, key, errp, fmt, ap); + va_end(ap); +} + +int xs_node_vscanf(struct xs_handle *xsh, xs_transaction_t tid, + const char *node, const char *key, Error **errp, + const char *fmt, va_list ap) +{ + char *path, *value; + int rc; + + path = (strlen(node) != 0) ? g_strdup_printf("%s/%s", node, key) : + g_strdup(key); + value = xs_read(xsh, tid, path, NULL); + + trace_xs_node_vscanf(path, value); + + if (value) { + rc = vsscanf(value, fmt, ap); + } else { + error_setg_errno(errp, errno, "failed to read from '%s'", + path); + rc = EOF; + } + + free(value); + g_free(path); + + return rc; +} + +int xs_node_scanf(struct xs_handle *xsh, xs_transaction_t tid, + const char *node, const char *key, Error **errp, + const char *fmt, ...) +{ + va_list ap; + int rc; + + va_start(ap, fmt); + rc = xs_node_vscanf(xsh, tid, node, key, errp, fmt, ap); + va_end(ap); + + return rc; +} diff --git a/hw/xen/xen-bus.c b/hw/xen/xen-bus.c index bc04da748b..843fda26a9 100644 --- a/hw/xen/xen-bus.c +++ b/hw/xen/xen-bus.c @@ -8,24 +8,102 @@ #include "qemu/osdep.h" #include "hw/hw.h" #include "hw/sysbus.h" +#include "hw/xen/xen.h" #include "hw/xen/xen-bus.h" +#include "hw/xen/xen-bus-helper.h" +#include "monitor/monitor.h" #include "qapi/error.h" +#include "sysemu/sysemu.h" #include "trace.h" +static char *xen_device_get_backend_path(XenDevice *xendev) +{ + XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev))); + XenDeviceClass *xendev_class = XEN_DEVICE_GET_CLASS(xendev); + const char *type = object_get_typename(OBJECT(xendev)); + const char *backend = xendev_class->backend; + + if (!backend) { + backend = type; + } + + return g_strdup_printf("/local/domain/%u/backend/%s/%u/%s", + xenbus->backend_id, backend, xendev->frontend_id, + xendev->name); +} + +static char *xen_device_get_frontend_path(XenDevice *xendev) +{ + XenDeviceClass *xendev_class = XEN_DEVICE_GET_CLASS(xendev); + const char *type = object_get_typename(OBJECT(xendev)); + const char *device = xendev_class->device; + + if (!device) { + device = type; + } + + return g_strdup_printf("/local/domain/%u/device/%s/%s", + xendev->frontend_id, device, xendev->name); +} + +static void xen_bus_print_dev(Monitor *mon, DeviceState *dev, int indent) +{ + XenDevice *xendev = XEN_DEVICE(dev); + + monitor_printf(mon, "%*sname = '%s' frontend_id = %u\n", + indent, "", xendev->name, xendev->frontend_id); +} + +static char *xen_bus_get_dev_path(DeviceState *dev) +{ + return xen_device_get_backend_path(XEN_DEVICE(dev)); +} + static void xen_bus_unrealize(BusState *bus, Error **errp) { + XenBus *xenbus = XEN_BUS(bus); + trace_xen_bus_unrealize(); + + if (!xenbus->xsh) { + return; + } + + xs_close(xenbus->xsh); } static void xen_bus_realize(BusState *bus, Error **errp) { + XenBus *xenbus = XEN_BUS(bus); + unsigned int domid; + trace_xen_bus_realize(); + + xenbus->xsh = xs_open(0); + if (!xenbus->xsh) { + error_setg_errno(errp, errno, "failed xs_open"); + goto fail; + } + + if (xs_node_scanf(xenbus->xsh, XBT_NULL, "", /* domain root node */ + "domid", NULL, "%u", &domid) == 1) { + xenbus->backend_id = domid; + } else { + xenbus->backend_id = 0; /* Assume lack of node means dom0 */ + } + + return; + +fail: + xen_bus_unrealize(bus, &error_abort); } static void xen_bus_class_init(ObjectClass *class, void *data) { BusClass *bus_class = BUS_CLASS(class); + bus_class->print_dev = xen_bus_print_dev; + bus_class->get_dev_path = xen_bus_get_dev_path; bus_class->realize = xen_bus_realize; bus_class->unrealize = xen_bus_unrealize; } @@ -42,27 +120,241 @@ static const TypeInfo xen_bus_type_info = { }, }; +static void xen_device_backend_printf(XenDevice *xendev, const char *key, + const char *fmt, ...) +{ + XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev))); + Error *local_err = NULL; + va_list ap; + + g_assert(xenbus->xsh); + + va_start(ap, fmt); + xs_node_vprintf(xenbus->xsh, XBT_NULL, xendev->backend_path, key, + &local_err, fmt, ap); + va_end(ap); + + if (local_err) { + error_report_err(local_err); + } +} + +static void xen_device_backend_set_state(XenDevice *xendev, + enum xenbus_state state) +{ + const char *type = object_get_typename(OBJECT(xendev)); + + if (xendev->backend_state == state) { + return; + } + + trace_xen_device_backend_state(type, xendev->name, + xs_strstate(state)); + + xendev->backend_state = state; + xen_device_backend_printf(xendev, "state", "%u", state); +} + +static void xen_device_backend_create(XenDevice *xendev, Error **errp) +{ + XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev))); + struct xs_permissions perms[2]; + Error *local_err = NULL; + + xendev->backend_path = xen_device_get_backend_path(xendev); + + perms[0].id = xenbus->backend_id; + perms[0].perms = XS_PERM_NONE; + perms[1].id = xendev->frontend_id; + perms[1].perms = XS_PERM_READ; + + g_assert(xenbus->xsh); + + xs_node_create(xenbus->xsh, XBT_NULL, xendev->backend_path, perms, + ARRAY_SIZE(perms), &local_err); + if (local_err) { + error_propagate_prepend(errp, local_err, + "failed to create backend: "); + } +} + +static void xen_device_backend_destroy(XenDevice *xendev) +{ + XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev))); + Error *local_err = NULL; + + if (!xendev->backend_path) { + return; + } + + g_assert(xenbus->xsh); + + xs_node_destroy(xenbus->xsh, XBT_NULL, xendev->backend_path, + &local_err); + g_free(xendev->backend_path); + xendev->backend_path = NULL; + + if (local_err) { + error_report_err(local_err); + } +} + +static void xen_device_frontend_printf(XenDevice *xendev, const char *key, + const char *fmt, ...) +{ + XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev))); + Error *local_err = NULL; + va_list ap; + + g_assert(xenbus->xsh); + + va_start(ap, fmt); + xs_node_vprintf(xenbus->xsh, XBT_NULL, xendev->frontend_path, key, + &local_err, fmt, ap); + va_end(ap); + + if (local_err) { + error_report_err(local_err); + } +} + +static void xen_device_frontend_set_state(XenDevice *xendev, + enum xenbus_state state) +{ + const char *type = object_get_typename(OBJECT(xendev)); + + if (xendev->frontend_state == state) { + return; + } + + trace_xen_device_frontend_state(type, xendev->name, + xs_strstate(state)); + + xendev->frontend_state = state; + xen_device_frontend_printf(xendev, "state", "%u", state); +} + +static void xen_device_frontend_create(XenDevice *xendev, Error **errp) +{ + XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev))); + struct xs_permissions perms[2]; + Error *local_err = NULL; + + xendev->frontend_path = xen_device_get_frontend_path(xendev); + + perms[0].id = xendev->frontend_id; + perms[0].perms = XS_PERM_NONE; + perms[1].id = xenbus->backend_id; + perms[1].perms = XS_PERM_READ | XS_PERM_WRITE; + + g_assert(xenbus->xsh); + + xs_node_create(xenbus->xsh, XBT_NULL, xendev->frontend_path, perms, + ARRAY_SIZE(perms), &local_err); + if (local_err) { + error_propagate_prepend(errp, local_err, + "failed to create frontend: "); + } +} + +static void xen_device_frontend_destroy(XenDevice *xendev) +{ + XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev))); + Error *local_err = NULL; + + if (!xendev->frontend_path) { + return; + } + + g_assert(xenbus->xsh); + + xs_node_destroy(xenbus->xsh, XBT_NULL, xendev->frontend_path, + &local_err); + g_free(xendev->frontend_path); + xendev->frontend_path = NULL; + + if (local_err) { + error_report_err(local_err); + } +} + static void xen_device_unrealize(DeviceState *dev, Error **errp) { XenDevice *xendev = XEN_DEVICE(dev); XenDeviceClass *xendev_class = XEN_DEVICE_GET_CLASS(xendev); const char *type = object_get_typename(OBJECT(xendev)); - trace_xen_device_unrealize(type); + if (!xendev->name) { + return; + } + + trace_xen_device_unrealize(type, xendev->name); + + if (xendev->exit.notify) { + qemu_remove_exit_notifier(&xendev->exit); + xendev->exit.notify = NULL; + } if (xendev_class->unrealize) { xendev_class->unrealize(xendev, errp); } + + xen_device_frontend_destroy(xendev); + xen_device_backend_destroy(xendev); + + g_free(xendev->name); + xendev->name = NULL; +} + +static void xen_device_exit(Notifier *n, void *data) +{ + XenDevice *xendev = container_of(n, XenDevice, exit); + + xen_device_unrealize(DEVICE(xendev), &error_abort); } static void xen_device_realize(DeviceState *dev, Error **errp) { XenDevice *xendev = XEN_DEVICE(dev); XenDeviceClass *xendev_class = XEN_DEVICE_GET_CLASS(xendev); + XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev))); const char *type = object_get_typename(OBJECT(xendev)); Error *local_err = NULL; - trace_xen_device_realize(type); + if (xendev->frontend_id == DOMID_INVALID) { + xendev->frontend_id = xen_domid; + } + + if (xendev->frontend_id >= DOMID_FIRST_RESERVED) { + error_setg(errp, "invalid frontend-id"); + goto unrealize; + } + + if (!xendev_class->get_name) { + error_setg(errp, "get_name method not implemented"); + goto unrealize; + } + + xendev->name = xendev_class->get_name(xendev, &local_err); + if (local_err) { + error_propagate_prepend(errp, local_err, + "failed to get device name: "); + goto unrealize; + } + + trace_xen_device_realize(type, xendev->name); + + xen_device_backend_create(xendev, &local_err); + if (local_err) { + error_propagate(errp, local_err); + goto unrealize; + } + + xen_device_frontend_create(xendev, &local_err); + if (local_err) { + error_propagate(errp, local_err); + goto unrealize; + } if (xendev_class->realize) { xendev_class->realize(xendev, &local_err); @@ -72,18 +364,43 @@ static void xen_device_realize(DeviceState *dev, Error **errp) } } + xen_device_backend_printf(xendev, "frontend", "%s", + xendev->frontend_path); + xen_device_backend_printf(xendev, "frontend-id", "%u", + xendev->frontend_id); + xen_device_backend_printf(xendev, "online", "%u", 1); + xen_device_backend_printf(xendev, "hotplug-status", "connected"); + + xen_device_backend_set_state(xendev, XenbusStateInitWait); + + xen_device_frontend_printf(xendev, "backend", "%s", + xendev->backend_path); + xen_device_frontend_printf(xendev, "backend-id", "%u", + xenbus->backend_id); + + xen_device_frontend_set_state(xendev, XenbusStateInitialising); + + xendev->exit.notify = xen_device_exit; + qemu_add_exit_notifier(&xendev->exit); return; unrealize: xen_device_unrealize(dev, &error_abort); } +static Property xen_device_props[] = { + DEFINE_PROP_UINT16("frontend-id", XenDevice, frontend_id, + DOMID_INVALID), + DEFINE_PROP_END_OF_LIST() +}; + static void xen_device_class_init(ObjectClass *class, void *data) { DeviceClass *dev_class = DEVICE_CLASS(class); dev_class->realize = xen_device_realize; dev_class->unrealize = xen_device_unrealize; + dev_class->props = xen_device_props; dev_class->bus_type = TYPE_XEN_BUS; } diff --git a/include/hw/xen/xen-bus-helper.h b/include/hw/xen/xen-bus-helper.h new file mode 100644 index 0000000000..5cd9c3d759 --- /dev/null +++ b/include/hw/xen/xen-bus-helper.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2018 Citrix Systems Inc. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef HW_XEN_BUS_HELPER_H +#define HW_XEN_BUS_HELPER_H + +#include "hw/xen/xen_common.h" + +const char *xs_strstate(enum xenbus_state state); + +void xs_node_create(struct xs_handle *xsh, xs_transaction_t tid, + const char *node, struct xs_permissions perms[], + unsigned int nr_perms, Error **errp); +void xs_node_destroy(struct xs_handle *xsh, xs_transaction_t tid, + const char *node, Error **errp); + +/* Write to node/key unless node is empty, in which case write to key */ +void xs_node_vprintf(struct xs_handle *xsh, xs_transaction_t tid, + const char *node, const char *key, Error **errp, + const char *fmt, va_list ap) + GCC_FMT_ATTR(6, 0); +void xs_node_printf(struct xs_handle *xsh, xs_transaction_t tid, + const char *node, const char *key, Error **errp, + const char *fmt, ...) + GCC_FMT_ATTR(6, 7); + +/* Read from node/key unless node is empty, in which case read from key */ +int xs_node_vscanf(struct xs_handle *xsh, xs_transaction_t tid, + const char *node, const char *key, Error **errp, + const char *fmt, va_list ap); +int xs_node_scanf(struct xs_handle *xsh, xs_transaction_t tid, + const char *node, const char *key, Error **errp, + const char *fmt, ...); + +#endif /* HW_XEN_BUS_HELPER_H */ diff --git a/include/hw/xen/xen-bus.h b/include/hw/xen/xen-bus.h index 0cb12464ce..85a75d8dec 100644 --- a/include/hw/xen/xen-bus.h +++ b/include/hw/xen/xen-bus.h @@ -8,12 +8,19 @@ #ifndef HW_XEN_BUS_H #define HW_XEN_BUS_H +#include "hw/xen/xen_common.h" #include "hw/sysbus.h" typedef struct XenDevice { DeviceState qdev; + domid_t frontend_id; + char *name; + char *backend_path, *frontend_path; + enum xenbus_state backend_state, frontend_state; + Notifier exit; } XenDevice; +typedef char *(*XenDeviceGetName)(XenDevice *xendev, Error **errp); typedef void (*XenDeviceRealize)(XenDevice *xendev, Error **errp); typedef void (*XenDeviceUnrealize)(XenDevice *xendev, Error **errp); @@ -21,6 +28,9 @@ typedef struct XenDeviceClass { /*< private >*/ DeviceClass parent_class; /*< public >*/ + const char *backend; + const char *device; + XenDeviceGetName get_name; XenDeviceRealize realize; XenDeviceUnrealize unrealize; } XenDeviceClass; @@ -35,6 +45,8 @@ typedef struct XenDeviceClass { typedef struct XenBus { BusState qbus; + domid_t backend_id; + struct xs_handle *xsh; } XenBus; typedef struct XenBusClass { From patchwork Mon Jan 14 13:51:36 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anthony PERARD X-Patchwork-Id: 10762681 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 3F4041390 for ; Mon, 14 Jan 2019 14:02:04 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 29E4828CC6 for ; Mon, 14 Jan 2019 14:02:04 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 254B828CD5; Mon, 14 Jan 2019 14:02:04 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id DC78A28BF2 for ; Mon, 14 Jan 2019 14:02:02 +0000 (UTC) Received: from localhost ([127.0.0.1]:33283 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gj2oU-0000qK-4y for patchwork-qemu-devel@patchwork.kernel.org; Mon, 14 Jan 2019 09:02:02 -0500 Received: from eggs.gnu.org ([209.51.188.92]:45786) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gj2iz-0004gJ-WE for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:56:23 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gj2eu-0002Os-8Z for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:52:11 -0500 Received: from smtp03.citrix.com ([162.221.156.55]:65436) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gj2et-0002O0-Vb for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:52:08 -0500 X-IronPort-AV: E=Sophos;i="5.56,477,1539648000"; d="scan'208";a="75506444" From: Anthony PERARD To: Date: Mon, 14 Jan 2019 13:51:36 +0000 Message-ID: <20190114135154.16826-8-anthony.perard@citrix.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190114135154.16826-1-anthony.perard@citrix.com> References: <20190114135154.16826-1-anthony.perard@citrix.com> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 162.221.156.55 Subject: [Qemu-devel] [PULL 07/25] xen: add xenstore watcher infrastructure X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Anthony PERARD , xen-devel@lists.xenproject.org, Peter Maydell Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Paul Durrant A Xen PV frontend communicates its state to the PV backend by writing to the 'state' key in the frontend area in xenstore. It is therefore necessary for a XenDevice implementation to be notified whenever the value of this key changes. This patch adds code to do this as follows: - an 'fd handler' is registered on the libxenstore handle which will be triggered whenever a 'watch' event occurs - primitives are added to xen-bus-helper to add or remove watch events - a list of Notifier objects is added to XenBus to provide a mechanism to call the appropriate 'watch handler' when its associated event occurs The xen-block implementation is extended with a 'frontend_changed' method, which calls as-yet stub 'connect' and 'disconnect' functions when the relevant frontend state transitions occur. A subsequent patch will supply a full implementation for these functions. Signed-off-by: Paul Durrant Reviewed-by: Anthony Perard Signed-off-by: Anthony PERARD --- hw/block/trace-events | 2 + hw/block/xen-block.c | 70 +++++++++++ hw/xen/trace-events | 6 + hw/xen/xen-bus-helper.c | 34 +++++ hw/xen/xen-bus.c | 211 +++++++++++++++++++++++++++++++- include/hw/xen/xen-bus-helper.h | 6 + include/hw/xen/xen-bus.h | 15 +++ 7 files changed, 342 insertions(+), 2 deletions(-) diff --git a/hw/block/trace-events b/hw/block/trace-events index 4afbd62a88..89e258319c 100644 --- a/hw/block/trace-events +++ b/hw/block/trace-events @@ -130,6 +130,8 @@ xen_disk_free(char *name) "%s" # hw/block/xen-block.c xen_block_realize(const char *type, uint32_t disk, uint32_t partition) "%s d%up%u" +xen_block_connect(const char *type, uint32_t disk, uint32_t partition) "%s d%up%u" +xen_block_disconnect(const char *type, uint32_t disk, uint32_t partition) "%s d%up%u" xen_block_unrealize(const char *type, uint32_t disk, uint32_t partition) "%s d%up%u" xen_disk_realize(void) "" xen_disk_unrealize(void) "" diff --git a/hw/block/xen-block.c b/hw/block/xen-block.c index d27a2865bc..3a963b0383 100644 --- a/hw/block/xen-block.c +++ b/hw/block/xen-block.c @@ -21,6 +21,24 @@ static char *xen_block_get_name(XenDevice *xendev, Error **errp) return g_strdup_printf("%lu", vdev->number); } +static void xen_block_disconnect(XenDevice *xendev, Error **errp) +{ + XenBlockDevice *blockdev = XEN_BLOCK_DEVICE(xendev); + const char *type = object_get_typename(OBJECT(blockdev)); + XenBlockVdev *vdev = &blockdev->props.vdev; + + trace_xen_block_disconnect(type, vdev->disk, vdev->partition); +} + +static void xen_block_connect(XenDevice *xendev, Error **errp) +{ + XenBlockDevice *blockdev = XEN_BLOCK_DEVICE(xendev); + const char *type = object_get_typename(OBJECT(blockdev)); + XenBlockVdev *vdev = &blockdev->props.vdev; + + trace_xen_block_connect(type, vdev->disk, vdev->partition); +} + static void xen_block_unrealize(XenDevice *xendev, Error **errp) { XenBlockDevice *blockdev = XEN_BLOCK_DEVICE(xendev); @@ -35,6 +53,9 @@ static void xen_block_unrealize(XenDevice *xendev, Error **errp) trace_xen_block_unrealize(type, vdev->disk, vdev->partition); + /* Disconnect from the frontend in case this has not already happened */ + xen_block_disconnect(xendev, NULL); + if (blockdev_class->unrealize) { blockdev_class->unrealize(blockdev, errp); } @@ -64,6 +85,54 @@ static void xen_block_realize(XenDevice *xendev, Error **errp) } } +static void xen_block_frontend_changed(XenDevice *xendev, + enum xenbus_state frontend_state, + Error **errp) +{ + enum xenbus_state backend_state = xen_device_backend_get_state(xendev); + Error *local_err = NULL; + + switch (frontend_state) { + case XenbusStateInitialised: + case XenbusStateConnected: + if (backend_state == XenbusStateConnected) { + break; + } + + xen_block_disconnect(xendev, &local_err); + if (local_err) { + error_propagate(errp, local_err); + break; + } + + xen_block_connect(xendev, &local_err); + if (local_err) { + error_propagate(errp, local_err); + break; + } + + xen_device_backend_set_state(xendev, XenbusStateConnected); + break; + + case XenbusStateClosing: + xen_device_backend_set_state(xendev, XenbusStateClosing); + break; + + case XenbusStateClosed: + xen_block_disconnect(xendev, &local_err); + if (local_err) { + error_propagate(errp, local_err); + break; + } + + xen_device_backend_set_state(xendev, XenbusStateClosed); + break; + + default: + break; + } +} + static char *disk_to_vbd_name(unsigned int disk) { char *name, *prefix = (disk >= 26) ? @@ -272,6 +341,7 @@ static void xen_block_class_init(ObjectClass *class, void *data) xendev_class->get_name = xen_block_get_name; xendev_class->realize = xen_block_realize; + xendev_class->frontend_changed = xen_block_frontend_changed; xendev_class->unrealize = xen_block_unrealize; dev_class->props = xen_block_props; diff --git a/hw/xen/trace-events b/hw/xen/trace-events index 75dc226d75..22055b5894 100644 --- a/hw/xen/trace-events +++ b/hw/xen/trace-events @@ -16,13 +16,19 @@ xen_domid_restrict(int err) "err: %u" # include/hw/xen/xen-bus.c xen_bus_realize(void) "" xen_bus_unrealize(void) "" +xen_bus_add_watch(const char *node, const char *key, char *token) "node: %s key: %s token: %s" +xen_bus_remove_watch(const char *node, const char *key, char *token) "node: %s key: %s token: %s" +xen_bus_watch(const char *token) "token: %s" xen_device_realize(const char *type, char *name) "type: %s name: %s" xen_device_unrealize(const char *type, char *name) "type: %s name: %s" xen_device_backend_state(const char *type, char *name, const char *state) "type: %s name: %s -> %s" xen_device_frontend_state(const char *type, char *name, const char *state) "type: %s name: %s -> %s" +xen_device_frontend_changed(const char *type, char *name) "type: %s name: %s" # include/hw/xen/xen-bus-helper.c xs_node_create(const char *node) "%s" xs_node_destroy(const char *node) "%s" xs_node_vprintf(char *path, char *value) "%s %s" xs_node_vscanf(char *path, char *value) "%s %s" +xs_node_watch(char *path) "%s" +xs_node_unwatch(char *path) "%s" diff --git a/hw/xen/xen-bus-helper.c b/hw/xen/xen-bus-helper.c index 15b3ad8d78..5f7a4b2612 100644 --- a/hw/xen/xen-bus-helper.c +++ b/hw/xen/xen-bus-helper.c @@ -148,3 +148,37 @@ int xs_node_scanf(struct xs_handle *xsh, xs_transaction_t tid, return rc; } + +void xs_node_watch(struct xs_handle *xsh, const char *node, const char *key, + char *token, Error **errp) +{ + char *path; + + path = (strlen(node) != 0) ? g_strdup_printf("%s/%s", node, key) : + g_strdup(key); + + trace_xs_node_watch(path); + + if (!xs_watch(xsh, path, token)) { + error_setg_errno(errp, errno, "failed to watch node '%s'", path); + } + + g_free(path); +} + +void xs_node_unwatch(struct xs_handle *xsh, const char *node, + const char *key, const char *token, Error **errp) +{ + char *path; + + path = (strlen(node) != 0) ? g_strdup_printf("%s/%s", node, key) : + g_strdup(key); + + trace_xs_node_unwatch(path); + + if (!xs_unwatch(xsh, path, token)) { + error_setg_errno(errp, errno, "failed to unwatch node '%s'", path); + } + + g_free(path); +} diff --git a/hw/xen/xen-bus.c b/hw/xen/xen-bus.c index 843fda26a9..5e19592190 100644 --- a/hw/xen/xen-bus.c +++ b/hw/xen/xen-bus.c @@ -6,6 +6,8 @@ */ #include "qemu/osdep.h" +#include "qemu/main-loop.h" +#include "qemu/uuid.h" #include "hw/hw.h" #include "hw/sysbus.h" #include "hw/xen/xen.h" @@ -59,6 +61,87 @@ static char *xen_bus_get_dev_path(DeviceState *dev) return xen_device_get_backend_path(XEN_DEVICE(dev)); } +struct XenWatch { + char *node, *key; + char *token; + XenWatchHandler handler; + void *opaque; + Notifier notifier; +}; + +static void watch_notify(Notifier *n, void *data) +{ + XenWatch *watch = container_of(n, XenWatch, notifier); + const char *token = data; + + if (!strcmp(watch->token, token)) { + watch->handler(watch->opaque); + } +} + +static XenWatch *new_watch(const char *node, const char *key, + XenWatchHandler handler, void *opaque) +{ + XenWatch *watch = g_new0(XenWatch, 1); + QemuUUID uuid; + + qemu_uuid_generate(&uuid); + + watch->token = qemu_uuid_unparse_strdup(&uuid); + watch->node = g_strdup(node); + watch->key = g_strdup(key); + watch->handler = handler; + watch->opaque = opaque; + watch->notifier.notify = watch_notify; + + return watch; +} + +static void free_watch(XenWatch *watch) +{ + g_free(watch->token); + g_free(watch->key); + g_free(watch->node); + + g_free(watch); +} + +static XenWatch *xen_bus_add_watch(XenBus *xenbus, const char *node, + const char *key, XenWatchHandler handler, + void *opaque, Error **errp) +{ + XenWatch *watch = new_watch(node, key, handler, opaque); + Error *local_err = NULL; + + trace_xen_bus_add_watch(watch->node, watch->key, watch->token); + + notifier_list_add(&xenbus->watch_notifiers, &watch->notifier); + + xs_node_watch(xenbus->xsh, node, key, watch->token, &local_err); + if (local_err) { + error_propagate(errp, local_err); + + notifier_remove(&watch->notifier); + free_watch(watch); + + return NULL; + } + + return watch; +} + +static void xen_bus_remove_watch(XenBus *xenbus, XenWatch *watch, + Error **errp) +{ + trace_xen_bus_remove_watch(watch->node, watch->key, watch->token); + + xs_node_unwatch(xenbus->xsh, watch->node, watch->key, watch->token, + errp); + + notifier_remove(&watch->notifier); + free_watch(watch); +} + static void xen_bus_unrealize(BusState *bus, Error **errp) { XenBus *xenbus = XEN_BUS(bus); @@ -69,9 +152,33 @@ static void xen_bus_unrealize(BusState *bus, Error **errp) return; } + qemu_set_fd_handler(xs_fileno(xenbus->xsh), NULL, NULL, NULL); + xs_close(xenbus->xsh); } +static void xen_bus_watch(void *opaque) +{ + XenBus *xenbus = opaque; + char **v; + const char *token; + + g_assert(xenbus->xsh); + + v = xs_check_watch(xenbus->xsh); + if (!v) { + return; + } + + token = v[XS_WATCH_TOKEN]; + + trace_xen_bus_watch(token); + + notifier_list_notify(&xenbus->watch_notifiers, (void *)token); + + free(v); +} + static void xen_bus_realize(BusState *bus, Error **errp) { XenBus *xenbus = XEN_BUS(bus); @@ -92,6 +199,9 @@ static void xen_bus_realize(BusState *bus, Error **errp) xenbus->backend_id = 0; /* Assume lack of node means dom0 */ } + notifier_list_init(&xenbus->watch_notifiers); + qemu_set_fd_handler(xs_fileno(xenbus->xsh), xen_bus_watch, NULL, + xenbus); return; fail: @@ -139,8 +249,25 @@ static void xen_device_backend_printf(XenDevice *xendev, const char *key, } } -static void xen_device_backend_set_state(XenDevice *xendev, - enum xenbus_state state) +static int xen_device_backend_scanf(XenDevice *xendev, const char *key, + const char *fmt, ...) +{ + XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev))); + va_list ap; + int rc; + + g_assert(xenbus->xsh); + + va_start(ap, fmt); + rc = xs_node_vscanf(xenbus->xsh, XBT_NULL, xendev->backend_path, key, + NULL, fmt, ap); + va_end(ap); + + return rc; +} + +void xen_device_backend_set_state(XenDevice *xendev, + enum xenbus_state state) { const char *type = object_get_typename(OBJECT(xendev)); @@ -155,6 +282,11 @@ static void xen_device_backend_set_state(XenDevice *xendev, xen_device_backend_printf(xendev, "state", "%u", state); } +enum xenbus_state xen_device_backend_get_state(XenDevice *xendev) +{ + return xendev->backend_state; +} + static void xen_device_backend_create(XenDevice *xendev, Error **errp) { XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev))); @@ -218,6 +350,23 @@ static void xen_device_frontend_printf(XenDevice *xendev, const char *key, } } +static int xen_device_frontend_scanf(XenDevice *xendev, const char *key, + const char *fmt, ...) +{ + XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev))); + va_list ap; + int rc; + + g_assert(xenbus->xsh); + + va_start(ap, fmt); + rc = xs_node_vscanf(xenbus->xsh, XBT_NULL, xendev->frontend_path, key, + NULL, fmt, ap); + va_end(ap); + + return rc; +} + static void xen_device_frontend_set_state(XenDevice *xendev, enum xenbus_state state) { @@ -234,6 +383,50 @@ static void xen_device_frontend_set_state(XenDevice *xendev, xen_device_frontend_printf(xendev, "state", "%u", state); } +static void xen_device_frontend_changed(void *opaque) +{ + XenDevice *xendev = opaque; + XenDeviceClass *xendev_class = XEN_DEVICE_GET_CLASS(xendev); + const char *type = object_get_typename(OBJECT(xendev)); + enum xenbus_state state; + + trace_xen_device_frontend_changed(type, xendev->name); + + if (xen_device_frontend_scanf(xendev, "state", "%u", &state) != 1) { + state = XenbusStateUnknown; + } + + xen_device_frontend_set_state(xendev, state); + + if (xendev_class->frontend_changed) { + Error *local_err = NULL; + + xendev_class->frontend_changed(xendev, state, &local_err); + + if (local_err) { + error_reportf_err(local_err, "frontend change error: "); + } + } + + /* + * If a backend is still 'online' then its state should be cycled + * back round to InitWait in order for a new frontend instance to + * connect. This may happen when, for example, a frontend driver is + * re-installed or updated. + */ + if (xendev->backend_state == XenbusStateClosed) { + unsigned int online; + + if (xen_device_backend_scanf(xendev, "online", "%u", &online) != 1) { + online = 0; + } + + if (online) { + xen_device_backend_set_state(xendev, XenbusStateInitWait); + } + } +} + static void xen_device_frontend_create(XenDevice *xendev, Error **errp) { XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev))); @@ -254,6 +447,15 @@ static void xen_device_frontend_create(XenDevice *xendev, Error **errp) if (local_err) { error_propagate_prepend(errp, local_err, "failed to create frontend: "); + return; + } + + xendev->frontend_state_watch = + xen_bus_add_watch(xenbus, xendev->frontend_path, "state", + xen_device_frontend_changed, xendev, &local_err); + if (local_err) { + error_propagate_prepend(errp, local_err, + "failed to watch frontend state: "); } } @@ -262,6 +464,11 @@ static void xen_device_frontend_destroy(XenDevice *xendev) XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev))); Error *local_err = NULL; + if (xendev->frontend_state_watch) { + xen_bus_remove_watch(xenbus, xendev->frontend_state_watch, NULL); + xendev->frontend_state_watch = NULL; + } + if (!xendev->frontend_path) { return; } diff --git a/include/hw/xen/xen-bus-helper.h b/include/hw/xen/xen-bus-helper.h index 5cd9c3d759..4c0f747445 100644 --- a/include/hw/xen/xen-bus-helper.h +++ b/include/hw/xen/xen-bus-helper.h @@ -36,4 +36,10 @@ int xs_node_scanf(struct xs_handle *xsh, xs_transaction_t tid, const char *node, const char *key, Error **errp, const char *fmt, ...); +/* Watch node/key unless node is empty, in which case watch key */ +void xs_node_watch(struct xs_handle *xsh, const char *node, const char *key, + char *token, Error **errp); +void xs_node_unwatch(struct xs_handle *xsh, const char *node, const char *key, + const char *token, Error **errp); + #endif /* HW_XEN_BUS_HELPER_H */ diff --git a/include/hw/xen/xen-bus.h b/include/hw/xen/xen-bus.h index 85a75d8dec..df73674fcd 100644 --- a/include/hw/xen/xen-bus.h +++ b/include/hw/xen/xen-bus.h @@ -10,6 +10,11 @@ #include "hw/xen/xen_common.h" #include "hw/sysbus.h" +#include "qemu/notify.h" + +typedef void (*XenWatchHandler)(void *opaque); + +typedef struct XenWatch XenWatch; typedef struct XenDevice { DeviceState qdev; @@ -18,10 +23,14 @@ typedef struct XenDevice { char *backend_path, *frontend_path; enum xenbus_state backend_state, frontend_state; Notifier exit; + XenWatch *frontend_state_watch; } XenDevice; typedef char *(*XenDeviceGetName)(XenDevice *xendev, Error **errp); typedef void (*XenDeviceRealize)(XenDevice *xendev, Error **errp); +typedef void (*XenDeviceFrontendChanged)(XenDevice *xendev, + enum xenbus_state frontend_state, + Error **errp); typedef void (*XenDeviceUnrealize)(XenDevice *xendev, Error **errp); typedef struct XenDeviceClass { @@ -32,6 +41,7 @@ typedef struct XenDeviceClass { const char *device; XenDeviceGetName get_name; XenDeviceRealize realize; + XenDeviceFrontendChanged frontend_changed; XenDeviceUnrealize unrealize; } XenDeviceClass; @@ -47,6 +57,7 @@ typedef struct XenBus { BusState qbus; domid_t backend_id; struct xs_handle *xsh; + NotifierList watch_notifiers; } XenBus; typedef struct XenBusClass { @@ -64,4 +75,8 @@ typedef struct XenBusClass { void xen_bus_init(void); +void xen_device_backend_set_state(XenDevice *xendev, + enum xenbus_state state); +enum xenbus_state xen_device_backend_get_state(XenDevice *xendev); + #endif /* HW_XEN_BUS_H */ From patchwork Mon Jan 14 13:51:37 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anthony PERARD X-Patchwork-Id: 10762693 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 38CF86C2 for ; Mon, 14 Jan 2019 14:08:29 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2535428CCE for ; Mon, 14 Jan 2019 14:08:29 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1909A28CDC; Mon, 14 Jan 2019 14:08:29 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 72D1128CCE for ; Mon, 14 Jan 2019 14:08:28 +0000 (UTC) Received: from localhost ([127.0.0.1]:34576 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gj2uh-0005Wa-KU for patchwork-qemu-devel@patchwork.kernel.org; Mon, 14 Jan 2019 09:08:27 -0500 Received: from eggs.gnu.org ([209.51.188.92]:46005) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gj2iz-0004mz-W7 for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:56:23 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gj2ew-0002Pq-MP for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:52:11 -0500 Received: from smtp03.citrix.com ([162.221.156.55]:65446) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gj2ew-0002PQ-Dp for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:52:10 -0500 X-IronPort-AV: E=Sophos;i="5.56,477,1539648000"; d="scan'208";a="75506450" From: Anthony PERARD To: Date: Mon, 14 Jan 2019 13:51:37 +0000 Message-ID: <20190114135154.16826-9-anthony.perard@citrix.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190114135154.16826-1-anthony.perard@citrix.com> References: <20190114135154.16826-1-anthony.perard@citrix.com> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 162.221.156.55 Subject: [Qemu-devel] [PULL 08/25] xen: add grant table interface for XenDevice-s X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Anthony PERARD , xen-devel@lists.xenproject.org, Peter Maydell Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Paul Durrant The legacy PV backend infrastructure provides functions to map, unmap and copy pages granted by frontends. Similar functionality will be required by XenDevice implementations so this patch adds the necessary support. Signed-off-by: Paul Durrant Reviewed-by: Anthony Perard Signed-off-by: Anthony PERARD --- hw/xen/xen-bus.c | 146 +++++++++++++++++++++++++++++++++++++++ include/hw/xen/xen-bus.h | 25 +++++++ 2 files changed, 171 insertions(+) diff --git a/hw/xen/xen-bus.c b/hw/xen/xen-bus.c index 5e19592190..faa9fd3577 100644 --- a/hw/xen/xen-bus.c +++ b/hw/xen/xen-bus.c @@ -485,6 +485,138 @@ static void xen_device_frontend_destroy(XenDevice *xendev) } } +void xen_device_set_max_grant_refs(XenDevice *xendev, unsigned int nr_refs, + Error **errp) +{ + if (xengnttab_set_max_grants(xendev->xgth, nr_refs)) { + error_setg_errno(errp, errno, "xengnttab_set_max_grants failed"); + } +} + +void *xen_device_map_grant_refs(XenDevice *xendev, uint32_t *refs, + unsigned int nr_refs, int prot, + Error **errp) +{ + void *map = xengnttab_map_domain_grant_refs(xendev->xgth, nr_refs, + xendev->frontend_id, refs, + prot); + + if (!map) { + error_setg_errno(errp, errno, + "xengnttab_map_domain_grant_refs failed"); + } + + return map; +} + +void xen_device_unmap_grant_refs(XenDevice *xendev, void *map, + unsigned int nr_refs, Error **errp) +{ + if (xengnttab_unmap(xendev->xgth, map, nr_refs)) { + error_setg_errno(errp, errno, "xengnttab_unmap failed"); + } +} + +static void compat_copy_grant_refs(XenDevice *xendev, bool to_domain, + XenDeviceGrantCopySegment segs[], + unsigned int nr_segs, Error **errp) +{ + uint32_t *refs = g_new(uint32_t, nr_segs); + int prot = to_domain ? PROT_WRITE : PROT_READ; + void *map; + unsigned int i; + + for (i = 0; i < nr_segs; i++) { + XenDeviceGrantCopySegment *seg = &segs[i]; + + refs[i] = to_domain ? seg->dest.foreign.ref : + seg->source.foreign.ref; + } + + map = xengnttab_map_domain_grant_refs(xendev->xgth, nr_segs, + xendev->frontend_id, refs, + prot); + if (!map) { + error_setg_errno(errp, errno, + "xengnttab_map_domain_grant_refs failed"); + goto done; + } + + for (i = 0; i < nr_segs; i++) { + XenDeviceGrantCopySegment *seg = &segs[i]; + void *page = map + (i * XC_PAGE_SIZE); + + if (to_domain) { + memcpy(page + seg->dest.foreign.offset, seg->source.virt, + seg->len); + } else { + memcpy(seg->dest.virt, page + seg->source.foreign.offset, + seg->len); + } + } + + if (xengnttab_unmap(xendev->xgth, map, nr_segs)) { + error_setg_errno(errp, errno, "xengnttab_unmap failed"); + } + +done: + g_free(refs); +} + +void xen_device_copy_grant_refs(XenDevice *xendev, bool to_domain, + XenDeviceGrantCopySegment segs[], + unsigned int nr_segs, Error **errp) +{ + xengnttab_grant_copy_segment_t *xengnttab_segs; + unsigned int i; + + if (!xendev->feature_grant_copy) { + compat_copy_grant_refs(xendev, to_domain, segs, nr_segs, errp); + return; + } + + xengnttab_segs = g_new0(xengnttab_grant_copy_segment_t, nr_segs); + + for (i = 0; i < nr_segs; i++) { + XenDeviceGrantCopySegment *seg = &segs[i]; + xengnttab_grant_copy_segment_t *xengnttab_seg = &xengnttab_segs[i]; + + if (to_domain) { + xengnttab_seg->flags = GNTCOPY_dest_gref; + xengnttab_seg->dest.foreign.domid = xendev->frontend_id; + xengnttab_seg->dest.foreign.ref = seg->dest.foreign.ref; + xengnttab_seg->dest.foreign.offset = seg->dest.foreign.offset; + xengnttab_seg->source.virt = seg->source.virt; + } else { + xengnttab_seg->flags = GNTCOPY_source_gref; + xengnttab_seg->source.foreign.domid = xendev->frontend_id; + xengnttab_seg->source.foreign.ref = seg->source.foreign.ref; + xengnttab_seg->source.foreign.offset = + seg->source.foreign.offset; + xengnttab_seg->dest.virt = seg->dest.virt; + } + + xengnttab_seg->len = seg->len; + } + + if (xengnttab_grant_copy(xendev->xgth, nr_segs, xengnttab_segs)) { + error_setg_errno(errp, errno, "xengnttab_grant_copy failed"); + goto done; + } + + for (i = 0; i < nr_segs; i++) { + xengnttab_grant_copy_segment_t *xengnttab_seg = &xengnttab_segs[i]; + + if (xengnttab_seg->status != GNTST_okay) { + error_setg(errp, "xengnttab_grant_copy seg[%u] failed", i); + break; + } + } + +done: + g_free(xengnttab_segs); +} + static void xen_device_unrealize(DeviceState *dev, Error **errp) { XenDevice *xendev = XEN_DEVICE(dev); @@ -509,6 +641,11 @@ static void xen_device_unrealize(DeviceState *dev, Error **errp) xen_device_frontend_destroy(xendev); xen_device_backend_destroy(xendev); + if (xendev->xgth) { + xengnttab_close(xendev->xgth); + xendev->xgth = NULL; + } + g_free(xendev->name); xendev->name = NULL; } @@ -551,6 +688,15 @@ static void xen_device_realize(DeviceState *dev, Error **errp) trace_xen_device_realize(type, xendev->name); + xendev->xgth = xengnttab_open(NULL, 0); + if (!xendev->xgth) { + error_setg_errno(errp, errno, "failed xengnttab_open"); + goto unrealize; + } + + xendev->feature_grant_copy = + (xengnttab_grant_copy(xendev->xgth, 0, NULL) == 0); + xen_device_backend_create(xendev, &local_err); if (local_err) { error_propagate(errp, local_err); diff --git a/include/hw/xen/xen-bus.h b/include/hw/xen/xen-bus.h index df73674fcd..63a09b67ee 100644 --- a/include/hw/xen/xen-bus.h +++ b/include/hw/xen/xen-bus.h @@ -24,6 +24,8 @@ typedef struct XenDevice { enum xenbus_state backend_state, frontend_state; Notifier exit; XenWatch *frontend_state_watch; + xengnttab_handle *xgth; + bool feature_grant_copy; } XenDevice; typedef char *(*XenDeviceGetName)(XenDevice *xendev, Error **errp); @@ -79,4 +81,27 @@ void xen_device_backend_set_state(XenDevice *xendev, enum xenbus_state state); enum xenbus_state xen_device_backend_get_state(XenDevice *xendev); +void xen_device_set_max_grant_refs(XenDevice *xendev, unsigned int nr_refs, + Error **errp); +void *xen_device_map_grant_refs(XenDevice *xendev, uint32_t *refs, + unsigned int nr_refs, int prot, + Error **errp); +void xen_device_unmap_grant_refs(XenDevice *xendev, void *map, + unsigned int nr_refs, Error **errp); + +typedef struct XenDeviceGrantCopySegment { + union { + void *virt; + struct { + uint32_t ref; + off_t offset; + } foreign; + } source, dest; + size_t len; +} XenDeviceGrantCopySegment; + +void xen_device_copy_grant_refs(XenDevice *xendev, bool to_domain, + XenDeviceGrantCopySegment segs[], + unsigned int nr_segs, Error **errp); + #endif /* HW_XEN_BUS_H */ From patchwork Mon Jan 14 13:51:38 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anthony PERARD X-Patchwork-Id: 10762671 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 393B51390 for ; Mon, 14 Jan 2019 13:57:54 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 271AD28BC2 for ; Mon, 14 Jan 2019 13:57:54 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1B0B628BD9; Mon, 14 Jan 2019 13:57:54 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 7A32028BC2 for ; Mon, 14 Jan 2019 13:57:53 +0000 (UTC) Received: from localhost ([127.0.0.1]:60558 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gj2kS-00061X-Ot for patchwork-qemu-devel@patchwork.kernel.org; Mon, 14 Jan 2019 08:57:52 -0500 Received: from eggs.gnu.org ([209.51.188.92]:45938) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gj2in-0004hh-DB for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:56:10 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gj2fY-0002eS-7W for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:52:49 -0500 Received: from smtp03.citrix.com ([162.221.156.55]:65464) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gj2fX-0002cK-Sl for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:52:48 -0500 X-IronPort-AV: E=Sophos;i="5.56,477,1539648000"; d="scan'208";a="75506463" From: Anthony PERARD To: Date: Mon, 14 Jan 2019 13:51:38 +0000 Message-ID: <20190114135154.16826-10-anthony.perard@citrix.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190114135154.16826-1-anthony.perard@citrix.com> References: <20190114135154.16826-1-anthony.perard@citrix.com> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 162.221.156.55 Subject: [Qemu-devel] [PULL 09/25] xen: add event channel interface for XenDevice-s X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Anthony PERARD , xen-devel@lists.xenproject.org, Peter Maydell Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Paul Durrant The legacy PV backend infrastructure provides functions to bind, unbind and send notifications to event channnels. Similar functionality will be required by XenDevice implementations so this patch adds the necessary support. Signed-off-by: Paul Durrant Reviewed-by: Anthony Perard Signed-off-by: Anthony PERARD Patch squashed with: Patch "xen: add event channel interface for XenDevice-s" makes use of the type xenevtchn_port_or_error_t, but this isn't avaiable before Xen 4.7. Also the function xen_device_bind_event_channel assign the return value of xenevtchn_bind_interdomain to channel->local_port but check the result for error with xendev->local_port. Fix by: - removing local_port from struct XenDevice as it isn't use anywere. - adding a compatibility typedef for xenevtchn_port_or_error_t for Xen 4.6 and earlier. As extra, replace the type of XenEventChannel->local_port by evtchn_port_t. Signed-off-by: Anthony PERARD Reviewed-by: Paul Durrant --- hw/xen/xen-bus.c | 103 ++++++++++++++++++++++++++++++++++++ include/hw/xen/xen-bus.h | 17 ++++++ include/hw/xen/xen_common.h | 1 + 3 files changed, 121 insertions(+) diff --git a/hw/xen/xen-bus.c b/hw/xen/xen-bus.c index faa9fd3577..14881126ff 100644 --- a/hw/xen/xen-bus.c +++ b/hw/xen/xen-bus.c @@ -617,6 +617,83 @@ void xen_device_copy_grant_refs(XenDevice *xendev, bool to_domain, g_free(xengnttab_segs); } +struct XenEventChannel { + evtchn_port_t local_port; + XenEventHandler handler; + void *opaque; + Notifier notifier; +}; + +static void event_notify(Notifier *n, void *data) +{ + XenEventChannel *channel = container_of(n, XenEventChannel, notifier); + unsigned long port = (unsigned long)data; + + if (port == channel->local_port) { + channel->handler(channel->opaque); + } +} + +XenEventChannel *xen_device_bind_event_channel(XenDevice *xendev, + unsigned int port, + XenEventHandler handler, + void *opaque, Error **errp) +{ + XenEventChannel *channel = g_new0(XenEventChannel, 1); + xenevtchn_port_or_error_t local_port; + + local_port = xenevtchn_bind_interdomain(xendev->xeh, + xendev->frontend_id, + port); + if (local_port < 0) { + error_setg_errno(errp, errno, "xenevtchn_bind_interdomain failed"); + + g_free(channel); + return NULL; + } + + channel->local_port = local_port; + channel->handler = handler; + channel->opaque = opaque; + channel->notifier.notify = event_notify; + + notifier_list_add(&xendev->event_notifiers, &channel->notifier); + + return channel; +} + +void xen_device_notify_event_channel(XenDevice *xendev, + XenEventChannel *channel, + Error **errp) +{ + if (!channel) { + error_setg(errp, "bad channel"); + return; + } + + if (xenevtchn_notify(xendev->xeh, channel->local_port) < 0) { + error_setg_errno(errp, errno, "xenevtchn_notify failed"); + } +} + +void xen_device_unbind_event_channel(XenDevice *xendev, + XenEventChannel *channel, + Error **errp) +{ + if (!channel) { + error_setg(errp, "bad channel"); + return; + } + + notifier_remove(&channel->notifier); + + if (xenevtchn_unbind(xendev->xeh, channel->local_port) < 0) { + error_setg_errno(errp, errno, "xenevtchn_unbind failed"); + } + + g_free(channel); +} + static void xen_device_unrealize(DeviceState *dev, Error **errp) { XenDevice *xendev = XEN_DEVICE(dev); @@ -641,6 +718,12 @@ static void xen_device_unrealize(DeviceState *dev, Error **errp) xen_device_frontend_destroy(xendev); xen_device_backend_destroy(xendev); + if (xendev->xeh) { + qemu_set_fd_handler(xenevtchn_fd(xendev->xeh), NULL, NULL, NULL); + xenevtchn_close(xendev->xeh); + xendev->xeh = NULL; + } + if (xendev->xgth) { xengnttab_close(xendev->xgth); xendev->xgth = NULL; @@ -657,6 +740,16 @@ static void xen_device_exit(Notifier *n, void *data) xen_device_unrealize(DEVICE(xendev), &error_abort); } +static void xen_device_event(void *opaque) +{ + XenDevice *xendev = opaque; + unsigned long port = xenevtchn_pending(xendev->xeh); + + notifier_list_notify(&xendev->event_notifiers, (void *)port); + + xenevtchn_unmask(xendev->xeh, port); +} + static void xen_device_realize(DeviceState *dev, Error **errp) { XenDevice *xendev = XEN_DEVICE(dev); @@ -697,6 +790,16 @@ static void xen_device_realize(DeviceState *dev, Error **errp) xendev->feature_grant_copy = (xengnttab_grant_copy(xendev->xgth, 0, NULL) == 0); + xendev->xeh = xenevtchn_open(NULL, 0); + if (!xendev->xeh) { + error_setg_errno(errp, errno, "failed xenevtchn_open"); + goto unrealize; + } + + notifier_list_init(&xendev->event_notifiers); + qemu_set_fd_handler(xenevtchn_fd(xendev->xeh), xen_device_event, NULL, + xendev); + xen_device_backend_create(xendev, &local_err); if (local_err) { error_propagate(errp, local_err); diff --git a/include/hw/xen/xen-bus.h b/include/hw/xen/xen-bus.h index 63a09b67ee..b554559e5b 100644 --- a/include/hw/xen/xen-bus.h +++ b/include/hw/xen/xen-bus.h @@ -26,6 +26,8 @@ typedef struct XenDevice { XenWatch *frontend_state_watch; xengnttab_handle *xgth; bool feature_grant_copy; + xenevtchn_handle *xeh; + NotifierList event_notifiers; } XenDevice; typedef char *(*XenDeviceGetName)(XenDevice *xendev, Error **errp); @@ -104,4 +106,19 @@ void xen_device_copy_grant_refs(XenDevice *xendev, bool to_domain, XenDeviceGrantCopySegment segs[], unsigned int nr_segs, Error **errp); +typedef struct XenEventChannel XenEventChannel; + +typedef void (*XenEventHandler)(void *opaque); + +XenEventChannel *xen_device_bind_event_channel(XenDevice *xendev, + unsigned int port, + XenEventHandler handler, + void *opaque, Error **errp); +void xen_device_notify_event_channel(XenDevice *xendev, + XenEventChannel *channel, + Error **errp); +void xen_device_unbind_event_channel(XenDevice *xendev, + XenEventChannel *channel, + Error **errp); + #endif /* HW_XEN_BUS_H */ diff --git a/include/hw/xen/xen_common.h b/include/hw/xen/xen_common.h index 93f631e5bf..9c3ac07d78 100644 --- a/include/hw/xen/xen_common.h +++ b/include/hw/xen/xen_common.h @@ -32,6 +32,7 @@ extern xc_interface *xen_xc; typedef xc_interface xenforeignmemory_handle; typedef xc_evtchn xenevtchn_handle; typedef xc_gnttab xengnttab_handle; +typedef evtchn_port_or_error_t xenevtchn_port_or_error_t; #define xenevtchn_open(l, f) xc_evtchn_open(l, f); #define xenevtchn_close(h) xc_evtchn_close(h) From patchwork Mon Jan 14 13:51:39 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anthony PERARD X-Patchwork-Id: 10762691 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C70616C2 for ; Mon, 14 Jan 2019 14:08:11 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B1ECC28CD4 for ; Mon, 14 Jan 2019 14:08:11 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A5DA728CF0; Mon, 14 Jan 2019 14:08:11 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id C1B6A28CD4 for ; Mon, 14 Jan 2019 14:08:09 +0000 (UTC) Received: from localhost ([127.0.0.1]:34504 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gj2uO-0005Il-Tt for patchwork-qemu-devel@patchwork.kernel.org; Mon, 14 Jan 2019 09:08:09 -0500 Received: from eggs.gnu.org ([209.51.188.92]:47189) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gj2lL-0006le-Kk for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:58:51 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gj2lI-0004fV-A5 for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:58:47 -0500 Received: from smtp03.citrix.com ([162.221.156.55]:1339) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gj2lH-0004Z1-Sf for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:58:44 -0500 X-IronPort-AV: E=Sophos;i="5.56,477,1539648000"; d="scan'208";a="75506978" From: Anthony PERARD To: Date: Mon, 14 Jan 2019 13:51:39 +0000 Message-ID: <20190114135154.16826-11-anthony.perard@citrix.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190114135154.16826-1-anthony.perard@citrix.com> References: <20190114135154.16826-1-anthony.perard@citrix.com> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 162.221.156.55 Subject: [Qemu-devel] [PULL 10/25] xen: duplicate xen_disk.c as basis of dataplane/xen-block.c X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Anthony PERARD , xen-devel@lists.xenproject.org, Peter Maydell Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Paul Durrant The new xen-block XenDevice implementation requires the same core dataplane as the legacy xen_disk implementation it will eventually replace. This patch therefore copies the legacy xen_disk.c source module into a new dataplane/xen-block.c source module as the basis for the new dataplane and adjusts the MAINTAINERS file accordingly. NOTE: The duplicated code is not yet built. It is simply put into place by this patch (just fixing style violations) such that the modifications that will need to be made to the code are not conflated with code movement, thus making review harder. Signed-off-by: Paul Durrant Acked-by: Anthony Perard Signed-off-by: Anthony PERARD --- MAINTAINERS | 1 + hw/block/dataplane/xen-block.c | 1019 ++++++++++++++++++++++++++++++++ 2 files changed, 1020 insertions(+) create mode 100644 hw/block/dataplane/xen-block.c diff --git a/MAINTAINERS b/MAINTAINERS index 7514550c06..4c98b34853 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -415,6 +415,7 @@ F: hw/char/xen_console.c F: hw/display/xenfb.c F: hw/net/xen_nic.c F: hw/block/xen* +F: hw/block/dataplane/xen* F: hw/xen/ F: hw/xenpv/ F: hw/i386/xen/ diff --git a/hw/block/dataplane/xen-block.c b/hw/block/dataplane/xen-block.c new file mode 100644 index 0000000000..9fae50534e --- /dev/null +++ b/hw/block/dataplane/xen-block.c @@ -0,0 +1,1019 @@ +/* + * xen paravirt block device backend + * + * (c) Gerd Hoffmann + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; under version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see . + * + * Contributions after 2012-01-13 are licensed under the terms of the + * GNU GPL, version 2 or (at your option) any later version. + */ + +#include "qemu/osdep.h" +#include "qemu/units.h" +#include +#include + +#include "hw/hw.h" +#include "hw/xen/xen_backend.h" +#include "xen_blkif.h" +#include "sysemu/blockdev.h" +#include "sysemu/iothread.h" +#include "sysemu/block-backend.h" +#include "qapi/error.h" +#include "qapi/qmp/qdict.h" +#include "qapi/qmp/qstring.h" +#include "trace.h" + +/* ------------------------------------------------------------- */ + +#define BLOCK_SIZE 512 +#define IOCB_COUNT (BLKIF_MAX_SEGMENTS_PER_REQUEST + 2) + +struct ioreq { + blkif_request_t req; + int16_t status; + + /* parsed request */ + off_t start; + QEMUIOVector v; + void *buf; + size_t size; + int presync; + + /* aio status */ + int aio_inflight; + int aio_errors; + + struct XenBlkDev *blkdev; + QLIST_ENTRY(ioreq) list; + BlockAcctCookie acct; +}; + +#define MAX_RING_PAGE_ORDER 4 + +struct XenBlkDev { + struct XenLegacyDevice xendev; /* must be first */ + char *params; + char *mode; + char *type; + char *dev; + char *devtype; + bool directiosafe; + const char *fileproto; + const char *filename; + unsigned int ring_ref[1 << MAX_RING_PAGE_ORDER]; + unsigned int nr_ring_ref; + void *sring; + int64_t file_blk; + int64_t file_size; + int protocol; + blkif_back_rings_t rings; + int more_work; + + /* request lists */ + QLIST_HEAD(inflight_head, ioreq) inflight; + QLIST_HEAD(finished_head, ioreq) finished; + QLIST_HEAD(freelist_head, ioreq) freelist; + int requests_total; + int requests_inflight; + int requests_finished; + unsigned int max_requests; + + gboolean feature_discard; + + /* qemu block driver */ + DriveInfo *dinfo; + BlockBackend *blk; + QEMUBH *bh; + + IOThread *iothread; + AioContext *ctx; +}; + +/* ------------------------------------------------------------- */ + +static void ioreq_reset(struct ioreq *ioreq) +{ + memset(&ioreq->req, 0, sizeof(ioreq->req)); + ioreq->status = 0; + ioreq->start = 0; + ioreq->buf = NULL; + ioreq->size = 0; + ioreq->presync = 0; + + ioreq->aio_inflight = 0; + ioreq->aio_errors = 0; + + ioreq->blkdev = NULL; + memset(&ioreq->list, 0, sizeof(ioreq->list)); + memset(&ioreq->acct, 0, sizeof(ioreq->acct)); + + qemu_iovec_reset(&ioreq->v); +} + +static struct ioreq *ioreq_start(struct XenBlkDev *blkdev) +{ + struct ioreq *ioreq = NULL; + + if (QLIST_EMPTY(&blkdev->freelist)) { + if (blkdev->requests_total >= blkdev->max_requests) { + goto out; + } + /* allocate new struct */ + ioreq = g_malloc0(sizeof(*ioreq)); + ioreq->blkdev = blkdev; + blkdev->requests_total++; + qemu_iovec_init(&ioreq->v, 1); + } else { + /* get one from freelist */ + ioreq = QLIST_FIRST(&blkdev->freelist); + QLIST_REMOVE(ioreq, list); + } + QLIST_INSERT_HEAD(&blkdev->inflight, ioreq, list); + blkdev->requests_inflight++; + +out: + return ioreq; +} + +static void ioreq_finish(struct ioreq *ioreq) +{ + struct XenBlkDev *blkdev = ioreq->blkdev; + + QLIST_REMOVE(ioreq, list); + QLIST_INSERT_HEAD(&blkdev->finished, ioreq, list); + blkdev->requests_inflight--; + blkdev->requests_finished++; +} + +static void ioreq_release(struct ioreq *ioreq, bool finish) +{ + struct XenBlkDev *blkdev = ioreq->blkdev; + + QLIST_REMOVE(ioreq, list); + ioreq_reset(ioreq); + ioreq->blkdev = blkdev; + QLIST_INSERT_HEAD(&blkdev->freelist, ioreq, list); + if (finish) { + blkdev->requests_finished--; + } else { + blkdev->requests_inflight--; + } +} + +/* + * translate request into iovec + start offset + * do sanity checks along the way + */ +static int ioreq_parse(struct ioreq *ioreq) +{ + struct XenBlkDev *blkdev = ioreq->blkdev; + struct XenLegacyDevice *xendev = &blkdev->xendev; + size_t len; + int i; + + xen_pv_printf( + xendev, 3, + "op %d, nr %d, handle %d, id %" PRId64 ", sector %" PRId64 "\n", + ioreq->req.operation, ioreq->req.nr_segments, + ioreq->req.handle, ioreq->req.id, ioreq->req.sector_number); + switch (ioreq->req.operation) { + case BLKIF_OP_READ: + break; + case BLKIF_OP_FLUSH_DISKCACHE: + ioreq->presync = 1; + if (!ioreq->req.nr_segments) { + return 0; + } + /* fall through */ + case BLKIF_OP_WRITE: + break; + case BLKIF_OP_DISCARD: + return 0; + default: + xen_pv_printf(xendev, 0, "error: unknown operation (%d)\n", + ioreq->req.operation); + goto err; + }; + + if (ioreq->req.operation != BLKIF_OP_READ && blkdev->mode[0] != 'w') { + xen_pv_printf(xendev, 0, "error: write req for ro device\n"); + goto err; + } + + ioreq->start = ioreq->req.sector_number * blkdev->file_blk; + for (i = 0; i < ioreq->req.nr_segments; i++) { + if (i == BLKIF_MAX_SEGMENTS_PER_REQUEST) { + xen_pv_printf(xendev, 0, "error: nr_segments too big\n"); + goto err; + } + if (ioreq->req.seg[i].first_sect > ioreq->req.seg[i].last_sect) { + xen_pv_printf(xendev, 0, "error: first > last sector\n"); + goto err; + } + if (ioreq->req.seg[i].last_sect * BLOCK_SIZE >= XC_PAGE_SIZE) { + xen_pv_printf(xendev, 0, "error: page crossing\n"); + goto err; + } + + len = (ioreq->req.seg[i].last_sect - + ioreq->req.seg[i].first_sect + 1) * blkdev->file_blk; + ioreq->size += len; + } + if (ioreq->start + ioreq->size > blkdev->file_size) { + xen_pv_printf(xendev, 0, "error: access beyond end of file\n"); + goto err; + } + return 0; + +err: + ioreq->status = BLKIF_RSP_ERROR; + return -1; +} + +static int ioreq_grant_copy(struct ioreq *ioreq) +{ + struct XenBlkDev *blkdev = ioreq->blkdev; + struct XenLegacyDevice *xendev = &blkdev->xendev; + XenGrantCopySegment segs[BLKIF_MAX_SEGMENTS_PER_REQUEST]; + int i, count, rc; + int64_t file_blk = blkdev->file_blk; + bool to_domain = (ioreq->req.operation == BLKIF_OP_READ); + void *virt = ioreq->buf; + + if (ioreq->req.nr_segments == 0) { + return 0; + } + + count = ioreq->req.nr_segments; + + for (i = 0; i < count; i++) { + if (to_domain) { + segs[i].dest.foreign.ref = ioreq->req.seg[i].gref; + segs[i].dest.foreign.offset = ioreq->req.seg[i].first_sect * + file_blk; + segs[i].source.virt = virt; + } else { + segs[i].source.foreign.ref = ioreq->req.seg[i].gref; + segs[i].source.foreign.offset = ioreq->req.seg[i].first_sect * + file_blk; + segs[i].dest.virt = virt; + } + segs[i].len = (ioreq->req.seg[i].last_sect + - ioreq->req.seg[i].first_sect + 1) * file_blk; + virt += segs[i].len; + } + + rc = xen_be_copy_grant_refs(xendev, to_domain, segs, count); + + if (rc) { + xen_pv_printf(xendev, 0, + "failed to copy data %d\n", rc); + ioreq->aio_errors++; + return -1; + } + + return rc; +} + +static int ioreq_runio_qemu_aio(struct ioreq *ioreq); + +static void qemu_aio_complete(void *opaque, int ret) +{ + struct ioreq *ioreq = opaque; + struct XenBlkDev *blkdev = ioreq->blkdev; + struct XenLegacyDevice *xendev = &blkdev->xendev; + + aio_context_acquire(blkdev->ctx); + + if (ret != 0) { + xen_pv_printf(xendev, 0, "%s I/O error\n", + ioreq->req.operation == BLKIF_OP_READ ? "read" : "write"); + ioreq->aio_errors++; + } + + ioreq->aio_inflight--; + if (ioreq->presync) { + ioreq->presync = 0; + ioreq_runio_qemu_aio(ioreq); + goto done; + } + if (ioreq->aio_inflight > 0) { + goto done; + } + + switch (ioreq->req.operation) { + case BLKIF_OP_READ: + /* in case of failure ioreq->aio_errors is increased */ + if (ret == 0) { + ioreq_grant_copy(ioreq); + } + qemu_vfree(ioreq->buf); + break; + case BLKIF_OP_WRITE: + case BLKIF_OP_FLUSH_DISKCACHE: + if (!ioreq->req.nr_segments) { + break; + } + qemu_vfree(ioreq->buf); + break; + default: + break; + } + + ioreq->status = ioreq->aio_errors ? BLKIF_RSP_ERROR : BLKIF_RSP_OKAY; + ioreq_finish(ioreq); + + switch (ioreq->req.operation) { + case BLKIF_OP_WRITE: + case BLKIF_OP_FLUSH_DISKCACHE: + if (!ioreq->req.nr_segments) { + break; + } + case BLKIF_OP_READ: + if (ioreq->status == BLKIF_RSP_OKAY) { + block_acct_done(blk_get_stats(blkdev->blk), &ioreq->acct); + } else { + block_acct_failed(blk_get_stats(blkdev->blk), &ioreq->acct); + } + break; + case BLKIF_OP_DISCARD: + default: + break; + } + qemu_bh_schedule(blkdev->bh); + +done: + aio_context_release(blkdev->ctx); +} + +static bool blk_split_discard(struct ioreq *ioreq, blkif_sector_t sector_number, + uint64_t nr_sectors) +{ + struct XenBlkDev *blkdev = ioreq->blkdev; + int64_t byte_offset; + int byte_chunk; + uint64_t byte_remaining, limit; + uint64_t sec_start = sector_number; + uint64_t sec_count = nr_sectors; + + /* Wrap around, or overflowing byte limit? */ + if (sec_start + sec_count < sec_count || + sec_start + sec_count > INT64_MAX >> BDRV_SECTOR_BITS) { + return false; + } + + limit = BDRV_REQUEST_MAX_SECTORS << BDRV_SECTOR_BITS; + byte_offset = sec_start << BDRV_SECTOR_BITS; + byte_remaining = sec_count << BDRV_SECTOR_BITS; + + do { + byte_chunk = byte_remaining > limit ? limit : byte_remaining; + ioreq->aio_inflight++; + blk_aio_pdiscard(blkdev->blk, byte_offset, byte_chunk, + qemu_aio_complete, ioreq); + byte_remaining -= byte_chunk; + byte_offset += byte_chunk; + } while (byte_remaining > 0); + + return true; +} + +static int ioreq_runio_qemu_aio(struct ioreq *ioreq) +{ + struct XenBlkDev *blkdev = ioreq->blkdev; + + ioreq->buf = qemu_memalign(XC_PAGE_SIZE, ioreq->size); + if (ioreq->req.nr_segments && + (ioreq->req.operation == BLKIF_OP_WRITE || + ioreq->req.operation == BLKIF_OP_FLUSH_DISKCACHE) && + ioreq_grant_copy(ioreq)) { + qemu_vfree(ioreq->buf); + goto err; + } + + ioreq->aio_inflight++; + if (ioreq->presync) { + blk_aio_flush(ioreq->blkdev->blk, qemu_aio_complete, ioreq); + return 0; + } + + switch (ioreq->req.operation) { + case BLKIF_OP_READ: + qemu_iovec_add(&ioreq->v, ioreq->buf, ioreq->size); + block_acct_start(blk_get_stats(blkdev->blk), &ioreq->acct, + ioreq->v.size, BLOCK_ACCT_READ); + ioreq->aio_inflight++; + blk_aio_preadv(blkdev->blk, ioreq->start, &ioreq->v, 0, + qemu_aio_complete, ioreq); + break; + case BLKIF_OP_WRITE: + case BLKIF_OP_FLUSH_DISKCACHE: + if (!ioreq->req.nr_segments) { + break; + } + + qemu_iovec_add(&ioreq->v, ioreq->buf, ioreq->size); + block_acct_start(blk_get_stats(blkdev->blk), &ioreq->acct, + ioreq->v.size, + ioreq->req.operation == BLKIF_OP_WRITE ? + BLOCK_ACCT_WRITE : BLOCK_ACCT_FLUSH); + ioreq->aio_inflight++; + blk_aio_pwritev(blkdev->blk, ioreq->start, &ioreq->v, 0, + qemu_aio_complete, ioreq); + break; + case BLKIF_OP_DISCARD: + { + struct blkif_request_discard *req = (void *)&ioreq->req; + if (!blk_split_discard(ioreq, req->sector_number, req->nr_sectors)) { + goto err; + } + break; + } + default: + /* unknown operation (shouldn't happen -- parse catches this) */ + goto err; + } + + qemu_aio_complete(ioreq, 0); + + return 0; + +err: + ioreq_finish(ioreq); + ioreq->status = BLKIF_RSP_ERROR; + return -1; +} + +static int blk_send_response_one(struct ioreq *ioreq) +{ + struct XenBlkDev *blkdev = ioreq->blkdev; + int send_notify = 0; + int have_requests = 0; + blkif_response_t *resp; + + /* Place on the response ring for the relevant domain. */ + switch (blkdev->protocol) { + case BLKIF_PROTOCOL_NATIVE: + resp = (blkif_response_t *)RING_GET_RESPONSE( + &blkdev->rings.native, + blkdev->rings.native.rsp_prod_pvt); + break; + case BLKIF_PROTOCOL_X86_32: + resp = (blkif_response_t *)RING_GET_RESPONSE( + &blkdev->rings.x86_32_part, + blkdev->rings.x86_32_part.rsp_prod_pvt); + break; + case BLKIF_PROTOCOL_X86_64: + resp = (blkif_response_t *)RING_GET_RESPONSE( + &blkdev->rings.x86_64_part, + blkdev->rings.x86_64_part.rsp_prod_pvt); + break; + default: + return 0; + } + + resp->id = ioreq->req.id; + resp->operation = ioreq->req.operation; + resp->status = ioreq->status; + + blkdev->rings.common.rsp_prod_pvt++; + + RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&blkdev->rings.common, send_notify); + if (blkdev->rings.common.rsp_prod_pvt == blkdev->rings.common.req_cons) { + /* + * Tail check for pending requests. Allows frontend to avoid + * notifications if requests are already in flight (lower + * overheads and promotes batching). + */ + RING_FINAL_CHECK_FOR_REQUESTS(&blkdev->rings.common, have_requests); + } else if (RING_HAS_UNCONSUMED_REQUESTS(&blkdev->rings.common)) { + have_requests = 1; + } + + if (have_requests) { + blkdev->more_work++; + } + return send_notify; +} + +/* walk finished list, send outstanding responses, free requests */ +static void blk_send_response_all(struct XenBlkDev *blkdev) +{ + struct ioreq *ioreq; + int send_notify = 0; + + while (!QLIST_EMPTY(&blkdev->finished)) { + ioreq = QLIST_FIRST(&blkdev->finished); + send_notify += blk_send_response_one(ioreq); + ioreq_release(ioreq, true); + } + if (send_notify) { + xen_pv_send_notify(&blkdev->xendev); + } +} + +static int blk_get_request(struct XenBlkDev *blkdev, struct ioreq *ioreq, + RING_IDX rc) +{ + switch (blkdev->protocol) { + case BLKIF_PROTOCOL_NATIVE: + memcpy(&ioreq->req, RING_GET_REQUEST(&blkdev->rings.native, rc), + sizeof(ioreq->req)); + break; + case BLKIF_PROTOCOL_X86_32: + blkif_get_x86_32_req(&ioreq->req, + RING_GET_REQUEST(&blkdev->rings.x86_32_part, rc)); + break; + case BLKIF_PROTOCOL_X86_64: + blkif_get_x86_64_req(&ioreq->req, + RING_GET_REQUEST(&blkdev->rings.x86_64_part, rc)); + break; + } + /* Prevent the compiler from accessing the on-ring fields instead. */ + barrier(); + return 0; +} + +static void blk_handle_requests(struct XenBlkDev *blkdev) +{ + RING_IDX rc, rp; + struct ioreq *ioreq; + + blkdev->more_work = 0; + + rc = blkdev->rings.common.req_cons; + rp = blkdev->rings.common.sring->req_prod; + xen_rmb(); /* Ensure we see queued requests up to 'rp'. */ + + blk_send_response_all(blkdev); + while (rc != rp) { + /* pull request from ring */ + if (RING_REQUEST_CONS_OVERFLOW(&blkdev->rings.common, rc)) { + break; + } + ioreq = ioreq_start(blkdev); + if (ioreq == NULL) { + blkdev->more_work++; + break; + } + blk_get_request(blkdev, ioreq, rc); + blkdev->rings.common.req_cons = ++rc; + + /* parse them */ + if (ioreq_parse(ioreq) != 0) { + + switch (ioreq->req.operation) { + case BLKIF_OP_READ: + block_acct_invalid(blk_get_stats(blkdev->blk), + BLOCK_ACCT_READ); + break; + case BLKIF_OP_WRITE: + block_acct_invalid(blk_get_stats(blkdev->blk), + BLOCK_ACCT_WRITE); + break; + case BLKIF_OP_FLUSH_DISKCACHE: + block_acct_invalid(blk_get_stats(blkdev->blk), + BLOCK_ACCT_FLUSH); + default: + break; + }; + + if (blk_send_response_one(ioreq)) { + xen_pv_send_notify(&blkdev->xendev); + } + ioreq_release(ioreq, false); + continue; + } + + ioreq_runio_qemu_aio(ioreq); + } + + if (blkdev->more_work && blkdev->requests_inflight < blkdev->max_requests) { + qemu_bh_schedule(blkdev->bh); + } +} + +/* ------------------------------------------------------------- */ + +static void blk_bh(void *opaque) +{ + struct XenBlkDev *blkdev = opaque; + + aio_context_acquire(blkdev->ctx); + blk_handle_requests(blkdev); + aio_context_release(blkdev->ctx); +} + +static void blk_alloc(struct XenLegacyDevice *xendev) +{ + struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev); + Error *err = NULL; + + trace_xen_disk_alloc(xendev->name); + + QLIST_INIT(&blkdev->inflight); + QLIST_INIT(&blkdev->finished); + QLIST_INIT(&blkdev->freelist); + + blkdev->iothread = iothread_create(xendev->name, &err); + assert(!err); + + blkdev->ctx = iothread_get_aio_context(blkdev->iothread); + blkdev->bh = aio_bh_new(blkdev->ctx, blk_bh, blkdev); +} + +static void blk_parse_discard(struct XenBlkDev *blkdev) +{ + struct XenLegacyDevice *xendev = &blkdev->xendev; + int enable; + + blkdev->feature_discard = true; + + if (xenstore_read_be_int(xendev, "discard-enable", &enable) == 0) { + blkdev->feature_discard = !!enable; + } + + if (blkdev->feature_discard) { + xenstore_write_be_int(xendev, "feature-discard", 1); + } +} + +static int blk_init(struct XenLegacyDevice *xendev) +{ + struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev); + int info = 0; + char *directiosafe = NULL; + + trace_xen_disk_init(xendev->name); + + /* read xenstore entries */ + if (blkdev->params == NULL) { + char *h = NULL; + blkdev->params = xenstore_read_be_str(xendev, "params"); + if (blkdev->params != NULL) { + h = strchr(blkdev->params, ':'); + } + if (h != NULL) { + blkdev->fileproto = blkdev->params; + blkdev->filename = h + 1; + *h = 0; + } else { + blkdev->fileproto = ""; + blkdev->filename = blkdev->params; + } + } + if (!strcmp("aio", blkdev->fileproto)) { + blkdev->fileproto = "raw"; + } + if (!strcmp("vhd", blkdev->fileproto)) { + blkdev->fileproto = "vpc"; + } + if (blkdev->mode == NULL) { + blkdev->mode = xenstore_read_be_str(xendev, "mode"); + } + if (blkdev->type == NULL) { + blkdev->type = xenstore_read_be_str(xendev, "type"); + } + if (blkdev->dev == NULL) { + blkdev->dev = xenstore_read_be_str(xendev, "dev"); + } + if (blkdev->devtype == NULL) { + blkdev->devtype = xenstore_read_be_str(xendev, "device-type"); + } + directiosafe = xenstore_read_be_str(xendev, "direct-io-safe"); + blkdev->directiosafe = (directiosafe && atoi(directiosafe)); + + /* do we have all we need? */ + if (blkdev->params == NULL || + blkdev->mode == NULL || + blkdev->type == NULL || + blkdev->dev == NULL) { + goto out_error; + } + + /* read-only ? */ + if (strcmp(blkdev->mode, "w")) { + info |= VDISK_READONLY; + } + + /* cdrom ? */ + if (blkdev->devtype && !strcmp(blkdev->devtype, "cdrom")) { + info |= VDISK_CDROM; + } + + blkdev->file_blk = BLOCK_SIZE; + + /* fill info + * blk_connect supplies sector-size and sectors + */ + xenstore_write_be_int(xendev, "feature-flush-cache", 1); + xenstore_write_be_int(xendev, "info", info); + + xenstore_write_be_int(xendev, "max-ring-page-order", + MAX_RING_PAGE_ORDER); + + blk_parse_discard(blkdev); + + g_free(directiosafe); + return 0; + +out_error: + g_free(blkdev->params); + blkdev->params = NULL; + g_free(blkdev->mode); + blkdev->mode = NULL; + g_free(blkdev->type); + blkdev->type = NULL; + g_free(blkdev->dev); + blkdev->dev = NULL; + g_free(blkdev->devtype); + blkdev->devtype = NULL; + g_free(directiosafe); + blkdev->directiosafe = false; + return -1; +} + +static int blk_connect(struct XenLegacyDevice *xendev) +{ + struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev); + int index, qflags; + bool readonly = true; + bool writethrough = true; + int order, ring_ref; + unsigned int ring_size, max_grants; + unsigned int i; + + trace_xen_disk_connect(xendev->name); + + /* read-only ? */ + if (blkdev->directiosafe) { + qflags = BDRV_O_NOCACHE | BDRV_O_NATIVE_AIO; + } else { + qflags = 0; + writethrough = false; + } + if (strcmp(blkdev->mode, "w") == 0) { + qflags |= BDRV_O_RDWR; + readonly = false; + } + if (blkdev->feature_discard) { + qflags |= BDRV_O_UNMAP; + } + + /* init qemu block driver */ + index = (xendev->dev - 202 * 256) / 16; + blkdev->dinfo = drive_get(IF_XEN, 0, index); + if (!blkdev->dinfo) { + Error *local_err = NULL; + QDict *options = NULL; + + if (strcmp(blkdev->fileproto, "")) { + options = qdict_new(); + qdict_put_str(options, "driver", blkdev->fileproto); + } + + /* setup via xenbus -> create new block driver instance */ + xen_pv_printf(xendev, 2, "create new bdrv (xenbus setup)\n"); + blkdev->blk = blk_new_open(blkdev->filename, NULL, options, + qflags, &local_err); + if (!blkdev->blk) { + xen_pv_printf(xendev, 0, "error: %s\n", + error_get_pretty(local_err)); + error_free(local_err); + return -1; + } + blk_set_enable_write_cache(blkdev->blk, !writethrough); + } else { + /* setup via qemu cmdline -> already setup for us */ + xen_pv_printf(xendev, 2, + "get configured bdrv (cmdline setup)\n"); + blkdev->blk = blk_by_legacy_dinfo(blkdev->dinfo); + if (blk_is_read_only(blkdev->blk) && !readonly) { + xen_pv_printf(xendev, 0, "Unexpected read-only drive"); + blkdev->blk = NULL; + return -1; + } + /* blkdev->blk is not create by us, we get a reference + * so we can blk_unref() unconditionally */ + blk_ref(blkdev->blk); + } + blk_attach_dev_legacy(blkdev->blk, blkdev); + blkdev->file_size = blk_getlength(blkdev->blk); + if (blkdev->file_size < 0) { + BlockDriverState *bs = blk_bs(blkdev->blk); + const char *drv_name = bs ? bdrv_get_format_name(bs) : NULL; + xen_pv_printf(xendev, 1, "blk_getlength: %d (%s) | drv %s\n", + (int)blkdev->file_size, strerror(-blkdev->file_size), + drv_name ?: "-"); + blkdev->file_size = 0; + } + + xen_pv_printf(xendev, 1, "type \"%s\", fileproto \"%s\", filename \"%s\"," + " size %" PRId64 " (%" PRId64 " MB)\n", + blkdev->type, blkdev->fileproto, blkdev->filename, + blkdev->file_size, blkdev->file_size / MiB); + + /* Fill in number of sector size and number of sectors */ + xenstore_write_be_int(xendev, "sector-size", blkdev->file_blk); + xenstore_write_be_int64(xendev, "sectors", + blkdev->file_size / blkdev->file_blk); + + if (xenstore_read_fe_int(xendev, "ring-page-order", + &order) == -1) { + blkdev->nr_ring_ref = 1; + + if (xenstore_read_fe_int(xendev, "ring-ref", + &ring_ref) == -1) { + return -1; + } + blkdev->ring_ref[0] = ring_ref; + + } else if (order >= 0 && order <= MAX_RING_PAGE_ORDER) { + blkdev->nr_ring_ref = 1 << order; + + for (i = 0; i < blkdev->nr_ring_ref; i++) { + char *key; + + key = g_strdup_printf("ring-ref%u", i); + if (!key) { + return -1; + } + + if (xenstore_read_fe_int(xendev, key, + &ring_ref) == -1) { + g_free(key); + return -1; + } + blkdev->ring_ref[i] = ring_ref; + + g_free(key); + } + } else { + xen_pv_printf(xendev, 0, "invalid ring-page-order: %d\n", + order); + return -1; + } + + if (xenstore_read_fe_int(xendev, "event-channel", + &xendev->remote_port) == -1) { + return -1; + } + + if (!xendev->protocol) { + blkdev->protocol = BLKIF_PROTOCOL_NATIVE; + } else if (strcmp(xendev->protocol, XEN_IO_PROTO_ABI_NATIVE) == 0) { + blkdev->protocol = BLKIF_PROTOCOL_NATIVE; + } else if (strcmp(xendev->protocol, XEN_IO_PROTO_ABI_X86_32) == 0) { + blkdev->protocol = BLKIF_PROTOCOL_X86_32; + } else if (strcmp(xendev->protocol, XEN_IO_PROTO_ABI_X86_64) == 0) { + blkdev->protocol = BLKIF_PROTOCOL_X86_64; + } else { + blkdev->protocol = BLKIF_PROTOCOL_NATIVE; + } + + ring_size = XC_PAGE_SIZE * blkdev->nr_ring_ref; + switch (blkdev->protocol) { + case BLKIF_PROTOCOL_NATIVE: + { + blkdev->max_requests = __CONST_RING_SIZE(blkif, ring_size); + break; + } + case BLKIF_PROTOCOL_X86_32: + { + blkdev->max_requests = __CONST_RING_SIZE(blkif_x86_32, ring_size); + break; + } + case BLKIF_PROTOCOL_X86_64: + { + blkdev->max_requests = __CONST_RING_SIZE(blkif_x86_64, ring_size); + break; + } + default: + return -1; + } + + /* Add on the number needed for the ring pages */ + max_grants = blkdev->nr_ring_ref; + + xen_be_set_max_grant_refs(xendev, max_grants); + blkdev->sring = xen_be_map_grant_refs(xendev, blkdev->ring_ref, + blkdev->nr_ring_ref, + PROT_READ | PROT_WRITE); + if (!blkdev->sring) { + return -1; + } + + switch (blkdev->protocol) { + case BLKIF_PROTOCOL_NATIVE: + { + blkif_sring_t *sring_native = blkdev->sring; + BACK_RING_INIT(&blkdev->rings.native, sring_native, ring_size); + break; + } + case BLKIF_PROTOCOL_X86_32: + { + blkif_x86_32_sring_t *sring_x86_32 = blkdev->sring; + + BACK_RING_INIT(&blkdev->rings.x86_32_part, sring_x86_32, ring_size); + break; + } + case BLKIF_PROTOCOL_X86_64: + { + blkif_x86_64_sring_t *sring_x86_64 = blkdev->sring; + + BACK_RING_INIT(&blkdev->rings.x86_64_part, sring_x86_64, ring_size); + break; + } + } + + blk_set_aio_context(blkdev->blk, blkdev->ctx); + + xen_be_bind_evtchn(xendev); + + xen_pv_printf(xendev, 1, "ok: proto %s, nr-ring-ref %u, " + "remote port %d, local port %d\n", + xendev->protocol, blkdev->nr_ring_ref, + xendev->remote_port, xendev->local_port); + return 0; +} + +static void blk_disconnect(struct XenLegacyDevice *xendev) +{ + struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev); + + trace_xen_disk_disconnect(xendev->name); + + aio_context_acquire(blkdev->ctx); + + if (blkdev->blk) { + blk_set_aio_context(blkdev->blk, qemu_get_aio_context()); + blk_detach_dev(blkdev->blk, blkdev); + blk_unref(blkdev->blk); + blkdev->blk = NULL; + } + xen_pv_unbind_evtchn(xendev); + + aio_context_release(blkdev->ctx); + + if (blkdev->sring) { + xen_be_unmap_grant_refs(xendev, blkdev->sring, + blkdev->nr_ring_ref); + blkdev->sring = NULL; + } +} + +static int blk_free(struct XenLegacyDevice *xendev) +{ + struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev); + struct ioreq *ioreq; + + trace_xen_disk_free(xendev->name); + + blk_disconnect(xendev); + + while (!QLIST_EMPTY(&blkdev->freelist)) { + ioreq = QLIST_FIRST(&blkdev->freelist); + QLIST_REMOVE(ioreq, list); + qemu_iovec_destroy(&ioreq->v); + g_free(ioreq); + } + + g_free(blkdev->params); + g_free(blkdev->mode); + g_free(blkdev->type); + g_free(blkdev->dev); + g_free(blkdev->devtype); + qemu_bh_delete(blkdev->bh); + iothread_destroy(blkdev->iothread); + return 0; +} + +static void blk_event(struct XenLegacyDevice *xendev) +{ + struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev); + + qemu_bh_schedule(blkdev->bh); +} + +struct XenDevOps xen_blkdev_ops = { + .flags = DEVOPS_FLAG_NEED_GNTDEV, + .size = sizeof(struct XenBlkDev), + .alloc = blk_alloc, + .init = blk_init, + .initialise = blk_connect, + .disconnect = blk_disconnect, + .event = blk_event, + .free = blk_free, +}; From patchwork Mon Jan 14 13:51:40 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anthony PERARD X-Patchwork-Id: 10762739 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id A67C7184E for ; Mon, 14 Jan 2019 14:14:47 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 945F528B02 for ; Mon, 14 Jan 2019 14:14:47 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 88E3B28C46; Mon, 14 Jan 2019 14:14:47 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 66B3328B02 for ; Mon, 14 Jan 2019 14:14:46 +0000 (UTC) Received: from localhost ([127.0.0.1]:36166 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gj30n-00021K-Js for patchwork-qemu-devel@patchwork.kernel.org; Mon, 14 Jan 2019 09:14:45 -0500 Received: from eggs.gnu.org ([209.51.188.92]:47366) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gj2lm-0007BC-1g for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:59:20 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gj2lj-0004tW-TQ for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:59:13 -0500 Received: from smtp03.citrix.com ([162.221.156.55]:1370) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gj2lh-0004ll-Q8 for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:59:11 -0500 X-IronPort-AV: E=Sophos;i="5.56,477,1539648000"; d="scan'208";a="75507023" From: Anthony PERARD To: Date: Mon, 14 Jan 2019 13:51:40 +0000 Message-ID: <20190114135154.16826-12-anthony.perard@citrix.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190114135154.16826-1-anthony.perard@citrix.com> References: <20190114135154.16826-1-anthony.perard@citrix.com> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 162.221.156.55 Subject: [Qemu-devel] [PULL 11/25] xen: remove unnecessary code from dataplane/xen-block.c X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Anthony PERARD , xen-devel@lists.xenproject.org, Peter Maydell Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Paul Durrant Not all of the code duplicated from xen_disk.c is required as the basis for the new dataplane implementation so this patch removes extraneous code, along with the legacy #includes and calls to the legacy xen_pv_printf() function. Error messages are changed to be reported using error_report(). NOTE: The code is still not yet built. Further transformations will be required to make it correctly interface to the new XenBus/XenDevice framework. They will be delivered in a subsequent patch. Signed-off-by: Paul Durrant Acked-by: Anthony Perard Signed-off-by: Anthony PERARD --- hw/block/dataplane/xen-block.c | 429 ++------------------------------- 1 file changed, 23 insertions(+), 406 deletions(-) diff --git a/hw/block/dataplane/xen-block.c b/hw/block/dataplane/xen-block.c index 9fae50534e..228472320a 100644 --- a/hw/block/dataplane/xen-block.c +++ b/hw/block/dataplane/xen-block.c @@ -1,45 +1,23 @@ /* - * xen paravirt block device backend + * Copyright (c) 2018 Citrix Systems Inc. + * (c) Gerd Hoffmann * - * (c) Gerd Hoffmann + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; under version 2 of the License. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; under version 2 of the License. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License along + * with this program; if not, see . * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see . - * - * Contributions after 2012-01-13 are licensed under the terms of the - * GNU GPL, version 2 or (at your option) any later version. + * Contributions after 2012-01-13 are licensed under the terms of the + * GNU GPL, version 2 or (at your option) any later version. */ -#include "qemu/osdep.h" -#include "qemu/units.h" -#include -#include - -#include "hw/hw.h" -#include "hw/xen/xen_backend.h" -#include "xen_blkif.h" -#include "sysemu/blockdev.h" -#include "sysemu/iothread.h" -#include "sysemu/block-backend.h" -#include "qapi/error.h" -#include "qapi/qmp/qdict.h" -#include "qapi/qmp/qstring.h" -#include "trace.h" - -/* ------------------------------------------------------------- */ - -#define BLOCK_SIZE 512 -#define IOCB_COUNT (BLKIF_MAX_SEGMENTS_PER_REQUEST + 2) - struct ioreq { blkif_request_t req; int16_t status; @@ -101,8 +79,6 @@ struct XenBlkDev { AioContext *ctx; }; -/* ------------------------------------------------------------- */ - static void ioreq_reset(struct ioreq *ioreq) { memset(&ioreq->req, 0, sizeof(ioreq->req)); @@ -183,11 +159,6 @@ static int ioreq_parse(struct ioreq *ioreq) size_t len; int i; - xen_pv_printf( - xendev, 3, - "op %d, nr %d, handle %d, id %" PRId64 ", sector %" PRId64 "\n", - ioreq->req.operation, ioreq->req.nr_segments, - ioreq->req.handle, ioreq->req.id, ioreq->req.sector_number); switch (ioreq->req.operation) { case BLKIF_OP_READ: break; @@ -202,28 +173,27 @@ static int ioreq_parse(struct ioreq *ioreq) case BLKIF_OP_DISCARD: return 0; default: - xen_pv_printf(xendev, 0, "error: unknown operation (%d)\n", - ioreq->req.operation); + error_report("error: unknown operation (%d)", ioreq->req.operation); goto err; }; if (ioreq->req.operation != BLKIF_OP_READ && blkdev->mode[0] != 'w') { - xen_pv_printf(xendev, 0, "error: write req for ro device\n"); + error_report("error: write req for ro device"); goto err; } ioreq->start = ioreq->req.sector_number * blkdev->file_blk; for (i = 0; i < ioreq->req.nr_segments; i++) { if (i == BLKIF_MAX_SEGMENTS_PER_REQUEST) { - xen_pv_printf(xendev, 0, "error: nr_segments too big\n"); + error_report("error: nr_segments too big"); goto err; } if (ioreq->req.seg[i].first_sect > ioreq->req.seg[i].last_sect) { - xen_pv_printf(xendev, 0, "error: first > last sector\n"); + error_report("error: first > last sector"); goto err; } if (ioreq->req.seg[i].last_sect * BLOCK_SIZE >= XC_PAGE_SIZE) { - xen_pv_printf(xendev, 0, "error: page crossing\n"); + error_report("error: page crossing"); goto err; } @@ -232,7 +202,7 @@ static int ioreq_parse(struct ioreq *ioreq) ioreq->size += len; } if (ioreq->start + ioreq->size > blkdev->file_size) { - xen_pv_printf(xendev, 0, "error: access beyond end of file\n"); + error_report("error: access beyond end of file"); goto err; } return 0; @@ -278,8 +248,7 @@ static int ioreq_grant_copy(struct ioreq *ioreq) rc = xen_be_copy_grant_refs(xendev, to_domain, segs, count); if (rc) { - xen_pv_printf(xendev, 0, - "failed to copy data %d\n", rc); + error_report("failed to copy data %d", rc); ioreq->aio_errors++; return -1; } @@ -298,8 +267,9 @@ static void qemu_aio_complete(void *opaque, int ret) aio_context_acquire(blkdev->ctx); if (ret != 0) { - xen_pv_printf(xendev, 0, "%s I/O error\n", - ioreq->req.operation == BLKIF_OP_READ ? "read" : "write"); + error_report("%s I/O error", + ioreq->req.operation == BLKIF_OP_READ ? + "read" : "write"); ioreq->aio_errors++; } @@ -605,8 +575,6 @@ static void blk_handle_requests(struct XenBlkDev *blkdev) } } -/* ------------------------------------------------------------- */ - static void blk_bh(void *opaque) { struct XenBlkDev *blkdev = opaque; @@ -634,346 +602,6 @@ static void blk_alloc(struct XenLegacyDevice *xendev) blkdev->bh = aio_bh_new(blkdev->ctx, blk_bh, blkdev); } -static void blk_parse_discard(struct XenBlkDev *blkdev) -{ - struct XenLegacyDevice *xendev = &blkdev->xendev; - int enable; - - blkdev->feature_discard = true; - - if (xenstore_read_be_int(xendev, "discard-enable", &enable) == 0) { - blkdev->feature_discard = !!enable; - } - - if (blkdev->feature_discard) { - xenstore_write_be_int(xendev, "feature-discard", 1); - } -} - -static int blk_init(struct XenLegacyDevice *xendev) -{ - struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev); - int info = 0; - char *directiosafe = NULL; - - trace_xen_disk_init(xendev->name); - - /* read xenstore entries */ - if (blkdev->params == NULL) { - char *h = NULL; - blkdev->params = xenstore_read_be_str(xendev, "params"); - if (blkdev->params != NULL) { - h = strchr(blkdev->params, ':'); - } - if (h != NULL) { - blkdev->fileproto = blkdev->params; - blkdev->filename = h + 1; - *h = 0; - } else { - blkdev->fileproto = ""; - blkdev->filename = blkdev->params; - } - } - if (!strcmp("aio", blkdev->fileproto)) { - blkdev->fileproto = "raw"; - } - if (!strcmp("vhd", blkdev->fileproto)) { - blkdev->fileproto = "vpc"; - } - if (blkdev->mode == NULL) { - blkdev->mode = xenstore_read_be_str(xendev, "mode"); - } - if (blkdev->type == NULL) { - blkdev->type = xenstore_read_be_str(xendev, "type"); - } - if (blkdev->dev == NULL) { - blkdev->dev = xenstore_read_be_str(xendev, "dev"); - } - if (blkdev->devtype == NULL) { - blkdev->devtype = xenstore_read_be_str(xendev, "device-type"); - } - directiosafe = xenstore_read_be_str(xendev, "direct-io-safe"); - blkdev->directiosafe = (directiosafe && atoi(directiosafe)); - - /* do we have all we need? */ - if (blkdev->params == NULL || - blkdev->mode == NULL || - blkdev->type == NULL || - blkdev->dev == NULL) { - goto out_error; - } - - /* read-only ? */ - if (strcmp(blkdev->mode, "w")) { - info |= VDISK_READONLY; - } - - /* cdrom ? */ - if (blkdev->devtype && !strcmp(blkdev->devtype, "cdrom")) { - info |= VDISK_CDROM; - } - - blkdev->file_blk = BLOCK_SIZE; - - /* fill info - * blk_connect supplies sector-size and sectors - */ - xenstore_write_be_int(xendev, "feature-flush-cache", 1); - xenstore_write_be_int(xendev, "info", info); - - xenstore_write_be_int(xendev, "max-ring-page-order", - MAX_RING_PAGE_ORDER); - - blk_parse_discard(blkdev); - - g_free(directiosafe); - return 0; - -out_error: - g_free(blkdev->params); - blkdev->params = NULL; - g_free(blkdev->mode); - blkdev->mode = NULL; - g_free(blkdev->type); - blkdev->type = NULL; - g_free(blkdev->dev); - blkdev->dev = NULL; - g_free(blkdev->devtype); - blkdev->devtype = NULL; - g_free(directiosafe); - blkdev->directiosafe = false; - return -1; -} - -static int blk_connect(struct XenLegacyDevice *xendev) -{ - struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev); - int index, qflags; - bool readonly = true; - bool writethrough = true; - int order, ring_ref; - unsigned int ring_size, max_grants; - unsigned int i; - - trace_xen_disk_connect(xendev->name); - - /* read-only ? */ - if (blkdev->directiosafe) { - qflags = BDRV_O_NOCACHE | BDRV_O_NATIVE_AIO; - } else { - qflags = 0; - writethrough = false; - } - if (strcmp(blkdev->mode, "w") == 0) { - qflags |= BDRV_O_RDWR; - readonly = false; - } - if (blkdev->feature_discard) { - qflags |= BDRV_O_UNMAP; - } - - /* init qemu block driver */ - index = (xendev->dev - 202 * 256) / 16; - blkdev->dinfo = drive_get(IF_XEN, 0, index); - if (!blkdev->dinfo) { - Error *local_err = NULL; - QDict *options = NULL; - - if (strcmp(blkdev->fileproto, "")) { - options = qdict_new(); - qdict_put_str(options, "driver", blkdev->fileproto); - } - - /* setup via xenbus -> create new block driver instance */ - xen_pv_printf(xendev, 2, "create new bdrv (xenbus setup)\n"); - blkdev->blk = blk_new_open(blkdev->filename, NULL, options, - qflags, &local_err); - if (!blkdev->blk) { - xen_pv_printf(xendev, 0, "error: %s\n", - error_get_pretty(local_err)); - error_free(local_err); - return -1; - } - blk_set_enable_write_cache(blkdev->blk, !writethrough); - } else { - /* setup via qemu cmdline -> already setup for us */ - xen_pv_printf(xendev, 2, - "get configured bdrv (cmdline setup)\n"); - blkdev->blk = blk_by_legacy_dinfo(blkdev->dinfo); - if (blk_is_read_only(blkdev->blk) && !readonly) { - xen_pv_printf(xendev, 0, "Unexpected read-only drive"); - blkdev->blk = NULL; - return -1; - } - /* blkdev->blk is not create by us, we get a reference - * so we can blk_unref() unconditionally */ - blk_ref(blkdev->blk); - } - blk_attach_dev_legacy(blkdev->blk, blkdev); - blkdev->file_size = blk_getlength(blkdev->blk); - if (blkdev->file_size < 0) { - BlockDriverState *bs = blk_bs(blkdev->blk); - const char *drv_name = bs ? bdrv_get_format_name(bs) : NULL; - xen_pv_printf(xendev, 1, "blk_getlength: %d (%s) | drv %s\n", - (int)blkdev->file_size, strerror(-blkdev->file_size), - drv_name ?: "-"); - blkdev->file_size = 0; - } - - xen_pv_printf(xendev, 1, "type \"%s\", fileproto \"%s\", filename \"%s\"," - " size %" PRId64 " (%" PRId64 " MB)\n", - blkdev->type, blkdev->fileproto, blkdev->filename, - blkdev->file_size, blkdev->file_size / MiB); - - /* Fill in number of sector size and number of sectors */ - xenstore_write_be_int(xendev, "sector-size", blkdev->file_blk); - xenstore_write_be_int64(xendev, "sectors", - blkdev->file_size / blkdev->file_blk); - - if (xenstore_read_fe_int(xendev, "ring-page-order", - &order) == -1) { - blkdev->nr_ring_ref = 1; - - if (xenstore_read_fe_int(xendev, "ring-ref", - &ring_ref) == -1) { - return -1; - } - blkdev->ring_ref[0] = ring_ref; - - } else if (order >= 0 && order <= MAX_RING_PAGE_ORDER) { - blkdev->nr_ring_ref = 1 << order; - - for (i = 0; i < blkdev->nr_ring_ref; i++) { - char *key; - - key = g_strdup_printf("ring-ref%u", i); - if (!key) { - return -1; - } - - if (xenstore_read_fe_int(xendev, key, - &ring_ref) == -1) { - g_free(key); - return -1; - } - blkdev->ring_ref[i] = ring_ref; - - g_free(key); - } - } else { - xen_pv_printf(xendev, 0, "invalid ring-page-order: %d\n", - order); - return -1; - } - - if (xenstore_read_fe_int(xendev, "event-channel", - &xendev->remote_port) == -1) { - return -1; - } - - if (!xendev->protocol) { - blkdev->protocol = BLKIF_PROTOCOL_NATIVE; - } else if (strcmp(xendev->protocol, XEN_IO_PROTO_ABI_NATIVE) == 0) { - blkdev->protocol = BLKIF_PROTOCOL_NATIVE; - } else if (strcmp(xendev->protocol, XEN_IO_PROTO_ABI_X86_32) == 0) { - blkdev->protocol = BLKIF_PROTOCOL_X86_32; - } else if (strcmp(xendev->protocol, XEN_IO_PROTO_ABI_X86_64) == 0) { - blkdev->protocol = BLKIF_PROTOCOL_X86_64; - } else { - blkdev->protocol = BLKIF_PROTOCOL_NATIVE; - } - - ring_size = XC_PAGE_SIZE * blkdev->nr_ring_ref; - switch (blkdev->protocol) { - case BLKIF_PROTOCOL_NATIVE: - { - blkdev->max_requests = __CONST_RING_SIZE(blkif, ring_size); - break; - } - case BLKIF_PROTOCOL_X86_32: - { - blkdev->max_requests = __CONST_RING_SIZE(blkif_x86_32, ring_size); - break; - } - case BLKIF_PROTOCOL_X86_64: - { - blkdev->max_requests = __CONST_RING_SIZE(blkif_x86_64, ring_size); - break; - } - default: - return -1; - } - - /* Add on the number needed for the ring pages */ - max_grants = blkdev->nr_ring_ref; - - xen_be_set_max_grant_refs(xendev, max_grants); - blkdev->sring = xen_be_map_grant_refs(xendev, blkdev->ring_ref, - blkdev->nr_ring_ref, - PROT_READ | PROT_WRITE); - if (!blkdev->sring) { - return -1; - } - - switch (blkdev->protocol) { - case BLKIF_PROTOCOL_NATIVE: - { - blkif_sring_t *sring_native = blkdev->sring; - BACK_RING_INIT(&blkdev->rings.native, sring_native, ring_size); - break; - } - case BLKIF_PROTOCOL_X86_32: - { - blkif_x86_32_sring_t *sring_x86_32 = blkdev->sring; - - BACK_RING_INIT(&blkdev->rings.x86_32_part, sring_x86_32, ring_size); - break; - } - case BLKIF_PROTOCOL_X86_64: - { - blkif_x86_64_sring_t *sring_x86_64 = blkdev->sring; - - BACK_RING_INIT(&blkdev->rings.x86_64_part, sring_x86_64, ring_size); - break; - } - } - - blk_set_aio_context(blkdev->blk, blkdev->ctx); - - xen_be_bind_evtchn(xendev); - - xen_pv_printf(xendev, 1, "ok: proto %s, nr-ring-ref %u, " - "remote port %d, local port %d\n", - xendev->protocol, blkdev->nr_ring_ref, - xendev->remote_port, xendev->local_port); - return 0; -} - -static void blk_disconnect(struct XenLegacyDevice *xendev) -{ - struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev); - - trace_xen_disk_disconnect(xendev->name); - - aio_context_acquire(blkdev->ctx); - - if (blkdev->blk) { - blk_set_aio_context(blkdev->blk, qemu_get_aio_context()); - blk_detach_dev(blkdev->blk, blkdev); - blk_unref(blkdev->blk); - blkdev->blk = NULL; - } - xen_pv_unbind_evtchn(xendev); - - aio_context_release(blkdev->ctx); - - if (blkdev->sring) { - xen_be_unmap_grant_refs(xendev, blkdev->sring, - blkdev->nr_ring_ref); - blkdev->sring = NULL; - } -} - static int blk_free(struct XenLegacyDevice *xendev) { struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev); @@ -1006,14 +634,3 @@ static void blk_event(struct XenLegacyDevice *xendev) qemu_bh_schedule(blkdev->bh); } - -struct XenDevOps xen_blkdev_ops = { - .flags = DEVOPS_FLAG_NEED_GNTDEV, - .size = sizeof(struct XenBlkDev), - .alloc = blk_alloc, - .init = blk_init, - .initialise = blk_connect, - .disconnect = blk_disconnect, - .event = blk_event, - .free = blk_free, -}; From patchwork Mon Jan 14 13:51:41 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anthony PERARD X-Patchwork-Id: 10762749 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id CA8BA13B4 for ; Mon, 14 Jan 2019 14:18:49 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id AF90E286D5 for ; Mon, 14 Jan 2019 14:18:49 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id AD6D528747; Mon, 14 Jan 2019 14:18:49 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 83905286D5 for ; Mon, 14 Jan 2019 14:18:48 +0000 (UTC) Received: from localhost ([127.0.0.1]:37092 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gj34h-0004oZ-IX for patchwork-qemu-devel@patchwork.kernel.org; Mon, 14 Jan 2019 09:18:47 -0500 Received: from eggs.gnu.org ([209.51.188.92]:47226) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gj2lN-0006n6-TB for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:58:51 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gj2lK-0004hm-Ot for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:58:49 -0500 Received: from smtp03.citrix.com ([162.221.156.55]:1352) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gj2lK-0004gB-F3 for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:58:46 -0500 X-IronPort-AV: E=Sophos;i="5.56,477,1539648000"; d="scan'208";a="75506985" From: Anthony PERARD To: Date: Mon, 14 Jan 2019 13:51:41 +0000 Message-ID: <20190114135154.16826-13-anthony.perard@citrix.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190114135154.16826-1-anthony.perard@citrix.com> References: <20190114135154.16826-1-anthony.perard@citrix.com> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 162.221.156.55 Subject: [Qemu-devel] [PULL 12/25] xen: add header and build dataplane/xen-block.c X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Anthony PERARD , xen-devel@lists.xenproject.org, Peter Maydell Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Paul Durrant This patch adds the transformations necessary to get dataplane/xen-block.c to build against the new XenBus/XenDevice framework. MAINTAINERS is also updated due to the introduction of dataplane/xen-block.h. NOTE: Existing data structure names are retained for the moment. These will be modified by subsequent patches. A typedef for XenBlockDataPlane has been added to the header (based on the old struct XenBlkDev name for the moment) so that the old names don't need to leak out of the dataplane code. Signed-off-by: Paul Durrant Reviewed-by: Anthony Perard Signed-off-by: Anthony PERARD --- MAINTAINERS | 1 + hw/block/dataplane/Makefile.objs | 1 + hw/block/dataplane/xen-block.c | 356 ++++++++++++++++++++++--------- hw/block/dataplane/xen-block.h | 29 +++ 4 files changed, 287 insertions(+), 100 deletions(-) create mode 100644 hw/block/dataplane/xen-block.h diff --git a/MAINTAINERS b/MAINTAINERS index 4c98b34853..43b2691b5d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -419,6 +419,7 @@ F: hw/block/dataplane/xen* F: hw/xen/ F: hw/xenpv/ F: hw/i386/xen/ +F: include/hw/block/dataplane/xen* F: include/hw/xen/ F: include/sysemu/xen-mapcache.h diff --git a/hw/block/dataplane/Makefile.objs b/hw/block/dataplane/Makefile.objs index e786f66421..c6c68dbc00 100644 --- a/hw/block/dataplane/Makefile.objs +++ b/hw/block/dataplane/Makefile.objs @@ -1 +1,2 @@ obj-y += virtio-blk.o +obj-$(CONFIG_XEN) += xen-block.o diff --git a/hw/block/dataplane/xen-block.c b/hw/block/dataplane/xen-block.c index 228472320a..ed2b91ffff 100644 --- a/hw/block/dataplane/xen-block.c +++ b/hw/block/dataplane/xen-block.c @@ -18,65 +18,53 @@ * GNU GPL, version 2 or (at your option) any later version. */ +#include "qemu/osdep.h" +#include "qemu/error-report.h" +#include "qapi/error.h" +#include "hw/hw.h" +#include "hw/xen/xen_common.h" +#include "hw/block/xen_blkif.h" +#include "sysemu/block-backend.h" +#include "sysemu/iothread.h" +#include "xen-block.h" + struct ioreq { - blkif_request_t req; - int16_t status; - - /* parsed request */ - off_t start; - QEMUIOVector v; - void *buf; - size_t size; - int presync; - - /* aio status */ - int aio_inflight; - int aio_errors; - - struct XenBlkDev *blkdev; - QLIST_ENTRY(ioreq) list; - BlockAcctCookie acct; + blkif_request_t req; + int16_t status; + off_t start; + QEMUIOVector v; + void *buf; + size_t size; + int presync; + int aio_inflight; + int aio_errors; + struct XenBlkDev *blkdev; + QLIST_ENTRY(ioreq) list; + BlockAcctCookie acct; }; -#define MAX_RING_PAGE_ORDER 4 - struct XenBlkDev { - struct XenLegacyDevice xendev; /* must be first */ - char *params; - char *mode; - char *type; - char *dev; - char *devtype; - bool directiosafe; - const char *fileproto; - const char *filename; - unsigned int ring_ref[1 << MAX_RING_PAGE_ORDER]; - unsigned int nr_ring_ref; - void *sring; - int64_t file_blk; - int64_t file_size; - int protocol; - blkif_back_rings_t rings; - int more_work; - - /* request lists */ + XenDevice *xendev; + XenEventChannel *event_channel; + unsigned int *ring_ref; + unsigned int nr_ring_ref; + void *sring; + int64_t file_blk; + int64_t file_size; + int protocol; + blkif_back_rings_t rings; + int more_work; QLIST_HEAD(inflight_head, ioreq) inflight; QLIST_HEAD(finished_head, ioreq) finished; QLIST_HEAD(freelist_head, ioreq) freelist; - int requests_total; - int requests_inflight; - int requests_finished; - unsigned int max_requests; - - gboolean feature_discard; - - /* qemu block driver */ - DriveInfo *dinfo; - BlockBackend *blk; - QEMUBH *bh; - - IOThread *iothread; - AioContext *ctx; + int requests_total; + int requests_inflight; + int requests_finished; + unsigned int max_requests; + BlockBackend *blk; + QEMUBH *bh; + IOThread *iothread; + AioContext *ctx; }; static void ioreq_reset(struct ioreq *ioreq) @@ -155,7 +143,6 @@ static void ioreq_release(struct ioreq *ioreq, bool finish) static int ioreq_parse(struct ioreq *ioreq) { struct XenBlkDev *blkdev = ioreq->blkdev; - struct XenLegacyDevice *xendev = &blkdev->xendev; size_t len; int i; @@ -177,7 +164,8 @@ static int ioreq_parse(struct ioreq *ioreq) goto err; }; - if (ioreq->req.operation != BLKIF_OP_READ && blkdev->mode[0] != 'w') { + if (ioreq->req.operation != BLKIF_OP_READ && + blk_is_read_only(blkdev->blk)) { error_report("error: write req for ro device"); goto err; } @@ -192,7 +180,7 @@ static int ioreq_parse(struct ioreq *ioreq) error_report("error: first > last sector"); goto err; } - if (ioreq->req.seg[i].last_sect * BLOCK_SIZE >= XC_PAGE_SIZE) { + if (ioreq->req.seg[i].last_sect * blkdev->file_blk >= XC_PAGE_SIZE) { error_report("error: page crossing"); goto err; } @@ -215,12 +203,13 @@ static int ioreq_parse(struct ioreq *ioreq) static int ioreq_grant_copy(struct ioreq *ioreq) { struct XenBlkDev *blkdev = ioreq->blkdev; - struct XenLegacyDevice *xendev = &blkdev->xendev; - XenGrantCopySegment segs[BLKIF_MAX_SEGMENTS_PER_REQUEST]; - int i, count, rc; + XenDevice *xendev = blkdev->xendev; + XenDeviceGrantCopySegment segs[BLKIF_MAX_SEGMENTS_PER_REQUEST]; + int i, count; int64_t file_blk = blkdev->file_blk; bool to_domain = (ioreq->req.operation == BLKIF_OP_READ); void *virt = ioreq->buf; + Error *local_err = NULL; if (ioreq->req.nr_segments == 0) { return 0; @@ -240,20 +229,21 @@ static int ioreq_grant_copy(struct ioreq *ioreq) file_blk; segs[i].dest.virt = virt; } - segs[i].len = (ioreq->req.seg[i].last_sect - - ioreq->req.seg[i].first_sect + 1) * file_blk; + segs[i].len = (ioreq->req.seg[i].last_sect - + ioreq->req.seg[i].first_sect + 1) * file_blk; virt += segs[i].len; } - rc = xen_be_copy_grant_refs(xendev, to_domain, segs, count); + xen_device_copy_grant_refs(xendev, to_domain, segs, count, &local_err); + + if (local_err) { + error_reportf_err(local_err, "failed to copy data: "); - if (rc) { - error_report("failed to copy data %d", rc); ioreq->aio_errors++; return -1; } - return rc; + return 0; } static int ioreq_runio_qemu_aio(struct ioreq *ioreq); @@ -262,7 +252,6 @@ static void qemu_aio_complete(void *opaque, int ret) { struct ioreq *ioreq = opaque; struct XenBlkDev *blkdev = ioreq->blkdev; - struct XenLegacyDevice *xendev = &blkdev->xendev; aio_context_acquire(blkdev->ctx); @@ -340,13 +329,13 @@ static bool blk_split_discard(struct ioreq *ioreq, blkif_sector_t sector_number, /* Wrap around, or overflowing byte limit? */ if (sec_start + sec_count < sec_count || - sec_start + sec_count > INT64_MAX >> BDRV_SECTOR_BITS) { + sec_start + sec_count > INT64_MAX / blkdev->file_blk) { return false; } - limit = BDRV_REQUEST_MAX_SECTORS << BDRV_SECTOR_BITS; - byte_offset = sec_start << BDRV_SECTOR_BITS; - byte_remaining = sec_count << BDRV_SECTOR_BITS; + limit = BDRV_REQUEST_MAX_SECTORS * blkdev->file_blk; + byte_offset = sec_start * blkdev->file_blk; + byte_remaining = sec_count * blkdev->file_blk; do { byte_chunk = byte_remaining > limit ? limit : byte_remaining; @@ -428,10 +417,10 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq) static int blk_send_response_one(struct ioreq *ioreq) { - struct XenBlkDev *blkdev = ioreq->blkdev; - int send_notify = 0; - int have_requests = 0; - blkif_response_t *resp; + struct XenBlkDev *blkdev = ioreq->blkdev; + int send_notify = 0; + int have_requests = 0; + blkif_response_t *resp; /* Place on the response ring for the relevant domain. */ switch (blkdev->protocol) { @@ -454,9 +443,9 @@ static int blk_send_response_one(struct ioreq *ioreq) return 0; } - resp->id = ioreq->req.id; + resp->id = ioreq->req.id; resp->operation = ioreq->req.operation; - resp->status = ioreq->status; + resp->status = ioreq->status; blkdev->rings.common.rsp_prod_pvt++; @@ -490,7 +479,14 @@ static void blk_send_response_all(struct XenBlkDev *blkdev) ioreq_release(ioreq, true); } if (send_notify) { - xen_pv_send_notify(&blkdev->xendev); + Error *local_err = NULL; + + xen_device_notify_event_channel(blkdev->xendev, + blkdev->event_channel, + &local_err); + if (local_err) { + error_report_err(local_err); + } } } @@ -561,7 +557,14 @@ static void blk_handle_requests(struct XenBlkDev *blkdev) }; if (blk_send_response_one(ioreq)) { - xen_pv_send_notify(&blkdev->xendev); + Error *local_err = NULL; + + xen_device_notify_event_channel(blkdev->xendev, + blkdev->event_channel, + &local_err); + if (local_err) { + error_report_err(local_err); + } } ioreq_release(ioreq, false); continue; @@ -584,32 +587,47 @@ static void blk_bh(void *opaque) aio_context_release(blkdev->ctx); } -static void blk_alloc(struct XenLegacyDevice *xendev) +static void blk_event(void *opaque) +{ + struct XenBlkDev *blkdev = opaque; + + qemu_bh_schedule(blkdev->bh); +} + +struct XenBlkDev *xen_block_dataplane_create(XenDevice *xendev, + BlockConf *conf, + IOThread *iothread) { - struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev); - Error *err = NULL; + struct XenBlkDev *blkdev = g_new0(struct XenBlkDev, 1); - trace_xen_disk_alloc(xendev->name); + blkdev->xendev = xendev; + blkdev->file_blk = conf->logical_block_size; + blkdev->blk = conf->blk; + blkdev->file_size = blk_getlength(blkdev->blk); QLIST_INIT(&blkdev->inflight); QLIST_INIT(&blkdev->finished); QLIST_INIT(&blkdev->freelist); - blkdev->iothread = iothread_create(xendev->name, &err); - assert(!err); - - blkdev->ctx = iothread_get_aio_context(blkdev->iothread); + if (iothread) { + blkdev->iothread = iothread; + object_ref(OBJECT(blkdev->iothread)); + blkdev->ctx = iothread_get_aio_context(blkdev->iothread); + } else { + blkdev->ctx = qemu_get_aio_context(); + } blkdev->bh = aio_bh_new(blkdev->ctx, blk_bh, blkdev); + + return blkdev; } -static int blk_free(struct XenLegacyDevice *xendev) +void xen_block_dataplane_destroy(struct XenBlkDev *blkdev) { - struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev); struct ioreq *ioreq; - trace_xen_disk_free(xendev->name); - - blk_disconnect(xendev); + if (!blkdev) { + return; + } while (!QLIST_EMPTY(&blkdev->freelist)) { ioreq = QLIST_FIRST(&blkdev->freelist); @@ -618,19 +636,157 @@ static int blk_free(struct XenLegacyDevice *xendev) g_free(ioreq); } - g_free(blkdev->params); - g_free(blkdev->mode); - g_free(blkdev->type); - g_free(blkdev->dev); - g_free(blkdev->devtype); qemu_bh_delete(blkdev->bh); - iothread_destroy(blkdev->iothread); - return 0; + if (blkdev->iothread) { + object_unref(OBJECT(blkdev->iothread)); + } + + g_free(blkdev); } -static void blk_event(struct XenLegacyDevice *xendev) + +void xen_block_dataplane_stop(struct XenBlkDev *blkdev) { - struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev); + XenDevice *xendev; - qemu_bh_schedule(blkdev->bh); + if (!blkdev) { + return; + } + + aio_context_acquire(blkdev->ctx); + blk_set_aio_context(blkdev->blk, qemu_get_aio_context()); + aio_context_release(blkdev->ctx); + + xendev = blkdev->xendev; + + if (blkdev->event_channel) { + Error *local_err = NULL; + + xen_device_unbind_event_channel(xendev, blkdev->event_channel, + &local_err); + blkdev->event_channel = NULL; + + if (local_err) { + error_report_err(local_err); + } + } + + if (blkdev->sring) { + Error *local_err = NULL; + + xen_device_unmap_grant_refs(xendev, blkdev->sring, + blkdev->nr_ring_ref, &local_err); + blkdev->sring = NULL; + + if (local_err) { + error_report_err(local_err); + } + } + + g_free(blkdev->ring_ref); + blkdev->ring_ref = NULL; +} + +void xen_block_dataplane_start(struct XenBlkDev *blkdev, + const unsigned int ring_ref[], + unsigned int nr_ring_ref, + unsigned int event_channel, + unsigned int protocol, + Error **errp) +{ + XenDevice *xendev = blkdev->xendev; + Error *local_err = NULL; + unsigned int ring_size; + unsigned int i; + + blkdev->nr_ring_ref = nr_ring_ref; + blkdev->ring_ref = g_new(unsigned int, nr_ring_ref); + + for (i = 0; i < nr_ring_ref; i++) { + blkdev->ring_ref[i] = ring_ref[i]; + } + + blkdev->protocol = protocol; + + ring_size = XC_PAGE_SIZE * blkdev->nr_ring_ref; + switch (blkdev->protocol) { + case BLKIF_PROTOCOL_NATIVE: + { + blkdev->max_requests = __CONST_RING_SIZE(blkif, ring_size); + break; + } + case BLKIF_PROTOCOL_X86_32: + { + blkdev->max_requests = __CONST_RING_SIZE(blkif_x86_32, ring_size); + break; + } + case BLKIF_PROTOCOL_X86_64: + { + blkdev->max_requests = __CONST_RING_SIZE(blkif_x86_64, ring_size); + break; + } + default: + error_setg(errp, "unknown protocol %u", blkdev->protocol); + return; + } + + xen_device_set_max_grant_refs(xendev, blkdev->nr_ring_ref, + &local_err); + if (local_err) { + error_propagate(errp, local_err); + goto stop; + } + + blkdev->sring = xen_device_map_grant_refs(xendev, + blkdev->ring_ref, + blkdev->nr_ring_ref, + PROT_READ | PROT_WRITE, + &local_err); + if (local_err) { + error_propagate(errp, local_err); + goto stop; + } + + switch (blkdev->protocol) { + case BLKIF_PROTOCOL_NATIVE: + { + blkif_sring_t *sring_native = blkdev->sring; + + BACK_RING_INIT(&blkdev->rings.native, sring_native, ring_size); + break; + } + case BLKIF_PROTOCOL_X86_32: + { + blkif_x86_32_sring_t *sring_x86_32 = blkdev->sring; + + BACK_RING_INIT(&blkdev->rings.x86_32_part, sring_x86_32, + ring_size); + break; + } + case BLKIF_PROTOCOL_X86_64: + { + blkif_x86_64_sring_t *sring_x86_64 = blkdev->sring; + + BACK_RING_INIT(&blkdev->rings.x86_64_part, sring_x86_64, + ring_size); + break; + } + } + + blkdev->event_channel = + xen_device_bind_event_channel(xendev, event_channel, + blk_event, blkdev, + &local_err); + if (local_err) { + error_propagate(errp, local_err); + goto stop; + } + + aio_context_acquire(blkdev->ctx); + blk_set_aio_context(blkdev->blk, blkdev->ctx); + aio_context_release(blkdev->ctx); + return; + +stop: + xen_block_dataplane_stop(blkdev); } diff --git a/hw/block/dataplane/xen-block.h b/hw/block/dataplane/xen-block.h new file mode 100644 index 0000000000..f31da38464 --- /dev/null +++ b/hw/block/dataplane/xen-block.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2018 Citrix Systems Inc. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef HW_BLOCK_DATAPLANE_XEN_BLOCK_H +#define HW_BLOCK_DATAPLANE_XEN_BLOCK_H + +#include "hw/block/block.h" +#include "hw/xen/xen-bus.h" +#include "sysemu/iothread.h" + +typedef struct XenBlkDev XenBlockDataPlane; + +XenBlockDataPlane *xen_block_dataplane_create(XenDevice *xendev, + BlockConf *conf, + IOThread *iothread); +void xen_block_dataplane_destroy(XenBlockDataPlane *dataplane); +void xen_block_dataplane_start(XenBlockDataPlane *dataplane, + const unsigned int ring_ref[], + unsigned int nr_ring_ref, + unsigned int event_channel, + unsigned int protocol, + Error **errp); +void xen_block_dataplane_stop(XenBlockDataPlane *dataplane); + +#endif /* HW_BLOCK_DATAPLANE_XEN_BLOCK_H */ From patchwork Mon Jan 14 13:51:42 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anthony PERARD X-Patchwork-Id: 10762821 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id A4CBD139A for ; Mon, 14 Jan 2019 14:22:09 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9214328D3B for ; Mon, 14 Jan 2019 14:22:09 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 860E528D82; Mon, 14 Jan 2019 14:22:09 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id C524428D58 for ; Mon, 14 Jan 2019 14:22:07 +0000 (UTC) Received: from localhost ([127.0.0.1]:37912 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gj37u-0007Ty-EQ for patchwork-qemu-devel@patchwork.kernel.org; Mon, 14 Jan 2019 09:22:06 -0500 Received: from eggs.gnu.org ([209.51.188.92]:47282) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gj2lc-00071X-HM for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:59:07 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gj2lU-0004mR-9f for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:59:01 -0500 Received: from smtp03.citrix.com ([162.221.156.55]:1370) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gj2lT-0004ll-As for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:58:56 -0500 X-IronPort-AV: E=Sophos;i="5.56,477,1539648000"; d="scan'208";a="75507001" From: Anthony PERARD To: Date: Mon, 14 Jan 2019 13:51:42 +0000 Message-ID: <20190114135154.16826-14-anthony.perard@citrix.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190114135154.16826-1-anthony.perard@citrix.com> References: <20190114135154.16826-1-anthony.perard@citrix.com> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 162.221.156.55 Subject: [Qemu-devel] [PULL 13/25] xen: remove 'XenBlkDev' and 'blkdev' names from dataplane/xen-block X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Anthony PERARD , xen-devel@lists.xenproject.org, Peter Maydell Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Paul Durrant This is a purely cosmetic patch that substitutes the old 'struct XenBlkDev' name with 'XenBlockDataPlane' and 'blkdev' field/variable names with 'dataplane', and then does necessary fix-up to adhere to coding style. No functional change. Signed-off-by: Paul Durrant Acked-by: Anthony Perard Signed-off-by: Anthony PERARD --- hw/block/dataplane/xen-block.c | 352 +++++++++++++++++---------------- hw/block/dataplane/xen-block.h | 2 +- 2 files changed, 183 insertions(+), 171 deletions(-) diff --git a/hw/block/dataplane/xen-block.c b/hw/block/dataplane/xen-block.c index ed2b91ffff..1ff464973c 100644 --- a/hw/block/dataplane/xen-block.c +++ b/hw/block/dataplane/xen-block.c @@ -38,12 +38,12 @@ struct ioreq { int presync; int aio_inflight; int aio_errors; - struct XenBlkDev *blkdev; + XenBlockDataPlane *dataplane; QLIST_ENTRY(ioreq) list; BlockAcctCookie acct; }; -struct XenBlkDev { +struct XenBlockDataPlane { XenDevice *xendev; XenEventChannel *event_channel; unsigned int *ring_ref; @@ -79,33 +79,33 @@ static void ioreq_reset(struct ioreq *ioreq) ioreq->aio_inflight = 0; ioreq->aio_errors = 0; - ioreq->blkdev = NULL; + ioreq->dataplane = NULL; memset(&ioreq->list, 0, sizeof(ioreq->list)); memset(&ioreq->acct, 0, sizeof(ioreq->acct)); qemu_iovec_reset(&ioreq->v); } -static struct ioreq *ioreq_start(struct XenBlkDev *blkdev) +static struct ioreq *ioreq_start(XenBlockDataPlane *dataplane) { struct ioreq *ioreq = NULL; - if (QLIST_EMPTY(&blkdev->freelist)) { - if (blkdev->requests_total >= blkdev->max_requests) { + if (QLIST_EMPTY(&dataplane->freelist)) { + if (dataplane->requests_total >= dataplane->max_requests) { goto out; } /* allocate new struct */ ioreq = g_malloc0(sizeof(*ioreq)); - ioreq->blkdev = blkdev; - blkdev->requests_total++; + ioreq->dataplane = dataplane; + dataplane->requests_total++; qemu_iovec_init(&ioreq->v, 1); } else { /* get one from freelist */ - ioreq = QLIST_FIRST(&blkdev->freelist); + ioreq = QLIST_FIRST(&dataplane->freelist); QLIST_REMOVE(ioreq, list); } - QLIST_INSERT_HEAD(&blkdev->inflight, ioreq, list); - blkdev->requests_inflight++; + QLIST_INSERT_HEAD(&dataplane->inflight, ioreq, list); + dataplane->requests_inflight++; out: return ioreq; @@ -113,26 +113,26 @@ static struct ioreq *ioreq_start(struct XenBlkDev *blkdev) static void ioreq_finish(struct ioreq *ioreq) { - struct XenBlkDev *blkdev = ioreq->blkdev; + XenBlockDataPlane *dataplane = ioreq->dataplane; QLIST_REMOVE(ioreq, list); - QLIST_INSERT_HEAD(&blkdev->finished, ioreq, list); - blkdev->requests_inflight--; - blkdev->requests_finished++; + QLIST_INSERT_HEAD(&dataplane->finished, ioreq, list); + dataplane->requests_inflight--; + dataplane->requests_finished++; } static void ioreq_release(struct ioreq *ioreq, bool finish) { - struct XenBlkDev *blkdev = ioreq->blkdev; + XenBlockDataPlane *dataplane = ioreq->dataplane; QLIST_REMOVE(ioreq, list); ioreq_reset(ioreq); - ioreq->blkdev = blkdev; - QLIST_INSERT_HEAD(&blkdev->freelist, ioreq, list); + ioreq->dataplane = dataplane; + QLIST_INSERT_HEAD(&dataplane->freelist, ioreq, list); if (finish) { - blkdev->requests_finished--; + dataplane->requests_finished--; } else { - blkdev->requests_inflight--; + dataplane->requests_inflight--; } } @@ -142,7 +142,7 @@ static void ioreq_release(struct ioreq *ioreq, bool finish) */ static int ioreq_parse(struct ioreq *ioreq) { - struct XenBlkDev *blkdev = ioreq->blkdev; + XenBlockDataPlane *dataplane = ioreq->dataplane; size_t len; int i; @@ -165,12 +165,12 @@ static int ioreq_parse(struct ioreq *ioreq) }; if (ioreq->req.operation != BLKIF_OP_READ && - blk_is_read_only(blkdev->blk)) { + blk_is_read_only(dataplane->blk)) { error_report("error: write req for ro device"); goto err; } - ioreq->start = ioreq->req.sector_number * blkdev->file_blk; + ioreq->start = ioreq->req.sector_number * dataplane->file_blk; for (i = 0; i < ioreq->req.nr_segments; i++) { if (i == BLKIF_MAX_SEGMENTS_PER_REQUEST) { error_report("error: nr_segments too big"); @@ -180,16 +180,16 @@ static int ioreq_parse(struct ioreq *ioreq) error_report("error: first > last sector"); goto err; } - if (ioreq->req.seg[i].last_sect * blkdev->file_blk >= XC_PAGE_SIZE) { + if (ioreq->req.seg[i].last_sect * dataplane->file_blk >= XC_PAGE_SIZE) { error_report("error: page crossing"); goto err; } len = (ioreq->req.seg[i].last_sect - - ioreq->req.seg[i].first_sect + 1) * blkdev->file_blk; + ioreq->req.seg[i].first_sect + 1) * dataplane->file_blk; ioreq->size += len; } - if (ioreq->start + ioreq->size > blkdev->file_size) { + if (ioreq->start + ioreq->size > dataplane->file_size) { error_report("error: access beyond end of file"); goto err; } @@ -202,11 +202,11 @@ static int ioreq_parse(struct ioreq *ioreq) static int ioreq_grant_copy(struct ioreq *ioreq) { - struct XenBlkDev *blkdev = ioreq->blkdev; - XenDevice *xendev = blkdev->xendev; + XenBlockDataPlane *dataplane = ioreq->dataplane; + XenDevice *xendev = dataplane->xendev; XenDeviceGrantCopySegment segs[BLKIF_MAX_SEGMENTS_PER_REQUEST]; int i, count; - int64_t file_blk = blkdev->file_blk; + int64_t file_blk = dataplane->file_blk; bool to_domain = (ioreq->req.operation == BLKIF_OP_READ); void *virt = ioreq->buf; Error *local_err = NULL; @@ -251,9 +251,9 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq); static void qemu_aio_complete(void *opaque, int ret) { struct ioreq *ioreq = opaque; - struct XenBlkDev *blkdev = ioreq->blkdev; + XenBlockDataPlane *dataplane = ioreq->dataplane; - aio_context_acquire(blkdev->ctx); + aio_context_acquire(dataplane->ctx); if (ret != 0) { error_report("%s I/O error", @@ -302,25 +302,25 @@ static void qemu_aio_complete(void *opaque, int ret) } case BLKIF_OP_READ: if (ioreq->status == BLKIF_RSP_OKAY) { - block_acct_done(blk_get_stats(blkdev->blk), &ioreq->acct); + block_acct_done(blk_get_stats(dataplane->blk), &ioreq->acct); } else { - block_acct_failed(blk_get_stats(blkdev->blk), &ioreq->acct); + block_acct_failed(blk_get_stats(dataplane->blk), &ioreq->acct); } break; case BLKIF_OP_DISCARD: default: break; } - qemu_bh_schedule(blkdev->bh); + qemu_bh_schedule(dataplane->bh); done: - aio_context_release(blkdev->ctx); + aio_context_release(dataplane->ctx); } static bool blk_split_discard(struct ioreq *ioreq, blkif_sector_t sector_number, uint64_t nr_sectors) { - struct XenBlkDev *blkdev = ioreq->blkdev; + XenBlockDataPlane *dataplane = ioreq->dataplane; int64_t byte_offset; int byte_chunk; uint64_t byte_remaining, limit; @@ -329,18 +329,18 @@ static bool blk_split_discard(struct ioreq *ioreq, blkif_sector_t sector_number, /* Wrap around, or overflowing byte limit? */ if (sec_start + sec_count < sec_count || - sec_start + sec_count > INT64_MAX / blkdev->file_blk) { + sec_start + sec_count > INT64_MAX / dataplane->file_blk) { return false; } - limit = BDRV_REQUEST_MAX_SECTORS * blkdev->file_blk; - byte_offset = sec_start * blkdev->file_blk; - byte_remaining = sec_count * blkdev->file_blk; + limit = BDRV_REQUEST_MAX_SECTORS * dataplane->file_blk; + byte_offset = sec_start * dataplane->file_blk; + byte_remaining = sec_count * dataplane->file_blk; do { byte_chunk = byte_remaining > limit ? limit : byte_remaining; ioreq->aio_inflight++; - blk_aio_pdiscard(blkdev->blk, byte_offset, byte_chunk, + blk_aio_pdiscard(dataplane->blk, byte_offset, byte_chunk, qemu_aio_complete, ioreq); byte_remaining -= byte_chunk; byte_offset += byte_chunk; @@ -351,7 +351,7 @@ static bool blk_split_discard(struct ioreq *ioreq, blkif_sector_t sector_number, static int ioreq_runio_qemu_aio(struct ioreq *ioreq) { - struct XenBlkDev *blkdev = ioreq->blkdev; + XenBlockDataPlane *dataplane = ioreq->dataplane; ioreq->buf = qemu_memalign(XC_PAGE_SIZE, ioreq->size); if (ioreq->req.nr_segments && @@ -364,17 +364,17 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq) ioreq->aio_inflight++; if (ioreq->presync) { - blk_aio_flush(ioreq->blkdev->blk, qemu_aio_complete, ioreq); + blk_aio_flush(ioreq->dataplane->blk, qemu_aio_complete, ioreq); return 0; } switch (ioreq->req.operation) { case BLKIF_OP_READ: qemu_iovec_add(&ioreq->v, ioreq->buf, ioreq->size); - block_acct_start(blk_get_stats(blkdev->blk), &ioreq->acct, + block_acct_start(blk_get_stats(dataplane->blk), &ioreq->acct, ioreq->v.size, BLOCK_ACCT_READ); ioreq->aio_inflight++; - blk_aio_preadv(blkdev->blk, ioreq->start, &ioreq->v, 0, + blk_aio_preadv(dataplane->blk, ioreq->start, &ioreq->v, 0, qemu_aio_complete, ioreq); break; case BLKIF_OP_WRITE: @@ -384,12 +384,12 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq) } qemu_iovec_add(&ioreq->v, ioreq->buf, ioreq->size); - block_acct_start(blk_get_stats(blkdev->blk), &ioreq->acct, + block_acct_start(blk_get_stats(dataplane->blk), &ioreq->acct, ioreq->v.size, ioreq->req.operation == BLKIF_OP_WRITE ? BLOCK_ACCT_WRITE : BLOCK_ACCT_FLUSH); ioreq->aio_inflight++; - blk_aio_pwritev(blkdev->blk, ioreq->start, &ioreq->v, 0, + blk_aio_pwritev(dataplane->blk, ioreq->start, &ioreq->v, 0, qemu_aio_complete, ioreq); break; case BLKIF_OP_DISCARD: @@ -417,27 +417,27 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq) static int blk_send_response_one(struct ioreq *ioreq) { - struct XenBlkDev *blkdev = ioreq->blkdev; + XenBlockDataPlane *dataplane = ioreq->dataplane; int send_notify = 0; int have_requests = 0; blkif_response_t *resp; /* Place on the response ring for the relevant domain. */ - switch (blkdev->protocol) { + switch (dataplane->protocol) { case BLKIF_PROTOCOL_NATIVE: resp = (blkif_response_t *)RING_GET_RESPONSE( - &blkdev->rings.native, - blkdev->rings.native.rsp_prod_pvt); + &dataplane->rings.native, + dataplane->rings.native.rsp_prod_pvt); break; case BLKIF_PROTOCOL_X86_32: resp = (blkif_response_t *)RING_GET_RESPONSE( - &blkdev->rings.x86_32_part, - blkdev->rings.x86_32_part.rsp_prod_pvt); + &dataplane->rings.x86_32_part, + dataplane->rings.x86_32_part.rsp_prod_pvt); break; case BLKIF_PROTOCOL_X86_64: resp = (blkif_response_t *)RING_GET_RESPONSE( - &blkdev->rings.x86_64_part, - blkdev->rings.x86_64_part.rsp_prod_pvt); + &dataplane->rings.x86_64_part, + dataplane->rings.x86_64_part.rsp_prod_pvt); break; default: return 0; @@ -447,42 +447,45 @@ static int blk_send_response_one(struct ioreq *ioreq) resp->operation = ioreq->req.operation; resp->status = ioreq->status; - blkdev->rings.common.rsp_prod_pvt++; + dataplane->rings.common.rsp_prod_pvt++; - RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&blkdev->rings.common, send_notify); - if (blkdev->rings.common.rsp_prod_pvt == blkdev->rings.common.req_cons) { + RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&dataplane->rings.common, + send_notify); + if (dataplane->rings.common.rsp_prod_pvt == + dataplane->rings.common.req_cons) { /* * Tail check for pending requests. Allows frontend to avoid * notifications if requests are already in flight (lower * overheads and promotes batching). */ - RING_FINAL_CHECK_FOR_REQUESTS(&blkdev->rings.common, have_requests); - } else if (RING_HAS_UNCONSUMED_REQUESTS(&blkdev->rings.common)) { + RING_FINAL_CHECK_FOR_REQUESTS(&dataplane->rings.common, + have_requests); + } else if (RING_HAS_UNCONSUMED_REQUESTS(&dataplane->rings.common)) { have_requests = 1; } if (have_requests) { - blkdev->more_work++; + dataplane->more_work++; } return send_notify; } /* walk finished list, send outstanding responses, free requests */ -static void blk_send_response_all(struct XenBlkDev *blkdev) +static void blk_send_response_all(XenBlockDataPlane *dataplane) { struct ioreq *ioreq; int send_notify = 0; - while (!QLIST_EMPTY(&blkdev->finished)) { - ioreq = QLIST_FIRST(&blkdev->finished); + while (!QLIST_EMPTY(&dataplane->finished)) { + ioreq = QLIST_FIRST(&dataplane->finished); send_notify += blk_send_response_one(ioreq); ioreq_release(ioreq, true); } if (send_notify) { Error *local_err = NULL; - xen_device_notify_event_channel(blkdev->xendev, - blkdev->event_channel, + xen_device_notify_event_channel(dataplane->xendev, + dataplane->event_channel, &local_err); if (local_err) { error_report_err(local_err); @@ -490,67 +493,76 @@ static void blk_send_response_all(struct XenBlkDev *blkdev) } } -static int blk_get_request(struct XenBlkDev *blkdev, struct ioreq *ioreq, +static int blk_get_request(XenBlockDataPlane *dataplane, struct ioreq *ioreq, RING_IDX rc) { - switch (blkdev->protocol) { - case BLKIF_PROTOCOL_NATIVE: - memcpy(&ioreq->req, RING_GET_REQUEST(&blkdev->rings.native, rc), - sizeof(ioreq->req)); + switch (dataplane->protocol) { + case BLKIF_PROTOCOL_NATIVE: { + blkif_request_t *req = + RING_GET_REQUEST(&dataplane->rings.native, rc); + + memcpy(&ioreq->req, req, sizeof(ioreq->req)); break; - case BLKIF_PROTOCOL_X86_32: - blkif_get_x86_32_req(&ioreq->req, - RING_GET_REQUEST(&blkdev->rings.x86_32_part, rc)); + } + case BLKIF_PROTOCOL_X86_32: { + blkif_x86_32_request_t *req = + RING_GET_REQUEST(&dataplane->rings.x86_32_part, rc); + + blkif_get_x86_32_req(&ioreq->req, req); break; - case BLKIF_PROTOCOL_X86_64: - blkif_get_x86_64_req(&ioreq->req, - RING_GET_REQUEST(&blkdev->rings.x86_64_part, rc)); + } + case BLKIF_PROTOCOL_X86_64: { + blkif_x86_64_request_t *req = + RING_GET_REQUEST(&dataplane->rings.x86_64_part, rc); + + blkif_get_x86_64_req(&ioreq->req, req); break; } + } /* Prevent the compiler from accessing the on-ring fields instead. */ barrier(); return 0; } -static void blk_handle_requests(struct XenBlkDev *blkdev) +static void blk_handle_requests(XenBlockDataPlane *dataplane) { RING_IDX rc, rp; struct ioreq *ioreq; - blkdev->more_work = 0; + dataplane->more_work = 0; - rc = blkdev->rings.common.req_cons; - rp = blkdev->rings.common.sring->req_prod; + rc = dataplane->rings.common.req_cons; + rp = dataplane->rings.common.sring->req_prod; xen_rmb(); /* Ensure we see queued requests up to 'rp'. */ - blk_send_response_all(blkdev); + blk_send_response_all(dataplane); while (rc != rp) { /* pull request from ring */ - if (RING_REQUEST_CONS_OVERFLOW(&blkdev->rings.common, rc)) { + if (RING_REQUEST_CONS_OVERFLOW(&dataplane->rings.common, rc)) { break; } - ioreq = ioreq_start(blkdev); + ioreq = ioreq_start(dataplane); if (ioreq == NULL) { - blkdev->more_work++; + dataplane->more_work++; break; } - blk_get_request(blkdev, ioreq, rc); - blkdev->rings.common.req_cons = ++rc; + blk_get_request(dataplane, ioreq, rc); + dataplane->rings.common.req_cons = ++rc; /* parse them */ if (ioreq_parse(ioreq) != 0) { switch (ioreq->req.operation) { case BLKIF_OP_READ: - block_acct_invalid(blk_get_stats(blkdev->blk), + block_acct_invalid(blk_get_stats(dataplane->blk), BLOCK_ACCT_READ); break; case BLKIF_OP_WRITE: - block_acct_invalid(blk_get_stats(blkdev->blk), + block_acct_invalid(blk_get_stats(dataplane->blk), BLOCK_ACCT_WRITE); break; case BLKIF_OP_FLUSH_DISKCACHE: - block_acct_invalid(blk_get_stats(blkdev->blk), + block_acct_invalid(blk_get_stats(dataplane->blk), BLOCK_ACCT_FLUSH); default: break; @@ -559,8 +571,8 @@ static void blk_handle_requests(struct XenBlkDev *blkdev) if (blk_send_response_one(ioreq)) { Error *local_err = NULL; - xen_device_notify_event_channel(blkdev->xendev, - blkdev->event_channel, + xen_device_notify_event_channel(dataplane->xendev, + dataplane->event_channel, &local_err); if (local_err) { error_report_err(local_err); @@ -573,173 +585,173 @@ static void blk_handle_requests(struct XenBlkDev *blkdev) ioreq_runio_qemu_aio(ioreq); } - if (blkdev->more_work && blkdev->requests_inflight < blkdev->max_requests) { - qemu_bh_schedule(blkdev->bh); + if (dataplane->more_work && + dataplane->requests_inflight < dataplane->max_requests) { + qemu_bh_schedule(dataplane->bh); } } static void blk_bh(void *opaque) { - struct XenBlkDev *blkdev = opaque; + XenBlockDataPlane *dataplane = opaque; - aio_context_acquire(blkdev->ctx); - blk_handle_requests(blkdev); - aio_context_release(blkdev->ctx); + aio_context_acquire(dataplane->ctx); + blk_handle_requests(dataplane); + aio_context_release(dataplane->ctx); } static void blk_event(void *opaque) { - struct XenBlkDev *blkdev = opaque; + XenBlockDataPlane *dataplane = opaque; - qemu_bh_schedule(blkdev->bh); + qemu_bh_schedule(dataplane->bh); } -struct XenBlkDev *xen_block_dataplane_create(XenDevice *xendev, - BlockConf *conf, - IOThread *iothread) +XenBlockDataPlane *xen_block_dataplane_create(XenDevice *xendev, + BlockConf *conf, + IOThread *iothread) { - struct XenBlkDev *blkdev = g_new0(struct XenBlkDev, 1); + XenBlockDataPlane *dataplane = g_new0(XenBlockDataPlane, 1); - blkdev->xendev = xendev; - blkdev->file_blk = conf->logical_block_size; - blkdev->blk = conf->blk; - blkdev->file_size = blk_getlength(blkdev->blk); + dataplane->xendev = xendev; + dataplane->file_blk = conf->logical_block_size; + dataplane->blk = conf->blk; + dataplane->file_size = blk_getlength(dataplane->blk); - QLIST_INIT(&blkdev->inflight); - QLIST_INIT(&blkdev->finished); - QLIST_INIT(&blkdev->freelist); + QLIST_INIT(&dataplane->inflight); + QLIST_INIT(&dataplane->finished); + QLIST_INIT(&dataplane->freelist); if (iothread) { - blkdev->iothread = iothread; - object_ref(OBJECT(blkdev->iothread)); - blkdev->ctx = iothread_get_aio_context(blkdev->iothread); + dataplane->iothread = iothread; + object_ref(OBJECT(dataplane->iothread)); + dataplane->ctx = iothread_get_aio_context(dataplane->iothread); } else { - blkdev->ctx = qemu_get_aio_context(); + dataplane->ctx = qemu_get_aio_context(); } - blkdev->bh = aio_bh_new(blkdev->ctx, blk_bh, blkdev); + dataplane->bh = aio_bh_new(dataplane->ctx, blk_bh, dataplane); - return blkdev; + return dataplane; } -void xen_block_dataplane_destroy(struct XenBlkDev *blkdev) +void xen_block_dataplane_destroy(XenBlockDataPlane *dataplane) { struct ioreq *ioreq; - if (!blkdev) { + if (!dataplane) { return; } - while (!QLIST_EMPTY(&blkdev->freelist)) { - ioreq = QLIST_FIRST(&blkdev->freelist); + while (!QLIST_EMPTY(&dataplane->freelist)) { + ioreq = QLIST_FIRST(&dataplane->freelist); QLIST_REMOVE(ioreq, list); qemu_iovec_destroy(&ioreq->v); g_free(ioreq); } - qemu_bh_delete(blkdev->bh); - if (blkdev->iothread) { - object_unref(OBJECT(blkdev->iothread)); + qemu_bh_delete(dataplane->bh); + if (dataplane->iothread) { + object_unref(OBJECT(dataplane->iothread)); } - g_free(blkdev); + g_free(dataplane); } - -void xen_block_dataplane_stop(struct XenBlkDev *blkdev) +void xen_block_dataplane_stop(XenBlockDataPlane *dataplane) { XenDevice *xendev; - if (!blkdev) { + if (!dataplane) { return; } - aio_context_acquire(blkdev->ctx); - blk_set_aio_context(blkdev->blk, qemu_get_aio_context()); - aio_context_release(blkdev->ctx); + aio_context_acquire(dataplane->ctx); + blk_set_aio_context(dataplane->blk, qemu_get_aio_context()); + aio_context_release(dataplane->ctx); - xendev = blkdev->xendev; + xendev = dataplane->xendev; - if (blkdev->event_channel) { + if (dataplane->event_channel) { Error *local_err = NULL; - xen_device_unbind_event_channel(xendev, blkdev->event_channel, + xen_device_unbind_event_channel(xendev, dataplane->event_channel, &local_err); - blkdev->event_channel = NULL; + dataplane->event_channel = NULL; if (local_err) { error_report_err(local_err); } } - if (blkdev->sring) { + if (dataplane->sring) { Error *local_err = NULL; - xen_device_unmap_grant_refs(xendev, blkdev->sring, - blkdev->nr_ring_ref, &local_err); - blkdev->sring = NULL; + xen_device_unmap_grant_refs(xendev, dataplane->sring, + dataplane->nr_ring_ref, &local_err); + dataplane->sring = NULL; if (local_err) { error_report_err(local_err); } } - g_free(blkdev->ring_ref); - blkdev->ring_ref = NULL; + g_free(dataplane->ring_ref); + dataplane->ring_ref = NULL; } -void xen_block_dataplane_start(struct XenBlkDev *blkdev, +void xen_block_dataplane_start(XenBlockDataPlane *dataplane, const unsigned int ring_ref[], unsigned int nr_ring_ref, unsigned int event_channel, unsigned int protocol, Error **errp) { - XenDevice *xendev = blkdev->xendev; + XenDevice *xendev = dataplane->xendev; Error *local_err = NULL; unsigned int ring_size; unsigned int i; - blkdev->nr_ring_ref = nr_ring_ref; - blkdev->ring_ref = g_new(unsigned int, nr_ring_ref); + dataplane->nr_ring_ref = nr_ring_ref; + dataplane->ring_ref = g_new(unsigned int, nr_ring_ref); for (i = 0; i < nr_ring_ref; i++) { - blkdev->ring_ref[i] = ring_ref[i]; + dataplane->ring_ref[i] = ring_ref[i]; } - blkdev->protocol = protocol; + dataplane->protocol = protocol; - ring_size = XC_PAGE_SIZE * blkdev->nr_ring_ref; - switch (blkdev->protocol) { + ring_size = XC_PAGE_SIZE * dataplane->nr_ring_ref; + switch (dataplane->protocol) { case BLKIF_PROTOCOL_NATIVE: { - blkdev->max_requests = __CONST_RING_SIZE(blkif, ring_size); + dataplane->max_requests = __CONST_RING_SIZE(blkif, ring_size); break; } case BLKIF_PROTOCOL_X86_32: { - blkdev->max_requests = __CONST_RING_SIZE(blkif_x86_32, ring_size); + dataplane->max_requests = __CONST_RING_SIZE(blkif_x86_32, ring_size); break; } case BLKIF_PROTOCOL_X86_64: { - blkdev->max_requests = __CONST_RING_SIZE(blkif_x86_64, ring_size); + dataplane->max_requests = __CONST_RING_SIZE(blkif_x86_64, ring_size); break; } default: - error_setg(errp, "unknown protocol %u", blkdev->protocol); + error_setg(errp, "unknown protocol %u", dataplane->protocol); return; } - xen_device_set_max_grant_refs(xendev, blkdev->nr_ring_ref, + xen_device_set_max_grant_refs(xendev, dataplane->nr_ring_ref, &local_err); if (local_err) { error_propagate(errp, local_err); goto stop; } - blkdev->sring = xen_device_map_grant_refs(xendev, - blkdev->ring_ref, - blkdev->nr_ring_ref, + dataplane->sring = xen_device_map_grant_refs(xendev, + dataplane->ring_ref, + dataplane->nr_ring_ref, PROT_READ | PROT_WRITE, &local_err); if (local_err) { @@ -747,46 +759,46 @@ void xen_block_dataplane_start(struct XenBlkDev *blkdev, goto stop; } - switch (blkdev->protocol) { + switch (dataplane->protocol) { case BLKIF_PROTOCOL_NATIVE: { - blkif_sring_t *sring_native = blkdev->sring; + blkif_sring_t *sring_native = dataplane->sring; - BACK_RING_INIT(&blkdev->rings.native, sring_native, ring_size); + BACK_RING_INIT(&dataplane->rings.native, sring_native, ring_size); break; } case BLKIF_PROTOCOL_X86_32: { - blkif_x86_32_sring_t *sring_x86_32 = blkdev->sring; + blkif_x86_32_sring_t *sring_x86_32 = dataplane->sring; - BACK_RING_INIT(&blkdev->rings.x86_32_part, sring_x86_32, + BACK_RING_INIT(&dataplane->rings.x86_32_part, sring_x86_32, ring_size); break; } case BLKIF_PROTOCOL_X86_64: { - blkif_x86_64_sring_t *sring_x86_64 = blkdev->sring; + blkif_x86_64_sring_t *sring_x86_64 = dataplane->sring; - BACK_RING_INIT(&blkdev->rings.x86_64_part, sring_x86_64, + BACK_RING_INIT(&dataplane->rings.x86_64_part, sring_x86_64, ring_size); break; } } - blkdev->event_channel = + dataplane->event_channel = xen_device_bind_event_channel(xendev, event_channel, - blk_event, blkdev, + blk_event, dataplane, &local_err); if (local_err) { error_propagate(errp, local_err); goto stop; } - aio_context_acquire(blkdev->ctx); - blk_set_aio_context(blkdev->blk, blkdev->ctx); - aio_context_release(blkdev->ctx); + aio_context_acquire(dataplane->ctx); + blk_set_aio_context(dataplane->blk, dataplane->ctx); + aio_context_release(dataplane->ctx); return; stop: - xen_block_dataplane_stop(blkdev); + xen_block_dataplane_stop(dataplane); } diff --git a/hw/block/dataplane/xen-block.h b/hw/block/dataplane/xen-block.h index f31da38464..d6fa6d26dd 100644 --- a/hw/block/dataplane/xen-block.h +++ b/hw/block/dataplane/xen-block.h @@ -12,7 +12,7 @@ #include "hw/xen/xen-bus.h" #include "sysemu/iothread.h" -typedef struct XenBlkDev XenBlockDataPlane; +typedef struct XenBlockDataPlane XenBlockDataPlane; XenBlockDataPlane *xen_block_dataplane_create(XenDevice *xendev, BlockConf *conf, From patchwork Mon Jan 14 13:51:43 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anthony PERARD X-Patchwork-Id: 10762741 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 7CE4813B4 for ; Mon, 14 Jan 2019 14:18:28 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 683B628D34 for ; Mon, 14 Jan 2019 14:18:28 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5C5B028CF6; Mon, 14 Jan 2019 14:18:28 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 12EB528D35 for ; Mon, 14 Jan 2019 14:18:26 +0000 (UTC) Received: from localhost ([127.0.0.1]:36993 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gj34K-0004W5-RM for patchwork-qemu-devel@patchwork.kernel.org; Mon, 14 Jan 2019 09:18:24 -0500 Received: from eggs.gnu.org ([209.51.188.92]:47466) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gj2mC-0007ZN-QY for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:59:43 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gj2mA-00051Z-FL for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:59:40 -0500 Received: from smtp03.citrix.com ([162.221.156.55]:1419) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gj2m5-0004zB-RV for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:59:36 -0500 X-IronPort-AV: E=Sophos;i="5.56,477,1539648000"; d="scan'208";a="75507057" From: Anthony PERARD To: Date: Mon, 14 Jan 2019 13:51:43 +0000 Message-ID: <20190114135154.16826-15-anthony.perard@citrix.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190114135154.16826-1-anthony.perard@citrix.com> References: <20190114135154.16826-1-anthony.perard@citrix.com> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 162.221.156.55 Subject: [Qemu-devel] [PULL 14/25] xen: remove 'ioreq' struct/varable/field names from dataplane/xen-block.c X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Anthony PERARD , xen-devel@lists.xenproject.org, Peter Maydell Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Paul Durrant This is a purely cosmetic patch that purges the name 'ioreq' from struct, variable and field names. (This name has been problematic for a long time as 'ioreq' is the name used for generic I/O requests coming from Xen). The patch replaces 'struct ioreq' with a new 'XenBlockRequest' type and 'ioreq' field/variable names with 'request', and then does necessary fix-up to adhere to coding style. Function names are not modified by this patch. They will be dealt with in a subsequent patch. No functional change. Signed-off-by: Paul Durrant Acked-by: Anthony Perard Signed-off-by: Anthony PERARD --- hw/block/dataplane/xen-block.c | 310 +++++++++++++++++---------------- 1 file changed, 156 insertions(+), 154 deletions(-) diff --git a/hw/block/dataplane/xen-block.c b/hw/block/dataplane/xen-block.c index 1ff464973c..6788bbf338 100644 --- a/hw/block/dataplane/xen-block.c +++ b/hw/block/dataplane/xen-block.c @@ -28,7 +28,7 @@ #include "sysemu/iothread.h" #include "xen-block.h" -struct ioreq { +typedef struct XenBlockRequest { blkif_request_t req; int16_t status; off_t start; @@ -39,9 +39,9 @@ struct ioreq { int aio_inflight; int aio_errors; XenBlockDataPlane *dataplane; - QLIST_ENTRY(ioreq) list; + QLIST_ENTRY(XenBlockRequest) list; BlockAcctCookie acct; -}; +} XenBlockRequest; struct XenBlockDataPlane { XenDevice *xendev; @@ -54,9 +54,9 @@ struct XenBlockDataPlane { int protocol; blkif_back_rings_t rings; int more_work; - QLIST_HEAD(inflight_head, ioreq) inflight; - QLIST_HEAD(finished_head, ioreq) finished; - QLIST_HEAD(freelist_head, ioreq) freelist; + QLIST_HEAD(inflight_head, XenBlockRequest) inflight; + QLIST_HEAD(finished_head, XenBlockRequest) finished; + QLIST_HEAD(freelist_head, XenBlockRequest) freelist; int requests_total; int requests_inflight; int requests_finished; @@ -67,68 +67,68 @@ struct XenBlockDataPlane { AioContext *ctx; }; -static void ioreq_reset(struct ioreq *ioreq) +static void ioreq_reset(XenBlockRequest *request) { - memset(&ioreq->req, 0, sizeof(ioreq->req)); - ioreq->status = 0; - ioreq->start = 0; - ioreq->buf = NULL; - ioreq->size = 0; - ioreq->presync = 0; + memset(&request->req, 0, sizeof(request->req)); + request->status = 0; + request->start = 0; + request->buf = NULL; + request->size = 0; + request->presync = 0; - ioreq->aio_inflight = 0; - ioreq->aio_errors = 0; + request->aio_inflight = 0; + request->aio_errors = 0; - ioreq->dataplane = NULL; - memset(&ioreq->list, 0, sizeof(ioreq->list)); - memset(&ioreq->acct, 0, sizeof(ioreq->acct)); + request->dataplane = NULL; + memset(&request->list, 0, sizeof(request->list)); + memset(&request->acct, 0, sizeof(request->acct)); - qemu_iovec_reset(&ioreq->v); + qemu_iovec_reset(&request->v); } -static struct ioreq *ioreq_start(XenBlockDataPlane *dataplane) +static XenBlockRequest *ioreq_start(XenBlockDataPlane *dataplane) { - struct ioreq *ioreq = NULL; + XenBlockRequest *request = NULL; if (QLIST_EMPTY(&dataplane->freelist)) { if (dataplane->requests_total >= dataplane->max_requests) { goto out; } /* allocate new struct */ - ioreq = g_malloc0(sizeof(*ioreq)); - ioreq->dataplane = dataplane; + request = g_malloc0(sizeof(*request)); + request->dataplane = dataplane; dataplane->requests_total++; - qemu_iovec_init(&ioreq->v, 1); + qemu_iovec_init(&request->v, 1); } else { /* get one from freelist */ - ioreq = QLIST_FIRST(&dataplane->freelist); - QLIST_REMOVE(ioreq, list); + request = QLIST_FIRST(&dataplane->freelist); + QLIST_REMOVE(request, list); } - QLIST_INSERT_HEAD(&dataplane->inflight, ioreq, list); + QLIST_INSERT_HEAD(&dataplane->inflight, request, list); dataplane->requests_inflight++; out: - return ioreq; + return request; } -static void ioreq_finish(struct ioreq *ioreq) +static void ioreq_finish(XenBlockRequest *request) { - XenBlockDataPlane *dataplane = ioreq->dataplane; + XenBlockDataPlane *dataplane = request->dataplane; - QLIST_REMOVE(ioreq, list); - QLIST_INSERT_HEAD(&dataplane->finished, ioreq, list); + QLIST_REMOVE(request, list); + QLIST_INSERT_HEAD(&dataplane->finished, request, list); dataplane->requests_inflight--; dataplane->requests_finished++; } -static void ioreq_release(struct ioreq *ioreq, bool finish) +static void ioreq_release(XenBlockRequest *request, bool finish) { - XenBlockDataPlane *dataplane = ioreq->dataplane; + XenBlockDataPlane *dataplane = request->dataplane; - QLIST_REMOVE(ioreq, list); - ioreq_reset(ioreq); - ioreq->dataplane = dataplane; - QLIST_INSERT_HEAD(&dataplane->freelist, ioreq, list); + QLIST_REMOVE(request, list); + ioreq_reset(request); + request->dataplane = dataplane; + QLIST_INSERT_HEAD(&dataplane->freelist, request, list); if (finish) { dataplane->requests_finished--; } else { @@ -140,18 +140,18 @@ static void ioreq_release(struct ioreq *ioreq, bool finish) * translate request into iovec + start offset * do sanity checks along the way */ -static int ioreq_parse(struct ioreq *ioreq) +static int ioreq_parse(XenBlockRequest *request) { - XenBlockDataPlane *dataplane = ioreq->dataplane; + XenBlockDataPlane *dataplane = request->dataplane; size_t len; int i; - switch (ioreq->req.operation) { + switch (request->req.operation) { case BLKIF_OP_READ: break; case BLKIF_OP_FLUSH_DISKCACHE: - ioreq->presync = 1; - if (!ioreq->req.nr_segments) { + request->presync = 1; + if (!request->req.nr_segments) { return 0; } /* fall through */ @@ -160,77 +160,78 @@ static int ioreq_parse(struct ioreq *ioreq) case BLKIF_OP_DISCARD: return 0; default: - error_report("error: unknown operation (%d)", ioreq->req.operation); + error_report("error: unknown operation (%d)", request->req.operation); goto err; }; - if (ioreq->req.operation != BLKIF_OP_READ && + if (request->req.operation != BLKIF_OP_READ && blk_is_read_only(dataplane->blk)) { error_report("error: write req for ro device"); goto err; } - ioreq->start = ioreq->req.sector_number * dataplane->file_blk; - for (i = 0; i < ioreq->req.nr_segments; i++) { + request->start = request->req.sector_number * dataplane->file_blk; + for (i = 0; i < request->req.nr_segments; i++) { if (i == BLKIF_MAX_SEGMENTS_PER_REQUEST) { error_report("error: nr_segments too big"); goto err; } - if (ioreq->req.seg[i].first_sect > ioreq->req.seg[i].last_sect) { + if (request->req.seg[i].first_sect > request->req.seg[i].last_sect) { error_report("error: first > last sector"); goto err; } - if (ioreq->req.seg[i].last_sect * dataplane->file_blk >= XC_PAGE_SIZE) { + if (request->req.seg[i].last_sect * dataplane->file_blk >= + XC_PAGE_SIZE) { error_report("error: page crossing"); goto err; } - len = (ioreq->req.seg[i].last_sect - - ioreq->req.seg[i].first_sect + 1) * dataplane->file_blk; - ioreq->size += len; + len = (request->req.seg[i].last_sect - + request->req.seg[i].first_sect + 1) * dataplane->file_blk; + request->size += len; } - if (ioreq->start + ioreq->size > dataplane->file_size) { + if (request->start + request->size > dataplane->file_size) { error_report("error: access beyond end of file"); goto err; } return 0; err: - ioreq->status = BLKIF_RSP_ERROR; + request->status = BLKIF_RSP_ERROR; return -1; } -static int ioreq_grant_copy(struct ioreq *ioreq) +static int ioreq_grant_copy(XenBlockRequest *request) { - XenBlockDataPlane *dataplane = ioreq->dataplane; + XenBlockDataPlane *dataplane = request->dataplane; XenDevice *xendev = dataplane->xendev; XenDeviceGrantCopySegment segs[BLKIF_MAX_SEGMENTS_PER_REQUEST]; int i, count; int64_t file_blk = dataplane->file_blk; - bool to_domain = (ioreq->req.operation == BLKIF_OP_READ); - void *virt = ioreq->buf; + bool to_domain = (request->req.operation == BLKIF_OP_READ); + void *virt = request->buf; Error *local_err = NULL; - if (ioreq->req.nr_segments == 0) { + if (request->req.nr_segments == 0) { return 0; } - count = ioreq->req.nr_segments; + count = request->req.nr_segments; for (i = 0; i < count; i++) { if (to_domain) { - segs[i].dest.foreign.ref = ioreq->req.seg[i].gref; - segs[i].dest.foreign.offset = ioreq->req.seg[i].first_sect * + segs[i].dest.foreign.ref = request->req.seg[i].gref; + segs[i].dest.foreign.offset = request->req.seg[i].first_sect * file_blk; segs[i].source.virt = virt; } else { - segs[i].source.foreign.ref = ioreq->req.seg[i].gref; - segs[i].source.foreign.offset = ioreq->req.seg[i].first_sect * + segs[i].source.foreign.ref = request->req.seg[i].gref; + segs[i].source.foreign.offset = request->req.seg[i].first_sect * file_blk; segs[i].dest.virt = virt; } - segs[i].len = (ioreq->req.seg[i].last_sect - - ioreq->req.seg[i].first_sect + 1) * file_blk; + segs[i].len = (request->req.seg[i].last_sect - + request->req.seg[i].first_sect + 1) * file_blk; virt += segs[i].len; } @@ -239,72 +240,72 @@ static int ioreq_grant_copy(struct ioreq *ioreq) if (local_err) { error_reportf_err(local_err, "failed to copy data: "); - ioreq->aio_errors++; + request->aio_errors++; return -1; } return 0; } -static int ioreq_runio_qemu_aio(struct ioreq *ioreq); +static int ioreq_runio_qemu_aio(XenBlockRequest *request); static void qemu_aio_complete(void *opaque, int ret) { - struct ioreq *ioreq = opaque; - XenBlockDataPlane *dataplane = ioreq->dataplane; + XenBlockRequest *request = opaque; + XenBlockDataPlane *dataplane = request->dataplane; aio_context_acquire(dataplane->ctx); if (ret != 0) { error_report("%s I/O error", - ioreq->req.operation == BLKIF_OP_READ ? + request->req.operation == BLKIF_OP_READ ? "read" : "write"); - ioreq->aio_errors++; + request->aio_errors++; } - ioreq->aio_inflight--; - if (ioreq->presync) { - ioreq->presync = 0; - ioreq_runio_qemu_aio(ioreq); + request->aio_inflight--; + if (request->presync) { + request->presync = 0; + ioreq_runio_qemu_aio(request); goto done; } - if (ioreq->aio_inflight > 0) { + if (request->aio_inflight > 0) { goto done; } - switch (ioreq->req.operation) { + switch (request->req.operation) { case BLKIF_OP_READ: - /* in case of failure ioreq->aio_errors is increased */ + /* in case of failure request->aio_errors is increased */ if (ret == 0) { - ioreq_grant_copy(ioreq); + ioreq_grant_copy(request); } - qemu_vfree(ioreq->buf); + qemu_vfree(request->buf); break; case BLKIF_OP_WRITE: case BLKIF_OP_FLUSH_DISKCACHE: - if (!ioreq->req.nr_segments) { + if (!request->req.nr_segments) { break; } - qemu_vfree(ioreq->buf); + qemu_vfree(request->buf); break; default: break; } - ioreq->status = ioreq->aio_errors ? BLKIF_RSP_ERROR : BLKIF_RSP_OKAY; - ioreq_finish(ioreq); + request->status = request->aio_errors ? BLKIF_RSP_ERROR : BLKIF_RSP_OKAY; + ioreq_finish(request); - switch (ioreq->req.operation) { + switch (request->req.operation) { case BLKIF_OP_WRITE: case BLKIF_OP_FLUSH_DISKCACHE: - if (!ioreq->req.nr_segments) { + if (!request->req.nr_segments) { break; } case BLKIF_OP_READ: - if (ioreq->status == BLKIF_RSP_OKAY) { - block_acct_done(blk_get_stats(dataplane->blk), &ioreq->acct); + if (request->status == BLKIF_RSP_OKAY) { + block_acct_done(blk_get_stats(dataplane->blk), &request->acct); } else { - block_acct_failed(blk_get_stats(dataplane->blk), &ioreq->acct); + block_acct_failed(blk_get_stats(dataplane->blk), &request->acct); } break; case BLKIF_OP_DISCARD: @@ -317,10 +318,11 @@ static void qemu_aio_complete(void *opaque, int ret) aio_context_release(dataplane->ctx); } -static bool blk_split_discard(struct ioreq *ioreq, blkif_sector_t sector_number, +static bool blk_split_discard(XenBlockRequest *request, + blkif_sector_t sector_number, uint64_t nr_sectors) { - XenBlockDataPlane *dataplane = ioreq->dataplane; + XenBlockDataPlane *dataplane = request->dataplane; int64_t byte_offset; int byte_chunk; uint64_t byte_remaining, limit; @@ -339,9 +341,9 @@ static bool blk_split_discard(struct ioreq *ioreq, blkif_sector_t sector_number, do { byte_chunk = byte_remaining > limit ? limit : byte_remaining; - ioreq->aio_inflight++; + request->aio_inflight++; blk_aio_pdiscard(dataplane->blk, byte_offset, byte_chunk, - qemu_aio_complete, ioreq); + qemu_aio_complete, request); byte_remaining -= byte_chunk; byte_offset += byte_chunk; } while (byte_remaining > 0); @@ -349,53 +351,53 @@ static bool blk_split_discard(struct ioreq *ioreq, blkif_sector_t sector_number, return true; } -static int ioreq_runio_qemu_aio(struct ioreq *ioreq) +static int ioreq_runio_qemu_aio(XenBlockRequest *request) { - XenBlockDataPlane *dataplane = ioreq->dataplane; - - ioreq->buf = qemu_memalign(XC_PAGE_SIZE, ioreq->size); - if (ioreq->req.nr_segments && - (ioreq->req.operation == BLKIF_OP_WRITE || - ioreq->req.operation == BLKIF_OP_FLUSH_DISKCACHE) && - ioreq_grant_copy(ioreq)) { - qemu_vfree(ioreq->buf); + XenBlockDataPlane *dataplane = request->dataplane; + + request->buf = qemu_memalign(XC_PAGE_SIZE, request->size); + if (request->req.nr_segments && + (request->req.operation == BLKIF_OP_WRITE || + request->req.operation == BLKIF_OP_FLUSH_DISKCACHE) && + ioreq_grant_copy(request)) { + qemu_vfree(request->buf); goto err; } - ioreq->aio_inflight++; - if (ioreq->presync) { - blk_aio_flush(ioreq->dataplane->blk, qemu_aio_complete, ioreq); + request->aio_inflight++; + if (request->presync) { + blk_aio_flush(request->dataplane->blk, qemu_aio_complete, request); return 0; } - switch (ioreq->req.operation) { + switch (request->req.operation) { case BLKIF_OP_READ: - qemu_iovec_add(&ioreq->v, ioreq->buf, ioreq->size); - block_acct_start(blk_get_stats(dataplane->blk), &ioreq->acct, - ioreq->v.size, BLOCK_ACCT_READ); - ioreq->aio_inflight++; - blk_aio_preadv(dataplane->blk, ioreq->start, &ioreq->v, 0, - qemu_aio_complete, ioreq); + qemu_iovec_add(&request->v, request->buf, request->size); + block_acct_start(blk_get_stats(dataplane->blk), &request->acct, + request->v.size, BLOCK_ACCT_READ); + request->aio_inflight++; + blk_aio_preadv(dataplane->blk, request->start, &request->v, 0, + qemu_aio_complete, request); break; case BLKIF_OP_WRITE: case BLKIF_OP_FLUSH_DISKCACHE: - if (!ioreq->req.nr_segments) { + if (!request->req.nr_segments) { break; } - qemu_iovec_add(&ioreq->v, ioreq->buf, ioreq->size); - block_acct_start(blk_get_stats(dataplane->blk), &ioreq->acct, - ioreq->v.size, - ioreq->req.operation == BLKIF_OP_WRITE ? + qemu_iovec_add(&request->v, request->buf, request->size); + block_acct_start(blk_get_stats(dataplane->blk), &request->acct, + request->v.size, + request->req.operation == BLKIF_OP_WRITE ? BLOCK_ACCT_WRITE : BLOCK_ACCT_FLUSH); - ioreq->aio_inflight++; - blk_aio_pwritev(dataplane->blk, ioreq->start, &ioreq->v, 0, - qemu_aio_complete, ioreq); + request->aio_inflight++; + blk_aio_pwritev(dataplane->blk, request->start, &request->v, 0, + qemu_aio_complete, request); break; case BLKIF_OP_DISCARD: { - struct blkif_request_discard *req = (void *)&ioreq->req; - if (!blk_split_discard(ioreq, req->sector_number, req->nr_sectors)) { + struct blkif_request_discard *req = (void *)&request->req; + if (!blk_split_discard(request, req->sector_number, req->nr_sectors)) { goto err; } break; @@ -405,19 +407,19 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq) goto err; } - qemu_aio_complete(ioreq, 0); + qemu_aio_complete(request, 0); return 0; err: - ioreq_finish(ioreq); - ioreq->status = BLKIF_RSP_ERROR; + ioreq_finish(request); + request->status = BLKIF_RSP_ERROR; return -1; } -static int blk_send_response_one(struct ioreq *ioreq) +static int blk_send_response_one(XenBlockRequest *request) { - XenBlockDataPlane *dataplane = ioreq->dataplane; + XenBlockDataPlane *dataplane = request->dataplane; int send_notify = 0; int have_requests = 0; blkif_response_t *resp; @@ -443,9 +445,9 @@ static int blk_send_response_one(struct ioreq *ioreq) return 0; } - resp->id = ioreq->req.id; - resp->operation = ioreq->req.operation; - resp->status = ioreq->status; + resp->id = request->req.id; + resp->operation = request->req.operation; + resp->status = request->status; dataplane->rings.common.rsp_prod_pvt++; @@ -473,13 +475,13 @@ static int blk_send_response_one(struct ioreq *ioreq) /* walk finished list, send outstanding responses, free requests */ static void blk_send_response_all(XenBlockDataPlane *dataplane) { - struct ioreq *ioreq; + XenBlockRequest *request; int send_notify = 0; while (!QLIST_EMPTY(&dataplane->finished)) { - ioreq = QLIST_FIRST(&dataplane->finished); - send_notify += blk_send_response_one(ioreq); - ioreq_release(ioreq, true); + request = QLIST_FIRST(&dataplane->finished); + send_notify += blk_send_response_one(request); + ioreq_release(request, true); } if (send_notify) { Error *local_err = NULL; @@ -493,29 +495,29 @@ static void blk_send_response_all(XenBlockDataPlane *dataplane) } } -static int blk_get_request(XenBlockDataPlane *dataplane, struct ioreq *ioreq, - RING_IDX rc) +static int blk_get_request(XenBlockDataPlane *dataplane, + XenBlockRequest *request, RING_IDX rc) { switch (dataplane->protocol) { case BLKIF_PROTOCOL_NATIVE: { blkif_request_t *req = RING_GET_REQUEST(&dataplane->rings.native, rc); - memcpy(&ioreq->req, req, sizeof(ioreq->req)); + memcpy(&request->req, req, sizeof(request->req)); break; } case BLKIF_PROTOCOL_X86_32: { blkif_x86_32_request_t *req = RING_GET_REQUEST(&dataplane->rings.x86_32_part, rc); - blkif_get_x86_32_req(&ioreq->req, req); + blkif_get_x86_32_req(&request->req, req); break; } case BLKIF_PROTOCOL_X86_64: { blkif_x86_64_request_t *req = RING_GET_REQUEST(&dataplane->rings.x86_64_part, rc); - blkif_get_x86_64_req(&ioreq->req, req); + blkif_get_x86_64_req(&request->req, req); break; } } @@ -527,7 +529,7 @@ static int blk_get_request(XenBlockDataPlane *dataplane, struct ioreq *ioreq, static void blk_handle_requests(XenBlockDataPlane *dataplane) { RING_IDX rc, rp; - struct ioreq *ioreq; + XenBlockRequest *request; dataplane->more_work = 0; @@ -541,18 +543,18 @@ static void blk_handle_requests(XenBlockDataPlane *dataplane) if (RING_REQUEST_CONS_OVERFLOW(&dataplane->rings.common, rc)) { break; } - ioreq = ioreq_start(dataplane); - if (ioreq == NULL) { + request = ioreq_start(dataplane); + if (request == NULL) { dataplane->more_work++; break; } - blk_get_request(dataplane, ioreq, rc); + blk_get_request(dataplane, request, rc); dataplane->rings.common.req_cons = ++rc; /* parse them */ - if (ioreq_parse(ioreq) != 0) { + if (ioreq_parse(request) != 0) { - switch (ioreq->req.operation) { + switch (request->req.operation) { case BLKIF_OP_READ: block_acct_invalid(blk_get_stats(dataplane->blk), BLOCK_ACCT_READ); @@ -568,7 +570,7 @@ static void blk_handle_requests(XenBlockDataPlane *dataplane) break; }; - if (blk_send_response_one(ioreq)) { + if (blk_send_response_one(request)) { Error *local_err = NULL; xen_device_notify_event_channel(dataplane->xendev, @@ -578,11 +580,11 @@ static void blk_handle_requests(XenBlockDataPlane *dataplane) error_report_err(local_err); } } - ioreq_release(ioreq, false); + ioreq_release(request, false); continue; } - ioreq_runio_qemu_aio(ioreq); + ioreq_runio_qemu_aio(request); } if (dataplane->more_work && @@ -636,17 +638,17 @@ XenBlockDataPlane *xen_block_dataplane_create(XenDevice *xendev, void xen_block_dataplane_destroy(XenBlockDataPlane *dataplane) { - struct ioreq *ioreq; + XenBlockRequest *request; if (!dataplane) { return; } while (!QLIST_EMPTY(&dataplane->freelist)) { - ioreq = QLIST_FIRST(&dataplane->freelist); - QLIST_REMOVE(ioreq, list); - qemu_iovec_destroy(&ioreq->v); - g_free(ioreq); + request = QLIST_FIRST(&dataplane->freelist); + QLIST_REMOVE(request, list); + qemu_iovec_destroy(&request->v); + g_free(request); } qemu_bh_delete(dataplane->bh); From patchwork Mon Jan 14 13:51:44 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anthony PERARD X-Patchwork-Id: 10762685 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 213296C2 for ; Mon, 14 Jan 2019 14:04:26 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0E78628911 for ; Mon, 14 Jan 2019 14:04:26 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0259D28BEE; Mon, 14 Jan 2019 14:04:25 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 3753C28911 for ; Mon, 14 Jan 2019 14:04:25 +0000 (UTC) Received: from localhost ([127.0.0.1]:33756 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gj2ql-0002eI-To for patchwork-qemu-devel@patchwork.kernel.org; Mon, 14 Jan 2019 09:04:24 -0500 Received: from eggs.gnu.org ([209.51.188.92]:47353) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gj2ll-0007Ab-GI for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:59:15 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gj2lj-0004tI-S0 for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:59:13 -0500 Received: from smtp03.citrix.com ([162.221.156.55]:1392) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gj2lh-0004s2-QB for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:59:11 -0500 X-IronPort-AV: E=Sophos;i="5.56,477,1539648000"; d="scan'208";a="75507026" From: Anthony PERARD To: Date: Mon, 14 Jan 2019 13:51:44 +0000 Message-ID: <20190114135154.16826-16-anthony.perard@citrix.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190114135154.16826-1-anthony.perard@citrix.com> References: <20190114135154.16826-1-anthony.perard@citrix.com> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 162.221.156.55 Subject: [Qemu-devel] [PULL 15/25] xen: purge 'blk' and 'ioreq' from function names in dataplane/xen-block.c X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Anthony PERARD , xen-devel@lists.xenproject.org, Peter Maydell Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Paul Durrant This is a purely cosmetic patch that purges remaining use of 'blk' and 'ioreq' in local function names, and then makes sure all functions are prefixed with 'xen_block_'. No functional change. Signed-off-by: Paul Durrant Acked-by: Anthony Perard Signed-off-by: Anthony PERARD --- hw/block/dataplane/xen-block.c | 90 +++++++++++++++++----------------- 1 file changed, 46 insertions(+), 44 deletions(-) diff --git a/hw/block/dataplane/xen-block.c b/hw/block/dataplane/xen-block.c index 6788bbf338..8e3965e171 100644 --- a/hw/block/dataplane/xen-block.c +++ b/hw/block/dataplane/xen-block.c @@ -67,7 +67,7 @@ struct XenBlockDataPlane { AioContext *ctx; }; -static void ioreq_reset(XenBlockRequest *request) +static void reset_request(XenBlockRequest *request) { memset(&request->req, 0, sizeof(request->req)); request->status = 0; @@ -86,7 +86,7 @@ static void ioreq_reset(XenBlockRequest *request) qemu_iovec_reset(&request->v); } -static XenBlockRequest *ioreq_start(XenBlockDataPlane *dataplane) +static XenBlockRequest *xen_block_start_request(XenBlockDataPlane *dataplane) { XenBlockRequest *request = NULL; @@ -111,7 +111,7 @@ static XenBlockRequest *ioreq_start(XenBlockDataPlane *dataplane) return request; } -static void ioreq_finish(XenBlockRequest *request) +static void xen_block_finish_request(XenBlockRequest *request) { XenBlockDataPlane *dataplane = request->dataplane; @@ -121,12 +121,12 @@ static void ioreq_finish(XenBlockRequest *request) dataplane->requests_finished++; } -static void ioreq_release(XenBlockRequest *request, bool finish) +static void xen_block_release_request(XenBlockRequest *request, bool finish) { XenBlockDataPlane *dataplane = request->dataplane; QLIST_REMOVE(request, list); - ioreq_reset(request); + reset_request(request); request->dataplane = dataplane; QLIST_INSERT_HEAD(&dataplane->freelist, request, list); if (finish) { @@ -140,7 +140,7 @@ static void ioreq_release(XenBlockRequest *request, bool finish) * translate request into iovec + start offset * do sanity checks along the way */ -static int ioreq_parse(XenBlockRequest *request) +static int xen_block_parse_request(XenBlockRequest *request) { XenBlockDataPlane *dataplane = request->dataplane; size_t len; @@ -201,7 +201,7 @@ static int ioreq_parse(XenBlockRequest *request) return -1; } -static int ioreq_grant_copy(XenBlockRequest *request) +static int xen_block_copy_request(XenBlockRequest *request) { XenBlockDataPlane *dataplane = request->dataplane; XenDevice *xendev = dataplane->xendev; @@ -247,9 +247,9 @@ static int ioreq_grant_copy(XenBlockRequest *request) return 0; } -static int ioreq_runio_qemu_aio(XenBlockRequest *request); +static int xen_block_do_aio(XenBlockRequest *request); -static void qemu_aio_complete(void *opaque, int ret) +static void xen_block_complete_aio(void *opaque, int ret) { XenBlockRequest *request = opaque; XenBlockDataPlane *dataplane = request->dataplane; @@ -266,7 +266,7 @@ static void qemu_aio_complete(void *opaque, int ret) request->aio_inflight--; if (request->presync) { request->presync = 0; - ioreq_runio_qemu_aio(request); + xen_block_do_aio(request); goto done; } if (request->aio_inflight > 0) { @@ -277,7 +277,7 @@ static void qemu_aio_complete(void *opaque, int ret) case BLKIF_OP_READ: /* in case of failure request->aio_errors is increased */ if (ret == 0) { - ioreq_grant_copy(request); + xen_block_copy_request(request); } qemu_vfree(request->buf); break; @@ -293,7 +293,7 @@ static void qemu_aio_complete(void *opaque, int ret) } request->status = request->aio_errors ? BLKIF_RSP_ERROR : BLKIF_RSP_OKAY; - ioreq_finish(request); + xen_block_finish_request(request); switch (request->req.operation) { case BLKIF_OP_WRITE: @@ -318,9 +318,9 @@ static void qemu_aio_complete(void *opaque, int ret) aio_context_release(dataplane->ctx); } -static bool blk_split_discard(XenBlockRequest *request, - blkif_sector_t sector_number, - uint64_t nr_sectors) +static bool xen_block_split_discard(XenBlockRequest *request, + blkif_sector_t sector_number, + uint64_t nr_sectors) { XenBlockDataPlane *dataplane = request->dataplane; int64_t byte_offset; @@ -343,7 +343,7 @@ static bool blk_split_discard(XenBlockRequest *request, byte_chunk = byte_remaining > limit ? limit : byte_remaining; request->aio_inflight++; blk_aio_pdiscard(dataplane->blk, byte_offset, byte_chunk, - qemu_aio_complete, request); + xen_block_complete_aio, request); byte_remaining -= byte_chunk; byte_offset += byte_chunk; } while (byte_remaining > 0); @@ -351,7 +351,7 @@ static bool blk_split_discard(XenBlockRequest *request, return true; } -static int ioreq_runio_qemu_aio(XenBlockRequest *request) +static int xen_block_do_aio(XenBlockRequest *request) { XenBlockDataPlane *dataplane = request->dataplane; @@ -359,14 +359,15 @@ static int ioreq_runio_qemu_aio(XenBlockRequest *request) if (request->req.nr_segments && (request->req.operation == BLKIF_OP_WRITE || request->req.operation == BLKIF_OP_FLUSH_DISKCACHE) && - ioreq_grant_copy(request)) { + xen_block_copy_request(request)) { qemu_vfree(request->buf); goto err; } request->aio_inflight++; if (request->presync) { - blk_aio_flush(request->dataplane->blk, qemu_aio_complete, request); + blk_aio_flush(request->dataplane->blk, xen_block_complete_aio, + request); return 0; } @@ -377,7 +378,7 @@ static int ioreq_runio_qemu_aio(XenBlockRequest *request) request->v.size, BLOCK_ACCT_READ); request->aio_inflight++; blk_aio_preadv(dataplane->blk, request->start, &request->v, 0, - qemu_aio_complete, request); + xen_block_complete_aio, request); break; case BLKIF_OP_WRITE: case BLKIF_OP_FLUSH_DISKCACHE: @@ -392,12 +393,13 @@ static int ioreq_runio_qemu_aio(XenBlockRequest *request) BLOCK_ACCT_WRITE : BLOCK_ACCT_FLUSH); request->aio_inflight++; blk_aio_pwritev(dataplane->blk, request->start, &request->v, 0, - qemu_aio_complete, request); + xen_block_complete_aio, request); break; case BLKIF_OP_DISCARD: { struct blkif_request_discard *req = (void *)&request->req; - if (!blk_split_discard(request, req->sector_number, req->nr_sectors)) { + if (!xen_block_split_discard(request, req->sector_number, + req->nr_sectors)) { goto err; } break; @@ -407,17 +409,17 @@ static int ioreq_runio_qemu_aio(XenBlockRequest *request) goto err; } - qemu_aio_complete(request, 0); + xen_block_complete_aio(request, 0); return 0; err: - ioreq_finish(request); + xen_block_finish_request(request); request->status = BLKIF_RSP_ERROR; return -1; } -static int blk_send_response_one(XenBlockRequest *request) +static int xen_block_send_response_one(XenBlockRequest *request) { XenBlockDataPlane *dataplane = request->dataplane; int send_notify = 0; @@ -473,15 +475,15 @@ static int blk_send_response_one(XenBlockRequest *request) } /* walk finished list, send outstanding responses, free requests */ -static void blk_send_response_all(XenBlockDataPlane *dataplane) +static void xen_block_send_response_all(XenBlockDataPlane *dataplane) { XenBlockRequest *request; int send_notify = 0; while (!QLIST_EMPTY(&dataplane->finished)) { request = QLIST_FIRST(&dataplane->finished); - send_notify += blk_send_response_one(request); - ioreq_release(request, true); + send_notify += xen_block_send_response_one(request); + xen_block_release_request(request, true); } if (send_notify) { Error *local_err = NULL; @@ -495,8 +497,8 @@ static void blk_send_response_all(XenBlockDataPlane *dataplane) } } -static int blk_get_request(XenBlockDataPlane *dataplane, - XenBlockRequest *request, RING_IDX rc) +static int xen_block_get_request(XenBlockDataPlane *dataplane, + XenBlockRequest *request, RING_IDX rc) { switch (dataplane->protocol) { case BLKIF_PROTOCOL_NATIVE: { @@ -526,7 +528,7 @@ static int blk_get_request(XenBlockDataPlane *dataplane, return 0; } -static void blk_handle_requests(XenBlockDataPlane *dataplane) +static void xen_block_handle_requests(XenBlockDataPlane *dataplane) { RING_IDX rc, rp; XenBlockRequest *request; @@ -537,23 +539,22 @@ static void blk_handle_requests(XenBlockDataPlane *dataplane) rp = dataplane->rings.common.sring->req_prod; xen_rmb(); /* Ensure we see queued requests up to 'rp'. */ - blk_send_response_all(dataplane); + xen_block_send_response_all(dataplane); while (rc != rp) { /* pull request from ring */ if (RING_REQUEST_CONS_OVERFLOW(&dataplane->rings.common, rc)) { break; } - request = ioreq_start(dataplane); + request = xen_block_start_request(dataplane); if (request == NULL) { dataplane->more_work++; break; } - blk_get_request(dataplane, request, rc); + xen_block_get_request(dataplane, request, rc); dataplane->rings.common.req_cons = ++rc; /* parse them */ - if (ioreq_parse(request) != 0) { - + if (xen_block_parse_request(request) != 0) { switch (request->req.operation) { case BLKIF_OP_READ: block_acct_invalid(blk_get_stats(dataplane->blk), @@ -570,7 +571,7 @@ static void blk_handle_requests(XenBlockDataPlane *dataplane) break; }; - if (blk_send_response_one(request)) { + if (xen_block_send_response_one(request)) { Error *local_err = NULL; xen_device_notify_event_channel(dataplane->xendev, @@ -580,11 +581,11 @@ static void blk_handle_requests(XenBlockDataPlane *dataplane) error_report_err(local_err); } } - ioreq_release(request, false); + xen_block_release_request(request, false); continue; } - ioreq_runio_qemu_aio(request); + xen_block_do_aio(request); } if (dataplane->more_work && @@ -593,16 +594,16 @@ static void blk_handle_requests(XenBlockDataPlane *dataplane) } } -static void blk_bh(void *opaque) +static void xen_block_dataplane_bh(void *opaque) { XenBlockDataPlane *dataplane = opaque; aio_context_acquire(dataplane->ctx); - blk_handle_requests(dataplane); + xen_block_handle_requests(dataplane); aio_context_release(dataplane->ctx); } -static void blk_event(void *opaque) +static void xen_block_dataplane_event(void *opaque) { XenBlockDataPlane *dataplane = opaque; @@ -631,7 +632,8 @@ XenBlockDataPlane *xen_block_dataplane_create(XenDevice *xendev, } else { dataplane->ctx = qemu_get_aio_context(); } - dataplane->bh = aio_bh_new(dataplane->ctx, blk_bh, dataplane); + dataplane->bh = aio_bh_new(dataplane->ctx, xen_block_dataplane_bh, + dataplane); return dataplane; } @@ -789,7 +791,7 @@ void xen_block_dataplane_start(XenBlockDataPlane *dataplane, dataplane->event_channel = xen_device_bind_event_channel(xendev, event_channel, - blk_event, dataplane, + xen_block_dataplane_event, dataplane, &local_err); if (local_err) { error_propagate(errp, local_err); From patchwork Mon Jan 14 13:51:45 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anthony PERARD X-Patchwork-Id: 10762717 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 50E346C2 for ; Mon, 14 Jan 2019 14:11:33 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3E85228D07 for ; Mon, 14 Jan 2019 14:11:33 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 32B3528D19; Mon, 14 Jan 2019 14:11:33 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id E291128D07 for ; Mon, 14 Jan 2019 14:11:31 +0000 (UTC) Received: from localhost ([127.0.0.1]:35354 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gj2xf-0007yx-2F for patchwork-qemu-devel@patchwork.kernel.org; Mon, 14 Jan 2019 09:11:31 -0500 Received: from eggs.gnu.org ([209.51.188.92]:47217) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gj2lM-0006mi-T1 for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:58:51 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gj2lK-0004hB-5c for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:58:48 -0500 Received: from smtp03.citrix.com ([162.221.156.55]:1352) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gj2lJ-0004gB-PX for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:58:46 -0500 X-IronPort-AV: E=Sophos;i="5.56,477,1539648000"; d="scan'208";a="75506982" From: Anthony PERARD To: Date: Mon, 14 Jan 2019 13:51:45 +0000 Message-ID: <20190114135154.16826-17-anthony.perard@citrix.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190114135154.16826-1-anthony.perard@citrix.com> References: <20190114135154.16826-1-anthony.perard@citrix.com> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 162.221.156.55 Subject: [Qemu-devel] [PULL 16/25] xen: add implementations of xen-block connect and disconnect functions... X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Anthony PERARD , xen-devel@lists.xenproject.org, Peter Maydell Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Paul Durrant ...and wire in the dataplane. This patch adds the remaining code to make the xen-block XenDevice functional. The parameters that a block frontend expects to find are populated in the backend xenstore area, and the 'ring-ref' and 'event-channel' values specified in the frontend xenstore area are mapped/bound and used to set up the dataplane. Signed-off-by: Paul Durrant Reviewed-by: Anthony Perard Signed-off-by: Anthony PERARD --- hw/block/xen-block.c | 166 ++++++++++++++++++++++++++++++++ hw/xen/trace-events | 3 + hw/xen/xen-bus.c | 187 ++++++++++++++++++++++++++++++++----- include/hw/xen/xen-block.h | 9 ++ include/hw/xen/xen-bus.h | 14 ++- 5 files changed, 353 insertions(+), 26 deletions(-) diff --git a/hw/block/xen-block.c b/hw/block/xen-block.c index 3a963b0383..a7c37c185a 100644 --- a/hw/block/xen-block.c +++ b/hw/block/xen-block.c @@ -10,7 +10,13 @@ #include "qapi/error.h" #include "qapi/visitor.h" #include "hw/hw.h" +#include "hw/xen/xen_common.h" +#include "hw/block/xen_blkif.h" #include "hw/xen/xen-block.h" +#include "sysemu/blockdev.h" +#include "sysemu/block-backend.h" +#include "sysemu/iothread.h" +#include "dataplane/xen-block.h" #include "trace.h" static char *xen_block_get_name(XenDevice *xendev, Error **errp) @@ -28,6 +34,8 @@ static void xen_block_disconnect(XenDevice *xendev, Error **errp) XenBlockVdev *vdev = &blockdev->props.vdev; trace_xen_block_disconnect(type, vdev->disk, vdev->partition); + + xen_block_dataplane_stop(blockdev->dataplane); } static void xen_block_connect(XenDevice *xendev, Error **errp) @@ -35,8 +43,72 @@ static void xen_block_connect(XenDevice *xendev, Error **errp) XenBlockDevice *blockdev = XEN_BLOCK_DEVICE(xendev); const char *type = object_get_typename(OBJECT(blockdev)); XenBlockVdev *vdev = &blockdev->props.vdev; + unsigned int order, nr_ring_ref, *ring_ref, event_channel, protocol; + char *str; trace_xen_block_connect(type, vdev->disk, vdev->partition); + + if (xen_device_frontend_scanf(xendev, "ring-page-order", "%u", + &order) != 1) { + nr_ring_ref = 1; + ring_ref = g_new(unsigned int, nr_ring_ref); + + if (xen_device_frontend_scanf(xendev, "ring-ref", "%u", + &ring_ref[0]) != 1) { + error_setg(errp, "failed to read ring-ref"); + g_free(ring_ref); + return; + } + } else if (order <= blockdev->props.max_ring_page_order) { + unsigned int i; + + nr_ring_ref = 1 << order; + ring_ref = g_new(unsigned int, nr_ring_ref); + + for (i = 0; i < nr_ring_ref; i++) { + const char *key = g_strdup_printf("ring-ref%u", i); + + if (xen_device_frontend_scanf(xendev, key, "%u", + &ring_ref[i]) != 1) { + error_setg(errp, "failed to read %s", key); + g_free((gpointer)key); + g_free(ring_ref); + return; + } + + g_free((gpointer)key); + } + } else { + error_setg(errp, "invalid ring-page-order (%d)", order); + return; + } + + if (xen_device_frontend_scanf(xendev, "event-channel", "%u", + &event_channel) != 1) { + error_setg(errp, "failed to read event-channel"); + g_free(ring_ref); + return; + } + + if (xen_device_frontend_scanf(xendev, "protocol", "%ms", + &str) != 1) { + protocol = BLKIF_PROTOCOL_NATIVE; + } else { + if (strcmp(str, XEN_IO_PROTO_ABI_X86_32) == 0) { + protocol = BLKIF_PROTOCOL_X86_32; + } else if (strcmp(str, XEN_IO_PROTO_ABI_X86_64) == 0) { + protocol = BLKIF_PROTOCOL_X86_64; + } else { + protocol = BLKIF_PROTOCOL_NATIVE; + } + + free(str); + } + + xen_block_dataplane_start(blockdev->dataplane, ring_ref, nr_ring_ref, + event_channel, protocol, errp); + + g_free(ring_ref); } static void xen_block_unrealize(XenDevice *xendev, Error **errp) @@ -56,6 +128,9 @@ static void xen_block_unrealize(XenDevice *xendev, Error **errp) /* Disconnect from the frontend in case this has not already happened */ xen_block_disconnect(xendev, NULL); + xen_block_dataplane_destroy(blockdev->dataplane); + blockdev->dataplane = NULL; + if (blockdev_class->unrealize) { blockdev_class->unrealize(blockdev, errp); } @@ -68,6 +143,7 @@ static void xen_block_realize(XenDevice *xendev, Error **errp) XEN_BLOCK_DEVICE_GET_CLASS(xendev); const char *type = object_get_typename(OBJECT(blockdev)); XenBlockVdev *vdev = &blockdev->props.vdev; + BlockConf *conf = &blockdev->props.conf; Error *local_err = NULL; if (vdev->type == XEN_BLOCK_VDEV_TYPE_INVALID) { @@ -81,8 +157,62 @@ static void xen_block_realize(XenDevice *xendev, Error **errp) blockdev_class->realize(blockdev, &local_err); if (local_err) { error_propagate(errp, local_err); + return; } } + + /* + * The blkif protocol does not deal with removable media, so it must + * always be present, even for CDRom devices. + */ + assert(conf->blk); + if (!blk_is_inserted(conf->blk)) { + error_setg(errp, "device needs media, but drive is empty"); + return; + } + + if (!blkconf_apply_backend_options(conf, blockdev->info & VDISK_READONLY, + false, errp)) { + return; + } + + if (!(blockdev->info & VDISK_CDROM) && + !blkconf_geometry(conf, NULL, 65535, 255, 255, errp)) { + return; + } + + blkconf_blocksizes(conf); + + if (conf->logical_block_size > conf->physical_block_size) { + error_setg( + errp, "logical_block_size > physical_block_size not supported"); + return; + } + + blk_set_guest_block_size(conf->blk, conf->logical_block_size); + + if (conf->discard_granularity > 0) { + xen_device_backend_printf(xendev, "feature-discard", "%u", 1); + } + + xen_device_backend_printf(xendev, "feature-flush-cache", "%u", 1); + xen_device_backend_printf(xendev, "max-ring-page-order", "%u", + blockdev->props.max_ring_page_order); + xen_device_backend_printf(xendev, "info", "%u", blockdev->info); + + xen_device_frontend_printf(xendev, "virtual-device", "%lu", + vdev->number); + xen_device_frontend_printf(xendev, "device-type", "%s", + blockdev->device_type); + + xen_device_backend_printf(xendev, "sector-size", "%u", + conf->logical_block_size); + xen_device_backend_printf(xendev, "sectors", "%lu", + blk_getlength(conf->blk) / + conf->logical_block_size); + + blockdev->dataplane = + xen_block_dataplane_create(xendev, conf, blockdev->props.iothread); } static void xen_block_frontend_changed(XenDevice *xendev, @@ -331,6 +461,11 @@ const PropertyInfo xen_block_prop_vdev = { static Property xen_block_props[] = { DEFINE_PROP("vdev", XenBlockDevice, props.vdev, xen_block_prop_vdev, XenBlockVdev), + DEFINE_BLOCK_PROPERTIES(XenBlockDevice, props.conf), + DEFINE_PROP_UINT32("max-ring-page-order", XenBlockDevice, + props.max_ring_page_order, 4), + DEFINE_PROP_LINK("iothread", XenBlockDevice, props.iothread, + TYPE_IOTHREAD, IOThread *), DEFINE_PROP_END_OF_LIST() }; @@ -339,6 +474,7 @@ static void xen_block_class_init(ObjectClass *class, void *data) DeviceClass *dev_class = DEVICE_CLASS(class); XenDeviceClass *xendev_class = XEN_DEVICE_CLASS(class); + xendev_class->device = "vbd"; xendev_class->get_name = xen_block_get_name; xendev_class->realize = xen_block_realize; xendev_class->frontend_changed = xen_block_frontend_changed; @@ -363,7 +499,18 @@ static void xen_disk_unrealize(XenBlockDevice *blockdev, Error **errp) static void xen_disk_realize(XenBlockDevice *blockdev, Error **errp) { + BlockConf *conf = &blockdev->props.conf; + trace_xen_disk_realize(); + + blockdev->device_type = "disk"; + + if (!conf->blk) { + error_setg(errp, "drive property not set"); + return; + } + + blockdev->info = blk_is_read_only(conf->blk) ? VDISK_READONLY : 0; } static void xen_disk_class_init(ObjectClass *class, void *data) @@ -391,7 +538,26 @@ static void xen_cdrom_unrealize(XenBlockDevice *blockdev, Error **errp) static void xen_cdrom_realize(XenBlockDevice *blockdev, Error **errp) { + BlockConf *conf = &blockdev->props.conf; + trace_xen_cdrom_realize(); + + blockdev->device_type = "cdrom"; + + if (!conf->blk) { + int rc; + + /* Set up an empty drive */ + conf->blk = blk_new(0, BLK_PERM_ALL); + + rc = blk_attach_dev(conf->blk, DEVICE(blockdev)); + if (!rc) { + error_setg_errno(errp, -rc, "failed to create drive"); + return; + } + } + + blockdev->info = VDISK_READONLY | VDISK_CDROM; } static void xen_cdrom_class_init(ObjectClass *class, void *data) diff --git a/hw/xen/trace-events b/hw/xen/trace-events index 22055b5894..d4651bdb30 100644 --- a/hw/xen/trace-events +++ b/hw/xen/trace-events @@ -22,8 +22,11 @@ xen_bus_watch(const char *token) "token: %s" xen_device_realize(const char *type, char *name) "type: %s name: %s" xen_device_unrealize(const char *type, char *name) "type: %s name: %s" xen_device_backend_state(const char *type, char *name, const char *state) "type: %s name: %s -> %s" +xen_device_backend_online(const char *type, char *name, bool online) "type: %s name: %s -> %u" +xen_device_backend_changed(const char *type, char *name) "type: %s name: %s" xen_device_frontend_state(const char *type, char *name, const char *state) "type: %s name: %s -> %s" xen_device_frontend_changed(const char *type, char *name) "type: %s name: %s" +xen_device_unplug(const char *type, char *name) "type: %s name: %s" # include/hw/xen/xen-bus-helper.c xs_node_create(const char *node) "%s" diff --git a/hw/xen/xen-bus.c b/hw/xen/xen-bus.c index 14881126ff..6861ce136e 100644 --- a/hw/xen/xen-bus.c +++ b/hw/xen/xen-bus.c @@ -48,6 +48,54 @@ static char *xen_device_get_frontend_path(XenDevice *xendev) xendev->frontend_id, device, xendev->name); } +static void xen_device_unplug(XenDevice *xendev, Error **errp) +{ + XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev))); + const char *type = object_get_typename(OBJECT(xendev)); + Error *local_err = NULL; + xs_transaction_t tid; + + trace_xen_device_unplug(type, xendev->name); + + /* Mimic the way the Xen toolstack does an unplug */ +again: + tid = xs_transaction_start(xenbus->xsh); + if (tid == XBT_NULL) { + error_setg_errno(errp, errno, "failed xs_transaction_start"); + return; + } + + xs_node_printf(xenbus->xsh, tid, xendev->backend_path, "online", + &local_err, "%u", 0); + if (local_err) { + goto abort; + } + + xs_node_printf(xenbus->xsh, tid, xendev->backend_path, "state", + &local_err, "%u", XenbusStateClosing); + if (local_err) { + goto abort; + } + + if (!xs_transaction_end(xenbus->xsh, tid, false)) { + if (errno == EAGAIN) { + goto again; + } + + error_setg_errno(errp, errno, "failed xs_transaction_end"); + } + + return; + +abort: + /* + * We only abort if there is already a failure so ignore any error + * from ending the transaction. + */ + xs_transaction_end(xenbus->xsh, tid, true); + error_propagate(errp, local_err); +} + static void xen_bus_print_dev(Monitor *mon, DeviceState *dev, int indent) { XenDevice *xendev = XEN_DEVICE(dev); @@ -208,14 +256,26 @@ static void xen_bus_realize(BusState *bus, Error **errp) xen_bus_unrealize(bus, &error_abort); } +static void xen_bus_unplug_request(HotplugHandler *hotplug, + DeviceState *dev, + Error **errp) +{ + XenDevice *xendev = XEN_DEVICE(dev); + + xen_device_unplug(xendev, errp); +} + static void xen_bus_class_init(ObjectClass *class, void *data) { BusClass *bus_class = BUS_CLASS(class); + HotplugHandlerClass *hotplug_class = HOTPLUG_HANDLER_CLASS(class); bus_class->print_dev = xen_bus_print_dev; bus_class->get_dev_path = xen_bus_get_dev_path; bus_class->realize = xen_bus_realize; bus_class->unrealize = xen_bus_unrealize; + + hotplug_class->unplug_request = xen_bus_unplug_request; } static const TypeInfo xen_bus_type_info = { @@ -230,8 +290,8 @@ static const TypeInfo xen_bus_type_info = { }, }; -static void xen_device_backend_printf(XenDevice *xendev, const char *key, - const char *fmt, ...) +void xen_device_backend_printf(XenDevice *xendev, const char *key, + const char *fmt, ...) { XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev))); Error *local_err = NULL; @@ -287,6 +347,70 @@ enum xenbus_state xen_device_backend_get_state(XenDevice *xendev) return xendev->backend_state; } +static void xen_device_backend_set_online(XenDevice *xendev, bool online) +{ + const char *type = object_get_typename(OBJECT(xendev)); + + if (xendev->backend_online == online) { + return; + } + + trace_xen_device_backend_online(type, xendev->name, online); + + xendev->backend_online = online; + xen_device_backend_printf(xendev, "online", "%u", online); +} + +static void xen_device_backend_changed(void *opaque) +{ + XenDevice *xendev = opaque; + const char *type = object_get_typename(OBJECT(xendev)); + enum xenbus_state state; + unsigned int online; + + trace_xen_device_backend_changed(type, xendev->name); + + if (xen_device_backend_scanf(xendev, "state", "%u", &state) != 1) { + state = XenbusStateUnknown; + } + + xen_device_backend_set_state(xendev, state); + + if (xen_device_backend_scanf(xendev, "online", "%u", &online) != 1) { + online = 0; + } + + xen_device_backend_set_online(xendev, !!online); + + /* + * If the toolstack (or unplug request callback) has set the backend + * state to Closing, but there is no active frontend (i.e. the + * state is not Connected) then set the backend state to Closed. + */ + if (xendev->backend_state == XenbusStateClosing && + xendev->frontend_state != XenbusStateConnected) { + xen_device_backend_set_state(xendev, XenbusStateClosed); + } + + /* + * If a backend is still 'online' then its state should be cycled + * back round to InitWait in order for a new frontend instance to + * connect. This may happen when, for example, a frontend driver is + * re-installed or updated. + * If a backend is not 'online' then the device should be destroyed. + */ + if (xendev->backend_online && + xendev->backend_state == XenbusStateClosed) { + xen_device_backend_set_state(xendev, XenbusStateInitWait); + } else if (!xendev->backend_online && + (xendev->backend_state == XenbusStateClosed || + xendev->backend_state == XenbusStateInitialising || + xendev->backend_state == XenbusStateInitWait || + xendev->backend_state == XenbusStateUnknown)) { + object_unparent(OBJECT(xendev)); + } +} + static void xen_device_backend_create(XenDevice *xendev, Error **errp) { XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev))); @@ -307,6 +431,27 @@ static void xen_device_backend_create(XenDevice *xendev, Error **errp) if (local_err) { error_propagate_prepend(errp, local_err, "failed to create backend: "); + return; + } + + xendev->backend_state_watch = + xen_bus_add_watch(xenbus, xendev->backend_path, + "state", xen_device_backend_changed, + xendev, &local_err); + if (local_err) { + error_propagate_prepend(errp, local_err, + "failed to watch backend state: "); + return; + } + + xendev->backend_online_watch = + xen_bus_add_watch(xenbus, xendev->backend_path, + "online", xen_device_backend_changed, + xendev, &local_err); + if (local_err) { + error_propagate_prepend(errp, local_err, + "failed to watch backend online: "); + return; } } @@ -315,6 +460,16 @@ static void xen_device_backend_destroy(XenDevice *xendev) XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev))); Error *local_err = NULL; + if (xendev->backend_online_watch) { + xen_bus_remove_watch(xenbus, xendev->backend_online_watch, NULL); + xendev->backend_online_watch = NULL; + } + + if (xendev->backend_state_watch) { + xen_bus_remove_watch(xenbus, xendev->backend_state_watch, NULL); + xendev->backend_state_watch = NULL; + } + if (!xendev->backend_path) { return; } @@ -331,8 +486,8 @@ static void xen_device_backend_destroy(XenDevice *xendev) } } -static void xen_device_frontend_printf(XenDevice *xendev, const char *key, - const char *fmt, ...) +void xen_device_frontend_printf(XenDevice *xendev, const char *key, + const char *fmt, ...) { XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev))); Error *local_err = NULL; @@ -350,8 +505,8 @@ static void xen_device_frontend_printf(XenDevice *xendev, const char *key, } } -static int xen_device_frontend_scanf(XenDevice *xendev, const char *key, - const char *fmt, ...) +int xen_device_frontend_scanf(XenDevice *xendev, const char *key, + const char *fmt, ...) { XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev))); va_list ap; @@ -407,24 +562,6 @@ static void xen_device_frontend_changed(void *opaque) error_reportf_err(local_err, "frontend change error: "); } } - - /* - * If a backend is still 'online' then its state should be cycled - * back round to InitWait in order for a new frontend instance to - * connect. This may happen when, for example, a frontend driver is - * re-installed or updated. - */ - if (xendev->backend_state == XenbusStateClosed) { - unsigned int online; - - if (xen_device_backend_scanf(xendev, "online", "%u", &online) != 1) { - online = 0; - } - - if (online) { - xen_device_backend_set_state(xendev, XenbusStateInitWait); - } - } } static void xen_device_frontend_create(XenDevice *xendev, Error **errp) @@ -824,9 +961,9 @@ static void xen_device_realize(DeviceState *dev, Error **errp) xendev->frontend_path); xen_device_backend_printf(xendev, "frontend-id", "%u", xendev->frontend_id); - xen_device_backend_printf(xendev, "online", "%u", 1); xen_device_backend_printf(xendev, "hotplug-status", "connected"); + xen_device_backend_set_online(xendev, true); xen_device_backend_set_state(xendev, XenbusStateInitWait); xen_device_frontend_printf(xendev, "backend", "%s", diff --git a/include/hw/xen/xen-block.h b/include/hw/xen/xen-block.h index 29413256e9..c4223f9be1 100644 --- a/include/hw/xen/xen-block.h +++ b/include/hw/xen/xen-block.h @@ -9,6 +9,9 @@ #define HW_XEN_BLOCK_H #include "hw/xen/xen-bus.h" +#include "hw/block/block.h" +#include "hw/block/dataplane/xen-block.h" +#include "sysemu/iothread.h" typedef enum XenBlockVdevType { XEN_BLOCK_VDEV_TYPE_INVALID, @@ -28,11 +31,17 @@ typedef struct XenBlockVdev { typedef struct XenBlockProperties { XenBlockVdev vdev; + BlockConf conf; + unsigned int max_ring_page_order; + IOThread *iothread; } XenBlockProperties; typedef struct XenBlockDevice { XenDevice xendev; XenBlockProperties props; + const char *device_type; + unsigned int info; + XenBlockDataPlane *dataplane; } XenBlockDevice; typedef void (*XenBlockDeviceRealize)(XenBlockDevice *blockdev, Error **errp); diff --git a/include/hw/xen/xen-bus.h b/include/hw/xen/xen-bus.h index b554559e5b..8f39f88d35 100644 --- a/include/hw/xen/xen-bus.h +++ b/include/hw/xen/xen-bus.h @@ -23,7 +23,9 @@ typedef struct XenDevice { char *backend_path, *frontend_path; enum xenbus_state backend_state, frontend_state; Notifier exit; - XenWatch *frontend_state_watch; + XenWatch *backend_state_watch, *frontend_state_watch; + bool backend_online; + XenWatch *backend_online_watch; xengnttab_handle *xgth; bool feature_grant_copy; xenevtchn_handle *xeh; @@ -83,6 +85,16 @@ void xen_device_backend_set_state(XenDevice *xendev, enum xenbus_state state); enum xenbus_state xen_device_backend_get_state(XenDevice *xendev); +void xen_device_backend_printf(XenDevice *xendev, const char *key, + const char *fmt, ...) + GCC_FMT_ATTR(3, 4); +void xen_device_frontend_printf(XenDevice *xendev, const char *key, + const char *fmt, ...) + GCC_FMT_ATTR(3, 4); + +int xen_device_frontend_scanf(XenDevice *xendev, const char *key, + const char *fmt, ...); + void xen_device_set_max_grant_refs(XenDevice *xendev, unsigned int nr_refs, Error **errp); void *xen_device_map_grant_refs(XenDevice *xendev, uint32_t *refs, From patchwork Mon Jan 14 13:51:46 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anthony PERARD X-Patchwork-Id: 10762831 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0D1C1139A for ; Mon, 14 Jan 2019 14:27:55 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E11FB28A99 for ; Mon, 14 Jan 2019 14:27:54 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D575028D29; Mon, 14 Jan 2019 14:27:54 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id C05BD28A99 for ; Mon, 14 Jan 2019 14:27:53 +0000 (UTC) Received: from localhost ([127.0.0.1]:39333 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gj3DU-00048m-Vy for patchwork-qemu-devel@patchwork.kernel.org; Mon, 14 Jan 2019 09:27:53 -0500 Received: from eggs.gnu.org ([209.51.188.92]:47308) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gj2lh-00076o-OS for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:59:11 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gj2le-0004rO-EF for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:59:09 -0500 Received: from smtp03.citrix.com ([162.221.156.55]:1370) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gj2lb-0004ll-Lo for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:59:05 -0500 X-IronPort-AV: E=Sophos;i="5.56,477,1539648000"; d="scan'208";a="75507011" From: Anthony PERARD To: Date: Mon, 14 Jan 2019 13:51:46 +0000 Message-ID: <20190114135154.16826-18-anthony.perard@citrix.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190114135154.16826-1-anthony.perard@citrix.com> References: <20190114135154.16826-1-anthony.perard@citrix.com> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 162.221.156.55 Subject: [Qemu-devel] [PULL 17/25] xen: add a mechanism to automatically create XenDevice-s... X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Anthony PERARD , xen-devel@lists.xenproject.org, Peter Maydell Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Paul Durrant ...that maintains compatibility with existing Xen toolstacks. Xen toolstacks instantiate PV backends by simply writing information into xenstore and expecting a backend implementation to be watching for this. This patch adds a new 'xen-backend' module to allow individual XenDevice implementations to register create and destroy functions. The creator will be called when a tool-stack instantiates a new backend in this way, and the destructor will then be called after the resulting XenDevice object is unrealized. To support this it is also necessary to add new watchers into the XenBus implementation to handle enumeration of new backends and also destruction of XenDevice-s when the toolstack sets the backend 'online' key to 0. NOTE: This patch only adds the framework. A subsequent patch will add a creator function for xen-block devices. Signed-off-by: Paul Durrant Reviewed-by: Anthony Perard Signed-off-by: Anthony PERARD --- hw/xen/Makefile.objs | 2 +- hw/xen/trace-events | 3 + hw/xen/xen-backend.c | 165 +++++++++++++++++++++++++++++++++++ hw/xen/xen-bus.c | 164 +++++++++++++++++++++++++++++++++- include/hw/xen/xen-backend.h | 39 +++++++++ include/hw/xen/xen-bus.h | 1 + include/qemu/module.h | 3 + 7 files changed, 375 insertions(+), 2 deletions(-) create mode 100644 hw/xen/xen-backend.c create mode 100644 include/hw/xen/xen-backend.h diff --git a/hw/xen/Makefile.objs b/hw/xen/Makefile.objs index 77c0868190..84df60a928 100644 --- a/hw/xen/Makefile.objs +++ b/hw/xen/Makefile.objs @@ -1,5 +1,5 @@ # xen backend driver support -common-obj-$(CONFIG_XEN) += xen-legacy-backend.o xen_devconfig.o xen_pvdev.o xen-common.o xen-bus.o xen-bus-helper.o +common-obj-$(CONFIG_XEN) += xen-legacy-backend.o xen_devconfig.o xen_pvdev.o xen-common.o xen-bus.o xen-bus-helper.o xen-backend.o obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen-host-pci-device.o obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen_pt.o xen_pt_config_init.o xen_pt_graphics.o xen_pt_msi.o diff --git a/hw/xen/trace-events b/hw/xen/trace-events index d4651bdb30..f6944624b2 100644 --- a/hw/xen/trace-events +++ b/hw/xen/trace-events @@ -16,6 +16,9 @@ xen_domid_restrict(int err) "err: %u" # include/hw/xen/xen-bus.c xen_bus_realize(void) "" xen_bus_unrealize(void) "" +xen_bus_enumerate(void) "" +xen_bus_type_enumerate(const char *type) "type: %s" +xen_bus_backend_create(const char *type, const char *path) "type: %s path: %s" xen_bus_add_watch(const char *node, const char *key, char *token) "node: %s key: %s token: %s" xen_bus_remove_watch(const char *node, const char *key, char *token) "node: %s key: %s token: %s" xen_bus_watch(const char *token) "token: %s" diff --git a/hw/xen/xen-backend.c b/hw/xen/xen-backend.c new file mode 100644 index 0000000000..da065f81b7 --- /dev/null +++ b/hw/xen/xen-backend.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2018 Citrix Systems Inc. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "qemu/error-report.h" +#include "qapi/error.h" +#include "hw/xen/xen-backend.h" +#include "hw/xen/xen-bus.h" + +typedef struct XenBackendImpl { + const char *type; + XenBackendDeviceCreate create; + XenBackendDeviceDestroy destroy; +} XenBackendImpl; + +struct XenBackendInstance { + QLIST_ENTRY(XenBackendInstance) entry; + const XenBackendImpl *impl; + XenBus *xenbus; + char *name; + XenDevice *xendev; +}; + +static GHashTable *xen_backend_table_get(void) +{ + static GHashTable *table; + + if (table == NULL) { + table = g_hash_table_new(g_str_hash, g_str_equal); + } + + return table; +} + +static void xen_backend_table_add(XenBackendImpl *impl) +{ + g_hash_table_insert(xen_backend_table_get(), (void *)impl->type, impl); +} + +static const XenBackendImpl *xen_backend_table_lookup(const char *type) +{ + return g_hash_table_lookup(xen_backend_table_get(), type); +} + +void xen_backend_register(const XenBackendInfo *info) +{ + XenBackendImpl *impl = g_new0(XenBackendImpl, 1); + + g_assert(info->type); + + if (xen_backend_table_lookup(info->type)) { + error_report("attempt to register duplicate Xen backend type '%s'", + info->type); + abort(); + } + + if (!info->create) { + error_report("backend type '%s' has no creator", info->type); + abort(); + } + + impl->type = info->type; + impl->create = info->create; + impl->destroy = info->destroy; + + xen_backend_table_add(impl); +} + +static QLIST_HEAD(, XenBackendInstance) backend_list; + +static void xen_backend_list_add(XenBackendInstance *backend) +{ + QLIST_INSERT_HEAD(&backend_list, backend, entry); +} + +static XenBackendInstance *xen_backend_list_find(XenDevice *xendev) +{ + XenBackendInstance *backend; + + QLIST_FOREACH(backend, &backend_list, entry) { + if (backend->xendev == xendev) { + return backend; + } + } + + return NULL; +} + +static void xen_backend_list_remove(XenBackendInstance *backend) +{ + QLIST_REMOVE(backend, entry); +} + +void xen_backend_device_create(XenBus *xenbus, const char *type, + const char *name, QDict *opts, Error **errp) +{ + const XenBackendImpl *impl = xen_backend_table_lookup(type); + XenBackendInstance *backend; + Error *local_error = NULL; + + if (!impl) { + return; + } + + backend = g_new0(XenBackendInstance, 1); + backend->xenbus = xenbus; + backend->name = g_strdup(name); + + impl->create(backend, opts, &local_error); + if (local_error) { + error_propagate(errp, local_error); + g_free(backend->name); + g_free(backend); + return; + } + + backend->impl = impl; + xen_backend_list_add(backend); +} + +XenBus *xen_backend_get_bus(XenBackendInstance *backend) +{ + return backend->xenbus; +} + +const char *xen_backend_get_name(XenBackendInstance *backend) +{ + return backend->name; +} + +void xen_backend_set_device(XenBackendInstance *backend, + XenDevice *xendev) +{ + g_assert(!backend->xendev); + backend->xendev = xendev; +} + +XenDevice *xen_backend_get_device(XenBackendInstance *backend) +{ + return backend->xendev; +} + + +bool xen_backend_try_device_destroy(XenDevice *xendev, Error **errp) +{ + XenBackendInstance *backend = xen_backend_list_find(xendev); + const XenBackendImpl *impl; + + if (!backend) { + return false; + } + + impl = backend->impl; + impl->destroy(backend, errp); + + xen_backend_list_remove(backend); + g_free(backend->name); + g_free(backend); + + return true; +} diff --git a/hw/xen/xen-bus.c b/hw/xen/xen-bus.c index 6861ce136e..3aeccec69c 100644 --- a/hw/xen/xen-bus.c +++ b/hw/xen/xen-bus.c @@ -11,10 +11,12 @@ #include "hw/hw.h" #include "hw/sysbus.h" #include "hw/xen/xen.h" +#include "hw/xen/xen-backend.h" #include "hw/xen/xen-bus.h" #include "hw/xen/xen-bus-helper.h" #include "monitor/monitor.h" #include "qapi/error.h" +#include "qapi/qmp/qdict.h" #include "sysemu/sysemu.h" #include "trace.h" @@ -190,12 +192,151 @@ static void xen_bus_remove_watch(XenBus *xenbus, XenWatch *watch, free_watch(watch); } +static void xen_bus_backend_create(XenBus *xenbus, const char *type, + const char *name, char *path, + Error **errp) +{ + xs_transaction_t tid; + char **key; + QDict *opts; + unsigned int i, n; + Error *local_err = NULL; + + trace_xen_bus_backend_create(type, path); + +again: + tid = xs_transaction_start(xenbus->xsh); + if (tid == XBT_NULL) { + error_setg(errp, "failed xs_transaction_start"); + return; + } + + key = xs_directory(xenbus->xsh, tid, path, &n); + if (!key) { + if (!xs_transaction_end(xenbus->xsh, tid, true)) { + error_setg_errno(errp, errno, "failed xs_transaction_end"); + } + return; + } + + opts = qdict_new(); + for (i = 0; i < n; i++) { + char *val; + + /* + * Assume anything found in the xenstore backend area, other than + * the keys created for a generic XenDevice, are parameters + * to be used to configure the backend. + */ + if (!strcmp(key[i], "state") || + !strcmp(key[i], "online") || + !strcmp(key[i], "frontend") || + !strcmp(key[i], "frontend-id") || + !strcmp(key[i], "hotplug-status")) + continue; + + if (xs_node_scanf(xenbus->xsh, tid, path, key[i], NULL, "%ms", + &val) == 1) { + qdict_put_str(opts, key[i], val); + free(val); + } + } + + free(key); + + if (!xs_transaction_end(xenbus->xsh, tid, false)) { + qobject_unref(opts); + + if (errno == EAGAIN) { + goto again; + } + + error_setg_errno(errp, errno, "failed xs_transaction_end"); + return; + } + + xen_backend_device_create(xenbus, type, name, opts, &local_err); + qobject_unref(opts); + + if (local_err) { + error_propagate_prepend(errp, local_err, + "failed to create '%s' device '%s': ", + type, name); + } +} + +static void xen_bus_type_enumerate(XenBus *xenbus, const char *type) +{ + char *domain_path = g_strdup_printf("backend/%s/%u", type, xen_domid); + char **backend; + unsigned int i, n; + + trace_xen_bus_type_enumerate(type); + + backend = xs_directory(xenbus->xsh, XBT_NULL, domain_path, &n); + if (!backend) { + goto out; + } + + for (i = 0; i < n; i++) { + char *backend_path = g_strdup_printf("%s/%s", domain_path, + backend[i]); + enum xenbus_state backend_state; + + if (xs_node_scanf(xenbus->xsh, XBT_NULL, backend_path, "state", + NULL, "%u", &backend_state) != 1) + backend_state = XenbusStateUnknown; + + if (backend_state == XenbusStateInitialising) { + Error *local_err = NULL; + + xen_bus_backend_create(xenbus, type, backend[i], backend_path, + &local_err); + if (local_err) { + error_report_err(local_err); + } + } + + g_free(backend_path); + } + + free(backend); + +out: + g_free(domain_path); +} + +static void xen_bus_enumerate(void *opaque) +{ + XenBus *xenbus = opaque; + char **type; + unsigned int i, n; + + trace_xen_bus_enumerate(); + + type = xs_directory(xenbus->xsh, XBT_NULL, "backend", &n); + if (!type) { + return; + } + + for (i = 0; i < n; i++) { + xen_bus_type_enumerate(xenbus, type[i]); + } + + free(type); +} + static void xen_bus_unrealize(BusState *bus, Error **errp) { XenBus *xenbus = XEN_BUS(bus); trace_xen_bus_unrealize(); + if (xenbus->backend_watch) { + xen_bus_remove_watch(xenbus, xenbus->backend_watch, NULL); + xenbus->backend_watch = NULL; + } + if (!xenbus->xsh) { return; } @@ -231,6 +372,7 @@ static void xen_bus_realize(BusState *bus, Error **errp) { XenBus *xenbus = XEN_BUS(bus); unsigned int domid; + Error *local_err = NULL; trace_xen_bus_realize(); @@ -250,6 +392,18 @@ static void xen_bus_realize(BusState *bus, Error **errp) notifier_list_init(&xenbus->watch_notifiers); qemu_set_fd_handler(xs_fileno(xenbus->xsh), xen_bus_watch, NULL, xenbus); + + module_call_init(MODULE_INIT_XEN_BACKEND); + + xenbus->backend_watch = + xen_bus_add_watch(xenbus, "", /* domain root node */ + "backend", xen_bus_enumerate, xenbus, &local_err); + if (local_err) { + /* This need not be treated as a hard error so don't propagate */ + error_reportf_err(local_err, + "failed to set up enumeration watch: "); + } + return; fail: @@ -407,7 +561,15 @@ static void xen_device_backend_changed(void *opaque) xendev->backend_state == XenbusStateInitialising || xendev->backend_state == XenbusStateInitWait || xendev->backend_state == XenbusStateUnknown)) { - object_unparent(OBJECT(xendev)); + Error *local_err = NULL; + + if (!xen_backend_try_device_destroy(xendev, &local_err)) { + object_unparent(OBJECT(xendev)); + } + + if (local_err) { + error_report_err(local_err); + } } } diff --git a/include/hw/xen/xen-backend.h b/include/hw/xen/xen-backend.h new file mode 100644 index 0000000000..010d712638 --- /dev/null +++ b/include/hw/xen/xen-backend.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2018 Citrix Systems Inc. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef HW_XEN_BACKEND_H +#define HW_XEN_BACKEND_H + +#include "hw/xen/xen-bus.h" + +typedef struct XenBackendInstance XenBackendInstance; + +typedef void (*XenBackendDeviceCreate)(XenBackendInstance *backend, + QDict *opts, Error **errp); +typedef void (*XenBackendDeviceDestroy)(XenBackendInstance *backend, + Error **errp); + +typedef struct XenBackendInfo { + const char *type; + XenBackendDeviceCreate create; + XenBackendDeviceDestroy destroy; +} XenBackendInfo; + +XenBus *xen_backend_get_bus(XenBackendInstance *backend); +const char *xen_backend_get_name(XenBackendInstance *backend); + +void xen_backend_set_device(XenBackendInstance *backend, + XenDevice *xendevice); +XenDevice *xen_backend_get_device(XenBackendInstance *backend); + +void xen_backend_register(const XenBackendInfo *info); + +void xen_backend_device_create(XenBus *xenbus, const char *type, + const char *name, QDict *opts, Error **errp); +bool xen_backend_try_device_destroy(XenDevice *xendev, Error **errp); + +#endif /* HW_XEN_BACKEND_H */ diff --git a/include/hw/xen/xen-bus.h b/include/hw/xen/xen-bus.h index 8f39f88d35..3183f10e3c 100644 --- a/include/hw/xen/xen-bus.h +++ b/include/hw/xen/xen-bus.h @@ -64,6 +64,7 @@ typedef struct XenBus { domid_t backend_id; struct xs_handle *xsh; NotifierList watch_notifiers; + XenWatch *backend_watch; } XenBus; typedef struct XenBusClass { diff --git a/include/qemu/module.h b/include/qemu/module.h index 54300ab6e5..55dd2beea8 100644 --- a/include/qemu/module.h +++ b/include/qemu/module.h @@ -44,6 +44,7 @@ typedef enum { MODULE_INIT_OPTS, MODULE_INIT_QOM, MODULE_INIT_TRACE, + MODULE_INIT_XEN_BACKEND, MODULE_INIT_MAX } module_init_type; @@ -51,6 +52,8 @@ typedef enum { #define opts_init(function) module_init(function, MODULE_INIT_OPTS) #define type_init(function) module_init(function, MODULE_INIT_QOM) #define trace_init(function) module_init(function, MODULE_INIT_TRACE) +#define xen_backend_init(function) module_init(function, \ + MODULE_INIT_XEN_BACKEND) #define block_module_load_one(lib) module_load_one("block-", lib) #define ui_module_load_one(lib) module_load_one("ui-", lib) From patchwork Mon Jan 14 13:51:47 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anthony PERARD X-Patchwork-Id: 10762835 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 1C60A139A for ; Mon, 14 Jan 2019 14:31:24 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0AC6E28D50 for ; Mon, 14 Jan 2019 14:31:24 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0893728DD5; Mon, 14 Jan 2019 14:31:24 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 18D8928D50 for ; Mon, 14 Jan 2019 14:31:23 +0000 (UTC) Received: from localhost ([127.0.0.1]:40158 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gj3Go-0006ag-D5 for patchwork-qemu-devel@patchwork.kernel.org; Mon, 14 Jan 2019 09:31:19 -0500 Received: from eggs.gnu.org ([209.51.188.92]:47439) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gj2ls-0007HH-AQ for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:59:23 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gj2lq-0004wd-I6 for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:59:20 -0500 Received: from smtp03.citrix.com ([162.221.156.55]:1411) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gj2lq-0004wI-7C for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:59:18 -0500 X-IronPort-AV: E=Sophos;i="5.56,477,1539648000"; d="scan'208";a="75507049" From: Anthony PERARD To: Date: Mon, 14 Jan 2019 13:51:47 +0000 Message-ID: <20190114135154.16826-19-anthony.perard@citrix.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190114135154.16826-1-anthony.perard@citrix.com> References: <20190114135154.16826-1-anthony.perard@citrix.com> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 162.221.156.55 Subject: [Qemu-devel] [PULL 18/25] xen: automatically create XenBlockDevice-s X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Anthony PERARD , xen-devel@lists.xenproject.org, Peter Maydell Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Paul Durrant This patch adds create and destroy function for XenBlockDevice-s so that they can be created automatically when the Xen toolstack instantiates a new PV backend via xenstore. When the XenBlockDevice is created this way it is also necessary to create a 'drive' which matches the configuration that the Xen toolstack has written into xenstore. This is done by formulating the parameters necessary for each 'blockdev' layer of the drive and then using qmp_blockdev_add() to create the layers. Also, for compatibility with the legacy 'xen_disk' implementation, an iothread is automatically created for the new XenBlockDevice. This, like the driver layers, will be destroyed after the XenBlockDevice is unrealized. The legacy backend scan for 'qdisk' is removed by this patch, which makes the 'xen_disk' code is redundant. The code will be removed by a subsequent patch. Signed-off-by: Paul Durrant Reviewed-by: Anthony PERARD Signed-off-by: Anthony PERARD --- hw/block/trace-events | 4 + hw/block/xen-block.c | 375 ++++++++++++++++++++++++++++++++++++ hw/xen/xen-legacy-backend.c | 1 - include/hw/xen/xen-block.h | 12 ++ 4 files changed, 391 insertions(+), 1 deletion(-) diff --git a/hw/block/trace-events b/hw/block/trace-events index 89e258319c..55e5a5500c 100644 --- a/hw/block/trace-events +++ b/hw/block/trace-events @@ -137,3 +137,7 @@ xen_disk_realize(void) "" xen_disk_unrealize(void) "" xen_cdrom_realize(void) "" xen_cdrom_unrealize(void) "" +xen_block_blockdev_add(char *str) "%s" +xen_block_blockdev_del(const char *node_name) "%s" +xen_block_device_create(unsigned int number) "%u" +xen_block_device_destroy(unsigned int number) "%u" diff --git a/hw/block/xen-block.c b/hw/block/xen-block.c index a7c37c185a..be28b63442 100644 --- a/hw/block/xen-block.c +++ b/hw/block/xen-block.c @@ -7,12 +7,20 @@ #include "qemu/osdep.h" #include "qemu/cutils.h" +#include "qemu/option.h" #include "qapi/error.h" +#include "qapi/qapi-commands-block-core.h" +#include "qapi/qapi-commands-misc.h" +#include "qapi/qapi-visit-block-core.h" +#include "qapi/qobject-input-visitor.h" #include "qapi/visitor.h" +#include "qapi/qmp/qdict.h" +#include "qapi/qmp/qstring.h" #include "hw/hw.h" #include "hw/xen/xen_common.h" #include "hw/block/xen_blkif.h" #include "hw/xen/xen-block.h" +#include "hw/xen/xen-backend.h" #include "sysemu/blockdev.h" #include "sysemu/block-backend.h" #include "sysemu/iothread.h" @@ -474,6 +482,7 @@ static void xen_block_class_init(ObjectClass *class, void *data) DeviceClass *dev_class = DEVICE_CLASS(class); XenDeviceClass *xendev_class = XEN_DEVICE_CLASS(class); + xendev_class->backend = "qdisk"; xendev_class->device = "vbd"; xendev_class->get_name = xen_block_get_name; xendev_class->realize = xen_block_realize; @@ -586,3 +595,369 @@ static void xen_block_register_types(void) } type_init(xen_block_register_types) + +static void xen_block_blockdev_del(const char *node_name, Error **errp) +{ + trace_xen_block_blockdev_del(node_name); + + qmp_blockdev_del(node_name, errp); +} + +static char *xen_block_blockdev_add(const char *id, QDict *qdict, + Error **errp) +{ + const char *driver = qdict_get_try_str(qdict, "driver"); + BlockdevOptions *options = NULL; + Error *local_err = NULL; + char *node_name; + Visitor *v; + + if (!driver) { + error_setg(errp, "no 'driver' parameter"); + return NULL; + } + + node_name = g_strdup_printf("%s-%s", id, driver); + qdict_put_str(qdict, "node-name", node_name); + + trace_xen_block_blockdev_add(node_name); + + v = qobject_input_visitor_new(QOBJECT(qdict)); + visit_type_BlockdevOptions(v, NULL, &options, &local_err); + visit_free(v); + + if (local_err) { + error_propagate(errp, local_err); + goto fail; + } + + qmp_blockdev_add(options, &local_err); + + if (local_err) { + error_propagate(errp, local_err); + goto fail; + } + + qapi_free_BlockdevOptions(options); + + return node_name; + +fail: + if (options) { + qapi_free_BlockdevOptions(options); + } + g_free(node_name); + + return NULL; +} + +static void xen_block_drive_destroy(XenBlockDrive *drive, Error **errp) +{ + char *node_name = drive->node_name; + + if (node_name) { + Error *local_err = NULL; + + xen_block_blockdev_del(node_name, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + g_free(node_name); + drive->node_name = NULL; + } + g_free(drive->id); + g_free(drive); +} + +static XenBlockDrive *xen_block_drive_create(const char *id, + const char *device_type, + QDict *opts, Error **errp) +{ + const char *params = qdict_get_try_str(opts, "params"); + const char *mode = qdict_get_try_str(opts, "mode"); + const char *direct_io_safe = qdict_get_try_str(opts, "direct-io-safe"); + const char *discard_enable = qdict_get_try_str(opts, "discard-enable"); + char *driver = NULL; + char *filename = NULL; + XenBlockDrive *drive = NULL; + Error *local_err = NULL; + QDict *file_layer; + QDict *driver_layer; + + if (params) { + char **v = g_strsplit(params, ":", 2); + + if (v[1] == NULL) { + filename = g_strdup(v[0]); + driver = g_strdup("raw"); + } else { + if (strcmp(v[0], "aio") == 0) { + driver = g_strdup("raw"); + } else if (strcmp(v[0], "vhd") == 0) { + driver = g_strdup("vpc"); + } else { + driver = g_strdup(v[0]); + } + filename = g_strdup(v[1]); + } + + g_strfreev(v); + } + + if (!filename) { + error_setg(errp, "no filename"); + goto done; + } + assert(driver); + + drive = g_new0(XenBlockDrive, 1); + drive->id = g_strdup(id); + + file_layer = qdict_new(); + + qdict_put_str(file_layer, "driver", "file"); + qdict_put_str(file_layer, "filename", filename); + + if (mode && *mode != 'w') { + qdict_put_bool(file_layer, "read-only", true); + } + + if (direct_io_safe) { + unsigned long value; + + if (!qemu_strtoul(direct_io_safe, NULL, 2, &value) && !!value) { + QDict *cache_qdict = qdict_new(); + + qdict_put_bool(cache_qdict, "direct", true); + qdict_put_obj(file_layer, "cache", QOBJECT(cache_qdict)); + + qdict_put_str(file_layer, "aio", "native"); + } + } + + if (discard_enable) { + unsigned long value; + + if (!qemu_strtoul(discard_enable, NULL, 2, &value) && !!value) { + qdict_put_str(file_layer, "discard", "unmap"); + } + } + + /* + * It is necessary to turn file locking off as an emulated device + * may have already opened the same image file. + */ + qdict_put_str(file_layer, "locking", "off"); + + driver_layer = qdict_new(); + + qdict_put_str(driver_layer, "driver", driver); + qdict_put_obj(driver_layer, "file", QOBJECT(file_layer)); + + g_assert(!drive->node_name); + drive->node_name = xen_block_blockdev_add(drive->id, driver_layer, + &local_err); + +done: + g_free(driver); + g_free(filename); + + if (local_err) { + error_propagate(errp, local_err); + xen_block_drive_destroy(drive, NULL); + return NULL; + } + + return drive; +} + +static const char *xen_block_drive_get_node_name(XenBlockDrive *drive) +{ + return drive->node_name ? drive->node_name : ""; +} + +static void xen_block_iothread_destroy(XenBlockIOThread *iothread, + Error **errp) +{ + qmp_object_del(iothread->id, errp); + + g_free(iothread->id); + g_free(iothread); +} + +static XenBlockIOThread *xen_block_iothread_create(const char *id, + Error **errp) +{ + XenBlockIOThread *iothread = g_new(XenBlockIOThread, 1); + Error *local_err = NULL; + + iothread->id = g_strdup(id); + + qmp_object_add(TYPE_IOTHREAD, id, false, NULL, &local_err); + if (local_err) { + error_propagate(errp, local_err); + + g_free(iothread->id); + g_free(iothread); + return NULL; + } + + return iothread; +} + +static void xen_block_device_create(XenBackendInstance *backend, + QDict *opts, Error **errp) +{ + XenBus *xenbus = xen_backend_get_bus(backend); + const char *name = xen_backend_get_name(backend); + unsigned long number; + const char *vdev, *device_type; + XenBlockDrive *drive = NULL; + XenBlockIOThread *iothread = NULL; + XenDevice *xendev = NULL; + Error *local_err = NULL; + const char *type; + XenBlockDevice *blockdev; + + if (qemu_strtoul(name, NULL, 10, &number)) { + error_setg(errp, "failed to parse name '%s'", name); + goto fail; + } + + trace_xen_block_device_create(number); + + vdev = qdict_get_try_str(opts, "dev"); + if (!vdev) { + error_setg(errp, "no dev parameter"); + goto fail; + } + + device_type = qdict_get_try_str(opts, "device-type"); + if (!device_type) { + error_setg(errp, "no device-type parameter"); + goto fail; + } + + if (!strcmp(device_type, "disk")) { + type = TYPE_XEN_DISK_DEVICE; + } else if (!strcmp(device_type, "cdrom")) { + type = TYPE_XEN_CDROM_DEVICE; + } else { + error_setg(errp, "invalid device-type parameter '%s'", device_type); + goto fail; + } + + drive = xen_block_drive_create(vdev, device_type, opts, &local_err); + if (!drive) { + error_propagate_prepend(errp, local_err, "failed to create drive: "); + goto fail; + } + + iothread = xen_block_iothread_create(vdev, &local_err); + if (local_err) { + error_propagate_prepend(errp, local_err, + "failed to create iothread: "); + goto fail; + } + + xendev = XEN_DEVICE(qdev_create(BUS(xenbus), type)); + blockdev = XEN_BLOCK_DEVICE(xendev); + + object_property_set_str(OBJECT(xendev), vdev, "vdev", &local_err); + if (local_err) { + error_propagate_prepend(errp, local_err, "failed to set 'vdev': "); + goto fail; + } + + object_property_set_str(OBJECT(xendev), + xen_block_drive_get_node_name(drive), "drive", + &local_err); + if (local_err) { + error_propagate_prepend(errp, local_err, "failed to set 'drive': "); + goto fail; + } + + object_property_set_str(OBJECT(xendev), iothread->id, "iothread", + &local_err); + if (local_err) { + error_propagate_prepend(errp, local_err, + "failed to set 'iothread': "); + goto fail; + } + + blockdev->iothread = iothread; + blockdev->drive = drive; + + object_property_set_bool(OBJECT(xendev), true, "realized", &local_err); + if (local_err) { + error_propagate_prepend(errp, local_err, + "realization of device %s failed: ", + type); + goto fail; + } + + xen_backend_set_device(backend, xendev); + return; + +fail: + if (xendev) { + object_unparent(OBJECT(xendev)); + } + + if (iothread) { + xen_block_iothread_destroy(iothread, NULL); + } + + if (drive) { + xen_block_drive_destroy(drive, NULL); + } +} + +static void xen_block_device_destroy(XenBackendInstance *backend, + Error **errp) +{ + XenDevice *xendev = xen_backend_get_device(backend); + XenBlockDevice *blockdev = XEN_BLOCK_DEVICE(xendev); + XenBlockVdev *vdev = &blockdev->props.vdev; + XenBlockDrive *drive = blockdev->drive; + XenBlockIOThread *iothread = blockdev->iothread; + + trace_xen_block_device_destroy(vdev->number); + + object_unparent(OBJECT(xendev)); + + if (iothread) { + Error *local_err = NULL; + + xen_block_iothread_destroy(iothread, &local_err); + if (local_err) { + error_propagate_prepend(errp, local_err, + "failed to destroy iothread: "); + return; + } + } + + if (drive) { + Error *local_err = NULL; + + xen_block_drive_destroy(drive, &local_err); + if (local_err) { + error_propagate_prepend(errp, local_err, + "failed to destroy drive: "); + } + } +} + +static const XenBackendInfo xen_block_backend_info = { + .type = "qdisk", + .create = xen_block_device_create, + .destroy = xen_block_device_destroy, +}; + +static void xen_block_register_backend(void) +{ + xen_backend_register(&xen_block_backend_info); +} + +xen_backend_init(xen_block_register_backend); diff --git a/hw/xen/xen-legacy-backend.c b/hw/xen/xen-legacy-backend.c index 41419763c8..36fd1e9b09 100644 --- a/hw/xen/xen-legacy-backend.c +++ b/hw/xen/xen-legacy-backend.c @@ -753,7 +753,6 @@ void xen_be_register_common(void) xen_be_register("console", &xen_console_ops); xen_be_register("vkbd", &xen_kbdmouse_ops); - xen_be_register("qdisk", &xen_blkdev_ops); #ifdef CONFIG_VIRTFS xen_be_register("9pfs", &xen_9pfs_ops); #endif diff --git a/include/hw/xen/xen-block.h b/include/hw/xen/xen-block.h index c4223f9be1..11d351b4b3 100644 --- a/include/hw/xen/xen-block.h +++ b/include/hw/xen/xen-block.h @@ -29,6 +29,7 @@ typedef struct XenBlockVdev { unsigned long number; } XenBlockVdev; + typedef struct XenBlockProperties { XenBlockVdev vdev; BlockConf conf; @@ -36,12 +37,23 @@ typedef struct XenBlockProperties { IOThread *iothread; } XenBlockProperties; +typedef struct XenBlockDrive { + char *id; + char *node_name; +} XenBlockDrive; + +typedef struct XenBlockIOThread { + char *id; +} XenBlockIOThread; + typedef struct XenBlockDevice { XenDevice xendev; XenBlockProperties props; const char *device_type; unsigned int info; XenBlockDataPlane *dataplane; + XenBlockDrive *drive; + XenBlockIOThread *iothread; } XenBlockDevice; typedef void (*XenBlockDeviceRealize)(XenBlockDevice *blockdev, Error **errp); From patchwork Mon Jan 14 13:51:48 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anthony PERARD X-Patchwork-Id: 10762675 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 61DFE14E5 for ; Mon, 14 Jan 2019 14:00:26 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5145A289BC for ; Mon, 14 Jan 2019 14:00:26 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4F4D728BF8; Mon, 14 Jan 2019 14:00:26 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 4407028A46 for ; Mon, 14 Jan 2019 14:00:25 +0000 (UTC) Received: from localhost ([127.0.0.1]:32933 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gj2mu-0008AF-Fz for patchwork-qemu-devel@patchwork.kernel.org; Mon, 14 Jan 2019 09:00:24 -0500 Received: from eggs.gnu.org ([209.51.188.92]:47208) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gj2lM-0006mN-Gw for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:58:51 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gj2lL-0004iV-Nt for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:58:48 -0500 Received: from smtp03.citrix.com ([162.221.156.55]:1352) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gj2lL-0004gB-F8 for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:58:47 -0500 X-IronPort-AV: E=Sophos;i="5.56,477,1539648000"; d="scan'208";a="75506989" From: Anthony PERARD To: Date: Mon, 14 Jan 2019 13:51:48 +0000 Message-ID: <20190114135154.16826-20-anthony.perard@citrix.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190114135154.16826-1-anthony.perard@citrix.com> References: <20190114135154.16826-1-anthony.perard@citrix.com> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 162.221.156.55 Subject: [Qemu-devel] [PULL 19/25] MAINTAINERS: add myself as a Xen maintainer X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Anthony PERARD , xen-devel@lists.xenproject.org, Peter Maydell Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Paul Durrant I have made many significant contributions to the Xen code in QEMU, particularly the recent patches introducing a new PV device framework. I intend to make further significant contributions, porting other PV back- ends to the new framework with the intent of eventually removing the legacy code. It therefore seems reasonable that I become a maintainer of the Xen code. Signed-off-by: Paul Durrant Acked-by: Anthony Perard Acked-by: Stefano Stabellini Signed-off-by: Anthony PERARD --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 43b2691b5d..2a1520dee7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -407,6 +407,7 @@ Guest CPU Cores (Xen): X86 M: Stefano Stabellini M: Anthony Perard +M: Paul Durrant L: xen-devel@lists.xenproject.org S: Supported F: */xen* From patchwork Mon Jan 14 13:51:49 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anthony PERARD X-Patchwork-Id: 10762735 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id F02046C2 for ; Mon, 14 Jan 2019 14:14:18 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D9DEA28B02 for ; Mon, 14 Jan 2019 14:14:18 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id CD64328C46; Mon, 14 Jan 2019 14:14:18 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 3B63F28B02 for ; Mon, 14 Jan 2019 14:14:17 +0000 (UTC) Received: from localhost ([127.0.0.1]:36053 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gj30K-0001fK-Ep for patchwork-qemu-devel@patchwork.kernel.org; Mon, 14 Jan 2019 09:14:16 -0500 Received: from eggs.gnu.org ([209.51.188.92]:47492) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gj2mG-0007cI-8L for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:59:47 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gj2mD-00052R-8U for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:59:44 -0500 Received: from smtp03.citrix.com ([162.221.156.55]:1427) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gj2mC-00050B-RR for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:59:41 -0500 X-IronPort-AV: E=Sophos;i="5.56,477,1539648000"; d="scan'208";a="75507066" From: Anthony PERARD To: Date: Mon, 14 Jan 2019 13:51:49 +0000 Message-ID: <20190114135154.16826-21-anthony.perard@citrix.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190114135154.16826-1-anthony.perard@citrix.com> References: <20190114135154.16826-1-anthony.perard@citrix.com> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 162.221.156.55 Subject: [Qemu-devel] [PULL 20/25] xen: remove the legacy 'xen_disk' backend X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Anthony PERARD , xen-devel@lists.xenproject.org, Peter Maydell Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Paul Durrant This backend has now been replaced by the 'xen-qdisk' XenDevice. Signed-off-by: Paul Durrant Acked-by: Anthony Perard Signed-off-by: Anthony PERARD --- hw/block/Makefile.objs | 1 - hw/block/xen_disk.c | 1011 ---------------------------------------- 2 files changed, 1012 deletions(-) delete mode 100644 hw/block/xen_disk.c diff --git a/hw/block/Makefile.objs b/hw/block/Makefile.objs index f34813a377..e206b8e712 100644 --- a/hw/block/Makefile.objs +++ b/hw/block/Makefile.objs @@ -5,7 +5,6 @@ common-obj-$(CONFIG_NAND) += nand.o common-obj-$(CONFIG_PFLASH_CFI01) += pflash_cfi01.o common-obj-$(CONFIG_PFLASH_CFI02) += pflash_cfi02.o common-obj-$(CONFIG_XEN) += xen-block.o -common-obj-$(CONFIG_XEN) += xen_disk.o common-obj-$(CONFIG_ECC) += ecc.o common-obj-$(CONFIG_ONENAND) += onenand.o common-obj-$(CONFIG_NVME_PCI) += nvme.o diff --git a/hw/block/xen_disk.c b/hw/block/xen_disk.c deleted file mode 100644 index 477dfcca9f..0000000000 --- a/hw/block/xen_disk.c +++ /dev/null @@ -1,1011 +0,0 @@ -/* - * xen paravirt block device backend - * - * (c) Gerd Hoffmann - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; under version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see . - * - * Contributions after 2012-01-13 are licensed under the terms of the - * GNU GPL, version 2 or (at your option) any later version. - */ - -#include "qemu/osdep.h" -#include "qemu/units.h" -#include -#include - -#include "hw/hw.h" -#include "hw/xen/xen-legacy-backend.h" -#include "xen_blkif.h" -#include "sysemu/blockdev.h" -#include "sysemu/iothread.h" -#include "sysemu/block-backend.h" -#include "qapi/error.h" -#include "qapi/qmp/qdict.h" -#include "qapi/qmp/qstring.h" -#include "trace.h" - -/* ------------------------------------------------------------- */ - -#define BLOCK_SIZE 512 -#define IOCB_COUNT (BLKIF_MAX_SEGMENTS_PER_REQUEST + 2) - -struct ioreq { - blkif_request_t req; - int16_t status; - - /* parsed request */ - off_t start; - QEMUIOVector v; - void *buf; - size_t size; - int presync; - - /* aio status */ - int aio_inflight; - int aio_errors; - - struct XenBlkDev *blkdev; - QLIST_ENTRY(ioreq) list; - BlockAcctCookie acct; -}; - -#define MAX_RING_PAGE_ORDER 4 - -struct XenBlkDev { - struct XenLegacyDevice xendev; /* must be first */ - char *params; - char *mode; - char *type; - char *dev; - char *devtype; - bool directiosafe; - const char *fileproto; - const char *filename; - unsigned int ring_ref[1 << MAX_RING_PAGE_ORDER]; - unsigned int nr_ring_ref; - void *sring; - int64_t file_blk; - int64_t file_size; - int protocol; - blkif_back_rings_t rings; - int more_work; - - /* request lists */ - QLIST_HEAD(, ioreq) inflight; - QLIST_HEAD(, ioreq) finished; - QLIST_HEAD(, ioreq) freelist; - int requests_total; - int requests_inflight; - int requests_finished; - unsigned int max_requests; - - gboolean feature_discard; - - /* qemu block driver */ - DriveInfo *dinfo; - BlockBackend *blk; - QEMUBH *bh; - - IOThread *iothread; - AioContext *ctx; -}; - -/* ------------------------------------------------------------- */ - -static void ioreq_reset(struct ioreq *ioreq) -{ - memset(&ioreq->req, 0, sizeof(ioreq->req)); - ioreq->status = 0; - ioreq->start = 0; - ioreq->buf = NULL; - ioreq->size = 0; - ioreq->presync = 0; - - ioreq->aio_inflight = 0; - ioreq->aio_errors = 0; - - ioreq->blkdev = NULL; - memset(&ioreq->list, 0, sizeof(ioreq->list)); - memset(&ioreq->acct, 0, sizeof(ioreq->acct)); - - qemu_iovec_reset(&ioreq->v); -} - -static struct ioreq *ioreq_start(struct XenBlkDev *blkdev) -{ - struct ioreq *ioreq = NULL; - - if (QLIST_EMPTY(&blkdev->freelist)) { - if (blkdev->requests_total >= blkdev->max_requests) { - goto out; - } - /* allocate new struct */ - ioreq = g_malloc0(sizeof(*ioreq)); - ioreq->blkdev = blkdev; - blkdev->requests_total++; - qemu_iovec_init(&ioreq->v, 1); - } else { - /* get one from freelist */ - ioreq = QLIST_FIRST(&blkdev->freelist); - QLIST_REMOVE(ioreq, list); - } - QLIST_INSERT_HEAD(&blkdev->inflight, ioreq, list); - blkdev->requests_inflight++; - -out: - return ioreq; -} - -static void ioreq_finish(struct ioreq *ioreq) -{ - struct XenBlkDev *blkdev = ioreq->blkdev; - - QLIST_REMOVE(ioreq, list); - QLIST_INSERT_HEAD(&blkdev->finished, ioreq, list); - blkdev->requests_inflight--; - blkdev->requests_finished++; -} - -static void ioreq_release(struct ioreq *ioreq, bool finish) -{ - struct XenBlkDev *blkdev = ioreq->blkdev; - - QLIST_REMOVE(ioreq, list); - ioreq_reset(ioreq); - ioreq->blkdev = blkdev; - QLIST_INSERT_HEAD(&blkdev->freelist, ioreq, list); - if (finish) { - blkdev->requests_finished--; - } else { - blkdev->requests_inflight--; - } -} - -/* - * translate request into iovec + start offset - * do sanity checks along the way - */ -static int ioreq_parse(struct ioreq *ioreq) -{ - struct XenBlkDev *blkdev = ioreq->blkdev; - struct XenLegacyDevice *xendev = &blkdev->xendev; - size_t len; - int i; - - xen_pv_printf(xendev, 3, - "op %d, nr %d, handle %d, id %" PRId64 ", sector %" PRId64 "\n", - ioreq->req.operation, ioreq->req.nr_segments, - ioreq->req.handle, ioreq->req.id, ioreq->req.sector_number); - switch (ioreq->req.operation) { - case BLKIF_OP_READ: - break; - case BLKIF_OP_FLUSH_DISKCACHE: - ioreq->presync = 1; - if (!ioreq->req.nr_segments) { - return 0; - } - /* fall through */ - case BLKIF_OP_WRITE: - break; - case BLKIF_OP_DISCARD: - return 0; - default: - xen_pv_printf(xendev, 0, "error: unknown operation (%d)\n", - ioreq->req.operation); - goto err; - }; - - if (ioreq->req.operation != BLKIF_OP_READ && blkdev->mode[0] != 'w') { - xen_pv_printf(xendev, 0, "error: write req for ro device\n"); - goto err; - } - - ioreq->start = ioreq->req.sector_number * blkdev->file_blk; - for (i = 0; i < ioreq->req.nr_segments; i++) { - if (i == BLKIF_MAX_SEGMENTS_PER_REQUEST) { - xen_pv_printf(xendev, 0, "error: nr_segments too big\n"); - goto err; - } - if (ioreq->req.seg[i].first_sect > ioreq->req.seg[i].last_sect) { - xen_pv_printf(xendev, 0, "error: first > last sector\n"); - goto err; - } - if (ioreq->req.seg[i].last_sect * BLOCK_SIZE >= XC_PAGE_SIZE) { - xen_pv_printf(xendev, 0, "error: page crossing\n"); - goto err; - } - - len = (ioreq->req.seg[i].last_sect - ioreq->req.seg[i].first_sect + 1) * blkdev->file_blk; - ioreq->size += len; - } - if (ioreq->start + ioreq->size > blkdev->file_size) { - xen_pv_printf(xendev, 0, "error: access beyond end of file\n"); - goto err; - } - return 0; - -err: - ioreq->status = BLKIF_RSP_ERROR; - return -1; -} - -static int ioreq_grant_copy(struct ioreq *ioreq) -{ - struct XenBlkDev *blkdev = ioreq->blkdev; - struct XenLegacyDevice *xendev = &blkdev->xendev; - XenGrantCopySegment segs[BLKIF_MAX_SEGMENTS_PER_REQUEST]; - int i, count, rc; - int64_t file_blk = blkdev->file_blk; - bool to_domain = (ioreq->req.operation == BLKIF_OP_READ); - void *virt = ioreq->buf; - - if (ioreq->req.nr_segments == 0) { - return 0; - } - - count = ioreq->req.nr_segments; - - for (i = 0; i < count; i++) { - if (to_domain) { - segs[i].dest.foreign.ref = ioreq->req.seg[i].gref; - segs[i].dest.foreign.offset = ioreq->req.seg[i].first_sect * file_blk; - segs[i].source.virt = virt; - } else { - segs[i].source.foreign.ref = ioreq->req.seg[i].gref; - segs[i].source.foreign.offset = ioreq->req.seg[i].first_sect * file_blk; - segs[i].dest.virt = virt; - } - segs[i].len = (ioreq->req.seg[i].last_sect - - ioreq->req.seg[i].first_sect + 1) * file_blk; - virt += segs[i].len; - } - - rc = xen_be_copy_grant_refs(xendev, to_domain, segs, count); - - if (rc) { - xen_pv_printf(xendev, 0, - "failed to copy data %d\n", rc); - ioreq->aio_errors++; - return -1; - } - - return rc; -} - -static int ioreq_runio_qemu_aio(struct ioreq *ioreq); - -static void qemu_aio_complete(void *opaque, int ret) -{ - struct ioreq *ioreq = opaque; - struct XenBlkDev *blkdev = ioreq->blkdev; - struct XenLegacyDevice *xendev = &blkdev->xendev; - - aio_context_acquire(blkdev->ctx); - - if (ret != 0) { - xen_pv_printf(xendev, 0, "%s I/O error\n", - ioreq->req.operation == BLKIF_OP_READ ? "read" : "write"); - ioreq->aio_errors++; - } - - ioreq->aio_inflight--; - if (ioreq->presync) { - ioreq->presync = 0; - ioreq_runio_qemu_aio(ioreq); - goto done; - } - if (ioreq->aio_inflight > 0) { - goto done; - } - - switch (ioreq->req.operation) { - case BLKIF_OP_READ: - /* in case of failure ioreq->aio_errors is increased */ - if (ret == 0) { - ioreq_grant_copy(ioreq); - } - qemu_vfree(ioreq->buf); - break; - case BLKIF_OP_WRITE: - case BLKIF_OP_FLUSH_DISKCACHE: - if (!ioreq->req.nr_segments) { - break; - } - qemu_vfree(ioreq->buf); - break; - default: - break; - } - - ioreq->status = ioreq->aio_errors ? BLKIF_RSP_ERROR : BLKIF_RSP_OKAY; - ioreq_finish(ioreq); - - switch (ioreq->req.operation) { - case BLKIF_OP_WRITE: - case BLKIF_OP_FLUSH_DISKCACHE: - if (!ioreq->req.nr_segments) { - break; - } - case BLKIF_OP_READ: - if (ioreq->status == BLKIF_RSP_OKAY) { - block_acct_done(blk_get_stats(blkdev->blk), &ioreq->acct); - } else { - block_acct_failed(blk_get_stats(blkdev->blk), &ioreq->acct); - } - break; - case BLKIF_OP_DISCARD: - default: - break; - } - qemu_bh_schedule(blkdev->bh); - -done: - aio_context_release(blkdev->ctx); -} - -static bool blk_split_discard(struct ioreq *ioreq, blkif_sector_t sector_number, - uint64_t nr_sectors) -{ - struct XenBlkDev *blkdev = ioreq->blkdev; - int64_t byte_offset; - int byte_chunk; - uint64_t byte_remaining, limit; - uint64_t sec_start = sector_number; - uint64_t sec_count = nr_sectors; - - /* Wrap around, or overflowing byte limit? */ - if (sec_start + sec_count < sec_count || - sec_start + sec_count > INT64_MAX >> BDRV_SECTOR_BITS) { - return false; - } - - limit = BDRV_REQUEST_MAX_SECTORS << BDRV_SECTOR_BITS; - byte_offset = sec_start << BDRV_SECTOR_BITS; - byte_remaining = sec_count << BDRV_SECTOR_BITS; - - do { - byte_chunk = byte_remaining > limit ? limit : byte_remaining; - ioreq->aio_inflight++; - blk_aio_pdiscard(blkdev->blk, byte_offset, byte_chunk, - qemu_aio_complete, ioreq); - byte_remaining -= byte_chunk; - byte_offset += byte_chunk; - } while (byte_remaining > 0); - - return true; -} - -static int ioreq_runio_qemu_aio(struct ioreq *ioreq) -{ - struct XenBlkDev *blkdev = ioreq->blkdev; - - ioreq->buf = qemu_memalign(XC_PAGE_SIZE, ioreq->size); - if (ioreq->req.nr_segments && - (ioreq->req.operation == BLKIF_OP_WRITE || - ioreq->req.operation == BLKIF_OP_FLUSH_DISKCACHE) && - ioreq_grant_copy(ioreq)) { - qemu_vfree(ioreq->buf); - goto err; - } - - ioreq->aio_inflight++; - if (ioreq->presync) { - blk_aio_flush(ioreq->blkdev->blk, qemu_aio_complete, ioreq); - return 0; - } - - switch (ioreq->req.operation) { - case BLKIF_OP_READ: - qemu_iovec_add(&ioreq->v, ioreq->buf, ioreq->size); - block_acct_start(blk_get_stats(blkdev->blk), &ioreq->acct, - ioreq->v.size, BLOCK_ACCT_READ); - ioreq->aio_inflight++; - blk_aio_preadv(blkdev->blk, ioreq->start, &ioreq->v, 0, - qemu_aio_complete, ioreq); - break; - case BLKIF_OP_WRITE: - case BLKIF_OP_FLUSH_DISKCACHE: - if (!ioreq->req.nr_segments) { - break; - } - - qemu_iovec_add(&ioreq->v, ioreq->buf, ioreq->size); - block_acct_start(blk_get_stats(blkdev->blk), &ioreq->acct, - ioreq->v.size, - ioreq->req.operation == BLKIF_OP_WRITE ? - BLOCK_ACCT_WRITE : BLOCK_ACCT_FLUSH); - ioreq->aio_inflight++; - blk_aio_pwritev(blkdev->blk, ioreq->start, &ioreq->v, 0, - qemu_aio_complete, ioreq); - break; - case BLKIF_OP_DISCARD: - { - struct blkif_request_discard *req = (void *)&ioreq->req; - if (!blk_split_discard(ioreq, req->sector_number, req->nr_sectors)) { - goto err; - } - break; - } - default: - /* unknown operation (shouldn't happen -- parse catches this) */ - goto err; - } - - qemu_aio_complete(ioreq, 0); - - return 0; - -err: - ioreq_finish(ioreq); - ioreq->status = BLKIF_RSP_ERROR; - return -1; -} - -static int blk_send_response_one(struct ioreq *ioreq) -{ - struct XenBlkDev *blkdev = ioreq->blkdev; - int send_notify = 0; - int have_requests = 0; - blkif_response_t *resp; - - /* Place on the response ring for the relevant domain. */ - switch (blkdev->protocol) { - case BLKIF_PROTOCOL_NATIVE: - resp = (blkif_response_t *) RING_GET_RESPONSE(&blkdev->rings.native, - blkdev->rings.native.rsp_prod_pvt); - break; - case BLKIF_PROTOCOL_X86_32: - resp = (blkif_response_t *) RING_GET_RESPONSE(&blkdev->rings.x86_32_part, - blkdev->rings.x86_32_part.rsp_prod_pvt); - break; - case BLKIF_PROTOCOL_X86_64: - resp = (blkif_response_t *) RING_GET_RESPONSE(&blkdev->rings.x86_64_part, - blkdev->rings.x86_64_part.rsp_prod_pvt); - break; - default: - return 0; - } - - resp->id = ioreq->req.id; - resp->operation = ioreq->req.operation; - resp->status = ioreq->status; - - blkdev->rings.common.rsp_prod_pvt++; - - RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&blkdev->rings.common, send_notify); - if (blkdev->rings.common.rsp_prod_pvt == blkdev->rings.common.req_cons) { - /* - * Tail check for pending requests. Allows frontend to avoid - * notifications if requests are already in flight (lower - * overheads and promotes batching). - */ - RING_FINAL_CHECK_FOR_REQUESTS(&blkdev->rings.common, have_requests); - } else if (RING_HAS_UNCONSUMED_REQUESTS(&blkdev->rings.common)) { - have_requests = 1; - } - - if (have_requests) { - blkdev->more_work++; - } - return send_notify; -} - -/* walk finished list, send outstanding responses, free requests */ -static void blk_send_response_all(struct XenBlkDev *blkdev) -{ - struct ioreq *ioreq; - int send_notify = 0; - - while (!QLIST_EMPTY(&blkdev->finished)) { - ioreq = QLIST_FIRST(&blkdev->finished); - send_notify += blk_send_response_one(ioreq); - ioreq_release(ioreq, true); - } - if (send_notify) { - xen_pv_send_notify(&blkdev->xendev); - } -} - -static int blk_get_request(struct XenBlkDev *blkdev, struct ioreq *ioreq, RING_IDX rc) -{ - switch (blkdev->protocol) { - case BLKIF_PROTOCOL_NATIVE: - memcpy(&ioreq->req, RING_GET_REQUEST(&blkdev->rings.native, rc), - sizeof(ioreq->req)); - break; - case BLKIF_PROTOCOL_X86_32: - blkif_get_x86_32_req(&ioreq->req, - RING_GET_REQUEST(&blkdev->rings.x86_32_part, rc)); - break; - case BLKIF_PROTOCOL_X86_64: - blkif_get_x86_64_req(&ioreq->req, - RING_GET_REQUEST(&blkdev->rings.x86_64_part, rc)); - break; - } - /* Prevent the compiler from accessing the on-ring fields instead. */ - barrier(); - return 0; -} - -static void blk_handle_requests(struct XenBlkDev *blkdev) -{ - RING_IDX rc, rp; - struct ioreq *ioreq; - - blkdev->more_work = 0; - - rc = blkdev->rings.common.req_cons; - rp = blkdev->rings.common.sring->req_prod; - xen_rmb(); /* Ensure we see queued requests up to 'rp'. */ - - blk_send_response_all(blkdev); - while (rc != rp) { - /* pull request from ring */ - if (RING_REQUEST_CONS_OVERFLOW(&blkdev->rings.common, rc)) { - break; - } - ioreq = ioreq_start(blkdev); - if (ioreq == NULL) { - blkdev->more_work++; - break; - } - blk_get_request(blkdev, ioreq, rc); - blkdev->rings.common.req_cons = ++rc; - - /* parse them */ - if (ioreq_parse(ioreq) != 0) { - - switch (ioreq->req.operation) { - case BLKIF_OP_READ: - block_acct_invalid(blk_get_stats(blkdev->blk), - BLOCK_ACCT_READ); - break; - case BLKIF_OP_WRITE: - block_acct_invalid(blk_get_stats(blkdev->blk), - BLOCK_ACCT_WRITE); - break; - case BLKIF_OP_FLUSH_DISKCACHE: - block_acct_invalid(blk_get_stats(blkdev->blk), - BLOCK_ACCT_FLUSH); - default: - break; - }; - - if (blk_send_response_one(ioreq)) { - xen_pv_send_notify(&blkdev->xendev); - } - ioreq_release(ioreq, false); - continue; - } - - ioreq_runio_qemu_aio(ioreq); - } - - if (blkdev->more_work && blkdev->requests_inflight < blkdev->max_requests) { - qemu_bh_schedule(blkdev->bh); - } -} - -/* ------------------------------------------------------------- */ - -static void blk_bh(void *opaque) -{ - struct XenBlkDev *blkdev = opaque; - - aio_context_acquire(blkdev->ctx); - blk_handle_requests(blkdev); - aio_context_release(blkdev->ctx); -} - -static void blk_alloc(struct XenLegacyDevice *xendev) -{ - struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev); - Error *err = NULL; - - trace_xen_disk_alloc(xendev->name); - - QLIST_INIT(&blkdev->inflight); - QLIST_INIT(&blkdev->finished); - QLIST_INIT(&blkdev->freelist); - - blkdev->iothread = iothread_create(xendev->name, &err); - assert(!err); - - blkdev->ctx = iothread_get_aio_context(blkdev->iothread); - blkdev->bh = aio_bh_new(blkdev->ctx, blk_bh, blkdev); -} - -static void blk_parse_discard(struct XenBlkDev *blkdev) -{ - struct XenLegacyDevice *xendev = &blkdev->xendev; - int enable; - - blkdev->feature_discard = true; - - if (xenstore_read_be_int(xendev, "discard-enable", &enable) == 0) { - blkdev->feature_discard = !!enable; - } - - if (blkdev->feature_discard) { - xenstore_write_be_int(xendev, "feature-discard", 1); - } -} - -static int blk_init(struct XenLegacyDevice *xendev) -{ - struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev); - int info = 0; - char *directiosafe = NULL; - - trace_xen_disk_init(xendev->name); - - /* read xenstore entries */ - if (blkdev->params == NULL) { - char *h = NULL; - blkdev->params = xenstore_read_be_str(xendev, "params"); - if (blkdev->params != NULL) { - h = strchr(blkdev->params, ':'); - } - if (h != NULL) { - blkdev->fileproto = blkdev->params; - blkdev->filename = h+1; - *h = 0; - } else { - blkdev->fileproto = ""; - blkdev->filename = blkdev->params; - } - } - if (!strcmp("aio", blkdev->fileproto)) { - blkdev->fileproto = "raw"; - } - if (!strcmp("vhd", blkdev->fileproto)) { - blkdev->fileproto = "vpc"; - } - if (blkdev->mode == NULL) { - blkdev->mode = xenstore_read_be_str(xendev, "mode"); - } - if (blkdev->type == NULL) { - blkdev->type = xenstore_read_be_str(xendev, "type"); - } - if (blkdev->dev == NULL) { - blkdev->dev = xenstore_read_be_str(xendev, "dev"); - } - if (blkdev->devtype == NULL) { - blkdev->devtype = xenstore_read_be_str(xendev, "device-type"); - } - directiosafe = xenstore_read_be_str(xendev, "direct-io-safe"); - blkdev->directiosafe = (directiosafe && atoi(directiosafe)); - - /* do we have all we need? */ - if (blkdev->params == NULL || - blkdev->mode == NULL || - blkdev->type == NULL || - blkdev->dev == NULL) { - goto out_error; - } - - /* read-only ? */ - if (strcmp(blkdev->mode, "w")) { - info |= VDISK_READONLY; - } - - /* cdrom ? */ - if (blkdev->devtype && !strcmp(blkdev->devtype, "cdrom")) { - info |= VDISK_CDROM; - } - - blkdev->file_blk = BLOCK_SIZE; - - /* fill info - * blk_connect supplies sector-size and sectors - */ - xenstore_write_be_int(xendev, "feature-flush-cache", 1); - xenstore_write_be_int(xendev, "info", info); - - xenstore_write_be_int(xendev, "max-ring-page-order", - MAX_RING_PAGE_ORDER); - - blk_parse_discard(blkdev); - - g_free(directiosafe); - return 0; - -out_error: - g_free(blkdev->params); - blkdev->params = NULL; - g_free(blkdev->mode); - blkdev->mode = NULL; - g_free(blkdev->type); - blkdev->type = NULL; - g_free(blkdev->dev); - blkdev->dev = NULL; - g_free(blkdev->devtype); - blkdev->devtype = NULL; - g_free(directiosafe); - blkdev->directiosafe = false; - return -1; -} - -static int blk_connect(struct XenLegacyDevice *xendev) -{ - struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev); - int index, qflags; - bool readonly = true; - bool writethrough = true; - int order, ring_ref; - unsigned int ring_size, max_grants; - unsigned int i; - - trace_xen_disk_connect(xendev->name); - - /* read-only ? */ - if (blkdev->directiosafe) { - qflags = BDRV_O_NOCACHE | BDRV_O_NATIVE_AIO; - } else { - qflags = 0; - writethrough = false; - } - if (strcmp(blkdev->mode, "w") == 0) { - qflags |= BDRV_O_RDWR; - readonly = false; - } - if (blkdev->feature_discard) { - qflags |= BDRV_O_UNMAP; - } - - /* init qemu block driver */ - index = (xendev->dev - 202 * 256) / 16; - blkdev->dinfo = drive_get(IF_XEN, 0, index); - if (!blkdev->dinfo) { - Error *local_err = NULL; - QDict *options = NULL; - - if (strcmp(blkdev->fileproto, "")) { - options = qdict_new(); - qdict_put_str(options, "driver", blkdev->fileproto); - } - - /* setup via xenbus -> create new block driver instance */ - xen_pv_printf(xendev, 2, "create new bdrv (xenbus setup)\n"); - blkdev->blk = blk_new_open(blkdev->filename, NULL, options, - qflags, &local_err); - if (!blkdev->blk) { - xen_pv_printf(xendev, 0, "error: %s\n", - error_get_pretty(local_err)); - error_free(local_err); - return -1; - } - blk_set_enable_write_cache(blkdev->blk, !writethrough); - } else { - /* setup via qemu cmdline -> already setup for us */ - xen_pv_printf(xendev, 2, - "get configured bdrv (cmdline setup)\n"); - blkdev->blk = blk_by_legacy_dinfo(blkdev->dinfo); - if (blk_is_read_only(blkdev->blk) && !readonly) { - xen_pv_printf(xendev, 0, "Unexpected read-only drive"); - blkdev->blk = NULL; - return -1; - } - /* blkdev->blk is not create by us, we get a reference - * so we can blk_unref() unconditionally */ - blk_ref(blkdev->blk); - } - blk_attach_dev_legacy(blkdev->blk, blkdev); - blkdev->file_size = blk_getlength(blkdev->blk); - if (blkdev->file_size < 0) { - BlockDriverState *bs = blk_bs(blkdev->blk); - const char *drv_name = bs ? bdrv_get_format_name(bs) : NULL; - xen_pv_printf(xendev, 1, "blk_getlength: %d (%s) | drv %s\n", - (int)blkdev->file_size, strerror(-blkdev->file_size), - drv_name ?: "-"); - blkdev->file_size = 0; - } - - xen_pv_printf(xendev, 1, "type \"%s\", fileproto \"%s\", filename \"%s\"," - " size %" PRId64 " (%" PRId64 " MB)\n", - blkdev->type, blkdev->fileproto, blkdev->filename, - blkdev->file_size, blkdev->file_size / MiB); - - /* Fill in number of sector size and number of sectors */ - xenstore_write_be_int(xendev, "sector-size", blkdev->file_blk); - xenstore_write_be_int64(xendev, "sectors", - blkdev->file_size / blkdev->file_blk); - - if (xenstore_read_fe_int(xendev, "ring-page-order", - &order) == -1) { - blkdev->nr_ring_ref = 1; - - if (xenstore_read_fe_int(xendev, "ring-ref", - &ring_ref) == -1) { - return -1; - } - blkdev->ring_ref[0] = ring_ref; - - } else if (order >= 0 && order <= MAX_RING_PAGE_ORDER) { - blkdev->nr_ring_ref = 1 << order; - - for (i = 0; i < blkdev->nr_ring_ref; i++) { - char *key; - - key = g_strdup_printf("ring-ref%u", i); - if (!key) { - return -1; - } - - if (xenstore_read_fe_int(xendev, key, - &ring_ref) == -1) { - g_free(key); - return -1; - } - blkdev->ring_ref[i] = ring_ref; - - g_free(key); - } - } else { - xen_pv_printf(xendev, 0, "invalid ring-page-order: %d\n", - order); - return -1; - } - - if (xenstore_read_fe_int(xendev, "event-channel", - &xendev->remote_port) == -1) { - return -1; - } - - if (!xendev->protocol) { - blkdev->protocol = BLKIF_PROTOCOL_NATIVE; - } else if (strcmp(xendev->protocol, XEN_IO_PROTO_ABI_NATIVE) == 0) { - blkdev->protocol = BLKIF_PROTOCOL_NATIVE; - } else if (strcmp(xendev->protocol, XEN_IO_PROTO_ABI_X86_32) == 0) { - blkdev->protocol = BLKIF_PROTOCOL_X86_32; - } else if (strcmp(xendev->protocol, XEN_IO_PROTO_ABI_X86_64) == 0) { - blkdev->protocol = BLKIF_PROTOCOL_X86_64; - } else { - blkdev->protocol = BLKIF_PROTOCOL_NATIVE; - } - - ring_size = XC_PAGE_SIZE * blkdev->nr_ring_ref; - switch (blkdev->protocol) { - case BLKIF_PROTOCOL_NATIVE: - { - blkdev->max_requests = __CONST_RING_SIZE(blkif, ring_size); - break; - } - case BLKIF_PROTOCOL_X86_32: - { - blkdev->max_requests = __CONST_RING_SIZE(blkif_x86_32, ring_size); - break; - } - case BLKIF_PROTOCOL_X86_64: - { - blkdev->max_requests = __CONST_RING_SIZE(blkif_x86_64, ring_size); - break; - } - default: - return -1; - } - - /* Add on the number needed for the ring pages */ - max_grants = blkdev->nr_ring_ref; - - xen_be_set_max_grant_refs(xendev, max_grants); - blkdev->sring = xen_be_map_grant_refs(xendev, blkdev->ring_ref, - blkdev->nr_ring_ref, - PROT_READ | PROT_WRITE); - if (!blkdev->sring) { - return -1; - } - - switch (blkdev->protocol) { - case BLKIF_PROTOCOL_NATIVE: - { - blkif_sring_t *sring_native = blkdev->sring; - BACK_RING_INIT(&blkdev->rings.native, sring_native, ring_size); - break; - } - case BLKIF_PROTOCOL_X86_32: - { - blkif_x86_32_sring_t *sring_x86_32 = blkdev->sring; - - BACK_RING_INIT(&blkdev->rings.x86_32_part, sring_x86_32, ring_size); - break; - } - case BLKIF_PROTOCOL_X86_64: - { - blkif_x86_64_sring_t *sring_x86_64 = blkdev->sring; - - BACK_RING_INIT(&blkdev->rings.x86_64_part, sring_x86_64, ring_size); - break; - } - } - - blk_set_aio_context(blkdev->blk, blkdev->ctx); - - xen_be_bind_evtchn(xendev); - - xen_pv_printf(xendev, 1, "ok: proto %s, nr-ring-ref %u, " - "remote port %d, local port %d\n", - xendev->protocol, blkdev->nr_ring_ref, - xendev->remote_port, xendev->local_port); - return 0; -} - -static void blk_disconnect(struct XenLegacyDevice *xendev) -{ - struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev); - - trace_xen_disk_disconnect(xendev->name); - - aio_context_acquire(blkdev->ctx); - - if (blkdev->blk) { - blk_set_aio_context(blkdev->blk, qemu_get_aio_context()); - blk_detach_dev(blkdev->blk, blkdev); - blk_unref(blkdev->blk); - blkdev->blk = NULL; - } - xen_pv_unbind_evtchn(xendev); - - aio_context_release(blkdev->ctx); - - if (blkdev->sring) { - xen_be_unmap_grant_refs(xendev, blkdev->sring, - blkdev->nr_ring_ref); - blkdev->sring = NULL; - } -} - -static int blk_free(struct XenLegacyDevice *xendev) -{ - struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev); - struct ioreq *ioreq; - - trace_xen_disk_free(xendev->name); - - blk_disconnect(xendev); - - while (!QLIST_EMPTY(&blkdev->freelist)) { - ioreq = QLIST_FIRST(&blkdev->freelist); - QLIST_REMOVE(ioreq, list); - qemu_iovec_destroy(&ioreq->v); - g_free(ioreq); - } - - g_free(blkdev->params); - g_free(blkdev->mode); - g_free(blkdev->type); - g_free(blkdev->dev); - g_free(blkdev->devtype); - qemu_bh_delete(blkdev->bh); - iothread_destroy(blkdev->iothread); - return 0; -} - -static void blk_event(struct XenLegacyDevice *xendev) -{ - struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev); - - qemu_bh_schedule(blkdev->bh); -} - -struct XenDevOps xen_blkdev_ops = { - .flags = DEVOPS_FLAG_NEED_GNTDEV, - .size = sizeof(struct XenBlkDev), - .alloc = blk_alloc, - .init = blk_init, - .initialise = blk_connect, - .disconnect = blk_disconnect, - .event = blk_event, - .free = blk_free, -}; From patchwork Mon Jan 14 13:51:50 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anthony PERARD X-Patchwork-Id: 10762855 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id F308F1580 for ; Mon, 14 Jan 2019 14:35:00 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DFE5E28B5D for ; Mon, 14 Jan 2019 14:35:00 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D29DF28B65; Mon, 14 Jan 2019 14:35:00 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id D5D9D28B5D for ; Mon, 14 Jan 2019 14:34:58 +0000 (UTC) Received: from localhost ([127.0.0.1]:40939 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gj3KM-0000jY-4Q for patchwork-qemu-devel@patchwork.kernel.org; Mon, 14 Jan 2019 09:34:58 -0500 Received: from eggs.gnu.org ([209.51.188.92]:47484) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gj2mE-0007b1-Qy for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:59:45 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gj2mC-000528-QW for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:59:42 -0500 Received: from smtp03.citrix.com ([162.221.156.55]:1419) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gj2mB-0004zB-3c for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:59:40 -0500 X-IronPort-AV: E=Sophos;i="5.56,477,1539648000"; d="scan'208";a="75507075" From: Anthony PERARD To: Date: Mon, 14 Jan 2019 13:51:50 +0000 Message-ID: <20190114135154.16826-22-anthony.perard@citrix.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190114135154.16826-1-anthony.perard@citrix.com> References: <20190114135154.16826-1-anthony.perard@citrix.com> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 162.221.156.55 Subject: [Qemu-devel] [PULL 21/25] Remove broken Xen PV domain builder X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Anthony PERARD , xen-devel@lists.xenproject.org, Peter Maydell Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP It is broken since Xen 4.9 [1] and it will not build in Xen 4.12. Also, it is not built by default since QEMU 2.6. [1] https://lists.xenproject.org/archives/html/xen-devel/2018-09/msg00313.html Signed-off-by: Anthony PERARD Acked-by: Stefano Stabellini --- configure | 17 -- hw/xenpv/Makefile.objs | 2 - hw/xenpv/xen_domainbuild.c | 299 ------------------------------------ hw/xenpv/xen_domainbuild.h | 13 -- hw/xenpv/xen_machine_pv.c | 14 -- include/hw/xen/xen.h | 1 - include/hw/xen/xen_common.h | 18 --- qemu-options.hx | 8 - vl.c | 7 - 9 files changed, 379 deletions(-) delete mode 100644 hw/xenpv/xen_domainbuild.c delete mode 100644 hw/xenpv/xen_domainbuild.h diff --git a/configure b/configure index 4ea3f14883..f992709b89 100755 --- a/configure +++ b/configure @@ -357,7 +357,6 @@ vnc_png="" xkbcommon="" xen="" xen_ctrl_version="" -xen_pv_domain_build="no" xen_pci_passthrough="" linux_aio="" cap_ng="" @@ -1119,10 +1118,6 @@ for opt do ;; --enable-xen-pci-passthrough) xen_pci_passthrough="yes" ;; - --disable-xen-pv-domain-build) xen_pv_domain_build="no" - ;; - --enable-xen-pv-domain-build) xen_pv_domain_build="yes" - ;; --disable-brlapi) brlapi="no" ;; --enable-brlapi) brlapi="yes" @@ -1685,8 +1680,6 @@ Advanced options (experts only): --tls-priority default TLS protocol/cipher priority string --enable-gprof QEMU profiling with gprof --enable-profiler profiler support - --enable-xen-pv-domain-build - xen pv domain builder --enable-debug-stack-usage track the maximum stack usage of stacks created by qemu_alloc_stack @@ -2678,12 +2671,6 @@ if test "$xen_pci_passthrough" != "no"; then fi fi -if test "$xen_pv_domain_build" = "yes" && - test "$xen" != "yes"; then - error_exit "User requested Xen PV domain builder support" \ - "which requires Xen support." -fi - ########################################## # Windows Hypervisor Platform accelerator (WHPX) check if test "$whpx" != "no" ; then @@ -6069,7 +6056,6 @@ fi echo "xen support $xen" if test "$xen" = "yes" ; then echo "xen ctrl version $xen_ctrl_version" - echo "pv dom build $xen_pv_domain_build" fi echo "brlapi support $brlapi" echo "bluez support $bluez" @@ -6539,9 +6525,6 @@ fi if test "$xen" = "yes" ; then echo "CONFIG_XEN_BACKEND=y" >> $config_host_mak echo "CONFIG_XEN_CTRL_INTERFACE_VERSION=$xen_ctrl_version" >> $config_host_mak - if test "$xen_pv_domain_build" = "yes" ; then - echo "CONFIG_XEN_PV_DOMAIN_BUILD=y" >> $config_host_mak - fi fi if test "$linux_aio" = "yes" ; then echo "CONFIG_LINUX_AIO=y" >> $config_host_mak diff --git a/hw/xenpv/Makefile.objs b/hw/xenpv/Makefile.objs index bbf5873fd1..8bfa4586ab 100644 --- a/hw/xenpv/Makefile.objs +++ b/hw/xenpv/Makefile.objs @@ -1,4 +1,2 @@ # Xen PV machine support obj-$(CONFIG_XEN) += xen_machine_pv.o -# Xen PV machine builder support -obj-$(CONFIG_XEN_PV_DOMAIN_BUILD) += xen_domainbuild.o diff --git a/hw/xenpv/xen_domainbuild.c b/hw/xenpv/xen_domainbuild.c deleted file mode 100644 index 1d9926e8d6..0000000000 --- a/hw/xenpv/xen_domainbuild.c +++ /dev/null @@ -1,299 +0,0 @@ -#include "qemu/osdep.h" -#include "qemu/units.h" -#include "hw/xen/xen-legacy-backend.h" -#include "xen_domainbuild.h" -#include "qemu/timer.h" -#include "qemu/log.h" - -#include - -static int xenstore_domain_mkdir(char *path) -{ - struct xs_permissions perms_ro[] = {{ - .id = 0, /* set owner: dom0 */ - },{ - .id = xen_domid, - .perms = XS_PERM_READ, - }}; - struct xs_permissions perms_rw[] = {{ - .id = 0, /* set owner: dom0 */ - },{ - .id = xen_domid, - .perms = XS_PERM_READ | XS_PERM_WRITE, - }}; - const char *writable[] = { "device", "control", "error", NULL }; - char subpath[256]; - int i; - - if (!xs_mkdir(xenstore, 0, path)) { - fprintf(stderr, "%s: xs_mkdir %s: failed\n", __func__, path); - return -1; - } - if (!xs_set_permissions(xenstore, 0, path, perms_ro, 2)) { - fprintf(stderr, "%s: xs_set_permissions failed\n", __func__); - return -1; - } - - for (i = 0; writable[i]; i++) { - snprintf(subpath, sizeof(subpath), "%s/%s", path, writable[i]); - if (!xs_mkdir(xenstore, 0, subpath)) { - fprintf(stderr, "%s: xs_mkdir %s: failed\n", __func__, subpath); - return -1; - } - if (!xs_set_permissions(xenstore, 0, subpath, perms_rw, 2)) { - fprintf(stderr, "%s: xs_set_permissions failed\n", __func__); - return -1; - } - } - return 0; -} - -int xenstore_domain_init1(const char *kernel, const char *ramdisk, - const char *cmdline) -{ - char *dom, uuid_string[42], vm[256], path[256]; - int i; - - qemu_uuid_unparse(&qemu_uuid, uuid_string); - dom = xs_get_domain_path(xenstore, xen_domid); - snprintf(vm, sizeof(vm), "/vm/%s", uuid_string); - - xenstore_domain_mkdir(dom); - - xenstore_write_str(vm, "image/ostype", "linux"); - if (kernel) - xenstore_write_str(vm, "image/kernel", kernel); - if (ramdisk) - xenstore_write_str(vm, "image/ramdisk", ramdisk); - if (cmdline) - xenstore_write_str(vm, "image/cmdline", cmdline); - - /* name + id */ - xenstore_write_str(vm, "name", qemu_name ? qemu_name : "no-name"); - xenstore_write_str(vm, "uuid", uuid_string); - xenstore_write_str(dom, "name", qemu_name ? qemu_name : "no-name"); - xenstore_write_int(dom, "domid", xen_domid); - xenstore_write_str(dom, "vm", vm); - - /* memory */ - xenstore_write_int(dom, "memory/target", ram_size / KiB); - xenstore_write_int(vm, "memory", ram_size / MiB); - xenstore_write_int(vm, "maxmem", ram_size / MiB); - - /* cpus */ - for (i = 0; i < smp_cpus; i++) { - snprintf(path, sizeof(path), "cpu/%d/availability",i); - xenstore_write_str(dom, path, "online"); - } - xenstore_write_int(vm, "vcpu_avail", smp_cpus); - xenstore_write_int(vm, "vcpus", smp_cpus); - - /* vnc password */ - xenstore_write_str(vm, "vncpassword", "" /* FIXME */); - - free(dom); - return 0; -} - -int xenstore_domain_init2(int xenstore_port, int xenstore_mfn, - int console_port, int console_mfn) -{ - char *dom; - - dom = xs_get_domain_path(xenstore, xen_domid); - - /* signal new domain */ - xs_introduce_domain(xenstore, - xen_domid, - xenstore_mfn, - xenstore_port); - - /* xenstore */ - xenstore_write_int(dom, "store/ring-ref", xenstore_mfn); - xenstore_write_int(dom, "store/port", xenstore_port); - - /* console */ - xenstore_write_str(dom, "console/type", "ioemu"); - xenstore_write_int(dom, "console/limit", 128 * KiB); - xenstore_write_int(dom, "console/ring-ref", console_mfn); - xenstore_write_int(dom, "console/port", console_port); - xen_config_dev_console(0); - - free(dom); - return 0; -} - -/* ------------------------------------------------------------- */ - -static QEMUTimer *xen_poll; - -/* check domain state once per second */ -static void xen_domain_poll(void *opaque) -{ - struct xc_dominfo info; - int rc; - - rc = xc_domain_getinfo(xen_xc, xen_domid, 1, &info); - if ((rc != 1) || (info.domid != xen_domid)) { - qemu_log("xen: domain %d is gone\n", xen_domid); - goto quit; - } - if (info.dying) { - qemu_log("xen: domain %d is dying (%s%s)\n", xen_domid, - info.crashed ? "crashed" : "", - info.shutdown ? "shutdown" : ""); - goto quit; - } - - timer_mod(xen_poll, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 1000); - return; - -quit: - qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); -} - -static int xen_domain_watcher(void) -{ - int qemu_running = 1; - int fd[2], i, n, rc; - char byte; - - if (pipe(fd) != 0) { - qemu_log("%s: Huh? pipe error: %s\n", __func__, strerror(errno)); - return -1; - } - if (fork() != 0) - return 0; /* not child */ - - /* close all file handles, except stdio/out/err, - * our watch pipe and the xen interface handle */ - n = getdtablesize(); - for (i = 3; i < n; i++) { - if (i == fd[0]) - continue; - close(i); - } - - /* - * Reopen xc interface, since the original is unsafe after fork - * and was closed above. - */ - xen_xc = xc_interface_open(0, 0, 0); - - /* ignore term signals */ - signal(SIGINT, SIG_IGN); - signal(SIGTERM, SIG_IGN); - - /* wait for qemu exiting */ - while (qemu_running) { - rc = read(fd[0], &byte, 1); - switch (rc) { - case -1: - if (errno == EINTR) - continue; - qemu_log("%s: Huh? read error: %s\n", __func__, strerror(errno)); - qemu_running = 0; - break; - case 0: - /* EOF -> qemu exited */ - qemu_running = 0; - break; - default: - qemu_log("%s: Huh? data on the watch pipe?\n", __func__); - break; - } - } - - /* cleanup */ - qemu_log("%s: destroy domain %d\n", __func__, xen_domid); - xc_domain_destroy(xen_xc, xen_domid); - _exit(0); -} - -/* normal cleanup */ -static void xen_domain_cleanup(void) -{ - char *dom; - - dom = xs_get_domain_path(xenstore, xen_domid); - if (dom) { - xs_rm(xenstore, 0, dom); - free(dom); - } - xs_release_domain(xenstore, xen_domid); -} - -int xen_domain_build_pv(const char *kernel, const char *ramdisk, - const char *cmdline) -{ - uint32_t ssidref = 0; - uint32_t flags = 0; - xen_domain_handle_t uuid; - unsigned int xenstore_port = 0, console_port = 0; - unsigned long xenstore_mfn = 0, console_mfn = 0; - int rc; - - memcpy(uuid, &qemu_uuid, sizeof(uuid)); - rc = xen_domain_create(xen_xc, ssidref, uuid, flags, &xen_domid); - if (rc < 0) { - fprintf(stderr, "xen: xc_domain_create() failed\n"); - goto err; - } - qemu_log("xen: created domain %d\n", xen_domid); - atexit(xen_domain_cleanup); - if (xen_domain_watcher() == -1) { - goto err; - } - - xenstore_domain_init1(kernel, ramdisk, cmdline); - - rc = xc_domain_max_vcpus(xen_xc, xen_domid, smp_cpus); - if (rc < 0) { - fprintf(stderr, "xen: xc_domain_max_vcpus() failed\n"); - goto err; - } - -#if 0 - rc = xc_domain_setcpuweight(xen_xc, xen_domid, 256); - if (rc < 0) { - fprintf(stderr, "xen: xc_domain_setcpuweight() failed\n"); - goto err; - } -#endif - - rc = xc_domain_setmaxmem(xen_xc, xen_domid, ram_size / KiB); - if (rc < 0) { - fprintf(stderr, "xen: xc_domain_setmaxmem() failed\n"); - goto err; - } - - xenstore_port = xc_evtchn_alloc_unbound(xen_xc, xen_domid, 0); - console_port = xc_evtchn_alloc_unbound(xen_xc, xen_domid, 0); - - rc = xc_linux_build(xen_xc, xen_domid, ram_size / MiB, - kernel, ramdisk, cmdline, - 0, flags, - xenstore_port, &xenstore_mfn, - console_port, &console_mfn); - if (rc < 0) { - fprintf(stderr, "xen: xc_linux_build() failed\n"); - goto err; - } - - xenstore_domain_init2(xenstore_port, xenstore_mfn, - console_port, console_mfn); - - qemu_log("xen: unpausing domain %d\n", xen_domid); - rc = xc_domain_unpause(xen_xc, xen_domid); - if (rc < 0) { - fprintf(stderr, "xen: xc_domain_unpause() failed\n"); - goto err; - } - - xen_poll = timer_new_ms(QEMU_CLOCK_REALTIME, xen_domain_poll, NULL); - timer_mod(xen_poll, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 1000); - return 0; - -err: - return -1; -} diff --git a/hw/xenpv/xen_domainbuild.h b/hw/xenpv/xen_domainbuild.h deleted file mode 100644 index 652d9b410f..0000000000 --- a/hw/xenpv/xen_domainbuild.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef QEMU_HW_XEN_DOMAINBUILD_H -#define QEMU_HW_XEN_DOMAINBUILD_H - -#include "hw/xen/xen_common.h" - -int xenstore_domain_init1(const char *kernel, const char *ramdisk, - const char *cmdline); -int xenstore_domain_init2(int xenstore_port, int xenstore_mfn, - int console_port, int console_mfn); -int xen_domain_build_pv(const char *kernel, const char *ramdisk, - const char *cmdline); - -#endif /* QEMU_HW_XEN_DOMAINBUILD_H */ diff --git a/hw/xenpv/xen_machine_pv.c b/hw/xenpv/xen_machine_pv.c index 608e591bcc..8d68fef25e 100644 --- a/hw/xenpv/xen_machine_pv.c +++ b/hw/xenpv/xen_machine_pv.c @@ -28,7 +28,6 @@ #include "hw/boards.h" #include "hw/xen/xen-legacy-backend.h" #include "hw/xen/xen-bus.h" -#include "xen_domainbuild.h" #include "sysemu/block-backend.h" static void xen_init_pv(MachineState *machine) @@ -46,19 +45,6 @@ static void xen_init_pv(MachineState *machine) case XEN_ATTACH: /* nothing to do, xend handles everything */ break; -#ifdef CONFIG_XEN_PV_DOMAIN_BUILD - case XEN_CREATE: { - const char *kernel_filename = machine->kernel_filename; - const char *kernel_cmdline = machine->kernel_cmdline; - const char *initrd_filename = machine->initrd_filename; - if (xen_domain_build_pv(kernel_filename, initrd_filename, - kernel_cmdline) < 0) { - error_report("xen pv domain creation failed"); - exit(1); - } - break; - } -#endif case XEN_EMULATE: error_report("xen emulation not implemented (yet)"); exit(1); diff --git a/include/hw/xen/xen.h b/include/hw/xen/xen.h index 7efcdaa8fe..978aaa31fb 100644 --- a/include/hw/xen/xen.h +++ b/include/hw/xen/xen.h @@ -15,7 +15,6 @@ /* xen-machine.c */ enum xen_mode { XEN_EMULATE = 0, // xen emulation, using xenner (default) - XEN_CREATE, // create xen domain XEN_ATTACH // attach to xen domain created by xend }; diff --git a/include/hw/xen/xen_common.h b/include/hw/xen/xen_common.h index 9c3ac07d78..9a8155e172 100644 --- a/include/hw/xen/xen_common.h +++ b/include/hw/xen/xen_common.h @@ -662,24 +662,6 @@ static inline int xen_set_ioreq_server_state(domid_t dom, #endif -#ifdef CONFIG_XEN_PV_DOMAIN_BUILD -#if CONFIG_XEN_CTRL_INTERFACE_VERSION < 40700 -static inline int xen_domain_create(xc_interface *xc, uint32_t ssidref, - xen_domain_handle_t handle, uint32_t flags, - uint32_t *pdomid) -{ - return xc_domain_create(xc, ssidref, handle, flags, pdomid); -} -#else -static inline int xen_domain_create(xc_interface *xc, uint32_t ssidref, - xen_domain_handle_t handle, uint32_t flags, - uint32_t *pdomid) -{ - return xc_domain_create(xc, ssidref, handle, flags, pdomid, NULL); -} -#endif -#endif - /* Xen before 4.8 */ #if CONFIG_XEN_CTRL_INTERFACE_VERSION < 40800 diff --git a/qemu-options.hx b/qemu-options.hx index d4f3564b78..7c323c9406 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -3394,10 +3394,6 @@ ETEXI DEF("xen-domid", HAS_ARG, QEMU_OPTION_xen_domid, "-xen-domid id specify xen guest domain id\n", QEMU_ARCH_ALL) -DEF("xen-create", 0, QEMU_OPTION_xen_create, - "-xen-create create domain using xen hypercalls, bypassing xend\n" - " warning: should not be used when xend is in use\n", - QEMU_ARCH_ALL) DEF("xen-attach", 0, QEMU_OPTION_xen_attach, "-xen-attach attach to existing xen domain\n" " xend will use this when starting QEMU\n", @@ -3411,10 +3407,6 @@ STEXI @item -xen-domid @var{id} @findex -xen-domid Specify xen guest domain @var{id} (XEN only). -@item -xen-create -@findex -xen-create -Create domain using xen hypercalls, bypassing xend. -Warning: should not be used when xend is in use (XEN only). @item -xen-attach @findex -xen-attach Attach to existing xen domain. diff --git a/vl.c b/vl.c index 9b8ea3f654..bc9fbec654 100644 --- a/vl.c +++ b/vl.c @@ -3856,13 +3856,6 @@ int main(int argc, char **argv, char **envp) } xen_domid = atoi(optarg); break; - case QEMU_OPTION_xen_create: - if (!(xen_available())) { - error_report("Option not supported for this target"); - exit(1); - } - xen_mode = XEN_CREATE; - break; case QEMU_OPTION_xen_attach: if (!(xen_available())) { error_report("Option not supported for this target"); From patchwork Mon Jan 14 13:51:51 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anthony PERARD X-Patchwork-Id: 10762827 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id DDBB0139A for ; Mon, 14 Jan 2019 14:23:36 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D016328DBD for ; Mon, 14 Jan 2019 14:23:36 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id BFFF928DD3; Mon, 14 Jan 2019 14:23:36 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id CF03C28DBD for ; Mon, 14 Jan 2019 14:23:31 +0000 (UTC) Received: from localhost ([127.0.0.1]:38183 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gj39G-00009c-LE for patchwork-qemu-devel@patchwork.kernel.org; Mon, 14 Jan 2019 09:23:30 -0500 Received: from eggs.gnu.org ([209.51.188.92]:47124) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gj2lI-0006gL-QI for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:58:45 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gj2lH-0004eT-Lu for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:58:44 -0500 Received: from smtp03.citrix.com ([162.221.156.55]:1339) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gj2lH-0004Z1-DF for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:58:43 -0500 X-IronPort-AV: E=Sophos;i="5.56,477,1539648000"; d="scan'208";a="75506967" From: Anthony PERARD To: Date: Mon, 14 Jan 2019 13:51:51 +0000 Message-ID: <20190114135154.16826-23-anthony.perard@citrix.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190114135154.16826-1-anthony.perard@citrix.com> References: <20190114135154.16826-1-anthony.perard@citrix.com> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 162.221.156.55 Subject: [Qemu-devel] [PULL 22/25] xen: Replace few mentions of xend by libxl X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Anthony PERARD , xen-devel@lists.xenproject.org, Peter Maydell Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP xend have been replaced by libxenlight (libxl) for many Xen releases now. Signed-off-by: Anthony PERARD Acked-by: Stefano Stabellini --- hw/xenpv/xen_machine_pv.c | 2 +- include/hw/xen/xen.h | 2 +- qemu-options.hx | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/xenpv/xen_machine_pv.c b/hw/xenpv/xen_machine_pv.c index 8d68fef25e..dcaf2a01a3 100644 --- a/hw/xenpv/xen_machine_pv.c +++ b/hw/xenpv/xen_machine_pv.c @@ -43,7 +43,7 @@ static void xen_init_pv(MachineState *machine) switch (xen_mode) { case XEN_ATTACH: - /* nothing to do, xend handles everything */ + /* nothing to do, libxl handles everything */ break; case XEN_EMULATE: error_report("xen emulation not implemented (yet)"); diff --git a/include/hw/xen/xen.h b/include/hw/xen/xen.h index 978aaa31fb..ba039c146d 100644 --- a/include/hw/xen/xen.h +++ b/include/hw/xen/xen.h @@ -15,7 +15,7 @@ /* xen-machine.c */ enum xen_mode { XEN_EMULATE = 0, // xen emulation, using xenner (default) - XEN_ATTACH // attach to xen domain created by xend + XEN_ATTACH // attach to xen domain created by libxl }; extern uint32_t xen_domid; diff --git a/qemu-options.hx b/qemu-options.hx index 7c323c9406..521511ec13 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -3396,7 +3396,7 @@ DEF("xen-domid", HAS_ARG, QEMU_OPTION_xen_domid, "-xen-domid id specify xen guest domain id\n", QEMU_ARCH_ALL) DEF("xen-attach", 0, QEMU_OPTION_xen_attach, "-xen-attach attach to existing xen domain\n" - " xend will use this when starting QEMU\n", + " libxl will use this when starting QEMU\n", QEMU_ARCH_ALL) DEF("xen-domid-restrict", 0, QEMU_OPTION_xen_domid_restrict, "-xen-domid-restrict restrict set of available xen operations\n" @@ -3410,7 +3410,7 @@ Specify xen guest domain @var{id} (XEN only). @item -xen-attach @findex -xen-attach Attach to existing xen domain. -xend will use this when starting QEMU (XEN only). +libxl will use this when starting QEMU (XEN only). @findex -xen-domid-restrict Restrict set of available xen operations to specified domain id (XEN only). ETEXI From patchwork Mon Jan 14 13:51:52 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anthony PERARD X-Patchwork-Id: 10762829 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 4C723139A for ; Mon, 14 Jan 2019 14:25:09 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3B5A52893C for ; Mon, 14 Jan 2019 14:25:09 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2C91D28A99; Mon, 14 Jan 2019 14:25:09 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id F26F32893C for ; Mon, 14 Jan 2019 14:25:07 +0000 (UTC) Received: from localhost ([127.0.0.1]:38611 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gj3Ap-0001cu-4t for patchwork-qemu-devel@patchwork.kernel.org; Mon, 14 Jan 2019 09:25:07 -0500 Received: from eggs.gnu.org ([209.51.188.92]:47401) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gj2lp-0007Em-Gk for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:59:19 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gj2lo-0004vg-JK for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:59:17 -0500 Received: from smtp03.citrix.com ([162.221.156.55]:1402) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gj2lo-0004v3-BU for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:59:16 -0500 X-IronPort-AV: E=Sophos;i="5.56,477,1539648000"; d="scan'208";a="75507045" From: Anthony PERARD To: Date: Mon, 14 Jan 2019 13:51:52 +0000 Message-ID: <20190114135154.16826-24-anthony.perard@citrix.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190114135154.16826-1-anthony.perard@citrix.com> References: <20190114135154.16826-1-anthony.perard@citrix.com> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 162.221.156.55 Subject: [Qemu-devel] [PULL 23/25] xen-block: improve batching behaviour X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Anthony PERARD , xen-devel@lists.xenproject.org, Peter Maydell Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Tim Smith When I/O consists of many small requests, performance is improved by batching them together in a single io_submit() call. When there are relatively few requests, the extra overhead is not worth it. This introduces a check to start batching I/O requests via blk_io_plug()/ blk_io_unplug() in an amount proportional to the number which were already in flight at the time we started reading the ring. Signed-off-by: Tim Smith Re-based and commit comment adjusted. Signed-off-by: Paul Durrant Acked-by: Anthony PERARD Signed-off-by: Anthony PERARD --- hw/block/dataplane/xen-block.c | 35 ++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/hw/block/dataplane/xen-block.c b/hw/block/dataplane/xen-block.c index 8e3965e171..acd23a74a8 100644 --- a/hw/block/dataplane/xen-block.c +++ b/hw/block/dataplane/xen-block.c @@ -528,10 +528,18 @@ static int xen_block_get_request(XenBlockDataPlane *dataplane, return 0; } +/* + * Threshold of in-flight requests above which we will start using + * blk_io_plug()/blk_io_unplug() to batch requests. + */ +#define IO_PLUG_THRESHOLD 1 + static void xen_block_handle_requests(XenBlockDataPlane *dataplane) { RING_IDX rc, rp; XenBlockRequest *request; + int inflight_atstart = dataplane->requests_inflight; + int batched = 0; dataplane->more_work = 0; @@ -540,6 +548,18 @@ static void xen_block_handle_requests(XenBlockDataPlane *dataplane) xen_rmb(); /* Ensure we see queued requests up to 'rp'. */ xen_block_send_response_all(dataplane); + /* + * If there was more than IO_PLUG_THRESHOLD requests in flight + * when we got here, this is an indication that there the bottleneck + * is below us, so it's worth beginning to batch up I/O requests + * rather than submitting them immediately. The maximum number + * of requests we're willing to batch is the number already in + * flight, so it can grow up to max_requests when the bottleneck + * is below us. + */ + if (inflight_atstart > IO_PLUG_THRESHOLD) { + blk_io_plug(dataplane->blk); + } while (rc != rp) { /* pull request from ring */ if (RING_REQUEST_CONS_OVERFLOW(&dataplane->rings.common, rc)) { @@ -585,7 +605,22 @@ static void xen_block_handle_requests(XenBlockDataPlane *dataplane) continue; } + if (inflight_atstart > IO_PLUG_THRESHOLD && + batched >= inflight_atstart) { + blk_io_unplug(dataplane->blk); + } xen_block_do_aio(request); + if (inflight_atstart > IO_PLUG_THRESHOLD) { + if (batched >= inflight_atstart) { + blk_io_plug(dataplane->blk); + batched = 0; + } else { + batched++; + } + } + } + if (inflight_atstart > IO_PLUG_THRESHOLD) { + blk_io_unplug(dataplane->blk); } if (dataplane->more_work && From patchwork Mon Jan 14 13:51:53 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anthony PERARD X-Patchwork-Id: 10762689 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 8E5636C2 for ; Mon, 14 Jan 2019 14:07:54 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 725A428CCA for ; Mon, 14 Jan 2019 14:07:54 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 66AE628CD0; Mon, 14 Jan 2019 14:07:54 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id D597628CCE for ; Mon, 14 Jan 2019 14:07:53 +0000 (UTC) Received: from localhost ([127.0.0.1]:34442 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gj2u9-00057u-2J for patchwork-qemu-devel@patchwork.kernel.org; Mon, 14 Jan 2019 09:07:53 -0500 Received: from eggs.gnu.org ([209.51.188.92]:47399) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gj2lp-0007EZ-9V for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:59:19 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gj2lo-0004vR-4e for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:59:17 -0500 Received: from smtp03.citrix.com ([162.221.156.55]:1402) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gj2ln-0004v3-S3 for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:59:16 -0500 X-IronPort-AV: E=Sophos;i="5.56,477,1539648000"; d="scan'208";a="75507041" From: Anthony PERARD To: Date: Mon, 14 Jan 2019 13:51:53 +0000 Message-ID: <20190114135154.16826-25-anthony.perard@citrix.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190114135154.16826-1-anthony.perard@citrix.com> References: <20190114135154.16826-1-anthony.perard@citrix.com> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 162.221.156.55 Subject: [Qemu-devel] [PULL 24/25] xen-block: improve response latency X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Anthony PERARD , xen-devel@lists.xenproject.org, Peter Maydell Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Tim Smith If the I/O ring is full, the guest cannot send any more requests until some responses are sent. Only sending all available responses just before checking for new work does not leave much time for the guest to supply new work, so this will cause stalls if the ring gets full. Also, not completing reads as soon as possible adds latency to the guest. To alleviate that, complete IO requests as soon as they come back. xen_block_send_response() already returns a value indicating whether a notify should be sent, which is all the batching we need. Signed-off-by: Tim Smith Re-based and commit comment adjusted. Signed-off-by: Paul Durrant Acked-by: Anthony PERARD Signed-off-by: Anthony PERARD --- hw/block/dataplane/xen-block.c | 56 +++++++++++----------------------- 1 file changed, 18 insertions(+), 38 deletions(-) diff --git a/hw/block/dataplane/xen-block.c b/hw/block/dataplane/xen-block.c index acd23a74a8..35bfccfba7 100644 --- a/hw/block/dataplane/xen-block.c +++ b/hw/block/dataplane/xen-block.c @@ -55,11 +55,9 @@ struct XenBlockDataPlane { blkif_back_rings_t rings; int more_work; QLIST_HEAD(inflight_head, XenBlockRequest) inflight; - QLIST_HEAD(finished_head, XenBlockRequest) finished; QLIST_HEAD(freelist_head, XenBlockRequest) freelist; int requests_total; int requests_inflight; - int requests_finished; unsigned int max_requests; BlockBackend *blk; QEMUBH *bh; @@ -116,12 +114,10 @@ static void xen_block_finish_request(XenBlockRequest *request) XenBlockDataPlane *dataplane = request->dataplane; QLIST_REMOVE(request, list); - QLIST_INSERT_HEAD(&dataplane->finished, request, list); dataplane->requests_inflight--; - dataplane->requests_finished++; } -static void xen_block_release_request(XenBlockRequest *request, bool finish) +static void xen_block_release_request(XenBlockRequest *request) { XenBlockDataPlane *dataplane = request->dataplane; @@ -129,11 +125,7 @@ static void xen_block_release_request(XenBlockRequest *request, bool finish) reset_request(request); request->dataplane = dataplane; QLIST_INSERT_HEAD(&dataplane->freelist, request, list); - if (finish) { - dataplane->requests_finished--; - } else { - dataplane->requests_inflight--; - } + dataplane->requests_inflight--; } /* @@ -248,6 +240,7 @@ static int xen_block_copy_request(XenBlockRequest *request) } static int xen_block_do_aio(XenBlockRequest *request); +static int xen_block_send_response(XenBlockRequest *request); static void xen_block_complete_aio(void *opaque, int ret) { @@ -312,6 +305,18 @@ static void xen_block_complete_aio(void *opaque, int ret) default: break; } + if (xen_block_send_response(request)) { + Error *local_err = NULL; + + xen_device_notify_event_channel(dataplane->xendev, + dataplane->event_channel, + &local_err); + if (local_err) { + error_report_err(local_err); + } + } + xen_block_release_request(request); + qemu_bh_schedule(dataplane->bh); done: @@ -419,7 +424,7 @@ static int xen_block_do_aio(XenBlockRequest *request) return -1; } -static int xen_block_send_response_one(XenBlockRequest *request) +static int xen_block_send_response(XenBlockRequest *request) { XenBlockDataPlane *dataplane = request->dataplane; int send_notify = 0; @@ -474,29 +479,6 @@ static int xen_block_send_response_one(XenBlockRequest *request) return send_notify; } -/* walk finished list, send outstanding responses, free requests */ -static void xen_block_send_response_all(XenBlockDataPlane *dataplane) -{ - XenBlockRequest *request; - int send_notify = 0; - - while (!QLIST_EMPTY(&dataplane->finished)) { - request = QLIST_FIRST(&dataplane->finished); - send_notify += xen_block_send_response_one(request); - xen_block_release_request(request, true); - } - if (send_notify) { - Error *local_err = NULL; - - xen_device_notify_event_channel(dataplane->xendev, - dataplane->event_channel, - &local_err); - if (local_err) { - error_report_err(local_err); - } - } -} - static int xen_block_get_request(XenBlockDataPlane *dataplane, XenBlockRequest *request, RING_IDX rc) { @@ -547,7 +529,6 @@ static void xen_block_handle_requests(XenBlockDataPlane *dataplane) rp = dataplane->rings.common.sring->req_prod; xen_rmb(); /* Ensure we see queued requests up to 'rp'. */ - xen_block_send_response_all(dataplane); /* * If there was more than IO_PLUG_THRESHOLD requests in flight * when we got here, this is an indication that there the bottleneck @@ -591,7 +572,7 @@ static void xen_block_handle_requests(XenBlockDataPlane *dataplane) break; }; - if (xen_block_send_response_one(request)) { + if (xen_block_send_response(request)) { Error *local_err = NULL; xen_device_notify_event_channel(dataplane->xendev, @@ -601,7 +582,7 @@ static void xen_block_handle_requests(XenBlockDataPlane *dataplane) error_report_err(local_err); } } - xen_block_release_request(request, false); + xen_block_release_request(request); continue; } @@ -657,7 +638,6 @@ XenBlockDataPlane *xen_block_dataplane_create(XenDevice *xendev, dataplane->file_size = blk_getlength(dataplane->blk); QLIST_INIT(&dataplane->inflight); - QLIST_INIT(&dataplane->finished); QLIST_INIT(&dataplane->freelist); if (iothread) { From patchwork Mon Jan 14 13:51:54 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anthony PERARD X-Patchwork-Id: 10762713 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 24F0A6C2 for ; Mon, 14 Jan 2019 14:11:06 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 14DAA28C24 for ; Mon, 14 Jan 2019 14:11:06 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0913D28CF2; Mon, 14 Jan 2019 14:11:06 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 7BA1528CE6 for ; Mon, 14 Jan 2019 14:11:04 +0000 (UTC) Received: from localhost ([127.0.0.1]:35245 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gj2xD-0007g5-8c for patchwork-qemu-devel@patchwork.kernel.org; Mon, 14 Jan 2019 09:11:03 -0500 Received: from eggs.gnu.org ([209.51.188.92]:47436) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gj2ls-0007H1-0u for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:59:21 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gj2lr-0004wp-1j for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:59:19 -0500 Received: from smtp03.citrix.com ([162.221.156.55]:1411) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gj2lq-0004wI-QQ for qemu-devel@nongnu.org; Mon, 14 Jan 2019 08:59:18 -0500 X-IronPort-AV: E=Sophos;i="5.56,477,1539648000"; d="scan'208";a="75507052" From: Anthony PERARD To: Date: Mon, 14 Jan 2019 13:51:54 +0000 Message-ID: <20190114135154.16826-26-anthony.perard@citrix.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190114135154.16826-1-anthony.perard@citrix.com> References: <20190114135154.16826-1-anthony.perard@citrix.com> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 162.221.156.55 Subject: [Qemu-devel] [PULL 25/25] xen-block: avoid repeated memory allocation X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Anthony PERARD , xen-devel@lists.xenproject.org, Peter Maydell Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Tim Smith The xen-block dataplane currently allocates memory to hold the data for each request as that request is used, and frees it afterwards. Because it requires page-aligned blocks, this interacts poorly with non-page- aligned allocations and balloons the heap. Instead, allocate the maximum possible buffer size required for the protocol, which is BLKIF_MAX_SEGMENTS_PER_REQUEST (currently 11) pages when the request structure is created, and keep that buffer until it is destroyed. Since the requests are re-used via a free list, this should actually improve memory usage. Signed-off-by: Tim Smith Re-based and commit comment adjusted. Signed-off-by: Paul Durrant Acked-by: Anthony PERARD Signed-off-by: Anthony PERARD --- hw/block/dataplane/xen-block.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/hw/block/dataplane/xen-block.c b/hw/block/dataplane/xen-block.c index 35bfccfba7..d0d8905a33 100644 --- a/hw/block/dataplane/xen-block.c +++ b/hw/block/dataplane/xen-block.c @@ -70,7 +70,6 @@ static void reset_request(XenBlockRequest *request) memset(&request->req, 0, sizeof(request->req)); request->status = 0; request->start = 0; - request->buf = NULL; request->size = 0; request->presync = 0; @@ -95,6 +94,14 @@ static XenBlockRequest *xen_block_start_request(XenBlockDataPlane *dataplane) /* allocate new struct */ request = g_malloc0(sizeof(*request)); request->dataplane = dataplane; + /* + * We cannot need more pages per requests than this, and since we + * re-use requests, allocate the memory once here. It will be freed + * xen_block_dataplane_destroy() when the request list is freed. + */ + request->buf = qemu_memalign(XC_PAGE_SIZE, + BLKIF_MAX_SEGMENTS_PER_REQUEST * + XC_PAGE_SIZE); dataplane->requests_total++; qemu_iovec_init(&request->v, 1); } else { @@ -272,14 +279,12 @@ static void xen_block_complete_aio(void *opaque, int ret) if (ret == 0) { xen_block_copy_request(request); } - qemu_vfree(request->buf); break; case BLKIF_OP_WRITE: case BLKIF_OP_FLUSH_DISKCACHE: if (!request->req.nr_segments) { break; } - qemu_vfree(request->buf); break; default: break; @@ -360,12 +365,10 @@ static int xen_block_do_aio(XenBlockRequest *request) { XenBlockDataPlane *dataplane = request->dataplane; - request->buf = qemu_memalign(XC_PAGE_SIZE, request->size); if (request->req.nr_segments && (request->req.operation == BLKIF_OP_WRITE || request->req.operation == BLKIF_OP_FLUSH_DISKCACHE) && xen_block_copy_request(request)) { - qemu_vfree(request->buf); goto err; } @@ -665,6 +668,7 @@ void xen_block_dataplane_destroy(XenBlockDataPlane *dataplane) request = QLIST_FIRST(&dataplane->freelist); QLIST_REMOVE(request, list); qemu_iovec_destroy(&request->v); + qemu_vfree(request->buf); g_free(request); }