mirror of https://github.com/xemu-project/xemu.git
scsi: Introduce scsi_req_cancel_async
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 <famz@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
d5776465ee
commit
8e0a9320e9
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue