Merge remote-tracking branch 'kwolf/for-anthony' into staging
* kwolf/for-anthony: virtio-blk: hide VIRTIO_BLK_F_CONFIG_WCE from old machine types Documentation: Warn against qemu-img on active image vmdk: Read footer for streamOptimized images vmdk: Fix header structure Conflicts: hw/virtio-blk.c
This commit is contained in:
commit
7b2f89c435
58
block/vmdk.c
58
block/vmdk.c
@ -35,6 +35,7 @@
|
|||||||
#define VMDK4_FLAG_RGD (1 << 1)
|
#define VMDK4_FLAG_RGD (1 << 1)
|
||||||
#define VMDK4_FLAG_COMPRESS (1 << 16)
|
#define VMDK4_FLAG_COMPRESS (1 << 16)
|
||||||
#define VMDK4_FLAG_MARKER (1 << 17)
|
#define VMDK4_FLAG_MARKER (1 << 17)
|
||||||
|
#define VMDK4_GD_AT_END 0xffffffffffffffffULL
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t version;
|
uint32_t version;
|
||||||
@ -57,8 +58,8 @@ typedef struct {
|
|||||||
int64_t desc_offset;
|
int64_t desc_offset;
|
||||||
int64_t desc_size;
|
int64_t desc_size;
|
||||||
int32_t num_gtes_per_gte;
|
int32_t num_gtes_per_gte;
|
||||||
int64_t gd_offset;
|
|
||||||
int64_t rgd_offset;
|
int64_t rgd_offset;
|
||||||
|
int64_t gd_offset;
|
||||||
int64_t grain_offset;
|
int64_t grain_offset;
|
||||||
char filler[1];
|
char filler[1];
|
||||||
char check_bytes[4];
|
char check_bytes[4];
|
||||||
@ -115,6 +116,13 @@ typedef struct VmdkGrainMarker {
|
|||||||
uint8_t data[0];
|
uint8_t data[0];
|
||||||
} VmdkGrainMarker;
|
} VmdkGrainMarker;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
MARKER_END_OF_STREAM = 0,
|
||||||
|
MARKER_GRAIN_TABLE = 1,
|
||||||
|
MARKER_GRAIN_DIRECTORY = 2,
|
||||||
|
MARKER_FOOTER = 3,
|
||||||
|
};
|
||||||
|
|
||||||
static int vmdk_probe(const uint8_t *buf, int buf_size, const char *filename)
|
static int vmdk_probe(const uint8_t *buf, int buf_size, const char *filename)
|
||||||
{
|
{
|
||||||
uint32_t magic;
|
uint32_t magic;
|
||||||
@ -451,6 +459,54 @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
|
|||||||
if (header.capacity == 0 && header.desc_offset) {
|
if (header.capacity == 0 && header.desc_offset) {
|
||||||
return vmdk_open_desc_file(bs, flags, header.desc_offset << 9);
|
return vmdk_open_desc_file(bs, flags, header.desc_offset << 9);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (le64_to_cpu(header.gd_offset) == VMDK4_GD_AT_END) {
|
||||||
|
/*
|
||||||
|
* The footer takes precedence over the header, so read it in. The
|
||||||
|
* footer starts at offset -1024 from the end: One sector for the
|
||||||
|
* footer, and another one for the end-of-stream marker.
|
||||||
|
*/
|
||||||
|
struct {
|
||||||
|
struct {
|
||||||
|
uint64_t val;
|
||||||
|
uint32_t size;
|
||||||
|
uint32_t type;
|
||||||
|
uint8_t pad[512 - 16];
|
||||||
|
} QEMU_PACKED footer_marker;
|
||||||
|
|
||||||
|
uint32_t magic;
|
||||||
|
VMDK4Header header;
|
||||||
|
uint8_t pad[512 - 4 - sizeof(VMDK4Header)];
|
||||||
|
|
||||||
|
struct {
|
||||||
|
uint64_t val;
|
||||||
|
uint32_t size;
|
||||||
|
uint32_t type;
|
||||||
|
uint8_t pad[512 - 16];
|
||||||
|
} QEMU_PACKED eos_marker;
|
||||||
|
} QEMU_PACKED footer;
|
||||||
|
|
||||||
|
ret = bdrv_pread(file,
|
||||||
|
bs->file->total_sectors * 512 - 1536,
|
||||||
|
&footer, sizeof(footer));
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Some sanity checks for the footer */
|
||||||
|
if (be32_to_cpu(footer.magic) != VMDK4_MAGIC ||
|
||||||
|
le32_to_cpu(footer.footer_marker.size) != 0 ||
|
||||||
|
le32_to_cpu(footer.footer_marker.type) != MARKER_FOOTER ||
|
||||||
|
le64_to_cpu(footer.eos_marker.val) != 0 ||
|
||||||
|
le32_to_cpu(footer.eos_marker.size) != 0 ||
|
||||||
|
le32_to_cpu(footer.eos_marker.type) != MARKER_END_OF_STREAM)
|
||||||
|
{
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
header = footer.header;
|
||||||
|
}
|
||||||
|
|
||||||
l1_entry_sectors = le32_to_cpu(header.num_gtes_per_gte)
|
l1_entry_sectors = le32_to_cpu(header.num_gtes_per_gte)
|
||||||
* le64_to_cpu(header.granularity);
|
* le64_to_cpu(header.granularity);
|
||||||
if (l1_entry_sectors == 0) {
|
if (l1_entry_sectors == 0) {
|
||||||
|
@ -104,6 +104,7 @@ struct VirtIOBlkConf
|
|||||||
BlockConf conf;
|
BlockConf conf;
|
||||||
char *serial;
|
char *serial;
|
||||||
uint32_t scsi;
|
uint32_t scsi;
|
||||||
|
uint32_t config_wce;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DEFINE_VIRTIO_BLK_FEATURES(_state, _field) \
|
#define DEFINE_VIRTIO_BLK_FEATURES(_state, _field) \
|
||||||
|
@ -886,6 +886,7 @@ static Property virtio_blk_properties[] = {
|
|||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
DEFINE_PROP_BIT("scsi", VirtIOPCIProxy, blk.scsi, 0, true),
|
DEFINE_PROP_BIT("scsi", VirtIOPCIProxy, blk.scsi, 0, true),
|
||||||
#endif
|
#endif
|
||||||
|
DEFINE_PROP_BIT("config-wce", VirtIOPCIProxy, blk.config_wce, 0, true),
|
||||||
DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
|
DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
|
||||||
DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
|
DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
|
||||||
DEFINE_VIRTIO_BLK_FEATURES(VirtIOPCIProxy, host_features),
|
DEFINE_VIRTIO_BLK_FEATURES(VirtIOPCIProxy, host_features),
|
||||||
|
@ -4,6 +4,16 @@ usage: qemu-img command [command options]
|
|||||||
@c man end
|
@c man end
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
|
@c man begin DESCRIPTION
|
||||||
|
qemu-img allows you to create, convert and modify images offline. It can handle
|
||||||
|
all image formats supported by QEMU.
|
||||||
|
|
||||||
|
@b{Warning:} Never use qemu-img to modify images in use by a running virtual
|
||||||
|
machine or any other process; this may destroy the image. Also, be aware that
|
||||||
|
querying an image that is being modified by another process may encounter
|
||||||
|
inconsistent state.
|
||||||
|
@c man end
|
||||||
|
|
||||||
@c man begin OPTIONS
|
@c man begin OPTIONS
|
||||||
|
|
||||||
The following commands are supported:
|
The following commands are supported:
|
||||||
|
Loading…
Reference in New Issue
Block a user