Signed-off-by: Peter Lieven <p...@kamp.de>
---
block/iscsi.c | 156 +++++++++++++++++++++++++++------------------------------
1 file changed, 73 insertions(+), 83 deletions(-)
diff --git a/block/iscsi.c b/block/iscsi.c
index 19afd6c..cb44fb1 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -85,6 +85,7 @@ typedef struct IscsiAIOCB {
#define NOP_INTERVAL 5000
#define MAX_NOP_FAILURES 3
#define ISCSI_CMD_RETRIES 5
+#define ISCSI_MAX_UNMAP 131072
static void
iscsi_bh_cb(void *p)
@@ -622,88 +623,6 @@ iscsi_aio_flush(BlockDriverState *bs,
return &acb->common;
}
-static int iscsi_aio_discard_acb(IscsiAIOCB *acb);
-
-static void
-iscsi_unmap_cb(struct iscsi_context *iscsi, int status,
- void *command_data, void *opaque)
-{
- IscsiAIOCB *acb = opaque;
-
- if (acb->canceled != 0) {
- return;
- }
-
- acb->status = 0;
- if (status != 0) {
- if (status == SCSI_STATUS_CHECK_CONDITION
- && acb->task->sense.key == SCSI_SENSE_UNIT_ATTENTION
- && acb->retries-- > 0) {
- scsi_free_scsi_task(acb->task);
- acb->task = NULL;
- if (iscsi_aio_discard_acb(acb) == 0) {
- iscsi_set_events(acb->iscsilun);
- return;
- }
- }
- error_report("Failed to unmap data on iSCSI lun. %s",
- iscsi_get_error(iscsi));
- acb->status = -EIO;
- }
-
- iscsi_schedule_bh(acb);
-}
-
-static int iscsi_aio_discard_acb(IscsiAIOCB *acb) {
- struct iscsi_context *iscsi = acb->iscsilun->iscsi;
- struct unmap_list list[1];
-
- acb->canceled = 0;
- acb->bh = NULL;
- acb->status = -EINPROGRESS;
- acb->buf = NULL;
-
- list[0].lba = sector_qemu2lun(acb->sector_num, acb->iscsilun);
- list[0].num = acb->nb_sectors * BDRV_SECTOR_SIZE /
acb->iscsilun->block_size;
-
- acb->task = iscsi_unmap_task(iscsi, acb->iscsilun->lun,
- 0, 0, &list[0], 1,
- iscsi_unmap_cb,
- acb);
- if (acb->task == NULL) {
- error_report("iSCSI: Failed to send unmap command. %s",
- iscsi_get_error(iscsi));
- return -1;
- }
-
- return 0;
-}
-
-static BlockDriverAIOCB *
-iscsi_aio_discard(BlockDriverState *bs,
- int64_t sector_num, int nb_sectors,
- BlockDriverCompletionFunc *cb, void *opaque)
-{
- IscsiLun *iscsilun = bs->opaque;
- IscsiAIOCB *acb;
-
- acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
-
- acb->iscsilun = iscsilun;
- acb->nb_sectors = nb_sectors;
- acb->sector_num = sector_num;
- acb->retries = ISCSI_CMD_RETRIES;
-
- if (iscsi_aio_discard_acb(acb) != 0) {
- qemu_aio_release(acb);
- return NULL;
- }
-
- iscsi_set_events(iscsilun);
-
- return &acb->common;
-}
-
#ifdef __linux__
static void
iscsi_aio_ioctl_cb(struct iscsi_context *iscsi, int status,
@@ -985,6 +904,77 @@ out:
return ret;
}
+static int
+coroutine_fn iscsi_co_discard(BlockDriverState *bs, int64_t sector_num,
+ int nb_sectors)
+{
+ IscsiLun *iscsilun = bs->opaque;
+ struct IscsiTask iTask;
+ struct unmap_list list;
+ uint32_t nb_blocks;
+ uint32_t max_unmap;
+
+ if (!is_request_lun_aligned(sector_num, nb_sectors, iscsilun)) {
+ return -EINVAL;
+ }
+
+ if (!iscsilun->lbp.lbpu) {
+ /* UNMAP is not supported by the target */
+ return 0;
+ }