From patchwork Mon Nov 22 10:15:35 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hannes Reinecke X-Patchwork-Id: 72543 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 36452B7106 for ; Mon, 22 Nov 2010 22:20:21 +1100 (EST) Received: from localhost ([127.0.0.1]:43663 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PKTxF-0006DE-Gh for incoming@patchwork.ozlabs.org; Mon, 22 Nov 2010 05:49:01 -0500 Received: from [140.186.70.92] (port=48065 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PKTOX-00029m-JH for qemu-devel@nongnu.org; Mon, 22 Nov 2010 05:13:34 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1PKTOM-00019X-0j for qemu-devel@nongnu.org; Mon, 22 Nov 2010 05:13:09 -0500 Received: from cantor2.suse.de ([195.135.220.15]:58122 helo=mx2.suse.de) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1PKTOL-00018c-Mp for qemu-devel@nongnu.org; Mon, 22 Nov 2010 05:12:57 -0500 Received: from relay2.suse.de (charybdis-ext.suse.de [195.135.221.2]) by mx2.suse.de (Postfix) with ESMTP id 162DD8891E; Mon, 22 Nov 2010 11:12:56 +0100 (CET) Date: Mon, 22 Nov 2010 11:15:35 +0100 To: qemu-devel@nongnu.org User-Agent: Heirloom mailx 12.2 01/07/07 MIME-Version: 1.0 Message-Id: <20101122101536.2B09BF90AF@ochil.suse.de> From: hare@suse.de (Hannes Reinecke) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.4-2.6 Cc: stefanha@gmail.com, nab@linux-iscsi.org, kraxel@redhat.com Subject: [Qemu-devel] [PATCH] scsi: Implement alloc_req_iov callback X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Add callback to create a request with a predefined iovec. This is required for drivers which can use the iovec of a command directly. Signed-off-by: Hannes Reinecke --- hw/scsi-disk.c | 25 +++++++++++++++++++++---- hw/scsi-generic.c | 44 ++++++++++++++++++++++++++++++++++---------- hw/scsi.h | 2 ++ 3 files changed, 57 insertions(+), 14 deletions(-) diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index d1b7f74..88a2f74 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -96,14 +96,30 @@ static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, return req; } +static SCSIRequest *scsi_new_request_iovec(SCSIDevice *d, uint32_t tag, + uint32_t lun, struct iovec *iov, int iov_num) +{ + SCSIRequest *req; + SCSIDiskReq *r; + + req = scsi_req_alloc(sizeof(SCSIDiskReq), d, tag, lun); + r = DO_UPCAST(SCSIDiskReq, req, req); + r->iov = iov; + r->iov_num = iov_num; + r->iov_buf = NULL; + return req; +} + static void scsi_remove_request(SCSIRequest *req) { SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req); - qemu_vfree(r->iov); - r->iov = NULL; - qemu_vfree(r->iov_buf); - r->iov_buf = NULL; + if (r->iov_buf) { + qemu_vfree(r->iov); + r->iov = NULL; + qemu_vfree(r->iov_buf); + r->iov_buf = NULL; + } scsi_req_free(&r->req); } @@ -1207,6 +1223,7 @@ static SCSIDeviceInfo scsi_disk_info = { .init = scsi_disk_initfn, .destroy = scsi_destroy, .alloc_req = scsi_new_request, + .alloc_req_iov = scsi_new_request_iovec, .free_req = scsi_remove_request, .send_command = scsi_send_command, .read_data = scsi_read_data, diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c index 5c0f6ab..7d30115 100644 --- a/hw/scsi-generic.c +++ b/hw/scsi-generic.c @@ -107,6 +107,25 @@ static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun) return req; } +static SCSIRequest *scsi_new_request_iovec(SCSIDevice *d, uint32_t tag, + uint32_t lun, struct iovec *iov, int iov_num) +{ + SCSIRequest *req; + SCSIGenericReq *r; + int i; + + req = scsi_req_alloc(sizeof(SCSIGenericReq), d, tag, lun); + r = DO_UPCAST(SCSIGenericReq, req, req); + r->io_header.dxferp = iov; + r->io_header.iovec_count = iov_num; + r->io_header.dxfer_len = 0; + for (i = 0; i < iov_num; i++) + r->io_header.dxfer_len += iov[i].iov_len; + r->buf = NULL; + r->buflen = 0; + return req; +} + static void scsi_remove_request(SCSIRequest *req) { SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req); @@ -179,8 +198,10 @@ static int execute_command(BlockDriverState *bdrv, r->io_header.interface_id = 'S'; r->io_header.dxfer_direction = direction; - r->io_header.dxferp = r->buf; - r->io_header.dxfer_len = r->buflen; + if (r->buf) { + r->io_header.dxferp = r->buf; + r->io_header.dxfer_len = r->buflen; + } r->io_header.cmdp = r->req.cmd.buf; r->io_header.cmd_len = r->req.cmd.len; r->io_header.mx_sb_len = sizeof(s->sensebuf); @@ -286,7 +307,7 @@ static int scsi_write_data(SCSIRequest *req) DPRINTF("scsi_write_data 0x%x\n", req->tag); - if (r->len == 0) { + if (r->len == 0 && r->io_header.dxfer_len == 0) { r->len = r->buflen; r->req.bus->complete(&r->req, SCSI_REASON_DATA, r->len); return 0; @@ -380,14 +401,16 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd) return 0; } - if (r->buflen != r->req.cmd.xfer) { - if (r->buf != NULL) - qemu_free(r->buf); - r->buf = qemu_malloc(r->req.cmd.xfer); - r->buflen = r->req.cmd.xfer; - } + if (!r->io_header.iovec_count) { + if (r->buflen != r->req.cmd.xfer) { + if (r->buf != NULL) + qemu_free(r->buf); + r->buf = qemu_malloc(r->req.cmd.xfer); + r->buflen = r->req.cmd.xfer; + } - memset(r->buf, 0, r->buflen); + memset(r->buf, 0, r->buflen); + } r->len = r->req.cmd.xfer; if (r->req.cmd.mode == SCSI_XFER_TO_DEV) { r->len = 0; @@ -560,6 +583,7 @@ static SCSIDeviceInfo scsi_generic_info = { .init = scsi_generic_initfn, .destroy = scsi_destroy, .alloc_req = scsi_new_request, + .alloc_req_iov = scsi_new_request_iovec, .free_req = scsi_remove_request, .send_command = scsi_send_command, .read_data = scsi_read_data, diff --git a/hw/scsi.h b/hw/scsi.h index 0c467d1..538ae54 100644 --- a/hw/scsi.h +++ b/hw/scsi.h @@ -72,6 +72,8 @@ struct SCSIDeviceInfo { scsi_qdev_initfn init; void (*destroy)(SCSIDevice *s); SCSIRequest *(*alloc_req)(SCSIDevice *s, uint32_t tag, uint32_t lun); + SCSIRequest *(*alloc_req_iov)(SCSIDevice *s, uint32_t tag, uint32_t lun, + struct iovec *iov, int iov_num); void (*free_req)(SCSIRequest *req); int32_t (*send_command)(SCSIRequest *req, uint8_t *buf); void (*read_data)(SCSIRequest *req);