yeahuh / rpms / qemu-kvm

Forked from rpms/qemu-kvm 2 years ago
Clone

Blame SOURCES/kvm-iscsi-add-.bdrv_get_block_status.patch.patch.patch

9ae3a8
From a976099b24c5db9cb4ab1a059b01610d2fc48537 Mon Sep 17 00:00:00 2001
9ae3a8
Message-Id: <a976099b24c5db9cb4ab1a059b01610d2fc48537.1389014116.git.minovotn@redhat.com>
9ae3a8
In-Reply-To: <c8cc35838d42aa286242772d97e3a9be7bb786ba.1389014116.git.minovotn@redhat.com>
9ae3a8
References: <c8cc35838d42aa286242772d97e3a9be7bb786ba.1389014116.git.minovotn@redhat.com>
9ae3a8
From: Paolo Bonzini <pbonzini@redhat.com>
9ae3a8
Date: Mon, 9 Dec 2013 14:08:52 +0100
9ae3a8
Subject: [PATCH 04/50] iscsi: add .bdrv_get_block_status
9ae3a8
9ae3a8
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
9ae3a8
Message-id: <1386598178-11845-7-git-send-email-pbonzini@redhat.com>
9ae3a8
Patchwork-id: 56043
9ae3a8
O-Subject: [RHEL 7.0 qemu-kvm PATCH 06/52] iscsi: add .bdrv_get_block_status
9ae3a8
Bugzilla: 1007815
9ae3a8
RH-Acked-by: Jeffrey Cody <jcody@redhat.com>
9ae3a8
RH-Acked-by: Fam Zheng <famz@redhat.com>
9ae3a8
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
9ae3a8
9ae3a8
From: Peter Lieven <pl@kamp.de>
9ae3a8
9ae3a8
this patch adds a coroutine for .bdrv_co_block_status as well as
9ae3a8
a generic framework that can be used to build coroutines in block/iscsi.
9ae3a8
9ae3a8
Signed-off-by: Peter Lieven <pl@kamp.de>
9ae3a8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
9ae3a8
(cherry picked from commit 54a5c1d5db47b4146490937ed73e3f56022aaba6)
9ae3a8
---
9ae3a8
 block/iscsi.c | 136 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
9ae3a8
 1 file changed, 136 insertions(+)
9ae3a8
9ae3a8
Signed-off-by: Michal Novotny <minovotn@redhat.com>
9ae3a8
---
9ae3a8
 block/iscsi.c | 136 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
9ae3a8
 1 file changed, 136 insertions(+)
9ae3a8
9ae3a8
diff --git a/block/iscsi.c b/block/iscsi.c
9ae3a8
index 6804b6d..f8d021a 100644
9ae3a8
--- a/block/iscsi.c
9ae3a8
+++ b/block/iscsi.c
9ae3a8
@@ -58,6 +58,15 @@ typedef struct IscsiLun {
9ae3a8
     struct scsi_inquiry_block_limits bl;
9ae3a8
 } IscsiLun;
9ae3a8
 
9ae3a8
+typedef struct IscsiTask {
9ae3a8
+    int status;
9ae3a8
+    int complete;
9ae3a8
+    int retries;
9ae3a8
+    int do_retry;
9ae3a8
+    struct scsi_task *task;
9ae3a8
+    Coroutine *co;
9ae3a8
+} IscsiTask;
9ae3a8
+
9ae3a8
 typedef struct IscsiAIOCB {
9ae3a8
     BlockDriverAIOCB common;
9ae3a8
     QEMUIOVector *qiov;
9ae3a8
@@ -111,6 +120,41 @@ iscsi_schedule_bh(IscsiAIOCB *acb)
9ae3a8
     qemu_bh_schedule(acb->bh);
9ae3a8
 }
9ae3a8
 
9ae3a8
+static void
9ae3a8
+iscsi_co_generic_cb(struct iscsi_context *iscsi, int status,
9ae3a8
+                        void *command_data, void *opaque)
9ae3a8
+{
9ae3a8
+    struct IscsiTask *iTask = opaque;
9ae3a8
+    struct scsi_task *task = command_data;
9ae3a8
+
9ae3a8
+    iTask->complete = 1;
9ae3a8
+    iTask->status = status;
9ae3a8
+    iTask->do_retry = 0;
9ae3a8
+    iTask->task = task;
9ae3a8
+
9ae3a8
+    if (iTask->retries-- > 0 && status == SCSI_STATUS_CHECK_CONDITION
9ae3a8
+        && task->sense.key == SCSI_SENSE_UNIT_ATTENTION) {
9ae3a8
+        iTask->do_retry = 1;
9ae3a8
+        goto out;
9ae3a8
+    }
9ae3a8
+
9ae3a8
+    if (status != SCSI_STATUS_GOOD) {
9ae3a8
+        error_report("iSCSI: Failure. %s", iscsi_get_error(iscsi));
9ae3a8
+    }
9ae3a8
+
9ae3a8
+out:
9ae3a8
+    if (iTask->co) {
9ae3a8
+        qemu_coroutine_enter(iTask->co, NULL);
9ae3a8
+    }
9ae3a8
+}
9ae3a8
+
9ae3a8
+static void iscsi_co_init_iscsitask(IscsiLun *iscsilun, struct IscsiTask *iTask)
9ae3a8
+{
9ae3a8
+    *iTask = (struct IscsiTask) {
9ae3a8
+        .co         = qemu_coroutine_self(),
9ae3a8
+        .retries    = ISCSI_CMD_RETRIES,
9ae3a8
+    };
9ae3a8
+}
9ae3a8
 
9ae3a8
 static void
