qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Paolo Bonzini <pbonzini@redhat.com>
To: qemu-devel@nongnu.org
Cc: anthony@codemonkey.ws
Subject: [Qemu-devel] [PATCH 1/5] Revert "iscsi: Fix NULL dereferences / races between task completion and abort"
Date: Mon, 20 Aug 2012 16:13:09 +0200	[thread overview]
Message-ID: <1345471993-31629-2-git-send-email-pbonzini@redhat.com> (raw)
In-Reply-To: <1345471993-31629-1-git-send-email-pbonzini@redhat.com>

This reverts commit 64e69e80920d82df3fa679bc41b13770d2f99360.  The commit
returned immediately from iscsi_aio_cancel, risking corruption in case the
following happens:

    guest                  qemu                 target
  =========================================================================
    send write 1 -------->
                           send write 1 -------->
    cancel write 1 ------>
                           cancel write 1 ------>
       <------------------ cancellation processed
    send write 2 -------->
                           send write 2 -------->
                               <---------------- completed write 2
       <------------------ completed write 2
                               <---------------- completed write 1
                               <---------------- cancellation not done

Here, the guest would see write 2 superseding write 1, when in fact the
outcome could have been the opposite.  The right behavior is to return
only after the target says whether the cancellation was done or not, and
it will be implemented by the next three patches.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 block/iscsi.c | 55 ++++++++++++++++++++++++++++++++-----------------------
 1 file modificato, 32 inserzioni(+), 23 rimozioni(-)

diff --git a/block/iscsi.c b/block/iscsi.c
index bb9cf82..219f927 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -76,10 +76,6 @@ static void
 iscsi_abort_task_cb(struct iscsi_context *iscsi, int status, void *command_data,
                     void *private_data)
 {
-    IscsiAIOCB *acb = (IscsiAIOCB *)private_data;
-
-    scsi_free_scsi_task(acb->task);
-    acb->task = NULL;
 }
 
 static void
@@ -88,15 +84,15 @@ iscsi_aio_cancel(BlockDriverAIOCB *blockacb)
     IscsiAIOCB *acb = (IscsiAIOCB *)blockacb;
     IscsiLun *iscsilun = acb->iscsilun;
 
-    acb->canceled = 1;
-
     acb->common.cb(acb->common.opaque, -ECANCELED);
+    acb->canceled = 1;
 
