Blame SOURCES/kvm-iscsi-split-discard-requests-in-multiple-parts.patch.patch.patch

0a122b
From 2865e534fce4969a316a5ba764b65e540da08cee Mon Sep 17 00:00:00 2001
0a122b
Message-Id: <2865e534fce4969a316a5ba764b65e540da08cee.1389014116.git.minovotn@redhat.com>
0a122b
In-Reply-To: <c8cc35838d42aa286242772d97e3a9be7bb786ba.1389014116.git.minovotn@redhat.com>
0a122b
References: <c8cc35838d42aa286242772d97e3a9be7bb786ba.1389014116.git.minovotn@redhat.com>
0a122b
From: Paolo Bonzini <pbonzini@redhat.com>
0a122b
Date: Mon, 9 Dec 2013 14:08:53 +0100
0a122b
Subject: [PATCH 05/50] iscsi: split discard requests in multiple parts
0a122b
0a122b
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
0a122b
Message-id: <1386598178-11845-8-git-send-email-pbonzini@redhat.com>
0a122b
Patchwork-id: 56044
0a122b
O-Subject: [RHEL 7.0 qemu-kvm PATCH 07/52] iscsi: split discard requests in multiple parts
0a122b
Bugzilla: 1007815
0a122b
RH-Acked-by: Jeffrey Cody <jcody@redhat.com>
0a122b
RH-Acked-by: Fam Zheng <famz@redhat.com>
0a122b
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
0a122b
0a122b
From: Peter Lieven <pl@kamp.de>
0a122b
0a122b
Replace .bdrv_aio_discard with .bdrv_co_discard so that discard
0a122b
requests can be split in multiple parts, each for a small amount
0a122b
of sectors.
0a122b
0a122b
This is useful because we expose a generic API with no limit
0a122b
on the amount of sectors that can be unmapped in one request.
0a122b
0a122b
Signed-off-by: Peter Lieven <pl@kamp.de>
0a122b
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
0a122b
(cherry picked from commit 65f3e33964bc4bb634d61463814a4ccca794e3c0)
0a122b
---
0a122b
 block/iscsi.c | 156 +++++++++++++++++++++++++++-------------------------------
0a122b
 1 file changed, 73 insertions(+), 83 deletions(-)
0a122b
0a122b
Signed-off-by: Michal Novotny <minovotn@redhat.com>
0a122b
---
0a122b
 block/iscsi.c | 156 +++++++++++++++++++++++++++-------------------------------
0a122b
 1 file changed, 73 insertions(+), 83 deletions(-)
