Merge remote-tracking branch 'kwolf/for-anthony' into staging

This commit is contained in:
Anthony Liguori 2011-12-19 08:50:47 -06:00
commit ddf83d0173
31 changed files with 204 additions and 344 deletions

View File

@ -251,22 +251,12 @@ static int mig_save_device_bulk(Monitor *mon, QEMUFile *f,
blk->aiocb = bdrv_aio_readv(bs, cur_sector, &blk->qiov, blk->aiocb = bdrv_aio_readv(bs, cur_sector, &blk->qiov,
nr_sectors, blk_mig_read_cb, blk); nr_sectors, blk_mig_read_cb, blk);
if (!blk->aiocb) {
goto error;
}
block_mig_state.submitted++; block_mig_state.submitted++;
bdrv_reset_dirty(bs, cur_sector, nr_sectors); bdrv_reset_dirty(bs, cur_sector, nr_sectors);
bmds->cur_sector = cur_sector + nr_sectors; bmds->cur_sector = cur_sector + nr_sectors;
return (bmds->cur_sector >= total_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) 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, blk->aiocb = bdrv_aio_readv(bmds->bs, sector, &blk->qiov,
nr_sectors, blk_mig_read_cb, blk); nr_sectors, blk_mig_read_cb, blk);
if (!blk->aiocb) {
goto error;
}
block_mig_state.submitted++; block_mig_state.submitted++;
bmds_set_aio_inflight(bmds, sector, nr_sectors, 1); bmds_set_aio_inflight(bmds, sector, nr_sectors, 1);
} else { } else {

56
block.c
View File

@ -2812,7 +2812,6 @@ static int multiwrite_merge(BlockDriverState *bs, BlockRequest *reqs,
*/ */
int bdrv_aio_multiwrite(BlockDriverState *bs, BlockRequest *reqs, int num_reqs) int bdrv_aio_multiwrite(BlockDriverState *bs, BlockRequest *reqs, int num_reqs)
{ {
BlockDriverAIOCB *acb;
MultiwriteCB *mcb; MultiwriteCB *mcb;
int i; 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); trace_bdrv_aio_multiwrite(mcb, mcb->num_callbacks, num_reqs);
/* /* Run the aio requests. */
* Run the aio requests. As soon as one request can't be submitted mcb->num_requests = num_reqs;
* 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
for (i = 0; i < num_reqs; i++) { for (i = 0; i < num_reqs; i++) {
mcb->num_requests++; bdrv_aio_writev(bs, reqs[i].sector, reqs[i].qiov,
acb = bdrv_aio_writev(bs, reqs[i].sector, reqs[i].qiov,
reqs[i].nb_sectors, multiwrite_cb, mcb); 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; 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) void bdrv_aio_cancel(BlockDriverAIOCB *acb)
@ -3123,9 +3077,7 @@ static BlockDriverAIOCB *bdrv_aio_rw_vector(BlockDriverState *bs,
acb->is_write = is_write; acb->is_write = is_write;
acb->qiov = qiov; acb->qiov = qiov;
acb->bounce = qemu_blockalign(bs, qiov->size); acb->bounce = qemu_blockalign(bs, qiov->size);
acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb);
if (!acb->bh)
acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb);
if (is_write) { if (is_write) {
qemu_iovec_to_buffer(acb->qiov, acb->bounce); qemu_iovec_to_buffer(acb->qiov, acb->bounce);

View File

@ -22,7 +22,7 @@ typedef struct QEMUSnapshotInfo {
/* the following fields are informative. They are not needed for /* the following fields are informative. They are not needed for
the consistency of the snapshot */ the consistency of the snapshot */
char name[256]; /* user chosen name */ 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_sec; /* UTC date of the snapshot */
uint32_t date_nsec; uint32_t date_nsec;
uint64_t vm_clock_nsec; /* VM clock relative to boot */ uint64_t vm_clock_nsec; /* VM clock relative to boot */

View File

@ -310,14 +310,10 @@ static BlockDriverAIOCB *blkverify_aio_readv(BlockDriverState *bs,
qemu_iovec_init(&acb->raw_qiov, acb->qiov->niov); qemu_iovec_init(&acb->raw_qiov, acb->qiov->niov);
blkverify_iovec_clone(&acb->raw_qiov, qiov, acb->buf); blkverify_iovec_clone(&acb->raw_qiov, qiov, acb->buf);
if (!bdrv_aio_readv(s->test_file, sector_num, qiov, nb_sectors, bdrv_aio_readv(s->test_file, sector_num, qiov, nb_sectors,
blkverify_aio_cb, acb)) { blkverify_aio_cb, acb);
blkverify_aio_cb(acb, -EIO); bdrv_aio_readv(bs->file, sector_num, &acb->raw_qiov, nb_sectors,
} blkverify_aio_cb, acb);
if (!bdrv_aio_readv(bs->file, sector_num, &acb->raw_qiov, nb_sectors,
blkverify_aio_cb, acb)) {
blkverify_aio_cb(acb, -EIO);
}
return &acb->common; return &acb->common;
} }
@ -329,14 +325,10 @@ static BlockDriverAIOCB *blkverify_aio_writev(BlockDriverState *bs,
BlkverifyAIOCB *acb = blkverify_aio_get(bs, true, sector_num, qiov, BlkverifyAIOCB *acb = blkverify_aio_get(bs, true, sector_num, qiov,
nb_sectors, cb, opaque); nb_sectors, cb, opaque);
if (!bdrv_aio_writev(s->test_file, sector_num, qiov, nb_sectors, bdrv_aio_writev(s->test_file, sector_num, qiov, nb_sectors,
blkverify_aio_cb, acb)) { blkverify_aio_cb, acb);
blkverify_aio_cb(acb, -EIO); bdrv_aio_writev(bs->file, sector_num, qiov, nb_sectors,
} blkverify_aio_cb, acb);
if (!bdrv_aio_writev(bs->file, sector_num, qiov, nb_sectors,
blkverify_aio_cb, acb)) {
blkverify_aio_cb(acb, -EIO);
}
return &acb->common; return &acb->common;
} }

View File

@ -64,15 +64,26 @@ static int cow_open(BlockDriverState *bs, int flags)
struct cow_header_v2 cow_header; struct cow_header_v2 cow_header;
int bitmap_size; int bitmap_size;
int64_t size; int64_t size;
int ret;
/* see if it is a cow image */ /* see if it is a cow image */
if (bdrv_pread(bs->file, 0, &cow_header, sizeof(cow_header)) != ret = bdrv_pread(bs->file, 0, &cow_header, sizeof(cow_header));
sizeof(cow_header)) { if (ret < 0) {
goto fail; goto fail;
} }
if (be32_to_cpu(cow_header.magic) != COW_MAGIC || if (be32_to_cpu(cow_header.magic) != COW_MAGIC) {
be32_to_cpu(cow_header.version) != COW_VERSION) { 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; goto fail;
} }
@ -88,7 +99,7 @@ static int cow_open(BlockDriverState *bs, int flags)
qemu_co_mutex_init(&s->lock); qemu_co_mutex_init(&s->lock);
return 0; return 0;
fail: 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, ret = bdrv_pread(bs->file,
s->cow_sectors_offset + sector_num * 512, s->cow_sectors_offset + sector_num * 512,
buf, n * 512); buf, n * 512);
if (ret != n * 512) if (ret < 0) {
return -1; return ret;
}
} else { } else {
if (bs->backing_hd) { if (bs->backing_hd) {
/* read from the base image */ /* read from the base image */
ret = bdrv_read(bs->backing_hd, sector_num, buf, n); ret = bdrv_read(bs->backing_hd, sector_num, buf, n);
if (ret < 0) if (ret < 0) {
return -1; return ret;
}
} else { } else {
memset(buf, 0, n * 512); memset(buf, 0, n * 512);
} }
} }
nb_sectors -= n; nb_sectors -= n;
sector_num += 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, ret = bdrv_pwrite(bs->file, s->cow_sectors_offset + sector_num * 512,
buf, nb_sectors * 512); buf, nb_sectors * 512);
if (ret != nb_sectors * 512) if (ret < 0) {
return -1; return ret;
}
return cow_update_bitmap(bs, sector_num, nb_sectors); 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.sectorsize = cpu_to_be32(512);
cow_header.size = cpu_to_be64(image_sectors * 512); cow_header.size = cpu_to_be64(image_sectors * 512);
ret = bdrv_pwrite(cow_bs, 0, &cow_header, sizeof(cow_header)); ret = bdrv_pwrite(cow_bs, 0, &cow_header, sizeof(cow_header));
if (ret != sizeof(cow_header)) { if (ret < 0) {
goto exit; goto exit;
} }
/* resize to include at least all the bitmap */ /* resize to include at least all the bitmap */
ret = bdrv_truncate(cow_bs, ret = bdrv_truncate(cow_bs,
sizeof(cow_header) + ((image_sectors + 7) >> 3)); sizeof(cow_header) + ((image_sectors + 7) >> 3));
if (ret) { if (ret < 0) {
goto exit; goto exit;
} }

View File

@ -509,10 +509,6 @@ static BlockDriverAIOCB *curl_aio_readv(BlockDriverState *bs,
acb = qemu_aio_get(&curl_aio_pool, bs, cb, opaque); acb = qemu_aio_get(&curl_aio_pool, bs, cb, opaque);
if (!acb) {
return NULL;
}
acb->qiov = qiov; acb->qiov = qiov;
acb->sector_num = sector_num; acb->sector_num = sector_num;
acb->nb_sectors = nb_sectors; acb->nb_sectors = nb_sectors;

View File

@ -46,6 +46,10 @@ typedef struct QEMU_PACKED QCowSnapshotHeader {
/* name follows */ /* name follows */
} QCowSnapshotHeader; } QCowSnapshotHeader;
typedef struct QEMU_PACKED QCowSnapshotExtraData {
uint64_t vm_state_size_large;
} QCowSnapshotExtraData;
void qcow2_free_snapshots(BlockDriverState *bs) void qcow2_free_snapshots(BlockDriverState *bs)
{ {
BDRVQcowState *s = bs->opaque; BDRVQcowState *s = bs->opaque;
@ -64,6 +68,7 @@ int qcow2_read_snapshots(BlockDriverState *bs)
{ {
BDRVQcowState *s = bs->opaque; BDRVQcowState *s = bs->opaque;
QCowSnapshotHeader h; QCowSnapshotHeader h;
QCowSnapshotExtraData extra;
QCowSnapshot *sn; QCowSnapshot *sn;
int i, id_str_size, name_size; int i, id_str_size, name_size;
int64_t offset; int64_t offset;
@ -100,9 +105,18 @@ int qcow2_read_snapshots(BlockDriverState *bs)
id_str_size = be16_to_cpu(h.id_str_size); id_str_size = be16_to_cpu(h.id_str_size);
name_size = be16_to_cpu(h.name_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; offset += extra_data_size;
if (extra_data_size >= 8) {
sn->vm_state_size = be64_to_cpu(extra.vm_state_size_large);
}
/* Read snapshot ID */ /* Read snapshot ID */
sn->id_str = g_malloc(id_str_size + 1); sn->id_str = g_malloc(id_str_size + 1);
ret = bdrv_pread(bs->file, offset, sn->id_str, id_str_size); 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; BDRVQcowState *s = bs->opaque;
QCowSnapshot *sn; QCowSnapshot *sn;
QCowSnapshotHeader h; QCowSnapshotHeader h;
QCowSnapshotExtraData extra;
int i, name_size, id_str_size, snapshots_size; int i, name_size, id_str_size, snapshots_size;
struct { struct {
uint32_t nb_snapshots; uint32_t nb_snapshots;
@ -150,6 +165,7 @@ static int qcow2_write_snapshots(BlockDriverState *bs)
sn = s->snapshots + i; sn = s->snapshots + i;
offset = align_offset(offset, 8); offset = align_offset(offset, 8);
offset += sizeof(h); offset += sizeof(h);
offset += sizeof(extra);
offset += strlen(sn->id_str); offset += strlen(sn->id_str);
offset += strlen(sn->name); offset += strlen(sn->name);
} }
@ -169,10 +185,18 @@ static int qcow2_write_snapshots(BlockDriverState *bs)
memset(&h, 0, sizeof(h)); memset(&h, 0, sizeof(h));
h.l1_table_offset = cpu_to_be64(sn->l1_table_offset); h.l1_table_offset = cpu_to_be64(sn->l1_table_offset);
h.l1_size = cpu_to_be32(sn->l1_size); 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_sec = cpu_to_be32(sn->date_sec);
h.date_nsec = cpu_to_be32(sn->date_nsec); h.date_nsec = cpu_to_be32(sn->date_nsec);
h.vm_clock_nsec = cpu_to_be64(sn->vm_clock_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); id_str_size = strlen(sn->id_str);
name_size = strlen(sn->name); name_size = strlen(sn->name);
@ -186,6 +210,12 @@ static int qcow2_write_snapshots(BlockDriverState *bs)
} }
offset += sizeof(h); 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); ret = bdrv_pwrite(bs->file, offset, sn->id_str, id_str_size);
if (ret < 0) { if (ret < 0) {
goto fail; goto fail;

View File

@ -635,6 +635,7 @@ static void qcow2_close(BlockDriverState *bs)
g_free(s->cluster_cache); g_free(s->cluster_cache);
qemu_vfree(s->cluster_data); qemu_vfree(s->cluster_data);
qcow2_refcount_close(bs); qcow2_refcount_close(bs);
qcow2_free_snapshots(bs);
} }
static void qcow2_invalidate_cache(BlockDriverState *bs) static void qcow2_invalidate_cache(BlockDriverState *bs)

View File

@ -78,7 +78,7 @@ typedef struct QCowSnapshot {
uint32_t l1_size; uint32_t l1_size;
char *id_str; char *id_str;
char *name; char *name;
uint32_t vm_state_size; uint64_t vm_state_size;
uint32_t date_sec; uint32_t date_sec;
uint32_t date_nsec; uint32_t date_nsec;
uint64_t vm_clock_nsec; uint64_t vm_clock_nsec;

View File

@ -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), QEDReadTableCB *read_table_cb = gencb_alloc(sizeof(*read_table_cb),
cb, opaque); cb, opaque);
QEMUIOVector *qiov = &read_table_cb->qiov; QEMUIOVector *qiov = &read_table_cb->qiov;
BlockDriverAIOCB *aiocb;
trace_qed_read_table(s, offset, table); 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, read_table_cb->iov.iov_len = s->header.cluster_size * s->header.table_size,
qemu_iovec_init_external(qiov, &read_table_cb->iov, 1); qemu_iovec_init_external(qiov, &read_table_cb->iov, 1);
aiocb = bdrv_aio_readv(s->bs->file, offset / BDRV_SECTOR_SIZE, qiov, bdrv_aio_readv(s->bs->file, offset / BDRV_SECTOR_SIZE, qiov,
qiov->size / BDRV_SECTOR_SIZE, qiov->size / BDRV_SECTOR_SIZE,
qed_read_table_cb, read_table_cb); qed_read_table_cb, read_table_cb);
if (!aiocb) {
qed_read_table_cb(read_table_cb, -EIO);
}
} }
typedef struct { typedef struct {
@ -127,7 +123,6 @@ static void qed_write_table(BDRVQEDState *s, uint64_t offset, QEDTable *table,
BlockDriverCompletionFunc *cb, void *opaque) BlockDriverCompletionFunc *cb, void *opaque)
{ {
QEDWriteTableCB *write_table_cb; QEDWriteTableCB *write_table_cb;
BlockDriverAIOCB *aiocb;
unsigned int sector_mask = BDRV_SECTOR_SIZE / sizeof(uint64_t) - 1; unsigned int sector_mask = BDRV_SECTOR_SIZE / sizeof(uint64_t) - 1;
unsigned int start, end, i; unsigned int start, end, i;
size_t len_bytes; 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 */ /* Adjust for offset into table */
offset += start * sizeof(uint64_t); offset += start * sizeof(uint64_t);
aiocb = bdrv_aio_writev(s->bs->file, offset / BDRV_SECTOR_SIZE, bdrv_aio_writev(s->bs->file, offset / BDRV_SECTOR_SIZE,
&write_table_cb->qiov, &write_table_cb->qiov,
write_table_cb->qiov.size / BDRV_SECTOR_SIZE, write_table_cb->qiov.size / BDRV_SECTOR_SIZE,
qed_write_table_cb, write_table_cb); qed_write_table_cb, write_table_cb);
if (!aiocb) {
qed_write_table_cb(write_table_cb, -EIO);
}
} }
/** /**

View File

@ -123,7 +123,6 @@ static void qed_write_header_read_cb(void *opaque, int ret)
{ {
QEDWriteHeaderCB *write_header_cb = opaque; QEDWriteHeaderCB *write_header_cb = opaque;
BDRVQEDState *s = write_header_cb->s; BDRVQEDState *s = write_header_cb->s;
BlockDriverAIOCB *acb;
if (ret) { if (ret) {
qed_write_header_cb(write_header_cb, 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 */ /* Update header */
qed_header_cpu_to_le(&s->header, (QEDHeader *)write_header_cb->buf); qed_header_cpu_to_le(&s->header, (QEDHeader *)write_header_cb->buf);
acb = bdrv_aio_writev(s->bs->file, 0, &write_header_cb->qiov, bdrv_aio_writev(s->bs->file, 0, &write_header_cb->qiov,
write_header_cb->nsectors, qed_write_header_cb, write_header_cb->nsectors, qed_write_header_cb,
write_header_cb); write_header_cb);
if (!acb) {
qed_write_header_cb(write_header_cb, -EIO);
}
} }
/** /**
@ -156,7 +152,6 @@ static void qed_write_header(BDRVQEDState *s, BlockDriverCompletionFunc cb,
* them, and write back. * them, and write back.
*/ */
BlockDriverAIOCB *acb;
int nsectors = (sizeof(QEDHeader) + BDRV_SECTOR_SIZE - 1) / int nsectors = (sizeof(QEDHeader) + BDRV_SECTOR_SIZE - 1) /
BDRV_SECTOR_SIZE; BDRV_SECTOR_SIZE;
size_t len = nsectors * 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; write_header_cb->iov.iov_len = len;
qemu_iovec_init_external(&write_header_cb->qiov, &write_header_cb->iov, 1); 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, bdrv_aio_readv(s->bs->file, 0, &write_header_cb->qiov, nsectors,
qed_write_header_read_cb, write_header_cb); qed_write_header_read_cb, write_header_cb);
if (!acb) {
qed_write_header_cb(write_header_cb, -EIO);
}
} }
static uint64_t qed_max_image_size(uint32_t cluster_size, uint32_t table_size) 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, QEMUIOVector *qiov,
BlockDriverCompletionFunc *cb, void *opaque) BlockDriverCompletionFunc *cb, void *opaque)
{ {
BlockDriverAIOCB *aiocb;
uint64_t backing_length = 0; uint64_t backing_length = 0;
size_t size; 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); size = MIN((uint64_t)backing_length - pos, qiov->size);
BLKDBG_EVENT(s->bs->file, BLKDBG_READ_BACKING); BLKDBG_EVENT(s->bs->file, BLKDBG_READ_BACKING);
aiocb = bdrv_aio_readv(s->bs->backing_hd, pos / BDRV_SECTOR_SIZE, bdrv_aio_readv(s->bs->backing_hd, pos / BDRV_SECTOR_SIZE,
qiov, size / BDRV_SECTOR_SIZE, cb, opaque); qiov, size / BDRV_SECTOR_SIZE, cb, opaque);
if (!aiocb) {
cb(opaque, -EIO);
}
} }
typedef struct { typedef struct {
@ -786,7 +774,6 @@ static void qed_copy_from_backing_file_write(void *opaque, int ret)
{ {
CopyFromBackingFileCB *copy_cb = opaque; CopyFromBackingFileCB *copy_cb = opaque;
BDRVQEDState *s = copy_cb->s; BDRVQEDState *s = copy_cb->s;
BlockDriverAIOCB *aiocb;
if (ret) { if (ret) {
qed_copy_from_backing_file_cb(copy_cb, 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); BLKDBG_EVENT(s->bs->file, BLKDBG_COW_WRITE);
aiocb = bdrv_aio_writev(s->bs->file, copy_cb->offset / BDRV_SECTOR_SIZE, bdrv_aio_writev(s->bs->file, copy_cb->offset / BDRV_SECTOR_SIZE,
&copy_cb->qiov, &copy_cb->qiov, copy_cb->qiov.size / BDRV_SECTOR_SIZE,
copy_cb->qiov.size / BDRV_SECTOR_SIZE, qed_copy_from_backing_file_cb, copy_cb);
qed_copy_from_backing_file_cb, copy_cb);
if (!aiocb) {
qed_copy_from_backing_file_cb(copy_cb, -EIO);
}
} }
/** /**
@ -1022,7 +1005,6 @@ static void qed_aio_write_main(void *opaque, int ret)
uint64_t offset = acb->cur_cluster + uint64_t offset = acb->cur_cluster +
qed_offset_into_cluster(s, acb->cur_pos); qed_offset_into_cluster(s, acb->cur_pos);
BlockDriverCompletionFunc *next_fn; BlockDriverCompletionFunc *next_fn;
BlockDriverAIOCB *file_acb;
trace_qed_aio_write_main(s, acb, ret, offset, acb->cur_qiov.size); 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); BLKDBG_EVENT(s->bs->file, BLKDBG_WRITE_AIO);
file_acb = bdrv_aio_writev(s->bs->file, offset / BDRV_SECTOR_SIZE, bdrv_aio_writev(s->bs->file, offset / BDRV_SECTOR_SIZE,
&acb->cur_qiov, &acb->cur_qiov, acb->cur_qiov.size / BDRV_SECTOR_SIZE,
acb->cur_qiov.size / BDRV_SECTOR_SIZE, next_fn, acb);
next_fn, acb);
if (!file_acb) {
qed_aio_complete(acb, -EIO);
}
} }
/** /**
@ -1215,7 +1193,6 @@ static void qed_aio_read_data(void *opaque, int ret,
QEDAIOCB *acb = opaque; QEDAIOCB *acb = opaque;
BDRVQEDState *s = acb_to_s(acb); BDRVQEDState *s = acb_to_s(acb);
BlockDriverState *bs = acb->common.bs; BlockDriverState *bs = acb->common.bs;
BlockDriverAIOCB *file_acb;
/* Adjust offset into cluster */ /* Adjust offset into cluster */
offset += qed_offset_into_cluster(s, acb->cur_pos); 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); BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO);
file_acb = bdrv_aio_readv(bs->file, offset / BDRV_SECTOR_SIZE, bdrv_aio_readv(bs->file, offset / BDRV_SECTOR_SIZE,
&acb->cur_qiov, &acb->cur_qiov, acb->cur_qiov.size / BDRV_SECTOR_SIZE,
acb->cur_qiov.size / BDRV_SECTOR_SIZE, qed_aio_next_io, acb);
qed_aio_next_io, acb);
if (!file_acb) {
ret = -EIO;
goto err;
}
return; return;
err: err:

View File

@ -632,9 +632,6 @@ static BlockDriverAIOCB *rbd_aio_rw_vector(BlockDriverState *bs,
BDRVRBDState *s = bs->opaque; BDRVRBDState *s = bs->opaque;
acb = qemu_aio_get(&rbd_aio_pool, bs, cb, opaque); acb = qemu_aio_get(&rbd_aio_pool, bs, cb, opaque);
if (!acb) {
return NULL;
}
acb->write = write; acb->write = write;
acb->qiov = qiov; acb->qiov = qiov;
acb->bounce = qemu_blockalign(bs, qiov->size); acb->bounce = qemu_blockalign(bs, qiov->size);
@ -808,7 +805,7 @@ static int qemu_rbd_snap_list(BlockDriverState *bs,
} while (snap_count == -ERANGE); } while (snap_count == -ERANGE);
if (snap_count <= 0) { if (snap_count <= 0) {
return snap_count; goto done;
} }
sn_tab = g_malloc0(snap_count * sizeof(QEMUSnapshotInfo)); 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); rbd_snap_list_end(snaps);
done:
*psn_tab = sn_tab; *psn_tab = sn_tab;
return snap_count; return snap_count;
} }

