[Qemu-devel] [PATCH] scsi-disk: Fix crash if request is invaild or disk is no medium

Zhengui li posted 1 patch 5 years, 2 months ago
Test asan failed
Test docker-mingw@fedora passed
Test docker-clang@ubuntu passed
Test checkpatch failed
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/qemu tags/patchew/1551949037-15528-1-git-send-email-lizhengui@huawei.com
Maintainers: Paolo Bonzini <pbonzini@redhat.com>, Fam Zheng <fam@euphon.net>
hw/scsi/scsi-disk.c | 37 ++++++++++++++++++++++++-------------
1 file changed, 24 insertions(+), 13 deletions(-)
[Qemu-devel] [PATCH] scsi-disk: Fix crash if request is invaild or disk is no medium
Posted by Zhengui li 5 years, 2 months ago
From: Zhengui Li <lizhengui@huawei.com>

Qemu will crash with the assertion error that "assert(r->req.aiocb !=
NULL)" in scsi_read_complete if request is invaild or disk is no medium.
The error is below:
qemu-kvm: hw/scsi/scsi_disk.c:299: scsi_read_complete: Assertion
`r->req.aiocb != NULL' failed.

This patch add a funtion scsi_read_complete_noio to fix it.

Signed-off-by: Zhengui Li <lizhengui@huawei.com>
---
 hw/scsi/scsi-disk.c | 37 ++++++++++++++++++++++++-------------
 1 file changed, 24 insertions(+), 13 deletions(-)

diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
index d4e83ae..624df3c 100644
--- a/hw/scsi/scsi-disk.c
+++ b/hw/scsi/scsi-disk.c
@@ -296,22 +296,15 @@ static void scsi_dma_complete(void *opaque, int ret)
     aio_context_release(blk_get_aio_context(s->qdev.conf.blk));
 }
 
-static void scsi_read_complete(void * opaque, int ret)
+static void scsi_read_complete_noio(SCSIDiskReq *r, int ret)
 {
-    SCSIDiskReq *r = (SCSIDiskReq *)opaque;
-    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
-    int n;
+    uint32_t n;
 
-    assert(r->req.aiocb != NULL);
-    r->req.aiocb = NULL;
-    aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
-    if (scsi_disk_req_check_error(r, ret, true)) {
+    assert (r->req.aiocb == NULL);
+    if (scsi_disk_req_check_error(r, ret, false)) {
         goto done;
     }
 
-    block_acct_done(blk_get_stats(s->qdev.conf.blk), &r->acct);
-    trace_scsi_disk_read_complete(r->req.tag, r->qiov.size);
-
     n = r->qiov.size / 512;
     r->sector += n;
     r->sector_count -= n;
@@ -319,6 +312,24 @@ static void scsi_read_complete(void * opaque, int ret)
 
 done:
     scsi_req_unref(&r->req);
+}
+
+static void scsi_read_complete(void * opaque, int ret)
+{
+    SCSIDiskReq *r = (SCSIDiskReq *)opaque;
+    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
+
+    assert(r->req.aiocb != NULL);
+    r->req.aiocb = NULL;
+
+    aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
+    if (ret < 0) {
+        block_acct_failed(blk_get_stats(s->qdev.conf.blk), &r->acct);
+    } else {
+        block_acct_done(blk_get_stats(s->qdev.conf.blk), &r->acct);
+        trace_scsi_disk_read_complete(r->req.tag, r->qiov.size);
+    }
+    scsi_read_complete_noio(r, ret);
     aio_context_release(blk_get_aio_context(s->qdev.conf.blk));
 }
 
@@ -395,12 +406,12 @@ static void scsi_read_data(SCSIRequest *req)
     scsi_req_ref(&r->req);
     if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
         trace_scsi_disk_read_data_invalid();
-        scsi_read_complete(r, -EINVAL);
+        scsi_read_complete_noio(r, -EINVAL);
         return;
     }
 
     if (!blk_is_available(req->dev->conf.blk)) {
-        scsi_read_complete(r, -ENOMEDIUM);
+        scsi_read_complete_noio(r, -ENOMEDIUM);
         return;
     }
 
-- 
2.7.2.windows.1



Re: [Qemu-devel] [PATCH] scsi-disk: Fix crash if request is invaild or disk is no medium
Posted by no-reply@patchew.org 5 years, 2 months ago
Patchew URL: https://patchew.org/QEMU/1551949037-15528-1-git-send-email-lizhengui@huawei.com/



Hi,

This series seems to have some coding style problems. See output below for
more information:

Type: series
Message-id: 1551949037-15528-1-git-send-email-lizhengui@huawei.com
Subject: [Qemu-devel] [PATCH] scsi-disk: Fix crash if request is invaild or disk is no medium

=== TEST SCRIPT BEGIN ===
#!/bin/bash
git rev-parse base > /dev/null || exit 0
git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram
./scripts/checkpatch.pl --mailback base..
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
 * [new tag]               patchew/1551949037-15528-1-git-send-email-lizhengui@huawei.com -> patchew/1551949037-15528-1-git-send-email-lizhengui@huawei.com
Switched to a new branch 'test'
501088e7d7 scsi-disk: Fix crash if request is invaild or disk is no medium

=== OUTPUT BEGIN ===
ERROR: space prohibited between function name and open parenthesis '('
#38: FILE: hw/scsi/scsi-disk.c:303:
+    assert (r->req.aiocb == NULL);

ERROR: "foo * bar" should be "foo *bar"
#55: FILE: hw/scsi/scsi-disk.c:317:
+static void scsi_read_complete(void * opaque, int ret)

total: 2 errors, 0 warnings, 64 lines checked

Commit 501088e7d763 (scsi-disk: Fix crash if request is invaild or disk is no medium) has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
=== OUTPUT END ===

Test command exited with code: 1


The full log is available at
http://patchew.org/logs/1551949037-15528-1-git-send-email-lizhengui@huawei.com/testing.checkpatch/?type=message.
---
Email generated automatically by Patchew [http://patchew.org/].
Please send your feedback to patchew-devel@redhat.com
Re: [Qemu-devel] [Qemu-block] [PATCH] scsi-disk: Fix crash if request is invaild or disk is no medium
Posted by John Snow 5 years, 1 month ago

On 3/7/19 3:57 AM, Zhengui li wrote:
> From: Zhengui Li <lizhengui@huawei.com>
> 
> Qemu will crash with the assertion error that "assert(r->req.aiocb !=
> NULL)" in scsi_read_complete if request is invaild or disk is no medium.
> The error is below:
> qemu-kvm: hw/scsi/scsi_disk.c:299: scsi_read_complete: Assertion
> `r->req.aiocb != NULL' failed.
> 
> This patch add a funtion scsi_read_complete_noio to fix it.
> 

