From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([140.186.70.92]:42567) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RC6H8-0007rW-9p for qemu-devel@nongnu.org; Fri, 07 Oct 2011 04:59:27 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1RC6H6-0005i8-R0 for qemu-devel@nongnu.org; Fri, 07 Oct 2011 04:59:26 -0400 Received: from mail-bw0-f45.google.com ([209.85.214.45]:37323) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RC6H6-0005hP-Lx for qemu-devel@nongnu.org; Fri, 07 Oct 2011 04:59:24 -0400 Received: by mail-bw0-f45.google.com with SMTP id zv15so4509292bkb.4 for ; Fri, 07 Oct 2011 01:59:24 -0700 (PDT) Sender: Paolo Bonzini From: Paolo Bonzini Date: Fri, 7 Oct 2011 10:59:13 +0200 Message-Id: <1317977954-21366-4-git-send-email-pbonzini@redhat.com> In-Reply-To: <1317977954-21366-1-git-send-email-pbonzini@redhat.com> References: <1317977954-21366-1-git-send-email-pbonzini@redhat.com> Subject: [Qemu-devel] [PATCH 3/4] scsi-disk: bump SCSIRequest reference count until aio completion runs List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org In some cases a request may be canceled before the completion callback runs. Keep a reference to the request between starting an AIO operation, and let scsi_*_complete remove it. Since scsi_handle_rw_error returns whether something else has to be done for the request by the caller, it makes sense to transfer ownership of the ref to scsi_handle_rw_error when it returns 1; scsi_dma_restart_bh will then free the reference after restarting the operation. This is reproducible by doing an "eject -f" during an installer's media test, using the lsi adapter. The resulting "ABORT" message causes the request to be canceled and freed before the read completes. Signed-off-by: Paolo Bonzini --- hw/scsi-disk.c | 14 ++++++++++++++ 1 files changed, 14 insertions(+), 0 deletions(-) diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index 6497655..d6f2345 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -139,6 +139,7 @@ static void scsi_read_complete(void * opaque, int ret) if (ret) { if (scsi_handle_rw_error(r, -ret, SCSI_REQ_STATUS_RETRY_READ)) { + /* Leave in ref for scsi_dma_restart_bh. */ return; } } @@ -149,6 +150,7 @@ static void scsi_read_complete(void * opaque, int ret) r->sector += n; r->sector_count -= n; scsi_req_data(&r->req, r->qiov.size); + scsi_req_unref(&r->req); } static void scsi_flush_complete(void * opaque, int ret) @@ -163,11 +165,13 @@ static void scsi_flush_complete(void * opaque, int ret) if (ret < 0) { if (scsi_handle_rw_error(r, -ret, SCSI_REQ_STATUS_RETRY_FLUSH)) { + /* Leave in ref for scsi_dma_restart_bh. */ return; } } scsi_req_complete(&r->req, GOOD); + scsi_req_unref(&r->req); } /* Read more data from scsi device into buffer. */ @@ -202,6 +206,9 @@ static void scsi_read_data(SCSIRequest *req) if (s->tray_open) { scsi_read_complete(r, -ENOMEDIUM); } + + /* Save a ref for scsi_read_complete, in case r is canceled. */ + scsi_req_ref(&r->req); n = scsi_init_iovec(r); bdrv_acct_start(s->bs, &r->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_READ); r->req.aiocb = bdrv_aio_readv(s->bs, r->sector, &r->qiov, n, @@ -278,6 +285,7 @@ static void scsi_write_complete(void * opaque, int ret) DPRINTF("Write complete tag=0x%x more=%d\n", r->req.tag, r->qiov.size); scsi_req_data(&r->req, r->qiov.size); } + scsi_req_unref(&r->req); } static void scsi_write_data(SCSIRequest *req) @@ -295,6 +303,8 @@ static void scsi_write_data(SCSIRequest *req) return; } + /* Save a ref for scsi_write_complete, in case r is canceled. */ + scsi_req_ref(&r->req); n = r->qiov.size / 512; if (n) { if (s->tray_open) { @@ -343,6 +353,8 @@ static void scsi_dma_restart_bh(void *opaque) scsi_req_complete(&r->req, GOOD); } } + /* This reference was left in by scsi_handle_rw_error. */ + scsi_req_unref(&r->req); } } } @@ -1324,6 +1336,8 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf) r->iov.iov_len = rc; break; case SYNCHRONIZE_CACHE: + /* Save a ref for scsi_flush_complete, in case r is canceled. */ + scsi_req_ref(&r->req); bdrv_acct_start(s->bs, &r->acct, 0, BDRV_ACCT_FLUSH); r->req.aiocb = bdrv_aio_flush(s->bs, scsi_flush_complete, r); if (r->req.aiocb == NULL) { -- 1.7.6