qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 1/2] Stop VM on error in scsi-disk
@ 2009-01-22 13:31 Gleb Natapov
  2009-01-22 13:31 ` [Qemu-devel] [PATCH 2/2] Stop VM on error in virtio-blk Gleb Natapov
  2009-01-22 19:54 ` [Qemu-devel] [PATCH 1/2] Stop VM on error in scsi-disk Anthony Liguori
  0 siblings, 2 replies; 3+ messages in thread
From: Gleb Natapov @ 2009-01-22 13:31 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Gleb Natapov <gleb@redhat.com>
---

 hw/scsi-disk.c |   86 +++++++++++++++++++++++++++++++++++++++++++++-----------
 vl.c           |    4 +--
 2 files changed, 71 insertions(+), 19 deletions(-)

diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 744573e..9eda2f6 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -42,6 +42,8 @@ do { fprintf(stderr, "scsi-disk: " fmt , ##args); } while (0)
 #define SCSI_DMA_BUF_SIZE    131072
 #define SCSI_MAX_INQUIRY_LEN 256
 
+#define SCSI_REQ_STATUS_RETRY 0x01
+
 typedef struct SCSIRequest {
     SCSIDeviceState *dev;
     uint32_t tag;
@@ -55,6 +57,7 @@ typedef struct SCSIRequest {
     uint8_t *dma_buf;
     BlockDriverAIOCB *aiocb;
     struct SCSIRequest *next;
+    uint32_t status;
 } SCSIRequest;
 
 struct SCSIDeviceState
@@ -92,6 +95,7 @@ static SCSIRequest *scsi_new_request(SCSIDeviceState *s, uint32_t tag)
     r->sector_count = 0;
     r->buf_len = 0;
     r->aiocb = NULL;
+    r->status = 0;
 
     r->next = s->requests;
     s->requests = r;
@@ -212,18 +216,42 @@ static void scsi_read_data(SCSIDevice *d, uint32_t tag)
     r->sector_count -= n;
 }
 
+static int scsi_handle_write_error(SCSIRequest *r, int error)
+{
+    BlockInterfaceErrorAction action = drive_get_onerror(r->dev->bdrv);
+
+    if (action == BLOCK_ERR_IGNORE)
+        return 0;
+
+    if ((error == ENOSPC && action == BLOCK_ERR_STOP_ENOSPC)
+            || action == BLOCK_ERR_STOP_ANY) {
+        r->status |= SCSI_REQ_STATUS_RETRY;
+        vm_stop(0);
+    } else {
+        scsi_command_complete(r, STATUS_CHECK_CONDITION,
+                SENSE_HARDWARE_ERROR);
+    }
+
+    return 1;
+}
+
 static void scsi_write_complete(void * opaque, int ret)
 {
     SCSIRequest *r = (SCSIRequest *)opaque;
     SCSIDeviceState *s = r->dev;
     uint32_t len;
+    uint32_t n;
+
+    r->aiocb = NULL;
 
     if (ret) {
-        fprintf(stderr, "scsi-disc: IO write error\n");
-        exit(1);
+        if (scsi_handle_write_error(r, -ret))
+            return;
     }
 
-    r->aiocb = NULL;
+    n = r->buf_len / 512;
+    r->sector += n;
+    r->sector_count -= n;
     if (r->sector_count == 0) {
         scsi_command_complete(r, STATUS_GOOD, SENSE_NO_SENSE);
     } else {
@@ -237,13 +265,30 @@ static void scsi_write_complete(void * opaque, int ret)
     }
 }
 
+static void scsi_write_request(SCSIRequest *r)
+{
+    SCSIDeviceState *s = r->dev;
+    uint32_t n;
+
+    n = r->buf_len / 512;
+    if (n) {
+        r->aiocb = bdrv_aio_write(s->bdrv, r->sector, r->dma_buf, n,
+                                  scsi_write_complete, r);
+        if (r->aiocb == NULL)
+            scsi_command_complete(r, STATUS_CHECK_CONDITION,
+                                  SENSE_HARDWARE_ERROR);
+    } else {
+        /* Invoke completion routine to fetch data from host.  */
+        scsi_write_complete(r, 0);
+    }
+}
+
 /* Write data to a scsi device.  Returns nonzero on failure.
    The transfer may complete asynchronously.  */
 static int scsi_write_data(SCSIDevice *d, uint32_t tag)
 {
     SCSIDeviceState *s = d->state;
     SCSIRequest *r;
-    uint32_t n;
 
     DPRINTF("Write data tag=0x%x\n", tag);
     r = scsi_find_request(s, tag);
@@ -252,25 +297,31 @@ static int scsi_write_data(SCSIDevice *d, uint32_t tag)
         scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_HARDWARE_ERROR);
         return 1;
     }
+
     if (r->aiocb)
         BADF("Data transfer already in progress\n");
-    n = r->buf_len / 512;
-    if (n) {
-        r->aiocb = bdrv_aio_write(s->bdrv, r->sector, r->dma_buf, n,
-                                  scsi_write_complete, r);
-        if (r->aiocb == NULL)
-            scsi_command_complete(r, STATUS_CHECK_CONDITION,
-                                  SENSE_HARDWARE_ERROR);
-        r->sector += n;
-        r->sector_count -= n;
-    } else {
-        /* Invoke completion routine to fetch data from host.  */
-        scsi_write_complete(r, 0);
-    }
+
+    scsi_write_request(r);
 
     return 0;
 }
 