How do you reproduce this? Is there a test?

--js

> Signed-off-by: Zhengui Li <lizhengui@huawei.com>
> ---
>  hw/scsi/scsi-disk.c | 37 ++++++++++++++++++++++++-------------
>  1 file changed, 24 insertions(+), 13 deletions(-)
> 
> diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
> index d4e83ae..624df3c 100644
> --- a/hw/scsi/scsi-disk.c
> +++ b/hw/scsi/scsi-disk.c
> @@ -296,22 +296,15 @@ static void scsi_dma_complete(void *opaque, int ret)
>      aio_context_release(blk_get_aio_context(s->qdev.conf.blk));
>  }
>  
> -static void scsi_read_complete(void * opaque, int ret)
> +static void scsi_read_complete_noio(SCSIDiskReq *r, int ret)
>  {
> -    SCSIDiskReq *r = (SCSIDiskReq *)opaque;
> -    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
> -    int n;
> +    uint32_t n;
>  
> -    assert(r->req.aiocb != NULL);
> -    r->req.aiocb = NULL;
> -    aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
> -    if (scsi_disk_req_check_error(r, ret, true)) {
> +    assert (r->req.aiocb == NULL);
> +    if (scsi_disk_req_check_error(r, ret, false)) {
>          goto done;
>      }
>  
> -    block_acct_done(blk_get_stats(s->qdev.conf.blk), &r->acct);
> -    trace_scsi_disk_read_complete(r->req.tag, r->qiov.size);
> -
>      n = r->qiov.size / 512;
>      r->sector += n;
>      r->sector_count -= n;
> @@ -319,6 +312,24 @@ static void scsi_read_complete(void * opaque, int ret)
>  
>  done:
>      scsi_req_unref(&r->req);
> +}
> +
> +static void scsi_read_complete(void * opaque, int ret)
> +{
> +    SCSIDiskReq *r = (SCSIDiskReq *)opaque;
> +    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
> +
> +    assert(r->req.aiocb != NULL);
> +    r->req.aiocb = NULL;
> +
> +    aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
> +    if (ret < 0) {
> +        block_acct_failed(blk_get_stats(s->qdev.conf.blk), &r->acct);
> +    } else {
> +        block_acct_done(blk_get_stats(s->qdev.conf.blk), &r->acct);
> +        trace_scsi_disk_read_complete(r->req.tag, r->qiov.size);
> +    }
> +    scsi_read_complete_noio(r, ret);
>      aio_context_release(blk_get_aio_context(s->qdev.conf.blk));
>  }
>  
> @@ -395,12 +406,12 @@ static void scsi_read_data(SCSIRequest *req)
>      scsi_req_ref(&r->req);
>      if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
>          trace_scsi_disk_read_data_invalid();
> -        scsi_read_complete(r, -EINVAL);
> +        scsi_read_complete_noio(r, -EINVAL);
>          return;
>      }
>  
>      if (!blk_is_available(req->dev->conf.blk)) {
> -        scsi_read_complete(r, -ENOMEDIUM);
> +        scsi_read_complete_noio(r, -ENOMEDIUM);
>          return;
>      }
>  
> 

