qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Kevin Wolf <kwolf@redhat.com>
To: anthony@codemonkey.ws
Cc: kwolf@redhat.com, qemu-devel@nongnu.org
Subject: [Qemu-devel] [PATCH 10/20] scsi-disk: lazily allocate bounce buffer
Date: Tue, 20 Sep 2011 13:11:42 +0200	[thread overview]
Message-ID: <1316517112-9908-11-git-send-email-kwolf@redhat.com> (raw)
In-Reply-To: <1316517112-9908-1-git-send-email-kwolf@redhat.com>

From: Paolo Bonzini <pbonzini@redhat.com>

It will not be needed for reads and writes if the HBA provides a sglist.
In addition, this lets scsi-disk refuse commands with an excessive
allocation length, as well as limit memory on usual well-behaved guests.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 hw/scsi-disk.c |   44 +++++++++++++++++++++++++++++++++-----------
 1 files changed, 33 insertions(+), 11 deletions(-)

diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 84e8662..48abe49 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -55,6 +55,7 @@ typedef struct SCSIDiskReq {
     /* Both sector and sector_count are in terms of qemu 512 byte blocks.  */
     uint64_t sector;
     uint32_t sector_count;
+    uint32_t buflen;
     struct iovec iov;
     QEMUIOVector qiov;
     uint32_t status;
@@ -78,13 +79,15 @@ struct SCSIDiskState
 };
 
 static int scsi_handle_rw_error(SCSIDiskReq *r, int error, int type);
-static int scsi_disk_emulate_command(SCSIDiskReq *r, uint8_t *outbuf);
+static int scsi_disk_emulate_command(SCSIDiskReq *r);
 
 static void scsi_free_request(SCSIRequest *req)
 {
     SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
 
-    qemu_vfree(r->iov.iov_base);
+    if (r->iov.iov_base) {
+        qemu_vfree(r->iov.iov_base);
+    }
 }
 
 /* Helper function for command completion with sense.  */
@@ -110,7 +113,13 @@ static void scsi_cancel_io(SCSIRequest *req)
 
 static uint32_t scsi_init_iovec(SCSIDiskReq *r)
 {
-    r->iov.iov_len = MIN(r->sector_count * 512, SCSI_DMA_BUF_SIZE);
+    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
+
+    if (!r->iov.iov_base) {
+        r->buflen = SCSI_DMA_BUF_SIZE;
+        r->iov.iov_base = qemu_blockalign(s->bs, r->buflen);
+    }
+    r->iov.iov_len = MIN(r->sector_count * 512, r->buflen);
     qemu_iovec_init_external(&r->qiov, &r->iov, 1);
     return r->qiov.size / 512;
 }
@@ -323,7 +332,7 @@ static void scsi_dma_restart_bh(void *opaque)
                 scsi_write_data(&r->req);
                 break;
             case SCSI_REQ_STATUS_RETRY_FLUSH:
-                ret = scsi_disk_emulate_command(r, r->iov.iov_base);
+                ret = scsi_disk_emulate_command(r);
                 if (ret == 0) {
                     scsi_req_complete(&r->req, GOOD);
                 }
@@ -838,13 +847,31 @@ static int scsi_disk_emulate_start_stop(SCSIDiskReq *r)
     return 0;
 }
 
