mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'kwolf/for-anthony' into staging
# By Max Reitz (10) and others # Via Kevin Wolf * kwolf/for-anthony: (30 commits) qcow2: Remove useless count_contiguous_clusters() parameter qcow2: COMPRESSED on count_contiguous_clusters qcow2: count_contiguous_clusters and compression qcow2: Free only newly allocated clusters on error qcow2: Always use error path in l2_allocate qcow2: Don't put invalid L2 table into cache qemu-iotests: Preallocated zero clusters in 061 qcow2: Correct bitmap size in zero expansion qemu-iotests: Quote $TEST_IMG* and $TEST_DIR usage qemu-iotests: Add basic ability to use binary sample images qemu-iotests: fix qmp.py search path block: use DIV_ROUND_UP in bdrv_co_do_readv qcow2: Assert against currently impossible overflow block: qed - use QEMU_PACKED for on-disk structures block: qcow2 - used QEMU_PACKED for on-disk structures block: vpc - use QEMU_PACKED for on-disk structures block: vdi - use QEMU_PACKED for on-disk structures rbd: avoid qemu_rbd_snap_list() memory leaks qdict: Extract qdict_extract_subqdict block: Fix compiler warning (-Werror=uninitialized) ... Message-id: 1380296370-14523-1-git-send-email-kwolf@redhat.com
This commit is contained in:
@@ -792,7 +792,7 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
|
||||
/* Open the image, either directly or using a protocol */
|
||||
if (drv->bdrv_file_open) {
|
||||
assert(file == NULL);
|
||||
assert(drv->bdrv_parse_filename || filename != NULL);
|
||||
assert(!drv->bdrv_needs_filename || filename != NULL);
|
||||
ret = drv->bdrv_file_open(bs, options, open_flags, &local_err);
|
||||
} else {
|
||||
if (file == NULL) {
|
||||
@@ -911,7 +911,7 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename,
|
||||
goto fail;
|
||||
}
|
||||
qdict_del(options, "filename");
|
||||
} else if (!drv->bdrv_parse_filename && !filename) {
|
||||
} else if (drv->bdrv_needs_filename && !filename) {
|
||||
error_setg(errp, "The '%s' block driver requires a file name",
|
||||
drv->format_name);
|
||||
ret = -EINVAL;
|
||||
@@ -978,11 +978,12 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp)
|
||||
} else if (bs->backing_file[0] == '\0' && qdict_size(options) == 0) {
|
||||
QDECREF(options);
|
||||
return 0;
|
||||
} else {
|
||||
bdrv_get_full_backing_filename(bs, backing_filename,
|
||||
sizeof(backing_filename));
|
||||
}
|
||||
|
||||
bs->backing_hd = bdrv_new("");
|
||||
bdrv_get_full_backing_filename(bs, backing_filename,
|
||||
sizeof(backing_filename));
|
||||
|
||||
if (bs->backing_format[0] != '\0') {
|
||||
back_drv = bdrv_find_format(bs->backing_format);
|
||||
@@ -994,6 +995,8 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp)
|
||||
ret = bdrv_open(bs->backing_hd,
|
||||
*backing_filename ? backing_filename : NULL, options,
|
||||
back_flags, back_drv, &local_err);
|
||||
pstrcpy(bs->backing_file, sizeof(bs->backing_file),
|
||||
bs->backing_hd->file->filename);
|
||||
if (ret < 0) {
|
||||
bdrv_unref(bs->backing_hd);
|
||||
bs->backing_hd = NULL;
|
||||
@@ -1004,25 +1007,6 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void extract_subqdict(QDict *src, QDict **dst, const char *start)
|
||||
{
|
||||
const QDictEntry *entry, *next;
|
||||
const char *p;
|
||||
|
||||
*dst = qdict_new();
|
||||
entry = qdict_first(src);
|
||||
|
||||
while (entry != NULL) {
|
||||
next = qdict_next(src, entry);
|
||||
if (strstart(entry->key, start, &p)) {
|
||||
qobject_incref(entry->value);
|
||||
qdict_put_obj(*dst, p, entry->value);
|
||||
qdict_del(src, entry->key);
|
||||
}
|
||||
entry = next;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Opens a disk image (raw, qcow2, vmdk, ...)
|
||||
*
|
||||
@@ -1128,7 +1112,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
|
||||
flags |= BDRV_O_ALLOW_RDWR;
|
||||
}
|
||||
|
||||
extract_subqdict(options, &file_options, "file.");
|
||||
qdict_extract_subqdict(options, &file_options, "file.");
|
||||
|
||||
ret = bdrv_file_open(&file, filename, file_options,
|
||||
bdrv_open_flags(bs, flags | BDRV_O_UNMAP), &local_err);
|
||||
@@ -1166,7 +1150,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
|
||||
if ((flags & BDRV_O_NO_BACKING) == 0) {
|
||||
QDict *backing_options;
|
||||
|
||||
extract_subqdict(options, &backing_options, "backing.");
|
||||
qdict_extract_subqdict(options, &backing_options, "backing.");
|
||||
ret = bdrv_open_backing_file(bs, backing_options, &local_err);
|
||||
if (ret < 0) {
|
||||
goto close_and_fail;
|
||||
@@ -2669,7 +2653,7 @@ static int coroutine_fn bdrv_co_do_readv(BlockDriverState *bs,
|
||||
goto out;
|
||||
}
|
||||
|
||||
total_sectors = (len + BDRV_SECTOR_SIZE - 1) >> BDRV_SECTOR_BITS;
|
||||
total_sectors = DIV_ROUND_UP(len, BDRV_SECTOR_SIZE);
|
||||
max_nb_sectors = MAX(0, total_sectors - sector_num);
|
||||
if (max_nb_sectors > 0) {
|
||||
ret = drv->bdrv_co_readv(bs, sector_num,
|
||||
@@ -3159,13 +3143,14 @@ static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs,
|
||||
|
||||
ret = bs->drv->bdrv_co_get_block_status(bs, sector_num, nb_sectors, pnum);
|
||||
if (ret < 0) {
|
||||
*pnum = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!(ret & BDRV_BLOCK_DATA)) {
|
||||
if (bdrv_has_zero_init(bs)) {
|
||||
ret |= BDRV_BLOCK_ZERO;
|
||||
} else {
|
||||
} else if (bs->backing_hd) {
|
||||
BlockDriverState *bs2 = bs->backing_hd;
|
||||
int64_t length2 = bdrv_getlength(bs2);
|
||||
if (length2 >= 0 && sector_num >= (length2 >> BDRV_SECTOR_BITS)) {
|
||||
|
||||
@@ -611,6 +611,7 @@ static BlockDriver bdrv_gluster = {
|
||||
.format_name = "gluster",
|
||||
.protocol_name = "gluster",
|
||||
.instance_size = sizeof(BDRVGlusterState),
|
||||
.bdrv_needs_filename = true,
|
||||
.bdrv_file_open = qemu_gluster_open,
|
||||
.bdrv_close = qemu_gluster_close,
|
||||
.bdrv_create = qemu_gluster_create,
|
||||
@@ -631,6 +632,7 @@ static BlockDriver bdrv_gluster_tcp = {
|
||||
.format_name = "gluster",
|
||||
.protocol_name = "gluster+tcp",
|
||||
.instance_size = sizeof(BDRVGlusterState),
|
||||
.bdrv_needs_filename = true,
|
||||
.bdrv_file_open = qemu_gluster_open,
|
||||
.bdrv_close = qemu_gluster_close,
|
||||
.bdrv_create = qemu_gluster_create,
|
||||
@@ -651,6 +653,7 @@ static BlockDriver bdrv_gluster_unix = {
|
||||
.format_name = "gluster",
|
||||
.protocol_name = "gluster+unix",
|
||||
.instance_size = sizeof(BDRVGlusterState),
|
||||
.bdrv_needs_filename = true,
|
||||
.bdrv_file_open = qemu_gluster_open,
|
||||
.bdrv_close = qemu_gluster_close,
|
||||
.bdrv_create = qemu_gluster_create,
|
||||
@@ -671,6 +674,7 @@ static BlockDriver bdrv_gluster_rdma = {
|
||||
.format_name = "gluster",
|
||||
.protocol_name = "gluster+rdma",
|
||||
.instance_size = sizeof(BDRVGlusterState),
|
||||
.bdrv_needs_filename = true,
|
||||
.bdrv_file_open = qemu_gluster_open,
|
||||
.bdrv_close = qemu_gluster_close,
|
||||
.bdrv_create = qemu_gluster_create,
|
||||
|
||||
@@ -1520,6 +1520,7 @@ static BlockDriver bdrv_iscsi = {
|
||||
.protocol_name = "iscsi",
|
||||
|
||||
.instance_size = sizeof(IscsiLun),
|
||||
.bdrv_needs_filename = true,
|
||||
.bdrv_file_open = iscsi_open,
|
||||
.bdrv_close = iscsi_close,
|
||||
.bdrv_create = iscsi_create,
|
||||
|
||||
+56
-31
@@ -188,7 +188,7 @@ static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table)
|
||||
{
|
||||
BDRVQcowState *s = bs->opaque;
|
||||
uint64_t old_l2_offset;
|
||||
uint64_t *l2_table;
|
||||
uint64_t *l2_table = NULL;
|
||||
int64_t l2_offset;
|
||||
int ret;
|
||||
|
||||
@@ -200,7 +200,8 @@ static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table)
|
||||
|
||||
l2_offset = qcow2_alloc_clusters(bs, s->l2_size * sizeof(uint64_t));
|
||||
if (l2_offset < 0) {
|
||||
return l2_offset;
|
||||
ret = l2_offset;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = qcow2_cache_flush(bs, s->refcount_block_cache);
|
||||
@@ -213,7 +214,7 @@ static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table)
|
||||
trace_qcow2_l2_allocate_get_empty(bs, l1_index);
|
||||
ret = qcow2_cache_get_empty(bs, s->l2_table_cache, l2_offset, (void**) table);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
l2_table = *table;
|
||||
@@ -265,7 +266,9 @@ static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table)
|
||||
|
||||
fail:
|
||||
trace_qcow2_l2_allocate_done(bs, l1_index, ret);
|
||||
qcow2_cache_put(bs, s->l2_table_cache, (void**) table);
|
||||
if (l2_table != NULL) {
|
||||
qcow2_cache_put(bs, s->l2_table_cache, (void**) table);
|
||||
}
|
||||
s->l1_table[l1_index] = old_l2_offset;
|
||||
return ret;
|
||||
}
|
||||
@@ -278,23 +281,26 @@ fail:
|
||||
* cluster which may require a different handling)
|
||||
*/
|
||||
static int count_contiguous_clusters(uint64_t nb_clusters, int cluster_size,
|
||||
uint64_t *l2_table, uint64_t start, uint64_t stop_flags)
|
||||
uint64_t *l2_table, uint64_t stop_flags)
|
||||
{
|
||||
int i;
|
||||
uint64_t mask = stop_flags | L2E_OFFSET_MASK;
|
||||
uint64_t offset = be64_to_cpu(l2_table[0]) & mask;
|
||||
uint64_t mask = stop_flags | L2E_OFFSET_MASK | QCOW2_CLUSTER_COMPRESSED;
|
||||
uint64_t first_entry = be64_to_cpu(l2_table[0]);
|
||||
uint64_t offset = first_entry & mask;
|
||||
|
||||
if (!offset)
|
||||
return 0;
|
||||
|
||||
for (i = start; i < start + nb_clusters; i++) {
|
||||
assert(qcow2_get_cluster_type(first_entry) != QCOW2_CLUSTER_COMPRESSED);
|
||||
|
||||
for (i = 0; i < nb_clusters; i++) {
|
||||
uint64_t l2_entry = be64_to_cpu(l2_table[i]) & mask;
|
||||
if (offset + (uint64_t) i * cluster_size != l2_entry) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (i - start);
|
||||
return i;
|
||||
}
|
||||
|
||||
static int count_contiguous_free_clusters(uint64_t nb_clusters, uint64_t *l2_table)
|
||||
@@ -487,8 +493,7 @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
|
||||
return -EIO;
|
||||
}
|
||||
c = count_contiguous_clusters(nb_clusters, s->cluster_size,
|
||||
&l2_table[l2_index], 0,
|
||||
QCOW_OFLAG_COMPRESSED | QCOW_OFLAG_ZERO);
|
||||
&l2_table[l2_index], QCOW_OFLAG_ZERO);
|
||||
*cluster_offset = 0;
|
||||
break;
|
||||
case QCOW2_CLUSTER_UNALLOCATED:
|
||||
@@ -499,8 +504,7 @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
|
||||
case QCOW2_CLUSTER_NORMAL:
|
||||
/* how many allocated clusters ? */
|
||||
c = count_contiguous_clusters(nb_clusters, s->cluster_size,
|
||||
&l2_table[l2_index], 0,
|
||||
QCOW_OFLAG_COMPRESSED | QCOW_OFLAG_ZERO);
|
||||
&l2_table[l2_index], QCOW_OFLAG_ZERO);
|
||||
*cluster_offset &= L2E_OFFSET_MASK;
|
||||
break;
|
||||
default:
|
||||
@@ -716,6 +720,7 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)
|
||||
}
|
||||
qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table);
|
||||
|
||||
assert(l2_index + m->nb_clusters <= s->l2_size);
|
||||
for (i = 0; i < m->nb_clusters; i++) {
|
||||
/* if two concurrent writes happen to the same unallocated cluster
|
||||
* each write allocates separate cluster and writes data concurrently.
|
||||
@@ -929,7 +934,7 @@ static int handle_copied(BlockDriverState *bs, uint64_t guest_offset,
|
||||
/* We keep all QCOW_OFLAG_COPIED clusters */
|
||||
keep_clusters =
|
||||
count_contiguous_clusters(nb_clusters, s->cluster_size,
|
||||
&l2_table[l2_index], 0,
|
||||
&l2_table[l2_index],
|
||||
QCOW_OFLAG_COPIED | QCOW_OFLAG_ZERO);
|
||||
assert(keep_clusters <= nb_clusters);
|
||||
|
||||
@@ -1509,8 +1514,8 @@ fail:
|
||||
* i.e., the number of bits in expanded_clusters.
|
||||
*/
|
||||
static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
|
||||
int l1_size, uint8_t *expanded_clusters,
|
||||
uint64_t nb_clusters)
|
||||
int l1_size, uint8_t **expanded_clusters,
|
||||
uint64_t *nb_clusters)
|
||||
{
|
||||
BDRVQcowState *s = bs->opaque;
|
||||
bool is_active_l1 = (l1_table == s->l1_table);
|
||||
@@ -1550,11 +1555,12 @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
|
||||
uint64_t l2_entry = be64_to_cpu(l2_table[j]);
|
||||
int64_t offset = l2_entry & L2E_OFFSET_MASK, cluster_index;
|
||||
int cluster_type = qcow2_get_cluster_type(l2_entry);
|
||||
bool preallocated = offset != 0;
|
||||
|
||||
if (cluster_type == QCOW2_CLUSTER_NORMAL) {
|
||||
cluster_index = offset >> s->cluster_bits;
|
||||
assert((cluster_index >= 0) && (cluster_index < nb_clusters));
|
||||
if (expanded_clusters[cluster_index / 8] &
|
||||
assert((cluster_index >= 0) && (cluster_index < *nb_clusters));
|
||||
if ((*expanded_clusters)[cluster_index / 8] &
|
||||
(1 << (cluster_index % 8))) {
|
||||
/* Probably a shared L2 table; this cluster was a zero
|
||||
* cluster which has been expanded, its refcount
|
||||
@@ -1575,8 +1581,7 @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!offset) {
|
||||
/* not preallocated */
|
||||
if (!preallocated) {
|
||||
if (!bs->backing_hd) {
|
||||
/* not backed; therefore we can simply deallocate the
|
||||
* cluster */
|
||||
@@ -1595,16 +1600,20 @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
|
||||
ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT,
|
||||
offset, s->cluster_size);
|
||||
if (ret < 0) {
|
||||
qcow2_free_clusters(bs, offset, s->cluster_size,
|
||||
QCOW2_DISCARD_ALWAYS);
|
||||
if (!preallocated) {
|
||||
qcow2_free_clusters(bs, offset, s->cluster_size,
|
||||
QCOW2_DISCARD_ALWAYS);
|
||||
}
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = bdrv_write_zeroes(bs->file, offset / BDRV_SECTOR_SIZE,
|
||||
s->cluster_sectors);
|
||||
if (ret < 0) {
|
||||
qcow2_free_clusters(bs, offset, s->cluster_size,
|
||||
QCOW2_DISCARD_ALWAYS);
|
||||
if (!preallocated) {
|
||||
qcow2_free_clusters(bs, offset, s->cluster_size,
|
||||
QCOW2_DISCARD_ALWAYS);
|
||||
}
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -1612,8 +1621,25 @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
|
||||
l2_dirty = true;
|
||||
|
||||
cluster_index = offset >> s->cluster_bits;
|
||||
assert((cluster_index >= 0) && (cluster_index < nb_clusters));
|
||||
expanded_clusters[cluster_index / 8] |= 1 << (cluster_index % 8);
|
||||
|
||||
if (cluster_index >= *nb_clusters) {
|
||||
uint64_t old_bitmap_size = (*nb_clusters + 7) / 8;
|
||||
uint64_t new_bitmap_size;
|
||||
/* The offset may lie beyond the old end of the underlying image
|
||||
* file for growable files only */
|
||||
assert(bs->file->growable);
|
||||
*nb_clusters = size_to_clusters(s, bs->file->total_sectors *
|
||||
BDRV_SECTOR_SIZE);
|
||||
new_bitmap_size = (*nb_clusters + 7) / 8;
|
||||
*expanded_clusters = g_realloc(*expanded_clusters,
|
||||
new_bitmap_size);
|
||||
/* clear the newly allocated space */
|
||||
memset(&(*expanded_clusters)[old_bitmap_size], 0,
|
||||
new_bitmap_size - old_bitmap_size);
|
||||
}
|
||||
|
||||
assert((cluster_index >= 0) && (cluster_index < *nb_clusters));
|
||||
(*expanded_clusters)[cluster_index / 8] |= 1 << (cluster_index % 8);
|
||||
}
|
||||
|
||||
if (is_active_l1) {
|
||||
@@ -1672,18 +1698,17 @@ int qcow2_expand_zero_clusters(BlockDriverState *bs)
|
||||
{
|
||||
BDRVQcowState *s = bs->opaque;
|
||||
uint64_t *l1_table = NULL;
|
||||
int cluster_to_sector_bits = s->cluster_bits - BDRV_SECTOR_BITS;
|
||||
uint64_t nb_clusters;
|
||||
uint8_t *expanded_clusters;
|
||||
int ret;
|
||||
int i, j;
|
||||
|
||||
nb_clusters = (bs->total_sectors + (1 << cluster_to_sector_bits) - 1)
|
||||
>> cluster_to_sector_bits;
|
||||
nb_clusters = size_to_clusters(s, bs->file->total_sectors *
|
||||
BDRV_SECTOR_SIZE);
|
||||
expanded_clusters = g_malloc0((nb_clusters + 7) / 8);
|
||||
|
||||
ret = expand_zero_clusters_in_l1(bs, s->l1_table, s->l1_size,
|
||||
expanded_clusters, nb_clusters);
|
||||
&expanded_clusters, &nb_clusters);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -1717,7 +1742,7 @@ int qcow2_expand_zero_clusters(BlockDriverState *bs)
|
||||
}
|
||||
|
||||
ret = expand_zero_clusters_in_l1(bs, l1_table, s->snapshots[i].l1_size,
|
||||
expanded_clusters, nb_clusters);
|
||||
&expanded_clusters, &nb_clusters);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -874,7 +874,6 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
|
||||
nb_csectors = ((offset >> s->csize_shift) &
|
||||
s->csize_mask) + 1;
|
||||
if (addend != 0) {
|
||||
int ret;
|
||||
ret = update_refcount(bs,
|
||||
(offset & s->cluster_offset_mask) & ~511,
|
||||
nb_csectors * 512, addend,
|
||||
|
||||
+1
-1
@@ -52,7 +52,7 @@
|
||||
typedef struct {
|
||||
uint32_t magic;
|
||||
uint32_t len;
|
||||
} QCowExtension;
|
||||
} QEMU_PACKED QCowExtension;
|
||||
|
||||
#define QCOW2_EXT_MAGIC_END 0
|
||||
#define QCOW2_EXT_MAGIC_BACKING_FORMAT 0xE2792ACA
|
||||
|
||||
+1
-1
@@ -86,7 +86,7 @@ typedef struct QCowHeader {
|
||||
|
||||
uint32_t refcount_order;
|
||||
uint32_t header_length;
|
||||
} QCowHeader;
|
||||
} QEMU_PACKED QCowHeader;
|
||||
|
||||
typedef struct QCowSnapshot {
|
||||
uint64_t l1_table_offset;
|
||||
|
||||
+1
-1
@@ -100,7 +100,7 @@ typedef struct {
|
||||
/* if (features & QED_F_BACKING_FILE) */
|
||||
uint32_t backing_filename_offset; /* in bytes from start of header */
|
||||
uint32_t backing_filename_size; /* in bytes */
|
||||
} QEDHeader;
|
||||
} QEMU_PACKED QEDHeader;
|
||||
|
||||
typedef struct {
|
||||
uint64_t offsets[0]; /* in bytes */
|
||||
|
||||
@@ -1200,6 +1200,7 @@ static BlockDriver bdrv_file = {
|
||||
.format_name = "file",
|
||||
.protocol_name = "file",
|
||||
.instance_size = sizeof(BDRVRawState),
|
||||
.bdrv_needs_filename = true,
|
||||
.bdrv_probe = NULL, /* no probe for protocols */
|
||||
.bdrv_file_open = raw_open,
|
||||
.bdrv_reopen_prepare = raw_reopen_prepare,
|
||||
@@ -1542,6 +1543,7 @@ static BlockDriver bdrv_host_device = {
|
||||
.format_name = "host_device",
|
||||
.protocol_name = "host_device",
|
||||
.instance_size = sizeof(BDRVRawState),
|
||||
.bdrv_needs_filename = true,
|
||||
.bdrv_probe_device = hdev_probe_device,
|
||||
.bdrv_file_open = hdev_open,
|
||||
.bdrv_close = raw_close,
|
||||
@@ -1667,6 +1669,7 @@ static BlockDriver bdrv_host_floppy = {
|
||||
.format_name = "host_floppy",
|
||||
.protocol_name = "host_floppy",
|
||||
.instance_size = sizeof(BDRVRawState),
|
||||
.bdrv_needs_filename = true,
|
||||
.bdrv_probe_device = floppy_probe_device,
|
||||
.bdrv_file_open = floppy_open,
|
||||
.bdrv_close = raw_close,
|
||||
@@ -1769,6 +1772,7 @@ static BlockDriver bdrv_host_cdrom = {
|
||||
.format_name = "host_cdrom",
|
||||
.protocol_name = "host_cdrom",
|
||||
.instance_size = sizeof(BDRVRawState),
|
||||
.bdrv_needs_filename = true,
|
||||
.bdrv_probe_device = cdrom_probe_device,
|
||||
.bdrv_file_open = cdrom_open,
|
||||
.bdrv_close = raw_close,
|
||||
@@ -1890,6 +1894,7 @@ static BlockDriver bdrv_host_cdrom = {
|
||||
.format_name = "host_cdrom",
|
||||
.protocol_name = "host_cdrom",
|
||||
.instance_size = sizeof(BDRVRawState),
|
||||
.bdrv_needs_filename = true,
|
||||
.bdrv_probe_device = cdrom_probe_device,
|
||||
.bdrv_file_open = cdrom_open,
|
||||
.bdrv_close = raw_close,
|
||||
|
||||
@@ -459,6 +459,7 @@ static BlockDriver bdrv_file = {
|
||||
.format_name = "file",
|
||||
.protocol_name = "file",
|
||||
.instance_size = sizeof(BDRVRawState),
|
||||
.bdrv_needs_filename = true,
|
||||
.bdrv_file_open = raw_open,
|
||||
.bdrv_close = raw_close,
|
||||
.bdrv_create = raw_create,
|
||||
@@ -601,6 +602,7 @@ static BlockDriver bdrv_host_device = {
|
||||
.format_name = "host_device",
|
||||
.protocol_name = "host_device",
|
||||
.instance_size = sizeof(BDRVRawState),
|
||||
.bdrv_needs_filename = true,
|
||||
.bdrv_probe_device = hdev_probe_device,
|
||||
.bdrv_file_open = hdev_open,
|
||||
.bdrv_close = raw_close,
|
||||
|
||||
+3
-1
@@ -943,7 +943,7 @@ static int qemu_rbd_snap_list(BlockDriverState *bs,
|
||||
do {
|
||||
snaps = g_malloc(sizeof(*snaps) * max_snaps);
|
||||
snap_count = rbd_snap_list(s->image, snaps, &max_snaps);
|
||||
if (snap_count < 0) {
|
||||
if (snap_count <= 0) {
|
||||
g_free(snaps);
|
||||
}
|
||||
} while (snap_count == -ERANGE);
|
||||
@@ -967,6 +967,7 @@ static int qemu_rbd_snap_list(BlockDriverState *bs,
|
||||
sn_info->vm_clock_nsec = 0;
|
||||
}
|
||||
rbd_snap_list_end(snaps);
|
||||
g_free(snaps);
|
||||
|
||||
done:
|
||||
*psn_tab = sn_tab;
|
||||
@@ -1002,6 +1003,7 @@ static QEMUOptionParameter qemu_rbd_create_options[] = {
|
||||
static BlockDriver bdrv_rbd = {
|
||||
.format_name = "rbd",
|
||||
.instance_size = sizeof(BDRVRBDState),
|
||||
.bdrv_needs_filename = true,
|
||||
.bdrv_file_open = qemu_rbd_open,
|
||||
.bdrv_close = qemu_rbd_close,
|
||||
.bdrv_create = qemu_rbd_create,
|
||||
|
||||
@@ -2338,6 +2338,7 @@ static BlockDriver bdrv_sheepdog = {
|
||||
.format_name = "sheepdog",
|
||||
.protocol_name = "sheepdog",
|
||||
.instance_size = sizeof(BDRVSheepdogState),
|
||||
.bdrv_needs_filename = true,
|
||||
.bdrv_file_open = sd_open,
|
||||
.bdrv_close = sd_close,
|
||||
.bdrv_create = sd_create,
|
||||
@@ -2366,6 +2367,7 @@ static BlockDriver bdrv_sheepdog_tcp = {
|
||||
.format_name = "sheepdog",
|
||||
.protocol_name = "sheepdog+tcp",
|
||||
.instance_size = sizeof(BDRVSheepdogState),
|
||||
.bdrv_needs_filename = true,
|
||||
.bdrv_file_open = sd_open,
|
||||
.bdrv_close = sd_close,
|
||||
.bdrv_create = sd_create,
|
||||
@@ -2394,6 +2396,7 @@ static BlockDriver bdrv_sheepdog_unix = {
|
||||
.format_name = "sheepdog",
|
||||
.protocol_name = "sheepdog+unix",
|
||||
.instance_size = sizeof(BDRVSheepdogState),
|
||||
.bdrv_needs_filename = true,
|
||||
.bdrv_file_open = sd_open,
|
||||
.bdrv_close = sd_close,
|
||||
.bdrv_create = sd_create,
|
||||
|
||||
+3
-2
@@ -119,11 +119,12 @@ wait:
|
||||
break;
|
||||
}
|
||||
|
||||
copy = false;
|
||||
|
||||
ret = bdrv_is_allocated(bs, sector_num,
|
||||
STREAM_BUFFER_SIZE / BDRV_SECTOR_SIZE, &n);
|
||||
if (ret == 1) {
|
||||
/* Allocated in the top, no need to copy. */
|
||||
copy = false;
|
||||
} else if (ret >= 0) {
|
||||
/* Copy if allocated in the intermediate images. Limit to the
|
||||
* known-unallocated area [sector_num, sector_num+n). */
|
||||
@@ -138,7 +139,7 @@ wait:
|
||||
copy = (ret == 1);
|
||||
}
|
||||
trace_stream_one_iteration(s, sector_num, n, ret);
|
||||
if (ret >= 0 && copy) {
|
||||
if (copy) {
|
||||
if (s->common.speed) {
|
||||
delay_ns = ratelimit_calculate_delay(&s->limit, n);
|
||||
if (delay_ns > 0) {
|
||||
|
||||
+1
-1
@@ -165,7 +165,7 @@ typedef struct {
|
||||
uuid_t uuid_link;
|
||||
uuid_t uuid_parent;
|
||||
uint64_t unused2[7];
|
||||
} VdiHeader;
|
||||
} QEMU_PACKED VdiHeader;
|
||||
|
||||
typedef struct {
|
||||
/* The block map entries are little endian (even in memory). */
|
||||
|
||||
+3
-3
@@ -105,7 +105,7 @@ typedef struct VmdkExtent {
|
||||
uint32_t l2_cache_offsets[L2_CACHE_SIZE];
|
||||
uint32_t l2_cache_counts[L2_CACHE_SIZE];
|
||||
|
||||
unsigned int cluster_sectors;
|
||||
int64_t cluster_sectors;
|
||||
} VmdkExtent;
|
||||
|
||||
typedef struct BDRVVmdkState {
|
||||
@@ -424,7 +424,7 @@ static int vmdk_add_extent(BlockDriverState *bs,
|
||||
extent->l1_size = l1_size;
|
||||
extent->l1_entry_sectors = l2_size * cluster_sectors;
|
||||
extent->l2_size = l2_size;
|
||||
extent->cluster_sectors = cluster_sectors;
|
||||
extent->cluster_sectors = flat ? sectors : cluster_sectors;
|
||||
|
||||
if (s->num_extents > 1) {
|
||||
extent->end_sector = (*(extent - 1)).end_sector + extent->sectors;
|
||||
@@ -741,7 +741,7 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
|
||||
VmdkExtent *extent;
|
||||
|
||||
ret = vmdk_add_extent(bs, extent_file, true, sectors,
|
||||
0, 0, 0, 0, sectors, &extent);
|
||||
0, 0, 0, 0, 0, &extent);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
+14
-14
@@ -46,7 +46,7 @@ enum vhd_type {
|
||||
#define VHD_TIMESTAMP_BASE 946684800
|
||||
|
||||
// always big-endian
|
||||
struct vhd_footer {
|
||||
typedef struct vhd_footer {
|
||||
char creator[8]; // "conectix"
|
||||
uint32_t features;
|
||||
uint32_t version;
|
||||
@@ -79,9 +79,9 @@ struct vhd_footer {
|
||||
uint8_t uuid[16];
|
||||
|
||||
uint8_t in_saved_state;
|
||||
};
|
||||
} QEMU_PACKED VHDFooter;
|
||||
|
||||
struct vhd_dyndisk_header {
|
||||
typedef struct vhd_dyndisk_header {
|
||||
char magic[8]; // "cxsparse"
|
||||
|
||||
// Offset of next header structure, 0xFFFFFFFF if none
|
||||
@@ -111,7 +111,7 @@ struct vhd_dyndisk_header {
|
||||
uint32_t reserved;
|
||||
uint64_t data_offset;
|
||||
} parent_locator[8];
|
||||
};
|
||||
} QEMU_PACKED VHDDynDiskHeader;
|
||||
|
||||
typedef struct BDRVVPCState {
|
||||
CoMutex lock;
|
||||
@@ -160,8 +160,8 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
{
|
||||
BDRVVPCState *s = bs->opaque;
|
||||
int i;
|
||||
struct vhd_footer* footer;
|
||||
struct vhd_dyndisk_header* dyndisk_header;
|
||||
VHDFooter *footer;
|
||||
VHDDynDiskHeader *dyndisk_header;
|
||||
uint8_t buf[HEADER_SIZE];
|
||||
uint32_t checksum;
|
||||
int disk_type = VHD_DYNAMIC;
|
||||
@@ -172,7 +172,7 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
footer = (struct vhd_footer*) s->footer_buf;
|
||||
footer = (VHDFooter *) s->footer_buf;
|
||||
if (strncmp(footer->creator, "conectix", 8)) {
|
||||
int64_t offset = bdrv_getlength(bs->file);
|
||||
if (offset < 0) {
|
||||
@@ -224,7 +224,7 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
dyndisk_header = (struct vhd_dyndisk_header *) buf;
|
||||
dyndisk_header = (VHDDynDiskHeader *) buf;
|
||||
|
||||
if (strncmp(dyndisk_header->magic, "cxsparse", 8)) {
|
||||
ret = -EINVAL;
|
||||
@@ -446,7 +446,7 @@ static int vpc_read(BlockDriverState *bs, int64_t sector_num,
|
||||
int ret;
|
||||
int64_t offset;
|
||||
int64_t sectors, sectors_per_block;
|
||||
struct vhd_footer *footer = (struct vhd_footer *) s->footer_buf;
|
||||
VHDFooter *footer = (VHDFooter *) s->footer_buf;
|
||||
|
||||
if (cpu_to_be32(footer->type) == VHD_FIXED) {
|
||||
return bdrv_read(bs->file, sector_num, buf, nb_sectors);
|
||||
@@ -495,7 +495,7 @@ static int vpc_write(BlockDriverState *bs, int64_t sector_num,
|
||||
int64_t offset;
|
||||
int64_t sectors, sectors_per_block;
|
||||
int ret;
|
||||
struct vhd_footer *footer = (struct vhd_footer *) s->footer_buf;
|
||||
VHDFooter *footer = (VHDFooter *) s->footer_buf;
|
||||
|
||||
if (cpu_to_be32(footer->type) == VHD_FIXED) {
|
||||
return bdrv_write(bs->file, sector_num, buf, nb_sectors);
|
||||
@@ -597,8 +597,8 @@ static int calculate_geometry(int64_t total_sectors, uint16_t* cyls,
|
||||
|
||||
static int create_dynamic_disk(int fd, uint8_t *buf, int64_t total_sectors)
|
||||
{
|
||||
struct vhd_dyndisk_header* dyndisk_header =
|
||||
(struct vhd_dyndisk_header*) buf;
|
||||
VHDDynDiskHeader *dyndisk_header =
|
||||
(VHDDynDiskHeader *) buf;
|
||||
size_t block_size, num_bat_entries;
|
||||
int i;
|
||||
int ret = -EIO;
|
||||
@@ -688,7 +688,7 @@ static int vpc_create(const char *filename, QEMUOptionParameter *options,
|
||||
Error **errp)
|
||||
{
|
||||
uint8_t buf[1024];
|
||||
struct vhd_footer *footer = (struct vhd_footer *) buf;
|
||||
VHDFooter *footer = (VHDFooter *) buf;
|
||||
QEMUOptionParameter *disk_type_param;
|
||||
int fd, i;
|
||||
uint16_t cyls = 0;
|
||||
@@ -791,7 +791,7 @@ static int vpc_create(const char *filename, QEMUOptionParameter *options,
|
||||
static int vpc_has_zero_init(BlockDriverState *bs)
|
||||
{
|
||||
BDRVVPCState *s = bs->opaque;
|
||||
struct vhd_footer *footer = (struct vhd_footer *) s->footer_buf;
|
||||
VHDFooter *footer = (VHDFooter *) s->footer_buf;
|
||||
|
||||
if (cpu_to_be32(footer->type) == VHD_FIXED) {
|
||||
return bdrv_has_zero_init(bs->file);
|
||||
|
||||
@@ -73,6 +73,12 @@ struct BlockDriver {
|
||||
/* Any driver implementing this callback is expected to be able to handle
|
||||
* NULL file names in its .bdrv_open() implementation */
|
||||
void (*bdrv_parse_filename)(const char *filename, QDict *options, Error **errp);
|
||||
/* Drivers not implementing bdrv_parse_filename nor bdrv_open should have
|
||||
* this field set to true, except ones that are defined only by their
|
||||
* child's bs.
|
||||
* An example of the last type will be the quorum block driver.
|
||||
*/
|
||||
bool bdrv_needs_filename;
|
||||
|
||||
/* For handling image reopen for split or non-split files */
|
||||
int (*bdrv_reopen_prepare)(BDRVReopenState *reopen_state,
|
||||
|
||||
@@ -67,4 +67,6 @@ const char *qdict_get_try_str(const QDict *qdict, const char *key);
|
||||
QDict *qdict_clone_shallow(const QDict *src);
|
||||
void qdict_flatten(QDict *qdict);
|
||||
|
||||
void qdict_extract_subqdict(QDict *src, QDict **dst, const char *start);
|
||||
|
||||
#endif /* QDICT_H */
|
||||
|
||||
@@ -527,3 +527,24 @@ void qdict_flatten(QDict *qdict)
|
||||
{
|
||||
qdict_do_flatten(qdict, qdict, NULL);
|
||||
}
|
||||
|
||||
/* extract all the src QDict entries starting by start into dst */
|
||||
void qdict_extract_subqdict(QDict *src, QDict **dst, const char *start)
|
||||
|
||||
{
|
||||
const QDictEntry *entry, *next;
|
||||
const char *p;
|
||||
|
||||
*dst = qdict_new();
|
||||
entry = qdict_first(src);
|
||||
|
||||
while (entry != NULL) {
|
||||
next = qdict_next(src, entry);
|
||||
if (strstart(entry->key, start, &p)) {
|
||||
qobject_incref(entry->value);
|
||||
qdict_put_obj(*dst, p, entry->value);
|
||||
qdict_del(src, entry->key);
|
||||
}
|
||||
entry = next;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,15 +48,15 @@ _make_test_img $size
|
||||
|
||||
echo
|
||||
echo "== reading whole image =="
|
||||
$QEMU_IO -c "read 0 $size" $TEST_IMG | _filter_qemu_io
|
||||
$QEMU_IO -c "read 0 $size" "$TEST_IMG" | _filter_qemu_io
|
||||
|
||||
echo
|
||||
echo "== rewriting whole image =="
|
||||
$QEMU_IO -c "write -P 0xa 0 $size" $TEST_IMG | _filter_qemu_io
|
||||
$QEMU_IO -c "write -P 0xa 0 $size" "$TEST_IMG" | _filter_qemu_io
|
||||
|
||||
echo
|
||||
echo "== verify pattern =="
|
||||
$QEMU_IO -c "read -P 0xa 0 $size" $TEST_IMG | _filter_qemu_io
|
||||
$QEMU_IO -c "read -P 0xa 0 $size" "$TEST_IMG" | _filter_qemu_io
|
||||
|
||||
|
||||
# success, all done
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user