From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:35312) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XYwW3-0000SF-Pz for qemu-devel@nongnu.org; Tue, 30 Sep 2014 08:27:02 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1XYwVu-0003Go-Ny for qemu-devel@nongnu.org; Tue, 30 Sep 2014 08:26:51 -0400 Received: from mail-wi0-x22f.google.com ([2a00:1450:400c:c05::22f]:54542) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XYwVu-0003FX-He for qemu-devel@nongnu.org; Tue, 30 Sep 2014 08:26:42 -0400 Received: by mail-wi0-f175.google.com with SMTP id d1so3259619wiv.8 for ; Tue, 30 Sep 2014 05:26:36 -0700 (PDT) Sender: Paolo Bonzini From: Paolo Bonzini Date: Tue, 30 Sep 2014 14:25:16 +0200 Message-Id: <1412079919-18857-37-git-send-email-pbonzini@redhat.com> In-Reply-To: <1412079919-18857-1-git-send-email-pbonzini@redhat.com> References: <1412079919-18857-1-git-send-email-pbonzini@redhat.com> Subject: [Qemu-devel] [PULL 36/39] scsi: Introduce scsi_req_cancel_async List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Fam Zheng From: Fam Zheng Devices will call this function to start an asynchronous cancellation. The bus->info->cancel will be called after the request is canceled. Devices will probably need to track a separate TMF request that triggers this cancellation, and wait until the cancellation is done before completing it. So we store a notifier list in SCSIRequest and in scsi_req_cancel_complete we notify them. Signed-off-by: Fam Zheng Signed-off-by: Paolo Bonzini --- hw/scsi/scsi-bus.c | 26 ++++++++++++++++++++++++++ include/hw/scsi/scsi.h | 3 +++ 2 files changed, 29 insertions(+) diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c index c91db63..0f3e039 100644 --- a/hw/scsi/scsi-bus.c +++ b/hw/scsi/scsi-bus.c @@ -566,6 +566,7 @@ SCSIRequest *scsi_req_alloc(const SCSIReqOps *reqops, SCSIDevice *d, req->ops = reqops; object_ref(OBJECT(d)); object_ref(OBJECT(qbus->parent)); + notifier_list_init(&req->cancel_notifiers); trace_scsi_req_alloc(req->dev->id, req->lun, req->tag); return req; } @@ -1715,6 +1716,9 @@ void scsi_req_complete(SCSIRequest *req, int status) scsi_req_ref(req); scsi_req_dequeue(req); req->bus->info->complete(req, req->status, req->resid); + + /* Cancelled requests might end up being completed instead of cancelled */ + notifier_list_notify(&req->cancel_notifiers, req); scsi_req_unref(req); } @@ -1725,9 +1729,31 @@ void scsi_req_cancel_complete(SCSIRequest *req) if (req->bus->info->cancel) { req->bus->info->cancel(req); } + notifier_list_notify(&req->cancel_notifiers, req); scsi_req_unref(req); } +/* Cancel @req asynchronously. @notifier is added to @req's cancellation + * notifier list, the bus will be notified the requests cancellation is + * completed. + * */ +void scsi_req_cancel_async(SCSIRequest *req, Notifier *notifier) +{ + trace_scsi_req_cancel(req->dev->id, req->lun, req->tag); + if (notifier) { + notifier_list_add(&req->cancel_notifiers, notifier); + } + if (req->io_canceled) { + return; + } + scsi_req_ref(req); + scsi_req_dequeue(req); + req->io_canceled = true; + if (req->aiocb) { + bdrv_aio_cancel_async(req->aiocb); + } +} + void scsi_req_cancel(SCSIRequest *req) { trace_scsi_req_cancel(req->dev->id, req->lun, req->tag); diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h index 2127a33..b61bedb 100644 --- a/include/hw/scsi/scsi.h +++ b/include/hw/scsi/scsi.h @@ -5,6 +5,7 @@ #include "block/block.h" #include "hw/block/block.h" #include "sysemu/sysemu.h" +#include "qemu/notify.h" #define MAX_SCSI_DEVS 255 @@ -53,6 +54,7 @@ struct SCSIRequest { void *hba_private; size_t resid; SCSICommand cmd; + NotifierList cancel_notifiers; /* Note: * - fields before sense are initialized by scsi_req_alloc; @@ -266,6 +268,7 @@ uint8_t *scsi_req_get_buf(SCSIRequest *req); int scsi_req_get_sense(SCSIRequest *req, uint8_t *buf, int len); void scsi_req_cancel_complete(SCSIRequest *req); void scsi_req_cancel(SCSIRequest *req); +void scsi_req_cancel_async(SCSIRequest *req, Notifier *notifier); void scsi_req_retry(SCSIRequest *req); void scsi_device_purge_requests(SCSIDevice *sdev, SCSISense sense); void scsi_device_set_ua(SCSIDevice *sdev, SCSISense sense); -- 1.8.3.1