diff mbox

[06/10] scsi: prepare migration code for usb-storage support

Message ID 1337939061-13629-7-git-send-email-kraxel@redhat.com
State New
Headers show

Commit Message

Gerd Hoffmann May 25, 2012, 9:44 a.m. UTC
usb-storage can't handle requests in one go as the data transfer can be
splitted into lots of usb packets.  Because of that there can be
normal in-flight requests at savevm time and we need to handle that.
With other scsi hba's this happens only in case i/o is stopped due to
errors and there are pending requests which need to be restarted
(req->retry = true).

So, first we need to save req->retry and then handle the req->retry =
false case.  Write requests are handled fine already.  For read requests
we have to save the buffer as we will not restart the request (and thus
not refill the buffer) on the target host.

Cc: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/scsi-bus.c  |    8 ++++----
 hw/scsi-disk.c |   13 +++++++++++--
 2 files changed, 15 insertions(+), 6 deletions(-)

Comments

Paolo Bonzini May 25, 2012, 9:51 a.m. UTC | #1
Il 25/05/2012 11:44, Gerd Hoffmann ha scritto:
> usb-storage can't handle requests in one go as the data transfer can be
> splitted into lots of usb packets.  Because of that there can be
> normal in-flight requests at savevm time and we need to handle that.
> With other scsi hba's this happens only in case i/o is stopped due to
> errors and there are pending requests which need to be restarted
> (req->retry = true).
> 
> So, first we need to save req->retry and then handle the req->retry =
> false case.  Write requests are handled fine already.  For read requests
> we have to save the buffer as we will not restart the request (and thus
> not refill the buffer) on the target host.
> 
> Cc: Paolo Bonzini <pbonzini@redhat.com>
> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> ---
>  hw/scsi-bus.c  |    8 ++++----
>  hw/scsi-disk.c |   13 +++++++++++--
>  2 files changed, 15 insertions(+), 6 deletions(-)
> 
> diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
> index 8ab9bcd..92b8176 100644
> --- a/hw/scsi-bus.c
> +++ b/hw/scsi-bus.c
> @@ -1507,10 +1507,9 @@ static void put_scsi_requests(QEMUFile *f, void *pv, size_t size)
>      QTAILQ_FOREACH(req, &s->requests, next) {
>          assert(!req->io_canceled);
>          assert(req->status == -1);
> -        assert(req->retry);
>          assert(req->enqueued);
>  
> -        qemu_put_sbyte(f, 1);
> +        qemu_put_sbyte(f, req->retry ? 1 : 2);
>          qemu_put_buffer(f, req->cmd.buf, sizeof(req->cmd.buf));
>          qemu_put_be32s(f, &req->tag);
>          qemu_put_be32s(f, &req->lun);
> @@ -1528,8 +1527,9 @@ static int get_scsi_requests(QEMUFile *f, void *pv, size_t size)
>  {
>      SCSIDevice *s = pv;
>      SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, s->qdev.parent_bus);
> +    int8_t sbyte;
>  
> -    while (qemu_get_sbyte(f)) {
> +    while ((sbyte = qemu_get_sbyte(f)) > 0) {
>          uint8_t buf[SCSI_CMD_BUF_SIZE];
>          uint32_t tag;
>          uint32_t lun;
> @@ -1539,6 +1539,7 @@ static int get_scsi_requests(QEMUFile *f, void *pv, size_t size)
>          qemu_get_be32s(f, &tag);
>          qemu_get_be32s(f, &lun);
>          req = scsi_req_new(s, tag, lun, buf, NULL);
> +        req->retry = (sbyte == 1);
>          if (bus->info->load_request) {
>              req->hba_private = bus->info->load_request(f, req);
>          }
> @@ -1547,7 +1548,6 @@ static int get_scsi_requests(QEMUFile *f, void *pv, size_t size)
>          }
>  
>          /* Just restart it later.  */
> -        req->retry = true;
>          scsi_req_enqueue_internal(req);
>  
>          /* At this point, the request will be kept alive by the reference
> diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
> index 045c764..4fd39ff 100644
> --- a/hw/scsi-disk.c
> +++ b/hw/scsi-disk.c
> @@ -132,8 +132,13 @@ static void scsi_disk_save_request(QEMUFile *f, SCSIRequest *req)
>      qemu_put_be64s(f, &r->sector);
>      qemu_put_be32s(f, &r->sector_count);
>      qemu_put_be32s(f, &r->buflen);
> -    if (r->buflen && r->req.cmd.mode == SCSI_XFER_TO_DEV) {
> -        qemu_put_buffer(f, r->iov.iov_base, r->iov.iov_len);
> +    if (r->buflen) {
> +        if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
> +            qemu_put_buffer(f, r->iov.iov_base, r->iov.iov_len);
> +        } else if (!req->retry) {
> +            qemu_put_be64s(f, &r->iov.iov_len);
> +            qemu_put_buffer(f, r->iov.iov_base, r->iov.iov_len);
> +        }
>      }
>  }
>  
> @@ -148,6 +153,10 @@ static void scsi_disk_load_request(QEMUFile *f, SCSIRequest *req)
>          scsi_init_iovec(r, r->buflen);
>          if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
>              qemu_get_buffer(f, r->iov.iov_base, r->iov.iov_len);
> +        } else if (!r->req.retry) {
> +            qemu_get_be64s(f, &r->iov.iov_len);
> +            assert(r->iov.iov_len <= r->buflen);
> +            qemu_get_buffer(f, r->iov.iov_base, r->iov.iov_len);
>          }
>      }
>  

Acked-by: Paolo Bonzini <pbonzini@redhat.com>

Feel free to push this to Anthony yourself
.

Paolo
diff mbox

Patch

diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 8ab9bcd..92b8176 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -1507,10 +1507,9 @@  static void put_scsi_requests(QEMUFile *f, void *pv, size_t size)
     QTAILQ_FOREACH(req, &s->requests, next) {
         assert(!req->io_canceled);
         assert(req->status == -1);
-        assert(req->retry);
         assert(req->enqueued);
 
-        qemu_put_sbyte(f, 1);
+        qemu_put_sbyte(f, req->retry ? 1 : 2);
         qemu_put_buffer(f, req->cmd.buf, sizeof(req->cmd.buf));
         qemu_put_be32s(f, &req->tag);
         qemu_put_be32s(f, &req->lun);
@@ -1528,8 +1527,9 @@  static int get_scsi_requests(QEMUFile *f, void *pv, size_t size)
 {
     SCSIDevice *s = pv;
     SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, s->qdev.parent_bus);
+    int8_t sbyte;
 
-    while (qemu_get_sbyte(f)) {
+    while ((sbyte = qemu_get_sbyte(f)) > 0) {
         uint8_t buf[SCSI_CMD_BUF_SIZE];
         uint32_t tag;
         uint32_t lun;
@@ -1539,6 +1539,7 @@  static int get_scsi_requests(QEMUFile *f, void *pv, size_t size)
         qemu_get_be32s(f, &tag);
         qemu_get_be32s(f, &lun);
         req = scsi_req_new(s, tag, lun, buf, NULL);
+        req->retry = (sbyte == 1);
         if (bus->info->load_request) {
             req->hba_private = bus->info->load_request(f, req);
         }
@@ -1547,7 +1548,6 @@  static int get_scsi_requests(QEMUFile *f, void *pv, size_t size)
         }
 
         /* Just restart it later.  */
-        req->retry = true;
         scsi_req_enqueue_internal(req);
 
         /* At this point, the request will be kept alive by the reference
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 045c764..4fd39ff 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -132,8 +132,13 @@  static void scsi_disk_save_request(QEMUFile *f, SCSIRequest *req)
     qemu_put_be64s(f, &r->sector);
     qemu_put_be32s(f, &r->sector_count);
     qemu_put_be32s(f, &r->buflen);
-    if (r->buflen && r->req.cmd.mode == SCSI_XFER_TO_DEV) {
-        qemu_put_buffer(f, r->iov.iov_base, r->iov.iov_len);
+    if (r->buflen) {
+        if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
+            qemu_put_buffer(f, r->iov.iov_base, r->iov.iov_len);
+        } else if (!req->retry) {
+            qemu_put_be64s(f, &r->iov.iov_len);
+            qemu_put_buffer(f, r->iov.iov_base, r->iov.iov_len);
+        }
     }
 }
 
@@ -148,6 +153,10 @@  static void scsi_disk_load_request(QEMUFile *f, SCSIRequest *req)
         scsi_init_iovec(r, r->buflen);
         if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
             qemu_get_buffer(f, r->iov.iov_base, r->iov.iov_len);
+        } else if (!r->req.retry) {
+            qemu_get_be64s(f, &r->iov.iov_len);
+            assert(r->iov.iov_len <= r->buflen);
+            qemu_get_buffer(f, r->iov.iov_base, r->iov.iov_len);
         }
     }