From patchwork Fri May 3 02:45:22 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: pingfan liu X-Patchwork-Id: 241138 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 847EF2C009C for ; Fri, 3 May 2013 12:47:07 +1000 (EST) Received: from localhost ([::1]:57209 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UY61Z-0001ql-Mp for incoming@patchwork.ozlabs.org; Thu, 02 May 2013 22:47:05 -0400 Received: from eggs.gnu.org ([208.118.235.92]:39087) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UY60w-0001kv-Vq for qemu-devel@nongnu.org; Thu, 02 May 2013 22:46:28 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1UY60v-0002V6-C7 for qemu-devel@nongnu.org; Thu, 02 May 2013 22:46:26 -0400 Received: from mail-da0-x230.google.com ([2607:f8b0:400e:c00::230]:57147) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UY60u-0002Uu-W1 for qemu-devel@nongnu.org; Thu, 02 May 2013 22:46:25 -0400 Received: by mail-da0-f48.google.com with SMTP id h32so589395dak.35 for ; Thu, 02 May 2013 19:46:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=x-received:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references; bh=7Zy0oVZFwXu7E0obkQbNFqfVFq+OYkCUqnARQFrt88g=; b=y2ZY7kGVDEhCIePb3PLmYpSWFBHYH98Pryis003tdp6XFdiQy8Ah7MsXn7KF+X4MMt DD1NjXs0Haglm5NpjXKbkcdyls3lTZ9qE54BTshD3dc+MwaNIygXsVdi0JCCJGl6gPzP 7qHV4d8XxM8UjP33AJYbqmpmdItgUFoaGihAHgWdYW/ytFoj8PfUNUUZ9oBcd7EJpyrk M3Vrx9V60S/BpJBD/0VvhkQOnamNFIyJeYDcRmmwXEuwR6aX3aLTQQ4nMaAACwbkH0Pf x1A2kPZTaYFJimzV1GD0lw7nWBDL5eynI4agS3DawqNhXmRRiS0fGf1IWlJdSYLFqsNK OtQQ== X-Received: by 10.68.184.132 with SMTP id eu4mr11843376pbc.87.1367549184000; Thu, 02 May 2013 19:46:24 -0700 (PDT) Received: from localhost ([111.192.242.37]) by mx.google.com with ESMTPSA id cq1sm9637866pbc.13.2013.05.02.19.46.19 for (version=TLSv1.1 cipher=RC4-SHA bits=128/128); Thu, 02 May 2013 19:46:23 -0700 (PDT) From: Liu Ping Fan To: qemu-devel@nongnu.org Date: Fri, 3 May 2013 10:45:22 +0800 Message-Id: <1367549122-2948-7-git-send-email-qemulist@gmail.com> X-Mailer: git-send-email 1.7.4.4 In-Reply-To: <1367549122-2948-1-git-send-email-qemulist@gmail.com> References: <1367549122-2948-1-git-send-email-qemulist@gmail.com> X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2607:f8b0:400e:c00::230 Cc: Peter Maydell , Anthony Liguori , Jan Kiszka , Vasilis Liaskovitis , Stefan Hajnoczi , Paolo Bonzini Subject: [Qemu-devel] [PATCH v2 6/6] virtio-blk: release reference to RAM's memoryRegion X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: Liu Ping Fan virtio-blk will unref RAM's memoryRegion when the io-req has been done. So we can avoid to call bdrv_drain_all() when RAM hot unplug. Signed-off-by: Liu Ping Fan --- hw/block/dataplane/virtio-blk.c | 51 +++++++++++++++++++++++++++++--------- 1 files changed, 39 insertions(+), 12 deletions(-) diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c index 3bb57d1..047e1df 100644 --- a/hw/block/dataplane/virtio-blk.c +++ b/hw/block/dataplane/virtio-blk.c @@ -35,6 +35,8 @@ enum { typedef struct { struct iocb iocb; /* Linux AIO control block */ + MemoryRegion *mrs[VRING_MAX]; + int mrs_cnt; QEMUIOVector *inhdr; /* iovecs for virtio_blk_inhdr */ unsigned int head; /* vring descriptor index */ struct iovec *bounce_iov; /* used if guest buffers are unaligned */ @@ -121,6 +123,10 @@ static void complete_request(struct iocb *iocb, ssize_t ret, void *opaque) * transferred plus the status bytes. */ vring_push(&s->vring, req->head, len + sizeof(hdr)); + while (--req->mrs_cnt >= 0) { + memory_region_unref(req->mrs[req->mrs_cnt]); + } + s->num_reqs--; } @@ -156,7 +162,8 @@ static void do_get_id_cmd(VirtIOBlockDataPlane *s, static int do_rdwr_cmd(VirtIOBlockDataPlane *s, bool read, struct iovec *iov, unsigned int iov_cnt, long long offset, unsigned int head, - QEMUIOVector *inhdr) + QEMUIOVector *inhdr, + MemoryRegion **mrs, int cnt) { struct iocb *iocb; QEMUIOVector qiov; @@ -188,6 +195,8 @@ static int do_rdwr_cmd(VirtIOBlockDataPlane *s, bool read, /* Fill in virtio block metadata needed for completion */ VirtIOBlockRequest *req = container_of(iocb, VirtIOBlockRequest, iocb); + memcpy(req->mrs, mrs, cnt*sizeof(MemoryRegion *)); + req->mrs_cnt = cnt; req->head = head; req->inhdr = inhdr; req->bounce_iov = bounce_iov; @@ -197,19 +206,22 @@ static int do_rdwr_cmd(VirtIOBlockDataPlane *s, bool read, static int process_request(IOQueue *ioq, struct iovec iov[], unsigned int out_num, unsigned int in_num, - unsigned int head) + unsigned int head, MemoryRegion **mrs) { VirtIOBlockDataPlane *s = container_of(ioq, VirtIOBlockDataPlane, ioqueue); struct iovec *in_iov = &iov[out_num]; struct virtio_blk_outhdr outhdr; QEMUIOVector *inhdr; size_t in_size; + unsigned int i, cnt = out_num+in_num; + int ret; /* Copy in outhdr */ if (unlikely(iov_to_buf(iov, out_num, 0, &outhdr, sizeof(outhdr)) != sizeof(outhdr))) { error_report("virtio-blk request outhdr too short"); - return -EFAULT; + ret = -EFAULT; + goto free_mrs; } iov_discard_front(&iov, &out_num, sizeof(outhdr)); @@ -217,7 +229,8 @@ static int process_request(IOQueue *ioq, struct iovec iov[], in_size = iov_size(in_iov, in_num); if (in_size < sizeof(struct virtio_blk_inhdr)) { error_report("virtio_blk request inhdr too short"); - return -EFAULT; + ret = -EFAULT; + goto free_mrs; } inhdr = g_slice_new(QEMUIOVector); qemu_iovec_init(inhdr, 1); @@ -231,17 +244,20 @@ static int process_request(IOQueue *ioq, struct iovec iov[], switch (outhdr.type) { case VIRTIO_BLK_T_IN: - do_rdwr_cmd(s, true, in_iov, in_num, outhdr.sector * 512, head, inhdr); + do_rdwr_cmd(s, true, in_iov, in_num, outhdr.sector * 512, head, inhdr, + mrs, cnt); return 0; case VIRTIO_BLK_T_OUT: - do_rdwr_cmd(s, false, iov, out_num, outhdr.sector * 512, head, inhdr); + do_rdwr_cmd(s, false, iov, out_num, outhdr.sector * 512, head, inhdr, + mrs, cnt); return 0; case VIRTIO_BLK_T_SCSI_CMD: /* TODO support SCSI commands */ complete_request_early(s, head, inhdr, VIRTIO_BLK_S_UNSUPP); - return 0; + ret = 0; + goto free_mrs; case VIRTIO_BLK_T_FLUSH: /* TODO fdsync not supported by Linux AIO, do it synchronously here! */ @@ -250,18 +266,27 @@ static int process_request(IOQueue *ioq, struct iovec iov[], } else { complete_request_early(s, head, inhdr, VIRTIO_BLK_S_OK); } - return 0; + ret = 0; + goto free_mrs; case VIRTIO_BLK_T_GET_ID: do_get_id_cmd(s, in_iov, in_num, head, inhdr); - return 0; + ret = 0; + goto free_mrs; default: error_report("virtio-blk unsupported request type %#x", outhdr.type); qemu_iovec_destroy(inhdr); g_slice_free(QEMUIOVector, inhdr); - return -EFAULT; + ret = -EFAULT; + goto free_mrs; + } + +free_mrs: + for (i = 0; i < cnt; i++) { + memory_region_unref(mrs[i]); } + return ret; } static int flush_true(EventNotifier *e) @@ -287,6 +312,7 @@ static void handle_notify(EventNotifier *e) struct iovec iovec[VRING_MAX]; struct iovec *end = &iovec[VRING_MAX]; struct iovec *iov = iovec; + MemoryRegion *mrs[VRING_MAX]; /* When a request is read from the vring, the index of the first descriptor * (aka head) is returned so that the completed request can be pushed onto @@ -306,7 +332,7 @@ static void handle_notify(EventNotifier *e) for (;;) { head = vring_pop(s->vdev, &s->vring, iov, end, &out_num, - &in_num, NULL); + &in_num, mrs); if (head < 0) { break; /* no more requests */ } @@ -314,7 +340,8 @@ static void handle_notify(EventNotifier *e) trace_virtio_blk_data_plane_process_request(s, out_num, in_num, head); - if (process_request(&s->ioqueue, iov, out_num, in_num, head) < 0) { + if (process_request(&s->ioqueue, iov, out_num, in_num, head, + mrs) < 0) { vring_set_broken(&s->vring); break; }