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

This commit is contained in:
Anthony Liguori 2011-02-16 08:47:13 -06:00
commit 79f2b6fcdb
10 changed files with 94 additions and 19 deletions

View File

@ -515,13 +515,16 @@ static int get_cluster_table(BlockDriverState *bs, uint64_t offset,
return ret;
}
} else {
/* FIXME Order */
if (l2_offset)
qcow2_free_clusters(bs, l2_offset, s->l2_size * sizeof(uint64_t));
/* First allocate a new L2 table (and do COW if needed) */
ret = l2_allocate(bs, l1_index, &l2_table);
if (ret < 0) {
return ret;
}
/* Then decrease the refcount of the old table */
if (l2_offset) {
qcow2_free_clusters(bs, l2_offset, s->l2_size * sizeof(uint64_t));
}
l2_offset = s->l1_table[l1_index] & ~QCOW_OFLAG_COPIED;
}
@ -878,11 +881,11 @@ int qcow2_decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset)
BLKDBG_EVENT(bs->file, BLKDBG_READ_COMPRESSED);
ret = bdrv_read(bs->file, coffset >> 9, s->cluster_data, nb_csectors);
if (ret < 0) {
return -1;
return ret;
}
if (decompress_buffer(s->cluster_cache, s->cluster_size,
s->cluster_data + sector_offset, csize) < 0) {
return -1;
return -EIO;
}
s->cluster_cache_offset = coffset;
}

View File

@ -28,6 +28,7 @@
#include "aes.h"
#include "block/qcow2.h"
#include "qemu-error.h"
#include "qerror.h"
/*
Differences with QCOW:
@ -59,7 +60,7 @@ static int qcow2_probe(const uint8_t *buf, int buf_size, const char *filename)
if (buf_size >= sizeof(QCowHeader) &&
be32_to_cpu(cow_header->magic) == QCOW_MAGIC &&
be32_to_cpu(cow_header->version) == QCOW_VERSION)
be32_to_cpu(cow_header->version) >= QCOW_VERSION)
return 100;
else
return 0;
@ -163,10 +164,18 @@ static int qcow2_open(BlockDriverState *bs, int flags)
be64_to_cpus(&header.snapshots_offset);
be32_to_cpus(&header.nb_snapshots);
if (header.magic != QCOW_MAGIC || header.version != QCOW_VERSION) {
if (header.magic != QCOW_MAGIC) {
ret = -EINVAL;
goto fail;
}
if (header.version != QCOW_VERSION) {
char version[64];
snprintf(version, sizeof(version), "QCOW version %d", header.version);
qerror_report(QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
bs->device_name, "qcow2", version);
ret = -ENOTSUP;
goto fail;
}
if (header.cluster_bits < MIN_CLUSTER_BITS ||
header.cluster_bits > MAX_CLUSTER_BITS) {
ret = -EINVAL;
@ -355,7 +364,7 @@ int qcow2_backing_read1(BlockDriverState *bs, QEMUIOVector *qiov,
else
n1 = bs->total_sectors - sector_num;
qemu_iovec_memset(qiov, 0, 512 * (nb_sectors - n1));
qemu_iovec_memset_skip(qiov, 0, 512 * (nb_sectors - n1), 512 * n1);
return n1;
}
@ -478,10 +487,11 @@ static void qcow2_aio_read_cb(void *opaque, int ret)
if (n1 > 0) {
BLKDBG_EVENT(bs->file, BLKDBG_READ_BACKING_AIO);
acb->hd_aiocb = bdrv_aio_readv(bs->backing_hd, acb->sector_num,
&acb->hd_qiov, acb->cur_nr_sectors,
qcow2_aio_read_cb, acb);
if (acb->hd_aiocb == NULL)
&acb->hd_qiov, n1, qcow2_aio_read_cb, acb);
if (acb->hd_aiocb == NULL) {
ret = -EIO;
goto done;
}
} else {
ret = qcow2_schedule_bh(qcow2_aio_read_bh, acb);
if (ret < 0)
@ -496,8 +506,10 @@ static void qcow2_aio_read_cb(void *opaque, int ret)
}
} else if (acb->cluster_offset & QCOW_OFLAG_COMPRESSED) {
/* add AIO support for compressed blocks ? */
if (qcow2_decompress_cluster(bs, acb->cluster_offset) < 0)
ret = qcow2_decompress_cluster(bs, acb->cluster_offset);
if (ret < 0) {
goto done;
}
qemu_iovec_from_buffer(&acb->hd_qiov,
s->cluster_cache + index_in_cluster * 512,

View File

@ -14,6 +14,7 @@
#include "trace.h"
#include "qed.h"
#include "qerror.h"
static void qed_aio_cancel(BlockDriverAIOCB *blockacb)
{
@ -311,7 +312,13 @@ static int bdrv_qed_open(BlockDriverState *bs, int flags)
return -EINVAL;
}
if (s->header.features & ~QED_FEATURE_MASK) {
return -ENOTSUP; /* image uses unsupported feature bits */
/* image uses unsupported feature bits */
char buf[64];
snprintf(buf, sizeof(buf), "%" PRIx64,
s->header.features & ~QED_FEATURE_MASK);
qerror_report(QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
bs->device_name, "QED", buf);
return -ENOTSUP;
}
if (!qed_is_cluster_size_valid(s->header.cluster_size)) {
return -EINVAL;

View File

@ -182,6 +182,7 @@ static void drive_uninit(DriveInfo *dinfo)
{
qemu_opts_del(dinfo->opts);
bdrv_delete(dinfo->bdrv);
qemu_free(dinfo->id);
QTAILQ_REMOVE(&drives, dinfo, next);
qemu_free(dinfo);
}
@ -525,7 +526,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
} else if (ro == 1) {
if (type != IF_SCSI && type != IF_VIRTIO && type != IF_FLOPPY && type != IF_NONE) {
error_report("readonly not supported by this bus type");
return NULL;
goto err;
}
}
@ -535,12 +536,19 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
if (ret < 0) {
error_report("could not open disk image %s: %s",
file, strerror(-ret));
return NULL;
goto err;
}
if (bdrv_key_required(dinfo->bdrv))
autostart = 0;
return dinfo;
err:
bdrv_delete(dinfo->bdrv);
qemu_free(dinfo->id);
QTAILQ_REMOVE(&drives, dinfo, next);
qemu_free(dinfo);
return NULL;
}
void do_commit(Monitor *mon, const QDict *qdict)