+static void scsi_dma_restart_cb(void *opaque, int running)
+{
+    SCSIDeviceState *s = opaque;
+    SCSIRequest *r = s->requests;
+    if (!running)
+        return;
+
+    while (r) {
+        if (r->status & SCSI_REQ_STATUS_RETRY) {
+            r->status &= ~SCSI_REQ_STATUS_RETRY;
+            scsi_write_request(r); 
+        }
+        r = r->next;
+    }
+}
+
 /* Return a pointer to the data buffer.  */
 static uint8_t *scsi_get_buf(SCSIDevice *d, uint32_t tag)
 {
@@ -822,6 +873,7 @@ SCSIDevice *scsi_disk_init(BlockDriverState *bdrv, int tcq,
             sizeof(s->drive_serial_str));
     if (strlen(s->drive_serial_str) == 0)
         pstrcpy(s->drive_serial_str, sizeof(s->drive_serial_str), "0");
+    qemu_add_vm_change_state_handler(scsi_dma_restart_cb, s);
     d = (SCSIDevice *)qemu_mallocz(sizeof(SCSIDevice));
     d->state = s;
     d->destroy = scsi_destroy;
diff --git a/vl.c b/vl.c
index 045b09f..a325c81 100644
--- a/vl.c
+++ b/vl.c
@@ -2432,8 +2432,8 @@ static int drive_init(struct drive_opt *arg, int snapshot,
 
     onerror = BLOCK_ERR_REPORT;
     if (get_param_value(buf, sizeof(serial), "werror", str)) {
-        if (type != IF_IDE) {
-            fprintf(stderr, "werror is supported only by IDE\n");
+        if (type != IF_IDE && type != IF_SCSI) {
+            fprintf(stderr, "werror is no supported by this format\n");
             return -1;
         }
         if (!strcmp(buf, "ignore"))

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [Qemu-devel] [PATCH 2/2] Stop VM on error in virtio-blk.
  2009-01-22 13:31 [Qemu-devel] [PATCH 1/2] Stop VM on error in scsi-disk Gleb Natapov
@ 2009-01-22 13:31 ` Gleb Natapov
  2009-01-22 19:54 ` [Qemu-devel] [PATCH 1/2] Stop VM on error in scsi-disk Anthony Liguori
  1 sibling, 0 replies; 3+ messages in thread
From: Gleb Natapov @ 2009-01-22 13:31 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Gleb Natapov <gleb@redhat.com>
---

 hw/virtio-blk.c |  170 ++++++++++++++++++++++++++++++++++++++++---------------
 vl.c            |    2 -
 2 files changed, 125 insertions(+), 47 deletions(-)

diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index e654cc5..b5ac467 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -11,6 +11,8 @@
  *
  */
 
+#include <qemu-common.h>
+#include <sysemu.h>
 #include "virtio-blk.h"
 #include "block_int.h"
 
@@ -19,6 +21,7 @@ typedef struct VirtIOBlock
     VirtIODevice vdev;
     BlockDriverState *bs;
     VirtQueue *vq;
+    void *rq;
 } VirtIOBlock;
 
 static VirtIOBlock *to_virtio_blk(VirtIODevice *vdev)
@@ -34,12 +37,44 @@ typedef struct VirtIOBlockReq
     struct virtio_blk_outhdr *out;
     size_t size;
     uint8_t *buffer;
+    struct VirtIOBlockReq *next;
 } VirtIOBlockReq;
 
+static void virtio_blk_req_complete(VirtIOBlockReq *req, int status)
+{
+    VirtIOBlock *s = req->dev;
+
+    req->in->status = status;
+    virtqueue_push(s->vq, &req->elem, req->size + sizeof(*req->in));
+    virtio_notify(&s->vdev, s->vq);
+
+    qemu_free(req->buffer);
+    qemu_free(req);
+}
+
+static int virtio_blk_handle_write_error(VirtIOBlockReq *req, int error)
+{
+    BlockInterfaceErrorAction action = drive_get_onerror(req->dev->bs);
+    VirtIOBlock *s = req->dev;
+
+    if (action == BLOCK_ERR_IGNORE)
+        return 0;
+
+    if ((error == ENOSPC && action == BLOCK_ERR_STOP_ENOSPC)
+            || action == BLOCK_ERR_STOP_ANY) {
+        req->next = s->rq;
+        s->rq = req;
+        vm_stop(0);
+    } else {
+        virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR);
+    }
+
+    return 1;
+}
+
 static void virtio_blk_rw_complete(void *opaque, int ret)
 {
     VirtIOBlockReq *req = opaque;
-    VirtIOBlock *s = req->dev;
 
     /* Copy read data to the guest */
     if (!ret && !(req->out->type & VIRTIO_BLK_T_OUT)) {
@@ -58,33 +93,71 @@ static void virtio_blk_rw_complete(void *opaque, int ret)
                    len);
             offset += len;
         }
+    } else if (ret && (req->out->type & VIRTIO_BLK_T_OUT)) {
+        if (virtio_blk_handle_write_error(req, -ret))
+            return;
     }
 