-    /* send a task mgmt call to the target to cancel the task on the target
-     * this also cancels the task in libiscsi
-     */
+    /* send a task mgmt call to the target to cancel the task on the target */
     iscsi_task_mgmt_abort_task_async(iscsilun->iscsi, acb->task,
-                                     iscsi_abort_task_cb, &acb);
+                                     iscsi_abort_task_cb, NULL);
+
+    /* then also cancel the task locally in libiscsi */
+    iscsi_scsi_task_cancel(iscsilun->iscsi, acb->task);
 }
 
 static AIOPool iscsi_aio_pool = {
@@ -183,18 +179,11 @@ iscsi_readv_writev_bh_cb(void *p)
 
     qemu_bh_delete(acb->bh);
 
-    if (!acb->canceled) {
+    if (acb->canceled == 0) {
         acb->common.cb(acb->common.opaque, acb->status);
     }
 
     qemu_aio_release(acb);
-
-    if (acb->canceled) {
-        return;
-    }
-
-    scsi_free_scsi_task(acb->task);
-    acb->task = NULL;
 }
 
 
@@ -208,8 +197,10 @@ iscsi_aio_write16_cb(struct iscsi_context *iscsi, int status,
 
     g_free(acb->buf);
 
-    if (acb->canceled) {
+    if (acb->canceled != 0) {
         qemu_aio_release(acb);
+        scsi_free_scsi_task(acb->task);
+        acb->task = NULL;
         return;
     }
 
@@ -221,6 +212,8 @@ iscsi_aio_write16_cb(struct iscsi_context *iscsi, int status,
     }
 
     iscsi_schedule_bh(iscsi_readv_writev_bh_cb, acb);
+    scsi_free_scsi_task(acb->task);
+    acb->task = NULL;
 }
 
 static int64_t sector_qemu2lun(int64_t sector, IscsiLun *iscsilun)
@@ -305,8 +298,10 @@ iscsi_aio_read16_cb(struct iscsi_context *iscsi, int status,
 
     trace_iscsi_aio_read16_cb(iscsi, status, acb, acb->canceled);
 
-    if (acb->canceled) {
+    if (acb->canceled != 0) {
         qemu_aio_release(acb);
+        scsi_free_scsi_task(acb->task);
+        acb->task = NULL;
         return;
     }
 
@@ -318,6 +313,8 @@ iscsi_aio_read16_cb(struct iscsi_context *iscsi, int status,
     }
 
     iscsi_schedule_bh(iscsi_readv_writev_bh_cb, acb);
+    scsi_free_scsi_task(acb->task);
+    acb->task = NULL;
 }
 
 static BlockDriverAIOCB *
@@ -417,8 +414,10 @@ iscsi_synccache10_cb(struct iscsi_context *iscsi, int status,
 {
     IscsiAIOCB *acb = opaque;
 
-    if (acb->canceled) {
+    if (acb->canceled != 0) {
         qemu_aio_release(acb);
+        scsi_free_scsi_task(acb->task);
+        acb->task = NULL;
         return;
     }
 
@@ -430,6 +429,8 @@ iscsi_synccache10_cb(struct iscsi_context *iscsi, int status,
     }
 
     iscsi_schedule_bh(iscsi_readv_writev_bh_cb, acb);
+    scsi_free_scsi_task(acb->task);
+    acb->task = NULL;
 }
 
 static BlockDriverAIOCB *
@@ -467,8 +468,10 @@ iscsi_unmap_cb(struct iscsi_context *iscsi, int status,
 {
     IscsiAIOCB *acb = opaque;
 
-    if (acb->canceled) {
+    if (acb->canceled != 0) {
         qemu_aio_release(acb);
+        scsi_free_scsi_task(acb->task);
+        acb->task = NULL;
         return;
     }
 
@@ -480,6 +483,8 @@ iscsi_unmap_cb(struct iscsi_context *iscsi, int status,
     }
 
     iscsi_schedule_bh(iscsi_readv_writev_bh_cb, acb);
+    scsi_free_scsi_task(acb->task);
+    acb->task = NULL;
 }
 
 static BlockDriverAIOCB *
@@ -523,8 +528,10 @@ iscsi_aio_ioctl_cb(struct iscsi_context *iscsi, int status,
 {
     IscsiAIOCB *acb = opaque;
 
-    if (acb->canceled) {
+    if (acb->canceled != 0) {
         qemu_aio_release(acb);
+        scsi_free_scsi_task(acb->task);
+        acb->task = NULL;
         return;
     }
 
@@ -553,6 +560,8 @@ iscsi_aio_ioctl_cb(struct iscsi_context *iscsi, int status,
     }
 
     iscsi_schedule_bh(iscsi_readv_writev_bh_cb, acb);
+    scsi_free_scsi_task(acb->task);
+    acb->task = NULL;
 }
 
 static BlockDriverAIOCB *iscsi_aio_ioctl(BlockDriverState *bs,
-- 
1.7.11.2

  reply	other threads:[~2012-08-20 14:13 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-08-20 14:13 [Qemu-devel] [PULL 0/5] SCSI fixed for -rc1 Paolo Bonzini
2012-08-20 14:13 ` Paolo Bonzini [this message]
2012-08-20 14:13 ` [Qemu-devel] [PATCH 2/5] iscsi: move iscsi_schedule_bh and iscsi_readv_writev_bh_cb Paolo Bonzini
2012-08-20 14:13 ` [Qemu-devel] [PATCH 3/5] iscsi: simplify iscsi_schedule_bh Paolo Bonzini
2012-08-20 14:13 ` [Qemu-devel] [PATCH 4/5] iscsi: fix races between task completion and abort Paolo Bonzini
2012-08-20 14:13 ` [Qemu-devel] [PATCH 5/5] virtio-scsi: add backwards-compatibility properties for 1.1 and earlier machines Paolo Bonzini

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=1345471993-31629-2-git-send-email-pbonzini@redhat.com \
    --to=pbonzini@redhat.com \
    --cc=anthony@codemonkey.ws \
    --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).