View File

@ -267,6 +267,37 @@ void qemu_iovec_memset(QEMUIOVector *qiov, int c, size_t count)
}
}
void qemu_iovec_memset_skip(QEMUIOVector *qiov, int c, size_t count,
size_t skip)
{
int i;
size_t done;
void *iov_base;
uint64_t iov_len;
done = 0;
for (i = 0; (i < qiov->niov) && (done != count); i++) {
if (skip >= qiov->iov[i].iov_len) {
/* Skip the whole iov */
skip -= qiov->iov[i].iov_len;
continue;
} else {
/* Skip only part (or nothing) of the iov */
iov_base = (uint8_t*) qiov->iov[i].iov_base + skip;
iov_len = qiov->iov[i].iov_len - skip;
skip = 0;
}
if (done + iov_len > count) {
memset(iov_base, c, count - done);
break;
} else {
memset(iov_base, c, iov_len);
}
done += iov_len;
}
}
#ifndef _WIN32
/* Sets a specific flag */
int fcntl_setfl(int fd, int flag)

View File

@ -822,7 +822,7 @@ ETEXI
{
.name = "snapshot_blkdev",
.args_type = "device:s,snapshot_file:s?,format:s?",
.args_type = "device:B,snapshot_file:s?,format:s?",
.params = "device [new-image-file] [format]",
.help = "initiates a live snapshot\n\t\t\t"
"of device. If a new image file is specified, the\n\t\t\t"

View File

@ -323,6 +323,8 @@ void qemu_iovec_reset(QEMUIOVector *qiov);
void qemu_iovec_to_buffer(QEMUIOVector *qiov, void *buf);
void qemu_iovec_from_buffer(QEMUIOVector *qiov, const void *buf, size_t count);
void qemu_iovec_memset(QEMUIOVector *qiov, int c, size_t count);
void qemu_iovec_memset_skip(QEMUIOVector *qiov, int c, size_t count,
size_t skip);
struct Monitor;
typedef struct Monitor Monitor;

View File

@ -213,8 +213,9 @@ static BlockDriverState *bdrv_new_open(const char *filename,
BlockDriverState *bs;
BlockDriver *drv;
char password[256];
int ret;
bs = bdrv_new("");
bs = bdrv_new("image");
if (fmt) {
drv = bdrv_find_format(fmt);
@ -225,10 +226,13 @@ static BlockDriverState *bdrv_new_open(const char *filename,
} else {
drv = NULL;
}
if (bdrv_open(bs, filename, flags, drv) < 0) {
error_report("Could not open '%s'", filename);
ret = bdrv_open(bs, filename, flags, drv);
if (ret < 0) {
error_report("Could not open '%s': %s", filename, strerror(-ret));
goto fail;
}
if (bdrv_is_encrypted(bs)) {
printf("Disk image '%s' is encrypted.\n", filename);
if (read_password(password, sizeof(password)) < 0) {

View File

@ -200,6 +200,11 @@ static const QErrorStringTable qerror_table[] = {
.error_fmt = QERR_UNDEFINED_ERROR,
.desc = "An undefined error has ocurred",
},
{
.error_fmt = QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
.desc = "'%(device)' uses a %(format) feature which is not "
"supported by this qemu version: %(feature)",
},
{
.error_fmt = QERR_VNC_SERVER_FAILED,
.desc = "Could not start VNC server on %(target)",

View File

@ -165,6 +165,9 @@ QError *qobject_to_qerror(const QObject *obj);
#define QERR_UNDEFINED_ERROR \
"{ 'class': 'UndefinedError', 'data': {} }"
#define QERR_UNKNOWN_BLOCK_FORMAT_FEATURE \
"{ 'class': 'UnknownBlockFormatFeature', 'data': { 'device': %s, 'format': %s, 'feature': %s } }"
#define QERR_VNC_SERVER_FAILED \
"{ 'class': 'VNCServerFailed', 'data': { 'target': %s } }"