AHCI: Fix port reset race
authorAlexander Graf <agraf@suse.de>
Mon, 30 Jan 2012 22:29:47 +0000 (23:29 +0100)
committerKevin Wolf <kwolf@redhat.com>
Thu, 9 Feb 2012 15:17:51 +0000 (16:17 +0100)
bdrv_aio_cancel() can trigger bdrv_aio_flush() which makes all aio
that is currently in flight finish. So what we do is:

  port reset
  detect ncq in flight
  cancel ncq
  delete ncq sg list

at which point we have double freed the sg list. Instead, with this
patch we do:

  port reset
  detect ncq in flight
  cancel ncq
  check if we are really still in flight
  delete ncq sg list

which makes things work and gets rid of the race.

Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
hw/ide/ahci.c

index c87a6ca515b710402ea7b52736fc3b7be1a70856..caff7bc9e6c11a9b73a5d1e02905f028040b1819 100644 (file)
@@ -560,6 +560,11 @@ static void ahci_reset_port(AHCIState *s, int port)
             ncq_tfs->aiocb = NULL;
         }
 
+        /* Maybe we just finished the request thanks to bdrv_aio_cancel() */
+        if (!ncq_tfs->used) {
+            continue;
+        }
+
         qemu_sglist_destroy(&ncq_tfs->sglist);
         ncq_tfs->used = 0;
     }