View File

@ -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); bs, sector_num, qiov, nb_sectors, cb, opaque, is_write);
acb = qemu_aio_get(&vdi_aio_pool, bs, cb, opaque); acb = qemu_aio_get(&vdi_aio_pool, bs, cb, opaque);
if (acb) { acb->hd_aiocb = NULL;
acb->hd_aiocb = NULL; acb->sector_num = sector_num;
acb->sector_num = sector_num; acb->qiov = qiov;
acb->qiov = qiov; acb->is_write = is_write;
acb->is_write = is_write;
if (qiov->niov > 1) { if (qiov->niov > 1) {
acb->buf = qemu_blockalign(bs, qiov->size); acb->buf = qemu_blockalign(bs, qiov->size);
acb->orig_buf = acb->buf; acb->orig_buf = acb->buf;
if (is_write) { if (is_write) {
qemu_iovec_to_buffer(qiov, acb->buf); qemu_iovec_to_buffer(qiov, acb->buf);
}
} else {
acb->buf = (uint8_t *)qiov->iov->iov_base;
} }
acb->nb_sectors = nb_sectors; } else {
acb->n_sectors = 0; acb->buf = (uint8_t *)qiov->iov->iov_base;
acb->bmap_first = VDI_UNALLOCATED;
acb->bmap_last = VDI_UNALLOCATED;
acb->block_buffer = NULL;
acb->header_modified = 0;
} }
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; 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); qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
acb->hd_aiocb = bdrv_aio_readv(bs->file, offset, &acb->hd_qiov, acb->hd_aiocb = bdrv_aio_readv(bs->file, offset, &acb->hd_qiov,
n_sectors, vdi_aio_read_cb, acb); n_sectors, vdi_aio_read_cb, acb);
if (acb->hd_aiocb == NULL) {
ret = -EIO;
goto done;
}
} }
return; return;
done: done:
@ -657,10 +651,6 @@ static BlockDriverAIOCB *vdi_aio_readv(BlockDriverState *bs,
logout("\n"); logout("\n");
acb = vdi_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque, 0); 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); ret = vdi_schedule_bh(vdi_aio_rw_bh, acb);
if (ret < 0) { if (ret < 0) {
if (acb->qiov->niov > 1) { 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); qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
acb->hd_aiocb = bdrv_aio_writev(bs->file, 0, &acb->hd_qiov, 1, acb->hd_aiocb = bdrv_aio_writev(bs->file, 0, &acb->hd_qiov, 1,
vdi_aio_write_cb, acb); vdi_aio_write_cb, acb);
if (acb->hd_aiocb == NULL) {
ret = -EIO;
goto done;
}
return; return;
} else if (VDI_IS_ALLOCATED(acb->bmap_first)) { } else if (VDI_IS_ALLOCATED(acb->bmap_first)) {
/* One or more new blocks were allocated. */ /* 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); n_sectors, bmap_first);
acb->hd_aiocb = bdrv_aio_writev(bs->file, offset, &acb->hd_qiov, acb->hd_aiocb = bdrv_aio_writev(bs->file, offset, &acb->hd_qiov,
n_sectors, vdi_aio_write_cb, acb); n_sectors, vdi_aio_write_cb, acb);
if (acb->hd_aiocb == NULL) {
ret = -EIO;
goto done;
}
return; return;
} }
ret = 0; 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_aiocb = bdrv_aio_writev(bs->file, offset,
&acb->hd_qiov, s->block_sectors, &acb->hd_qiov, s->block_sectors,
vdi_aio_write_cb, acb); vdi_aio_write_cb, acb);
if (acb->hd_aiocb == NULL) {
ret = -EIO;
goto done;
}
} else { } else {
uint64_t offset = s->header.offset_data / SECTOR_SIZE + uint64_t offset = s->header.offset_data / SECTOR_SIZE +
(uint64_t)bmap_entry * s->block_sectors + (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); qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
acb->hd_aiocb = bdrv_aio_writev(bs->file, offset, &acb->hd_qiov, acb->hd_aiocb = bdrv_aio_writev(bs->file, offset, &acb->hd_qiov,
n_sectors, vdi_aio_write_cb, acb); n_sectors, vdi_aio_write_cb, acb);
if (acb->hd_aiocb == NULL) {
ret = -EIO;
goto done;
}
} }
return; return;
@ -827,10 +801,6 @@ static BlockDriverAIOCB *vdi_aio_writev(BlockDriverState *bs,
logout("\n"); logout("\n");
acb = vdi_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque, 1); 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); ret = vdi_schedule_bh(vdi_aio_rw_bh, acb);
if (ret < 0) { if (ret < 0) {
if (acb->qiov->niov > 1) { if (acb->qiov->niov > 1) {

View File

@ -35,6 +35,10 @@ enum {
POOL_MAX_SIZE = 64, 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 { typedef struct {
Coroutine base; Coroutine base;
void *stack; void *stack;
@ -48,10 +52,6 @@ typedef struct {
/** Currently executing coroutine */ /** Currently executing coroutine */
Coroutine *current; Coroutine *current;
/** Free list to speed up creation */
QLIST_HEAD(, Coroutine) pool;
unsigned int pool_size;
/** The default coroutine */ /** The default coroutine */
CoroutineUContext leader; CoroutineUContext leader;
} CoroutineThreadState; } CoroutineThreadState;
@ -75,7 +75,6 @@ static CoroutineThreadState *coroutine_get_thread_state(void)
if (!s) { if (!s) {
s = g_malloc0(sizeof(*s)); s = g_malloc0(sizeof(*s));
s->current = &s->leader.base; s->current = &s->leader.base;
QLIST_INIT(&s->pool);
pthread_setspecific(thread_state_key, s); pthread_setspecific(thread_state_key, s);
} }
return s; return s;
@ -84,14 +83,19 @@ static CoroutineThreadState *coroutine_get_thread_state(void)
static void qemu_coroutine_thread_cleanup(void *opaque) static void qemu_coroutine_thread_cleanup(void *opaque)
{ {
CoroutineThreadState *s = opaque; CoroutineThreadState *s = opaque;
g_free(s);
}
static void __attribute__((destructor)) coroutine_cleanup(void)
{
Coroutine *co; Coroutine *co;
Coroutine *tmp; 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(DO_UPCAST(CoroutineUContext, base, co)->stack);
g_free(co); g_free(co);
} }
g_free(s);
} }
static void __attribute__((constructor)) coroutine_init(void) static void __attribute__((constructor)) coroutine_init(void)
@ -169,13 +173,12 @@ static Coroutine *coroutine_new(void)
Coroutine *qemu_coroutine_new(void) Coroutine *qemu_coroutine_new(void)
{ {
CoroutineThreadState *s = coroutine_get_thread_state();
Coroutine *co; Coroutine *co;
co = QLIST_FIRST(&s->pool); co = QLIST_FIRST(&pool);
if (co) { if (co) {
QLIST_REMOVE(co, pool_next); QLIST_REMOVE(co, pool_next);
s->pool_size--; pool_size--;
} else { } else {
co = coroutine_new(); co = coroutine_new();
} }
@ -184,13 +187,12 @@ Coroutine *qemu_coroutine_new(void)
void qemu_coroutine_delete(Coroutine *co_) void qemu_coroutine_delete(Coroutine *co_)
{ {
CoroutineThreadState *s = coroutine_get_thread_state();
CoroutineUContext *co = DO_UPCAST(CoroutineUContext, base, co_); CoroutineUContext *co = DO_UPCAST(CoroutineUContext, base, co_);
if (s->pool_size < POOL_MAX_SIZE) { if (pool_size < POOL_MAX_SIZE) {
QLIST_INSERT_HEAD(&s->pool, &co->base, pool_next); QLIST_INSERT_HEAD(&pool, &co->base, pool_next);
co->base.caller = NULL; co->base.caller = NULL;
s->pool_size++; pool_size++;
return; return;
} }

View File

@ -217,7 +217,10 @@ void qemu_iovec_destroy(QEMUIOVector *qiov)
{ {
assert(qiov->nalloc != -1); assert(qiov->nalloc != -1);
qemu_iovec_reset(qiov);
g_free(qiov->iov); g_free(qiov->iov);
qiov->nalloc = 0;
qiov->iov = NULL;
} }
void qemu_iovec_reset(QEMUIOVector *qiov) void qemu_iovec_reset(QEMUIOVector *qiov)

View File

@ -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->acb = dbs->io_func(dbs->bs, dbs->sector_num, &dbs->iov,
dbs->iov.size / 512, dma_bdrv_cb, dbs); dbs->iov.size / 512, dma_bdrv_cb, dbs);
if (!dbs->acb) { assert(dbs->acb);
dma_complete(dbs, -EIO);
}
} }
static void dma_aio_cancel(BlockDriverAIOCB *acb) static void dma_aio_cancel(BlockDriverAIOCB *acb)

View File

@ -253,7 +253,13 @@ Snapshot table entry:
36 - 39: Size of extra data in the table entry (used for future 36 - 39: Size of extra data in the table entry (used for future
extensions of the format) 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) variable: Unique ID string for the snapshot (not null terminated)

View File

@ -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->aiocb = bdrv_aio_readv(s->bs, (int64_t)s->lba << 2,
&s->bus->dma->qiov, n * 4, &s->bus->dma->qiov, n * 4,
ide_atapi_cmd_read_dma_cb, s); 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; return;
eot: eot:
bdrv_acct_done(s->bs, &s->acct); bdrv_acct_done(s->bs, &s->acct);
s->bus->dma->ops->add_status(s->bus->dma, BM_STATUS_INT); s->bus->dma->ops->add_status(s->bus->dma, BM_STATUS_INT);

View File

@ -549,7 +549,6 @@ void ide_dma_cb(void *opaque, int ret)
int n; int n;
int64_t sector_num; int64_t sector_num;
handle_rw_error:
if (ret < 0) { if (ret < 0) {
int op = BM_STATUS_DMA_RETRY; int op = BM_STATUS_DMA_RETRY;
@ -608,11 +607,6 @@ handle_rw_error:
ide_issue_trim, ide_dma_cb, s, true); ide_issue_trim, ide_dma_cb, s, true);
break; break;
} }
if (!s->bus->dma->aiocb) {
ret = -1;
goto handle_rw_error;
}
return; return;
eot: eot:
@ -718,18 +712,13 @@ static void ide_flush_cb(void *opaque, int ret)
void ide_flush_cache(IDEState *s) void ide_flush_cache(IDEState *s)
{ {
BlockDriverAIOCB *acb;
if (s->bs == NULL) { if (s->bs == NULL) {
ide_flush_cb(s, 0); ide_flush_cb(s, 0);
return; return;
} }
bdrv_acct_start(s->bs, &s->acct, 0, BDRV_ACCT_FLUSH); bdrv_acct_start(s->bs, &s->acct, 0, BDRV_ACCT_FLUSH);
acb = bdrv_aio_flush(s->bs, ide_flush_cb, s); bdrv_aio_flush(s->bs, ide_flush_cb, s);
if (acb == NULL) {
ide_flush_cb(s, -EIO);
}
} }
static void ide_cfata_metadata_inquiry(IDEState *s) static void ide_cfata_metadata_inquiry(IDEState *s)

