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;
}
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);
}
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);
#include "block/block.h"
#include "hw/block/block.h"
#include "sysemu/sysemu.h"
+#include "qemu/notify.h"
#define MAX_SCSI_DEVS 255
void *hba_private;
size_t resid;
SCSICommand cmd;
+ NotifierList cancel_notifiers;
/* Note:
* - fields before sense are initialized by scsi_req_alloc;
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);