Block patches for 2.3-rc0
-----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABAgAGBQJVBwDLAAoJEH8JsnLIjy/WPRwP/A8mF/yaGnSIs1zKYzikWiPg CPoIcWZnU27Uc2fa0jW7vFh7mnrQ1+fgzQx4MJ/zxuDGI63Nr7QnkDSQqNDsKlFb bQjH5NNFYlqLqsTNqMEc7bV1NnUUqC3932oqgzcAcVeh1DphNU//Mu87bmTE+NVi ZHtnnasEN8eBWPsiLyphCqirQWO2mPRHAwYjEE0SwHEX+HEoV0Bx8GUJMmZ8J+oA 4FXl1R3iZiqFGE4ExNFa+XKy/kXChRkLT7GWlCgB8ngRQ42OdLIz3vV/KMwnzndA luz0yywCYBkfDohAYZ0wAWSDsGYgSAG33/XOatIatQfdLE/MMm9Ab9EN4WO9oeVs XnYJAZzd5i7hCL4fH76jPHo4seMq6F/4Ou9bCmevMzjZc9o6I6qaUyIFgSY7zZqf j08soL3KqlnxwvZNh+kAjrRhoJNzjTOvsz4e5h9Y8b9McG0ObRR1uxKCFIMyHSJB hJs0bgZiFye4pn9FDFOC6dU4ShVOgL2AeuREdVUJpIUq5kBIjk6djCGvIRJky1Rx WujcLml5vzqcfYIqzRFmh1wZ6JEnpqU70r6g7O6yUOEJA3qJC+vkue+bxiXW4KAX uFDz2zCDwsNmbMOwfClDs1D9DPoyikElVOwovq92erDTIHTcOqThcbUS+SmIV/ps bO68612w4UJZKyXbndDT =XCJ5 -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging Block patches for 2.3-rc0 # gpg: Signature made Mon Mar 16 16:11:55 2015 GMT using RSA key ID C88F2FD6 # gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>" * remotes/kevin/tags/for-upstream: block/vpc: remove disabled code from get_sector_offset block/vpc: rename footer->size -> footer->current_size block/vpc: make calculate_geometry spec conform vpc: Ignore geometry for large images block/vpc: optimize vpc_co_get_block_status block: Drop bdrv_find blockdev: Convert bdrv_find to blk_by_name migration: Convert bdrv_find to blk_by_name monitor: Convert bdrv_find to blk_by_name iotests: Test non-self-referential qcow2 refblocks iotests: Add tests for refcount table growth qcow2: Respect new_block in alloc_refcount_block() qemu-img: Avoid qerror_report_err() outside QMP handlers, again block: Fix block-set-write-threshold not to use funky error class block: Deprecate QCOW/QCOW2 encryption qemu-img: Fix convert, amend error messages for unknown options iotests: Update 051's reference output Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
3521f76706
16
block.c
16
block.c
@ -1065,6 +1065,13 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
|
|||||||
goto free_and_fail;
|
goto free_and_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bs->encrypted) {
|
||||||
|
error_report("Encrypted images are deprecated");
|
||||||
|
error_printf("Support for them will be removed in a future release.\n"
|
||||||
|
"You can use 'qemu-img convert' to convert your image"
|
||||||
|
" to an unencrypted one.\n");
|
||||||
|
}
|
||||||
|
|
||||||
ret = refresh_total_sectors(bs, bs->total_sectors);
|
ret = refresh_total_sectors(bs, bs->total_sectors);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
error_setg_errno(errp, -ret, "Could not refresh total sector count");
|
error_setg_errno(errp, -ret, "Could not refresh total sector count");
|
||||||
@ -3814,15 +3821,6 @@ void bdrv_iterate_format(void (*it)(void *opaque, const char *name),
|
|||||||
g_free(formats);
|
g_free(formats);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function is to find block backend bs */
|
|
||||||
/* TODO convert callers to blk_by_name(), then remove */
|
|
||||||
BlockDriverState *bdrv_find(const char *name)
|
|
||||||
{
|
|
||||||
BlockBackend *blk = blk_by_name(name);
|
|
||||||
|
|
||||||
return blk ? blk_bs(blk) : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This function is to find a node in the bs graph */
|
/* This function is to find a node in the bs graph */
|
||||||
BlockDriverState *bdrv_find_node(const char *node_name)
|
BlockDriverState *bdrv_find_node(const char *node_name)
|
||||||
{
|
{
|
||||||
|
@ -466,8 +466,20 @@ static int alloc_refcount_block(BlockDriverState *bs,
|
|||||||
*/
|
*/
|
||||||
BLKDBG_EVENT(bs->file, BLKDBG_REFTABLE_GROW);
|
BLKDBG_EVENT(bs->file, BLKDBG_REFTABLE_GROW);
|
||||||
|
|
||||||
/* Calculate the number of refcount blocks needed so far */
|
/* Calculate the number of refcount blocks needed so far; this will be the
|
||||||
uint64_t blocks_used = DIV_ROUND_UP(cluster_index, s->refcount_block_size);
|
* basis for calculating the index of the first cluster used for the
|
||||||
|
* self-describing refcount structures which we are about to create.
|
||||||
|
*
|
||||||
|
* Because we reached this point, there cannot be any refcount entries for
|
||||||
|
* cluster_index or higher indices yet. However, because new_block has been
|
||||||
|
* allocated to describe that cluster (and it will assume this role later
|
||||||
|
* on), we cannot use that index; also, new_block may actually have a higher
|
||||||
|
* cluster index than cluster_index, so it needs to be taken into account
|
||||||
|
* here (and 1 needs to be added to its value because that cluster is used).
|
||||||
|
*/
|
||||||
|
uint64_t blocks_used = DIV_ROUND_UP(MAX(cluster_index + 1,
|
||||||
|
(new_block >> s->cluster_bits) + 1),
|
||||||
|
s->refcount_block_size);
|
||||||
|
|
||||||
if (blocks_used > QCOW_MAX_REFTABLE_SIZE / sizeof(uint64_t)) {
|
if (blocks_used > QCOW_MAX_REFTABLE_SIZE / sizeof(uint64_t)) {
|
||||||
return -EFBIG;
|
return -EFBIG;
|
||||||
|
106
block/vpc.c
106
block/vpc.c
@ -46,6 +46,7 @@ enum vhd_type {
|
|||||||
#define VHD_TIMESTAMP_BASE 946684800
|
#define VHD_TIMESTAMP_BASE 946684800
|
||||||
|
|
||||||
#define VHD_MAX_SECTORS (65535LL * 255 * 255)
|
#define VHD_MAX_SECTORS (65535LL * 255 * 255)
|
||||||
|
#define VHD_MAX_GEOMETRY (65535LL * 16 * 255)
|
||||||
|
|
||||||
// always big-endian
|
// always big-endian
|
||||||
typedef struct vhd_footer {
|
typedef struct vhd_footer {
|
||||||
@ -65,7 +66,7 @@ typedef struct vhd_footer {
|
|||||||
char creator_os[4]; // "Wi2k"
|
char creator_os[4]; // "Wi2k"
|
||||||
|
|
||||||
uint64_t orig_size;
|
uint64_t orig_size;
|
||||||
uint64_t size;
|
uint64_t current_size;
|
||||||
|
|
||||||
uint16_t cyls;
|
uint16_t cyls;
|
||||||
uint8_t heads;
|
uint8_t heads;
|
||||||
@ -215,13 +216,12 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
bs->total_sectors = (int64_t)
|
bs->total_sectors = (int64_t)
|
||||||
be16_to_cpu(footer->cyls) * footer->heads * footer->secs_per_cyl;
|
be16_to_cpu(footer->cyls) * footer->heads * footer->secs_per_cyl;
|
||||||
|
|
||||||
/* images created with disk2vhd report a far higher virtual size
|
/* Images that have exactly the maximum geometry are probably bigger and
|
||||||
* than expected with the cyls * heads * sectors_per_cyl formula.
|
* would be truncated if we adhered to the geometry for them. Rely on
|
||||||
* use the footer->size instead if the image was created with
|
* footer->current_size for them. */
|
||||||
* disk2vhd.
|
if (bs->total_sectors == VHD_MAX_GEOMETRY) {
|
||||||
*/
|
bs->total_sectors = be64_to_cpu(footer->current_size) /
|
||||||
if (!strncmp(footer->creator_app, "d2v", 4)) {
|
BDRV_SECTOR_SIZE;
|
||||||
bs->total_sectors = be64_to_cpu(footer->size) / BDRV_SECTOR_SIZE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allow a maximum disk size of approximately 2 TB */
|
/* Allow a maximum disk size of approximately 2 TB */
|
||||||
@ -376,38 +376,6 @@ static inline int64_t get_sector_offset(BlockDriverState *bs,
|
|||||||
bdrv_pwrite_sync(bs->file, bitmap_offset, bitmap, s->bitmap_size);
|
bdrv_pwrite_sync(bs->file, bitmap_offset, bitmap, s->bitmap_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
// printf("sector: %" PRIx64 ", index: %x, offset: %x, bioff: %" PRIx64 ", bloff: %" PRIx64 "\n",
|
|
||||||
// sector_num, pagetable_index, pageentry_index,
|
|
||||||
// bitmap_offset, block_offset);
|
|
||||||
|
|
||||||
// disabled by reason
|
|
||||||
#if 0
|
|
||||||
#ifdef CACHE
|
|
||||||
if (bitmap_offset != s->last_bitmap)
|
|
||||||
{
|
|
||||||
lseek(s->fd, bitmap_offset, SEEK_SET);
|
|
||||||
|
|
||||||
s->last_bitmap = bitmap_offset;
|
|
||||||
|
|
||||||
// Scary! Bitmap is stored as big endian 32bit entries,
|
|
||||||
// while we used to look it up byte by byte
|
|
||||||
read(s->fd, s->pageentry_u8, 512);
|
|
||||||
for (i = 0; i < 128; i++)
|
|
||||||
be32_to_cpus(&s->pageentry_u32[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((s->pageentry_u8[pageentry_index / 8] >> (pageentry_index % 8)) & 1)
|
|
||||||
return -1;
|
|
||||||
#else
|
|
||||||
lseek(s->fd, bitmap_offset + (pageentry_index / 8), SEEK_SET);
|
|
||||||
|
|
||||||
read(s->fd, &bitmap_entry, 1);
|
|
||||||
|
|
||||||
if ((bitmap_entry >> (pageentry_index % 8)) & 1)
|
|
||||||
return -1; // not allocated
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return block_offset;
|
return block_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -602,7 +570,7 @@ static int64_t coroutine_fn vpc_co_get_block_status(BlockDriverState *bs,
|
|||||||
{
|
{
|
||||||
BDRVVPCState *s = bs->opaque;
|
BDRVVPCState *s = bs->opaque;
|
||||||
VHDFooter *footer = (VHDFooter*) s->footer_buf;
|
VHDFooter *footer = (VHDFooter*) s->footer_buf;
|
||||||
int64_t start, offset, next;
|
int64_t start, offset;
|
||||||
bool allocated;
|
bool allocated;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
@ -626,20 +594,18 @@ static int64_t coroutine_fn vpc_co_get_block_status(BlockDriverState *bs,
|
|||||||
*pnum += n;
|
*pnum += n;
|
||||||
sector_num += n;
|
sector_num += n;
|
||||||
nb_sectors -= n;
|
nb_sectors -= n;
|
||||||
next = start + (*pnum * BDRV_SECTOR_SIZE);
|
/* *pnum can't be greater than one block for allocated
|
||||||
|
* sectors since there is always a bitmap in between. */
|
||||||
|
if (allocated) {
|
||||||
|
return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | start;
|
||||||
|
}
|
||||||
if (nb_sectors == 0) {
|
if (nb_sectors == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
offset = get_sector_offset(bs, sector_num, 0);
|
offset = get_sector_offset(bs, sector_num, 0);
|
||||||
} while ((allocated && offset == next) || (!allocated && offset == -1));
|
} while (offset == -1);
|
||||||
|
|
||||||
if (allocated) {
|
return 0;
|
||||||
return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | start;
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -659,26 +625,20 @@ static int calculate_geometry(int64_t total_sectors, uint16_t* cyls,
|
|||||||
{
|
{
|
||||||
uint32_t cyls_times_heads;
|
uint32_t cyls_times_heads;
|
||||||
|
|
||||||
/* Allow a maximum disk size of approximately 2 TB */
|
total_sectors = MIN(total_sectors, VHD_MAX_GEOMETRY);
|
||||||
if (total_sectors > 65535LL * 255 * 255) {
|
|
||||||
return -EFBIG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (total_sectors > 65535 * 16 * 63) {
|
if (total_sectors >= 65535LL * 16 * 63) {
|
||||||
*secs_per_cyl = 255;
|
*secs_per_cyl = 255;
|
||||||
if (total_sectors > 65535 * 16 * 255) {
|
*heads = 16;
|
||||||
*heads = 255;
|
|
||||||
} else {
|
|
||||||
*heads = 16;
|
|
||||||
}
|
|
||||||
cyls_times_heads = total_sectors / *secs_per_cyl;
|
cyls_times_heads = total_sectors / *secs_per_cyl;
|
||||||
} else {
|
} else {
|
||||||
*secs_per_cyl = 17;
|
*secs_per_cyl = 17;
|
||||||
cyls_times_heads = total_sectors / *secs_per_cyl;
|
cyls_times_heads = total_sectors / *secs_per_cyl;
|
||||||
*heads = (cyls_times_heads + 1023) / 1024;
|
*heads = (cyls_times_heads + 1023) / 1024;
|
||||||
|
|
||||||
if (*heads < 4)
|
if (*heads < 4) {
|
||||||
*heads = 4;
|
*heads = 4;
|
||||||
|
}
|
||||||
|
|
||||||
if (cyls_times_heads >= (*heads * 1024) || *heads > 16) {
|
if (cyls_times_heads >= (*heads * 1024) || *heads > 16) {
|
||||||
*secs_per_cyl = 31;
|
*secs_per_cyl = 31;
|
||||||
@ -834,20 +794,28 @@ static int vpc_create(const char *filename, QemuOpts *opts, Error **errp)
|
|||||||
* Calculate matching total_size and geometry. Increase the number of
|
* Calculate matching total_size and geometry. Increase the number of
|
||||||
* sectors requested until we get enough (or fail). This ensures that
|
* sectors requested until we get enough (or fail). This ensures that
|
||||||
* qemu-img convert doesn't truncate images, but rather rounds up.
|
* qemu-img convert doesn't truncate images, but rather rounds up.
|
||||||
|
*
|
||||||
|
* If the image size can't be represented by a spec conform CHS geometry,
|
||||||
|
* we set the geometry to 65535 x 16 x 255 (CxHxS) sectors and use
|
||||||
|
* the image size from the VHD footer to calculate total_sectors.
|
||||||
*/
|
*/
|
||||||
total_sectors = total_size / BDRV_SECTOR_SIZE;
|
total_sectors = MIN(VHD_MAX_GEOMETRY, total_size / BDRV_SECTOR_SIZE);
|
||||||
for (i = 0; total_sectors > (int64_t)cyls * heads * secs_per_cyl; i++) {
|
for (i = 0; total_sectors > (int64_t)cyls * heads * secs_per_cyl; i++) {
|
||||||
if (calculate_geometry(total_sectors + i, &cyls, &heads,
|
calculate_geometry(total_sectors + i, &cyls, &heads, &secs_per_cyl);
|
||||||
&secs_per_cyl))
|
}
|
||||||
{
|
|
||||||
|
if ((int64_t)cyls * heads * secs_per_cyl == VHD_MAX_GEOMETRY) {
|
||||||
|
total_sectors = total_size / BDRV_SECTOR_SIZE;
|
||||||
|
/* Allow a maximum disk size of approximately 2 TB */
|
||||||
|
if (total_sectors > VHD_MAX_SECTORS) {
|
||||||
ret = -EFBIG;
|
ret = -EFBIG;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
total_sectors = (int64_t)cyls * heads * secs_per_cyl;
|
||||||
|
total_size = total_sectors * BDRV_SECTOR_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
total_sectors = (int64_t) cyls * heads * secs_per_cyl;
|
|
||||||
total_size = total_sectors * BDRV_SECTOR_SIZE;
|
|
||||||
|
|
||||||
/* Prepare the Hard Disk Footer */
|
/* Prepare the Hard Disk Footer */
|
||||||
memset(buf, 0, 1024);
|
memset(buf, 0, 1024);
|
||||||
|
|
||||||
@ -869,7 +837,7 @@ static int vpc_create(const char *filename, QemuOpts *opts, Error **errp)
|
|||||||
footer->major = cpu_to_be16(0x0005);
|
footer->major = cpu_to_be16(0x0005);
|
||||||
footer->minor = cpu_to_be16(0x0003);
|
footer->minor = cpu_to_be16(0x0003);
|
||||||
footer->orig_size = cpu_to_be64(total_size);
|
footer->orig_size = cpu_to_be64(total_size);
|
||||||
footer->size = cpu_to_be64(total_size);
|
footer->current_size = cpu_to_be64(total_size);
|
||||||
footer->cyls = cpu_to_be16(cyls);
|
footer->cyls = cpu_to_be16(cyls);
|
||||||
footer->heads = heads;
|
footer->heads = heads;
|
||||||
footer->secs_per_cyl = secs_per_cyl;
|
footer->secs_per_cyl = secs_per_cyl;
|
||||||
|
@ -112,7 +112,7 @@ void qmp_block_set_write_threshold(const char *node_name,
|
|||||||
|
|
||||||
bs = bdrv_find_node(node_name);
|
bs = bdrv_find_node(node_name);
|
||||||
if (!bs) {
|
if (!bs) {
|
||||||
error_set(errp, QERR_DEVICE_NOT_FOUND, node_name);
|
error_setg(errp, "Device '%s' not found", node_name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
92
blockdev.c
92
blockdev.c
@ -1016,18 +1016,18 @@ fail:
|
|||||||
void hmp_commit(Monitor *mon, const QDict *qdict)
|
void hmp_commit(Monitor *mon, const QDict *qdict)
|
||||||
{
|
{
|
||||||
const char *device = qdict_get_str(qdict, "device");
|
const char *device = qdict_get_str(qdict, "device");
|
||||||
BlockDriverState *bs;
|
BlockBackend *blk;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!strcmp(device, "all")) {
|
if (!strcmp(device, "all")) {
|
||||||
ret = bdrv_commit_all();
|
ret = bdrv_commit_all();
|
||||||
} else {
|
} else {
|
||||||
bs = bdrv_find(device);
|
blk = blk_by_name(device);
|
||||||
if (!bs) {
|
if (!blk) {
|
||||||
monitor_printf(mon, "Device '%s' not found\n", device);
|
monitor_printf(mon, "Device '%s' not found\n", device);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ret = bdrv_commit(bs);
|
ret = bdrv_commit(blk_bs(blk));
|
||||||
}
|
}
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
monitor_printf(mon, "'commit' error for '%s': %s\n", device,
|
monitor_printf(mon, "'commit' error for '%s': %s\n", device,
|
||||||
@ -1092,17 +1092,20 @@ SnapshotInfo *qmp_blockdev_snapshot_delete_internal_sync(const char *device,
|
|||||||
const char *name,
|
const char *name,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
BlockDriverState *bs = bdrv_find(device);
|
BlockDriverState *bs;
|
||||||
|
BlockBackend *blk;
|
||||||
AioContext *aio_context;
|
AioContext *aio_context;
|
||||||
QEMUSnapshotInfo sn;
|
QEMUSnapshotInfo sn;
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
SnapshotInfo *info = NULL;
|
SnapshotInfo *info = NULL;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!bs) {
|
blk = blk_by_name(device);
|
||||||
|
if (!blk) {
|
||||||
error_set(errp, QERR_DEVICE_NOT_FOUND, device);
|
error_set(errp, QERR_DEVICE_NOT_FOUND, device);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
bs = blk_bs(blk);
|
||||||
|
|
||||||
if (!has_id) {
|
if (!has_id) {
|
||||||
id = NULL;
|
id = NULL;
|
||||||
@ -1205,6 +1208,7 @@ static void internal_snapshot_prepare(BlkTransactionState *common,
|
|||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
const char *device;
|
const char *device;
|
||||||
const char *name;
|
const char *name;
|
||||||
|
BlockBackend *blk;
|
||||||
BlockDriverState *bs;
|
BlockDriverState *bs;
|
||||||
QEMUSnapshotInfo old_sn, *sn;
|
QEMUSnapshotInfo old_sn, *sn;
|
||||||
bool ret;
|
bool ret;
|
||||||
@ -1223,11 +1227,12 @@ static void internal_snapshot_prepare(BlkTransactionState *common,
|
|||||||
name = internal->name;
|
name = internal->name;
|
||||||
|
|
||||||
/* 2. check for validation */
|
/* 2. check for validation */
|
||||||
bs = bdrv_find(device);
|
blk = blk_by_name(device);
|
||||||
if (!bs) {
|
if (!blk) {
|
||||||
error_set(errp, QERR_DEVICE_NOT_FOUND, device);
|
error_set(errp, QERR_DEVICE_NOT_FOUND, device);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
bs = blk_bs(blk);
|
||||||
|
|
||||||
/* AioContext is released in .clean() */
|
/* AioContext is released in .clean() */
|
||||||
state->aio_context = bdrv_get_aio_context(bs);
|
state->aio_context = bdrv_get_aio_context(bs);
|
||||||
@ -1494,17 +1499,19 @@ static void drive_backup_prepare(BlkTransactionState *common, Error **errp)
|
|||||||
{
|
{
|
||||||
DriveBackupState *state = DO_UPCAST(DriveBackupState, common, common);
|
DriveBackupState *state = DO_UPCAST(DriveBackupState, common, common);
|
||||||
BlockDriverState *bs;
|
BlockDriverState *bs;
|
||||||
|
BlockBackend *blk;
|
||||||
DriveBackup *backup;
|
DriveBackup *backup;
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
|
|
||||||
assert(common->action->kind == TRANSACTION_ACTION_KIND_DRIVE_BACKUP);
|
assert(common->action->kind == TRANSACTION_ACTION_KIND_DRIVE_BACKUP);
|
||||||
backup = common->action->drive_backup;
|
backup = common->action->drive_backup;
|
||||||
|
|
||||||
bs = bdrv_find(backup->device);
|
blk = blk_by_name(backup->device);
|
||||||
if (!bs) {
|
if (!blk) {
|
||||||
error_set(errp, QERR_DEVICE_NOT_FOUND, backup->device);
|
error_set(errp, QERR_DEVICE_NOT_FOUND, backup->device);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
bs = blk_bs(blk);
|
||||||
|
|
||||||
/* AioContext is released in .clean() */
|
/* AioContext is released in .clean() */
|
||||||
state->aio_context = bdrv_get_aio_context(bs);
|
state->aio_context = bdrv_get_aio_context(bs);
|
||||||
@ -1559,22 +1566,25 @@ static void blockdev_backup_prepare(BlkTransactionState *common, Error **errp)
|
|||||||
BlockdevBackupState *state = DO_UPCAST(BlockdevBackupState, common, common);
|
BlockdevBackupState *state = DO_UPCAST(BlockdevBackupState, common, common);
|
||||||
BlockdevBackup *backup;
|
BlockdevBackup *backup;
|
||||||
BlockDriverState *bs, *target;
|
BlockDriverState *bs, *target;
|
||||||
|
BlockBackend *blk;
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
|
|
||||||
assert(common->action->kind == TRANSACTION_ACTION_KIND_BLOCKDEV_BACKUP);
|
assert(common->action->kind == TRANSACTION_ACTION_KIND_BLOCKDEV_BACKUP);
|
||||||
backup = common->action->blockdev_backup;
|
backup = common->action->blockdev_backup;
|
||||||
|
|
||||||
bs = bdrv_find(backup->device);
|
blk = blk_by_name(backup->device);
|
||||||
if (!bs) {
|
if (!blk) {
|
||||||
error_set(errp, QERR_DEVICE_NOT_FOUND, backup->device);
|
error_set(errp, QERR_DEVICE_NOT_FOUND, backup->device);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
bs = blk_bs(blk);
|
||||||
|
|
||||||
target = bdrv_find(backup->target);
|
blk = blk_by_name(backup->target);
|
||||||
if (!target) {
|
if (!blk) {
|
||||||
error_set(errp, QERR_DEVICE_NOT_FOUND, backup->target);
|
error_set(errp, QERR_DEVICE_NOT_FOUND, backup->target);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
target = blk_bs(blk);
|
||||||
|
|
||||||
/* AioContext is released in .clean() */
|
/* AioContext is released in .clean() */
|
||||||
state->aio_context = bdrv_get_aio_context(bs);
|
state->aio_context = bdrv_get_aio_context(bs);
|
||||||
@ -1881,13 +1891,15 @@ void qmp_block_set_io_throttle(const char *device, int64_t bps, int64_t bps_rd,
|
|||||||
{
|
{
|
||||||
ThrottleConfig cfg;
|
ThrottleConfig cfg;
|
||||||
BlockDriverState *bs;
|
BlockDriverState *bs;
|
||||||
|
BlockBackend *blk;
|
||||||
AioContext *aio_context;
|
AioContext *aio_context;
|
||||||
|
|
||||||
bs = bdrv_find(device);
|
blk = blk_by_name(device);
|
||||||
if (!bs) {
|
if (!blk) {
|
||||||
error_set(errp, QERR_DEVICE_NOT_FOUND, device);
|
error_set(errp, QERR_DEVICE_NOT_FOUND, device);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
bs = blk_bs(blk);
|
||||||
|
|
||||||
memset(&cfg, 0, sizeof(cfg));
|
memset(&cfg, 0, sizeof(cfg));
|
||||||
cfg.buckets[THROTTLE_BPS_TOTAL].avg = bps;
|
cfg.buckets[THROTTLE_BPS_TOTAL].avg = bps;
|
||||||
@ -2091,6 +2103,7 @@ void qmp_block_stream(const char *device,
|
|||||||
bool has_on_error, BlockdevOnError on_error,
|
bool has_on_error, BlockdevOnError on_error,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
|
BlockBackend *blk;
|
||||||
BlockDriverState *bs;
|
BlockDriverState *bs;
|
||||||
BlockDriverState *base_bs = NULL;
|
BlockDriverState *base_bs = NULL;
|
||||||
AioContext *aio_context;
|
AioContext *aio_context;
|
||||||
@ -2101,11 +2114,12 @@ void qmp_block_stream(const char *device,
|
|||||||
on_error = BLOCKDEV_ON_ERROR_REPORT;
|
on_error = BLOCKDEV_ON_ERROR_REPORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
bs = bdrv_find(device);
|
blk = blk_by_name(device);
|
||||||
if (!bs) {
|
if (!blk) {
|
||||||
error_set(errp, QERR_DEVICE_NOT_FOUND, device);
|
error_set(errp, QERR_DEVICE_NOT_FOUND, device);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
bs = blk_bs(blk);
|
||||||
|
|
||||||
aio_context = bdrv_get_aio_context(bs);
|
aio_context = bdrv_get_aio_context(bs);
|
||||||
aio_context_acquire(aio_context);
|
aio_context_acquire(aio_context);
|
||||||
@ -2155,6 +2169,7 @@ void qmp_block_commit(const char *device,
|
|||||||
bool has_speed, int64_t speed,
|
bool has_speed, int64_t speed,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
|
BlockBackend *blk;
|
||||||
BlockDriverState *bs;
|
BlockDriverState *bs;
|
||||||
BlockDriverState *base_bs, *top_bs;
|
BlockDriverState *base_bs, *top_bs;
|
||||||
AioContext *aio_context;
|
AioContext *aio_context;
|
||||||
@ -2173,11 +2188,12 @@ void qmp_block_commit(const char *device,
|
|||||||
* live commit feature versions; for this to work, we must make sure to
|
* live commit feature versions; for this to work, we must make sure to
|
||||||
* perform the device lookup before any generic errors that may occur in a
|
* perform the device lookup before any generic errors that may occur in a
|
||||||
* scenario in which all optional arguments are omitted. */
|
* scenario in which all optional arguments are omitted. */
|
||||||
bs = bdrv_find(device);
|
blk = blk_by_name(device);
|
||||||
if (!bs) {
|
if (!blk) {
|
||||||
error_set(errp, QERR_DEVICE_NOT_FOUND, device);
|
error_set(errp, QERR_DEVICE_NOT_FOUND, device);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
bs = blk_bs(blk);
|
||||||
|
|
||||||
aio_context = bdrv_get_aio_context(bs);
|
aio_context = bdrv_get_aio_context(bs);
|
||||||
aio_context_acquire(aio_context);
|
aio_context_acquire(aio_context);
|
||||||
@ -2258,6 +2274,7 @@ void qmp_drive_backup(const char *device, const char *target,
|
|||||||
bool has_on_target_error, BlockdevOnError on_target_error,
|
bool has_on_target_error, BlockdevOnError on_target_error,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
|
BlockBackend *blk;
|
||||||
BlockDriverState *bs;
|
BlockDriverState *bs;
|
||||||
BlockDriverState *target_bs;
|
BlockDriverState *target_bs;
|
||||||
BlockDriverState *source = NULL;
|
BlockDriverState *source = NULL;
|
||||||
@ -2281,11 +2298,12 @@ void qmp_drive_backup(const char *device, const char *target,
|
|||||||
mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
|
mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
|
||||||
}
|
}
|
||||||
|
|
||||||
bs = bdrv_find(device);
|
blk = blk_by_name(device);
|
||||||
if (!bs) {
|
if (!blk) {
|
||||||
error_set(errp, QERR_DEVICE_NOT_FOUND, device);
|
error_set(errp, QERR_DEVICE_NOT_FOUND, device);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
bs = blk_bs(blk);
|
||||||
|
|
||||||
aio_context = bdrv_get_aio_context(bs);
|
aio_context = bdrv_get_aio_context(bs);
|
||||||
aio_context_acquire(aio_context);
|
aio_context_acquire(aio_context);
|
||||||
@ -2385,6 +2403,7 @@ void qmp_blockdev_backup(const char *device, const char *target,
|
|||||||
BlockdevOnError on_target_error,
|
BlockdevOnError on_target_error,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
|
BlockBackend *blk;
|
||||||
BlockDriverState *bs;
|
BlockDriverState *bs;
|
||||||
BlockDriverState *target_bs;
|
BlockDriverState *target_bs;
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
@ -2400,20 +2419,22 @@ void qmp_blockdev_backup(const char *device, const char *target,
|
|||||||
on_target_error = BLOCKDEV_ON_ERROR_REPORT;
|
on_target_error = BLOCKDEV_ON_ERROR_REPORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
bs = bdrv_find(device);
|
blk = blk_by_name(device);
|
||||||
if (!bs) {
|
if (!blk) {
|
||||||
error_set(errp, QERR_DEVICE_NOT_FOUND, device);
|
error_set(errp, QERR_DEVICE_NOT_FOUND, device);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
bs = blk_bs(blk);
|
||||||
|
|
||||||
aio_context = bdrv_get_aio_context(bs);
|
aio_context = bdrv_get_aio_context(bs);
|
||||||
aio_context_acquire(aio_context);
|
aio_context_acquire(aio_context);
|
||||||
|
|
||||||
target_bs = bdrv_find(target);
|
blk = blk_by_name(target);
|
||||||
if (!target_bs) {
|
if (!blk) {
|
||||||
error_set(errp, QERR_DEVICE_NOT_FOUND, target);
|
error_set(errp, QERR_DEVICE_NOT_FOUND, target);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
target_bs = blk_bs(blk);
|
||||||
|
|
||||||
bdrv_ref(target_bs);
|
bdrv_ref(target_bs);
|
||||||
bdrv_set_aio_context(target_bs, aio_context);
|
bdrv_set_aio_context(target_bs, aio_context);
|
||||||
@ -2442,6 +2463,7 @@ void qmp_drive_mirror(const char *device, const char *target,
|
|||||||
bool has_on_target_error, BlockdevOnError on_target_error,
|
bool has_on_target_error, BlockdevOnError on_target_error,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
|
BlockBackend *blk;
|
||||||
BlockDriverState *bs;
|
BlockDriverState *bs;
|
||||||
BlockDriverState *source, *target_bs;
|
BlockDriverState *source, *target_bs;
|
||||||
AioContext *aio_context;
|
AioContext *aio_context;
|
||||||
@ -2481,11 +2503,12 @@ void qmp_drive_mirror(const char *device, const char *target,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bs = bdrv_find(device);
|
blk = blk_by_name(device);
|
||||||
if (!bs) {
|
if (!blk) {
|
||||||
error_set(errp, QERR_DEVICE_NOT_FOUND, device);
|
error_set(errp, QERR_DEVICE_NOT_FOUND, device);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
bs = blk_bs(blk);
|
||||||
|
|
||||||
aio_context = bdrv_get_aio_context(bs);
|
aio_context = bdrv_get_aio_context(bs);
|
||||||
aio_context_acquire(aio_context);
|
aio_context_acquire(aio_context);
|
||||||
@ -2623,12 +2646,14 @@ out:
|
|||||||
static BlockJob *find_block_job(const char *device, AioContext **aio_context,
|
static BlockJob *find_block_job(const char *device, AioContext **aio_context,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
|
BlockBackend *blk;
|
||||||
BlockDriverState *bs;
|
BlockDriverState *bs;
|
||||||
|
|
||||||
bs = bdrv_find(device);
|
blk = blk_by_name(device);
|
||||||
if (!bs) {
|
if (!blk) {
|
||||||
goto notfound;
|
goto notfound;
|
||||||
}
|
}
|
||||||
|
bs = blk_bs(blk);
|
||||||
|
|
||||||
*aio_context = bdrv_get_aio_context(bs);
|
*aio_context = bdrv_get_aio_context(bs);
|
||||||
aio_context_acquire(*aio_context);
|
aio_context_acquire(*aio_context);
|
||||||
@ -2733,6 +2758,7 @@ void qmp_change_backing_file(const char *device,
|
|||||||
const char *backing_file,
|
const char *backing_file,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
|
BlockBackend *blk;
|
||||||
BlockDriverState *bs = NULL;
|
BlockDriverState *bs = NULL;
|
||||||
AioContext *aio_context;
|
AioContext *aio_context;
|
||||||
BlockDriverState *image_bs = NULL;
|
BlockDriverState *image_bs = NULL;
|
||||||
@ -2741,12 +2767,12 @@ void qmp_change_backing_file(const char *device,
|
|||||||
int open_flags;
|
int open_flags;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* find the top layer BDS of the chain */
|
blk = blk_by_name(device);
|
||||||
bs = bdrv_find(device);
|
if (!blk) {
|
||||||
if (!bs) {
|
|
||||||
error_set(errp, QERR_DEVICE_NOT_FOUND, device);
|
error_set(errp, QERR_DEVICE_NOT_FOUND, device);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
bs = blk_bs(blk);
|
||||||
|
|
||||||
aio_context = bdrv_get_aio_context(bs);
|
aio_context = bdrv_get_aio_context(bs);
|
||||||
aio_context_acquire(aio_context);
|
aio_context_acquire(aio_context);
|
||||||
|
@ -381,7 +381,6 @@ int bdrv_media_changed(BlockDriverState *bs);
|
|||||||
void bdrv_lock_medium(BlockDriverState *bs, bool locked);
|
void bdrv_lock_medium(BlockDriverState *bs, bool locked);
|
||||||
void bdrv_eject(BlockDriverState *bs, bool eject_flag);
|
void bdrv_eject(BlockDriverState *bs, bool eject_flag);
|
||||||
const char *bdrv_get_format_name(BlockDriverState *bs);
|
const char *bdrv_get_format_name(BlockDriverState *bs);
|
||||||
BlockDriverState *bdrv_find(const char *name);
|
|
||||||
BlockDriverState *bdrv_find_node(const char *node_name);
|
BlockDriverState *bdrv_find_node(const char *node_name);
|
||||||
BlockDeviceInfoList *bdrv_named_nodes_list(void);
|
BlockDeviceInfoList *bdrv_named_nodes_list(void);
|
||||||
BlockDriverState *bdrv_lookup_bs(const char *device,
|
BlockDriverState *bdrv_lookup_bs(const char *device,
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "migration/block.h"
|
#include "migration/block.h"
|
||||||
#include "migration/migration.h"
|
#include "migration/migration.h"
|
||||||
#include "sysemu/blockdev.h"
|
#include "sysemu/blockdev.h"
|
||||||
|
#include "sysemu/block-backend.h"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#define BLOCK_SIZE (1 << 20)
|
#define BLOCK_SIZE (1 << 20)
|
||||||
@ -783,6 +784,7 @@ static int block_load(QEMUFile *f, void *opaque, int version_id)
|
|||||||
char device_name[256];
|
char device_name[256];
|
||||||
int64_t addr;
|
int64_t addr;
|
||||||
BlockDriverState *bs, *bs_prev = NULL;
|
BlockDriverState *bs, *bs_prev = NULL;
|
||||||
|
BlockBackend *blk;
|
||||||
uint8_t *buf;
|
uint8_t *buf;
|
||||||
int64_t total_sectors = 0;
|
int64_t total_sectors = 0;
|
||||||
int nr_sectors;
|
int nr_sectors;
|
||||||
@ -800,12 +802,13 @@ static int block_load(QEMUFile *f, void *opaque, int version_id)
|
|||||||
qemu_get_buffer(f, (uint8_t *)device_name, len);
|
qemu_get_buffer(f, (uint8_t *)device_name, len);
|
||||||
device_name[len] = '\0';
|
device_name[len] = '\0';
|
||||||
|
|
||||||
bs = bdrv_find(device_name);
|
blk = blk_by_name(device_name);
|
||||||
if (!bs) {
|
if (!blk) {
|
||||||
fprintf(stderr, "Error unknown block device %s\n",
|
fprintf(stderr, "Error unknown block device %s\n",
|
||||||
device_name);
|
device_name);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
bs = blk_bs(blk);
|
||||||
|
|
||||||
if (bs != bs_prev) {
|
if (bs != bs_prev) {
|
||||||
bs_prev = bs;
|
bs_prev = bs;
|
||||||
|
@ -73,6 +73,7 @@
|
|||||||
#include "block/qapi.h"
|
#include "block/qapi.h"
|
||||||
#include "qapi/qmp-event.h"
|
#include "qapi/qmp-event.h"
|
||||||
#include "qapi-event.h"
|
#include "qapi-event.h"
|
||||||
|
#include "sysemu/block-backend.h"
|
||||||
|
|
||||||
/* for hmp_info_irq/pic */
|
/* for hmp_info_irq/pic */
|
||||||
#if defined(TARGET_SPARC)
|
#if defined(TARGET_SPARC)
|
||||||
@ -5414,15 +5415,15 @@ int monitor_read_block_device_key(Monitor *mon, const char *device,
|
|||||||
BlockCompletionFunc *completion_cb,
|
BlockCompletionFunc *completion_cb,
|
||||||
void *opaque)
|
void *opaque)
|
||||||
{
|
{
|
||||||
BlockDriverState *bs;
|
BlockBackend *blk;
|
||||||
|
|
||||||
bs = bdrv_find(device);
|
blk = blk_by_name(device);
|
||||||
if (!bs) {
|
if (!blk) {
|
||||||
monitor_printf(mon, "Device not found %s\n", device);
|
monitor_printf(mon, "Device not found %s\n", device);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return monitor_read_bdrv_key_start(mon, bs, completion_cb, opaque);
|
return monitor_read_bdrv_key_start(mon, blk_bs(blk), completion_cb, opaque);
|
||||||
}
|
}
|
||||||
|
|
||||||
QemuOptsList qemu_mon_opts = {
|
QemuOptsList qemu_mon_opts = {
|
||||||
|
@ -1961,10 +1961,6 @@
|
|||||||
# @write-threshold: configured threshold for the block device, bytes.
|
# @write-threshold: configured threshold for the block device, bytes.
|
||||||
# Use 0 to disable the threshold.
|
# Use 0 to disable the threshold.
|
||||||
#
|
#
|
||||||
# Returns: Nothing on success
|
|
||||||
# If @node name is not found on the block device graph,
|
|
||||||
# DeviceNotFound
|
|
||||||
#
|
|
||||||
# Since: 2.3
|
# Since: 2.3
|
||||||
##
|
##
|
||||||
{ 'command': 'block-set-write-threshold',
|
{ 'command': 'block-set-write-threshold',
|
||||||
|
@ -539,8 +539,8 @@ storage.
|
|||||||
@item qcow2
|
@item qcow2
|
||||||
QEMU image format, the most versatile format. Use it to have smaller
|
QEMU image format, the most versatile format. Use it to have smaller
|
||||||
images (useful if your filesystem does not supports holes, for example
|
images (useful if your filesystem does not supports holes, for example
|
||||||
on Windows), optional AES encryption, zlib based compression and
|
on Windows), zlib based compression and support of multiple VM
|
||||||
support of multiple VM snapshots.
|
snapshots.
|
||||||
|
|
||||||
Supported options:
|
Supported options:
|
||||||
@table @code
|
@table @code
|
||||||
@ -574,9 +574,10 @@ original file must then be securely erased using a program like shred,
|
|||||||
though even this is ineffective with many modern storage technologies.
|
though even this is ineffective with many modern storage technologies.
|
||||||
@end itemize
|
@end itemize
|
||||||
|
|
||||||
Use of qcow / qcow2 encryption is thus strongly discouraged. Users are
|
Use of qcow / qcow2 encryption with QEMU is deprecated, and support for
|
||||||
recommended to use an alternative encryption technology such as the
|
it will go away in a future release. Users are recommended to use an
|
||||||
Linux dm-crypt / LUKS system.
|
alternative encryption technology such as the Linux dm-crypt / LUKS
|
||||||
|
system.
|
||||||
|
|
||||||
@item cluster_size
|
@item cluster_size
|
||||||
Changes the qcow2 cluster size (must be between 512 and 2M). Smaller cluster
|
Changes the qcow2 cluster size (must be between 512 and 2M). Smaller cluster
|
||||||
|
12
qemu-img.c
12
qemu-img.c
@ -274,8 +274,7 @@ static int print_block_option_help(const char *filename, const char *fmt)
|
|||||||
if (filename) {
|
if (filename) {
|
||||||
proto_drv = bdrv_find_protocol(filename, true, &local_err);
|
proto_drv = bdrv_find_protocol(filename, true, &local_err);
|
||||||
if (!proto_drv) {
|
if (!proto_drv) {
|
||||||
qerror_report_err(local_err);
|
error_report_err(local_err);
|
||||||
error_free(local_err);
|
|
||||||
qemu_opts_free(create_opts);
|
qemu_opts_free(create_opts);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -1526,8 +1525,7 @@ static int img_convert(int argc, char **argv)
|
|||||||
|
|
||||||
proto_drv = bdrv_find_protocol(out_filename, true, &local_err);
|
proto_drv = bdrv_find_protocol(out_filename, true, &local_err);
|
||||||
if (!proto_drv) {
|
if (!proto_drv) {
|
||||||
qerror_report_err(local_err);
|
error_report_err(local_err);
|
||||||
error_free(local_err);
|
|
||||||
ret = -1;
|
ret = -1;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -1554,8 +1552,7 @@ static int img_convert(int argc, char **argv)
|
|||||||
if (options) {
|
if (options) {
|
||||||
qemu_opts_do_parse(opts, options, NULL, &local_err);
|
qemu_opts_do_parse(opts, options, NULL, &local_err);
|
||||||
if (local_err) {
|
if (local_err) {
|
||||||
error_report("Invalid options for file format '%s'", out_fmt);
|
error_report_err(local_err);
|
||||||
error_free(local_err);
|
|
||||||
ret = -1;
|
ret = -1;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -3001,8 +2998,7 @@ static int img_amend(int argc, char **argv)
|
|||||||
if (options) {
|
if (options) {
|
||||||
qemu_opts_do_parse(opts, options, NULL, &err);
|
qemu_opts_do_parse(opts, options, NULL, &err);
|
||||||
if (err) {
|
if (err) {
|
||||||
error_report("Invalid options for file format '%s'", fmt);
|
error_report_err(err);
|
||||||
error_free(err);
|
|
||||||
ret = -1;
|
ret = -1;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -188,6 +188,12 @@ qemu-img create -f qcow2 -o encryption=off TEST_DIR/t.qcow2 64M
|
|||||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
qemu-img create -f qcow2 -o encryption=on TEST_DIR/t.qcow2 64M
|
qemu-img create -f qcow2 -o encryption=on TEST_DIR/t.qcow2 64M
|
||||||
|
qemu-img: Encrypted images are deprecated
|
||||||
|
Support for them will be removed in a future release.
|
||||||
|
You can use 'qemu-img convert' to convert your image to an unencrypted one.
|
||||||
|
qemu-img: Encrypted images are deprecated
|
||||||
|
Support for them will be removed in a future release.
|
||||||
|
You can use 'qemu-img convert' to convert your image to an unencrypted one.
|
||||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=on cluster_size=65536 lazy_refcounts=off refcount_bits=16
|
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=on cluster_size=65536 lazy_refcounts=off refcount_bits=16
|
||||||
|
|
||||||
== Check lazy_refcounts option (only with v3) ==
|
== Check lazy_refcounts option (only with v3) ==
|
||||||
|
@ -128,13 +128,11 @@ QEMU_PROG: Initialization of device ide-hd failed: Device initialization failed.
|
|||||||
Testing: -drive if=virtio
|
Testing: -drive if=virtio
|
||||||
QEMU X.Y.Z monitor - type 'help' for more information
|
QEMU X.Y.Z monitor - type 'help' for more information
|
||||||
(qemu) QEMU_PROG: -drive if=virtio: Device needs media, but drive is empty
|
(qemu) QEMU_PROG: -drive if=virtio: Device needs media, but drive is empty
|
||||||
QEMU_PROG: -drive if=virtio: Device initialization failed.
|
|
||||||
QEMU_PROG: -drive if=virtio: Device 'virtio-blk-pci' could not be initialized
|
QEMU_PROG: -drive if=virtio: Device 'virtio-blk-pci' could not be initialized
|
||||||
|
|
||||||
Testing: -drive if=scsi
|
Testing: -drive if=scsi
|
||||||
QEMU X.Y.Z monitor - type 'help' for more information
|
QEMU X.Y.Z monitor - type 'help' for more information
|
||||||
(qemu) QEMU_PROG: -drive if=scsi: Device needs media, but drive is empty
|
(qemu) QEMU_PROG: Initialization of device lsi53c895a failed: Device needs media, but drive is empty
|
||||||
QEMU_PROG: Initialization of device lsi53c895a failed: Device initialization failed.
|
|
||||||
|
|
||||||
Testing: -drive if=none,id=disk -device ide-cd,drive=disk
|
Testing: -drive if=none,id=disk -device ide-cd,drive=disk
|
||||||
QEMU X.Y.Z monitor - type 'help' for more information
|
QEMU X.Y.Z monitor - type 'help' for more information
|
||||||
|
@ -288,7 +288,6 @@ qemu-img: Error while amending options: Invalid argument
|
|||||||
Unknown compatibility level 0.42.
|
Unknown compatibility level 0.42.
|
||||||
qemu-img: Error while amending options: Invalid argument
|
qemu-img: Error while amending options: Invalid argument
|
||||||
qemu-img: Invalid parameter 'foo'
|
qemu-img: Invalid parameter 'foo'
|
||||||
qemu-img: Invalid options for file format 'qcow2'
|
|
||||||
Changing the cluster size is not supported.
|
Changing the cluster size is not supported.
|
||||||
qemu-img: Error while amending options: Operation not supported
|
qemu-img: Error while amending options: Operation not supported
|
||||||
Changing the encryption flag is not supported.
|
Changing the encryption flag is not supported.
|
||||||
|
@ -44,10 +44,19 @@ QMP_VERSION
|
|||||||
|
|
||||||
=== Encrypted image ===
|
=== Encrypted image ===
|
||||||
|
|
||||||
|
qemu-img: Encrypted images are deprecated
|
||||||
|
Support for them will be removed in a future release.
|
||||||
|
You can use 'qemu-img convert' to convert your image to an unencrypted one.
|
||||||
|
qemu-img: Encrypted images are deprecated
|
||||||
|
Support for them will be removed in a future release.
|
||||||
|
You can use 'qemu-img convert' to convert your image to an unencrypted one.
|
||||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on
|
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on
|
||||||
Testing: -S
|
Testing: -S
|
||||||
QMP_VERSION
|
QMP_VERSION
|
||||||
{"return": {}}
|
{"return": {}}
|
||||||
|
Encrypted images are deprecated
|
||||||
|
Support for them will be removed in a future release.
|
||||||
|
You can use 'qemu-img convert' to convert your image to an unencrypted one.
|
||||||
{"error": {"class": "GenericError", "desc": "blockdev-add doesn't support encrypted devices"}}
|
{"error": {"class": "GenericError", "desc": "blockdev-add doesn't support encrypted devices"}}
|
||||||
{"return": {}}
|
{"return": {}}
|
||||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"}
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"}
|
||||||
@ -57,6 +66,9 @@ QMP_VERSION
|
|||||||
Testing:
|
Testing:
|
||||||
QMP_VERSION
|
QMP_VERSION
|
||||||
{"return": {}}
|
{"return": {}}
|
||||||
|
Encrypted images are deprecated
|
||||||
|
Support for them will be removed in a future release.
|
||||||
|
You can use 'qemu-img convert' to convert your image to an unencrypted one.
|
||||||
{"error": {"class": "GenericError", "desc": "Guest must be stopped for opening of encrypted image"}}
|
{"error": {"class": "GenericError", "desc": "Guest must be stopped for opening of encrypted image"}}
|
||||||
{"return": {}}
|
{"return": {}}
|
||||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"}
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"}
|
||||||
@ -66,6 +78,12 @@ QMP_VERSION
|
|||||||
|
|
||||||
=== Missing driver ===
|
=== Missing driver ===
|
||||||
|
|
||||||
|
qemu-img: Encrypted images are deprecated
|
||||||
|
Support for them will be removed in a future release.
|
||||||
|
You can use 'qemu-img convert' to convert your image to an unencrypted one.
|
||||||
|
qemu-img: Encrypted images are deprecated
|
||||||
|
Support for them will be removed in a future release.
|
||||||
|
You can use 'qemu-img convert' to convert your image to an unencrypted one.
|
||||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on
|
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on
|
||||||
Testing: -S
|
Testing: -S
|
||||||
QMP_VERSION
|
QMP_VERSION
|
||||||
|
95
tests/qemu-iotests/115
Executable file
95
tests/qemu-iotests/115
Executable file
@ -0,0 +1,95 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Test case for non-self-referential qcow2 refcount blocks
|
||||||
|
#
|
||||||
|
# Copyright (C) 2014 Red Hat, Inc.
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
# creator
|
||||||
|
owner=mreitz@redhat.com
|
||||||
|
|
||||||
|
seq="$(basename $0)"
|
||||||
|
echo "QA output created by $seq"
|
||||||
|
|
||||||
|
here="$PWD"
|
||||||
|
tmp=/tmp/$$
|
||||||
|
status=1 # failure is the default!
|
||||||
|
|
||||||
|
_cleanup()
|
||||||
|
{
|
||||||
|
_cleanup_test_img
|
||||||
|
}
|
||||||
|
trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||||
|
|
||||||
|
# get standard environment, filters and checks
|
||||||
|
. ./common.rc
|
||||||
|
. ./common.filter
|
||||||
|
|
||||||
|
_supported_fmt qcow2
|
||||||
|
_supported_proto file
|
||||||
|
_supported_os Linux
|
||||||
|
# This test relies on refcounts being 64 bits wide (which does not work with
|
||||||
|
# compat=0.10)
|
||||||
|
_unsupported_imgopts 'refcount_bits=\([^6]\|.\([^4]\|$\)\)' 'compat=0.10'
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo '=== Testing large refcount and L1 table ==='
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Create an image with an L1 table and a refcount table that each span twice the
|
||||||
|
# number of clusters which can be described by a single refblock; therefore, at
|
||||||
|
# least two refblocks cannot count their own refcounts because all the clusters
|
||||||
|
# they describe are part of the L1 table or refcount table.
|
||||||
|
|
||||||
|
# One refblock can describe (with cluster_size=512 and refcount_bits=64)
|
||||||
|
# 512/8 = 64 clusters, therefore the L1 table should cover 128 clusters, which
|
||||||
|
# equals 128 * (512/8) = 8192 entries (actually, 8192 - 512/8 = 8129 would
|
||||||
|
# suffice, but it does not really matter). 8192 L2 tables can in turn describe
|
||||||
|
# 8192 * 512/8 = 524,288 clusters which cover a space of 256 MB.
|
||||||
|
|
||||||
|
# Since with refcount_bits=64 every refcount block entry is 64 bits wide (just
|
||||||
|
# like the L2 table entries), the same calculation applies to the refcount table
|
||||||
|
# as well; the difference is that while for the L1 table the guest disk size is
|
||||||
|
# concerned, for the refcount table it is the image length that has to be at
|
||||||
|
# least 256 MB. We can achieve that by using preallocation=metadata for an image
|
||||||
|
# which has a guest disk size of 256 MB.
|
||||||
|
|
||||||
|
IMGOPTS="$IMGOPTS,refcount_bits=64,cluster_size=512,preallocation=metadata" \
|
||||||
|
_make_test_img 256M
|
||||||
|
|
||||||
|
# We know for sure that the L1 and refcount tables do not overlap with any other
|
||||||
|
# structure because the metadata overlap checks would have caught that case.
|
||||||
|
|
||||||
|
# Because qemu refuses to open qcow2 files whose L1 table does not cover the
|
||||||
|
# whole guest disk size, it is definitely large enough. On the other hand, to
|
||||||
|
# test whether the refcount table is large enough, we simply have to verify that
|
||||||
|
# indeed all the clusters are allocated, which is done by qemu-img check.
|
||||||
|
|
||||||
|
# The final thing we need to test is whether the tables are actually covered by
|
||||||
|
# refcount blocks; since all clusters of the tables are referenced, we can use
|
||||||
|
# qemu-img check for that purpose, too.
|
||||||
|
|
||||||
|
$QEMU_IMG check "$TEST_IMG" | \
|
||||||
|
sed -e 's/^.* = \([0-9]\+\.[0-9]\+% allocated\).*\(clusters\)$/\1 \2/' \
|
||||||
|
-e '/^Image end offset/d'
|
||||||
|
|
||||||
|
# (Note that we cannot use _check_test_img because that function filters out the
|
||||||
|
# allocation status)
|
||||||
|
|
||||||
|
# success, all done
|
||||||
|
echo '*** done'
|
||||||
|
rm -f $seq.full
|
||||||
|
status=0
|
8
tests/qemu-iotests/115.out
Normal file
8
tests/qemu-iotests/115.out
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
QA output created by 115
|
||||||
|
|
||||||
|
=== Testing large refcount and L1 table ===
|
||||||
|
|
||||||
|
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=268435456 preallocation='metadata'
|
||||||
|
No errors were found on the image.
|
||||||
|
100.00% allocated clusters
|
||||||
|
*** done
|
102
tests/qemu-iotests/121
Executable file
102
tests/qemu-iotests/121
Executable file
@ -0,0 +1,102 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Test cases for qcow2 refcount table growth
|
||||||
|
#
|
||||||
|
# Copyright (C) 2015 Red Hat, Inc.
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
# creator
|
||||||
|
owner=mreitz@redhat.com
|
||||||
|
|
||||||
|
seq="$(basename $0)"
|
||||||
|
echo "QA output created by $seq"
|
||||||
|
|
||||||
|
here="$PWD"
|
||||||
|
tmp=/tmp/$$
|
||||||
|
status=1 # failure is the default!
|
||||||
|
|
||||||
|
_cleanup()
|
||||||
|
{
|
||||||
|
_cleanup_test_img
|
||||||
|
}
|
||||||
|
trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||||
|
|
||||||
|
# get standard environment, filters and checks
|
||||||
|
. ./common.rc
|
||||||
|
. ./common.filter
|
||||||
|
|
||||||
|
_supported_fmt qcow2
|
||||||
|
_supported_proto file
|
||||||
|
_supported_os Linux
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo '=== New refcount structures may not conflict with existing structures ==='
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo '--- Test 1 ---'
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Preallocation speeds up the write operation, but preallocating everything will
|
||||||
|
# destroy the purpose of the write; so preallocate one KB less than what would
|
||||||
|
# cause a reftable growth...
|
||||||
|
IMGOPTS='preallocation=metadata,cluster_size=1k' _make_test_img 64512K
|
||||||
|
# ...and make the image the desired size afterwards.
|
||||||
|
$QEMU_IMG resize "$TEST_IMG" 65M
|
||||||
|
|
||||||
|
# The first write results in a growth of the refcount table during an allocation
|
||||||
|
# which has precisely the required size so that the new refcount block allocated
|
||||||
|
# in alloc_refcount_block() is right after cluster_index; this did lead to a
|
||||||
|
# different refcount block being written to disk (a zeroed cluster) than what is
|
||||||
|
# cached (a refblock with one entry having a refcount of 1), and the second
|
||||||
|
# write would then result in that cached cluster being marked dirty and then
|
||||||
|
# in it being written to disk.
|
||||||
|
# This should not happen, the new refcount structures may not conflict with
|
||||||
|
# new_block.
|
||||||
|
# (Note that for some reason, 'write 63M 1K' does not trigger the problem)
|
||||||
|
$QEMU_IO -c 'write 62M 1025K' -c 'write 64M 1M' "$TEST_IMG" | _filter_qemu_io
|
||||||
|
|
||||||
|
_check_test_img
|
||||||
|
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo '--- Test 2 ---'
|
||||||
|
echo
|
||||||
|
|
||||||
|
IMGOPTS='preallocation=metadata,cluster_size=1k' _make_test_img 64513K
|
||||||
|
# This results in an L1 table growth which in turn results in some clusters at
|
||||||
|
# the start of the image becoming free
|
||||||
|
$QEMU_IMG resize "$TEST_IMG" 65M
|
||||||
|
|
||||||
|
# This write results in a refcount table growth; but the refblock allocated
|
||||||
|
# immediately before that (new_block) takes cluster index 4 (which is now free)
|
||||||
|
# and is thus not self-describing (in contrast to test 1, where new_block was
|
||||||
|
# self-describing). The refcount table growth algorithm then used to place the
|
||||||
|
# new refcount structures at cluster index 65536 (which is the same as the
|
||||||
|
# cluster_index parameter in this case), allocating a new refcount block for
|
||||||
|
# that cluster while new_block already existed, leaking new_block.
|
||||||
|
# Therefore, the new refcount structures may not be put at cluster_index
|
||||||
|
# (because new_block already describes that cluster, and the new structures try
|
||||||
|
# to be self-describing).
|
||||||
|
$QEMU_IO -c 'write 63M 130K' "$TEST_IMG" | _filter_qemu_io
|
||||||
|
|
||||||
|
_check_test_img
|
||||||
|
|
||||||
|
|
||||||
|
# success, all done
|
||||||
|
echo
|
||||||
|
echo '*** done'
|
||||||
|
rm -f $seq.full
|
||||||
|
status=0
|
23
tests/qemu-iotests/121.out
Normal file
23
tests/qemu-iotests/121.out
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
QA output created by 121
|
||||||
|
|
||||||
|
=== New refcount structures may not conflict with existing structures ===
|
||||||
|
|
||||||
|
--- Test 1 ---
|
||||||
|
|
||||||
|
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=66060288 preallocation='metadata'
|
||||||
|
Image resized.
|
||||||
|
wrote 1049600/1049600 bytes at offset 65011712
|
||||||
|
1.001 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
|
wrote 1048576/1048576 bytes at offset 67108864
|
||||||
|
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
|
No errors were found on the image.
|
||||||
|
|
||||||
|
--- Test 2 ---
|
||||||
|
|
||||||
|
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=66061312 preallocation='metadata'
|
||||||
|
Image resized.
|
||||||
|
wrote 133120/133120 bytes at offset 66060288
|
||||||
|
130 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||||
|
No errors were found on the image.
|
||||||
|
|
||||||
|
*** done
|
@ -119,6 +119,8 @@
|
|||||||
112 rw auto
|
112 rw auto
|
||||||
113 rw auto quick
|
113 rw auto quick
|
||||||
114 rw auto quick
|
114 rw auto quick
|
||||||
|
115 rw auto
|
||||||
116 rw auto quick
|
116 rw auto quick
|
||||||
|
121 rw auto
|
||||||
123 rw auto quick
|
123 rw auto quick
|
||||||
128 rw auto quick
|
128 rw auto quick
|
||||||
|
Loading…
Reference in New Issue
Block a user