View File

@ -84,13 +84,6 @@ static void pmac_ide_atapi_transfer_cb(void *opaque, int ret)
m->aiocb = dma_bdrv_read(s->bs, &s->sg, m->aiocb = dma_bdrv_read(s->bs, &s->sg,
(int64_t)(s->lba << 2) + (s->io_buffer_index >> 9), (int64_t)(s->lba << 2) + (s->io_buffer_index >> 9),
pmac_ide_atapi_transfer_cb, io); 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; return;
done: done:
@ -159,10 +152,8 @@ static void pmac_ide_transfer_cb(void *opaque, int ret)
ide_issue_trim, pmac_ide_transfer_cb, s, true); ide_issue_trim, pmac_ide_transfer_cb, s, true);
break; break;
} }
if (!m->aiocb)
pmac_ide_transfer_cb(io, -1);
return; return;
done: done:
if (s->dma_cmd == IDE_DMA_READ || s->dma_cmd == IDE_DMA_WRITE) { if (s->dma_cmd == IDE_DMA_READ || s->dma_cmd == IDE_DMA_WRITE) {
bdrv_acct_done(s->bs, &s->acct); bdrv_acct_done(s->bs, &s->acct);

View File

@ -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); 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, r->req.aiocb = bdrv_aio_readv(s->qdev.conf.bs, r->sector, &r->qiov, n,
scsi_read_complete, r); 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); 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, r->req.aiocb = bdrv_aio_writev(s->qdev.conf.bs, r->sector, &r->qiov, n,
scsi_write_complete, r); scsi_write_complete, r);
if (r->req.aiocb == NULL) {
scsi_write_complete(r, -ENOMEM);
}
} else { } else {
/* Called for the first time. Ask the driver to send us more data. */ /* Called for the first time. Ask the driver to send us more data. */
scsi_write_complete(r, 0); 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); scsi_req_ref(&r->req);
bdrv_acct_start(s->qdev.conf.bs, &r->acct, 0, BDRV_ACCT_FLUSH); 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); 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; return 0;
case READ_6: case READ_6:
case READ_10: case READ_10:

