Blame SOURCES/kvm-block-return-get_block_status-data-and-flags-for-for.patch

9ae3a8
From 90d033044f22ff96e5fc7c409934f7318d03f103 Mon Sep 17 00:00:00 2001
9ae3a8
From: Paolo Bonzini <pbonzini@redhat.com>
9ae3a8
Date: Fri, 18 Oct 2013 08:14:39 +0200
9ae3a8
Subject: [PATCH 14/81] block: return get_block_status data and flags for formats
9ae3a8
9ae3a8
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
9ae3a8
Message-id: <1382084091-16636-15-git-send-email-pbonzini@redhat.com>
9ae3a8
Patchwork-id: 54996
9ae3a8
O-Subject: [RHEL 7.0 qemu-kvm PATCH 14/26] block: return get_block_status data and flags for formats
9ae3a8
Bugzilla: 989646
9ae3a8
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
9ae3a8
RH-Acked-by: Max Reitz <mreitz@redhat.com>
9ae3a8
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
9ae3a8
9ae3a8
Reviewed-by: Eric Blake <eblake@redhat.com>
9ae3a8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
9ae3a8
(cherry picked from commit 4bc74be997a72922170f4f272fd5e8074a3ecc27)
9ae3a8
---
9ae3a8
 block/cow.c      |  8 +++++++-
9ae3a8
 block/qcow.c     |  9 ++++++++-
9ae3a8
 block/qcow2.c    | 16 ++++++++++++++--
9ae3a8
 block/qed.c      | 35 ++++++++++++++++++++++++++++-------
9ae3a8
 block/sheepdog.c |  2 +-
9ae3a8
 block/vdi.c      | 13 ++++++++++++-
9ae3a8
 block/vmdk.c     | 19 ++++++++++++++++++-
9ae3a8
 block/vvfat.c    | 11 ++++++-----
9ae3a8
 8 files changed, 94 insertions(+), 19 deletions(-)
9ae3a8
9ae3a8
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
9ae3a8
---
9ae3a8
 block/cow.c      |    8 +++++++-
9ae3a8
 block/qcow.c     |    9 ++++++++-
9ae3a8
 block/qcow2.c    |   16 ++++++++++++++--
9ae3a8
 block/qed.c      |   35 ++++++++++++++++++++++++++++-------
9ae3a8
 block/sheepdog.c |    2 +-
9ae3a8
 block/vdi.c      |   13 ++++++++++++-
9ae3a8
 block/vmdk.c     |   19 ++++++++++++++++++-
9ae3a8
 block/vvfat.c    |   11 ++++++-----
9ae3a8
 8 files changed, 94 insertions(+), 19 deletions(-)