-static int scsi_disk_emulate_command(SCSIDiskReq *r, uint8_t *outbuf)
+static int scsi_disk_emulate_command(SCSIDiskReq *r)
 {
     SCSIRequest *req = &r->req;
     SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
     uint64_t nb_sectors;
+    uint8_t *outbuf;
     int buflen = 0;
 
+    if (!r->iov.iov_base) {
+        /*
+         * FIXME: we shouldn't return anything bigger than 4k, but the code
+         * requires the buffer to be as big as req->cmd.xfer in several
+         * places.  So, do not allow CDBs with a very large ALLOCATION
+         * LENGTH.  The real fix would be to modify scsi_read_data and
+         * dma_buf_read, so that they return data beyond the buflen
+         * as all zeros.
+         */
+        if (req->cmd.xfer > 65536) {
+            goto illegal_request;
+        }
+        r->buflen = MAX(4096, req->cmd.xfer);
+        r->iov.iov_base = qemu_blockalign(s->bs, r->buflen);
+    }
+
+    outbuf = r->iov.iov_base;
     switch (req->cmd.buf[0]) {
     case TEST_UNIT_READY:
         if (s->tray_open || !bdrv_is_inserted(s->bs))
@@ -995,11 +1022,9 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
     SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
     int32_t len;
     uint8_t command;
-    uint8_t *outbuf;
     int rc;
 
     command = buf[0];
-    outbuf = (uint8_t *)r->iov.iov_base;
     DPRINTF("Command: lun=%d tag=0x%x data=0x%02x", req->lun, req->tag, buf[0]);
 
 #ifdef DEBUG_SCSI
@@ -1028,7 +1053,7 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
     case GET_CONFIGURATION:
     case SERVICE_ACTION_IN_16:
     case VERIFY_10:
-        rc = scsi_disk_emulate_command(r, outbuf);
+        rc = scsi_disk_emulate_command(r);
         if (rc < 0) {
             return 0;
         }
@@ -1279,11 +1304,8 @@ static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag,
 {
     SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
     SCSIRequest *req;
-    SCSIDiskReq *r;
 
     req = scsi_req_alloc(&scsi_disk_reqops, &s->qdev, tag, lun, hba_private);
-    r = DO_UPCAST(SCSIDiskReq, req, req);
-    r->iov.iov_base = qemu_blockalign(s->bs, SCSI_DMA_BUF_SIZE);
     return req;
 }
 
-- 
1.7.6.2

  parent reply	other threads:[~2011-09-20 11:09 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-09-20 11:11 [Qemu-devel] [PULL 00/20] Block patches Kevin Wolf
2011-09-20 11:11 ` [Qemu-devel] [PATCH 01/20] nbd: support feature negotiation Kevin Wolf
2011-09-20 11:11 ` [Qemu-devel] [PATCH 02/20] nbd: sync API definitions with upstream Kevin Wolf
2011-09-20 11:11 ` [Qemu-devel] [PATCH 03/20] nbd: support NBD_SET_FLAGS ioctl Kevin Wolf
2011-09-20 11:11 ` [Qemu-devel] [PATCH 04/20] raw-posix: Fix bdrv_flush error return values Kevin Wolf
2011-09-20 11:11 ` [Qemu-devel] [PATCH 05/20] scsi-generic: do not disable FUA Kevin Wolf
2011-09-20 11:11 ` [Qemu-devel] [PATCH 06/20] dma-helpers: rename is_write to to_dev Kevin Wolf
2011-09-20 11:11 ` [Qemu-devel] [PATCH 07/20] dma-helpers: allow including from target-independent code Kevin Wolf
2011-09-20 11:11 ` [Qemu-devel] [PATCH 08/20] dma-helpers: rewrite completion/cancellation Kevin Wolf
2011-09-20 11:11 ` [Qemu-devel] [PATCH 09/20] scsi-disk: commonize iovec creation between reads and writes Kevin Wolf
2011-09-20 11:11 ` Kevin Wolf [this message]
2011-09-20 11:11 ` [Qemu-devel] [PATCH 11/20] VMDK: fix leak of extent_file Kevin Wolf
2011-09-20 11:11 ` [Qemu-devel] [PATCH 12/20] posix-aio-compat: Removed unused offset variable Kevin Wolf
2011-09-20 11:11 ` [Qemu-devel] [PATCH 13/20] AHCI Port Interrupt Enable register cleaning on soft reset Kevin Wolf
2011-09-20 11:11 ` [Qemu-devel] [PATCH 14/20] rbd: ignore failures when reading from default conf location Kevin Wolf
2011-09-20 11:11 ` [Qemu-devel] [PATCH 15/20] rbd: update comment heading Kevin Wolf
2011-09-20 11:11 ` [Qemu-devel] [PATCH 16/20] rbd: call flush, if available Kevin Wolf
2011-09-20 11:11 ` [Qemu-devel] [PATCH 17/20] scsi: fix sign extension problems Kevin Wolf
2011-09-20 11:11 ` [Qemu-devel] [PATCH 18/20] block: avoid SIGUSR2 Kevin Wolf
2011-09-20 11:11 ` [Qemu-devel] [PATCH 19/20] linux-aio: remove process requests callback Kevin Wolf
2011-09-20 11:11 ` [Qemu-devel] [PATCH 20/20] rbd: allow escaping in config string Kevin Wolf
2011-09-20 20:39 ` [Qemu-devel] [PULL 00/20] Block patches Anthony Liguori

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1316517112-9908-11-git-send-email-kwolf@redhat.com \
    --to=kwolf@redhat.com \
    --cc=anthony@codemonkey.ws \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).