[Qemu-devel] 答复: [Qemu-block] [PATCH] scsi-disk: Fix crash if request is invaild or disk is no medium
Posted by lizhengui 5 years, 1 month ago
This problem can be reproduced by detaching and attaching remote cdrom repeatly.

-----邮件原件-----
发件人: John Snow [mailto:jsnow@redhat.com] 
发送时间: 2019年3月19日 7:34
收件人: lizhengui; pbonzini@redhat.com; stefanha@redhat.com; mreitz@redhat.com
抄送: qemu-block@nongnu.org; Fangyi (C); qemu-devel@nongnu.org; wangjie (P)
主题: Re: [Qemu-block] [PATCH] scsi-disk: Fix crash if request is invaild or disk is no medium



On 3/7/19 3:57 AM, Zhengui li wrote:
> From: Zhengui Li <lizhengui@huawei.com>
> 
> Qemu will crash with the assertion error that "assert(r->req.aiocb !=
> NULL)" in scsi_read_complete if request is invaild or disk is no medium.
> The error is below:
> qemu-kvm: hw/scsi/scsi_disk.c:299: scsi_read_complete: Assertion
> `r->req.aiocb != NULL' failed.
> 
> This patch add a funtion scsi_read_complete_noio to fix it.
> 

How do you reproduce this? Is there a test?

--js

> Signed-off-by: Zhengui Li <lizhengui@huawei.com>
> ---
>  hw/scsi/scsi-disk.c | 37 ++++++++++++++++++++++++-------------
>  1 file changed, 24 insertions(+), 13 deletions(-)
> 
> diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
> index d4e83ae..624df3c 100644
> --- a/hw/scsi/scsi-disk.c
> +++ b/hw/scsi/scsi-disk.c
> @@ -296,22 +296,15 @@ static void scsi_dma_complete(void *opaque, int ret)
>      aio_context_release(blk_get_aio_context(s->qdev.conf.blk));
>  }
>  
> -static void scsi_read_complete(void * opaque, int ret)
> +static void scsi_read_complete_noio(SCSIDiskReq *r, int ret)
>  {
> -    SCSIDiskReq *r = (SCSIDiskReq *)opaque;
> -    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
> -    int n;
> +    uint32_t n;
>  
> -    assert(r->req.aiocb != NULL);
> -    r->req.aiocb = NULL;
> -    aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
> -    if (scsi_disk_req_check_error(r, ret, true)) {
> +    assert (r->req.aiocb == NULL);
> +    if (scsi_disk_req_check_error(r, ret, false)) {
>          goto done;
>      }
>  
> -    block_acct_done(blk_get_stats(s->qdev.conf.blk), &r->acct);
> -    trace_scsi_disk_read_complete(r->req.tag, r->qiov.size);
> -
>      n = r->qiov.size / 512;
>      r->sector += n;
>      r->sector_count -= n;
> @@ -319,6 +312,24 @@ static void scsi_read_complete(void * opaque, int ret)
>  
>  done:
>      scsi_req_unref(&r->req);
> +}
> +
> +static void scsi_read_complete(void * opaque, int ret)
> +{
> +    SCSIDiskReq *r = (SCSIDiskReq *)opaque;
> +    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
> +
> +    assert(r->req.aiocb != NULL);
> +    r->req.aiocb = NULL;
> +
> +    aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
> +    if (ret < 0) {
> +        block_acct_failed(blk_get_stats(s->qdev.conf.blk), &r->acct);
> +    } else {
> +        block_acct_done(blk_get_stats(s->qdev.conf.blk), &r->acct);
> +        trace_scsi_disk_read_complete(r->req.tag, r->qiov.size);
> +    }
> +    scsi_read_complete_noio(r, ret);
>      aio_context_release(blk_get_aio_context(s->qdev.conf.blk));
>  }
>  
> @@ -395,12 +406,12 @@ static void scsi_read_data(SCSIRequest *req)
>      scsi_req_ref(&r->req);
>      if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
>          trace_scsi_disk_read_data_invalid();
> -        scsi_read_complete(r, -EINVAL);
> +        scsi_read_complete_noio(r, -EINVAL);
>          return;
>      }
>  
>      if (!blk_is_available(req->dev->conf.blk)) {
> -        scsi_read_complete(r, -ENOMEDIUM);
> +        scsi_read_complete_noio(r, -ENOMEDIUM);
>          return;
>      }
>  
> 
Re: [Qemu-devel]答复: [Qemu-block] [PATCH] scsi-disk: Fix crash if request is invaild or disk is no medium
Posted by John Snow 5 years, 1 month ago

On 3/18/19 9:52 PM, lizhengui wrote:
> This problem can be reproduced by detaching and attaching remote cdrom repeatly.
> 

While a guest tries to access it, or not? do you have a scriptable test?

--js

> -----邮件原件-----
> 发件人: John Snow [mailto:jsnow@redhat.com] 
> 发送时间: 2019年3月19日 7:34
> 收件人: lizhengui; pbonzini@redhat.com; stefanha@redhat.com; mreitz@redhat.com
> 抄送: qemu-block@nongnu.org; Fangyi (C); qemu-devel@nongnu.org; wangjie (P)
> 主题: Re: [Qemu-block] [PATCH] scsi-disk: Fix crash if request is invaild or disk is no medium
> 
> 
> 
> On 3/7/19 3:57 AM, Zhengui li wrote:
>> From: Zhengui Li <lizhengui@huawei.com>
>>
>> Qemu will crash with the assertion error that "assert(r->req.aiocb !=
>> NULL)" in scsi_read_complete if request is invaild or disk is no medium.
>> The error is below:
>> qemu-kvm: hw/scsi/scsi_disk.c:299: scsi_read_complete: Assertion
>> `r->req.aiocb != NULL' failed.
>>
>> This patch add a funtion scsi_read_complete_noio to fix it.
>>
> 
> How do you reproduce this? Is there a test?
> 
> --js
> 
>> Signed-off-by: Zhengui Li <lizhengui@huawei.com>
>> ---
>>  hw/scsi/scsi-disk.c | 37 ++++++++++++++++++++++++-------------
>>  1 file changed, 24 insertions(+), 13 deletions(-)
>>
>> diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
>> index d4e83ae..624df3c 100644
>> --- a/hw/scsi/scsi-disk.c
>> +++ b/hw/scsi/scsi-disk.c
>> @@ -296,22 +296,15 @@ static void scsi_dma_complete(void *opaque, int ret)
>>      aio_context_release(blk_get_aio_context(s->qdev.conf.blk));
>>  }
>>  
>> -static void scsi_read_complete(void * opaque, int ret)
>> +static void scsi_read_complete_noio(SCSIDiskReq *r, int ret)
>>  {
>> -    SCSIDiskReq *r = (SCSIDiskReq *)opaque;
>> -    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
>> -    int n;
>> +    uint32_t n;
>>  
>> -    assert(r->req.aiocb != NULL);
>> -    r->req.aiocb = NULL;
>> -    aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
>> -    if (scsi_disk_req_check_error(r, ret, true)) {
>> +    assert (r->req.aiocb == NULL);
>> +    if (scsi_disk_req_check_error(r, ret, false)) {
>>          goto done;
>>      }
>>  
>> -    block_acct_done(blk_get_stats(s->qdev.conf.blk), &r->acct);
>> -    trace_scsi_disk_read_complete(r->req.tag, r->qiov.size);
>> -
>>      n = r->qiov.size / 512;
>>      r->sector += n;
>>      r->sector_count -= n;
>> @@ -319,6 +312,24 @@ static void scsi_read_complete(void * opaque, int ret)
>>  
>>  done:
>>      scsi_req_unref(&r->req);
>> +}
>> +
>> +static void scsi_read_complete(void * opaque, int ret)
>> +{
>> +    SCSIDiskReq *r = (SCSIDiskReq *)opaque;
>> +    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
>> +
>> +    assert(r->req.aiocb != NULL);
>> +    r->req.aiocb = NULL;
>> +
>> +    aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
>> +    if (ret < 0) {
>> +        block_acct_failed(blk_get_stats(s->qdev.conf.blk), &r->acct);
>> +    } else {
>> +        block_acct_done(blk_get_stats(s->qdev.conf.blk), &r->acct);
>> +        trace_scsi_disk_read_complete(r->req.tag, r->qiov.size);
>> +    }
>> +    scsi_read_complete_noio(r, ret);
>>      aio_context_release(blk_get_aio_context(s->qdev.conf.blk));
>>  }
>>  
>> @@ -395,12 +406,12 @@ static void scsi_read_data(SCSIRequest *req)
>>      scsi_req_ref(&r->req);
>>      if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
>>          trace_scsi_disk_read_data_invalid();
>> -        scsi_read_complete(r, -EINVAL);
>> +        scsi_read_complete_noio(r, -EINVAL);
>>          return;
>>      }
>>  
>>      if (!blk_is_available(req->dev->conf.blk)) {
>> -        scsi_read_complete(r, -ENOMEDIUM);
>> +        scsi_read_complete_noio(r, -ENOMEDIUM);
>>          return;
>>      }
>>  
>>