-    req->in->status = ret ? VIRTIO_BLK_S_IOERR : VIRTIO_BLK_S_OK;
-    virtqueue_push(s->vq, &req->elem, req->size + sizeof(*req->in));
-    virtio_notify(&s->vdev, s->vq);
+    virtio_blk_req_complete(req, VIRTIO_BLK_S_OK);
+}
 
-    qemu_free(req->buffer);
-    qemu_free(req);
+static VirtIOBlockReq *virtio_blk_alloc_request(VirtIOBlock *s)
+{
+    VirtIOBlockReq *req = qemu_mallocz(sizeof(*req));
+    if (req != NULL)
+        req->dev = s;
+    return req;
 }
 
 static VirtIOBlockReq *virtio_blk_get_request(VirtIOBlock *s)
 {
-    VirtIOBlockReq *req;
+    VirtIOBlockReq *req = virtio_blk_alloc_request(s);
 
-    req = qemu_mallocz(sizeof(*req));
-    if (req == NULL)
-        return NULL;
-
-    req->dev = s;
-    if (!virtqueue_pop(s->vq, &req->elem)) {
-        qemu_free(req);
-        return NULL;
+    if (req != NULL) {
+        if (!virtqueue_pop(s->vq, &req->elem)) {
+            qemu_free(req);
+            return NULL;
+        }
     }
 
     return req;
 }
 
+static int virtio_blk_handle_write(VirtIOBlockReq *req)
+{
+    if (!req->buffer) {
+        size_t offset = 0;
+        int i;
+
+        for (i = 1; i < req->elem.out_num; i++)
+            req->size += req->elem.out_sg[i].iov_len;
+
+        req->buffer = qemu_memalign(512, req->size);
+        if (req->buffer == NULL) {
+            qemu_free(req);
+            return -1;
+        }
+
+        /* We copy the data from the SG list to avoid splitting up the request.
+           This helps performance a lot until we can pass full sg lists as AIO
+           operations */
+        for (i = 1; i < req->elem.out_num; i++) {
+            size_t len;
+
+            len = MIN(req->elem.out_sg[i].iov_len,
+                    req->size - offset);
+            memcpy(req->buffer + offset,
+                    req->elem.out_sg[i].iov_base,
+                    len);
+            offset += len;
+        }
+    }
+
+    bdrv_aio_write(req->dev->bs, req->out->sector, req->buffer, req->size / 512,
+            virtio_blk_rw_complete, req);
+    return 0;
+}
+
 static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq)
 {
     VirtIOBlock *s = to_virtio_blk(vdev);
@@ -115,36 +188,8 @@ static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq)
             virtio_notify(vdev, vq);
             qemu_free(req);
         } else if (req->out->type & VIRTIO_BLK_T_OUT) {
-            size_t offset;
-
-            for (i = 1; i < req->elem.out_num; i++)
-                req->size += req->elem.out_sg[i].iov_len;
-
-            req->buffer = qemu_memalign(512, req->size);
-            if (req->buffer == NULL) {
-                qemu_free(req);
+            if (virtio_blk_handle_write(req) < 0)
                 break;
-            }
-
-            /* We copy the data from the SG list to avoid splitting up the request.  This helps
-               performance a lot until we can pass full sg lists as AIO operations */
-            offset = 0;
-            for (i = 1; i < req->elem.out_num; i++) {
-                size_t len;
-
-                len = MIN(req->elem.out_sg[i].iov_len,
-                          req->size - offset);
-                memcpy(req->buffer + offset,
-                       req->elem.out_sg[i].iov_base,
-                       len);
-                offset += len;
-            }
-
-            bdrv_aio_write(s->bs, req->out->sector,
-                           req->buffer,
-                           req->size / 512,
-                           virtio_blk_rw_complete,
-                           req);
         } else {
             for (i = 0; i < req->elem.in_num - 1; i++)
                 req->size += req->elem.in_sg[i].iov_len;
@@ -169,6 +214,22 @@ static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq)
      */
 }
 
