Pull request
-----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEE+ber27ys35W+dsvQfe+BBqr8OQ4FAl27BAAACgkQfe+BBqr8 OQ61RRAAiAbfuWvaQ/IiK08o3JZ60Qu4Ph8iO0cSM03vfZ6WqWBlAPsa2d/nkwBf qR61Yp5+5NVNo/YLZHM7sNPd7ZsnDiagRNAZEirqP6FsjPcae2sBkaB27TYrBccv 51ee4zr4f3T6SWeHheIa208FBmS6waIukRUT6DpkzPIysue/nbHTg9/zUhooUFCO cJB74d+x7jSDfwAPDZEDzVkB8HgFSZrK4Ou6QZiNndhu4uTIL6us1zJvZrM/ctP7 c1B0eUYjKYdk+IWvUwxCvq5K7CFxZOUt3faUahXJuTlj6AS7mQ2OcSnWtXfbwWxl KoDKhP4F6rmQT3x4Eq5bcMN7K4yqB6jH9fEFecmgRXV2VBBVLTITlqPma+MBY6Sv 2zifrBOv6OPE1aAQTW+eJJtlb75O9xB393eC1yjJL4zHpjeKLgJ4CJ+8R3FR4OO/ 01uIIeVpNABb0ijRLmSsPNMNt15cj7KWUsYI4PfLqOXsV/c2CT5qC3DtuxMxhSLV vxXxTctXsji5ocT0GqISLURv5CSM/rmQjMgK84a1t/DN2eqv4eJnKwi4JItnmfYI me9Y8tyBERrMc0WytJ8V3s9v7Fgajq+m0tPAzebdk/w7ebcfJfX9UzbRPG3BXiXd S3ovZoBqN43pEGlIszJ8zAHRXDXyFADkbkqnqx8HA3f2slIaiE8= =Y9mz -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/jnsnow/tags/ide-pull-request' into staging Pull request # gpg: Signature made Thu 31 Oct 2019 15:55:44 GMT # gpg: using RSA key F9B7ABDBBCACDF95BE76CBD07DEF8106AAFC390E # gpg: Good signature from "John Snow (John Huston) <jsnow@redhat.com>" [full] # Primary key fingerprint: FAEB 9711 A12C F475 812F 18F2 88A9 064D 1835 61EB # Subkey fingerprint: F9B7 ABDB BCAC DF95 BE76 CBD0 7DEF 8106 AAFC 390E * remotes/jnsnow/tags/ide-pull-request: hd-geo-test: Add tests for lchs override bootdevice: FW_CFG interface for LCHS values bootdevice: Refactor get_boot_devices_list bootdevice: Gather LCHS from all relevant devices scsi: Propagate unrealize() callback to scsi-hd bootdevice: Add interface to gather LCHS block: Support providing LCHS from user block: Refactor macros - fix tabbing IDE: deprecate ide-drive Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
b7c9a7f353
147
bootdevice.c
147
bootdevice.c
@ -202,6 +202,39 @@ DeviceState *get_boot_device(uint32_t position)
|
||||
return res;
|
||||
}
|
||||
|
||||
static char *get_boot_device_path(DeviceState *dev, bool ignore_suffixes,
|
||||
const char *suffix)
|
||||
{
|
||||
char *devpath = NULL, *s = NULL, *d, *bootpath;
|
||||
|
||||
if (dev) {
|
||||
devpath = qdev_get_fw_dev_path(dev);
|
||||
assert(devpath);
|
||||
}
|
||||
|
||||
if (!ignore_suffixes) {
|
||||
if (dev) {
|
||||
d = qdev_get_own_fw_dev_path_from_handler(dev->parent_bus, dev);
|
||||
if (d) {
|
||||
assert(!suffix);
|
||||
s = d;
|
||||
} else {
|
||||
s = g_strdup(suffix);
|
||||
}
|
||||
} else {
|
||||
s = g_strdup(suffix);
|
||||
}
|
||||
}
|
||||
|
||||
bootpath = g_strdup_printf("%s%s",
|
||||
devpath ? devpath : "",
|
||||
s ? s : "");
|
||||
g_free(devpath);
|
||||
g_free(s);
|
||||
|
||||
return bootpath;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function returns null terminated string that consist of new line
|
||||
* separated device paths.
|
||||
@ -218,36 +251,10 @@ char *get_boot_devices_list(size_t *size)
|
||||
bool ignore_suffixes = mc->ignore_boot_device_suffixes;
|
||||
|
||||
QTAILQ_FOREACH(i, &fw_boot_order, link) {
|
||||
char *devpath = NULL, *suffix = NULL;
|
||||
char *bootpath;
|
||||
char *d;
|
||||
size_t len;
|
||||
|
||||
if (i->dev) {
|
||||
devpath = qdev_get_fw_dev_path(i->dev);
|
||||
assert(devpath);
|
||||
}
|
||||
|
||||
if (!ignore_suffixes) {
|
||||
if (i->dev) {
|
||||
d = qdev_get_own_fw_dev_path_from_handler(i->dev->parent_bus,
|
||||
i->dev);
|
||||
if (d) {
|
||||
assert(!i->suffix);
|
||||
suffix = d;
|
||||
} else {
|
||||
suffix = g_strdup(i->suffix);
|
||||
}
|
||||
} else {
|
||||
suffix = g_strdup(i->suffix);
|
||||
}
|
||||
}
|
||||
|
||||
bootpath = g_strdup_printf("%s%s",
|
||||
devpath ? devpath : "",
|
||||
suffix ? suffix : "");
|
||||
g_free(devpath);
|
||||
g_free(suffix);
|
||||
bootpath = get_boot_device_path(i->dev, ignore_suffixes, i->suffix);
|
||||
|
||||
if (total) {
|
||||
list[total-1] = '\n';
|
||||
@ -343,3 +350,89 @@ void device_add_bootindex_property(Object *obj, int32_t *bootindex,
|
||||
/* initialize devices' bootindex property to -1 */
|
||||
object_property_set_int(obj, -1, name, NULL);
|
||||
}
|
||||
|
||||
typedef struct FWLCHSEntry FWLCHSEntry;
|
||||
|
||||
struct FWLCHSEntry {
|
||||
QTAILQ_ENTRY(FWLCHSEntry) link;
|
||||
DeviceState *dev;
|
||||
char *suffix;
|
||||
uint32_t lcyls;
|
||||
uint32_t lheads;
|
||||
uint32_t lsecs;
|
||||
};
|
||||
|
||||
static QTAILQ_HEAD(, FWLCHSEntry) fw_lchs =
|
||||
QTAILQ_HEAD_INITIALIZER(fw_lchs);
|
||||
|
||||
void add_boot_device_lchs(DeviceState *dev, const char *suffix,
|
||||
uint32_t lcyls, uint32_t lheads, uint32_t lsecs)
|
||||
{
|
||||
FWLCHSEntry *node;
|
||||
|
||||
if (!lcyls && !lheads && !lsecs) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert(dev != NULL || suffix != NULL);
|
||||
|
||||
node = g_malloc0(sizeof(FWLCHSEntry));
|
||||
node->suffix = g_strdup(suffix);
|
||||
node->dev = dev;
|
||||
node->lcyls = lcyls;
|
||||
node->lheads = lheads;
|
||||
node->lsecs = lsecs;
|
||||
|
||||
QTAILQ_INSERT_TAIL(&fw_lchs, node, link);
|
||||
}
|
||||
|
||||
void del_boot_device_lchs(DeviceState *dev, const char *suffix)
|
||||
{
|
||||
FWLCHSEntry *i;
|
||||
|
||||
if (dev == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
QTAILQ_FOREACH(i, &fw_lchs, link) {
|
||||
if ((!suffix || !g_strcmp0(i->suffix, suffix)) &&
|
||||
i->dev == dev) {
|
||||
QTAILQ_REMOVE(&fw_lchs, i, link);
|
||||
g_free(i->suffix);
|
||||
g_free(i);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char *get_boot_devices_lchs_list(size_t *size)
|
||||
{
|
||||
FWLCHSEntry *i;
|
||||
size_t total = 0;
|
||||
char *list = NULL;
|
||||
|
||||
QTAILQ_FOREACH(i, &fw_lchs, link) {
|
||||
char *bootpath;
|
||||
char *chs_string;
|
||||
size_t len;
|
||||
|
||||
bootpath = get_boot_device_path(i->dev, false, i->suffix);
|
||||
chs_string = g_strdup_printf("%s %" PRIu32 " %" PRIu32 " %" PRIu32,
|
||||
bootpath, i->lcyls, i->lheads, i->lsecs);
|
||||
|
||||
if (total) {
|
||||
list[total - 1] = '\n';
|
||||
}
|
||||
len = strlen(chs_string) + 1;
|
||||
list = g_realloc(list, total + len);
|
||||
memcpy(&list[total], chs_string, len);
|
||||
total += len;
|
||||
g_free(chs_string);
|
||||
g_free(bootpath);
|
||||
}
|
||||
|
||||
*size = total;
|
||||
|
||||
return list;
|
||||
}
|
||||
|
@ -1200,6 +1200,11 @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp)
|
||||
blk_set_guest_block_size(s->blk, s->conf.conf.logical_block_size);
|
||||
|
||||
blk_iostatus_enable(s->blk);
|
||||
|
||||
add_boot_device_lchs(dev, "/disk@0,0",
|
||||
conf->conf.lcyls,
|
||||
conf->conf.lheads,
|
||||
conf->conf.lsecs);
|
||||
}
|
||||
|
||||
static void virtio_blk_device_unrealize(DeviceState *dev, Error **errp)
|
||||
@ -1210,6 +1215,7 @@ static void virtio_blk_device_unrealize(DeviceState *dev, Error **errp)
|
||||
unsigned i;
|
||||
|
||||
blk_drain(s->blk);
|
||||
del_boot_device_lchs(dev, "/disk@0,0");
|
||||
virtio_blk_data_plane_destroy(s->dataplane);
|
||||
s->dataplane = NULL;
|
||||
for (i = 0; i < conf->num_queues; i++) {
|
||||
|
@ -220,6 +220,11 @@ static void ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind, Error **errp)
|
||||
|
||||
add_boot_device_path(dev->conf.bootindex, &dev->qdev,
|
||||
dev->unit ? "/disk@1" : "/disk@0");
|
||||
|
||||
add_boot_device_lchs(&dev->qdev, dev->unit ? "/disk@1" : "/disk@0",
|
||||
dev->conf.lcyls,
|
||||
dev->conf.lheads,
|
||||
dev->conf.lsecs);
|
||||
}
|
||||
|
||||
static void ide_dev_get_bootindex(Object *obj, Visitor *v, const char *name,
|
||||
@ -279,6 +284,9 @@ static void ide_drive_realize(IDEDevice *dev, Error **errp)
|
||||
{
|
||||
DriveInfo *dinfo = NULL;
|
||||
|
||||
warn_report("'ide-drive' is deprecated, "
|
||||
"please use 'ide-hd' or 'ide-cd' instead");
|
||||
|
||||
if (dev->conf.blk) {
|
||||
dinfo = blk_legacy_dinfo(dev->conf.blk);
|
||||
}
|
||||
@ -290,7 +298,7 @@ static void ide_drive_realize(IDEDevice *dev, Error **errp)
|
||||
DEFINE_BLOCK_PROPERTIES(IDEDrive, dev.conf), \
|
||||
DEFINE_BLOCK_ERROR_PROPERTIES(IDEDrive, dev.conf), \
|
||||
DEFINE_PROP_STRING("ver", IDEDrive, dev.version), \
|
||||
DEFINE_PROP_UINT64("wwn", IDEDrive, dev.wwn, 0), \
|
||||
DEFINE_PROP_UINT64("wwn", IDEDrive, dev.wwn, 0), \
|
||||
DEFINE_PROP_STRING("serial", IDEDrive, dev.serial),\
|
||||
DEFINE_PROP_STRING("model", IDEDrive, dev.model)
|
||||
|
||||
|
@ -949,13 +949,21 @@ void *fw_cfg_modify_file(FWCfgState *s, const char *filename,
|
||||
|
||||
static void fw_cfg_machine_reset(void *opaque)
|
||||
{
|
||||
MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine());
|
||||
FWCfgState *s = opaque;
|
||||
void *ptr;
|
||||
size_t len;
|
||||
FWCfgState *s = opaque;
|
||||
char *bootindex = get_boot_devices_list(&len);
|
||||
char *buf;
|
||||
|
||||
ptr = fw_cfg_modify_file(s, "bootorder", (uint8_t *)bootindex, len);
|
||||
buf = get_boot_devices_list(&len);
|
||||
ptr = fw_cfg_modify_file(s, "bootorder", (uint8_t *)buf, len);
|
||||
g_free(ptr);
|
||||
|
||||
if (!mc->legacy_fw_cfg_order) {
|
||||
buf = get_boot_devices_lchs_list(&len);
|
||||
ptr = fw_cfg_modify_file(s, "bios-geometry", (uint8_t *)buf, len);
|
||||
g_free(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
static void fw_cfg_machine_ready(struct Notifier *n, void *data)
|
||||
|
@ -59,6 +59,14 @@ static void scsi_device_realize(SCSIDevice *s, Error **errp)
|
||||
}
|
||||
}
|
||||
|
||||
static void scsi_device_unrealize(SCSIDevice *s, Error **errp)
|
||||
{
|
||||
SCSIDeviceClass *sc = SCSI_DEVICE_GET_CLASS(s);
|
||||
if (sc->unrealize) {
|
||||
sc->unrealize(s, errp);
|
||||
}
|
||||
}
|
||||
|
||||
int scsi_bus_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf,
|
||||
void *hba_private)
|
||||
{
|
||||
@ -217,12 +225,20 @@ static void scsi_qdev_realize(DeviceState *qdev, Error **errp)
|
||||
static void scsi_qdev_unrealize(DeviceState *qdev, Error **errp)
|
||||
{
|
||||
SCSIDevice *dev = SCSI_DEVICE(qdev);
|
||||
Error *local_err = NULL;
|
||||
|
||||
if (dev->vmsentry) {
|
||||
qemu_del_vm_change_state_handler(dev->vmsentry);
|
||||
}
|
||||
|
||||
scsi_device_purge_requests(dev, SENSE_CODE(NO_SENSE));
|
||||
|
||||
scsi_device_unrealize(dev, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
|
||||
blockdev_mark_auto_del(dev->conf.blk);
|
||||
}
|
||||
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "hw/block/block.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "sysemu/dma.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "trace.h"
|
||||
|
||||
@ -2414,6 +2415,16 @@ static void scsi_realize(SCSIDevice *dev, Error **errp)
|
||||
blk_set_guest_block_size(s->qdev.conf.blk, s->qdev.blocksize);
|
||||
|
||||
blk_iostatus_enable(s->qdev.conf.blk);
|
||||
|
||||
add_boot_device_lchs(&dev->qdev, NULL,
|
||||
dev->conf.lcyls,
|
||||
dev->conf.lheads,
|
||||
dev->conf.lsecs);
|
||||
}
|
||||
|
||||
static void scsi_unrealize(SCSIDevice *dev, Error **errp)
|
||||
{
|
||||
del_boot_device_lchs(&dev->qdev, NULL);
|
||||
}
|
||||
|
||||
static void scsi_hd_realize(SCSIDevice *dev, Error **errp)
|
||||
@ -3018,6 +3029,7 @@ static void scsi_hd_class_initfn(ObjectClass *klass, void *data)
|
||||
SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass);
|
||||
|
||||
sc->realize = scsi_hd_realize;
|
||||
sc->unrealize = scsi_unrealize;
|
||||
sc->alloc_req = scsi_new_request;
|
||||
sc->unit_attention_reported = scsi_disk_unit_attention_reported;
|
||||
dc->desc = "virtual SCSI disk";
|
||||
|
@ -26,6 +26,7 @@ typedef struct BlockConf {
|
||||
uint32_t discard_granularity;
|
||||
/* geometry, not all devices use this */
|
||||
uint32_t cyls, heads, secs;
|
||||
uint32_t lcyls, lheads, lsecs;
|
||||
OnOffAuto wce;
|
||||
bool share_rw;
|
||||
BlockdevOnError rerror;
|
||||
@ -50,22 +51,25 @@ static inline unsigned int get_physical_block_exp(BlockConf *conf)
|
||||
_conf.logical_block_size), \
|
||||
DEFINE_PROP_BLOCKSIZE("physical_block_size", _state, \
|
||||
_conf.physical_block_size), \
|
||||
DEFINE_PROP_UINT16("min_io_size", _state, _conf.min_io_size, 0), \
|
||||
DEFINE_PROP_UINT16("min_io_size", _state, _conf.min_io_size, 0), \
|
||||
DEFINE_PROP_UINT32("opt_io_size", _state, _conf.opt_io_size, 0), \
|
||||
DEFINE_PROP_UINT32("discard_granularity", _state, \
|
||||
_conf.discard_granularity, -1), \
|
||||
DEFINE_PROP_ON_OFF_AUTO("write-cache", _state, _conf.wce, \
|
||||
ON_OFF_AUTO_AUTO), \
|
||||
DEFINE_PROP_UINT32("discard_granularity", _state, \
|
||||
_conf.discard_granularity, -1), \
|
||||
DEFINE_PROP_ON_OFF_AUTO("write-cache", _state, _conf.wce, \
|
||||
ON_OFF_AUTO_AUTO), \
|
||||
DEFINE_PROP_BOOL("share-rw", _state, _conf.share_rw, false)
|
||||
|
||||
#define DEFINE_BLOCK_PROPERTIES(_state, _conf) \
|
||||
DEFINE_PROP_DRIVE("drive", _state, _conf.blk), \
|
||||
DEFINE_BLOCK_PROPERTIES_BASE(_state, _conf)
|
||||
|
||||
#define DEFINE_BLOCK_CHS_PROPERTIES(_state, _conf) \
|
||||
DEFINE_PROP_UINT32("cyls", _state, _conf.cyls, 0), \
|
||||
DEFINE_PROP_UINT32("heads", _state, _conf.heads, 0), \
|
||||
DEFINE_PROP_UINT32("secs", _state, _conf.secs, 0)
|
||||
#define DEFINE_BLOCK_CHS_PROPERTIES(_state, _conf) \
|
||||
DEFINE_PROP_UINT32("cyls", _state, _conf.cyls, 0), \
|
||||
DEFINE_PROP_UINT32("heads", _state, _conf.heads, 0), \
|
||||
DEFINE_PROP_UINT32("secs", _state, _conf.secs, 0), \
|
||||
DEFINE_PROP_UINT32("lcyls", _state, _conf.lcyls, 0), \
|
||||
DEFINE_PROP_UINT32("lheads", _state, _conf.lheads, 0), \
|
||||
DEFINE_PROP_UINT32("lsecs", _state, _conf.lsecs, 0)
|
||||
|
||||
#define DEFINE_BLOCK_ERROR_PROPERTIES(_state, _conf) \
|
||||
DEFINE_PROP_BLOCKDEV_ON_ERROR("rerror", _state, _conf.rerror, \
|
||||
|
@ -59,6 +59,7 @@ struct SCSIRequest {
|
||||
typedef struct SCSIDeviceClass {
|
||||
DeviceClass parent_class;
|
||||
void (*realize)(SCSIDevice *dev, Error **errp);
|
||||
void (*unrealize)(SCSIDevice *dev, Error **errp);
|
||||
int (*parse_cdb)(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf,
|
||||
void *hba_private);
|
||||
SCSIRequest *(*alloc_req)(SCSIDevice *s, uint32_t tag, uint32_t lun,
|
||||
|
@ -103,6 +103,10 @@ void device_add_bootindex_property(Object *obj, int32_t *bootindex,
|
||||
DeviceState *dev, Error **errp);
|
||||
void restore_boot_order(void *opaque);
|
||||
void validate_bootdevices(const char *devices, Error **errp);
|
||||
void add_boot_device_lchs(DeviceState *dev, const char *suffix,
|
||||
uint32_t lcyls, uint32_t lheads, uint32_t lsecs);
|
||||
void del_boot_device_lchs(DeviceState *dev, const char *suffix);
|
||||
char *get_boot_devices_lchs_list(size_t *size);
|
||||
|
||||
/* handler to set the boot_device order for a specific type of MachineClass */
|
||||
typedef void QEMUBootSetHandler(void *opaque, const char *boot_order,
|
||||
|
@ -254,6 +254,11 @@ quite a bit. It will be removed without replacement unless some users speaks
|
||||
up at the @email{qemu-devel@@nongnu.org} mailing list with information about
|
||||
their usecases.
|
||||
|
||||
@subsection ide-drive (since 4.2)
|
||||
|
||||
The 'ide-drive' device is deprecated. Users should use 'ide-hd' or
|
||||
'ide-cd' as appropriate to get an IDE hard disk or CD-ROM as needed.
|
||||
|
||||
@section System emulator machines
|
||||
|
||||
@subsection pc-0.12, pc-0.13, pc-0.14 and pc-0.15 (since 4.0)
|
||||
|
@ -794,7 +794,7 @@ tests/ide-test$(EXESUF): tests/ide-test.o $(libqos-pc-obj-y)
|
||||
tests/ahci-test$(EXESUF): tests/ahci-test.o $(libqos-pc-obj-y) qemu-img$(EXESUF)
|
||||
tests/ipmi-kcs-test$(EXESUF): tests/ipmi-kcs-test.o
|
||||
tests/ipmi-bt-test$(EXESUF): tests/ipmi-bt-test.o
|
||||
tests/hd-geo-test$(EXESUF): tests/hd-geo-test.o
|
||||
tests/hd-geo-test$(EXESUF): tests/hd-geo-test.o $(libqos-obj-y)
|
||||
tests/boot-order-test$(EXESUF): tests/boot-order-test.o $(libqos-obj-y)
|
||||
tests/boot-serial-test$(EXESUF): tests/boot-serial-test.o $(libqos-obj-y)
|
||||
tests/bios-tables-test$(EXESUF): tests/bios-tables-test.o \
|
||||
|
@ -17,7 +17,12 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/bswap.h"
|
||||
#include "qapi/qmp/qlist.h"
|
||||
#include "libqtest.h"
|
||||
#include "libqos/fw_cfg.h"
|
||||
#include "libqos/libqos.h"
|
||||
#include "standard-headers/linux/qemu_fw_cfg.h"
|
||||
|
||||
#define ARGV_SIZE 256
|
||||
|
||||
@ -388,6 +393,537 @@ static void test_ide_drive_cd_0(void)
|
||||
qtest_quit(qts);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
bool active;
|
||||
uint32_t head;
|
||||
uint32_t sector;
|
||||
uint32_t cyl;
|
||||
uint32_t end_head;
|
||||
uint32_t end_sector;
|
||||
uint32_t end_cyl;
|
||||
uint32_t start_sect;
|
||||
uint32_t nr_sects;
|
||||
} MBRpartitions[4];
|
||||
|
||||
static MBRpartitions empty_mbr = { {false, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
{false, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
{false, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
{false, 0, 0, 0, 0, 0, 0, 0, 0} };
|
||||
|
||||
static char *create_qcow2_with_mbr(MBRpartitions mbr, uint64_t sectors)
|
||||
{
|
||||
const char *template = "/tmp/qtest.XXXXXX";
|
||||
char *raw_path = strdup(template);
|
||||
char *qcow2_path = strdup(template);
|
||||
char cmd[100 + 2 * PATH_MAX];
|
||||
uint8_t buf[512];
|
||||
int i, ret, fd, offset;
|
||||
uint64_t qcow2_size = sectors * 512;
|
||||
uint8_t status, parttype, head, sector, cyl;
|
||||
char *qemu_img_path;
|
||||
char *qemu_img_abs_path;
|
||||
|
||||
offset = 0xbe;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
status = mbr[i].active ? 0x80 : 0x00;
|
||||
g_assert(mbr[i].head < 256);
|
||||
g_assert(mbr[i].sector < 64);
|
||||
g_assert(mbr[i].cyl < 1024);
|
||||
head = mbr[i].head;
|
||||
sector = mbr[i].sector + ((mbr[i].cyl & 0x300) >> 2);
|
||||
cyl = mbr[i].cyl & 0xff;
|
||||
|
||||
buf[offset + 0x0] = status;
|
||||
buf[offset + 0x1] = head;
|
||||
buf[offset + 0x2] = sector;
|
||||
buf[offset + 0x3] = cyl;
|
||||
|
||||
parttype = 0;
|
||||
g_assert(mbr[i].end_head < 256);
|
||||
g_assert(mbr[i].end_sector < 64);
|
||||
g_assert(mbr[i].end_cyl < 1024);
|
||||
head = mbr[i].end_head;
|
||||
sector = mbr[i].end_sector + ((mbr[i].end_cyl & 0x300) >> 2);
|
||||
cyl = mbr[i].end_cyl & 0xff;
|
||||
|
||||
buf[offset + 0x4] = parttype;
|
||||
buf[offset + 0x5] = head;
|
||||
buf[offset + 0x6] = sector;
|
||||
buf[offset + 0x7] = cyl;
|
||||
|
||||
(*(uint32_t *)&buf[offset + 0x8]) = cpu_to_le32(mbr[i].start_sect);
|
||||
(*(uint32_t *)&buf[offset + 0xc]) = cpu_to_le32(mbr[i].nr_sects);
|
||||
|
||||
offset += 0x10;
|
||||
}
|
||||
|
||||
fd = mkstemp(raw_path);
|
||||
g_assert(fd);
|
||||
close(fd);
|
||||
|
||||
fd = open(raw_path, O_WRONLY);
|
||||
g_assert(fd >= 0);
|
||||
ret = write(fd, buf, sizeof(buf));
|
||||
g_assert(ret == sizeof(buf));
|
||||
close(fd);
|
||||
|
||||
fd = mkstemp(qcow2_path);
|
||||
g_assert(fd);
|
||||
close(fd);
|
||||
|
||||
qemu_img_path = getenv("QTEST_QEMU_IMG");
|
||||
g_assert(qemu_img_path);
|
||||
qemu_img_abs_path = realpath(qemu_img_path, NULL);
|
||||
g_assert(qemu_img_abs_path);
|
||||
|
||||
ret = snprintf(cmd, sizeof(cmd),
|
||||
"%s convert -f raw -O qcow2 %s %s > /dev/null",
|
||||
qemu_img_abs_path,
|
||||
raw_path, qcow2_path);
|
||||
g_assert((0 < ret) && (ret <= sizeof(cmd)));
|
||||
ret = system(cmd);
|
||||
g_assert(ret == 0);
|
||||
|
||||
ret = snprintf(cmd, sizeof(cmd),
|
||||
"%s resize %s %" PRIu64 " > /dev/null",
|
||||
qemu_img_abs_path,
|
||||
qcow2_path, qcow2_size);
|
||||
g_assert((0 < ret) && (ret <= sizeof(cmd)));
|
||||
ret = system(cmd);
|
||||
g_assert(ret == 0);
|
||||
|
||||
free(qemu_img_abs_path);
|
||||
|
||||
unlink(raw_path);
|
||||
free(raw_path);
|
||||
|
||||
return qcow2_path;
|
||||
}
|
||||
|
||||
#define BIOS_GEOMETRY_MAX_SIZE 10000
|
||||
|
||||
typedef struct {
|
||||
uint32_t c;
|
||||
uint32_t h;
|
||||
uint32_t s;
|
||||
} CHS;
|
||||
|
||||
typedef struct {
|
||||
const char *dev_path;
|
||||
CHS chs;
|
||||
} CHSResult;
|
||||
|
||||
static void read_bootdevices(QFWCFG *fw_cfg, CHSResult expected[])
|
||||
{
|
||||
char *buf = g_malloc0(BIOS_GEOMETRY_MAX_SIZE);
|
||||
char *cur;
|
||||
GList *results = NULL, *cur_result;
|
||||
CHSResult *r;
|
||||
int i;
|
||||
int res;
|
||||
bool found;
|
||||
|
||||
qfw_cfg_get_file(fw_cfg, "bios-geometry", buf, BIOS_GEOMETRY_MAX_SIZE);
|
||||
|
||||
for (cur = buf; *cur; cur++) {
|
||||
if (*cur == '\n') {
|
||||
*cur = '\0';
|
||||
}
|
||||
}
|
||||
cur = buf;
|
||||
|
||||
while (strlen(cur)) {
|
||||
|
||||
r = g_malloc0(sizeof(*r));
|
||||
r->dev_path = g_malloc0(strlen(cur) + 1);
|
||||
res = sscanf(cur, "%s %" PRIu32 " %" PRIu32 " %" PRIu32,
|
||||
(char *)r->dev_path,
|
||||
&(r->chs.c), &(r->chs.h), &(r->chs.s));
|
||||
|
||||
g_assert(res == 4);
|
||||
|
||||
results = g_list_prepend(results, r);
|
||||
|
||||
cur += strlen(cur) + 1;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
|
||||
while (expected[i].dev_path) {
|
||||
found = false;
|
||||
cur_result = results;
|
||||
while (cur_result) {
|
||||
r = cur_result->data;
|
||||
if (!strcmp(r->dev_path, expected[i].dev_path) &&
|
||||
!memcmp(&(r->chs), &(expected[i].chs), sizeof(r->chs))) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
cur_result = g_list_next(cur_result);
|
||||
}
|
||||
g_assert(found);
|
||||
g_free((char *)((CHSResult *)cur_result->data)->dev_path);
|
||||
g_free(cur_result->data);
|
||||
results = g_list_delete_link(results, cur_result);
|
||||
i++;
|
||||
}
|
||||
|
||||
g_assert(results == NULL);
|
||||
|
||||
g_free(buf);
|
||||
}
|
||||
|
||||
#define MAX_DRIVES 30
|
||||
|
||||
typedef struct {
|
||||
char **argv;
|
||||
int argc;
|
||||
char **drives;
|
||||
int n_drives;
|
||||
int n_scsi_disks;
|
||||
int n_scsi_controllers;
|
||||
int n_virtio_disks;
|
||||
} TestArgs;
|
||||
|
||||
static TestArgs *create_args(void)
|
||||
{
|
||||
TestArgs *args = g_malloc0(sizeof(*args));
|
||||
args->argv = g_new0(char *, ARGV_SIZE);
|
||||
args->argc = append_arg(args->argc, args->argv,
|
||||
ARGV_SIZE, g_strdup("-nodefaults"));
|
||||
args->drives = g_new0(char *, MAX_DRIVES);
|
||||
return args;
|
||||
}
|
||||
|
||||
static void add_drive_with_mbr(TestArgs *args,
|
||||
MBRpartitions mbr, uint64_t sectors)
|
||||
{
|
||||
char *img_file_name;
|
||||
char part[300];
|
||||
int ret;
|
||||
|
||||
g_assert(args->n_drives < MAX_DRIVES);
|
||||
|
||||
img_file_name = create_qcow2_with_mbr(mbr, sectors);
|
||||
|
||||
args->drives[args->n_drives] = img_file_name;
|
||||
ret = snprintf(part, sizeof(part),
|
||||
"-drive file=%s,if=none,format=qcow2,id=disk%d",
|
||||
img_file_name, args->n_drives);
|
||||
g_assert((0 < ret) && (ret <= sizeof(part)));
|
||||
args->argc = append_arg(args->argc, args->argv, ARGV_SIZE, g_strdup(part));
|
||||
args->n_drives++;
|
||||
}
|
||||
|
||||
static void add_ide_disk(TestArgs *args,
|
||||
int drive_idx, int bus, int unit, int c, int h, int s)
|
||||
{
|
||||
char part[300];
|
||||
int ret;
|
||||
|
||||
ret = snprintf(part, sizeof(part),
|
||||
"-device ide-hd,drive=disk%d,bus=ide.%d,unit=%d,"
|
||||
"lcyls=%d,lheads=%d,lsecs=%d",
|
||||
drive_idx, bus, unit, c, h, s);
|
||||
g_assert((0 < ret) && (ret <= sizeof(part)));
|
||||
args->argc = append_arg(args->argc, args->argv, ARGV_SIZE, g_strdup(part));
|
||||
}
|
||||
|
||||
static void add_scsi_controller(TestArgs *args,
|
||||
const char *type,
|
||||
const char *bus,
|
||||
int addr)
|
||||
{
|
||||
char part[300];
|
||||
int ret;
|
||||
|
||||
ret = snprintf(part, sizeof(part),
|
||||
"-device %s,id=scsi%d,bus=%s,addr=%d",
|
||||
type, args->n_scsi_controllers, bus, addr);
|
||||
g_assert((0 < ret) && (ret <= sizeof(part)));
|
||||
args->argc = append_arg(args->argc, args->argv, ARGV_SIZE, g_strdup(part));
|
||||
args->n_scsi_controllers++;
|
||||
}
|
||||
|
||||
static void add_scsi_disk(TestArgs *args,
|
||||
int drive_idx, int bus,
|
||||
int channel, int scsi_id, int lun,
|
||||
int c, int h, int s)
|
||||
{
|
||||
char part[300];
|
||||
int ret;
|
||||
|
||||
ret = snprintf(part, sizeof(part),
|
||||
"-device scsi-hd,id=scsi-disk%d,drive=disk%d,"
|
||||
"bus=scsi%d.0,"
|
||||
"channel=%d,scsi-id=%d,lun=%d,"
|
||||
"lcyls=%d,lheads=%d,lsecs=%d",
|
||||
args->n_scsi_disks, drive_idx, bus, channel, scsi_id, lun,
|
||||
c, h, s);
|
||||
g_assert((0 < ret) && (ret <= sizeof(part)));
|
||||
args->argc = append_arg(args->argc, args->argv, ARGV_SIZE, g_strdup(part));
|
||||
args->n_scsi_disks++;
|
||||
}
|
||||
|
||||
static void add_virtio_disk(TestArgs *args,
|
||||
int drive_idx, const char *bus, int addr,
|
||||
int c, int h, int s)
|
||||
{
|
||||
char part[300];
|
||||
int ret;
|
||||
|
||||
ret = snprintf(part, sizeof(part),
|
||||
"-device virtio-blk-pci,id=virtio-disk%d,"
|
||||
"drive=disk%d,bus=%s,addr=%d,"
|
||||
"lcyls=%d,lheads=%d,lsecs=%d",
|
||||
args->n_virtio_disks, drive_idx, bus, addr, c, h, s);
|
||||
g_assert((0 < ret) && (ret <= sizeof(part)));
|
||||
args->argc = append_arg(args->argc, args->argv, ARGV_SIZE, g_strdup(part));
|
||||
args->n_virtio_disks++;
|
||||
}
|
||||
|
||||
static void test_override(TestArgs *args, CHSResult expected[])
|
||||
{
|
||||
QTestState *qts;
|
||||
char *joined_args;
|
||||
QFWCFG *fw_cfg;
|
||||
int i;
|
||||
|
||||
joined_args = g_strjoinv(" ", args->argv);
|
||||
|
||||
qts = qtest_init(joined_args);
|
||||
fw_cfg = pc_fw_cfg_init(qts);
|
||||
|
||||
read_bootdevices(fw_cfg, expected);
|
||||
|
||||
g_free(joined_args);
|
||||
qtest_quit(qts);
|
||||
|
||||
g_free(fw_cfg);
|
||||
|
||||
for (i = 0; i < args->n_drives; i++) {
|
||||
unlink(args->drives[i]);
|
||||
free(args->drives[i]);
|
||||
}
|
||||
g_free(args->drives);
|
||||
g_strfreev(args->argv);
|
||||
g_free(args);
|
||||
}
|
||||
|
||||
static void test_override_ide(void)
|
||||
{
|
||||
TestArgs *args = create_args();
|
||||
CHSResult expected[] = {
|
||||
{"/pci@i0cf8/ide@1,1/drive@0/disk@0", {10000, 120, 30} },
|
||||
{"/pci@i0cf8/ide@1,1/drive@0/disk@1", {9000, 120, 30} },
|
||||
{"/pci@i0cf8/ide@1,1/drive@1/disk@0", {0, 1, 1} },
|
||||
{"/pci@i0cf8/ide@1,1/drive@1/disk@1", {1, 0, 0} },
|
||||
{NULL, {0, 0, 0} }
|
||||
};
|
||||
add_drive_with_mbr(args, empty_mbr, 1);
|
||||
add_drive_with_mbr(args, empty_mbr, 1);
|
||||
add_drive_with_mbr(args, empty_mbr, 1);
|
||||
add_drive_with_mbr(args, empty_mbr, 1);
|
||||
add_ide_disk(args, 0, 0, 0, 10000, 120, 30);
|
||||
add_ide_disk(args, 1, 0, 1, 9000, 120, 30);
|
||||
add_ide_disk(args, 2, 1, 0, 0, 1, 1);
|
||||
add_ide_disk(args, 3, 1, 1, 1, 0, 0);
|
||||
test_override(args, expected);
|
||||
}
|
||||
|
||||
static void test_override_scsi(void)
|
||||
{
|
||||
TestArgs *args = create_args();
|
||||
CHSResult expected[] = {
|
||||
{"/pci@i0cf8/scsi@3/channel@0/disk@0,0", {10000, 120, 30} },
|
||||
{"/pci@i0cf8/scsi@3/channel@0/disk@1,0", {9000, 120, 30} },
|
||||
{"/pci@i0cf8/scsi@3/channel@0/disk@2,0", {1, 0, 0} },
|
||||
{"/pci@i0cf8/scsi@3/channel@0/disk@3,0", {0, 1, 0} },
|
||||
{NULL, {0, 0, 0} }
|
||||
};
|
||||
add_drive_with_mbr(args, empty_mbr, 1);
|
||||
add_drive_with_mbr(args, empty_mbr, 1);
|
||||
add_drive_with_mbr(args, empty_mbr, 1);
|
||||
add_drive_with_mbr(args, empty_mbr, 1);
|
||||
add_scsi_controller(args, "lsi53c895a", "pci.0", 3);
|
||||
add_scsi_disk(args, 0, 0, 0, 0, 0, 10000, 120, 30);
|
||||
add_scsi_disk(args, 1, 0, 0, 1, 0, 9000, 120, 30);
|
||||
add_scsi_disk(args, 2, 0, 0, 2, 0, 1, 0, 0);
|
||||
add_scsi_disk(args, 3, 0, 0, 3, 0, 0, 1, 0);
|
||||
test_override(args, expected);
|
||||
}
|
||||
|
||||
static void test_override_scsi_2_controllers(void)
|
||||
{
|
||||
TestArgs *args = create_args();
|
||||
CHSResult expected[] = {
|
||||
{"/pci@i0cf8/scsi@3/channel@0/disk@0,0", {10000, 120, 30} },
|
||||
{"/pci@i0cf8/scsi@3/channel@0/disk@1,0", {9000, 120, 30} },
|
||||
{"/pci@i0cf8/scsi@4/channel@0/disk@0,1", {1, 0, 0} },
|
||||
{"/pci@i0cf8/scsi@4/channel@0/disk@1,2", {0, 1, 0} },
|
||||
{NULL, {0, 0, 0} }
|
||||
};
|
||||
add_drive_with_mbr(args, empty_mbr, 1);
|
||||
add_drive_with_mbr(args, empty_mbr, 1);
|
||||
add_drive_with_mbr(args, empty_mbr, 1);
|
||||
add_drive_with_mbr(args, empty_mbr, 1);
|
||||
add_scsi_controller(args, "lsi53c895a", "pci.0", 3);
|
||||
add_scsi_controller(args, "virtio-scsi-pci", "pci.0", 4);
|
||||
add_scsi_disk(args, 0, 0, 0, 0, 0, 10000, 120, 30);
|
||||
add_scsi_disk(args, 1, 0, 0, 1, 0, 9000, 120, 30);
|
||||
add_scsi_disk(args, 2, 1, 0, 0, 1, 1, 0, 0);
|
||||
add_scsi_disk(args, 3, 1, 0, 1, 2, 0, 1, 0);
|
||||
test_override(args, expected);
|
||||
}
|
||||
|
||||
static void test_override_virtio_blk(void)
|
||||
{
|
||||
TestArgs *args = create_args();
|
||||
CHSResult expected[] = {
|
||||
{"/pci@i0cf8/scsi@3/disk@0,0", {10000, 120, 30} },
|
||||
{"/pci@i0cf8/scsi@4/disk@0,0", {9000, 120, 30} },
|
||||
{NULL, {0, 0, 0} }
|
||||
};
|
||||
add_drive_with_mbr(args, empty_mbr, 1);
|
||||
add_drive_with_mbr(args, empty_mbr, 1);
|
||||
add_virtio_disk(args, 0, "pci.0", 3, 10000, 120, 30);
|
||||
add_virtio_disk(args, 1, "pci.0", 4, 9000, 120, 30);
|
||||
test_override(args, expected);
|
||||
}
|
||||
|
||||
static void test_override_zero_chs(void)
|
||||
{
|
||||
TestArgs *args = create_args();
|
||||
CHSResult expected[] = {
|
||||
{NULL, {0, 0, 0} }
|
||||
};
|
||||
add_drive_with_mbr(args, empty_mbr, 1);
|
||||
add_ide_disk(args, 0, 1, 1, 0, 0, 0);
|
||||
test_override(args, expected);
|
||||
}
|
||||
|
||||
static void test_override_scsi_hot_unplug(void)
|
||||
{
|
||||
QTestState *qts;
|
||||
char *joined_args;
|
||||
QFWCFG *fw_cfg;
|
||||
QDict *response;
|
||||
int i;
|
||||
TestArgs *args = create_args();
|
||||
CHSResult expected[] = {
|
||||
{"/pci@i0cf8/scsi@2/channel@0/disk@0,0", {10000, 120, 30} },
|
||||
{"/pci@i0cf8/scsi@2/channel@0/disk@1,0", {20, 20, 20} },
|
||||
{NULL, {0, 0, 0} }
|
||||
};
|
||||
CHSResult expected2[] = {
|
||||
{"/pci@i0cf8/scsi@2/channel@0/disk@1,0", {20, 20, 20} },
|
||||
{NULL, {0, 0, 0} }
|
||||
};
|
||||
add_drive_with_mbr(args, empty_mbr, 1);
|
||||
add_drive_with_mbr(args, empty_mbr, 1);
|
||||
add_scsi_controller(args, "virtio-scsi-pci", "pci.0", 2);
|
||||
add_scsi_disk(args, 0, 0, 0, 0, 0, 10000, 120, 30);
|
||||
add_scsi_disk(args, 1, 0, 0, 1, 0, 20, 20, 20);
|
||||
|
||||
joined_args = g_strjoinv(" ", args->argv);
|
||||
|
||||
qts = qtest_init(joined_args);
|
||||
fw_cfg = pc_fw_cfg_init(qts);
|
||||
|
||||
read_bootdevices(fw_cfg, expected);
|
||||
|
||||
/* unplug device an restart */
|
||||
response = qtest_qmp(qts,
|
||||
"{ 'execute': 'device_del',"
|
||||
" 'arguments': {'id': 'scsi-disk0' }}");
|
||||
g_assert(response);
|
||||
g_assert(!qdict_haskey(response, "error"));
|
||||
qobject_unref(response);
|
||||
response = qtest_qmp(qts,
|
||||
"{ 'execute': 'system_reset', 'arguments': { }}");
|
||||
g_assert(response);
|
||||
g_assert(!qdict_haskey(response, "error"));
|
||||
qobject_unref(response);
|
||||
|
||||
qtest_qmp_eventwait(qts, "RESET");
|
||||
|
||||
read_bootdevices(fw_cfg, expected2);
|
||||
|
||||
g_free(joined_args);
|
||||
qtest_quit(qts);
|
||||
|
||||
g_free(fw_cfg);
|
||||
|
||||
for (i = 0; i < args->n_drives; i++) {
|
||||
unlink(args->drives[i]);
|
||||
free(args->drives[i]);
|
||||
}
|
||||
g_free(args->drives);
|
||||
g_strfreev(args->argv);
|
||||
g_free(args);
|
||||
}
|
||||
|
||||
static void test_override_virtio_hot_unplug(void)
|
||||
{
|
||||
QTestState *qts;
|
||||
char *joined_args;
|
||||
QFWCFG *fw_cfg;
|
||||
QDict *response;
|
||||
int i;
|
||||
TestArgs *args = create_args();
|
||||
CHSResult expected[] = {
|
||||
{"/pci@i0cf8/scsi@2/disk@0,0", {10000, 120, 30} },
|
||||
{"/pci@i0cf8/scsi@3/disk@0,0", {20, 20, 20} },
|
||||
{NULL, {0, 0, 0} }
|
||||
};
|
||||
CHSResult expected2[] = {
|
||||
{"/pci@i0cf8/scsi@3/disk@0,0", {20, 20, 20} },
|
||||
{NULL, {0, 0, 0} }
|
||||
};
|
||||
add_drive_with_mbr(args, empty_mbr, 1);
|
||||
add_drive_with_mbr(args, empty_mbr, 1);
|
||||
add_virtio_disk(args, 0, "pci.0", 2, 10000, 120, 30);
|
||||
add_virtio_disk(args, 1, "pci.0", 3, 20, 20, 20);
|
||||
|
||||
joined_args = g_strjoinv(" ", args->argv);
|
||||
|
||||
qts = qtest_init(joined_args);
|
||||
fw_cfg = pc_fw_cfg_init(qts);
|
||||
|
||||
read_bootdevices(fw_cfg, expected);
|
||||
|
||||
/* unplug device an restart */
|
||||
response = qtest_qmp(qts,
|
||||
"{ 'execute': 'device_del',"
|
||||
" 'arguments': {'id': 'virtio-disk0' }}");
|
||||
g_assert(response);
|
||||
g_assert(!qdict_haskey(response, "error"));
|
||||
qobject_unref(response);
|
||||
response = qtest_qmp(qts,
|
||||
"{ 'execute': 'system_reset', 'arguments': { }}");
|
||||
g_assert(response);
|
||||
g_assert(!qdict_haskey(response, "error"));
|
||||
qobject_unref(response);
|
||||
|
||||
qtest_qmp_eventwait(qts, "RESET");
|
||||
|
||||
read_bootdevices(fw_cfg, expected2);
|
||||
|
||||
g_free(joined_args);
|
||||
qtest_quit(qts);
|
||||
|
||||
g_free(fw_cfg);
|
||||
|
||||
for (i = 0; i < args->n_drives; i++) {
|
||||
unlink(args->drives[i]);
|
||||
free(args->drives[i]);
|
||||
}
|
||||
g_free(args->drives);
|
||||
g_strfreev(args->argv);
|
||||
g_free(args);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
Backend i;
|
||||
@ -413,6 +949,21 @@ int main(int argc, char **argv)
|
||||
qtest_add_func("hd-geo/ide/device/mbr/chs", test_ide_device_mbr_chs);
|
||||
qtest_add_func("hd-geo/ide/device/user/chs", test_ide_device_user_chs);
|
||||
qtest_add_func("hd-geo/ide/device/user/chst", test_ide_device_user_chst);
|
||||
if (have_qemu_img()) {
|
||||
qtest_add_func("hd-geo/override/ide", test_override_ide);
|
||||
qtest_add_func("hd-geo/override/scsi", test_override_scsi);
|
||||
qtest_add_func("hd-geo/override/scsi_2_controllers",
|
||||
test_override_scsi_2_controllers);
|
||||
qtest_add_func("hd-geo/override/virtio_blk", test_override_virtio_blk);
|
||||
qtest_add_func("hd-geo/override/zero_chs", test_override_zero_chs);
|
||||
qtest_add_func("hd-geo/override/scsi_hot_unplug",
|
||||
test_override_scsi_hot_unplug);
|
||||
qtest_add_func("hd-geo/override/virtio_hot_unplug",
|
||||
test_override_virtio_hot_unplug);
|
||||
} else {
|
||||
g_test_message("QTEST_QEMU_IMG not set or qemu-img missing; "
|
||||
"skipping hd-geo/override/* tests");
|
||||
}
|
||||
|
||||
ret = g_test_run();
|
||||
|
||||
|
@ -158,7 +158,8 @@ QEMU X.Y.Z monitor - type 'help' for more information
|
||||
|
||||
Testing: -drive if=none,id=disk -device ide-drive,drive=disk
|
||||
QEMU X.Y.Z monitor - type 'help' for more information
|
||||
(qemu) QEMU_PROG: -device ide-drive,drive=disk: Device needs media, but drive is empty
|
||||
(qemu) QEMU_PROG: -device ide-drive,drive=disk: warning: 'ide-drive' is deprecated, please use 'ide-hd' or 'ide-cd' instead
|
||||
QEMU_PROG: -device ide-drive,drive=disk: Device needs media, but drive is empty
|
||||
|
||||
Testing: -drive if=none,id=disk -device ide-hd,drive=disk
|
||||
QEMU X.Y.Z monitor - type 'help' for more information
|
||||
@ -228,7 +229,8 @@ QEMU X.Y.Z monitor - type 'help' for more information
|
||||
|
||||
Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device ide-drive,drive=disk
|
||||
QEMU X.Y.Z monitor - type 'help' for more information
|
||||
(qemu) QEMU_PROG: -device ide-drive,drive=disk: Block node is read-only
|
||||
(qemu) QEMU_PROG: -device ide-drive,drive=disk: warning: 'ide-drive' is deprecated, please use 'ide-hd' or 'ide-cd' instead
|
||||
QEMU_PROG: -device ide-drive,drive=disk: Block node is read-only
|
||||
|
||||
Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device ide-hd,drive=disk
|
||||
QEMU X.Y.Z monitor - type 'help' for more information
|
||||
|
Loading…
Reference in New Issue
Block a user