[Qemu-devel] reply: reply: [Qemu-block] [PATCH] scsi-disk: Fix crash if request is invaild or disk is no medium
Posted by lizhengui 5 years, 1 month ago
Yes, While a guest tries to access it and detach remote cdrom at sametime.

-----邮件原件-----
发件人: John Snow [mailto:jsnow@redhat.com] 
发送时间: 2019年3月20日 0:35
收件人: lizhengui
抄送: qemu-block@nongnu.org; Fangyi (C); qemu-devel@nongnu.org; wangjie (P); pbonzini@redhat.com; stefanha@redhat.com; mreitz@redhat.com
主题: Re: 答复: [Qemu-block] [PATCH] scsi-disk: Fix crash if request is invaild or disk is no medium



On 3/18/19 9:52 PM, lizhengui wrote:
> This problem can be reproduced by detaching and attaching remote cdrom repeatly.
> 

While a guest tries to access it, or not? do you have a scriptable test?

--js

> -----邮件原件-----
> 发件人: John Snow [mailto:jsnow@redhat.com] 
> 发送时间: 2019年3月19日 7:34
> 收件人: lizhengui; pbonzini@redhat.com; stefanha@redhat.com; mreitz@redhat.com
> 抄送: qemu-block@nongnu.org; Fangyi (C); qemu-devel@nongnu.org; wangjie (P)
> 主题: Re: [Qemu-block] [PATCH] scsi-disk: Fix crash if request is invaild or disk is no medium
> 
> 
> 
> On 3/7/19 3:57 AM, Zhengui li wrote:
>> From: Zhengui Li <lizhengui@huawei.com>
>>
>> Qemu will crash with the assertion error that "assert(r->req.aiocb !=
>> NULL)" in scsi_read_complete if request is invaild or disk is no medium.
>> The error is below:
>> qemu-kvm: hw/scsi/scsi_disk.c:299: scsi_read_complete: Assertion
>> `r->req.aiocb != NULL' failed.
>>
>> This patch add a funtion scsi_read_complete_noio to fix it.
>>
> 
> How do you reproduce this? Is there a test?
> 
> --js
> 
>> Signed-off-by: Zhengui Li <lizhengui@huawei.com>
>> ---
>>  hw/scsi/scsi-disk.c | 37 ++++++++++++++++++++++++-------------
>>  1 file changed, 24 insertions(+), 13 deletions(-)
>>
>> diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
>> index d4e83ae..624df3c 100644
>> --- a/hw/scsi/scsi-disk.c
>> +++ b/hw/scsi/scsi-disk.c
>> @@ -296,22 +296,15 @@ static void scsi_dma_complete(void *opaque, int ret)
>>      aio_context_release(blk_get_aio_context(s->qdev.conf.blk));
>>  }
>>  
>> -static void scsi_read_complete(void * opaque, int ret)
>> +static void scsi_read_complete_noio(SCSIDiskReq *r, int ret)
>>  {
>> -    SCSIDiskReq *r = (SCSIDiskReq *)opaque;
>> -    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
>> -    int n;
>> +    uint32_t n;
>>  
>> -    assert(r->req.aiocb != NULL);
>> -    r->req.aiocb = NULL;
>> -    aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
>> -    if (scsi_disk_req_check_error(r, ret, true)) {
>> +    assert (r->req.aiocb == NULL);
>> +    if (scsi_disk_req_check_error(r, ret, false)) {
>>          goto done;
>>      }
>>  
>> -    block_acct_done(blk_get_stats(s->qdev.conf.blk), &r->acct);
>> -    trace_scsi_disk_read_complete(r->req.tag, r->qiov.size);
>> -
>>      n = r->qiov.size / 512;
>>      r->sector += n;
>>      r->sector_count -= n;
>> @@ -319,6 +312,24 @@ static void scsi_read_complete(void * opaque, int ret)
>>  
>>  done:
>>      scsi_req_unref(&r->req);
>> +}
>> +
>> +static void scsi_read_complete(void * opaque, int ret)
>> +{
>> +    SCSIDiskReq *r = (SCSIDiskReq *)opaque;
>> +    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
>> +
>> +    assert(r->req.aiocb != NULL);
>> +    r->req.aiocb = NULL;
>> +
>> +    aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
>> +    if (ret < 0) {
>> +        block_acct_failed(blk_get_stats(s->qdev.conf.blk), &r->acct);
>> +    } else {
>> +        block_acct_done(blk_get_stats(s->qdev.conf.blk), &r->acct);
>> +        trace_scsi_disk_read_complete(r->req.tag, r->qiov.size);
>> +    }
>> +    scsi_read_complete_noio(r, ret);
>>      aio_context_release(blk_get_aio_context(s->qdev.conf.blk));
>>  }
>>  
>> @@ -395,12 +406,12 @@ static void scsi_read_data(SCSIRequest *req)
>>      scsi_req_ref(&r->req);
>>      if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
>>          trace_scsi_disk_read_data_invalid();
>> -        scsi_read_complete(r, -EINVAL);
>> +        scsi_read_complete_noio(r, -EINVAL);
>>          return;
>>      }
>>  
>>      if (!blk_is_available(req->dev->conf.blk)) {
>> -        scsi_read_complete(r, -ENOMEDIUM);
>> +        scsi_read_complete_noio(r, -ENOMEDIUM);
>>          return;
>>      }
>>  
>>