mirror of https://github.com/xemu-project/xemu.git
block: return get_block_status data and flags for formats
Reviewed-by: Eric Blake <eblake@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
parent
4333bb7140
commit
4bc74be997
|
@ -191,7 +191,13 @@ static int coroutine_fn cow_co_is_allocated(BlockDriverState *bs,
|
||||||
static int64_t coroutine_fn cow_co_get_block_status(BlockDriverState *bs,
|
static int64_t coroutine_fn cow_co_get_block_status(BlockDriverState *bs,
|
||||||
int64_t sector_num, int nb_sectors, int *num_same)
|
int64_t sector_num, int nb_sectors, int *num_same)
|
||||||
{
|
{
|
||||||
return cow_co_is_allocated(bs, sector_num, nb_sectors, num_same);
|
BDRVCowState *s = bs->opaque;
|
||||||
|
int ret = cow_co_is_allocated(bs, sector_num, nb_sectors, num_same);
|
||||||
|
int64_t offset = s->cow_sectors_offset + (sector_num << BDRV_SECTOR_BITS);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
return (ret ? BDRV_BLOCK_DATA : 0) | offset | BDRV_BLOCK_OFFSET_VALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cow_update_bitmap(BlockDriverState *bs, int64_t sector_num,
|
static int cow_update_bitmap(BlockDriverState *bs, int64_t sector_num,
|
||||||
|
|
|
@ -410,7 +410,14 @@ static int64_t coroutine_fn qcow_co_get_block_status(BlockDriverState *bs,
|
||||||
if (n > nb_sectors)
|
if (n > nb_sectors)
|
||||||
n = nb_sectors;
|
n = nb_sectors;
|
||||||
*pnum = n;
|
*pnum = n;
|
||||||
return (cluster_offset != 0);
|
if (!cluster_offset) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if ((cluster_offset & QCOW_OFLAG_COMPRESSED) || s->crypt_method) {
|
||||||
|
return BDRV_BLOCK_DATA;
|
||||||
|
}
|
||||||
|
cluster_offset |= (index_in_cluster << BDRV_SECTOR_BITS);
|
||||||
|
return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | cluster_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int decompress_buffer(uint8_t *out_buf, int out_buf_size,
|
static int decompress_buffer(uint8_t *out_buf, int out_buf_size,
|
||||||
|
|
|
@ -693,7 +693,8 @@ static int64_t coroutine_fn qcow2_co_get_block_status(BlockDriverState *bs,
|
||||||
{
|
{
|
||||||
BDRVQcowState *s = bs->opaque;
|
BDRVQcowState *s = bs->opaque;
|
||||||
uint64_t cluster_offset;
|
uint64_t cluster_offset;
|
||||||
int ret;
|
int index_in_cluster, ret;
|
||||||
|
int64_t status = 0;
|
||||||
|
|
||||||
*pnum = nb_sectors;
|
*pnum = nb_sectors;
|
||||||
qemu_co_mutex_lock(&s->lock);
|
qemu_co_mutex_lock(&s->lock);
|
||||||
|
@ -703,7 +704,18 @@ static int64_t coroutine_fn qcow2_co_get_block_status(BlockDriverState *bs,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (cluster_offset != 0) || (ret == QCOW2_CLUSTER_ZERO);
|
if (cluster_offset != 0 && ret != QCOW2_CLUSTER_COMPRESSED &&
|
||||||
|
!s->crypt_method) {
|
||||||
|
index_in_cluster = sector_num & (s->cluster_sectors - 1);
|
||||||
|
cluster_offset |= (index_in_cluster << BDRV_SECTOR_BITS);
|
||||||
|
status |= BDRV_BLOCK_OFFSET_VALID | cluster_offset;
|
||||||
|
}
|
||||||
|
if (ret == QCOW2_CLUSTER_ZERO) {
|
||||||
|
status |= BDRV_BLOCK_ZERO;
|
||||||
|
} else if (ret != QCOW2_CLUSTER_UNALLOCATED) {
|
||||||
|
status |= BDRV_BLOCK_DATA;
|
||||||
|
}
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* handle reading after the end of the backing file */
|
/* handle reading after the end of the backing file */
|
||||||
|
|
35
block/qed.c
35
block/qed.c
|
@ -652,16 +652,36 @@ static int bdrv_qed_create(const char *filename, QEMUOptionParameter *options)
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
BlockDriverState *bs;
|
||||||
Coroutine *co;
|
Coroutine *co;
|
||||||
int is_allocated;
|
uint64_t pos;
|
||||||
|
int64_t status;
|
||||||
int *pnum;
|
int *pnum;
|
||||||
} QEDIsAllocatedCB;
|
} QEDIsAllocatedCB;
|
||||||
|
|
||||||
static void qed_is_allocated_cb(void *opaque, int ret, uint64_t offset, size_t len)
|
static void qed_is_allocated_cb(void *opaque, int ret, uint64_t offset, size_t len)
|
||||||
{
|
{
|
||||||
QEDIsAllocatedCB *cb = opaque;
|
QEDIsAllocatedCB *cb = opaque;
|
||||||
|
BDRVQEDState *s = cb->bs->opaque;
|
||||||
*cb->pnum = len / BDRV_SECTOR_SIZE;
|
*cb->pnum = len / BDRV_SECTOR_SIZE;
|
||||||
cb->is_allocated = (ret == QED_CLUSTER_FOUND || ret == QED_CLUSTER_ZERO);
|
switch (ret) {
|
||||||
|
case QED_CLUSTER_FOUND:
|
||||||
|
offset |= qed_offset_into_cluster(s, cb->pos);
|
||||||
|
cb->status = BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | offset;
|
||||||
|
break;
|
||||||
|
case QED_CLUSTER_ZERO:
|
||||||
|
cb->status = BDRV_BLOCK_ZERO;
|
||||||
|
break;
|
||||||
|
case QED_CLUSTER_L2:
|
||||||
|
case QED_CLUSTER_L1:
|
||||||
|
cb->status = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(ret < 0);
|
||||||
|
cb->status = ret;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (cb->co) {
|
if (cb->co) {
|
||||||
qemu_coroutine_enter(cb->co, NULL);
|
qemu_coroutine_enter(cb->co, NULL);
|
||||||
}
|
}
|
||||||
|
@ -672,25 +692,26 @@ static int64_t coroutine_fn bdrv_qed_co_get_block_status(BlockDriverState *bs,
|
||||||
int nb_sectors, int *pnum)
|
int nb_sectors, int *pnum)
|
||||||
{
|
{
|
||||||
BDRVQEDState *s = bs->opaque;
|
BDRVQEDState *s = bs->opaque;
|
||||||
uint64_t pos = (uint64_t)sector_num * BDRV_SECTOR_SIZE;
|
|
||||||
size_t len = (size_t)nb_sectors * BDRV_SECTOR_SIZE;
|
size_t len = (size_t)nb_sectors * BDRV_SECTOR_SIZE;
|
||||||
QEDIsAllocatedCB cb = {
|
QEDIsAllocatedCB cb = {
|
||||||
.is_allocated = -1,
|
.bs = bs,
|
||||||
|
.pos = (uint64_t)sector_num * BDRV_SECTOR_SIZE,
|
||||||
|
.status = BDRV_BLOCK_OFFSET_MASK,
|
||||||
.pnum = pnum,
|
.pnum = pnum,
|
||||||
};
|
};
|
||||||
QEDRequest request = { .l2_table = NULL };
|
QEDRequest request = { .l2_table = NULL };
|
||||||
|
|
||||||
qed_find_cluster(s, &request, pos, len, qed_is_allocated_cb, &cb);
|
qed_find_cluster(s, &request, cb.pos, len, qed_is_allocated_cb, &cb);
|
||||||
|
|
||||||
/* Now sleep if the callback wasn't invoked immediately */
|
/* Now sleep if the callback wasn't invoked immediately */
|
||||||
while (cb.is_allocated == -1) {
|
while (cb.status == BDRV_BLOCK_OFFSET_MASK) {
|
||||||
cb.co = qemu_coroutine_self();
|
cb.co = qemu_coroutine_self();
|
||||||
qemu_coroutine_yield();
|
qemu_coroutine_yield();
|
||||||
}
|
}
|
||||||
|
|
||||||
qed_unref_l2_cache_entry(request.l2_table);
|
qed_unref_l2_cache_entry(request.l2_table);
|
||||||
|
|
||||||
return cb.is_allocated;
|
return cb.status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bdrv_qed_make_empty(BlockDriverState *bs)
|
static int bdrv_qed_make_empty(BlockDriverState *bs)
|
||||||
|
|
|
@ -2280,7 +2280,7 @@ sd_co_get_block_status(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
|
||||||
end = DIV_ROUND_UP((sector_num + nb_sectors) *
|
end = DIV_ROUND_UP((sector_num + nb_sectors) *
|
||||||
BDRV_SECTOR_SIZE, SD_DATA_OBJ_SIZE);
|
BDRV_SECTOR_SIZE, SD_DATA_OBJ_SIZE);
|
||||||
unsigned long idx;
|
unsigned long idx;
|
||||||
int ret = 1;
|
int64_t ret = BDRV_BLOCK_DATA;
|
||||||
|
|
||||||
for (idx = start; idx < end; idx++) {
|
for (idx = start; idx < end; idx++) {
|
||||||
if (inode->data_vdi_id[idx] == 0) {
|
if (inode->data_vdi_id[idx] == 0) {
|
||||||
|
|
13
block/vdi.c
13
block/vdi.c
|
@ -479,12 +479,23 @@ static int64_t coroutine_fn vdi_co_get_block_status(BlockDriverState *bs,
|
||||||
size_t sector_in_block = sector_num % s->block_sectors;
|
size_t sector_in_block = sector_num % s->block_sectors;
|
||||||
int n_sectors = s->block_sectors - sector_in_block;
|
int n_sectors = s->block_sectors - sector_in_block;
|
||||||
uint32_t bmap_entry = le32_to_cpu(s->bmap[bmap_index]);
|
uint32_t bmap_entry = le32_to_cpu(s->bmap[bmap_index]);
|
||||||
|
uint64_t offset;
|
||||||
|
int result;
|
||||||
|
|
||||||
logout("%p, %" PRId64 ", %d, %p\n", bs, sector_num, nb_sectors, pnum);
|
logout("%p, %" PRId64 ", %d, %p\n", bs, sector_num, nb_sectors, pnum);
|
||||||
if (n_sectors > nb_sectors) {
|
if (n_sectors > nb_sectors) {
|
||||||
n_sectors = nb_sectors;
|
n_sectors = nb_sectors;
|
||||||
}
|
}
|
||||||
*pnum = n_sectors;
|
*pnum = n_sectors;
|
||||||
return VDI_IS_ALLOCATED(bmap_entry);
|
result = VDI_IS_ALLOCATED(bmap_entry);
|
||||||
|
if (!result) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = s->header.offset_data +
|
||||||
|
(uint64_t)bmap_entry * s->block_size +
|
||||||
|
sector_in_block * SECTOR_SIZE;
|
||||||
|
return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int vdi_co_read(BlockDriverState *bs,
|
static int vdi_co_read(BlockDriverState *bs,
|
||||||
|
|
19
block/vmdk.c
19
block/vmdk.c
|
@ -1059,7 +1059,24 @@ static int64_t coroutine_fn vmdk_co_get_block_status(BlockDriverState *bs,
|
||||||
sector_num * 512, 0, &offset);
|
sector_num * 512, 0, &offset);
|
||||||
qemu_co_mutex_unlock(&s->lock);
|
qemu_co_mutex_unlock(&s->lock);
|
||||||
|
|
||||||
ret = (ret == VMDK_OK || ret == VMDK_ZEROED);
|
switch (ret) {
|
||||||
|
case VMDK_ERROR:
|
||||||
|
ret = -EIO;
|
||||||
|
break;
|
||||||
|
case VMDK_UNALLOC:
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
case VMDK_ZEROED:
|
||||||
|
ret = BDRV_BLOCK_ZERO;
|
||||||
|
break;
|
||||||
|
case VMDK_OK:
|
||||||
|
ret = BDRV_BLOCK_DATA;
|
||||||
|
if (extent->file == bs->file) {
|
||||||
|
ret |= BDRV_BLOCK_OFFSET_VALID | offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
index_in_cluster = sector_num % extent->cluster_sectors;
|
index_in_cluster = sector_num % extent->cluster_sectors;
|
||||||
n = extent->cluster_sectors - index_in_cluster;
|
n = extent->cluster_sectors - index_in_cluster;
|
||||||
|
|
|
@ -2879,11 +2879,12 @@ static int64_t coroutine_fn vvfat_co_get_block_status(BlockDriverState *bs,
|
||||||
{
|
{
|
||||||
BDRVVVFATState* s = bs->opaque;
|
BDRVVVFATState* s = bs->opaque;
|
||||||
*n = s->sector_count - sector_num;
|
*n = s->sector_count - sector_num;
|
||||||
if (*n > nb_sectors)
|
if (*n > nb_sectors) {
|
||||||
*n = nb_sectors;
|
*n = nb_sectors;
|
||||||
else if (*n < 0)
|
} else if (*n < 0) {
|
||||||
return 0;
|
return 0;
|
||||||
return 1;
|
}
|
||||||
|
return BDRV_BLOCK_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int write_target_commit(BlockDriverState *bs, int64_t sector_num,
|
static int write_target_commit(BlockDriverState *bs, int64_t sector_num,
|
||||||
|
|
Loading…
Reference in New Issue