View File

@ -152,10 +152,6 @@ static int execute_command(BlockDriverState *bdrv,
r->io_header.flags |= SG_FLAG_DIRECT_IO; r->io_header.flags |= SG_FLAG_DIRECT_IO;
r->req.aiocb = bdrv_aio_ioctl(bdrv, SG_IO, &r->io_header, complete, r); 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; return 0;
} }

View File

@ -288,19 +288,13 @@ static void virtio_submit_multiwrite(BlockDriverState *bs, MultiReqBuffer *mrb)
static void virtio_blk_handle_flush(VirtIOBlockReq *req, 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); bdrv_acct_start(req->dev->bs, &req->acct, 0, BDRV_ACCT_FLUSH);
/* /*
* Make sure all outstanding writes are posted to the backing device. * Make sure all outstanding writes are posted to the backing device.
*/ */
virtio_submit_multiwrite(req->dev->bs, mrb); virtio_submit_multiwrite(req->dev->bs, mrb);
bdrv_aio_flush(req->dev->bs, virtio_blk_flush_complete, req);
acb = bdrv_aio_flush(req->dev->bs, virtio_blk_flush_complete, req);
if (!acb) {
virtio_blk_flush_complete(req, -EIO);
}
} }
static void virtio_blk_handle_write(VirtIOBlockReq *req, MultiReqBuffer *mrb) 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) static void virtio_blk_handle_read(VirtIOBlockReq *req)
{ {
BlockDriverAIOCB *acb;
uint64_t sector; uint64_t sector;
sector = ldq_p(&req->out->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); virtio_blk_rw_complete(req, -EIO);
return; return;
} }
bdrv_aio_readv(req->dev->bs, sector, &req->qiov,
acb = bdrv_aio_readv(req->dev->bs, sector, &req->qiov, req->qiov.size / BDRV_SECTOR_SIZE,
req->qiov.size / BDRV_SECTOR_SIZE, virtio_blk_rw_complete, req);
virtio_blk_rw_complete, req);
if (!acb) {
virtio_blk_rw_complete(req, -EIO);
}
} }
static void virtio_blk_handle_request(VirtIOBlockReq *req, static void virtio_blk_handle_request(VirtIOBlockReq *req,

View File

@ -166,8 +166,6 @@ BlockDriverAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd,
off_t offset = sector_num * 512; off_t offset = sector_num * 512;
laiocb = qemu_aio_get(&laio_pool, bs, cb, opaque); laiocb = qemu_aio_get(&laio_pool, bs, cb, opaque);
if (!laiocb)
return NULL;
laiocb->nbytes = nb_sectors * 512; laiocb->nbytes = nb_sectors * 512;
laiocb->ctx = s; laiocb->ctx = s;
laiocb->ret = -EINPROGRESS; laiocb->ret = -EINPROGRESS;

View File

@ -611,8 +611,6 @@ BlockDriverAIOCB *paio_submit(BlockDriverState *bs, int fd,
struct qemu_paiocb *acb; struct qemu_paiocb *acb;
acb = qemu_aio_get(&raw_aio_pool, bs, cb, opaque); acb = qemu_aio_get(&raw_aio_pool, bs, cb, opaque);
if (!acb)
return NULL;
acb->aio_type = type; acb->aio_type = type;
acb->aio_fildes = fd; acb->aio_fildes = fd;
@ -638,8 +636,6 @@ BlockDriverAIOCB *paio_ioctl(BlockDriverState *bs, int fd,
struct qemu_paiocb *acb; struct qemu_paiocb *acb;
acb = qemu_aio_get(&raw_aio_pool, bs, cb, opaque); acb = qemu_aio_get(&raw_aio_pool, bs, cb, opaque);
if (!acb)
return NULL;
acb->aio_type = QEMU_AIO_IOCTL; acb->aio_type = QEMU_AIO_IOCTL;
acb->aio_fildes = fd; acb->aio_fildes = fd;
acb->aio_offset = 0; acb->aio_offset = 0;

View File

@ -24,13 +24,13 @@ ETEXI
DEF("commit", img_commit, DEF("commit", img_commit,
"commit [-f fmt] [-t cache] filename") "commit [-f fmt] [-t cache] filename")
STEXI STEXI
@item commit [-f @var{fmt}] @var{filename} @item commit [-f @var{fmt}] [-t @var{cache}] @var{filename}
ETEXI ETEXI
DEF("convert", img_convert, 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") "convert [-c] [-p] [-f fmt] [-t cache] [-O output_fmt] [-o options] [-s snapshot_name] [-S sparse_size] filename [filename2 [...]] output_filename")
STEXI 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 ETEXI
DEF("info", img_info, DEF("info", img_info,
@ -48,7 +48,7 @@ ETEXI
DEF("rebase", img_rebase, DEF("rebase", img_rebase,
"rebase [-f fmt] [-t cache] [-p] [-u] -b backing_file [-F backing_fmt] filename") "rebase [-f fmt] [-t cache] [-p] [-u] -b backing_file [-F backing_fmt] filename")
STEXI 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 ETEXI
DEF("resize", img_resize, DEF("resize", img_resize,

View File

@ -1420,6 +1420,8 @@ static int img_rebase(int argc, char **argv)
*/ */
if (!unsafe) { if (!unsafe) {
uint64_t num_sectors; uint64_t num_sectors;
uint64_t old_backing_num_sectors;
uint64_t new_backing_num_sectors;
uint64_t sector; uint64_t sector;
int n; int n;
uint8_t * buf_old; uint8_t * buf_old;
@ -1430,6 +1432,8 @@ static int img_rebase(int argc, char **argv)
buf_new = qemu_blockalign(bs, IO_BUF_SIZE); buf_new = qemu_blockalign(bs, IO_BUF_SIZE);
bdrv_get_geometry(bs, &num_sectors); 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 / local_progress = (float)100 /
(num_sectors / MIN(num_sectors, IO_BUF_SIZE / 512)); (num_sectors / MIN(num_sectors, IO_BUF_SIZE / 512));
@ -1448,16 +1452,36 @@ static int img_rebase(int argc, char **argv)
continue; continue;
} }
/* Read old and new backing file */ /*
ret = bdrv_read(bs_old_backing, sector, buf_old, n); * Read old and new backing file and take into consideration that
if (ret < 0) { * backing files may be smaller than the COW image.
error_report("error while reading from old backing file"); */
goto out; 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) { if (sector >= new_backing_num_sectors) {
error_report("error while reading from new backing file"); memset(buf_new, 0, n * BDRV_SECTOR_SIZE);
goto out; } 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 */ /* If they differ, we need to write to the COW file */

View 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 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 down to the nearest 512 bytes. You may use the common size suffixes like
@code{k} for kilobytes. @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 @end table
Parameters to snapshot subcommand: 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}, 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. 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. 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} 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} 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}. 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 Changes the backing file of an image. Only the formats @code{qcow2} and
@code{qed} support changing the backing file. @code{qed} support changing the backing file.

View File

@ -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) static int do_aio_readv(QEMUIOVector *qiov, int64_t offset, int *total)
{ {
BlockDriverAIOCB *acb;
int async_ret = NOT_DONE; int async_ret = NOT_DONE;
acb = bdrv_aio_readv(bs, offset >> 9, qiov, qiov->size >> 9, bdrv_aio_readv(bs, offset >> 9, qiov, qiov->size >> 9,
aio_rw_done, &async_ret); aio_rw_done, &async_ret);
if (!acb) {
return -EIO;
}
while (async_ret == NOT_DONE) { while (async_ret == NOT_DONE) {
qemu_aio_wait(); 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) static int do_aio_writev(QEMUIOVector *qiov, int64_t offset, int *total)
{ {
BlockDriverAIOCB *acb;
int async_ret = NOT_DONE; int async_ret = NOT_DONE;
acb = bdrv_aio_writev(bs, offset >> 9, qiov, qiov->size >> 9, bdrv_aio_writev(bs, offset >> 9, qiov, qiov->size >> 9,
aio_rw_done, &async_ret); aio_rw_done, &async_ret);
if (!acb) {
return -EIO;
}
while (async_ret == NOT_DONE) { while (async_ret == NOT_DONE) {
qemu_aio_wait(); qemu_aio_wait();
} }
@ -1151,7 +1142,6 @@ static int aio_read_f(int argc, char **argv)
{ {
int nr_iov, c; int nr_iov, c;
struct aio_ctx *ctx = calloc(1, sizeof(struct aio_ctx)); struct aio_ctx *ctx = calloc(1, sizeof(struct aio_ctx));
BlockDriverAIOCB *acb;
while ((c = getopt(argc, argv, "CP:qv")) != EOF) { while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
switch (c) { switch (c) {
@ -1206,14 +1196,8 @@ static int aio_read_f(int argc, char **argv)
} }
gettimeofday(&ctx->t1, NULL); gettimeofday(&ctx->t1, NULL);
acb = bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov, bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov,
ctx->qiov.size >> 9, aio_read_done, ctx); ctx->qiov.size >> 9, aio_read_done, ctx);
if (!acb) {
free(ctx->buf);
free(ctx);
return -EIO;
}
return 0; return 0;
} }
@ -1254,7 +1238,6 @@ static int aio_write_f(int argc, char **argv)
int nr_iov, c; int nr_iov, c;
int pattern = 0xcd; int pattern = 0xcd;
struct aio_ctx *ctx = calloc(1, sizeof(struct aio_ctx)); struct aio_ctx *ctx = calloc(1, sizeof(struct aio_ctx));
BlockDriverAIOCB *acb;
while ((c = getopt(argc, argv, "CqP:")) != EOF) { while ((c = getopt(argc, argv, "CqP:")) != EOF) {
switch (c) { switch (c) {
@ -1305,14 +1288,8 @@ static int aio_write_f(int argc, char **argv)
} }
gettimeofday(&ctx->t1, NULL); gettimeofday(&ctx->t1, NULL);
acb = bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov, bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov,
ctx->qiov.size >> 9, aio_write_done, ctx); ctx->qiov.size >> 9, aio_write_done, ctx);
if (!acb) {
free(ctx->buf);
free(ctx);
return -EIO;
}
return 0; return 0;
} }

View File

@ -2002,7 +2002,7 @@ void do_savevm(Monitor *mon, const QDict *qdict)
int ret; int ret;
QEMUFile *f; QEMUFile *f;
int saved_vm_running; int saved_vm_running;
uint32_t vm_state_size; uint64_t vm_state_size;
#ifdef _WIN32 #ifdef _WIN32
struct _timeb tb; struct _timeb tb;
struct tm *ptm; struct tm *ptm;

View File

@ -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\"" 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" 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(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_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_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" bdrv_aio_readv(void *bs, int64_t sector_num, int nb_sectors, void *opaque) "bs %p sector_num %"PRId64" nb_sectors %d opaque %p"