|
|
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 |
|