qemu-devel
[Top][All Lists]
Advanced

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

Re: [Qemu-devel] about qemu crash in scsi_handle_rw_error


From: Paolo Bonzini
Subject: Re: [Qemu-devel] about qemu crash in scsi_handle_rw_error
Date: Fri, 12 Oct 2018 12:08:33 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.0

On 12/10/2018 10:05, Wangguang wrote:
> Hi
> 
> qemu had a assert when we use scsi-3 reservation。
> 
> This happen when scsi sence is recoverd error。
> 
> And which lead scsi_req_complete twice.
> 
>  
> 
>  
> 
> 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);
> 
>     BlockErrorAction action = blk_get_error_action(s->qdev.conf.blk,
> 
>                                                    is_read, error);
> 
>  
> 
>     if (action == BLOCK_ERROR_ACTION_REPORT) {
> 
>         if (acct_failed) {
> 
>             block_acct_failed(blk_get_stats(s->qdev.conf.blk), &r->acct);
> 
>         }
> 
>         switch (error) {
> 
>         case 0:
> 
>             /* The command has run, no need to fake sense.  */
> 
>             assert(r->status && *r->status);
> 
>             scsi_req_complete(&r->req, *r->status);                     
> the  first complete
> 
>             break;
> 
>         case ENOMEDIUM:
> 
>             scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
> 
>             break;
> 
>         case ENOMEM:
> 
>             scsi_check_condition(r, SENSE_CODE(TARGET_FAILURE));
> 
>             break;
> 
>         case EINVAL:
> 
>             scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
> 
>             break;
> 
>         case ENOSPC:
> 
>             scsi_check_condition(r, SENSE_CODE(SPACE_ALLOC_FAILED));
> 
>             break;
> 
>         default:
> 
>             scsi_check_condition(r, SENSE_CODE(IO_ERROR));
> 
>             break;
> 
>         }
> 
>     }
> 
>     if (!error) {
> 
>         assert(r->status && *r->status);
> 
>         error = scsi_sense_buf_to_errno(r->req.sense, sizeof(r->req.sense));
> 
>  
> 
>         if (error == ECANCELED || error == EAGAIN || error == ENOTCONN ||
> 
>             error == 0)  {
> 
>             /* These errors are handled by guest. */
> 
>            scsi_req_complete(&r->req, *r->status);                     
> complete again when error==0;
> 
>             return true;
> 
>         }
> 
>     }
>  
> 
> Shall we delete error==0  at the second scsi_req_complete ??

No, the first call must go away.  In fact, even better, you can move the
entire contents of "if (!error)" inside the "case 0:".

Paolo



reply via email to

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