qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Anthony Liguori <aliguori@us.ibm.com>
To: qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH 1/2] Stop VM on error in scsi-disk
Date: Thu, 22 Jan 2009 13:54:45 -0600	[thread overview]
Message-ID: <4978CF05.5010701@us.ibm.com> (raw)
In-Reply-To: <20090122133142.16090.9308.stgit@dhcp-1-237.tlv.redhat.com>

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

      parent reply	other threads:[~2009-01-22 19:55 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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 [this message]

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=4978CF05.5010701@us.ibm.com \
    --to=aliguori@us.ibm.com \
    --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).