+static void virtio_blk_dma_restart_cb(void *opaque, int running)
+{
+    VirtIOBlock *s = opaque;
+    VirtIOBlockReq *req = s->rq;
+
+    if (!running)
+        return;
+
+    s->rq = NULL;
+
+    while (req) {
+        virtio_blk_handle_write(req);
+        req = req->next;
+    }
+}
+
 static void virtio_blk_reset(VirtIODevice *vdev)
 {
     /*
@@ -203,17 +264,32 @@ static uint32_t virtio_blk_get_features(VirtIODevice *vdev)
 static void virtio_blk_save(QEMUFile *f, void *opaque)
 {
     VirtIOBlock *s = opaque;
+    VirtIOBlockReq *req = s->rq;
+
     virtio_save(&s->vdev, f);
+    
+    while (req) {
+        qemu_put_sbyte(f, 1);
+        qemu_put_buffer(f, (unsigned char*)&req->elem, sizeof(req->elem));
+        req = req->next;
+    }
+    qemu_put_sbyte(f, 0);
 }
 
 static int virtio_blk_load(QEMUFile *f, void *opaque, int version_id)
 {
     VirtIOBlock *s = opaque;
 
-    if (version_id != 1)
+    if (version_id != 2)
         return -EINVAL;
 
     virtio_load(&s->vdev, f);
+    while (qemu_get_sbyte(f)) {
+        VirtIOBlockReq *req = virtio_blk_alloc_request(s);
+        qemu_get_buffer(f, (unsigned char*)&req->elem, sizeof(req->elem));
+        req->next = s->rq;
+        s->rq = req->next;
+    }
 
     return 0;
 }
@@ -237,12 +313,14 @@ void *virtio_blk_init(PCIBus *bus, BlockDriverState *bs)
     s->vdev.get_features = virtio_blk_get_features;
     s->vdev.reset = virtio_blk_reset;
     s->bs = bs;
+    s->rq = NULL;
     bdrv_guess_geometry(s->bs, &cylinders, &heads, &secs);
     bdrv_set_geometry_hint(s->bs, cylinders, heads, secs);
 
     s->vq = virtio_add_queue(&s->vdev, 128, virtio_blk_handle_output);
 
-    register_savevm("virtio-blk", virtio_blk_id++, 1,
+    qemu_add_vm_change_state_handler(virtio_blk_dma_restart_cb, s);
+    register_savevm("virtio-blk", virtio_blk_id++, 2,
                     virtio_blk_save, virtio_blk_load, s);
 
     return s;
diff --git a/vl.c b/vl.c
index a325c81..32f3cfb 100644
--- a/vl.c
+++ b/vl.c
@@ -2432,7 +2432,7 @@ static int drive_init(struct drive_opt *arg, int snapshot,
 
     onerror = BLOCK_ERR_REPORT;
     if (get_param_value(buf, sizeof(serial), "werror", str)) {
-        if (type != IF_IDE && type != IF_SCSI) {
+        if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO) {
             fprintf(stderr, "werror is no supported by this format\n");
             return -1;
         }

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [Qemu-devel] [PATCH 1/2] Stop VM on error in scsi-disk
  2009-01-22 13:31 [Qemu-devel] [PATCH 1/2] Stop VM on error in scsi-disk Gleb Natapov
  2009-01-22 13:31 ` [Qemu-devel] [PATCH 2/2] Stop VM on error in virtio-blk Gleb Natapov
@ 2009-01-22 19:54 ` Anthony Liguori
  1 sibling, 0 replies; 3+ messages in thread
From: Anthony Liguori @ 2009-01-22 19:54 UTC (permalink / raw)
  To: qemu-devel

Gleb Natapov wrote:
> Signed-off-by: Gleb Natapov <gleb@redhat.com>
>   

Applied both.  Thanks.

Regards,

Anthony Liguori

> ---
>
>  hw/scsi-disk.c |   86 +++++++++++++++++++++++++++++++++++++++++++++-----------
>  vl.c           |    4 +--
>  2 files changed, 71 insertions(+), 19 deletions(-)
>
> diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
> index 744573e..9eda2f6 100644
> --- a/hw/scsi-disk.c
> +++ b/hw/scsi-disk.c
> @@ -42,6 +42,8 @@ do { fprintf(stderr, "scsi-disk: " fmt , ##args); } while (0)
>  #define SCSI_DMA_BUF_SIZE    131072
>  #define SCSI_MAX_INQUIRY_LEN 256
>  
> +#define SCSI_REQ_STATUS_RETRY 0x01
> +
>  typedef struct SCSIRequest {
>      SCSIDeviceState *dev;
>      uint32_t tag;
> @@ -55,6 +57,7 @@ typedef struct SCSIRequest {
>      uint8_t *dma_buf;
>      BlockDriverAIOCB *aiocb;
>      struct SCSIRequest *next;
> +    uint32_t status;
>  } SCSIRequest;
>  
>  struct SCSIDeviceState
> @@ -92,6 +95,7 @@ static SCSIRequest *scsi_new_request(SCSIDeviceState *s, uint32_t tag)
>      r->sector_count = 0;
>      r->buf_len = 0;
>      r->aiocb = NULL;
> +    r->status = 0;
>  
>      r->next = s->requests;
>      s->requests = r;
> @@ -212,18 +216,42 @@ static void scsi_read_data(SCSIDevice *d, uint32_t tag)
>      r->sector_count -= n;
>  }
>  
> +static int scsi_handle_write_error(SCSIRequest *r, int error)
> +{
> +    BlockInterfaceErrorAction action = drive_get_onerror(r->dev->bdrv);
> +
> +    if (action == BLOCK_ERR_IGNORE)
> +        return 0;
> +
> +    if ((error == ENOSPC && action == BLOCK_ERR_STOP_ENOSPC)
> +            || action == BLOCK_ERR_STOP_ANY) {
> +        r->status |= SCSI_REQ_STATUS_RETRY;
> +        vm_stop(0);
> +    } else {
> +        scsi_command_complete(r, STATUS_CHECK_CONDITION,
> +                SENSE_HARDWARE_ERROR);
> +    }
> +
> +    return 1;
> +}
> +
>  static void scsi_write_complete(void * opaque, int ret)
>  {
>      SCSIRequest *r = (SCSIRequest *)opaque;
>      SCSIDeviceState *s = r->dev;
>      uint32_t len;
> +    uint32_t n;
> +
> +    r->aiocb = NULL;
>  
>      if (ret) {
> -        fprintf(stderr, "scsi-disc: IO write error\n");
> -        exit(1);
> +        if (scsi_handle_write_error(r, -ret))
> +            return;
>      }
>  
> -    r->aiocb = NULL;
> +    n = r->buf_len / 512;
> +    r->sector += n;
> +    r->sector_count -= n;
>      if (r->sector_count == 0) {
>          scsi_command_complete(r, STATUS_GOOD, SENSE_NO_SENSE);
>      } else {
> @@ -237,13 +265,30 @@ static void scsi_write_complete(void * opaque, int ret)
>      }
>  }
>  
> +static void scsi_write_request(SCSIRequest *r)
> +{
> +    SCSIDeviceState *s = r->dev;
> +    uint32_t n;
> +
> +    n = r->buf_len / 512;
> +    if (n) {
> +        r->aiocb = bdrv_aio_write(s->bdrv, r->sector, r->dma_buf, n,
> +                                  scsi_write_complete, r);
> +        if (r->aiocb == NULL)
> +            scsi_command_complete(r, STATUS_CHECK_CONDITION,
> +                                  SENSE_HARDWARE_ERROR);
> +    } else {
> +        /* Invoke completion routine to fetch data from host.  */
> +        scsi_write_complete(r, 0);
> +    }
> +}
> +
>  /* Write data to a scsi device.  Returns nonzero on failure.
>     The transfer may complete asynchronously.  */
>  static int scsi_write_data(SCSIDevice *d, uint32_t tag)
>  {
>      SCSIDeviceState *s = d->state;
>      SCSIRequest *r;
> -    uint32_t n;
>  
>      DPRINTF("Write data tag=0x%x\n", tag);
>      r = scsi_find_request(s, tag);
> @@ -252,25 +297,31 @@ static int scsi_write_data(SCSIDevice *d, uint32_t tag)
>          scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_HARDWARE_ERROR);
>          return 1;
>      }
> +
>      if (r->aiocb)
>          BADF("Data transfer already in progress\n");
> -    n = r->buf_len / 512;
> -    if (n) {
> -        r->aiocb = bdrv_aio_write(s->bdrv, r->sector, r->dma_buf, n,
> -                                  scsi_write_complete, r);
> -        if (r->aiocb == NULL)
> -            scsi_command_complete(r, STATUS_CHECK_CONDITION,
> -                                  SENSE_HARDWARE_ERROR);
> -        r->sector += n;
> -        r->sector_count -= n;
> -    } else {
> -        /* Invoke completion routine to fetch data from host.  */
> -        scsi_write_complete(r, 0);
> -    }
> +
> +    scsi_write_request(r);
>  
>      return 0;
>  }
>  
> +static void scsi_dma_restart_cb(void *opaque, int running)
> +{
> +    SCSIDeviceState *s = opaque;
> +    SCSIRequest *r = s->requests;
> +    if (!running)
> +        return;
> +
> +    while (r) {
> +        if (r->status & SCSI_REQ_STATUS_RETRY) {
> +            r->status &= ~SCSI_REQ_STATUS_RETRY;
> +            scsi_write_request(r); 
> +        }
> +        r = r->next;
> +    }
> +}
> +
>  /* Return a pointer to the data buffer.  */
>  static uint8_t *scsi_get_buf(SCSIDevice *d, uint32_t tag)
>  {
> @@ -822,6 +873,7 @@ SCSIDevice *scsi_disk_init(BlockDriverState *bdrv, int tcq,
>              sizeof(s->drive_serial_str));
>      if (strlen(s->drive_serial_str) == 0)
>          pstrcpy(s->drive_serial_str, sizeof(s->drive_serial_str), "0");
> +    qemu_add_vm_change_state_handler(scsi_dma_restart_cb, s);
>      d = (SCSIDevice *)qemu_mallocz(sizeof(SCSIDevice));
>      d->state = s;
>      d->destroy = scsi_destroy;
> diff --git a/vl.c b/vl.c
> index 045b09f..a325c81 100644
> --- a/vl.c
> +++ b/vl.c
> @@ -2432,8 +2432,8 @@ static int drive_init(struct drive_opt *arg, int snapshot,
>  
>      onerror = BLOCK_ERR_REPORT;
>      if (get_param_value(buf, sizeof(serial), "werror", str)) {
> -        if (type != IF_IDE) {
> -            fprintf(stderr, "werror is supported only by IDE\n");
> +        if (type != IF_IDE && type != IF_SCSI) {
> +            fprintf(stderr, "werror is no supported by this format\n");
>              return -1;
>          }
>          if (!strcmp(buf, "ignore"))
>
>
>
>
>   

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2009-01-22 19:55 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-01-22 13:31 [Qemu-devel] [PATCH 1/2] Stop VM on error in scsi-disk Gleb Natapov
2009-01-22 13:31 ` [Qemu-devel] [PATCH 2/2] Stop VM on error in virtio-blk Gleb Natapov
2009-01-22 19:54 ` [Qemu-devel] [PATCH 1/2] Stop VM on error in scsi-disk Anthony Liguori

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).