mirror of
https://github.com/qemu/qemu.git
synced 2024-12-05 17:53:36 +08:00
Merge remote-tracking branch 'kwolf/for-anthony' into staging
This commit is contained in:
commit
ddf83d0173
@ -251,22 +251,12 @@ static int mig_save_device_bulk(Monitor *mon, QEMUFile *f,
|
||||
|
||||
blk->aiocb = bdrv_aio_readv(bs, cur_sector, &blk->qiov,
|
||||
nr_sectors, blk_mig_read_cb, blk);
|
||||
if (!blk->aiocb) {
|
||||
goto error;
|
||||
}
|
||||
block_mig_state.submitted++;
|
||||
|
||||
bdrv_reset_dirty(bs, cur_sector, nr_sectors);
|
||||
bmds->cur_sector = cur_sector + nr_sectors;
|
||||
|
||||
return (bmds->cur_sector >= total_sectors);
|
||||
|
||||
error:
|
||||
monitor_printf(mon, "Error reading sector %" PRId64 "\n", cur_sector);
|
||||
qemu_file_set_error(f, -EIO);
|
||||
g_free(blk->buf);
|
||||
g_free(blk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void set_dirty_tracking(int enable)
|
||||
@ -413,9 +403,6 @@ static int mig_save_device_dirty(Monitor *mon, QEMUFile *f,
|
||||
|
||||
blk->aiocb = bdrv_aio_readv(bmds->bs, sector, &blk->qiov,
|
||||
nr_sectors, blk_mig_read_cb, blk);
|
||||
if (!blk->aiocb) {
|
||||
goto error;
|
||||
}
|
||||
block_mig_state.submitted++;
|
||||
bmds_set_aio_inflight(bmds, sector, nr_sectors, 1);
|
||||
} else {
|
||||
|
56
block.c
56
block.c
@ -2812,7 +2812,6 @@ static int multiwrite_merge(BlockDriverState *bs, BlockRequest *reqs,
|
||||
*/
|
||||
int bdrv_aio_multiwrite(BlockDriverState *bs, BlockRequest *reqs, int num_reqs)
|
||||
{
|
||||
BlockDriverAIOCB *acb;
|
||||
MultiwriteCB *mcb;
|
||||
int i;
|
||||
|
||||
@ -2843,59 +2842,14 @@ int bdrv_aio_multiwrite(BlockDriverState *bs, BlockRequest *reqs, int num_reqs)
|
||||
|
||||
trace_bdrv_aio_multiwrite(mcb, mcb->num_callbacks, num_reqs);
|
||||
|
||||
/*
|
||||
* Run the aio requests. As soon as one request can't be submitted
|
||||
* successfully, fail all requests that are not yet submitted (we must
|
||||
* return failure for all requests anyway)
|
||||
*
|
||||
* num_requests cannot be set to the right value immediately: If
|
||||
* bdrv_aio_writev fails for some request, num_requests would be too high
|
||||
* and therefore multiwrite_cb() would never recognize the multiwrite
|
||||
* request as completed. We also cannot use the loop variable i to set it
|
||||
* when the first request fails because the callback may already have been
|
||||
* called for previously submitted requests. Thus, num_requests must be
|
||||
* incremented for each request that is submitted.
|
||||
*
|
||||
* The problem that callbacks may be called early also means that we need
|
||||
* to take care that num_requests doesn't become 0 before all requests are
|
||||
* submitted - multiwrite_cb() would consider the multiwrite request
|
||||
* completed. A dummy request that is "completed" by a manual call to
|
||||
* multiwrite_cb() takes care of this.
|
||||
*/
|
||||
mcb->num_requests = 1;
|
||||
|
||||
// Run the aio requests
|
||||
/* Run the aio requests. */
|
||||
mcb->num_requests = num_reqs;
|
||||
for (i = 0; i < num_reqs; i++) {
|
||||
mcb->num_requests++;
|
||||
acb = bdrv_aio_writev(bs, reqs[i].sector, reqs[i].qiov,
|
||||
bdrv_aio_writev(bs, reqs[i].sector, reqs[i].qiov,
|
||||
reqs[i].nb_sectors, multiwrite_cb, mcb);
|
||||
|
||||
if (acb == NULL) {
|
||||
// We can only fail the whole thing if no request has been
|
||||
// submitted yet. Otherwise we'll wait for the submitted AIOs to
|
||||
// complete and report the error in the callback.
|
||||
if (i == 0) {
|
||||
trace_bdrv_aio_multiwrite_earlyfail(mcb);
|
||||
goto fail;
|
||||
} else {
|
||||
trace_bdrv_aio_multiwrite_latefail(mcb, i);
|
||||
multiwrite_cb(mcb, -EIO);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Complete the dummy request */
|
||||
multiwrite_cb(mcb, 0);
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
for (i = 0; i < mcb->num_callbacks; i++) {
|
||||
reqs[i].error = -EIO;
|
||||
}
|
||||
g_free(mcb);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void bdrv_aio_cancel(BlockDriverAIOCB *acb)
|
||||
@ -3123,9 +3077,7 @@ static BlockDriverAIOCB *bdrv_aio_rw_vector(BlockDriverState *bs,
|
||||
acb->is_write = is_write;
|
||||
acb->qiov = qiov;
|
||||
acb->bounce = qemu_blockalign(bs, qiov->size);
|
||||
|
||||
if (!acb->bh)
|
||||
acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb);
|
||||
acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb);
|
||||
|
||||
if (is_write) {
|
||||
qemu_iovec_to_buffer(acb->qiov, acb->bounce);
|
||||
|
2
block.h
2
block.h
@ -22,7 +22,7 @@ typedef struct QEMUSnapshotInfo {
|
||||
/* the following fields are informative. They are not needed for
|
||||
the consistency of the snapshot */
|
||||
char name[256]; /* user chosen name */
|
||||
uint32_t vm_state_size; /* VM state info size */
|
||||
uint64_t vm_state_size; /* VM state info size */
|
||||
uint32_t date_sec; /* UTC date of the snapshot */
|
||||
uint32_t date_nsec;
|
||||
uint64_t vm_clock_nsec; /* VM clock relative to boot */
|
||||
|
@ -310,14 +310,10 @@ static BlockDriverAIOCB *blkverify_aio_readv(BlockDriverState *bs,
|
||||
qemu_iovec_init(&acb->raw_qiov, acb->qiov->niov);
|
||||
blkverify_iovec_clone(&acb->raw_qiov, qiov, acb->buf);
|
||||
|
||||
if (!bdrv_aio_readv(s->test_file, sector_num, qiov, nb_sectors,
|
||||
blkverify_aio_cb, acb)) {
|
||||
blkverify_aio_cb(acb, -EIO);
|
||||
}
|
||||
if (!bdrv_aio_readv(bs->file, sector_num, &acb->raw_qiov, nb_sectors,
|
||||
blkverify_aio_cb, acb)) {
|
||||
blkverify_aio_cb(acb, -EIO);
|
||||
}
|
||||
bdrv_aio_readv(s->test_file, sector_num, qiov, nb_sectors,
|
||||
blkverify_aio_cb, acb);
|
||||
bdrv_aio_readv(bs->file, sector_num, &acb->raw_qiov, nb_sectors,
|
||||
blkverify_aio_cb, acb);
|
||||
return &acb->common;
|
||||
}
|
||||
|
||||
@ -329,14 +325,10 @@ static BlockDriverAIOCB *blkverify_aio_writev(BlockDriverState *bs,
|
||||
BlkverifyAIOCB *acb = blkverify_aio_get(bs, true, sector_num, qiov,
|
||||
nb_sectors, cb, opaque);
|
||||
|
||||
if (!bdrv_aio_writev(s->test_file, sector_num, qiov, nb_sectors,
|
||||
blkverify_aio_cb, acb)) {
|
||||
blkverify_aio_cb(acb, -EIO);
|
||||
}
|
||||
if (!bdrv_aio_writev(bs->file, sector_num, qiov, nb_sectors,
|
||||
blkverify_aio_cb, acb)) {
|
||||
blkverify_aio_cb(acb, -EIO);
|
||||
}
|
||||
bdrv_aio_writev(s->test_file, sector_num, qiov, nb_sectors,
|
||||
blkverify_aio_cb, acb);
|
||||
bdrv_aio_writev(bs->file, sector_num, qiov, nb_sectors,
|
||||
blkverify_aio_cb, acb);
|
||||
return &acb->common;
|
||||
}
|
||||
|
||||
|
44
block/cow.c
44
block/cow.c
@ -64,15 +64,26 @@ static int cow_open(BlockDriverState *bs, int flags)
|
||||
struct cow_header_v2 cow_header;
|
||||
int bitmap_size;
|
||||
int64_t size;
|
||||
int ret;
|
||||
|
||||
/* see if it is a cow image */
|
||||
if (bdrv_pread(bs->file, 0, &cow_header, sizeof(cow_header)) !=
|
||||
sizeof(cow_header)) {
|
||||
ret = bdrv_pread(bs->file, 0, &cow_header, sizeof(cow_header));
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (be32_to_cpu(cow_header.magic) != COW_MAGIC ||
|
||||
be32_to_cpu(cow_header.version) != COW_VERSION) {
|
||||
if (be32_to_cpu(cow_header.magic) != COW_MAGIC) {
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (be32_to_cpu(cow_header.version) != COW_VERSION) {
|
||||
char version[64];
|
||||
snprintf(version, sizeof(version),
|
||||
"COW version %d", cow_header.version);
|
||||
qerror_report(QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
|
||||
bs->device_name, "cow", version);
|
||||
ret = -ENOTSUP;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@ -88,7 +99,7 @@ static int cow_open(BlockDriverState *bs, int flags)
|
||||
qemu_co_mutex_init(&s->lock);
|
||||
return 0;
|
||||
fail:
|
||||
return -1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -182,17 +193,19 @@ static int coroutine_fn cow_read(BlockDriverState *bs, int64_t sector_num,
|
||||
ret = bdrv_pread(bs->file,
|
||||
s->cow_sectors_offset + sector_num * 512,
|
||||
buf, n * 512);
|
||||
if (ret != n * 512)
|
||||
return -1;
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
if (bs->backing_hd) {
|
||||
/* read from the base image */
|
||||
ret = bdrv_read(bs->backing_hd, sector_num, buf, n);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
memset(buf, 0, n * 512);
|
||||
}
|
||||
memset(buf, 0, n * 512);
|
||||
}
|
||||
}
|
||||
nb_sectors -= n;
|
||||
sector_num += n;
|
||||
@ -220,8 +233,9 @@ static int cow_write(BlockDriverState *bs, int64_t sector_num,
|
||||
|
||||
ret = bdrv_pwrite(bs->file, s->cow_sectors_offset + sector_num * 512,
|
||||
buf, nb_sectors * 512);
|
||||
if (ret != nb_sectors * 512)
|
||||
return -1;
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return cow_update_bitmap(bs, sector_num, nb_sectors);
|
||||
}
|
||||
@ -288,14 +302,14 @@ static int cow_create(const char *filename, QEMUOptionParameter *options)
|
||||
cow_header.sectorsize = cpu_to_be32(512);
|
||||
cow_header.size = cpu_to_be64(image_sectors * 512);
|
||||
ret = bdrv_pwrite(cow_bs, 0, &cow_header, sizeof(cow_header));
|
||||
if (ret != sizeof(cow_header)) {
|
||||
if (ret < 0) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* resize to include at least all the bitmap */
|
||||
ret = bdrv_truncate(cow_bs,
|
||||
sizeof(cow_header) + ((image_sectors + 7) >> 3));
|
||||
if (ret) {
|
||||
if (ret < 0) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
@ -509,10 +509,6 @@ static BlockDriverAIOCB *curl_aio_readv(BlockDriverState *bs,
|
||||
|
||||
acb = qemu_aio_get(&curl_aio_pool, bs, cb, opaque);
|
||||
|
||||
if (!acb) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
acb->qiov = qiov;
|
||||
acb->sector_num = sector_num;
|
||||
acb->nb_sectors = nb_sectors;
|
||||
|
@ -46,6 +46,10 @@ typedef struct QEMU_PACKED QCowSnapshotHeader {
|
||||
/* name follows */
|
||||
} QCowSnapshotHeader;
|
||||
|
||||
typedef struct QEMU_PACKED QCowSnapshotExtraData {
|
||||
uint64_t vm_state_size_large;
|
||||
} QCowSnapshotExtraData;
|
||||
|
||||
void qcow2_free_snapshots(BlockDriverState *bs)
|
||||
{
|
||||
BDRVQcowState *s = bs->opaque;
|
||||
@ -64,6 +68,7 @@ int qcow2_read_snapshots(BlockDriverState *bs)
|
||||
{
|
||||
BDRVQcowState *s = bs->opaque;
|
||||
QCowSnapshotHeader h;
|
||||
QCowSnapshotExtraData extra;
|
||||
QCowSnapshot *sn;
|
||||
int i, id_str_size, name_size;
|
||||
int64_t offset;
|
||||
@ -100,9 +105,18 @@ int qcow2_read_snapshots(BlockDriverState *bs)
|
||||
id_str_size = be16_to_cpu(h.id_str_size);
|
||||
name_size = be16_to_cpu(h.name_size);
|
||||
|
||||
/* Skip extra data */
|
||||
/* Read extra data */
|
||||
ret = bdrv_pread(bs->file, offset, &extra,
|
||||
MIN(sizeof(extra), extra_data_size));
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
offset += extra_data_size;
|
||||
|
||||
if (extra_data_size >= 8) {
|
||||
sn->vm_state_size = be64_to_cpu(extra.vm_state_size_large);
|
||||
}
|
||||
|
||||
/* Read snapshot ID */
|
||||
sn->id_str = g_malloc(id_str_size + 1);
|
||||
ret = bdrv_pread(bs->file, offset, sn->id_str, id_str_size);
|
||||
@ -136,6 +150,7 @@ static int qcow2_write_snapshots(BlockDriverState *bs)
|
||||
BDRVQcowState *s = bs->opaque;
|
||||
QCowSnapshot *sn;
|
||||
QCowSnapshotHeader h;
|
||||
QCowSnapshotExtraData extra;
|
||||
int i, name_size, id_str_size, snapshots_size;
|
||||
struct {
|
||||
uint32_t nb_snapshots;
|
||||
@ -150,6 +165,7 @@ static int qcow2_write_snapshots(BlockDriverState *bs)
|
||||
sn = s->snapshots + i;
|
||||
offset = align_offset(offset, 8);
|
||||
offset += sizeof(h);
|
||||
offset += sizeof(extra);
|
||||
offset += strlen(sn->id_str);
|
||||
offset += strlen(sn->name);
|
||||
}
|
||||
@ -169,10 +185,18 @@ static int qcow2_write_snapshots(BlockDriverState *bs)
|
||||
memset(&h, 0, sizeof(h));
|
||||
h.l1_table_offset = cpu_to_be64(sn->l1_table_offset);
|
||||
h.l1_size = cpu_to_be32(sn->l1_size);
|
||||
h.vm_state_size = cpu_to_be32(sn->vm_state_size);
|
||||
/* If it doesn't fit in 32 bit, older implementations should treat it
|
||||
* as a disk-only snapshot rather than truncate the VM state */
|
||||
if (sn->vm_state_size <= 0xffffffff) {
|
||||
h.vm_state_size = cpu_to_be32(sn->vm_state_size);
|
||||
}
|
||||
h.date_sec = cpu_to_be32(sn->date_sec);
|
||||
h.date_nsec = cpu_to_be32(sn->date_nsec);
|
||||
h.vm_clock_nsec = cpu_to_be64(sn->vm_clock_nsec);
|
||||
h.extra_data_size = cpu_to_be32(sizeof(extra));
|
||||
|
||||
memset(&extra, 0, sizeof(extra));
|
||||
extra.vm_state_size_large = cpu_to_be64(sn->vm_state_size);
|
||||
|
||||
id_str_size = strlen(sn->id_str);
|
||||
name_size = strlen(sn->name);
|
||||
@ -186,6 +210,12 @@ static int qcow2_write_snapshots(BlockDriverState *bs)
|
||||
}
|
||||
offset += sizeof(h);
|
||||
|
||||
ret = bdrv_pwrite(bs->file, offset, &extra, sizeof(extra));
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
offset += sizeof(extra);
|
||||
|
||||
ret = bdrv_pwrite(bs->file, offset, sn->id_str, id_str_size);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
|
@ -635,6 +635,7 @@ static void qcow2_close(BlockDriverState *bs)
|
||||
g_free(s->cluster_cache);
|
||||
qemu_vfree(s->cluster_data);
|
||||
qcow2_refcount_close(bs);
|
||||
qcow2_free_snapshots(bs);
|
||||
}
|
||||
|
||||
static void qcow2_invalidate_cache(BlockDriverState *bs)
|
||||
|
@ -78,7 +78,7 @@ typedef struct QCowSnapshot {
|
||||
uint32_t l1_size;
|
||||
char *id_str;
|
||||
char *name;
|
||||
uint32_t vm_state_size;
|
||||
uint64_t vm_state_size;
|
||||
uint32_t date_sec;
|
||||
uint32_t date_nsec;
|
||||
uint64_t vm_clock_nsec;
|
||||
|
@ -54,7 +54,6 @@ static void qed_read_table(BDRVQEDState *s, uint64_t offset, QEDTable *table,
|
||||
QEDReadTableCB *read_table_cb = gencb_alloc(sizeof(*read_table_cb),
|
||||
cb, opaque);
|
||||
QEMUIOVector *qiov = &read_table_cb->qiov;
|
||||
BlockDriverAIOCB *aiocb;
|
||||
|
||||
trace_qed_read_table(s, offset, table);
|
||||
|
||||
@ -64,12 +63,9 @@ static void qed_read_table(BDRVQEDState *s, uint64_t offset, QEDTable *table,
|
||||
read_table_cb->iov.iov_len = s->header.cluster_size * s->header.table_size,
|
||||
|
||||
qemu_iovec_init_external(qiov, &read_table_cb->iov, 1);
|
||||
aiocb = bdrv_aio_readv(s->bs->file, offset / BDRV_SECTOR_SIZE, qiov,
|
||||
qiov->size / BDRV_SECTOR_SIZE,
|
||||
qed_read_table_cb, read_table_cb);
|
||||
if (!aiocb) {
|
||||
qed_read_table_cb(read_table_cb, -EIO);
|
||||
}
|
||||
bdrv_aio_readv(s->bs->file, offset / BDRV_SECTOR_SIZE, qiov,
|
||||
qiov->size / BDRV_SECTOR_SIZE,
|
||||
qed_read_table_cb, read_table_cb);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
@ -127,7 +123,6 @@ static void qed_write_table(BDRVQEDState *s, uint64_t offset, QEDTable *table,
|
||||
BlockDriverCompletionFunc *cb, void *opaque)
|
||||
{
|
||||
QEDWriteTableCB *write_table_cb;
|
||||
BlockDriverAIOCB *aiocb;
|
||||
unsigned int sector_mask = BDRV_SECTOR_SIZE / sizeof(uint64_t) - 1;
|
||||
unsigned int start, end, i;
|
||||
size_t len_bytes;
|
||||
@ -158,13 +153,10 @@ static void qed_write_table(BDRVQEDState *s, uint64_t offset, QEDTable *table,
|
||||
/* Adjust for offset into table */
|
||||
offset += start * sizeof(uint64_t);
|
||||
|
||||
aiocb = bdrv_aio_writev(s->bs->file, offset / BDRV_SECTOR_SIZE,
|
||||
&write_table_cb->qiov,
|
||||
write_table_cb->qiov.size / BDRV_SECTOR_SIZE,
|
||||
qed_write_table_cb, write_table_cb);
|
||||
if (!aiocb) {
|
||||
qed_write_table_cb(write_table_cb, -EIO);
|
||||
}
|
||||
bdrv_aio_writev(s->bs->file, offset / BDRV_SECTOR_SIZE,
|
||||
&write_table_cb->qiov,
|
||||
write_table_cb->qiov.size / BDRV_SECTOR_SIZE,
|
||||
qed_write_table_cb, write_table_cb);
|
||||
}
|
||||
|
||||
/**
|
||||
|
60
block/qed.c
60
block/qed.c
@ -123,7 +123,6 @@ static void qed_write_header_read_cb(void *opaque, int ret)
|
||||
{
|
||||
QEDWriteHeaderCB *write_header_cb = opaque;
|
||||
BDRVQEDState *s = write_header_cb->s;
|
||||
BlockDriverAIOCB *acb;
|
||||
|
||||
if (ret) {
|
||||
qed_write_header_cb(write_header_cb, ret);
|
||||
@ -133,12 +132,9 @@ static void qed_write_header_read_cb(void *opaque, int ret)
|
||||
/* Update header */
|
||||
qed_header_cpu_to_le(&s->header, (QEDHeader *)write_header_cb->buf);
|
||||
|
||||
acb = bdrv_aio_writev(s->bs->file, 0, &write_header_cb->qiov,
|
||||
write_header_cb->nsectors, qed_write_header_cb,
|
||||
write_header_cb);
|
||||
if (!acb) {
|
||||
qed_write_header_cb(write_header_cb, -EIO);
|
||||
}
|
||||
bdrv_aio_writev(s->bs->file, 0, &write_header_cb->qiov,
|
||||
write_header_cb->nsectors, qed_write_header_cb,
|
||||
write_header_cb);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -156,7 +152,6 @@ static void qed_write_header(BDRVQEDState *s, BlockDriverCompletionFunc cb,
|
||||
* them, and write back.
|
||||
*/
|
||||
|
||||
BlockDriverAIOCB *acb;
|
||||
int nsectors = (sizeof(QEDHeader) + BDRV_SECTOR_SIZE - 1) /
|
||||
BDRV_SECTOR_SIZE;
|
||||
size_t len = nsectors * BDRV_SECTOR_SIZE;
|
||||
@ -170,11 +165,8 @@ static void qed_write_header(BDRVQEDState *s, BlockDriverCompletionFunc cb,
|
||||
write_header_cb->iov.iov_len = len;
|
||||
qemu_iovec_init_external(&write_header_cb->qiov, &write_header_cb->iov, 1);
|
||||
|
||||
acb = bdrv_aio_readv(s->bs->file, 0, &write_header_cb->qiov, nsectors,
|
||||
qed_write_header_read_cb, write_header_cb);
|
||||
if (!acb) {
|
||||
qed_write_header_cb(write_header_cb, -EIO);
|
||||
}
|
||||
bdrv_aio_readv(s->bs->file, 0, &write_header_cb->qiov, nsectors,
|
||||
qed_write_header_read_cb, write_header_cb);
|
||||
}
|
||||
|
||||
static uint64_t qed_max_image_size(uint32_t cluster_size, uint32_t table_size)
|
||||
@ -728,7 +720,6 @@ static void qed_read_backing_file(BDRVQEDState *s, uint64_t pos,
|
||||
QEMUIOVector *qiov,
|
||||
BlockDriverCompletionFunc *cb, void *opaque)
|
||||
{
|
||||
BlockDriverAIOCB *aiocb;
|
||||
uint64_t backing_length = 0;
|
||||
size_t size;
|
||||
|
||||
@ -760,11 +751,8 @@ static void qed_read_backing_file(BDRVQEDState *s, uint64_t pos,
|
||||
size = MIN((uint64_t)backing_length - pos, qiov->size);
|
||||
|
||||
BLKDBG_EVENT(s->bs->file, BLKDBG_READ_BACKING);
|
||||
aiocb = bdrv_aio_readv(s->bs->backing_hd, pos / BDRV_SECTOR_SIZE,
|
||||
qiov, size / BDRV_SECTOR_SIZE, cb, opaque);
|
||||
if (!aiocb) {
|
||||
cb(opaque, -EIO);
|
||||
}
|
||||
bdrv_aio_readv(s->bs->backing_hd, pos / BDRV_SECTOR_SIZE,
|
||||
qiov, size / BDRV_SECTOR_SIZE, cb, opaque);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
@ -786,7 +774,6 @@ static void qed_copy_from_backing_file_write(void *opaque, int ret)
|
||||
{
|
||||
CopyFromBackingFileCB *copy_cb = opaque;
|
||||
BDRVQEDState *s = copy_cb->s;
|
||||
BlockDriverAIOCB *aiocb;
|
||||
|
||||
if (ret) {
|
||||
qed_copy_from_backing_file_cb(copy_cb, ret);
|
||||
@ -794,13 +781,9 @@ static void qed_copy_from_backing_file_write(void *opaque, int ret)
|
||||
}
|
||||
|
||||
BLKDBG_EVENT(s->bs->file, BLKDBG_COW_WRITE);
|
||||
aiocb = bdrv_aio_writev(s->bs->file, copy_cb->offset / BDRV_SECTOR_SIZE,
|
||||
©_cb->qiov,
|
||||
copy_cb->qiov.size / BDRV_SECTOR_SIZE,
|
||||
qed_copy_from_backing_file_cb, copy_cb);
|
||||
if (!aiocb) {
|
||||
qed_copy_from_backing_file_cb(copy_cb, -EIO);
|
||||
}
|
||||
bdrv_aio_writev(s->bs->file, copy_cb->offset / BDRV_SECTOR_SIZE,
|
||||
©_cb->qiov, copy_cb->qiov.size / BDRV_SECTOR_SIZE,
|
||||
qed_copy_from_backing_file_cb, copy_cb);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1022,7 +1005,6 @@ static void qed_aio_write_main(void *opaque, int ret)
|
||||
uint64_t offset = acb->cur_cluster +
|
||||
qed_offset_into_cluster(s, acb->cur_pos);
|
||||
BlockDriverCompletionFunc *next_fn;
|
||||
BlockDriverAIOCB *file_acb;
|
||||
|
||||
trace_qed_aio_write_main(s, acb, ret, offset, acb->cur_qiov.size);
|
||||
|
||||
@ -1042,13 +1024,9 @@ static void qed_aio_write_main(void *opaque, int ret)
|
||||
}
|
||||
|
||||
BLKDBG_EVENT(s->bs->file, BLKDBG_WRITE_AIO);
|
||||
file_acb = bdrv_aio_writev(s->bs->file, offset / BDRV_SECTOR_SIZE,
|
||||
&acb->cur_qiov,
|
||||
acb->cur_qiov.size / BDRV_SECTOR_SIZE,
|
||||
next_fn, acb);
|
||||
if (!file_acb) {
|
||||
qed_aio_complete(acb, -EIO);
|
||||
}
|
||||
bdrv_aio_writev(s->bs->file, offset / BDRV_SECTOR_SIZE,
|
||||
&acb->cur_qiov, acb->cur_qiov.size / BDRV_SECTOR_SIZE,
|
||||
next_fn, acb);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1215,7 +1193,6 @@ static void qed_aio_read_data(void *opaque, int ret,
|
||||
QEDAIOCB *acb = opaque;
|
||||
BDRVQEDState *s = acb_to_s(acb);
|
||||
BlockDriverState *bs = acb->common.bs;
|
||||
BlockDriverAIOCB *file_acb;
|
||||
|
||||
/* Adjust offset into cluster */
|
||||
offset += qed_offset_into_cluster(s, acb->cur_pos);
|
||||
@ -1240,14 +1217,9 @@ static void qed_aio_read_data(void *opaque, int ret,
|
||||
}
|
||||
|
||||
BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO);
|
||||
file_acb = bdrv_aio_readv(bs->file, offset / BDRV_SECTOR_SIZE,
|
||||
&acb->cur_qiov,
|
||||
acb->cur_qiov.size / BDRV_SECTOR_SIZE,
|
||||
qed_aio_next_io, acb);
|
||||
if (!file_acb) {
|
||||
ret = -EIO;
|
||||
goto err;
|
||||
}
|
||||
bdrv_aio_readv(bs->file, offset / BDRV_SECTOR_SIZE,
|
||||
&acb->cur_qiov, acb->cur_qiov.size / BDRV_SECTOR_SIZE,
|
||||
qed_aio_next_io, acb);
|
||||
return;
|
||||
|
||||
err:
|
||||
|
@ -632,9 +632,6 @@ static BlockDriverAIOCB *rbd_aio_rw_vector(BlockDriverState *bs,
|
||||
BDRVRBDState *s = bs->opaque;
|
||||
|
||||
acb = qemu_aio_get(&rbd_aio_pool, bs, cb, opaque);
|
||||
if (!acb) {
|
||||
return NULL;
|
||||
}
|
||||
acb->write = write;
|
||||
acb->qiov = qiov;
|
||||
acb->bounce = qemu_blockalign(bs, qiov->size);
|
||||
@ -808,7 +805,7 @@ static int qemu_rbd_snap_list(BlockDriverState *bs,
|
||||
} while (snap_count == -ERANGE);
|
||||
|
||||
if (snap_count <= 0) {
|
||||
return snap_count;
|
||||
goto done;
|
||||
}
|
||||
|
||||
sn_tab = g_malloc0(snap_count * sizeof(QEMUSnapshotInfo));
|
||||
@ -827,6 +824,7 @@ static int qemu_rbd_snap_list(BlockDriverState *bs,
|
||||
}
|
||||
rbd_snap_list_end(snaps);
|
||||
|
||||
done:
|
||||
*psn_tab = sn_tab;
|
||||
return snap_count;
|
||||
}
|
||||
|
64
block/vdi.c
64
block/vdi.c
@ -515,28 +515,26 @@ static VdiAIOCB *vdi_aio_setup(BlockDriverState *bs, int64_t sector_num,
|
||||
bs, sector_num, qiov, nb_sectors, cb, opaque, is_write);
|
||||
|
||||
acb = qemu_aio_get(&vdi_aio_pool, bs, cb, opaque);
|
||||
if (acb) {
|
||||
acb->hd_aiocb = NULL;
|
||||
acb->sector_num = sector_num;
|
||||
acb->qiov = qiov;
|
||||
acb->is_write = is_write;
|
||||
acb->hd_aiocb = NULL;
|
||||
acb->sector_num = sector_num;
|
||||
acb->qiov = qiov;
|
||||
acb->is_write = is_write;
|
||||
|
||||
if (qiov->niov > 1) {
|
||||
acb->buf = qemu_blockalign(bs, qiov->size);
|
||||
acb->orig_buf = acb->buf;
|
||||
if (is_write) {
|
||||
qemu_iovec_to_buffer(qiov, acb->buf);
|
||||
}
|
||||
} else {
|
||||
acb->buf = (uint8_t *)qiov->iov->iov_base;
|
||||
if (qiov->niov > 1) {
|
||||
acb->buf = qemu_blockalign(bs, qiov->size);
|
||||
acb->orig_buf = acb->buf;
|
||||
if (is_write) {
|
||||
qemu_iovec_to_buffer(qiov, acb->buf);
|
||||
}
|
||||
acb->nb_sectors = nb_sectors;
|
||||
acb->n_sectors = 0;
|
||||
acb->bmap_first = VDI_UNALLOCATED;
|
||||
acb->bmap_last = VDI_UNALLOCATED;
|
||||
acb->block_buffer = NULL;
|
||||
acb->header_modified = 0;
|
||||
} else {
|
||||
acb->buf = (uint8_t *)qiov->iov->iov_base;
|
||||
}
|
||||
acb->nb_sectors = nb_sectors;
|
||||
acb->n_sectors = 0;
|
||||
acb->bmap_first = VDI_UNALLOCATED;
|
||||
acb->bmap_last = VDI_UNALLOCATED;
|
||||
acb->block_buffer = NULL;
|
||||
acb->header_modified = 0;
|
||||
return acb;
|
||||
}
|
||||
|
||||
@ -633,10 +631,6 @@ static void vdi_aio_read_cb(void *opaque, int ret)
|
||||
qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
|
||||
acb->hd_aiocb = bdrv_aio_readv(bs->file, offset, &acb->hd_qiov,
|
||||
n_sectors, vdi_aio_read_cb, acb);
|
||||
if (acb->hd_aiocb == NULL) {
|
||||
ret = -EIO;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
return;
|
||||
done:
|
||||
@ -657,10 +651,6 @@ static BlockDriverAIOCB *vdi_aio_readv(BlockDriverState *bs,
|
||||
|
||||
logout("\n");
|
||||
acb = vdi_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque, 0);
|
||||
if (!acb) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = vdi_schedule_bh(vdi_aio_rw_bh, acb);
|
||||
if (ret < 0) {
|
||||
if (acb->qiov->niov > 1) {
|
||||
@ -708,10 +698,6 @@ static void vdi_aio_write_cb(void *opaque, int ret)
|
||||
qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
|
||||
acb->hd_aiocb = bdrv_aio_writev(bs->file, 0, &acb->hd_qiov, 1,
|
||||
vdi_aio_write_cb, acb);
|
||||
if (acb->hd_aiocb == NULL) {
|
||||
ret = -EIO;
|
||||
goto done;
|
||||
}
|
||||
return;
|
||||
} else if (VDI_IS_ALLOCATED(acb->bmap_first)) {
|
||||
/* One or more new blocks were allocated. */
|
||||
@ -738,10 +724,6 @@ static void vdi_aio_write_cb(void *opaque, int ret)
|
||||
n_sectors, bmap_first);
|
||||
acb->hd_aiocb = bdrv_aio_writev(bs->file, offset, &acb->hd_qiov,
|
||||
n_sectors, vdi_aio_write_cb, acb);
|
||||
if (acb->hd_aiocb == NULL) {
|
||||
ret = -EIO;
|
||||
goto done;
|
||||
}
|
||||
return;
|
||||
}
|
||||
ret = 0;
|
||||
@ -789,10 +771,6 @@ static void vdi_aio_write_cb(void *opaque, int ret)
|
||||
acb->hd_aiocb = bdrv_aio_writev(bs->file, offset,
|
||||
&acb->hd_qiov, s->block_sectors,
|
||||
vdi_aio_write_cb, acb);
|
||||
if (acb->hd_aiocb == NULL) {
|
||||
ret = -EIO;
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
uint64_t offset = s->header.offset_data / SECTOR_SIZE +
|
||||
(uint64_t)bmap_entry * s->block_sectors +
|
||||
@ -802,10 +780,6 @@ static void vdi_aio_write_cb(void *opaque, int ret)
|
||||
qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
|
||||
acb->hd_aiocb = bdrv_aio_writev(bs->file, offset, &acb->hd_qiov,
|
||||
n_sectors, vdi_aio_write_cb, acb);
|
||||
if (acb->hd_aiocb == NULL) {
|
||||
ret = -EIO;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
@ -827,10 +801,6 @@ static BlockDriverAIOCB *vdi_aio_writev(BlockDriverState *bs,
|
||||
|
||||
logout("\n");
|
||||
acb = vdi_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque, 1);
|
||||
if (!acb) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = vdi_schedule_bh(vdi_aio_rw_bh, acb);
|
||||
if (ret < 0) {
|
||||
if (acb->qiov->niov > 1) {
|
||||
|
@ -35,6 +35,10 @@ enum {
|
||||
POOL_MAX_SIZE = 64,
|
||||
};
|
||||
|
||||
/** Free list to speed up creation */
|
||||
static QLIST_HEAD(, Coroutine) pool = QLIST_HEAD_INITIALIZER(pool);
|
||||
static unsigned int pool_size;
|
||||
|
||||
typedef struct {
|
||||
Coroutine base;
|
||||
void *stack;
|
||||
@ -48,10 +52,6 @@ typedef struct {
|
||||
/** Currently executing coroutine */
|
||||
Coroutine *current;
|
||||
|
||||
/** Free list to speed up creation */
|
||||
QLIST_HEAD(, Coroutine) pool;
|
||||
unsigned int pool_size;
|
||||
|
||||
/** The default coroutine */
|
||||
CoroutineUContext leader;
|
||||
} CoroutineThreadState;
|
||||
@ -75,7 +75,6 @@ static CoroutineThreadState *coroutine_get_thread_state(void)
|
||||
if (!s) {
|
||||
s = g_malloc0(sizeof(*s));
|
||||
s->current = &s->leader.base;
|
||||
QLIST_INIT(&s->pool);
|
||||
pthread_setspecific(thread_state_key, s);
|
||||
}
|
||||
return s;
|
||||
@ -84,14 +83,19 @@ static CoroutineThreadState *coroutine_get_thread_state(void)
|
||||
static void qemu_coroutine_thread_cleanup(void *opaque)
|
||||
{
|
||||
CoroutineThreadState *s = opaque;
|
||||
|
||||
g_free(s);
|
||||
}
|
||||
|
||||
static void __attribute__((destructor)) coroutine_cleanup(void)
|
||||
{
|
||||
Coroutine *co;
|
||||
Coroutine *tmp;
|
||||
|
||||
QLIST_FOREACH_SAFE(co, &s->pool, pool_next, tmp) {
|
||||
QLIST_FOREACH_SAFE(co, &pool, pool_next, tmp) {
|
||||
g_free(DO_UPCAST(CoroutineUContext, base, co)->stack);
|
||||
g_free(co);
|
||||
}
|
||||
g_free(s);
|
||||
}
|
||||
|
||||
static void __attribute__((constructor)) coroutine_init(void)
|
||||
@ -169,13 +173,12 @@ static Coroutine *coroutine_new(void)
|
||||
|
||||
Coroutine *qemu_coroutine_new(void)
|
||||
{
|
||||
CoroutineThreadState *s = coroutine_get_thread_state();
|
||||
Coroutine *co;
|
||||
|
||||
co = QLIST_FIRST(&s->pool);
|
||||
co = QLIST_FIRST(&pool);
|
||||
if (co) {
|
||||
QLIST_REMOVE(co, pool_next);
|
||||
s->pool_size--;
|
||||
pool_size--;
|
||||
} else {
|
||||
co = coroutine_new();
|
||||
}
|
||||
@ -184,13 +187,12 @@ Coroutine *qemu_coroutine_new(void)
|
||||
|
||||
void qemu_coroutine_delete(Coroutine *co_)
|
||||
{
|
||||
CoroutineThreadState *s = coroutine_get_thread_state();
|
||||
CoroutineUContext *co = DO_UPCAST(CoroutineUContext, base, co_);
|
||||
|
||||
if (s->pool_size < POOL_MAX_SIZE) {
|
||||
QLIST_INSERT_HEAD(&s->pool, &co->base, pool_next);
|
||||
if (pool_size < POOL_MAX_SIZE) {
|
||||
QLIST_INSERT_HEAD(&pool, &co->base, pool_next);
|
||||
co->base.caller = NULL;
|
||||
s->pool_size++;
|
||||
pool_size++;
|
||||
return;
|
||||
}
|
||||
|
||||
|
3
cutils.c
3
cutils.c
@ -217,7 +217,10 @@ void qemu_iovec_destroy(QEMUIOVector *qiov)
|
||||
{
|
||||
assert(qiov->nalloc != -1);
|
||||
|
||||
qemu_iovec_reset(qiov);
|
||||
g_free(qiov->iov);
|
||||
qiov->nalloc = 0;
|
||||
qiov->iov = NULL;
|
||||
}
|
||||
|
||||
void qemu_iovec_reset(QEMUIOVector *qiov)
|
||||
|
@ -142,9 +142,7 @@ static void dma_bdrv_cb(void *opaque, int ret)
|
||||
|
||||
dbs->acb = dbs->io_func(dbs->bs, dbs->sector_num, &dbs->iov,
|
||||
dbs->iov.size / 512, dma_bdrv_cb, dbs);
|
||||
if (!dbs->acb) {
|
||||
dma_complete(dbs, -EIO);
|
||||
}
|
||||
assert(dbs->acb);
|
||||
}
|
||||
|
||||
static void dma_aio_cancel(BlockDriverAIOCB *acb)
|
||||
|
@ -253,7 +253,13 @@ Snapshot table entry:
|
||||
36 - 39: Size of extra data in the table entry (used for future
|
||||
extensions of the format)
|
||||
|
||||
variable: Extra data for future extensions. Must be ignored.
|
||||
variable: Extra data for future extensions. Unknown fields must be
|
||||
ignored. Currently defined are (offset relative to snapshot
|
||||
table entry):
|
||||
|
||||
Byte 40 - 47: Size of the VM state in bytes. 0 if no VM
|
||||
state is saved. If this field is present,
|
||||
the 32-bit value in bytes 32-35 is ignored.
|
||||
|
||||
variable: Unique ID string for the snapshot (not null terminated)
|
||||
|
||||
|
@ -352,14 +352,8 @@ static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret)
|
||||
s->bus->dma->aiocb = bdrv_aio_readv(s->bs, (int64_t)s->lba << 2,
|
||||
&s->bus->dma->qiov, n * 4,
|
||||
ide_atapi_cmd_read_dma_cb, s);
|
||||
if (!s->bus->dma->aiocb) {
|
||||
/* Note: media not present is the most likely case */
|
||||
ide_atapi_cmd_error(s, NOT_READY,
|
||||
ASC_MEDIUM_NOT_PRESENT);
|
||||
goto eot;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
eot:
|
||||
bdrv_acct_done(s->bs, &s->acct);
|
||||
s->bus->dma->ops->add_status(s->bus->dma, BM_STATUS_INT);
|
||||
|
@ -549,7 +549,6 @@ void ide_dma_cb(void *opaque, int ret)
|
||||
int n;
|
||||
int64_t sector_num;
|
||||
|
||||
handle_rw_error:
|
||||
if (ret < 0) {
|
||||
int op = BM_STATUS_DMA_RETRY;
|
||||
|
||||
@ -608,11 +607,6 @@ handle_rw_error:
|
||||
ide_issue_trim, ide_dma_cb, s, true);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!s->bus->dma->aiocb) {
|
||||
ret = -1;
|
||||
goto handle_rw_error;
|
||||
}
|
||||
return;
|
||||
|
||||
eot:
|
||||
@ -718,18 +712,13 @@ static void ide_flush_cb(void *opaque, int ret)
|
||||
|
||||
void ide_flush_cache(IDEState *s)
|
||||
{
|
||||
BlockDriverAIOCB *acb;
|
||||
|
||||
if (s->bs == NULL) {
|
||||
ide_flush_cb(s, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
bdrv_acct_start(s->bs, &s->acct, 0, BDRV_ACCT_FLUSH);
|
||||
acb = bdrv_aio_flush(s->bs, ide_flush_cb, s);
|
||||
if (acb == NULL) {
|
||||
ide_flush_cb(s, -EIO);
|
||||
}
|
||||
bdrv_aio_flush(s->bs, ide_flush_cb, s);
|
||||
}
|
||||
|
||||
static void ide_cfata_metadata_inquiry(IDEState *s)
|
||||
|
@ -84,13 +84,6 @@ static void pmac_ide_atapi_transfer_cb(void *opaque, int ret)
|
||||
m->aiocb = dma_bdrv_read(s->bs, &s->sg,
|
||||
(int64_t)(s->lba << 2) + (s->io_buffer_index >> 9),
|
||||
pmac_ide_atapi_transfer_cb, io);
|
||||
if (!m->aiocb) {
|
||||
qemu_sglist_destroy(&s->sg);
|
||||
/* Note: media not present is the most likely case */
|
||||
ide_atapi_cmd_error(s, NOT_READY,
|
||||
ASC_MEDIUM_NOT_PRESENT);
|
||||
goto done;
|
||||
}
|
||||
return;
|
||||
|
||||
done:
|
||||
@ -159,10 +152,8 @@ static void pmac_ide_transfer_cb(void *opaque, int ret)
|
||||
ide_issue_trim, pmac_ide_transfer_cb, s, true);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!m->aiocb)
|
||||
pmac_ide_transfer_cb(io, -1);
|
||||
return;
|
||||
|
||||
done:
|
||||
if (s->dma_cmd == IDE_DMA_READ || s->dma_cmd == IDE_DMA_WRITE) {
|
||||
bdrv_acct_done(s->bs, &s->acct);
|
||||
|
@ -217,9 +217,6 @@ static void scsi_read_data(SCSIRequest *req)
|
||||
bdrv_acct_start(s->qdev.conf.bs, &r->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_READ);
|
||||
r->req.aiocb = bdrv_aio_readv(s->qdev.conf.bs, r->sector, &r->qiov, n,
|
||||
scsi_read_complete, r);
|
||||
if (r->req.aiocb == NULL) {
|
||||
scsi_read_complete(r, -EIO);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -327,9 +324,6 @@ static void scsi_write_data(SCSIRequest *req)
|
||||
bdrv_acct_start(s->qdev.conf.bs, &r->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_WRITE);
|
||||
r->req.aiocb = bdrv_aio_writev(s->qdev.conf.bs, r->sector, &r->qiov, n,
|
||||
scsi_write_complete, r);
|
||||
if (r->req.aiocb == NULL) {
|
||||
scsi_write_complete(r, -ENOMEM);
|
||||
}
|
||||
} else {
|
||||
/* Called for the first time. Ask the driver to send us more data. */
|
||||
scsi_write_complete(r, 0);
|
||||
@ -1332,9 +1326,6 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
|
||||
scsi_req_ref(&r->req);
|
||||
bdrv_acct_start(s->qdev.conf.bs, &r->acct, 0, BDRV_ACCT_FLUSH);
|
||||
r->req.aiocb = bdrv_aio_flush(s->qdev.conf.bs, scsi_flush_complete, r);
|
||||
if (r->req.aiocb == NULL) {
|
||||
scsi_flush_complete(r, -EIO);
|
||||
}
|
||||
return 0;
|
||||
case READ_6:
|
||||
case READ_10:
|
||||
|
@ -152,10 +152,6 @@ static int execute_command(BlockDriverState *bdrv,
|
||||
r->io_header.flags |= SG_FLAG_DIRECT_IO;
|
||||
|
||||
r->req.aiocb = bdrv_aio_ioctl(bdrv, SG_IO, &r->io_header, complete, r);
|
||||
if (r->req.aiocb == NULL) {
|
||||
BADF("execute_command: read failed !\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -288,19 +288,13 @@ static void virtio_submit_multiwrite(BlockDriverState *bs, MultiReqBuffer *mrb)
|
||||
|
||||
static void virtio_blk_handle_flush(VirtIOBlockReq *req, MultiReqBuffer *mrb)
|
||||
{
|
||||
BlockDriverAIOCB *acb;
|
||||
|
||||
bdrv_acct_start(req->dev->bs, &req->acct, 0, BDRV_ACCT_FLUSH);
|
||||
|
||||
/*
|
||||
* Make sure all outstanding writes are posted to the backing device.
|
||||
*/
|
||||
virtio_submit_multiwrite(req->dev->bs, mrb);
|
||||
|
||||
acb = bdrv_aio_flush(req->dev->bs, virtio_blk_flush_complete, req);
|
||||
if (!acb) {
|
||||
virtio_blk_flush_complete(req, -EIO);
|
||||
}
|
||||
bdrv_aio_flush(req->dev->bs, virtio_blk_flush_complete, req);
|
||||
}
|
||||
|
||||
static void virtio_blk_handle_write(VirtIOBlockReq *req, MultiReqBuffer *mrb)
|
||||
@ -340,7 +334,6 @@ static void virtio_blk_handle_write(VirtIOBlockReq *req, MultiReqBuffer *mrb)
|
||||
|
||||
static void virtio_blk_handle_read(VirtIOBlockReq *req)
|
||||
{
|
||||
BlockDriverAIOCB *acb;
|
||||
uint64_t sector;
|
||||
|
||||
sector = ldq_p(&req->out->sector);
|
||||
@ -355,13 +348,9 @@ static void virtio_blk_handle_read(VirtIOBlockReq *req)
|
||||
virtio_blk_rw_complete(req, -EIO);
|
||||
return;
|
||||
}
|
||||
|
||||
acb = bdrv_aio_readv(req->dev->bs, sector, &req->qiov,
|
||||
req->qiov.size / BDRV_SECTOR_SIZE,
|
||||
virtio_blk_rw_complete, req);
|
||||
if (!acb) {
|
||||
virtio_blk_rw_complete(req, -EIO);
|
||||
}
|
||||
bdrv_aio_readv(req->dev->bs, sector, &req->qiov,
|
||||
req->qiov.size / BDRV_SECTOR_SIZE,
|
||||
virtio_blk_rw_complete, req);
|
||||
}
|
||||
|
||||
static void virtio_blk_handle_request(VirtIOBlockReq *req,
|
||||
|
@ -166,8 +166,6 @@ BlockDriverAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd,
|
||||
off_t offset = sector_num * 512;
|
||||
|
||||
laiocb = qemu_aio_get(&laio_pool, bs, cb, opaque);
|
||||
if (!laiocb)
|
||||
return NULL;
|
||||
laiocb->nbytes = nb_sectors * 512;
|
||||
laiocb->ctx = s;
|
||||
laiocb->ret = -EINPROGRESS;
|
||||
|
@ -611,8 +611,6 @@ BlockDriverAIOCB *paio_submit(BlockDriverState *bs, int fd,
|
||||
struct qemu_paiocb *acb;
|
||||
|
||||
acb = qemu_aio_get(&raw_aio_pool, bs, cb, opaque);
|
||||
if (!acb)
|
||||
return NULL;
|
||||
acb->aio_type = type;
|
||||
acb->aio_fildes = fd;
|
||||
|
||||
@ -638,8 +636,6 @@ BlockDriverAIOCB *paio_ioctl(BlockDriverState *bs, int fd,
|
||||
struct qemu_paiocb *acb;
|
||||
|
||||
acb = qemu_aio_get(&raw_aio_pool, bs, cb, opaque);
|
||||
if (!acb)
|
||||
return NULL;
|
||||
acb->aio_type = QEMU_AIO_IOCTL;
|
||||
acb->aio_fildes = fd;
|
||||
acb->aio_offset = 0;
|
||||
|
@ -24,13 +24,13 @@ ETEXI
|
||||
DEF("commit", img_commit,
|
||||
"commit [-f fmt] [-t cache] filename")
|
||||
STEXI
|
||||
@item commit [-f @var{fmt}] @var{filename}
|
||||
@item commit [-f @var{fmt}] [-t @var{cache}] @var{filename}
|
||||
ETEXI
|
||||
|
||||
DEF("convert", img_convert,
|
||||
"convert [-c] [-p] [-f fmt] [-t cache] [-O output_fmt] [-o options] [-s snapshot_name] [-S sparse_size] filename [filename2 [...]] output_filename")
|
||||
STEXI
|
||||
@item convert [-c] [-p] [-f @var{fmt}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_name}] [-S @var{sparse_size}] @var{filename} [@var{filename2} [...]] @var{output_filename}
|
||||
@item convert [-c] [-p] [-f @var{fmt}] [-t @var{cache}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_name}] [-S @var{sparse_size}] @var{filename} [@var{filename2} [...]] @var{output_filename}
|
||||
ETEXI
|
||||
|
||||
DEF("info", img_info,
|
||||
@ -48,7 +48,7 @@ ETEXI
|
||||
DEF("rebase", img_rebase,
|
||||
"rebase [-f fmt] [-t cache] [-p] [-u] -b backing_file [-F backing_fmt] filename")
|
||||
STEXI
|
||||
@item rebase [-f @var{fmt}] [-p] [-u] -b @var{backing_file} [-F @var{backing_fmt}] @var{filename}
|
||||
@item rebase [-f @var{fmt}] [-t @var{cache}] [-p] [-u] -b @var{backing_file} [-F @var{backing_fmt}] @var{filename}
|
||||
ETEXI
|
||||
|
||||
DEF("resize", img_resize,
|
||||
|
42
qemu-img.c
42
qemu-img.c
@ -1420,6 +1420,8 @@ static int img_rebase(int argc, char **argv)
|
||||
*/
|
||||
if (!unsafe) {
|
||||
uint64_t num_sectors;
|
||||
uint64_t old_backing_num_sectors;
|
||||
uint64_t new_backing_num_sectors;
|
||||
uint64_t sector;
|
||||
int n;
|
||||
uint8_t * buf_old;
|
||||
@ -1430,6 +1432,8 @@ static int img_rebase(int argc, char **argv)
|
||||
buf_new = qemu_blockalign(bs, IO_BUF_SIZE);
|
||||
|
||||
bdrv_get_geometry(bs, &num_sectors);
|
||||
bdrv_get_geometry(bs_old_backing, &old_backing_num_sectors);
|
||||
bdrv_get_geometry(bs_new_backing, &new_backing_num_sectors);
|
||||
|
||||
local_progress = (float)100 /
|
||||
(num_sectors / MIN(num_sectors, IO_BUF_SIZE / 512));
|
||||
@ -1448,16 +1452,36 @@ static int img_rebase(int argc, char **argv)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Read old and new backing file */
|
||||
ret = bdrv_read(bs_old_backing, sector, buf_old, n);
|
||||
if (ret < 0) {
|
||||
error_report("error while reading from old backing file");
|
||||
goto out;
|
||||
/*
|
||||
* Read old and new backing file and take into consideration that
|
||||
* backing files may be smaller than the COW image.
|
||||
*/
|
||||
if (sector >= old_backing_num_sectors) {
|
||||
memset(buf_old, 0, n * BDRV_SECTOR_SIZE);
|
||||
} else {
|
||||
if (sector + n > old_backing_num_sectors) {
|
||||
n = old_backing_num_sectors - sector;
|
||||
}
|
||||
|
||||
ret = bdrv_read(bs_old_backing, sector, buf_old, n);
|
||||
if (ret < 0) {
|
||||
error_report("error while reading from old backing file");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
ret = bdrv_read(bs_new_backing, sector, buf_new, n);
|
||||
if (ret < 0) {
|
||||
error_report("error while reading from new backing file");
|
||||
goto out;
|
||||
|
||||
if (sector >= new_backing_num_sectors) {
|
||||
memset(buf_new, 0, n * BDRV_SECTOR_SIZE);
|
||||
} else {
|
||||
if (sector + n > new_backing_num_sectors) {
|
||||
n = new_backing_num_sectors - sector;
|
||||
}
|
||||
|
||||
ret = bdrv_read(bs_new_backing, sector, buf_new, n);
|
||||
if (ret < 0) {
|
||||
error_report("error while reading from new backing file");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/* If they differ, we need to write to the COW file */
|
||||
|
@ -45,6 +45,10 @@ indicates the consecutive number of bytes that must contain only zeros
|
||||
for qemu-img to create a sparse image during conversion. This value is rounded
|
||||
down to the nearest 512 bytes. You may use the common size suffixes like
|
||||
@code{k} for kilobytes.
|
||||
@item -t @var{cache}
|
||||
specifies the cache mode that should be used with the (destination) file. See
|
||||
the documentation of the emulator's @code{-drive cache=...} option for allowed
|
||||
values.
|
||||
@end table
|
||||
|
||||
Parameters to snapshot subcommand:
|
||||
@ -87,11 +91,11 @@ this case. @var{backing_file} will never be modified unless you use the
|
||||
The size can also be specified using the @var{size} option with @code{-o},
|
||||
it doesn't need to be specified separately in this case.
|
||||
|
||||
@item commit [-f @var{fmt}] @var{filename}
|
||||
@item commit [-f @var{fmt}] [-t @var{cache}] @var{filename}
|
||||
|
||||
Commit the changes recorded in @var{filename} in its base image.
|
||||
|
||||
@item convert [-c] [-p] [-f @var{fmt}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_name}] [-S @var{sparse_size}] @var{filename} [@var{filename2} [...]] @var{output_filename}
|
||||
@item convert [-c] [-p] [-f @var{fmt}] [-t @var{cache}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_name}] [-S @var{sparse_size}] @var{filename} [@var{filename2} [...]] @var{output_filename}
|
||||
|
||||
Convert the disk image @var{filename} or a snapshot @var{snapshot_name} to disk image @var{output_filename}
|
||||
using format @var{output_fmt}. It can be optionally compressed (@code{-c}
|
||||
@ -121,7 +125,7 @@ they are displayed too.
|
||||
|
||||
List, apply, create or delete snapshots in image @var{filename}.
|
||||
|
||||
@item rebase [-f @var{fmt}] [-p] [-u] -b @var{backing_file} [-F @var{backing_fmt}] @var{filename}
|
||||
@item rebase [-f @var{fmt}] [-t @var{cache}] [-p] [-u] -b @var{backing_file} [-F @var{backing_fmt}] @var{filename}
|
||||
|
||||
Changes the backing file of an image. Only the formats @code{qcow2} and
|
||||
@code{qed} support changing the backing file.
|
||||
|
39
qemu-io.c
39
qemu-io.c
@ -244,14 +244,10 @@ static void aio_rw_done(void *opaque, int ret)
|
||||
|
||||
static int do_aio_readv(QEMUIOVector *qiov, int64_t offset, int *total)
|
||||
{
|
||||
BlockDriverAIOCB *acb;
|
||||
int async_ret = NOT_DONE;
|
||||
|
||||
acb = bdrv_aio_readv(bs, offset >> 9, qiov, qiov->size >> 9,
|
||||
aio_rw_done, &async_ret);
|
||||
if (!acb) {
|
||||
return -EIO;
|
||||
}
|
||||
bdrv_aio_readv(bs, offset >> 9, qiov, qiov->size >> 9,
|
||||
aio_rw_done, &async_ret);
|
||||
while (async_ret == NOT_DONE) {
|
||||
qemu_aio_wait();
|
||||
}
|
||||
@ -262,15 +258,10 @@ static int do_aio_readv(QEMUIOVector *qiov, int64_t offset, int *total)
|
||||
|
||||
static int do_aio_writev(QEMUIOVector *qiov, int64_t offset, int *total)
|
||||
{
|
||||
BlockDriverAIOCB *acb;
|
||||
int async_ret = NOT_DONE;
|
||||
|
||||
acb = bdrv_aio_writev(bs, offset >> 9, qiov, qiov->size >> 9,
|
||||
aio_rw_done, &async_ret);
|
||||
if (!acb) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
bdrv_aio_writev(bs, offset >> 9, qiov, qiov->size >> 9,
|
||||
aio_rw_done, &async_ret);
|
||||
while (async_ret == NOT_DONE) {
|
||||
qemu_aio_wait();
|
||||
}
|
||||
@ -1151,7 +1142,6 @@ static int aio_read_f(int argc, char **argv)
|
||||
{
|
||||
int nr_iov, c;
|
||||
struct aio_ctx *ctx = calloc(1, sizeof(struct aio_ctx));
|
||||
BlockDriverAIOCB *acb;
|
||||
|
||||
while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
|
||||
switch (c) {
|
||||
@ -1206,14 +1196,8 @@ static int aio_read_f(int argc, char **argv)
|
||||
}
|
||||
|
||||
gettimeofday(&ctx->t1, NULL);
|
||||
acb = bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov,
|
||||
ctx->qiov.size >> 9, aio_read_done, ctx);
|
||||
if (!acb) {
|
||||
free(ctx->buf);
|
||||
free(ctx);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov,
|
||||
ctx->qiov.size >> 9, aio_read_done, ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1254,7 +1238,6 @@ static int aio_write_f(int argc, char **argv)
|
||||
int nr_iov, c;
|
||||
int pattern = 0xcd;
|
||||
struct aio_ctx *ctx = calloc(1, sizeof(struct aio_ctx));
|
||||
BlockDriverAIOCB *acb;
|
||||
|
||||
while ((c = getopt(argc, argv, "CqP:")) != EOF) {
|
||||
switch (c) {
|
||||
@ -1305,14 +1288,8 @@ static int aio_write_f(int argc, char **argv)
|
||||
}
|
||||
|
||||
gettimeofday(&ctx->t1, NULL);
|
||||
acb = bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov,
|
||||
ctx->qiov.size >> 9, aio_write_done, ctx);
|
||||
if (!acb) {
|
||||
free(ctx->buf);
|
||||
free(ctx);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov,
|
||||
ctx->qiov.size >> 9, aio_write_done, ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
2
savevm.c
2
savevm.c
@ -2002,7 +2002,7 @@ void do_savevm(Monitor *mon, const QDict *qdict)
|
||||
int ret;
|
||||
QEMUFile *f;
|
||||
int saved_vm_running;
|
||||
uint32_t vm_state_size;
|
||||
uint64_t vm_state_size;
|
||||
#ifdef _WIN32
|
||||
struct _timeb tb;
|
||||
struct tm *ptm;
|
||||
|
@ -59,8 +59,6 @@ virtio_console_chr_event(unsigned int port, int event) "port %u, event %d"
|
||||
bdrv_open_common(void *bs, const char *filename, int flags, const char *format_name) "bs %p filename \"%s\" flags %#x format_name \"%s\""
|
||||
multiwrite_cb(void *mcb, int ret) "mcb %p ret %d"
|
||||
bdrv_aio_multiwrite(void *mcb, int num_callbacks, int num_reqs) "mcb %p num_callbacks %d num_reqs %d"
|
||||
bdrv_aio_multiwrite_earlyfail(void *mcb) "mcb %p"
|
||||
bdrv_aio_multiwrite_latefail(void *mcb, int i) "mcb %p i %d"
|
||||
bdrv_aio_discard(void *bs, int64_t sector_num, int nb_sectors, void *opaque) "bs %p sector_num %"PRId64" nb_sectors %d opaque %p"
|
||||
bdrv_aio_flush(void *bs, void *opaque) "bs %p opaque %p"
|
||||
bdrv_aio_readv(void *bs, int64_t sector_num, int nb_sectors, void *opaque) "bs %p sector_num %"PRId64" nb_sectors %d opaque %p"
|
||||
|
Loading…
Reference in New Issue
Block a user