qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH v1 1/1] hw/scsi: Report errors and sense to gues


From: Paolo Bonzini
Subject: Re: [Qemu-devel] [PATCH v1 1/1] hw/scsi: Report errors and sense to guests through scsi-block
Date: Thu, 27 Jun 2019 11:01:09 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.7.2

On 27/06/19 00:46, Alistair Francis wrote:
> From: Shin'ichiro Kawasaki <address@hidden>
> 
> When host block devices are bridged to a guest system through
> virtio-scsi-pci and scsi-block driver, scsi_handle_rw_error() in
> hw/scsi/scsi-disk.c checks the error number to judge which error to
> report to the guests. EIO and EINVAL are not reported and ignored. Once
> EIO or EINVAL happen, eternal wait of guest system happens. This problem
> was observed with zoned block devices on the host system attached to the
> guest via virtio-scsi-pci. To avoid the eternal wait, add EIO and EINVAL
> to the list of error numbers to report to the guest.

This is certainly correct for EINVAL, I am not sure about EIO.  Did you
run the VM with "-drive ...,rerror=report,werror=report"?

The update_sense part is okay too.

Paolo

> On top of this, it is required to report SCSI sense data to the guest
> so that the guest can handle the error correctly. However,
> scsi_handle_rw_error() does not passthrough sense data that host
> scsi-block device reported. Instead, it newly generates fixed sense
> data only for certain error numbers. This is inflexible to support new
> error codes to report to guest. To avoid this inflexiblity, pass the SCSI
> sense data that the host scsi-block device reported as is. To be more
> precise, set valid sense_len in the SCSIDiskReq referring sb_len_wr that
> host SCSI device SG_IO ioctl reported. Add update_sense callback to
> SCSIDiskClass to refer the SG_IO ioctl result only when scsi-block device
> is targeted.
> 
> Signed-off-by: Shin'ichiro Kawasaki <address@hidden>
> Signed-off-by: Alistair Francis <address@hidden>
> ---
>  hw/scsi/scsi-disk.c | 15 ++++++++++++++-
>  1 file changed, 14 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
> index ed7295bfd7..6801e3a0d0 100644
> --- a/hw/scsi/scsi-disk.c
> +++ b/hw/scsi/scsi-disk.c
> @@ -62,6 +62,7 @@ typedef struct SCSIDiskClass {
>      DMAIOFunc       *dma_readv;
>      DMAIOFunc       *dma_writev;
>      bool            (*need_fua_emulation)(SCSICommand *cmd);
> +    void            (*update_sense)(SCSIRequest *r);
>  } SCSIDiskClass;
>  
>  typedef struct SCSIDiskReq {
> @@ -438,6 +439,7 @@ static bool scsi_handle_rw_error(SCSIDiskReq *r, int 
> error, bool acct_failed)
>  {
>      bool is_read = (r->req.cmd.mode == SCSI_XFER_FROM_DEV);
>      SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
> +    SCSIDiskClass *sdc = (SCSIDiskClass *) object_get_class(OBJECT(s));
>      BlockErrorAction action = blk_get_error_action(s->qdev.conf.blk,
>                                                     is_read, error);
>  
> @@ -452,9 +454,12 @@ static bool scsi_handle_rw_error(SCSIDiskReq *r, int 
> error, bool acct_failed)
>               * pause the host.
>               */
>              assert(r->status && *r->status);
> +            if (sdc->update_sense) {
> +                sdc->update_sense(&r->req);
> +            }
>              error = scsi_sense_buf_to_errno(r->req.sense, 
> sizeof(r->req.sense));
>              if (error == ECANCELED || error == EAGAIN || error == ENOTCONN ||
> -                error == 0)  {
> +                error == EIO || error == EINVAL || error == 0)  {
>                  /* These errors are handled by guest. */
>                  scsi_req_complete(&r->req, *r->status);
>                  return true;
> @@ -2894,6 +2899,13 @@ static int scsi_block_parse_cdb(SCSIDevice *d, 
> SCSICommand *cmd,
>      }
>  }
>  
> +static void scsi_block_update_sense(SCSIRequest *req)
> +{
> +    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
> +    SCSIBlockReq *br = DO_UPCAST(SCSIBlockReq, req, r);
> +    r->req.sense_len = MIN(br->io_header.sb_len_wr, sizeof(r->req.sense));
> +}
> +
>  #endif
>  
>  static
> @@ -3059,6 +3071,7 @@ static void scsi_block_class_initfn(ObjectClass *klass, 
> void *data)
>      sc->parse_cdb    = scsi_block_parse_cdb;
>      sdc->dma_readv   = scsi_block_dma_readv;
>      sdc->dma_writev  = scsi_block_dma_writev;
> +    sdc->update_sense = scsi_block_update_sense;
>      sdc->need_fua_emulation = scsi_block_no_fua;
>      dc->desc = "SCSI block device passthrough";
>      dc->props = scsi_block_properties;
> 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]