9ae3a8
 iscsi_abort_task_cb(struct iscsi_context *iscsi, int status, void *command_data,
9ae3a8
@@ -854,6 +898,96 @@ iscsi_getlength(BlockDriverState *bs)
9ae3a8
     return len;
9ae3a8
 }
9ae3a8
 
9ae3a8
+static int64_t coroutine_fn iscsi_co_get_block_status(BlockDriverState *bs,
9ae3a8
+                                                  int64_t sector_num,
9ae3a8
+                                                  int nb_sectors, int *pnum)
9ae3a8
+{
9ae3a8
+    IscsiLun *iscsilun = bs->opaque;
9ae3a8
+    struct scsi_get_lba_status *lbas = NULL;
9ae3a8
+    struct scsi_lba_status_descriptor *lbasd = NULL;
9ae3a8
+    struct IscsiTask iTask;
9ae3a8
+    int64_t ret;
9ae3a8
+
9ae3a8
+    iscsi_co_init_iscsitask(iscsilun, &iTask);
9ae3a8
+
9ae3a8
+    if (!is_request_lun_aligned(sector_num, nb_sectors, iscsilun)) {
9ae3a8
+        ret = -EINVAL;
9ae3a8
+        goto out;
9ae3a8
+    }
9ae3a8
+
9ae3a8
+    /* default to all sectors allocated */
9ae3a8
+    ret = BDRV_BLOCK_DATA;
9ae3a8
+    ret |= (sector_num << BDRV_SECTOR_BITS) | BDRV_BLOCK_OFFSET_VALID;
9ae3a8
+    *pnum = nb_sectors;
9ae3a8
+
9ae3a8
+    /* LUN does not support logical block provisioning */
9ae3a8
+    if (iscsilun->lbpme == 0) {
9ae3a8
+        goto out;
9ae3a8
+    }
9ae3a8
+
9ae3a8
+retry:
9ae3a8
+    if (iscsi_get_lba_status_task(iscsilun->iscsi, iscsilun->lun,
9ae3a8
+                                  sector_qemu2lun(sector_num, iscsilun),
9ae3a8
+                                  8 + 16, iscsi_co_generic_cb,
9ae3a8
+                                  &iTask) == NULL) {
9ae3a8
+        ret = -EIO;
9ae3a8
+        goto out;
9ae3a8
+    }
9ae3a8
+
9ae3a8
+    while (!iTask.complete) {
9ae3a8
+        iscsi_set_events(iscsilun);
9ae3a8
+        qemu_coroutine_yield();
9ae3a8
+    }
9ae3a8
+
9ae3a8
+    if (iTask.do_retry) {
9ae3a8
+        if (iTask.task != NULL) {
9ae3a8
+            scsi_free_scsi_task(iTask.task);
9ae3a8
+            iTask.task = NULL;
9ae3a8
+        }
9ae3a8
+        goto retry;
9ae3a8
+    }
9ae3a8
+
9ae3a8
+    if (iTask.status != SCSI_STATUS_GOOD) {
9ae3a8
+        /* in case the get_lba_status_callout fails (i.e.
9ae3a8
+         * because the device is busy or the cmd is not
9ae3a8
+         * supported) we pretend all blocks are allocated
9ae3a8
+         * for backwards compatiblity */
9ae3a8
+        goto out;
9ae3a8
+    }
9ae3a8
+
9ae3a8
+    lbas = scsi_datain_unmarshall(iTask.task);
9ae3a8
+    if (lbas == NULL) {
9ae3a8
+        ret = -EIO;
9ae3a8
+        goto out;
9ae3a8
+    }
9ae3a8
+
9ae3a8
+    lbasd = &lbas->descriptors[0];
9ae3a8
+
9ae3a8
+    if (sector_qemu2lun(sector_num, iscsilun) != lbasd->lba) {
9ae3a8
+        ret = -EIO;
9ae3a8
+        goto out;
9ae3a8
+    }
9ae3a8
+
9ae3a8
+    *pnum = sector_lun2qemu(lbasd->num_blocks, iscsilun);
9ae3a8
+    if (*pnum > nb_sectors) {
9ae3a8
+        *pnum = nb_sectors;
9ae3a8
+    }
9ae3a8
+
9ae3a8
+    if (lbasd->provisioning == SCSI_PROVISIONING_TYPE_DEALLOCATED ||
9ae3a8
+        lbasd->provisioning == SCSI_PROVISIONING_TYPE_ANCHORED) {
9ae3a8
+        ret &= ~BDRV_BLOCK_DATA;
9ae3a8
+        if (iscsilun->lbprz) {
9ae3a8
+            ret |= BDRV_BLOCK_ZERO;
9ae3a8
+        }
9ae3a8
+    }
9ae3a8
+
9ae3a8
+out:
9ae3a8
+    if (iTask.task != NULL) {
9ae3a8
+        scsi_free_scsi_task(iTask.task);
9ae3a8
+    }
9ae3a8
+    return ret;
9ae3a8
+}
9ae3a8
+
9ae3a8
 static int parse_chap(struct iscsi_context *iscsi, const char *target)
9ae3a8
 {
9ae3a8
     QemuOptsList *list;
9ae3a8
@@ -1406,6 +1540,8 @@ static BlockDriver bdrv_iscsi = {
9ae3a8
     .bdrv_getlength  = iscsi_getlength,
9ae3a8
     .bdrv_truncate   = iscsi_truncate,
9ae3a8
 
9ae3a8
+    .bdrv_co_get_block_status = iscsi_co_get_block_status,
9ae3a8
+
9ae3a8
     .bdrv_aio_readv  = iscsi_aio_readv,
9ae3a8
     .bdrv_aio_writev = iscsi_aio_writev,
9ae3a8
     .bdrv_aio_flush  = iscsi_aio_flush,
9ae3a8
-- 
9ae3a8
1.7.11.7
9ae3a8