From patchwork Mon Jan 7 14:12:52 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Paul Durrant X-Patchwork-Id: 10750643 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 29F2B13B5 for ; Mon, 7 Jan 2019 14:29:59 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 136F428A10 for ; Mon, 7 Jan 2019 14:29:59 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 005FF28A14; Mon, 7 Jan 2019 14:29:58 +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 64DCA28A10 for ; Mon, 7 Jan 2019 14:29:56 +0000 (UTC) Received: from localhost ([127.0.0.1]:37655 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ggVud-0005Ur-L7 for patchwork-qemu-devel@patchwork.kernel.org; Mon, 07 Jan 2019 09:29:55 -0500 Received: from eggs.gnu.org ([209.51.188.92]:58886) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ggVpi-00017H-8O for qemu-devel@nongnu.org; Mon, 07 Jan 2019 09:24:54 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ggVpd-0008PB-Tx for qemu-devel@nongnu.org; Mon, 07 Jan 2019 09:24:50 -0500 Received: from smtp03.citrix.com ([162.221.156.55]:22770) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ggVpd-0008OQ-0E; Mon, 07 Jan 2019 09:24:45 -0500 X-IronPort-AV: E=Sophos;i="5.56,451,1539648000"; d="scan'208";a="74964899" From: Paul Durrant To: , , Date: Mon, 7 Jan 2019 14:12:52 +0000 Message-ID: <20190107141309.15774-2-paul.durrant@citrix.com> X-Mailer: git-send-email 2.20.1.2.gb21ebb6 In-Reply-To: <20190107141309.15774-1-paul.durrant@citrix.com> References: <20190107141309.15774-1-paul.durrant@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] [PATCH v8 01/18] 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: Kevin Wolf , Stefano Stabellini , Eduardo Habkost , "Michael S. Tsirkin" , Jason Wang , Greg Kurz , Max Reitz , Paul Durrant , Gerd Hoffmann , Paolo Bonzini , Anthony Perard , =?utf-8?q?Marc-Andr=C3=A9_Lurea?= =?utf-8?q?u?= , Richard Henderson Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP ...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 --- Cc: Stefano Stabellini Cc: Greg Kurz Cc: Kevin Wolf Cc: Max Reitz Cc: "Marc-André Lureau" Cc: Paolo Bonzini Cc: Richard Henderson Cc: Eduardo Habkost Cc: "Michael S. Tsirkin" Cc: Marcel Apfelbaum Cc: Jason Wang Cc: Gerd Hoffmann --- 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 @@ out: 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 36eff94f84..75fe55f2ae 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 @@ err: 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 @@ out_error: 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 44f7236382..460adc1ba1 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 @@ out: 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 2143d33b18..6ef31571c8 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 4e4f069a24..9134a7bfef 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 f5d5c91094..5eabacba93 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 6ec14c73ca..ef130b2850 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 aebc19bd71..1b30bd7691 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 f1f3a3727c..b20bf3a453 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 47f9010c75..81112049b6 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 135c8df1e7..130cc6cbf0 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 aed783e844..61de091002 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_head, xs_dirs) xs_cleanup = QTAILQ_HEAD_INITIALIZER(xs_cleanup); -static QTAILQ_HEAD(XenDeviceHead, XenDevice) xendevs = +static QTAILQ_HEAD(XenLegacyDeviceHead, 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 188acaca16..deb28cf596 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 7 14:12:53 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Durrant X-Patchwork-Id: 10750633 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 2B75891E for ; Mon, 7 Jan 2019 14:26:15 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 162CC28A49 for ; Mon, 7 Jan 2019 14:26:15 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0981628A61; Mon, 7 Jan 2019 14:26:15 +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 47F2B28A49 for ; Mon, 7 Jan 2019 14:26:14 +0000 (UTC) Received: from localhost ([127.0.0.1]:36557 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ggVr3-0002MG-Ex for patchwork-qemu-devel@patchwork.kernel.org; Mon, 07 Jan 2019 09:26:13 -0500 Received: from eggs.gnu.org ([209.51.188.92]:58877) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ggVph-00016r-PT for qemu-devel@nongnu.org; Mon, 07 Jan 2019 09:24:51 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ggVpg-0008Pu-8F for qemu-devel@nongnu.org; Mon, 07 Jan 2019 09:24:49 -0500 Received: from smtp03.citrix.com ([162.221.156.55]:22770) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ggVpg-0008OQ-06; Mon, 07 Jan 2019 09:24:48 -0500 X-IronPort-AV: E=Sophos;i="5.56,451,1539648000"; d="scan'208";a="74964890" From: Paul Durrant To: , , Date: Mon, 7 Jan 2019 14:12:53 +0000 Message-ID: <20190107141309.15774-3-paul.durrant@citrix.com> X-Mailer: git-send-email 2.20.1.2.gb21ebb6 In-Reply-To: <20190107141309.15774-1-paul.durrant@citrix.com> References: <20190107141309.15774-1-paul.durrant@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] [PATCH v8 02/18] 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: Stefano Stabellini , Eduardo Habkost , "Michael S. Tsirkin" , Paul Durrant , Anthony Perard , Paolo Bonzini , Richard Henderson Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP 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 --- Cc: Stefano Stabellini Cc: "Michael S. Tsirkin" Cc: Marcel Apfelbaum Cc: Paolo Bonzini Cc: Richard Henderson Cc: Eduardo Habkost v3: - Don't use local_err unless it is needed v2: - Fix boilerplate - Make xen-bus hotplug capable --- 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 6ef31571c8..497e685d40 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 7 14:12:54 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Durrant X-Patchwork-Id: 10750637 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 2A62C91E for ; Mon, 7 Jan 2019 14:29:22 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0D5C428A0B for ; Mon, 7 Jan 2019 14:29:22 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 013F328A28; Mon, 7 Jan 2019 14:29:21 +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 EF38528A0B for ; Mon, 7 Jan 2019 14:29:20 +0000 (UTC) Received: from localhost ([127.0.0.1]:37470 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ggVu3-0004v9-Nc for patchwork-qemu-devel@patchwork.kernel.org; Mon, 07 Jan 2019 09:29:19 -0500 Received: from eggs.gnu.org ([209.51.188.92]:59015) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ggVpz-0001Nd-VT for qemu-devel@nongnu.org; Mon, 07 Jan 2019 09:25:09 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ggVpx-0008V4-Ul for qemu-devel@nongnu.org; Mon, 07 Jan 2019 09:25:07 -0500 Received: from smtp03.citrix.com ([162.221.156.55]:22782) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ggVpo-0008Rw-3A; Mon, 07 Jan 2019 09:24:57 -0500 X-IronPort-AV: E=Sophos;i="5.56,451,1539648000"; d="scan'208";a="74964892" From: Paul Durrant To: , , Date: Mon, 7 Jan 2019 14:12:54 +0000 Message-ID: <20190107141309.15774-4-paul.durrant@citrix.com> X-Mailer: git-send-email 2.20.1.2.gb21ebb6 In-Reply-To: <20190107141309.15774-1-paul.durrant@citrix.com> References: <20190107141309.15774-1-paul.durrant@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] [PATCH v8 03/18] 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 , Kevin Wolf , Paul Durrant , Stefano Stabellini , Max Reitz Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP 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 --- Cc: Kevin Wolf Cc: Max Reitz Cc: Stefano Stabellini v5: - Introduce properties sub-structure (which will be useful later) - Keeping Anthony's R-b from v4 since change is trivial v3: - Fix vdev parsing again, and vdev formatting this time - Remove an unnecessary local_err v2: - Fix boilerplate - Fix vdev parsing - Change name from 'xen-qdisk' to 'xen-block', make abstract, and split off 'xen-disk' and 'xen-cdrom' as concrete sub-types --- 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 19792cfb2d..38d6c3b973 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 7 14:12:55 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Durrant X-Patchwork-Id: 10750651 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 5A11F13BF for ; Mon, 7 Jan 2019 14:32:34 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4711A28A80 for ; Mon, 7 Jan 2019 14:32:34 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3B5E528A82; Mon, 7 Jan 2019 14:32:34 +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 E25FB28A80 for ; Mon, 7 Jan 2019 14:32:32 +0000 (UTC) Received: from localhost ([127.0.0.1]:38337 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ggVxA-0007jL-41 for patchwork-qemu-devel@patchwork.kernel.org; Mon, 07 Jan 2019 09:32:32 -0500 Received: from eggs.gnu.org ([209.51.188.92]:59972) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ggVsh-0003mU-MY for qemu-devel@nongnu.org; Mon, 07 Jan 2019 09:27:58 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ggVsf-0002Wc-9N for qemu-devel@nongnu.org; Mon, 07 Jan 2019 09:27:55 -0500 Received: from smtp03.citrix.com ([162.221.156.55]:23022) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ggVsa-0002U8-3Z; Mon, 07 Jan 2019 09:27:48 -0500 X-IronPort-AV: E=Sophos;i="5.56,451,1539648000"; d="scan'208";a="74964901" From: Paul Durrant To: , , Date: Mon, 7 Jan 2019 14:12:55 +0000 Message-ID: <20190107141309.15774-5-paul.durrant@citrix.com> X-Mailer: git-send-email 2.20.1.2.gb21ebb6 In-Reply-To: <20190107141309.15774-1-paul.durrant@citrix.com> References: <20190107141309.15774-1-paul.durrant@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] [PATCH v8 04/18] 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 , Kevin Wolf , Paul Durrant , Stefano Stabellini , Max Reitz Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP 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 --- Cc: Stefano Stabellini Cc: Kevin Wolf Cc: Max Reitz v5: - Re-base v3: - Add transaction id parameters to xen-bus-helper functions - Not added Anthony's R-b because of change v2: - Fix boilerplate - Add error pointers to all xs_node... helpers - Add GCC_FMT_ATTR to declarations of printf-like helpers --- 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 7 14:12:56 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Durrant X-Patchwork-Id: 10750629 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 352A791E for ; Mon, 7 Jan 2019 14:24:52 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2174528A49 for ; Mon, 7 Jan 2019 14:24:52 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1515828A61; Mon, 7 Jan 2019 14:24:52 +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 DC68A28A49 for ; Mon, 7 Jan 2019 14:24:50 +0000 (UTC) Received: from localhost ([127.0.0.1]:36134 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ggVpi-00016g-5W for patchwork-qemu-devel@patchwork.kernel.org; Mon, 07 Jan 2019 09:24:50 -0500 Received: from eggs.gnu.org ([209.51.188.92]:58359) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ggVoe-00006y-74 for qemu-devel@nongnu.org; Mon, 07 Jan 2019 09:23:46 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ggVoc-00071h-29 for qemu-devel@nongnu.org; Mon, 07 Jan 2019 09:23:44 -0500 Received: from smtp03.citrix.com ([162.221.156.55]:22663) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ggVoV-0006Im-94; Mon, 07 Jan 2019 09:23:37 -0500 X-IronPort-AV: E=Sophos;i="5.56,451,1539648000"; d="scan'208";a="74964878" From: Paul Durrant To: , , Date: Mon, 7 Jan 2019 14:12:56 +0000 Message-ID: <20190107141309.15774-6-paul.durrant@citrix.com> X-Mailer: git-send-email 2.20.1.2.gb21ebb6 In-Reply-To: <20190107141309.15774-1-paul.durrant@citrix.com> References: <20190107141309.15774-1-paul.durrant@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] [PATCH v8 05/18] 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 , Kevin Wolf , Paul Durrant , Stefano Stabellini , Max Reitz Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP 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 --- Cc: Kevin Wolf Cc: Max Reitz Cc: Stefano Stabellini v5: - Re-base v3: - Remove unnecessary instances of local_err v2: - Don't crash when xen_block_disconnect() fails - Check xs_unwatch() for error - Add new_watch() and free_watch() utility functions - Use xs_check_watch() rather than xs_read_watch() --- 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 7 14:12:57 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Durrant X-Patchwork-Id: 10750619 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 AF5821515 for ; Mon, 7 Jan 2019 14:19:41 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9B8A82897B for ; Mon, 7 Jan 2019 14:19:41 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 8CE6A289A5; Mon, 7 Jan 2019 14:19:41 +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 ED8052897B for ; Mon, 7 Jan 2019 14:19:40 +0000 (UTC) Received: from localhost ([127.0.0.1]:34736 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ggVki-0006gS-9u for patchwork-qemu-devel@patchwork.kernel.org; Mon, 07 Jan 2019 09:19:40 -0500 Received: from eggs.gnu.org ([209.51.188.92]:56615) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ggVjR-0005YV-CA for qemu-devel@nongnu.org; Mon, 07 Jan 2019 09:18:22 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ggVjP-0008OV-Vr for qemu-devel@nongnu.org; Mon, 07 Jan 2019 09:18:21 -0500 Received: from smtp03.citrix.com ([162.221.156.55]:22344) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ggVjP-0008Hn-Nr; Mon, 07 Jan 2019 09:18:19 -0500 X-IronPort-AV: E=Sophos;i="5.56,451,1539648000"; d="scan'208";a="74964902" From: Paul Durrant To: , , Date: Mon, 7 Jan 2019 14:12:57 +0000 Message-ID: <20190107141309.15774-7-paul.durrant@citrix.com> X-Mailer: git-send-email 2.20.1.2.gb21ebb6 In-Reply-To: <20190107141309.15774-1-paul.durrant@citrix.com> References: <20190107141309.15774-1-paul.durrant@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] [PATCH v8 06/18] 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 , Paul Durrant , Stefano Stabellini Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP 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 --- Cc: Stefano Stabellini --- 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 7 14:12:58 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Durrant X-Patchwork-Id: 10750635 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 7140A91E for ; Mon, 7 Jan 2019 14:27:06 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5F363289F8 for ; Mon, 7 Jan 2019 14:27:06 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5035D28A68; Mon, 7 Jan 2019 14:27: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 C01E0289F8 for ; Mon, 7 Jan 2019 14:27:05 +0000 (UTC) Received: from localhost ([127.0.0.1]:36801 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ggVrt-00034M-1X for patchwork-qemu-devel@patchwork.kernel.org; Mon, 07 Jan 2019 09:27:05 -0500 Received: from eggs.gnu.org ([209.51.188.92]:58281) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ggVob-0008WN-3p for qemu-devel@nongnu.org; Mon, 07 Jan 2019 09:23:42 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ggVoZ-0006vV-O1 for qemu-devel@nongnu.org; Mon, 07 Jan 2019 09:23:41 -0500 Received: from smtp03.citrix.com ([162.221.156.55]:22663) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ggVoZ-0006Im-DT; Mon, 07 Jan 2019 09:23:39 -0500 X-IronPort-AV: E=Sophos;i="5.56,451,1539648000"; d="scan'208";a="74964879" From: Paul Durrant To: , , Date: Mon, 7 Jan 2019 14:12:58 +0000 Message-ID: <20190107141309.15774-8-paul.durrant@citrix.com> X-Mailer: git-send-email 2.20.1.2.gb21ebb6 In-Reply-To: <20190107141309.15774-1-paul.durrant@citrix.com> References: <20190107141309.15774-1-paul.durrant@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] [PATCH v8 07/18] 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 , Paul Durrant , Stefano Stabellini Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP 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 --- Cc: Stefano Stabellini v2: - Added error pointers to notify and unbind --- hw/xen/xen-bus.c | 101 +++++++++++++++++++++++++++++++++++++++ include/hw/xen/xen-bus.h | 18 +++++++ 2 files changed, 119 insertions(+) diff --git a/hw/xen/xen-bus.c b/hw/xen/xen-bus.c index faa9fd3577..9443f27d44 100644 --- a/hw/xen/xen-bus.c +++ b/hw/xen/xen-bus.c @@ -617,6 +617,81 @@ done: g_free(xengnttab_segs); } +struct XenEventChannel { + unsigned int 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); + + channel->local_port = xenevtchn_bind_interdomain(xendev->xeh, + xendev->frontend_id, + port); + if (xendev->local_port < 0) { + error_setg_errno(errp, errno, "xenevtchn_bind_interdomain failed"); + + g_free(channel); + return NULL; + } + + 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 +716,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 +738,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 +788,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..f83a95cebd 100644 --- a/include/hw/xen/xen-bus.h +++ b/include/hw/xen/xen-bus.h @@ -26,6 +26,9 @@ typedef struct XenDevice { XenWatch *frontend_state_watch; xengnttab_handle *xgth; bool feature_grant_copy; + xenevtchn_handle *xeh; + xenevtchn_port_or_error_t local_port; + NotifierList event_notifiers; } XenDevice; typedef char *(*XenDeviceGetName)(XenDevice *xendev, Error **errp); @@ -104,4 +107,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 */ From patchwork Mon Jan 7 14:12:59 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Durrant X-Patchwork-Id: 10750631 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 43C0413B5 for ; Mon, 7 Jan 2019 14:25:47 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2DEAB28A5F for ; Mon, 7 Jan 2019 14:25:47 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2167F28A68; Mon, 7 Jan 2019 14:25: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 6894C28A5F for ; Mon, 7 Jan 2019 14:25:45 +0000 (UTC) Received: from localhost ([127.0.0.1]:36429 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ggVqa-0001zG-Jn for patchwork-qemu-devel@patchwork.kernel.org; Mon, 07 Jan 2019 09:25:44 -0500 Received: from eggs.gnu.org ([209.51.188.92]:58686) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ggVpE-0000jx-5S for qemu-devel@nongnu.org; Mon, 07 Jan 2019 09:24:23 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ggVp8-0008F2-Ja for qemu-devel@nongnu.org; Mon, 07 Jan 2019 09:24:19 -0500 Received: from smtp03.citrix.com ([162.221.156.55]:22705) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ggVp6-0008Db-IB; Mon, 07 Jan 2019 09:24:14 -0500 X-IronPort-AV: E=Sophos;i="5.56,451,1539648000"; d="scan'208";a="74964882" From: Paul Durrant To: , , Date: Mon, 7 Jan 2019 14:12:59 +0000 Message-ID: <20190107141309.15774-9-paul.durrant@citrix.com> X-Mailer: git-send-email 2.20.1.2.gb21ebb6 In-Reply-To: <20190107141309.15774-1-paul.durrant@citrix.com> References: <20190107141309.15774-1-paul.durrant@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] [PATCH v8 08/18] 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: Kevin Wolf , Stefano Stabellini , Max Reitz , Paul Durrant , Stefan Hajnoczi , Anthony Perard Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP 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 --- Cc: Stefano Stabellini Cc: Stefan Hajnoczi Cc: Kevin Wolf Cc: Max Reitz --- 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 38d6c3b973..f730d6c3cc 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 7 14:13:00 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Durrant X-Patchwork-Id: 10750659 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 1DEAB91E for ; Mon, 7 Jan 2019 14:36:38 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0BBE128A85 for ; Mon, 7 Jan 2019 14:36:38 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id F195028A8C; Mon, 7 Jan 2019 14:36:37 +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 CC39628A85 for ; Mon, 7 Jan 2019 14:36:36 +0000 (UTC) Received: from localhost ([127.0.0.1]:39263 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ggW15-0002Mz-Vs for patchwork-qemu-devel@patchwork.kernel.org; Mon, 07 Jan 2019 09:36:36 -0500 Received: from eggs.gnu.org ([209.51.188.92]:59094) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ggVqA-0001Vo-6a for qemu-devel@nongnu.org; Mon, 07 Jan 2019 09:25:20 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ggVq6-00009B-Dt for qemu-devel@nongnu.org; Mon, 07 Jan 2019 09:25:18 -0500 Received: from smtp03.citrix.com ([162.221.156.55]:22782) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ggVq5-0008Rw-0y; Mon, 07 Jan 2019 09:25:13 -0500 X-IronPort-AV: E=Sophos;i="5.56,451,1539648000"; d="scan'208";a="74964883" From: Paul Durrant To: , , Date: Mon, 7 Jan 2019 14:13:00 +0000 Message-ID: <20190107141309.15774-10-paul.durrant@citrix.com> X-Mailer: git-send-email 2.20.1.2.gb21ebb6 In-Reply-To: <20190107141309.15774-1-paul.durrant@citrix.com> References: <20190107141309.15774-1-paul.durrant@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] [PATCH v8 09/18] 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: Kevin Wolf , Stefano Stabellini , Max Reitz , Paul Durrant , Stefan Hajnoczi , Anthony Perard Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP 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 --- Cc: Stefano Stabellini Cc: Stefan Hajnoczi Cc: Kevin Wolf Cc: Max Reitz v6: - v5 was messed up so fix the boilerplate again - Drop Anthony's R-b so he can check it v2: - Leave existing boilerplate alone, other than removing the now-incorrect description --- 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 7 14:13:01 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Durrant X-Patchwork-Id: 10750649 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 8FE8F91E for ; Mon, 7 Jan 2019 14:31:12 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7A70828A80 for ; Mon, 7 Jan 2019 14:31:12 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6AF4F28A82; Mon, 7 Jan 2019 14:31:12 +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 2BFD428A80 for ; Mon, 7 Jan 2019 14:31:10 +0000 (UTC) Received: from localhost ([127.0.0.1]:38015 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ggVvq-0006oA-90 for patchwork-qemu-devel@patchwork.kernel.org; Mon, 07 Jan 2019 09:31:10 -0500 Received: from eggs.gnu.org ([209.51.188.92]:60520) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ggVuA-00053x-TD for qemu-devel@nongnu.org; Mon, 07 Jan 2019 09:29:28 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ggVu8-000361-V4 for qemu-devel@nongnu.org; Mon, 07 Jan 2019 09:29:26 -0500 Received: from smtp03.citrix.com ([162.221.156.55]:23137) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ggVu7-00034s-Ne; Mon, 07 Jan 2019 09:29:24 -0500 X-IronPort-AV: E=Sophos;i="5.56,451,1539648000"; d="scan'208";a="74966368" From: Paul Durrant To: , , Date: Mon, 7 Jan 2019 14:13:01 +0000 Message-ID: <20190107141309.15774-11-paul.durrant@citrix.com> X-Mailer: git-send-email 2.20.1.2.gb21ebb6 In-Reply-To: <20190107141309.15774-1-paul.durrant@citrix.com> References: <20190107141309.15774-1-paul.durrant@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] [PATCH v8 10/18] 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: Kevin Wolf , Stefano Stabellini , Max Reitz , Paul Durrant , Stefan Hajnoczi , Anthony Perard Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP 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 --- Cc: Stefan Hajnoczi Cc: Kevin Wolf Cc: Max Reitz Cc: Stefano Stabellini v2: - Tidy up header inclusions - Get rid of error_fatal --- 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 f730d6c3cc..aeac96401d 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 @@ err: 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 @@ err: 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 7 14:13:02 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Durrant X-Patchwork-Id: 10750705 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 EFB7113B5 for ; Mon, 7 Jan 2019 14:48:11 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D88CE28A82 for ; Mon, 7 Jan 2019 14:48:11 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id CA7D528A93; Mon, 7 Jan 2019 14:48: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 9C3D528A82 for ; Mon, 7 Jan 2019 14:48:09 +0000 (UTC) Received: from localhost ([127.0.0.1]:42168 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ggWCG-00020t-PS for patchwork-qemu-devel@patchwork.kernel.org; Mon, 07 Jan 2019 09:48:08 -0500 Received: from eggs.gnu.org ([209.51.188.92]:60641) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ggVuJ-0005CC-KF for qemu-devel@nongnu.org; Mon, 07 Jan 2019 09:29:38 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ggVuF-000383-P8 for qemu-devel@nongnu.org; Mon, 07 Jan 2019 09:29:35 -0500 Received: from smtp03.citrix.com ([162.221.156.55]:23137) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ggVuB-00034s-14; Mon, 07 Jan 2019 09:29:30 -0500 X-IronPort-AV: E=Sophos;i="5.56,451,1539648000"; d="scan'208";a="74966381" From: Paul Durrant To: , , Date: Mon, 7 Jan 2019 14:13:02 +0000 Message-ID: <20190107141309.15774-12-paul.durrant@citrix.com> X-Mailer: git-send-email 2.20.1.2.gb21ebb6 In-Reply-To: <20190107141309.15774-1-paul.durrant@citrix.com> References: <20190107141309.15774-1-paul.durrant@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] [PATCH v8 11/18] 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: Kevin Wolf , Stefano Stabellini , Max Reitz , Paul Durrant , Stefan Hajnoczi , Anthony Perard Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP 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 --- Cc: Stefano Stabellini Cc: Stefan Hajnoczi Cc: Kevin Wolf Cc: Max Reitz --- 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 @@ out: 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 @@ err: 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 @@ err: 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 7 14:13:03 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Durrant X-Patchwork-Id: 10750661 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 05A8991E for ; Mon, 7 Jan 2019 14:38:14 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E73B628A86 for ; Mon, 7 Jan 2019 14:38:13 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id DB45528A8E; Mon, 7 Jan 2019 14:38: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 A058E28A86 for ; Mon, 7 Jan 2019 14:38:12 +0000 (UTC) Received: from localhost ([127.0.0.1]:39608 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ggW2d-0003P5-SR for patchwork-qemu-devel@patchwork.kernel.org; Mon, 07 Jan 2019 09:38:11 -0500 Received: from eggs.gnu.org ([209.51.188.92]:60454) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ggVu3-0004vb-Fh for qemu-devel@nongnu.org; Mon, 07 Jan 2019 09:29:21 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ggVu1-00033I-9h for qemu-devel@nongnu.org; Mon, 07 Jan 2019 09:29:19 -0500 Received: from smtp03.citrix.com ([162.221.156.55]:23117) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ggVu0-00032v-Uu; Mon, 07 Jan 2019 09:29:17 -0500 X-IronPort-AV: E=Sophos;i="5.56,451,1539648000"; d="scan'208";a="74966337" From: Paul Durrant To: , , Date: Mon, 7 Jan 2019 14:13:03 +0000 Message-ID: <20190107141309.15774-13-paul.durrant@citrix.com> X-Mailer: git-send-email 2.20.1.2.gb21ebb6 In-Reply-To: <20190107141309.15774-1-paul.durrant@citrix.com> References: <20190107141309.15774-1-paul.durrant@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] [PATCH v8 12/18] 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: Kevin Wolf , Stefano Stabellini , Max Reitz , Paul Durrant , Stefan Hajnoczi , Anthony Perard Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP 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 --- Cc: Stefan Hajnoczi Cc: Stefano Stabellini Cc: Kevin Wolf Cc: Max Reitz --- 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 @@ done: 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 7 14:13:04 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Durrant X-Patchwork-Id: 10750703 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 B2B4313B5 for ; Mon, 7 Jan 2019 14:46:15 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9D39828716 for ; Mon, 7 Jan 2019 14:46:15 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 910F028A91; Mon, 7 Jan 2019 14:46:15 +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 9D1A428716 for ; Mon, 7 Jan 2019 14:46:14 +0000 (UTC) Received: from localhost ([127.0.0.1]:41741 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ggWAQ-0000z0-0x for patchwork-qemu-devel@patchwork.kernel.org; Mon, 07 Jan 2019 09:46:14 -0500 Received: from eggs.gnu.org ([209.51.188.92]:60589) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ggVuH-0005AX-Rr for qemu-devel@nongnu.org; Mon, 07 Jan 2019 09:29:35 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ggVuF-00037s-O6 for qemu-devel@nongnu.org; Mon, 07 Jan 2019 09:29:33 -0500 Received: from smtp03.citrix.com ([162.221.156.55]:23134) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ggVuA-00034N-RA; Mon, 07 Jan 2019 09:29:28 -0500 X-IronPort-AV: E=Sophos;i="5.56,451,1539648000"; d="scan'208";a="74966380" From: Paul Durrant To: , , Date: Mon, 7 Jan 2019 14:13:04 +0000 Message-ID: <20190107141309.15774-14-paul.durrant@citrix.com> X-Mailer: git-send-email 2.20.1.2.gb21ebb6 In-Reply-To: <20190107141309.15774-1-paul.durrant@citrix.com> References: <20190107141309.15774-1-paul.durrant@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] [PATCH v8 13/18] 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: Kevin Wolf , Stefano Stabellini , Max Reitz , Paul Durrant , Stefan Hajnoczi , Anthony Perard Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP 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 --- Cc: Stefano Stabellini Cc: Stefan Hajnoczi Cc: Kevin Wolf Cc: Max Reitz v2: - Add 'xen_block_' prefix --- 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 @@ out: 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 @@ err: 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 @@ done: 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 7 14:13:05 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Durrant X-Patchwork-Id: 10750685 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 058FE91E for ; Mon, 7 Jan 2019 14:41:39 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E68DC28A3F for ; Mon, 7 Jan 2019 14:41:38 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D735928A8E; Mon, 7 Jan 2019 14:41:38 +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 9079A28A3F for ; Mon, 7 Jan 2019 14:41:37 +0000 (UTC) Received: from localhost ([127.0.0.1]:40517 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ggW5w-00069p-Sz for patchwork-qemu-devel@patchwork.kernel.org; Mon, 07 Jan 2019 09:41:36 -0500 Received: from eggs.gnu.org ([209.51.188.92]:60553) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ggVuF-00058Y-On for qemu-devel@nongnu.org; Mon, 07 Jan 2019 09:29:34 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ggVuA-00036X-Qg for qemu-devel@nongnu.org; Mon, 07 Jan 2019 09:29:30 -0500 Received: from smtp03.citrix.com ([162.221.156.55]:23117) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ggVu2-00032v-Iq; Mon, 07 Jan 2019 09:29:18 -0500 X-IronPort-AV: E=Sophos;i="5.56,451,1539648000"; d="scan'208";a="74966353" From: Paul Durrant To: , , Date: Mon, 7 Jan 2019 14:13:05 +0000 Message-ID: <20190107141309.15774-15-paul.durrant@citrix.com> X-Mailer: git-send-email 2.20.1.2.gb21ebb6 In-Reply-To: <20190107141309.15774-1-paul.durrant@citrix.com> References: <20190107141309.15774-1-paul.durrant@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] [PATCH v8 14/18] 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 , Kevin Wolf , Paul Durrant , Stefano Stabellini , Max Reitz Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP ...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 --- Cc: Stefano Stabellini Cc: Kevin Wolf Cc: Max Reitz v5: - Re-base v3: - Add missing return statement to xen_block_realize() - Set device name to 'vbd' now the backend is functional - Add an unplug handler - Move backend watch code from subsequent patch since it's now needed to handle unplug v2: - Tidy up header inclusions - Stop leaking ring_ref on error - Auto-create drive for CDRom devices --- 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 9443f27d44..a22aa49921 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 @@ fail: 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) @@ -822,9 +959,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 f83a95cebd..0834cb3a7e 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; @@ -84,6 +86,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 7 14:13:06 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Durrant X-Patchwork-Id: 10750645 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 CD94113BF for ; Mon, 7 Jan 2019 14:30:18 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B98CF28A80 for ; Mon, 7 Jan 2019 14:30:18 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id ACA2D28A82; Mon, 7 Jan 2019 14:30: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 A495B28A80 for ; Mon, 7 Jan 2019 14:30:17 +0000 (UTC) Received: from localhost ([127.0.0.1]:37768 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ggVuy-0005wk-Uh for patchwork-qemu-devel@patchwork.kernel.org; Mon, 07 Jan 2019 09:30:17 -0500 Received: from eggs.gnu.org ([209.51.188.92]:60301) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ggVtZ-0004XA-Aj for qemu-devel@nongnu.org; Mon, 07 Jan 2019 09:28:51 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ggVtU-0002rf-0j for qemu-devel@nongnu.org; Mon, 07 Jan 2019 09:28:49 -0500 Received: from smtp03.citrix.com ([162.221.156.55]:23081) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ggVtT-0002pY-DL; Mon, 07 Jan 2019 09:28:43 -0500 X-IronPort-AV: E=Sophos;i="5.56,451,1539648000"; d="scan'208";a="74966322" From: Paul Durrant To: , , Date: Mon, 7 Jan 2019 14:13:06 +0000 Message-ID: <20190107141309.15774-16-paul.durrant@citrix.com> X-Mailer: git-send-email 2.20.1.2.gb21ebb6 In-Reply-To: <20190107141309.15774-1-paul.durrant@citrix.com> References: <20190107141309.15774-1-paul.durrant@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] [PATCH v8 15/18] 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 , Paul Durrant , Stefano Stabellini Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP ...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 --- Cc: Stefano Stabellini v5: - Added destructor function, therefore Anthony's R-b is not carried from v4 v3: - Use a xenstore transaction in enumeration code to ensure consistent parameters - Not adding Anthony's R-b because of change v2: - Sort out error paths and error reporting --- 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 a22aa49921..f90bcf2342 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 0834cb3a7e..e55a5de5f1 100644 --- a/include/hw/xen/xen-bus.h +++ b/include/hw/xen/xen-bus.h @@ -65,6 +65,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 7 14:13:07 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Durrant X-Patchwork-Id: 10750657 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 628EB91E for ; Mon, 7 Jan 2019 14:34:37 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 501BC28A7D for ; Mon, 7 Jan 2019 14:34:37 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 427AD28A81; Mon, 7 Jan 2019 14:34:37 +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 518D228A7D for ; Mon, 7 Jan 2019 14:34:36 +0000 (UTC) Received: from localhost ([127.0.0.1]:38813 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ggVz9-0000tF-3u for patchwork-qemu-devel@patchwork.kernel.org; Mon, 07 Jan 2019 09:34:35 -0500 Received: from eggs.gnu.org ([209.51.188.92]:60550) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ggVuF-00058V-OF for qemu-devel@nongnu.org; Mon, 07 Jan 2019 09:29:33 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ggVuA-00036S-QJ for qemu-devel@nongnu.org; Mon, 07 Jan 2019 09:29:30 -0500 Received: from smtp03.citrix.com ([162.221.156.55]:23117) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ggVu3-00032v-Bn; Mon, 07 Jan 2019 09:29:19 -0500 X-IronPort-AV: E=Sophos;i="5.56,451,1539648000"; d="scan'208";a="74966357" From: Paul Durrant To: , , Date: Mon, 7 Jan 2019 14:13:07 +0000 Message-ID: <20190107141309.15774-17-paul.durrant@citrix.com> X-Mailer: git-send-email 2.20.1.2.gb21ebb6 In-Reply-To: <20190107141309.15774-1-paul.durrant@citrix.com> References: <20190107141309.15774-1-paul.durrant@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] [PATCH v8 16/18] 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 , Kevin Wolf , Paul Durrant , Stefano Stabellini , Max Reitz Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP 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 --- Cc: Anthony Perard Cc: Kevin Wolf Cc: Max Reitz Cc: Stefano Stabellini v8: - Add 'raw' image layer for raw images v7: - Don't use qobject_input_visitor_new_flat_confused() v5: - Extensively re-worked to avoid using drive_new() and use qmp_blockdev_add() instead - Also use qmp_object_add() for IOThread - Dropped Anthony's R-b because of the code changes v2: - Get rid of error_abort - Don't use qdev_init_nofail() - Explain why file locking needs to be off --- hw/block/trace-events | 4 + hw/block/xen-block.c | 399 ++++++++++++++++++++++++++++++++++++ hw/xen/xen-legacy-backend.c | 1 - include/hw/xen/xen-block.h | 13 ++ 4 files changed, 416 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..91f5b58993 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,393 @@ 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) +{ + while (drive->layers-- != 0) { + char *node_name = drive->node_name[drive->layers]; + Error *local_err = NULL; + + xen_block_blockdev_del(node_name, &local_err); + if (local_err) { + error_propagate(errp, local_err); + drive->layers++; + return; + } + } + g_free(drive->id); + g_free(drive); +} + +static void xen_block_drive_layer_add(XenBlockDrive *drive, QDict *qdict, + Error **errp) +{ + unsigned int i = drive->layers; + char *node_name; + + g_assert(drive->layers < ARRAY_SIZE(drive->node_name)); + + if (i != 0) { + /* Link to the lower layer */ + qdict_put_str(qdict, "file", drive->node_name[i - 1]); + } + + node_name = xen_block_blockdev_add(drive->id, qdict, errp); + if (!node_name) { + return; + } + + drive->node_name[i] = node_name; + drive->layers++; +} + +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 *qdict; + + 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); + + qdict = qdict_new(); + + qdict_put_str(qdict, "driver", "file"); + qdict_put_str(qdict, "filename", filename); + + if (mode && *mode != 'w') { + qdict_put_bool(qdict, "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(qdict, "cache", QOBJECT(cache_qdict)); + + qdict_put_str(qdict, "aio", "native"); + } + } + + if (discard_enable) { + unsigned long value; + + if (!qemu_strtoul(discard_enable, NULL, 2, &value) && !!value) { + qdict_put_str(qdict, "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(qdict, "locking", "off"); + + xen_block_drive_layer_add(drive, qdict, &local_err); + qobject_unref(qdict); + + if (local_err) { + error_propagate(errp, local_err); + goto done; + } + + qdict = qdict_new(); + + qdict_put_str(qdict, "driver", driver); + + xen_block_drive_layer_add(drive, qdict, &local_err); + qobject_unref(qdict); + +done: + g_free(driver); + g_free(filename); + + if (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->layers ? drive->node_name[drive->layers - 1] : ""; +} + +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..6f5d675edb 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,24 @@ typedef struct XenBlockProperties { IOThread *iothread; } XenBlockProperties; +typedef struct XenBlockDrive { + char *id; + char *node_name[2]; + unsigned int layers; +} 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 7 14:13:08 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Durrant X-Patchwork-Id: 10750683 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 9562914E5 for ; Mon, 7 Jan 2019 14:41:30 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 854F428A3F for ; Mon, 7 Jan 2019 14:41:30 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7968328A8E; Mon, 7 Jan 2019 14:41:30 +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 0E53728A3F for ; Mon, 7 Jan 2019 14:41:29 +0000 (UTC) Received: from localhost ([127.0.0.1]:40476 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ggW5o-00062G-Eq for patchwork-qemu-devel@patchwork.kernel.org; Mon, 07 Jan 2019 09:41:28 -0500 Received: from eggs.gnu.org ([209.51.188.92]:60587) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ggVuH-0005AS-RO for qemu-devel@nongnu.org; Mon, 07 Jan 2019 09:29:34 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ggVuF-00038B-PY for qemu-devel@nongnu.org; Mon, 07 Jan 2019 09:29:33 -0500 Received: from smtp03.citrix.com ([162.221.156.55]:23146) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ggVuB-00035f-5S; Mon, 07 Jan 2019 09:29:30 -0500 X-IronPort-AV: E=Sophos;i="5.56,451,1539648000"; d="scan'208";a="74966392" From: Paul Durrant To: , , Date: Mon, 7 Jan 2019 14:13:08 +0000 Message-ID: <20190107141309.15774-18-paul.durrant@citrix.com> X-Mailer: git-send-email 2.20.1.2.gb21ebb6 In-Reply-To: <20190107141309.15774-1-paul.durrant@citrix.com> References: <20190107141309.15774-1-paul.durrant@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] [PATCH v8 17/18] 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 , Paolo Bonzini , Paul Durrant , Stefano Stabellini Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP 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 --- Cc: Paolo Bonzini v2: - Fix typo --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index aeac96401d..02df9765df 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 7 14:13:09 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Durrant X-Patchwork-Id: 10750655 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 0690313BF for ; Mon, 7 Jan 2019 14:33:37 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E5461286C5 for ; Mon, 7 Jan 2019 14:33:36 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D670F28A82; Mon, 7 Jan 2019 14:33: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 2C9A228A81 for ; Mon, 7 Jan 2019 14:33:35 +0000 (UTC) Received: from localhost ([127.0.0.1]:38588 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ggVyA-0008Ry-En for patchwork-qemu-devel@patchwork.kernel.org; Mon, 07 Jan 2019 09:33:34 -0500 Received: from eggs.gnu.org ([209.51.188.92]:60640) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ggVuJ-0005CB-Jm for qemu-devel@nongnu.org; Mon, 07 Jan 2019 09:29:38 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ggVuF-00037k-NQ for qemu-devel@nongnu.org; Mon, 07 Jan 2019 09:29:35 -0500 Received: from smtp03.citrix.com ([162.221.156.55]:23134) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ggVu5-00034N-7X; Mon, 07 Jan 2019 09:29:22 -0500 X-IronPort-AV: E=Sophos;i="5.56,451,1539648000"; d="scan'208";a="74966367" From: Paul Durrant To: , , Date: Mon, 7 Jan 2019 14:13:09 +0000 Message-ID: <20190107141309.15774-19-paul.durrant@citrix.com> X-Mailer: git-send-email 2.20.1.2.gb21ebb6 In-Reply-To: <20190107141309.15774-1-paul.durrant@citrix.com> References: <20190107141309.15774-1-paul.durrant@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] [PATCH v8 18/18] 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 , Kevin Wolf , Paul Durrant , Stefano Stabellini , Max Reitz Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP This backend has now been replaced by the 'xen-qdisk' XenDevice. Signed-off-by: Paul Durrant Acked-by: Anthony Perard --- Cc: Kevin Wolf Cc: Max Reitz Cc: Stefano Stabellini --- 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 75fe55f2ae..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(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, -};