9ae3a8
9ae3a8
diff --git a/block/cow.c b/block/cow.c
9ae3a8
index 5e71c76..6958808 100644
9ae3a8
--- a/block/cow.c
9ae3a8
+++ b/block/cow.c
9ae3a8
@@ -191,7 +191,13 @@ static int coroutine_fn cow_co_is_allocated(BlockDriverState *bs,
9ae3a8
 static int64_t coroutine_fn cow_co_get_block_status(BlockDriverState *bs,
9ae3a8
         int64_t sector_num, int nb_sectors, int *num_same)
9ae3a8
 {
9ae3a8
-    return cow_co_is_allocated(bs, sector_num, nb_sectors, num_same);
9ae3a8
+    BDRVCowState *s = bs->opaque;
9ae3a8
+    int ret = cow_co_is_allocated(bs, sector_num, nb_sectors, num_same);
9ae3a8
+    int64_t offset = s->cow_sectors_offset + (sector_num << BDRV_SECTOR_BITS);
9ae3a8
+    if (ret < 0) {
9ae3a8
+        return ret;
9ae3a8
+    }
9ae3a8
+    return (ret ? BDRV_BLOCK_DATA : 0) | offset | BDRV_BLOCK_OFFSET_VALID;
9ae3a8
 }
9ae3a8
 
9ae3a8
 static int cow_update_bitmap(BlockDriverState *bs, int64_t sector_num,
9ae3a8
diff --git a/block/qcow.c b/block/qcow.c
9ae3a8
index 05af25c..4ab552e 100644
9ae3a8
--- a/block/qcow.c
9ae3a8
+++ b/block/qcow.c
9ae3a8
@@ -410,7 +410,14 @@ static int64_t coroutine_fn qcow_co_get_block_status(BlockDriverState *bs,
9ae3a8
     if (n > nb_sectors)
9ae3a8
         n = nb_sectors;
9ae3a8
     *pnum = n;
9ae3a8
-    return (cluster_offset != 0);
9ae3a8
+    if (!cluster_offset) {
9ae3a8
+        return 0;
9ae3a8
+    }
9ae3a8
+    if ((cluster_offset & QCOW_OFLAG_COMPRESSED) || s->crypt_method) {
9ae3a8
+        return BDRV_BLOCK_DATA;
9ae3a8
+    }
9ae3a8
+    cluster_offset |= (index_in_cluster << BDRV_SECTOR_BITS);
9ae3a8
+    return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | cluster_offset;
9ae3a8
 }
9ae3a8
 
9ae3a8
 static int decompress_buffer(uint8_t *out_buf, int out_buf_size,
9ae3a8
diff --git a/block/qcow2.c b/block/qcow2.c
9ae3a8
index 8d3bf5d..8e894b9 100644
9ae3a8
--- a/block/qcow2.c
9ae3a8
+++ b/block/qcow2.c
9ae3a8
@@ -645,7 +645,8 @@ static int64_t coroutine_fn qcow2_co_get_block_status(BlockDriverState *bs,
9ae3a8
 {
9ae3a8
     BDRVQcowState *s = bs->opaque;
9ae3a8
     uint64_t cluster_offset;
9ae3a8
-    int ret;
9ae3a8
+    int index_in_cluster, ret;
9ae3a8
+    int64_t status = 0;
9ae3a8
 
9ae3a8
     *pnum = nb_sectors;
9ae3a8
     qemu_co_mutex_lock(&s->lock);
9ae3a8
@@ -655,7 +656,18 @@ static int64_t coroutine_fn qcow2_co_get_block_status(BlockDriverState *bs,
9ae3a8
         return ret;
9ae3a8
     }
9ae3a8
 
9ae3a8
-    return (cluster_offset != 0) || (ret == QCOW2_CLUSTER_ZERO);
9ae3a8
+    if (cluster_offset != 0 && ret != QCOW2_CLUSTER_COMPRESSED &&
9ae3a8
+        !s->crypt_method) {
9ae3a8
+        index_in_cluster = sector_num & (s->cluster_sectors - 1);
9ae3a8
+        cluster_offset |= (index_in_cluster << BDRV_SECTOR_BITS);
9ae3a8
+        status |= BDRV_BLOCK_OFFSET_VALID | cluster_offset;
9ae3a8
+    }
9ae3a8
+    if (ret == QCOW2_CLUSTER_ZERO) {
9ae3a8
+        status |= BDRV_BLOCK_ZERO;
9ae3a8
+    } else if (ret != QCOW2_CLUSTER_UNALLOCATED) {
9ae3a8
+        status |= BDRV_BLOCK_DATA;
9ae3a8
+    }
9ae3a8
+    return status;
9ae3a8
 }
9ae3a8
 
9ae3a8
 /* handle reading after the end of the backing file */
9ae3a8
diff --git a/block/qed.c b/block/qed.c
9ae3a8
index a573039..815ee1c 100644
9ae3a8
--- a/block/qed.c
9ae3a8
+++ b/block/qed.c
9ae3a8
@@ -652,16 +652,36 @@ static int bdrv_qed_create(const char *filename, QEMUOptionParameter *options)
9ae3a8
 }
9ae3a8
 
9ae3a8
 typedef struct {
9ae3a8
+    BlockDriverState *bs;
9ae3a8
     Coroutine *co;
9ae3a8
-    int is_allocated;
9ae3a8
+    uint64_t pos;
9ae3a8
+    int64_t status;
9ae3a8
     int *pnum;
9ae3a8
 } QEDIsAllocatedCB;
9ae3a8
 
9ae3a8
 static void qed_is_allocated_cb(void *opaque, int ret, uint64_t offset, size_t len)
9ae3a8
 {
9ae3a8
     QEDIsAllocatedCB *cb = opaque;
9ae3a8
+    BDRVQEDState *s = cb->bs->opaque;
9ae3a8
     *cb->pnum = len / BDRV_SECTOR_SIZE;
9ae3a8
-    cb->is_allocated = (ret == QED_CLUSTER_FOUND || ret == QED_CLUSTER_ZERO);
9ae3a8
+    switch (ret) {
9ae3a8
+    case QED_CLUSTER_FOUND:
9ae3a8
+        offset |= qed_offset_into_cluster(s, cb->pos);
9ae3a8
+        cb->status = BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | offset;
9ae3a8
+        break;
9ae3a8
+    case QED_CLUSTER_ZERO:
9ae3a8
+        cb->status = BDRV_BLOCK_ZERO;
9ae3a8
+        break;
9ae3a8
+    case QED_CLUSTER_L2:
9ae3a8
+    case QED_CLUSTER_L1:
9ae3a8
+        cb->status = 0;
9ae3a8
+        break;
9ae3a8
+    default:
9ae3a8
+        assert(ret < 0);
9ae3a8
+        cb->status = ret;
9ae3a8
+        break;
9ae3a8
+    }
9ae3a8
+
9ae3a8
     if (cb->co) {
9ae3a8
         qemu_coroutine_enter(cb->co, NULL);
9ae3a8
     }
9ae3a8
@@ -672,25 +692,26 @@ static int64_t coroutine_fn bdrv_qed_co_get_block_status(BlockDriverState *bs,
9ae3a8
                                                  int nb_sectors, int *pnum)
9ae3a8
 {
9ae3a8
     BDRVQEDState *s = bs->opaque;
9ae3a8
-    uint64_t pos = (uint64_t)sector_num * BDRV_SECTOR_SIZE;
9ae3a8
     size_t len = (size_t)nb_sectors * BDRV_SECTOR_SIZE;
9ae3a8
     QEDIsAllocatedCB cb = {
9ae3a8
-        .is_allocated = -1,
9ae3a8
+        .bs = bs,
9ae3a8
+        .pos = (uint64_t)sector_num * BDRV_SECTOR_SIZE,
9ae3a8
+        .status = BDRV_BLOCK_OFFSET_MASK,
9ae3a8
         .pnum = pnum,
9ae3a8
     };
9ae3a8
     QEDRequest request = { .l2_table = NULL };
9ae3a8
 
9ae3a8
-    qed_find_cluster(s, &request, pos, len, qed_is_allocated_cb, &cb;;
9ae3a8
+    qed_find_cluster(s, &request, cb.pos, len, qed_is_allocated_cb, &cb;;
9ae3a8
 
9ae3a8
     /* Now sleep if the callback wasn't invoked immediately */
9ae3a8
-    while (cb.is_allocated == -1) {
9ae3a8
+    while (cb.status == BDRV_BLOCK_OFFSET_MASK) {
9ae3a8
         cb.co = qemu_coroutine_self();
9ae3a8
         qemu_coroutine_yield();
9ae3a8
     }
9ae3a8
 
9ae3a8
     qed_unref_l2_cache_entry(request.l2_table);
9ae3a8
 
9ae3a8
-    return cb.is_allocated;
9ae3a8
+    return cb.status;
9ae3a8
 }
9ae3a8
 
9ae3a8
 static int bdrv_qed_make_empty(BlockDriverState *bs)
9ae3a8
diff --git a/block/sheepdog.c b/block/sheepdog.c
9ae3a8
index e5398bb..f7cc76e 100644
9ae3a8
--- a/block/sheepdog.c
9ae3a8
+++ b/block/sheepdog.c
9ae3a8
@@ -2299,7 +2299,7 @@ sd_co_get_block_status(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
9ae3a8
                   end = DIV_ROUND_UP((sector_num + nb_sectors) *
9ae3a8
                                      BDRV_SECTOR_SIZE, SD_DATA_OBJ_SIZE);
9ae3a8
     unsigned long idx;
9ae3a8
-    int ret = 1;
9ae3a8
+    int64_t ret = BDRV_BLOCK_DATA;
9ae3a8
 
9ae3a8
     for (idx = start; idx < end; idx++) {
9ae3a8
         if (inode->data_vdi_id[idx] == 0) {
9ae3a8
diff --git a/block/vdi.c b/block/vdi.c
9ae3a8
index 1252ad4..bc97c39 100644
9ae3a8
--- a/block/vdi.c
9ae3a8
+++ b/block/vdi.c
9ae3a8
@@ -479,12 +479,23 @@ static int64_t coroutine_fn vdi_co_get_block_status(BlockDriverState *bs,
9ae3a8
     size_t sector_in_block = sector_num % s->block_sectors;
9ae3a8
     int n_sectors = s->block_sectors - sector_in_block;
9ae3a8
     uint32_t bmap_entry = le32_to_cpu(s->bmap[bmap_index]);
9ae3a8
+    uint64_t offset;
9ae3a8
+    int result;
9ae3a8
+
9ae3a8
     logout("%p, %" PRId64 ", %d, %p\n", bs, sector_num, nb_sectors, pnum);
9ae3a8
     if (n_sectors > nb_sectors) {
9ae3a8
         n_sectors = nb_sectors;
9ae3a8
     }
9ae3a8
     *pnum = n_sectors;
9ae3a8
-    return VDI_IS_ALLOCATED(bmap_entry);
9ae3a8
+    result = VDI_IS_ALLOCATED(bmap_entry);
9ae3a8
+    if (!result) {
9ae3a8
+        return 0;
9ae3a8
+    }
9ae3a8
+
9ae3a8
+    offset = s->header.offset_data +
9ae3a8
+                              (uint64_t)bmap_entry * s->block_size +
9ae3a8
+                              sector_in_block * SECTOR_SIZE;
9ae3a8
+    return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | offset;
9ae3a8
 }
9ae3a8
 
9ae3a8
 static int vdi_co_read(BlockDriverState *bs,
9ae3a8
diff --git a/block/vmdk.c b/block/vmdk.c
9ae3a8
index a30c3b9..7456f9b 100644
9ae3a8
--- a/block/vmdk.c
9ae3a8
+++ b/block/vmdk.c
9ae3a8
@@ -1059,7 +1059,24 @@ static int64_t coroutine_fn vmdk_co_get_block_status(BlockDriverState *bs,
9ae3a8
                             sector_num * 512, 0, &offset);
9ae3a8
     qemu_co_mutex_unlock(&s->lock);
9ae3a8
 
9ae3a8
-    ret = (ret == VMDK_OK || ret == VMDK_ZEROED);
9ae3a8
+    switch (ret) {
9ae3a8
+    case VMDK_ERROR:
9ae3a8
+        ret = -EIO;
9ae3a8
+        break;
9ae3a8
+    case VMDK_UNALLOC:
9ae3a8
+        ret = 0;
9ae3a8
+        break;
9ae3a8
+    case VMDK_ZEROED:
9ae3a8
+        ret = BDRV_BLOCK_ZERO;
9ae3a8
+        break;
9ae3a8
+    case VMDK_OK:
9ae3a8
+        ret = BDRV_BLOCK_DATA;
9ae3a8
+        if (extent->file == bs->file) {
9ae3a8
+            ret |= BDRV_BLOCK_OFFSET_VALID | offset;
9ae3a8
+        }
9ae3a8
+
9ae3a8
+        break;
9ae3a8
+    }
9ae3a8
 
9ae3a8
     index_in_cluster = sector_num % extent->cluster_sectors;
9ae3a8
     n = extent->cluster_sectors - index_in_cluster;
9ae3a8
diff --git a/block/vvfat.c b/block/vvfat.c
9ae3a8
index 510a559..415fba3 100644
9ae3a8
--- a/block/vvfat.c
9ae3a8
+++ b/block/vvfat.c
9ae3a8
@@ -2879,11 +2879,12 @@ static int64_t coroutine_fn vvfat_co_get_block_status(BlockDriverState *bs,
9ae3a8
 {
9ae3a8
     BDRVVVFATState* s = bs->opaque;
9ae3a8
     *n = s->sector_count - sector_num;
9ae3a8
-    if (*n > nb_sectors)
9ae3a8
-	*n = nb_sectors;
9ae3a8
-    else if (*n < 0)
9ae3a8
-	return 0;
9ae3a8
-    return 1;
9ae3a8
+    if (*n > nb_sectors) {
9ae3a8
+        *n = nb_sectors;
9ae3a8
+    } else if (*n < 0) {
9ae3a8
+        return 0;
9ae3a8
+    }
9ae3a8
+    return BDRV_BLOCK_DATA;
9ae3a8
 }
9ae3a8
 
9ae3a8
 static int write_target_commit(BlockDriverState *bs, int64_t sector_num,
9ae3a8
-- 
9ae3a8
1.7.1
9ae3a8