0a122b
0a122b
diff --git a/block/iscsi.c b/block/iscsi.c
0a122b
index f8d021a..3a34eb7 100644
0a122b
--- a/block/iscsi.c
0a122b
+++ b/block/iscsi.c
0a122b
@@ -87,6 +87,7 @@ typedef struct IscsiAIOCB {
0a122b
 #define NOP_INTERVAL 5000
0a122b
 #define MAX_NOP_FAILURES 3
0a122b
 #define ISCSI_CMD_RETRIES 5
0a122b
+#define ISCSI_MAX_UNMAP 131072
0a122b
 
0a122b
 static void
0a122b
 iscsi_bh_cb(void *p)
0a122b
@@ -624,88 +625,6 @@ iscsi_aio_flush(BlockDriverState *bs,
0a122b
     return &acb->common;
0a122b
 }
0a122b
 
0a122b
-static int iscsi_aio_discard_acb(IscsiAIOCB *acb);
0a122b
-
0a122b
-static void
0a122b
-iscsi_unmap_cb(struct iscsi_context *iscsi, int status,
0a122b
-                     void *command_data, void *opaque)
0a122b
-{
0a122b
-    IscsiAIOCB *acb = opaque;
0a122b
-
0a122b
-    if (acb->canceled != 0) {
0a122b
-        return;
0a122b
-    }
0a122b
-
0a122b
-    acb->status = 0;
0a122b
-    if (status != 0) {
0a122b
-        if (status == SCSI_STATUS_CHECK_CONDITION
0a122b
-            && acb->task->sense.key == SCSI_SENSE_UNIT_ATTENTION
0a122b
-            && acb->retries-- > 0) {
0a122b
-            scsi_free_scsi_task(acb->task);
0a122b
-            acb->task = NULL;
0a122b
-            if (iscsi_aio_discard_acb(acb) == 0) {
0a122b
-                iscsi_set_events(acb->iscsilun);
0a122b
-                return;
0a122b
-            }
0a122b
-        }
0a122b
-        error_report("Failed to unmap data on iSCSI lun. %s",
0a122b
-                     iscsi_get_error(iscsi));
0a122b
-        acb->status = -EIO;
0a122b
-    }
0a122b
-
0a122b
-    iscsi_schedule_bh(acb);
0a122b
-}
0a122b
-
0a122b
-static int iscsi_aio_discard_acb(IscsiAIOCB *acb) {
0a122b
-    struct iscsi_context *iscsi = acb->iscsilun->iscsi;
0a122b
-    struct unmap_list list[1];
0a122b
-
0a122b
-    acb->canceled   = 0;
0a122b
-    acb->bh         = NULL;
0a122b
-    acb->status     = -EINPROGRESS;
0a122b
-    acb->buf        = NULL;
0a122b
-
0a122b
-    list[0].lba = sector_qemu2lun(acb->sector_num, acb->iscsilun);
0a122b
-    list[0].num = acb->nb_sectors * BDRV_SECTOR_SIZE / acb->iscsilun->block_size;
0a122b
-
0a122b
-    acb->task = iscsi_unmap_task(iscsi, acb->iscsilun->lun,
0a122b
-                                 0, 0, &list[0], 1,
0a122b
-                                 iscsi_unmap_cb,
0a122b
-                                 acb);
0a122b
-    if (acb->task == NULL) {
0a122b
-        error_report("iSCSI: Failed to send unmap command. %s",
0a122b
-                     iscsi_get_error(iscsi));
0a122b
-        return -1;
0a122b
-    }
0a122b
-
0a122b
-    return 0;
0a122b
-}
0a122b
-
0a122b
-static BlockDriverAIOCB *
0a122b
-iscsi_aio_discard(BlockDriverState *bs,
0a122b
-                  int64_t sector_num, int nb_sectors,
0a122b
-                  BlockDriverCompletionFunc *cb, void *opaque)
0a122b
-{
0a122b
-    IscsiLun *iscsilun = bs->opaque;
0a122b
-    IscsiAIOCB *acb;
0a122b
-
0a122b
-    acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
0a122b
-
0a122b
-    acb->iscsilun    = iscsilun;
0a122b
-    acb->nb_sectors  = nb_sectors;
0a122b
-    acb->sector_num  = sector_num;
0a122b
-    acb->retries     = ISCSI_CMD_RETRIES;
0a122b
-
0a122b
-    if (iscsi_aio_discard_acb(acb) != 0) {
0a122b
-        qemu_aio_release(acb);
0a122b
-        return NULL;
0a122b
-    }
0a122b
-
0a122b
-    iscsi_set_events(iscsilun);
0a122b
-
0a122b
-    return &acb->common;
0a122b
-}
0a122b
-
0a122b
 #ifdef __linux__
0a122b
 static void
0a122b
 iscsi_aio_ioctl_cb(struct iscsi_context *iscsi, int status,
0a122b
@@ -988,6 +907,77 @@ out:
0a122b
     return ret;
0a122b
 }
0a122b
 
0a122b
+static int
0a122b
+coroutine_fn iscsi_co_discard(BlockDriverState *bs, int64_t sector_num,
0a122b
+                                   int nb_sectors)
0a122b
+{
0a122b
+    IscsiLun *iscsilun = bs->opaque;
0a122b
+    struct IscsiTask iTask;
0a122b
+    struct unmap_list list;
0a122b
+    uint32_t nb_blocks;
0a122b
+    uint32_t max_unmap;
0a122b
+
0a122b
+    if (!is_request_lun_aligned(sector_num, nb_sectors, iscsilun)) {
0a122b
+        return -EINVAL;
0a122b
+    }
0a122b
+
0a122b
+    if (!iscsilun->lbp.lbpu) {
0a122b
+        /* UNMAP is not supported by the target */
0a122b
+        return 0;
0a122b
+    }
0a122b
+
0a122b
+    list.lba = sector_qemu2lun(sector_num, iscsilun);
0a122b
+    nb_blocks = sector_qemu2lun(nb_sectors, iscsilun);
0a122b
+
0a122b
+    max_unmap = iscsilun->bl.max_unmap;
0a122b
+    if (max_unmap == 0xffffffff) {
0a122b
+        max_unmap = ISCSI_MAX_UNMAP;
0a122b
+    }
0a122b
+
0a122b
+    while (nb_blocks > 0) {
0a122b
+        iscsi_co_init_iscsitask(iscsilun, &iTask);
0a122b
+        list.num = nb_blocks;
0a122b
+        if (list.num > max_unmap) {
0a122b
+            list.num = max_unmap;
0a122b
+        }
0a122b
+retry:
0a122b
+        if (iscsi_unmap_task(iscsilun->iscsi, iscsilun->lun, 0, 0, &list, 1,
0a122b
+                         iscsi_co_generic_cb, &iTask) == NULL) {
0a122b
+            return -EIO;
0a122b
+        }
0a122b
+
0a122b
+        while (!iTask.complete) {
0a122b
+            iscsi_set_events(iscsilun);
0a122b
+            qemu_coroutine_yield();
0a122b
+        }
0a122b
+
0a122b
+        if (iTask.task != NULL) {
0a122b
+            scsi_free_scsi_task(iTask.task);
0a122b
+            iTask.task = NULL;
0a122b
+        }
0a122b
+
0a122b
+        if (iTask.do_retry) {
0a122b
+            goto retry;
0a122b
+        }
0a122b
+
0a122b
+        if (iTask.status == SCSI_STATUS_CHECK_CONDITION) {
0a122b
+            /* the target might fail with a check condition if it
0a122b
+               is not happy with the alignment of the UNMAP request
0a122b
+               we silently fail in this case */
0a122b
+            return 0;
0a122b
+        }
0a122b
+
0a122b
+        if (iTask.status != SCSI_STATUS_GOOD) {
0a122b
+            return -EIO;
0a122b
+        }
0a122b
+
0a122b
+        list.lba += list.num;
0a122b
+        nb_blocks -= list.num;
0a122b
+    }
0a122b
+
0a122b
+    return 0;
0a122b
+}
0a122b
+
0a122b
 static int parse_chap(struct iscsi_context *iscsi, const char *target)
0a122b
 {
0a122b
     QemuOptsList *list;
0a122b
@@ -1541,12 +1531,12 @@ static BlockDriver bdrv_iscsi = {
0a122b
     .bdrv_truncate   = iscsi_truncate,
0a122b
 
0a122b
     .bdrv_co_get_block_status = iscsi_co_get_block_status,
0a122b
+    .bdrv_co_discard      = iscsi_co_discard,
0a122b
 
0a122b
     .bdrv_aio_readv  = iscsi_aio_readv,
0a122b
     .bdrv_aio_writev = iscsi_aio_writev,
0a122b
     .bdrv_aio_flush  = iscsi_aio_flush,
0a122b
 
0a122b
-    .bdrv_aio_discard = iscsi_aio_discard,
0a122b
     .bdrv_has_zero_init = iscsi_has_zero_init,
0a122b
 
0a122b
 #ifdef __linux__
0a122b
-- 
0a122b
1.7.11.7
0a122b