Compare commits
36 Commits
pull-input
...
pull-audio
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b1fe60cd35 | ||
|
|
a2554a334a | ||
|
|
c5fa6c86d0 | ||
|
|
5bc8f026dd | ||
|
|
6a23082b4e | ||
|
|
24fd848950 | ||
|
|
11b389f21e | ||
|
|
b162b49adc | ||
|
|
40d19394b7 | ||
|
|
13e315dada | ||
|
|
6297d9a279 | ||
|
|
29136cd8a4 | ||
|
|
87a560c455 | ||
|
|
297a3646c2 | ||
|
|
cdaec3808e | ||
|
|
2ddb16a95f | ||
|
|
f9f3a5ecde | ||
|
|
be3c771796 | ||
|
|
192cca60ae | ||
|
|
4fa953f20d | ||
|
|
468866b816 | ||
|
|
e2cd0f4fb4 | ||
|
|
cbc95538ed | ||
|
|
f9bee751be | ||
|
|
6e2bb3ec70 | ||
|
|
6a86dec619 | ||
|
|
3d2acaa308 | ||
|
|
5917af812e | ||
|
|
b03c38057b | ||
|
|
dbe5c58f2a | ||
|
|
d383c625e2 | ||
|
|
4522b69c6c | ||
|
|
23335f6273 | ||
|
|
34bb4d02e0 | ||
|
|
6ee143a0a4 | ||
|
|
4bbeb8b173 |
@@ -659,6 +659,12 @@ S: Supported
|
|||||||
F: hw/block/nvme*
|
F: hw/block/nvme*
|
||||||
F: tests/nvme-test.c
|
F: tests/nvme-test.c
|
||||||
|
|
||||||
|
megasas
|
||||||
|
M: Hannes Reinecke <hare@suse.de>
|
||||||
|
S: Supported
|
||||||
|
F: hw/scsi/megasas.c
|
||||||
|
F: hw/scsi/mfi.h
|
||||||
|
|
||||||
Xilinx EDK
|
Xilinx EDK
|
||||||
M: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
|
M: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
|
||||||
M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
|
M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
|
||||||
|
|||||||
319
block/iscsi.c
319
block/iscsi.c
@@ -30,6 +30,8 @@
|
|||||||
#include "qemu-common.h"
|
#include "qemu-common.h"
|
||||||
#include "qemu/config-file.h"
|
#include "qemu/config-file.h"
|
||||||
#include "qemu/error-report.h"
|
#include "qemu/error-report.h"
|
||||||
|
#include "qemu/bitops.h"
|
||||||
|
#include "qemu/bitmap.h"
|
||||||
#include "block/block_int.h"
|
#include "block/block_int.h"
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
#include "block/scsi.h"
|
#include "block/scsi.h"
|
||||||
@@ -59,6 +61,8 @@ typedef struct IscsiLun {
|
|||||||
struct scsi_inquiry_logical_block_provisioning lbp;
|
struct scsi_inquiry_logical_block_provisioning lbp;
|
||||||
struct scsi_inquiry_block_limits bl;
|
struct scsi_inquiry_block_limits bl;
|
||||||
unsigned char *zeroblock;
|
unsigned char *zeroblock;
|
||||||
|
unsigned long *allocationmap;
|
||||||
|
int cluster_sectors;
|
||||||
} IscsiLun;
|
} IscsiLun;
|
||||||
|
|
||||||
typedef struct IscsiTask {
|
typedef struct IscsiTask {
|
||||||
@@ -92,6 +96,15 @@ typedef struct IscsiAIOCB {
|
|||||||
#define MAX_NOP_FAILURES 3
|
#define MAX_NOP_FAILURES 3
|
||||||
#define ISCSI_CMD_RETRIES 5
|
#define ISCSI_CMD_RETRIES 5
|
||||||
|
|
||||||
|
/* this threshhold is a trade-off knob to choose between
|
||||||
|
* the potential additional overhead of an extra GET_LBA_STATUS request
|
||||||
|
* vs. unnecessarily reading a lot of zero sectors over the wire.
|
||||||
|
* If a read request is greater or equal than ISCSI_CHECKALLOC_THRES
|
||||||
|
* sectors we check the allocation status of the area covered by the
|
||||||
|
* request first if the allocationmap indicates that the area might be
|
||||||
|
* unallocated. */
|
||||||
|
#define ISCSI_CHECKALLOC_THRES 64
|
||||||
|
|
||||||
static void
|
static void
|
||||||
iscsi_bh_cb(void *p)
|
iscsi_bh_cb(void *p)
|
||||||
{
|
{
|
||||||
@@ -273,6 +286,32 @@ static bool is_request_lun_aligned(int64_t sector_num, int nb_sectors,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void iscsi_allocationmap_set(IscsiLun *iscsilun, int64_t sector_num,
|
||||||
|
int nb_sectors)
|
||||||
|
{
|
||||||
|
if (iscsilun->allocationmap == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
bitmap_set(iscsilun->allocationmap,
|
||||||
|
sector_num / iscsilun->cluster_sectors,
|
||||||
|
DIV_ROUND_UP(nb_sectors, iscsilun->cluster_sectors));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void iscsi_allocationmap_clear(IscsiLun *iscsilun, int64_t sector_num,
|
||||||
|
int nb_sectors)
|
||||||
|
{
|
||||||
|
int64_t cluster_num, nb_clusters;
|
||||||
|
if (iscsilun->allocationmap == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cluster_num = DIV_ROUND_UP(sector_num, iscsilun->cluster_sectors);
|
||||||
|
nb_clusters = (sector_num + nb_sectors) / iscsilun->cluster_sectors
|
||||||
|
- cluster_num;
|
||||||
|
if (nb_clusters > 0) {
|
||||||
|
bitmap_clear(iscsilun->allocationmap, cluster_num, nb_clusters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int coroutine_fn iscsi_co_writev(BlockDriverState *bs,
|
static int coroutine_fn iscsi_co_writev(BlockDriverState *bs,
|
||||||
int64_t sector_num, int nb_sectors,
|
int64_t sector_num, int nb_sectors,
|
||||||
QEMUIOVector *iov)
|
QEMUIOVector *iov)
|
||||||
@@ -336,9 +375,127 @@ retry:
|
|||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iscsi_allocationmap_set(iscsilun, sector_num, nb_sectors);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool iscsi_allocationmap_is_allocated(IscsiLun *iscsilun,
|
||||||
|
int64_t sector_num, int nb_sectors)
|
||||||
|
{
|
||||||
|
unsigned long size;
|
||||||
|
if (iscsilun->allocationmap == NULL) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
size = DIV_ROUND_UP(sector_num + nb_sectors, iscsilun->cluster_sectors);
|
||||||
|
return !(find_next_bit(iscsilun->allocationmap, size,
|
||||||
|
sector_num / iscsilun->cluster_sectors) == size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(LIBISCSI_FEATURE_IOVECTOR)
|
||||||
|
|
||||||
|
static int64_t coroutine_fn iscsi_co_get_block_status(BlockDriverState *bs,
|
||||||
|
int64_t sector_num,
|
||||||
|
int nb_sectors, int *pnum)
|
||||||
|
{
|
||||||
|
IscsiLun *iscsilun = bs->opaque;
|
||||||
|
struct scsi_get_lba_status *lbas = NULL;
|
||||||
|
struct scsi_lba_status_descriptor *lbasd = NULL;
|
||||||
|
struct IscsiTask iTask;
|
||||||
|
int64_t ret;
|
||||||
|
|
||||||
|
iscsi_co_init_iscsitask(iscsilun, &iTask);
|
||||||
|
|
||||||
|
if (!is_request_lun_aligned(sector_num, nb_sectors, iscsilun)) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* default to all sectors allocated */
|
||||||
|
ret = BDRV_BLOCK_DATA;
|
||||||
|
ret |= (sector_num << BDRV_SECTOR_BITS) | BDRV_BLOCK_OFFSET_VALID;
|
||||||
|
*pnum = nb_sectors;
|
||||||
|
|
||||||
|
/* LUN does not support logical block provisioning */
|
||||||
|
if (iscsilun->lbpme == 0) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
retry:
|
||||||
|
if (iscsi_get_lba_status_task(iscsilun->iscsi, iscsilun->lun,
|
||||||
|
sector_qemu2lun(sector_num, iscsilun),
|
||||||
|
8 + 16, iscsi_co_generic_cb,
|
||||||
|
&iTask) == NULL) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!iTask.complete) {
|
||||||
|
iscsi_set_events(iscsilun);
|
||||||
|
qemu_coroutine_yield();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iTask.do_retry) {
|
||||||
|
if (iTask.task != NULL) {
|
||||||
|
scsi_free_scsi_task(iTask.task);
|
||||||
|
iTask.task = NULL;
|
||||||
|
}
|
||||||
|
iTask.complete = 0;
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iTask.status != SCSI_STATUS_GOOD) {
|
||||||
|
/* in case the get_lba_status_callout fails (i.e.
|
||||||
|
* because the device is busy or the cmd is not
|
||||||
|
* supported) we pretend all blocks are allocated
|
||||||
|
* for backwards compatibility */
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
lbas = scsi_datain_unmarshall(iTask.task);
|
||||||
|
if (lbas == NULL) {
|
||||||
|
ret = -EIO;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
lbasd = &lbas->descriptors[0];
|
||||||
|
|
||||||
|
if (sector_qemu2lun(sector_num, iscsilun) != lbasd->lba) {
|
||||||
|
ret = -EIO;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pnum = sector_lun2qemu(lbasd->num_blocks, iscsilun);
|
||||||
|
|
||||||
|
if (lbasd->provisioning == SCSI_PROVISIONING_TYPE_DEALLOCATED ||
|
||||||
|
lbasd->provisioning == SCSI_PROVISIONING_TYPE_ANCHORED) {
|
||||||
|
ret &= ~BDRV_BLOCK_DATA;
|
||||||
|
if (iscsilun->lbprz) {
|
||||||
|
ret |= BDRV_BLOCK_ZERO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret & BDRV_BLOCK_ZERO) {
|
||||||
|
iscsi_allocationmap_clear(iscsilun, sector_num, *pnum);
|
||||||
|
} else {
|
||||||
|
iscsi_allocationmap_set(iscsilun, sector_num, *pnum);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*pnum > nb_sectors) {
|
||||||
|
*pnum = nb_sectors;
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
if (iTask.task != NULL) {
|
||||||
|
scsi_free_scsi_task(iTask.task);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* LIBISCSI_FEATURE_IOVECTOR */
|
||||||
|
|
||||||
|
|
||||||
static int coroutine_fn iscsi_co_readv(BlockDriverState *bs,
|
static int coroutine_fn iscsi_co_readv(BlockDriverState *bs,
|
||||||
int64_t sector_num, int nb_sectors,
|
int64_t sector_num, int nb_sectors,
|
||||||
QEMUIOVector *iov)
|
QEMUIOVector *iov)
|
||||||
@@ -355,6 +512,22 @@ static int coroutine_fn iscsi_co_readv(BlockDriverState *bs,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(LIBISCSI_FEATURE_IOVECTOR)
|
||||||
|
if (iscsilun->lbprz && nb_sectors >= ISCSI_CHECKALLOC_THRES &&
|
||||||
|
!iscsi_allocationmap_is_allocated(iscsilun, sector_num, nb_sectors)) {
|
||||||
|
int64_t ret;
|
||||||
|
int pnum;
|
||||||
|
ret = iscsi_co_get_block_status(bs, sector_num, INT_MAX, &pnum);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
if (ret & BDRV_BLOCK_ZERO && pnum >= nb_sectors) {
|
||||||
|
qemu_iovec_memset(iov, 0, 0x00, iov->size);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
lba = sector_qemu2lun(sector_num, iscsilun);
|
lba = sector_qemu2lun(sector_num, iscsilun);
|
||||||
num_sectors = sector_qemu2lun(nb_sectors, iscsilun);
|
num_sectors = sector_qemu2lun(nb_sectors, iscsilun);
|
||||||
|
|
||||||
@@ -643,101 +816,6 @@ iscsi_getlength(BlockDriverState *bs)
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(LIBISCSI_FEATURE_IOVECTOR)
|
|
||||||
|
|
||||||
static int64_t coroutine_fn iscsi_co_get_block_status(BlockDriverState *bs,
|
|
||||||
int64_t sector_num,
|
|
||||||
int nb_sectors, int *pnum)
|
|
||||||
{
|
|
||||||
IscsiLun *iscsilun = bs->opaque;
|
|
||||||
struct scsi_get_lba_status *lbas = NULL;
|
|
||||||
struct scsi_lba_status_descriptor *lbasd = NULL;
|
|
||||||
struct IscsiTask iTask;
|
|
||||||
int64_t ret;
|
|
||||||
|
|
||||||
iscsi_co_init_iscsitask(iscsilun, &iTask);
|
|
||||||
|
|
||||||
if (!is_request_lun_aligned(sector_num, nb_sectors, iscsilun)) {
|
|
||||||
ret = -EINVAL;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* default to all sectors allocated */
|
|
||||||
ret = BDRV_BLOCK_DATA;
|
|
||||||
ret |= (sector_num << BDRV_SECTOR_BITS) | BDRV_BLOCK_OFFSET_VALID;
|
|
||||||
*pnum = nb_sectors;
|
|
||||||
|
|
||||||
/* LUN does not support logical block provisioning */
|
|
||||||
if (iscsilun->lbpme == 0) {
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
retry:
|
|
||||||
if (iscsi_get_lba_status_task(iscsilun->iscsi, iscsilun->lun,
|
|
||||||
sector_qemu2lun(sector_num, iscsilun),
|
|
||||||
8 + 16, iscsi_co_generic_cb,
|
|
||||||
&iTask) == NULL) {
|
|
||||||
ret = -ENOMEM;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (!iTask.complete) {
|
|
||||||
iscsi_set_events(iscsilun);
|
|
||||||
qemu_coroutine_yield();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iTask.do_retry) {
|
|
||||||
if (iTask.task != NULL) {
|
|
||||||
scsi_free_scsi_task(iTask.task);
|
|
||||||
iTask.task = NULL;
|
|
||||||
}
|
|
||||||
iTask.complete = 0;
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iTask.status != SCSI_STATUS_GOOD) {
|
|
||||||
/* in case the get_lba_status_callout fails (i.e.
|
|
||||||
* because the device is busy or the cmd is not
|
|
||||||
* supported) we pretend all blocks are allocated
|
|
||||||
* for backwards compatibility */
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
lbas = scsi_datain_unmarshall(iTask.task);
|
|
||||||
if (lbas == NULL) {
|
|
||||||
ret = -EIO;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
lbasd = &lbas->descriptors[0];
|
|
||||||
|
|
||||||
if (sector_qemu2lun(sector_num, iscsilun) != lbasd->lba) {
|
|
||||||
ret = -EIO;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
*pnum = sector_lun2qemu(lbasd->num_blocks, iscsilun);
|
|
||||||
if (*pnum > nb_sectors) {
|
|
||||||
*pnum = nb_sectors;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lbasd->provisioning == SCSI_PROVISIONING_TYPE_DEALLOCATED ||
|
|
||||||
lbasd->provisioning == SCSI_PROVISIONING_TYPE_ANCHORED) {
|
|
||||||
ret &= ~BDRV_BLOCK_DATA;
|
|
||||||
if (iscsilun->lbprz) {
|
|
||||||
ret |= BDRV_BLOCK_ZERO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
out:
|
|
||||||
if (iTask.task != NULL) {
|
|
||||||
scsi_free_scsi_task(iTask.task);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* LIBISCSI_FEATURE_IOVECTOR */
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
coroutine_fn iscsi_co_discard(BlockDriverState *bs, int64_t sector_num,
|
coroutine_fn iscsi_co_discard(BlockDriverState *bs, int64_t sector_num,
|
||||||
int nb_sectors)
|
int nb_sectors)
|
||||||
@@ -791,6 +869,8 @@ retry:
|
|||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iscsi_allocationmap_clear(iscsilun, sector_num, nb_sectors);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -809,13 +889,14 @@ coroutine_fn iscsi_co_write_zeroes(BlockDriverState *bs, int64_t sector_num,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(flags & BDRV_REQ_MAY_UNMAP) && !iscsilun->has_write_same) {
|
if ((flags & BDRV_REQ_MAY_UNMAP) && !iscsilun->lbp.lbpws) {
|
||||||
/* WRITE SAME without UNMAP is not supported by the target */
|
/* WRITE SAME with UNMAP is not supported by the target,
|
||||||
return -ENOTSUP;
|
* fall back and try WRITE SAME without UNMAP */
|
||||||
|
flags &= ~BDRV_REQ_MAY_UNMAP;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((flags & BDRV_REQ_MAY_UNMAP) && !iscsilun->lbp.lbpws) {
|
if (!(flags & BDRV_REQ_MAY_UNMAP) && !iscsilun->has_write_same) {
|
||||||
/* WRITE SAME with UNMAP is not supported by the target */
|
/* WRITE SAME without UNMAP is not supported by the target */
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -864,6 +945,12 @@ retry:
|
|||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (flags & BDRV_REQ_MAY_UNMAP) {
|
||||||
|
iscsi_allocationmap_clear(iscsilun, sector_num, nb_sectors);
|
||||||
|
} else {
|
||||||
|
iscsi_allocationmap_set(iscsilun, sector_num, nb_sectors);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1295,6 +1382,22 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
timer_mod(iscsilun->nop_timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + NOP_INTERVAL);
|
timer_mod(iscsilun->nop_timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + NOP_INTERVAL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Guess the internal cluster (page) size of the iscsi target by the means
|
||||||
|
* of opt_unmap_gran. Transfer the unmap granularity only if it has a
|
||||||
|
* reasonable size */
|
||||||
|
if (iscsilun->bl.opt_unmap_gran * iscsilun->block_size >= 4 * 1024 &&
|
||||||
|
iscsilun->bl.opt_unmap_gran * iscsilun->block_size <= 16 * 1024 * 1024) {
|
||||||
|
iscsilun->cluster_sectors = (iscsilun->bl.opt_unmap_gran *
|
||||||
|
iscsilun->block_size) >> BDRV_SECTOR_BITS;
|
||||||
|
#if defined(LIBISCSI_FEATURE_IOVECTOR)
|
||||||
|
if (iscsilun->lbprz && !(bs->open_flags & BDRV_O_NOCACHE)) {
|
||||||
|
iscsilun->allocationmap =
|
||||||
|
bitmap_new(DIV_ROUND_UP(bs->total_sectors,
|
||||||
|
iscsilun->cluster_sectors));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
qemu_opts_del(opts);
|
qemu_opts_del(opts);
|
||||||
if (initiator_name != NULL) {
|
if (initiator_name != NULL) {
|
||||||
@@ -1328,6 +1431,7 @@ static void iscsi_close(BlockDriverState *bs)
|
|||||||
qemu_aio_set_fd_handler(iscsi_get_fd(iscsi), NULL, NULL, NULL);
|
qemu_aio_set_fd_handler(iscsi_get_fd(iscsi), NULL, NULL, NULL);
|
||||||
iscsi_destroy_context(iscsi);
|
iscsi_destroy_context(iscsi);
|
||||||
g_free(iscsilun->zeroblock);
|
g_free(iscsilun->zeroblock);
|
||||||
|
g_free(iscsilun->allocationmap);
|
||||||
memset(iscsilun, 0, sizeof(IscsiLun));
|
memset(iscsilun, 0, sizeof(IscsiLun));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1388,6 +1492,13 @@ static int iscsi_truncate(BlockDriverState *bs, int64_t offset)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (iscsilun->allocationmap != NULL) {
|
||||||
|
g_free(iscsilun->allocationmap);
|
||||||
|
iscsilun->allocationmap =
|
||||||
|
bitmap_new(DIV_ROUND_UP(bs->total_sectors,
|
||||||
|
iscsilun->cluster_sectors));
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1450,13 +1561,7 @@ static int iscsi_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
|
|||||||
IscsiLun *iscsilun = bs->opaque;
|
IscsiLun *iscsilun = bs->opaque;
|
||||||
bdi->unallocated_blocks_are_zero = !!iscsilun->lbprz;
|
bdi->unallocated_blocks_are_zero = !!iscsilun->lbprz;
|
||||||
bdi->can_write_zeroes_with_unmap = iscsilun->lbprz && iscsilun->lbp.lbpws;
|
bdi->can_write_zeroes_with_unmap = iscsilun->lbprz && iscsilun->lbp.lbpws;
|
||||||
/* Guess the internal cluster (page) size of the iscsi target by the means
|
bdi->cluster_size = iscsilun->cluster_sectors * BDRV_SECTOR_SIZE;
|
||||||
* of opt_unmap_gran. Transfer the unmap granularity only if it has a
|
|
||||||
* reasonable size for bdi->cluster_size */
|
|
||||||
if (iscsilun->bl.opt_unmap_gran * iscsilun->block_size >= 64 * 1024 &&
|
|
||||||
iscsilun->bl.opt_unmap_gran * iscsilun->block_size <= 16 * 1024 * 1024) {
|
|
||||||
bdi->cluster_size = iscsilun->bl.opt_unmap_gran * iscsilun->block_size;
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ The QAPI schema definitions can be modularized using the 'include' directive:
|
|||||||
{ 'include': 'path/to/file.json'}
|
{ 'include': 'path/to/file.json'}
|
||||||
|
|
||||||
The directive is evaluated recursively, and include paths are relative to the
|
The directive is evaluated recursively, and include paths are relative to the
|
||||||
file using the directive.
|
file using the directive. Multiple includes of the same file are safe.
|
||||||
|
|
||||||
|
|
||||||
=== Complex types ===
|
=== Complex types ===
|
||||||
@@ -230,14 +230,13 @@ node structure that can be used to chain together a list of such types in
|
|||||||
case we want to accept/return a list of this type with a command), and a
|
case we want to accept/return a list of this type with a command), and a
|
||||||
command which takes that type as a parameter and returns the same type:
|
command which takes that type as a parameter and returns the same type:
|
||||||
|
|
||||||
mdroth@illuin:~/w/qemu2.git$ cat example-schema.json
|
$ cat example-schema.json
|
||||||
{ 'type': 'UserDefOne',
|
{ 'type': 'UserDefOne',
|
||||||
'data': { 'integer': 'int', 'string': 'str' } }
|
'data': { 'integer': 'int', 'string': 'str' } }
|
||||||
|
|
||||||
{ 'command': 'my-command',
|
{ 'command': 'my-command',
|
||||||
'data': {'arg1': 'UserDefOne'},
|
'data': {'arg1': 'UserDefOne'},
|
||||||
'returns': 'UserDefOne' }
|
'returns': 'UserDefOne' }
|
||||||
mdroth@illuin:~/w/qemu2.git$
|
|
||||||
|
|
||||||
=== scripts/qapi-types.py ===
|
=== scripts/qapi-types.py ===
|
||||||
|
|
||||||
@@ -255,14 +254,25 @@ created code.
|
|||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
mdroth@illuin:~/w/qemu2.git$ python scripts/qapi-types.py \
|
$ python scripts/qapi-types.py --output-dir="qapi-generated" \
|
||||||
--output-dir="qapi-generated" --prefix="example-" --input-file=example-schema.json
|
--prefix="example-" --input-file=example-schema.json
|
||||||
mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qapi-types.c
|
$ cat qapi-generated/example-qapi-types.c
|
||||||
/* AUTOMATICALLY GENERATED, DO NOT MODIFY */
|
[Uninteresting stuff omitted...]
|
||||||
|
|
||||||
#include "qapi/qapi-dealloc-visitor.h"
|
void qapi_free_UserDefOneList(UserDefOneList * obj)
|
||||||
#include "example-qapi-types.h"
|
{
|
||||||
#include "example-qapi-visit.h"
|
QapiDeallocVisitor *md;
|
||||||
|
Visitor *v;
|
||||||
|
|
||||||
|
if (!obj) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
md = qapi_dealloc_visitor_new();
|
||||||
|
v = qapi_dealloc_get_visitor(md);
|
||||||
|
visit_type_UserDefOneList(v, &obj, NULL, NULL);
|
||||||
|
qapi_dealloc_visitor_cleanup(md);
|
||||||
|
}
|
||||||
|
|
||||||
void qapi_free_UserDefOne(UserDefOne * obj)
|
void qapi_free_UserDefOne(UserDefOne * obj)
|
||||||
{
|
{
|
||||||
@@ -279,32 +289,38 @@ Example:
|
|||||||
qapi_dealloc_visitor_cleanup(md);
|
qapi_dealloc_visitor_cleanup(md);
|
||||||
}
|
}
|
||||||
|
|
||||||
mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qapi-types.h
|
$ cat qapi-generated/example-qapi-types.h
|
||||||
/* AUTOMATICALLY GENERATED, DO NOT MODIFY */
|
[Uninteresting stuff omitted...]
|
||||||
#ifndef QAPI_GENERATED_EXAMPLE_QAPI_TYPES
|
|
||||||
#define QAPI_GENERATED_EXAMPLE_QAPI_TYPES
|
|
||||||
|
|
||||||
#include "qapi/qapi-types-core.h"
|
#ifndef EXAMPLE_QAPI_TYPES_H
|
||||||
|
#define EXAMPLE_QAPI_TYPES_H
|
||||||
|
|
||||||
|
[Builtin types omitted...]
|
||||||
|
|
||||||
typedef struct UserDefOne UserDefOne;
|
typedef struct UserDefOne UserDefOne;
|
||||||
|
|
||||||
typedef struct UserDefOneList
|
typedef struct UserDefOneList
|
||||||
{
|
{
|
||||||
|
union {
|
||||||
UserDefOne *value;
|
UserDefOne *value;
|
||||||
|
uint64_t padding;
|
||||||
|
};
|
||||||
struct UserDefOneList *next;
|
struct UserDefOneList *next;
|
||||||
} UserDefOneList;
|
} UserDefOneList;
|
||||||
|
|
||||||
|
[Functions on builtin types omitted...]
|
||||||
|
|
||||||
struct UserDefOne
|
struct UserDefOne
|
||||||
{
|
{
|
||||||
int64_t integer;
|
int64_t integer;
|
||||||
char * string;
|
char * string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void qapi_free_UserDefOneList(UserDefOneList * obj);
|
||||||
void qapi_free_UserDefOne(UserDefOne * obj);
|
void qapi_free_UserDefOne(UserDefOne * obj);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
=== scripts/qapi-visit.py ===
|
=== scripts/qapi-visit.py ===
|
||||||
|
|
||||||
Used to generate the visitor functions used to walk through and convert
|
Used to generate the visitor functions used to walk through and convert
|
||||||
@@ -325,51 +341,78 @@ $(prefix)qapi-visit.h: declarations for previously mentioned visitor
|
|||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
mdroth@illuin:~/w/qemu2.git$ python scripts/qapi-visit.py \
|
$ python scripts/qapi-visit.py --output-dir="qapi-generated"
|
||||||
--output-dir="qapi-generated" --prefix="example-" --input-file=example-schema.json
|
--prefix="example-" --input-file=example-schema.json
|
||||||
mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qapi-visit.c
|
$ cat qapi-generated/example-qapi-visit.c
|
||||||
/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
|
[Uninteresting stuff omitted...]
|
||||||
|
|
||||||
#include "example-qapi-visit.h"
|
static void visit_type_UserDefOne_fields(Visitor *m, UserDefOne ** obj, Error **errp)
|
||||||
|
{
|
||||||
|
Error *err = NULL;
|
||||||
|
visit_type_int(m, &(*obj)->integer, "integer", &err);
|
||||||
|
if (err) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
visit_type_str(m, &(*obj)->string, "string", &err);
|
||||||
|
if (err) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
error_propagate(errp, err);
|
||||||
|
}
|
||||||
|
|
||||||
void visit_type_UserDefOne(Visitor *m, UserDefOne ** obj, const char *name, Error **errp)
|
void visit_type_UserDefOne(Visitor *m, UserDefOne ** obj, const char *name, Error **errp)
|
||||||
{
|
{
|
||||||
visit_start_struct(m, (void **)obj, "UserDefOne", name, sizeof(UserDefOne), errp);
|
Error *err = NULL;
|
||||||
visit_type_int(m, (obj && *obj) ? &(*obj)->integer : NULL, "integer", errp);
|
|
||||||
visit_type_str(m, (obj && *obj) ? &(*obj)->string : NULL, "string", errp);
|
visit_start_struct(m, (void **)obj, "UserDefOne", name, sizeof(UserDefOne), &err);
|
||||||
visit_end_struct(m, errp);
|
if (!err) {
|
||||||
|
if (*obj) {
|
||||||
|
visit_type_UserDefOne_fields(m, obj, errp);
|
||||||
|
}
|
||||||
|
visit_end_struct(m, &err);
|
||||||
|
}
|
||||||
|
error_propagate(errp, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
void visit_type_UserDefOneList(Visitor *m, UserDefOneList ** obj, const char *name, Error **errp)
|
void visit_type_UserDefOneList(Visitor *m, UserDefOneList ** obj, const char *name, Error **errp)
|
||||||
{
|
{
|
||||||
GenericList *i, **prev = (GenericList **)obj;
|
Error *err = NULL;
|
||||||
|
GenericList *i, **prev;
|
||||||
|
|
||||||
visit_start_list(m, name, errp);
|
visit_start_list(m, name, &err);
|
||||||
|
if (err) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
for (; (i = visit_next_list(m, prev, errp)) != NULL; prev = &i) {
|
for (prev = (GenericList **)obj;
|
||||||
|
!err && (i = visit_next_list(m, prev, &err)) != NULL;
|
||||||
|
prev = &i) {
|
||||||
UserDefOneList *native_i = (UserDefOneList *)i;
|
UserDefOneList *native_i = (UserDefOneList *)i;
|
||||||
visit_type_UserDefOne(m, &native_i->value, NULL, errp);
|
visit_type_UserDefOne(m, &native_i->value, NULL, &err);
|
||||||
}
|
}
|
||||||
|
|
||||||
visit_end_list(m, errp);
|
error_propagate(errp, err);
|
||||||
|
err = NULL;
|
||||||
|
visit_end_list(m, &err);
|
||||||
|
out:
|
||||||
|
error_propagate(errp, err);
|
||||||
}
|
}
|
||||||
mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qapi-visit.h
|
$ python scripts/qapi-commands.py --output-dir="qapi-generated" \
|
||||||
/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
|
--prefix="example-" --input-file=example-schema.json
|
||||||
|
$ cat qapi-generated/example-qapi-visit.h
|
||||||
|
[Uninteresting stuff omitted...]
|
||||||
|
|
||||||
#ifndef QAPI_GENERATED_EXAMPLE_QAPI_VISIT
|
#ifndef EXAMPLE_QAPI_VISIT_H
|
||||||
#define QAPI_GENERATED_EXAMPLE_QAPI_VISIT
|
#define EXAMPLE_QAPI_VISIT_H
|
||||||
|
|
||||||
#include "qapi/qapi-visit-core.h"
|
[Visitors for builtin types omitted...]
|
||||||
#include "example-qapi-types.h"
|
|
||||||
|
|
||||||
void visit_type_UserDefOne(Visitor *m, UserDefOne ** obj, const char *name, Error **errp);
|
void visit_type_UserDefOne(Visitor *m, UserDefOne ** obj, const char *name, Error **errp);
|
||||||
void visit_type_UserDefOneList(Visitor *m, UserDefOneList ** obj, const char *name, Error **errp);
|
void visit_type_UserDefOneList(Visitor *m, UserDefOneList ** obj, const char *name, Error **errp);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
mdroth@illuin:~/w/qemu2.git$
|
|
||||||
|
|
||||||
(The actual structure of the visit_type_* functions is a bit more complex
|
|
||||||
in order to propagate errors correctly and avoid leaking memory).
|
|
||||||
|
|
||||||
=== scripts/qapi-commands.py ===
|
=== scripts/qapi-commands.py ===
|
||||||
|
|
||||||
@@ -390,77 +433,80 @@ $(prefix)qmp-commands.h: Function prototypes for the QMP commands
|
|||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qmp-marshal.c
|
$ cat qapi-generated/example-qmp-marshal.c
|
||||||
/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
|
[Uninteresting stuff omitted...]
|
||||||
|
|
||||||
#include "qemu-objects.h"
|
|
||||||
#include "qapi/qmp-core.h"
|
|
||||||
#include "qapi/qapi-visit-core.h"
|
|
||||||
#include "qapi/qmp-output-visitor.h"
|
|
||||||
#include "qapi/qmp-input-visitor.h"
|
|
||||||
#include "qapi/qapi-dealloc-visitor.h"
|
|
||||||
#include "example-qapi-types.h"
|
|
||||||
#include "example-qapi-visit.h"
|
|
||||||
|
|
||||||
#include "example-qmp-commands.h"
|
|
||||||
static void qmp_marshal_output_my_command(UserDefOne * ret_in, QObject **ret_out, Error **errp)
|
static void qmp_marshal_output_my_command(UserDefOne * ret_in, QObject **ret_out, Error **errp)
|
||||||
{
|
{
|
||||||
QapiDeallocVisitor *md = qapi_dealloc_visitor_new();
|
Error *local_err = NULL;
|
||||||
QmpOutputVisitor *mo = qmp_output_visitor_new();
|
QmpOutputVisitor *mo = qmp_output_visitor_new();
|
||||||
|
QapiDeallocVisitor *md;
|
||||||
Visitor *v;
|
Visitor *v;
|
||||||
|
|
||||||
v = qmp_output_get_visitor(mo);
|
v = qmp_output_get_visitor(mo);
|
||||||
visit_type_UserDefOne(v, &ret_in, "unused", errp);
|
visit_type_UserDefOne(v, &ret_in, "unused", &local_err);
|
||||||
v = qapi_dealloc_get_visitor(md);
|
if (local_err) {
|
||||||
visit_type_UserDefOne(v, &ret_in, "unused", errp);
|
goto out;
|
||||||
qapi_dealloc_visitor_cleanup(md);
|
}
|
||||||
|
|
||||||
|
|
||||||
*ret_out = qmp_output_get_qobject(mo);
|
*ret_out = qmp_output_get_qobject(mo);
|
||||||
|
|
||||||
|
out:
|
||||||
|
error_propagate(errp, local_err);
|
||||||
|
qmp_output_visitor_cleanup(mo);
|
||||||
|
md = qapi_dealloc_visitor_new();
|
||||||
|
v = qapi_dealloc_get_visitor(md);
|
||||||
|
visit_type_UserDefOne(v, &ret_in, "unused", NULL);
|
||||||
|
qapi_dealloc_visitor_cleanup(md);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void qmp_marshal_input_my_command(QmpState *qmp__sess, QDict *args, QObject **ret, Error **errp)
|
static void qmp_marshal_input_my_command(QDict *args, QObject **ret, Error **errp)
|
||||||
{
|
{
|
||||||
|
Error *local_err = NULL;
|
||||||
UserDefOne * retval = NULL;
|
UserDefOne * retval = NULL;
|
||||||
QmpInputVisitor *mi;
|
QmpInputVisitor *mi = qmp_input_visitor_new_strict(QOBJECT(args));
|
||||||
QapiDeallocVisitor *md;
|
QapiDeallocVisitor *md;
|
||||||
Visitor *v;
|
Visitor *v;
|
||||||
UserDefOne * arg1 = NULL;
|
UserDefOne * arg1 = NULL;
|
||||||
|
|
||||||
mi = qmp_input_visitor_new(QOBJECT(args));
|
|
||||||
v = qmp_input_get_visitor(mi);
|
v = qmp_input_get_visitor(mi);
|
||||||
visit_type_UserDefOne(v, &arg1, "arg1", errp);
|
visit_type_UserDefOne(v, &arg1, "arg1", &local_err);
|
||||||
|
if (local_err) {
|
||||||
if (error_is_set(errp)) {
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
retval = qmp_my_command(arg1, errp);
|
|
||||||
qmp_marshal_output_my_command(retval, ret, errp);
|
retval = qmp_my_command(arg1, &local_err);
|
||||||
|
if (local_err) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
qmp_marshal_output_my_command(retval, ret, &local_err);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
error_propagate(errp, local_err);
|
||||||
|
qmp_input_visitor_cleanup(mi);
|
||||||
md = qapi_dealloc_visitor_new();
|
md = qapi_dealloc_visitor_new();
|
||||||
v = qapi_dealloc_get_visitor(md);
|
v = qapi_dealloc_get_visitor(md);
|
||||||
visit_type_UserDefOne(v, &arg1, "arg1", errp);
|
visit_type_UserDefOne(v, &arg1, "arg1", NULL);
|
||||||
qapi_dealloc_visitor_cleanup(md);
|
qapi_dealloc_visitor_cleanup(md);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void qmp_init_marshal(void)
|
static void qmp_init_marshal(void)
|
||||||
{
|
{
|
||||||
qmp_register_command("my-command", qmp_marshal_input_my_command);
|
qmp_register_command("my-command", qmp_marshal_input_my_command, QCO_NO_OPTIONS);
|
||||||
}
|
}
|
||||||
|
|
||||||
qapi_init(qmp_init_marshal);
|
qapi_init(qmp_init_marshal);
|
||||||
mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qmp-commands.h
|
$ cat qapi-generated/example-qmp-commands.h
|
||||||
/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
|
[Uninteresting stuff omitted...]
|
||||||
|
|
||||||
#ifndef QAPI_GENERATED_EXAMPLE_QMP_COMMANDS
|
#ifndef EXAMPLE_QMP_COMMANDS_H
|
||||||
#define QAPI_GENERATED_EXAMPLE_QMP_COMMANDS
|
#define EXAMPLE_QMP_COMMANDS_H
|
||||||
|
|
||||||
#include "example-qapi-types.h"
|
#include "example-qapi-types.h"
|
||||||
#include "error.h"
|
#include "qapi/qmp/qdict.h"
|
||||||
|
#include "qapi/error.h"
|
||||||
|
|
||||||
UserDefOne * qmp_my_command(UserDefOne * arg1, Error **errp);
|
UserDefOne * qmp_my_command(UserDefOne * arg1, Error **errp);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
mdroth@illuin:~/w/qemu2.git$
|
|
||||||
|
|||||||
@@ -556,6 +556,7 @@ ETEXI
|
|||||||
.params = "keys [hold_ms]",
|
.params = "keys [hold_ms]",
|
||||||
.help = "send keys to the VM (e.g. 'sendkey ctrl-alt-f1', default hold time=100 ms)",
|
.help = "send keys to the VM (e.g. 'sendkey ctrl-alt-f1', default hold time=100 ms)",
|
||||||
.mhandler.cmd = hmp_send_key,
|
.mhandler.cmd = hmp_send_key,
|
||||||
|
.command_completion = sendkey_completion,
|
||||||
},
|
},
|
||||||
|
|
||||||
STEXI
|
STEXI
|
||||||
@@ -1233,9 +1234,10 @@ ETEXI
|
|||||||
{
|
{
|
||||||
.name = "netdev_add",
|
.name = "netdev_add",
|
||||||
.args_type = "netdev:O",
|
.args_type = "netdev:O",
|
||||||
.params = "[user|tap|socket|hubport|netmap],id=str[,prop=value][,...]",
|
.params = "[user|tap|socket|vde|bridge|hubport|netmap],id=str[,prop=value][,...]",
|
||||||
.help = "add host network device",
|
.help = "add host network device",
|
||||||
.mhandler.cmd = hmp_netdev_add,
|
.mhandler.cmd = hmp_netdev_add,
|
||||||
|
.command_completion = netdev_add_completion,
|
||||||
},
|
},
|
||||||
|
|
||||||
STEXI
|
STEXI
|
||||||
@@ -1250,6 +1252,7 @@ ETEXI
|
|||||||
.params = "id",
|
.params = "id",
|
||||||
.help = "remove host network device",
|
.help = "remove host network device",
|
||||||
.mhandler.cmd = hmp_netdev_del,
|
.mhandler.cmd = hmp_netdev_del,
|
||||||
|
.command_completion = netdev_del_completion,
|
||||||
},
|
},
|
||||||
|
|
||||||
STEXI
|
STEXI
|
||||||
@@ -1339,6 +1342,7 @@ ETEXI
|
|||||||
.params = "name on|off",
|
.params = "name on|off",
|
||||||
.help = "change the link status of a network adapter",
|
.help = "change the link status of a network adapter",
|
||||||
.mhandler.cmd = hmp_set_link,
|
.mhandler.cmd = hmp_set_link,
|
||||||
|
.command_completion = set_link_completion,
|
||||||
},
|
},
|
||||||
|
|
||||||
STEXI
|
STEXI
|
||||||
@@ -1622,6 +1626,7 @@ ETEXI
|
|||||||
.params = "args",
|
.params = "args",
|
||||||
.help = "add chardev",
|
.help = "add chardev",
|
||||||
.mhandler.cmd = hmp_chardev_add,
|
.mhandler.cmd = hmp_chardev_add,
|
||||||
|
.command_completion = chardev_add_completion,
|
||||||
},
|
},
|
||||||
|
|
||||||
STEXI
|
STEXI
|
||||||
@@ -1638,6 +1643,7 @@ ETEXI
|
|||||||
.params = "id",
|
.params = "id",
|
||||||
.help = "remove chardev",
|
.help = "remove chardev",
|
||||||
.mhandler.cmd = hmp_chardev_remove,
|
.mhandler.cmd = hmp_chardev_remove,
|
||||||
|
.command_completion = chardev_remove_completion,
|
||||||
},
|
},
|
||||||
|
|
||||||
STEXI
|
STEXI
|
||||||
|
|||||||
16
hmp.c
16
hmp.c
@@ -1388,6 +1388,7 @@ void hmp_netdev_del(Monitor *mon, const QDict *qdict)
|
|||||||
void hmp_object_add(Monitor *mon, const QDict *qdict)
|
void hmp_object_add(Monitor *mon, const QDict *qdict)
|
||||||
{
|
{
|
||||||
Error *err = NULL;
|
Error *err = NULL;
|
||||||
|
Error *err_end = NULL;
|
||||||
QemuOpts *opts;
|
QemuOpts *opts;
|
||||||
char *type = NULL;
|
char *type = NULL;
|
||||||
char *id = NULL;
|
char *id = NULL;
|
||||||
@@ -1411,24 +1412,23 @@ void hmp_object_add(Monitor *mon, const QDict *qdict)
|
|||||||
qdict_del(pdict, "qom-type");
|
qdict_del(pdict, "qom-type");
|
||||||
visit_type_str(opts_get_visitor(ov), &type, "qom-type", &err);
|
visit_type_str(opts_get_visitor(ov), &type, "qom-type", &err);
|
||||||
if (err) {
|
if (err) {
|
||||||
goto out_clean;
|
goto out_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
qdict_del(pdict, "id");
|
qdict_del(pdict, "id");
|
||||||
visit_type_str(opts_get_visitor(ov), &id, "id", &err);
|
visit_type_str(opts_get_visitor(ov), &id, "id", &err);
|
||||||
if (err) {
|
if (err) {
|
||||||
goto out_clean;
|
goto out_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
object_add(type, id, pdict, opts_get_visitor(ov), &err);
|
object_add(type, id, pdict, opts_get_visitor(ov), &err);
|
||||||
if (err) {
|
|
||||||
goto out_clean;
|
out_end:
|
||||||
}
|
visit_end_struct(opts_get_visitor(ov), &err_end);
|
||||||
visit_end_struct(opts_get_visitor(ov), &err);
|
if (!err && err_end) {
|
||||||
if (err) {
|
|
||||||
qmp_object_del(id, NULL);
|
qmp_object_del(id, NULL);
|
||||||
}
|
}
|
||||||
|
error_propagate(&err, err_end);
|
||||||
out_clean:
|
out_clean:
|
||||||
opts_visitor_cleanup(ov);
|
opts_visitor_cleanup(ov);
|
||||||
|
|
||||||
|
|||||||
6
hmp.h
6
hmp.h
@@ -97,5 +97,11 @@ void object_add_completion(ReadLineState *rs, int nb_args, const char *str);
|
|||||||
void object_del_completion(ReadLineState *rs, int nb_args, const char *str);
|
void object_del_completion(ReadLineState *rs, int nb_args, const char *str);
|
||||||
void device_add_completion(ReadLineState *rs, int nb_args, const char *str);
|
void device_add_completion(ReadLineState *rs, int nb_args, const char *str);
|
||||||
void device_del_completion(ReadLineState *rs, int nb_args, const char *str);
|
void device_del_completion(ReadLineState *rs, int nb_args, const char *str);
|
||||||
|
void sendkey_completion(ReadLineState *rs, int nb_args, const char *str);
|
||||||
|
void chardev_remove_completion(ReadLineState *rs, int nb_args, const char *str);
|
||||||
|
void chardev_add_completion(ReadLineState *rs, int nb_args, const char *str);
|
||||||
|
void set_link_completion(ReadLineState *rs, int nb_args, const char *str);
|
||||||
|
void netdev_add_completion(ReadLineState *rs, int nb_args, const char *str);
|
||||||
|
void netdev_del_completion(ReadLineState *rs, int nb_args, const char *str);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -245,7 +245,7 @@ static void intel_hda_update_int_sts(IntelHDAState *d)
|
|||||||
|
|
||||||
/* update global status */
|
/* update global status */
|
||||||
if (sts & d->int_ctl) {
|
if (sts & d->int_ctl) {
|
||||||
sts |= (1 << 31);
|
sts |= (1U << 31);
|
||||||
}
|
}
|
||||||
|
|
||||||
d->int_sts = sts;
|
d->int_sts = sts;
|
||||||
@@ -257,7 +257,7 @@ static void intel_hda_update_irq(IntelHDAState *d)
|
|||||||
int level;
|
int level;
|
||||||
|
|
||||||
intel_hda_update_int_sts(d);
|
intel_hda_update_int_sts(d);
|
||||||
if (d->int_sts & (1 << 31) && d->int_ctl & (1 << 31)) {
|
if (d->int_sts & (1U << 31) && d->int_ctl & (1U << 31)) {
|
||||||
level = 1;
|
level = 1;
|
||||||
} else {
|
} else {
|
||||||
level = 0;
|
level = 0;
|
||||||
@@ -574,7 +574,7 @@ static void intel_hda_set_st_ctl(IntelHDAState *d, const IntelHDAReg *reg, uint3
|
|||||||
if (st->ctl & 0x01) {
|
if (st->ctl & 0x01) {
|
||||||
/* reset */
|
/* reset */
|
||||||
dprint(d, 1, "st #%d: reset\n", reg->stream);
|
dprint(d, 1, "st #%d: reset\n", reg->stream);
|
||||||
st->ctl = 0;
|
st->ctl = SD_STS_FIFO_READY << 24;
|
||||||
}
|
}
|
||||||
if ((st->ctl & 0x02) != (old & 0x02)) {
|
if ((st->ctl & 0x02) != (old & 0x02)) {
|
||||||
uint32_t stnr = (st->ctl >> 20) & 0x0f;
|
uint32_t stnr = (st->ctl >> 20) & 0x0f;
|
||||||
@@ -829,6 +829,7 @@ static const struct IntelHDAReg regtab[] = {
|
|||||||
.wclear = 0x1c000000, \
|
.wclear = 0x1c000000, \
|
||||||
.offset = offsetof(IntelHDAState, st[_i].ctl), \
|
.offset = offsetof(IntelHDAState, st[_i].ctl), \
|
||||||
.whandler = intel_hda_set_st_ctl, \
|
.whandler = intel_hda_set_st_ctl, \
|
||||||
|
.reset = SD_STS_FIFO_READY << 24 \
|
||||||
}, \
|
}, \
|
||||||
[ ST_REG(_i, ICH6_REG_SD_LPIB) ] = { \
|
[ ST_REG(_i, ICH6_REG_SD_LPIB) ] = { \
|
||||||
.stream = _i, \
|
.stream = _i, \
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#include "hw/hw.h"
|
#include "hw/hw.h"
|
||||||
#include "hw/pci/pci.h"
|
#include "hw/pci/pci.h"
|
||||||
#include "sysemu/dma.h"
|
#include "sysemu/dma.h"
|
||||||
|
#include "hw/pci/msi.h"
|
||||||
#include "hw/pci/msix.h"
|
#include "hw/pci/msix.h"
|
||||||
#include "qemu/iov.h"
|
#include "qemu/iov.h"
|
||||||
#include "hw/scsi/scsi.h"
|
#include "hw/scsi/scsi.h"
|
||||||
@@ -43,9 +44,11 @@
|
|||||||
|
|
||||||
#define MEGASAS_FLAG_USE_JBOD 0
|
#define MEGASAS_FLAG_USE_JBOD 0
|
||||||
#define MEGASAS_MASK_USE_JBOD (1 << MEGASAS_FLAG_USE_JBOD)
|
#define MEGASAS_MASK_USE_JBOD (1 << MEGASAS_FLAG_USE_JBOD)
|
||||||
#define MEGASAS_FLAG_USE_MSIX 1
|
#define MEGASAS_FLAG_USE_MSI 1
|
||||||
|
#define MEGASAS_MASK_USE_MSI (1 << MEGASAS_FLAG_USE_MSI)
|
||||||
|
#define MEGASAS_FLAG_USE_MSIX 2
|
||||||
#define MEGASAS_MASK_USE_MSIX (1 << MEGASAS_FLAG_USE_MSIX)
|
#define MEGASAS_MASK_USE_MSIX (1 << MEGASAS_FLAG_USE_MSIX)
|
||||||
#define MEGASAS_FLAG_USE_QUEUE64 2
|
#define MEGASAS_FLAG_USE_QUEUE64 3
|
||||||
#define MEGASAS_MASK_USE_QUEUE64 (1 << MEGASAS_FLAG_USE_QUEUE64)
|
#define MEGASAS_MASK_USE_QUEUE64 (1 << MEGASAS_FLAG_USE_QUEUE64)
|
||||||
|
|
||||||
static const char *mfi_frame_desc[] = {
|
static const char *mfi_frame_desc[] = {
|
||||||
@@ -132,6 +135,11 @@ static bool megasas_use_queue64(MegasasState *s)
|
|||||||
return s->flags & MEGASAS_MASK_USE_QUEUE64;
|
return s->flags & MEGASAS_MASK_USE_QUEUE64;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool megasas_use_msi(MegasasState *s)
|
||||||
|
{
|
||||||
|
return s->flags & MEGASAS_MASK_USE_MSI;
|
||||||
|
}
|
||||||
|
|
||||||
static bool megasas_use_msix(MegasasState *s)
|
static bool megasas_use_msix(MegasasState *s)
|
||||||
{
|
{
|
||||||
return s->flags & MEGASAS_MASK_USE_MSIX;
|
return s->flags & MEGASAS_MASK_USE_MSIX;
|
||||||
@@ -538,6 +546,9 @@ static void megasas_complete_frame(MegasasState *s, uint64_t context)
|
|||||||
if (msix_enabled(pci_dev)) {
|
if (msix_enabled(pci_dev)) {
|
||||||
trace_megasas_msix_raise(0);
|
trace_megasas_msix_raise(0);
|
||||||
msix_notify(pci_dev, 0);
|
msix_notify(pci_dev, 0);
|
||||||
|
} else if (msi_enabled(pci_dev)) {
|
||||||
|
trace_megasas_msi_raise(0);
|
||||||
|
msi_notify(pci_dev, 0);
|
||||||
} else {
|
} else {
|
||||||
trace_megasas_irq_raise();
|
trace_megasas_irq_raise();
|
||||||
pci_irq_assert(pci_dev);
|
pci_irq_assert(pci_dev);
|
||||||
@@ -1106,6 +1117,21 @@ static int megasas_dcmd_ld_get_list(MegasasState *s, MegasasCmd *cmd)
|
|||||||
return MFI_STAT_OK;
|
return MFI_STAT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int megasas_dcmd_ld_list_query(MegasasState *s, MegasasCmd *cmd)
|
||||||
|
{
|
||||||
|
uint16_t flags;
|
||||||
|
|
||||||
|
/* mbox0 contains flags */
|
||||||
|
flags = le16_to_cpu(cmd->frame->dcmd.mbox[0]);
|
||||||
|
trace_megasas_dcmd_ld_list_query(cmd->index, flags);
|
||||||
|
if (flags == MR_LD_QUERY_TYPE_ALL ||
|
||||||
|
flags == MR_LD_QUERY_TYPE_EXPOSED_TO_HOST) {
|
||||||
|
return megasas_dcmd_ld_get_list(s, cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
return MFI_STAT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
static int megasas_ld_get_info_submit(SCSIDevice *sdev, int lun,
|
static int megasas_ld_get_info_submit(SCSIDevice *sdev, int lun,
|
||||||
MegasasCmd *cmd)
|
MegasasCmd *cmd)
|
||||||
{
|
{
|
||||||
@@ -1409,6 +1435,8 @@ static const struct dcmd_cmd_tbl_t {
|
|||||||
megasas_dcmd_dummy },
|
megasas_dcmd_dummy },
|
||||||
{ MFI_DCMD_LD_GET_LIST, "LD_GET_LIST",
|
{ MFI_DCMD_LD_GET_LIST, "LD_GET_LIST",
|
||||||
megasas_dcmd_ld_get_list},
|
megasas_dcmd_ld_get_list},
|
||||||
|
{ MFI_DCMD_LD_LIST_QUERY, "LD_LIST_QUERY",
|
||||||
|
megasas_dcmd_ld_list_query },
|
||||||
{ MFI_DCMD_LD_GET_INFO, "LD_GET_INFO",
|
{ MFI_DCMD_LD_GET_INFO, "LD_GET_INFO",
|
||||||
megasas_dcmd_ld_get_info },
|
megasas_dcmd_ld_get_info },
|
||||||
{ MFI_DCMD_LD_GET_PROP, "LD_GET_PROP",
|
{ MFI_DCMD_LD_GET_PROP, "LD_GET_PROP",
|
||||||
@@ -1939,12 +1967,20 @@ static void megasas_mmio_write(void *opaque, hwaddr addr,
|
|||||||
break;
|
break;
|
||||||
case MFI_OMSK:
|
case MFI_OMSK:
|
||||||
s->intr_mask = val;
|
s->intr_mask = val;
|
||||||
if (!megasas_intr_enabled(s) && !msix_enabled(pci_dev)) {
|
if (!megasas_intr_enabled(s) &&
|
||||||
|
!msi_enabled(pci_dev) &&
|
||||||
|
!msix_enabled(pci_dev)) {
|
||||||
trace_megasas_irq_lower();
|
trace_megasas_irq_lower();
|
||||||
pci_irq_deassert(pci_dev);
|
pci_irq_deassert(pci_dev);
|
||||||
}
|
}
|
||||||
if (megasas_intr_enabled(s)) {
|
if (megasas_intr_enabled(s)) {
|
||||||
|
if (msix_enabled(pci_dev)) {
|
||||||
|
trace_megasas_msix_enabled(0);
|
||||||
|
} else if (msi_enabled(pci_dev)) {
|
||||||
|
trace_megasas_msi_enabled(0);
|
||||||
|
} else {
|
||||||
trace_megasas_intr_enabled();
|
trace_megasas_intr_enabled();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
trace_megasas_intr_disabled();
|
trace_megasas_intr_disabled();
|
||||||
}
|
}
|
||||||
@@ -2068,6 +2104,7 @@ static const VMStateDescription vmstate_megasas = {
|
|||||||
.minimum_version_id_old = 0,
|
.minimum_version_id_old = 0,
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_PCI_DEVICE(parent_obj, MegasasState),
|
VMSTATE_PCI_DEVICE(parent_obj, MegasasState),
|
||||||
|
VMSTATE_MSIX(parent_obj, MegasasState),
|
||||||
|
|
||||||
VMSTATE_INT32(fw_state, MegasasState),
|
VMSTATE_INT32(fw_state, MegasasState),
|
||||||
VMSTATE_INT32(intr_mask, MegasasState),
|
VMSTATE_INT32(intr_mask, MegasasState),
|
||||||
@@ -2083,9 +2120,12 @@ static void megasas_scsi_uninit(PCIDevice *d)
|
|||||||
{
|
{
|
||||||
MegasasState *s = MEGASAS(d);
|
MegasasState *s = MEGASAS(d);
|
||||||
|
|
||||||
#ifdef USE_MSIX
|
if (megasas_use_msix(s)) {
|
||||||
msix_uninit(d, &s->mmio_io);
|
msix_uninit(d, &s->mmio_io, &s->mmio_io);
|
||||||
#endif
|
}
|
||||||
|
if (megasas_use_msi(s)) {
|
||||||
|
msi_uninit(d);
|
||||||
|
}
|
||||||
memory_region_destroy(&s->mmio_io);
|
memory_region_destroy(&s->mmio_io);
|
||||||
memory_region_destroy(&s->port_io);
|
memory_region_destroy(&s->port_io);
|
||||||
memory_region_destroy(&s->queue_io);
|
memory_region_destroy(&s->queue_io);
|
||||||
@@ -2124,15 +2164,15 @@ static int megasas_scsi_init(PCIDevice *dev)
|
|||||||
memory_region_init_io(&s->queue_io, OBJECT(s), &megasas_queue_ops, s,
|
memory_region_init_io(&s->queue_io, OBJECT(s), &megasas_queue_ops, s,
|
||||||
"megasas-queue", 0x40000);
|
"megasas-queue", 0x40000);
|
||||||
|
|
||||||
#ifdef USE_MSIX
|
if (megasas_use_msi(s) &&
|
||||||
/* MSI-X support is currently broken */
|
msi_init(dev, 0x50, 1, true, false)) {
|
||||||
|
s->flags &= ~MEGASAS_MASK_USE_MSI;
|
||||||
|
}
|
||||||
if (megasas_use_msix(s) &&
|
if (megasas_use_msix(s) &&
|
||||||
msix_init(dev, 15, &s->mmio_io, 0, 0x2000)) {
|
msix_init(dev, 15, &s->mmio_io, 0, 0x2000,
|
||||||
|
&s->mmio_io, 0, 0x3800, 0x68)) {
|
||||||
s->flags &= ~MEGASAS_MASK_USE_MSIX;
|
s->flags &= ~MEGASAS_MASK_USE_MSIX;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
s->flags &= ~MEGASAS_MASK_USE_MSIX;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bar_type = PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64;
|
bar_type = PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64;
|
||||||
pci_register_bar(dev, 0, bar_type, &s->mmio_io);
|
pci_register_bar(dev, 0, bar_type, &s->mmio_io);
|
||||||
@@ -2164,7 +2204,6 @@ static int megasas_scsi_init(PCIDevice *dev)
|
|||||||
s->fw_cmds = MEGASAS_MAX_FRAMES;
|
s->fw_cmds = MEGASAS_MAX_FRAMES;
|
||||||
}
|
}
|
||||||
trace_megasas_init(s->fw_sge, s->fw_cmds,
|
trace_megasas_init(s->fw_sge, s->fw_cmds,
|
||||||
megasas_use_msix(s) ? "MSI-X" : "INTx",
|
|
||||||
megasas_is_jbod(s) ? "jbod" : "raid");
|
megasas_is_jbod(s) ? "jbod" : "raid");
|
||||||
s->fw_luns = (MFI_MAX_LD > MAX_SCSI_DEVS) ?
|
s->fw_luns = (MFI_MAX_LD > MAX_SCSI_DEVS) ?
|
||||||
MAX_SCSI_DEVS : MFI_MAX_LD;
|
MAX_SCSI_DEVS : MFI_MAX_LD;
|
||||||
@@ -2189,6 +2228,13 @@ static int megasas_scsi_init(PCIDevice *dev)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
megasas_write_config(PCIDevice *pci, uint32_t addr, uint32_t val, int len)
|
||||||
|
{
|
||||||
|
pci_default_write_config(pci, addr, val, len);
|
||||||
|
msi_write_config(pci, addr, val, len);
|
||||||
|
}
|
||||||
|
|
||||||
static Property megasas_properties[] = {
|
static Property megasas_properties[] = {
|
||||||
DEFINE_PROP_UINT32("max_sge", MegasasState, fw_sge,
|
DEFINE_PROP_UINT32("max_sge", MegasasState, fw_sge,
|
||||||
MEGASAS_DEFAULT_SGE),
|
MEGASAS_DEFAULT_SGE),
|
||||||
@@ -2196,10 +2242,10 @@ static Property megasas_properties[] = {
|
|||||||
MEGASAS_DEFAULT_FRAMES),
|
MEGASAS_DEFAULT_FRAMES),
|
||||||
DEFINE_PROP_STRING("hba_serial", MegasasState, hba_serial),
|
DEFINE_PROP_STRING("hba_serial", MegasasState, hba_serial),
|
||||||
DEFINE_PROP_UINT64("sas_address", MegasasState, sas_addr, 0),
|
DEFINE_PROP_UINT64("sas_address", MegasasState, sas_addr, 0),
|
||||||
#ifdef USE_MSIX
|
DEFINE_PROP_BIT("use_msi", MegasasState, flags,
|
||||||
|
MEGASAS_FLAG_USE_MSI, false),
|
||||||
DEFINE_PROP_BIT("use_msix", MegasasState, flags,
|
DEFINE_PROP_BIT("use_msix", MegasasState, flags,
|
||||||
MEGASAS_FLAG_USE_MSIX, false),
|
MEGASAS_FLAG_USE_MSIX, false),
|
||||||
#endif
|
|
||||||
DEFINE_PROP_BIT("use_jbod", MegasasState, flags,
|
DEFINE_PROP_BIT("use_jbod", MegasasState, flags,
|
||||||
MEGASAS_FLAG_USE_JBOD, false),
|
MEGASAS_FLAG_USE_JBOD, false),
|
||||||
DEFINE_PROP_END_OF_LIST(),
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
@@ -2222,6 +2268,7 @@ static void megasas_class_init(ObjectClass *oc, void *data)
|
|||||||
dc->vmsd = &vmstate_megasas;
|
dc->vmsd = &vmstate_megasas;
|
||||||
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
|
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
|
||||||
dc->desc = "LSI MegaRAID SAS 1078";
|
dc->desc = "LSI MegaRAID SAS 1078";
|
||||||
|
pc->config_write = megasas_write_config;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo megasas_info = {
|
static const TypeInfo megasas_info = {
|
||||||
|
|||||||
@@ -164,6 +164,7 @@ typedef enum {
|
|||||||
MFI_DCMD_PD_BLINK = 0x02070100,
|
MFI_DCMD_PD_BLINK = 0x02070100,
|
||||||
MFI_DCMD_PD_UNBLINK = 0x02070200,
|
MFI_DCMD_PD_UNBLINK = 0x02070200,
|
||||||
MFI_DCMD_LD_GET_LIST = 0x03010000,
|
MFI_DCMD_LD_GET_LIST = 0x03010000,
|
||||||
|
MFI_DCMD_LD_LIST_QUERY = 0x03010100,
|
||||||
MFI_DCMD_LD_GET_INFO = 0x03020000,
|
MFI_DCMD_LD_GET_INFO = 0x03020000,
|
||||||
MFI_DCMD_LD_GET_PROP = 0x03030000,
|
MFI_DCMD_LD_GET_PROP = 0x03030000,
|
||||||
MFI_DCMD_LD_SET_PROP = 0x03040000,
|
MFI_DCMD_LD_SET_PROP = 0x03040000,
|
||||||
@@ -411,6 +412,14 @@ typedef enum {
|
|||||||
MR_PD_QUERY_TYPE_EXPOSED_TO_HOST = 5, /*query for system drives */
|
MR_PD_QUERY_TYPE_EXPOSED_TO_HOST = 5, /*query for system drives */
|
||||||
} mfi_pd_query_type;
|
} mfi_pd_query_type;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
MR_LD_QUERY_TYPE_ALL = 0,
|
||||||
|
MR_LD_QUERY_TYPE_EXPOSED_TO_HOST = 1,
|
||||||
|
MR_LD_QUERY_TYPE_USED_TGT_IDS = 2,
|
||||||
|
MR_LD_QUERY_TYPE_CLUSTER_ACCESS = 3,
|
||||||
|
MR_LD_QUERY_TYPE_CLUSTER_LOCALE = 4,
|
||||||
|
} mfi_ld_query_type;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Other propertities and definitions
|
* Other propertities and definitions
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -2458,21 +2458,27 @@ static int scsi_block_initfn(SCSIDevice *dev)
|
|||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (!s->qdev.conf.bs) {
|
if (!s->qdev.conf.bs) {
|
||||||
error_report("scsi-block: drive property not set");
|
error_report("drive property not set");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check we are using a driver managing SG_IO (version 3 and after) */
|
/* check we are using a driver managing SG_IO (version 3 and after) */
|
||||||
if (bdrv_ioctl(s->qdev.conf.bs, SG_GET_VERSION_NUM, &sg_version) < 0 ||
|
rc = bdrv_ioctl(s->qdev.conf.bs, SG_GET_VERSION_NUM, &sg_version);
|
||||||
sg_version < 30000) {
|
if (rc < 0) {
|
||||||
error_report("scsi-block: scsi generic interface too old");
|
error_report("cannot get SG_IO version number: %s. "
|
||||||
|
"Is this a SCSI device?",
|
||||||
|
strerror(-rc));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (sg_version < 30000) {
|
||||||
|
error_report("scsi generic interface too old");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get device type from INQUIRY data */
|
/* get device type from INQUIRY data */
|
||||||
rc = get_device_type(s);
|
rc = get_device_type(s);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
error_report("scsi-block: INQUIRY failed");
|
error_report("INQUIRY failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -394,6 +394,7 @@ static void scsi_destroy(SCSIDevice *s)
|
|||||||
|
|
||||||
static int scsi_generic_initfn(SCSIDevice *s)
|
static int scsi_generic_initfn(SCSIDevice *s)
|
||||||
{
|
{
|
||||||
|
int rc;
|
||||||
int sg_version;
|
int sg_version;
|
||||||
struct sg_scsi_id scsiid;
|
struct sg_scsi_id scsiid;
|
||||||
|
|
||||||
@@ -412,8 +413,11 @@ static int scsi_generic_initfn(SCSIDevice *s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* check we are using a driver managing SG_IO (version 3 and after */
|
/* check we are using a driver managing SG_IO (version 3 and after */
|
||||||
if (bdrv_ioctl(s->conf.bs, SG_GET_VERSION_NUM, &sg_version) < 0) {
|
rc = bdrv_ioctl(s->conf.bs, SG_GET_VERSION_NUM, &sg_version);
|
||||||
error_report("scsi generic interface not supported");
|
if (rc < 0) {
|
||||||
|
error_report("cannot get SG_IO version number: %s. "
|
||||||
|
"Is this a SCSI device?",
|
||||||
|
strerror(-rc));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (sg_version < 30000) {
|
if (sg_version < 30000) {
|
||||||
|
|||||||
@@ -793,19 +793,46 @@ static const MemoryRegionOps cmos_ops = {
|
|||||||
static void rtc_get_date(Object *obj, Visitor *v, void *opaque,
|
static void rtc_get_date(Object *obj, Visitor *v, void *opaque,
|
||||||
const char *name, Error **errp)
|
const char *name, Error **errp)
|
||||||
{
|
{
|
||||||
|
Error *err = NULL;
|
||||||
RTCState *s = MC146818_RTC(obj);
|
RTCState *s = MC146818_RTC(obj);
|
||||||
struct tm current_tm;
|
struct tm current_tm;
|
||||||
|
|
||||||
rtc_update_time(s);
|
rtc_update_time(s);
|
||||||
rtc_get_time(s, ¤t_tm);
|
rtc_get_time(s, ¤t_tm);
|
||||||
visit_start_struct(v, NULL, "struct tm", name, 0, errp);
|
visit_start_struct(v, NULL, "struct tm", name, 0, &err);
|
||||||
visit_type_int32(v, ¤t_tm.tm_year, "tm_year", errp);
|
if (err) {
|
||||||
visit_type_int32(v, ¤t_tm.tm_mon, "tm_mon", errp);
|
goto out;
|
||||||
visit_type_int32(v, ¤t_tm.tm_mday, "tm_mday", errp);
|
}
|
||||||
visit_type_int32(v, ¤t_tm.tm_hour, "tm_hour", errp);
|
visit_type_int32(v, ¤t_tm.tm_year, "tm_year", &err);
|
||||||
visit_type_int32(v, ¤t_tm.tm_min, "tm_min", errp);
|
if (err) {
|
||||||
visit_type_int32(v, ¤t_tm.tm_sec, "tm_sec", errp);
|
goto out_end;
|
||||||
|
}
|
||||||
|
visit_type_int32(v, ¤t_tm.tm_mon, "tm_mon", &err);
|
||||||
|
if (err) {
|
||||||
|
goto out_end;
|
||||||
|
}
|
||||||
|
visit_type_int32(v, ¤t_tm.tm_mday, "tm_mday", &err);
|
||||||
|
if (err) {
|
||||||
|
goto out_end;
|
||||||
|
}
|
||||||
|
visit_type_int32(v, ¤t_tm.tm_hour, "tm_hour", &err);
|
||||||
|
if (err) {
|
||||||
|
goto out_end;
|
||||||
|
}
|
||||||
|
visit_type_int32(v, ¤t_tm.tm_min, "tm_min", &err);
|
||||||
|
if (err) {
|
||||||
|
goto out_end;
|
||||||
|
}
|
||||||
|
visit_type_int32(v, ¤t_tm.tm_sec, "tm_sec", &err);
|
||||||
|
if (err) {
|
||||||
|
goto out_end;
|
||||||
|
}
|
||||||
|
out_end:
|
||||||
|
error_propagate(errp, err);
|
||||||
|
err = NULL;
|
||||||
visit_end_struct(v, errp);
|
visit_end_struct(v, errp);
|
||||||
|
out:
|
||||||
|
error_propagate(errp, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rtc_realizefn(DeviceState *dev, Error **errp)
|
static void rtc_realizefn(DeviceState *dev, Error **errp)
|
||||||
|
|||||||
@@ -108,6 +108,7 @@ static void balloon_stats_poll_cb(void *opaque)
|
|||||||
static void balloon_stats_get_all(Object *obj, struct Visitor *v,
|
static void balloon_stats_get_all(Object *obj, struct Visitor *v,
|
||||||
void *opaque, const char *name, Error **errp)
|
void *opaque, const char *name, Error **errp)
|
||||||
{
|
{
|
||||||
|
Error *err = NULL;
|
||||||
VirtIOBalloon *s = opaque;
|
VirtIOBalloon *s = opaque;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@@ -116,17 +117,33 @@ static void balloon_stats_get_all(Object *obj, struct Visitor *v,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
visit_start_struct(v, NULL, "guest-stats", name, 0, errp);
|
visit_start_struct(v, NULL, "guest-stats", name, 0, &err);
|
||||||
visit_type_int(v, &s->stats_last_update, "last-update", errp);
|
if (err) {
|
||||||
|
goto out;
|
||||||
visit_start_struct(v, NULL, NULL, "stats", 0, errp);
|
}
|
||||||
for (i = 0; i < VIRTIO_BALLOON_S_NR; i++) {
|
visit_type_int(v, &s->stats_last_update, "last-update", &err);
|
||||||
visit_type_int64(v, (int64_t *) &s->stats[i], balloon_stat_names[i],
|
if (err) {
|
||||||
errp);
|
goto out_end;
|
||||||
}
|
}
|
||||||
visit_end_struct(v, errp);
|
|
||||||
|
|
||||||
visit_end_struct(v, errp);
|
visit_start_struct(v, NULL, NULL, "stats", 0, &err);
|
||||||
|
if (err) {
|
||||||
|
goto out_end;
|
||||||
|
}
|
||||||
|
for (i = 0; !err && i < VIRTIO_BALLOON_S_NR; i++) {
|
||||||
|
visit_type_int64(v, (int64_t *) &s->stats[i], balloon_stat_names[i],
|
||||||
|
&err);
|
||||||
|
}
|
||||||
|
error_propagate(errp, err);
|
||||||
|
err = NULL;
|
||||||
|
visit_end_struct(v, &err);
|
||||||
|
|
||||||
|
out_end:
|
||||||
|
error_propagate(errp, err);
|
||||||
|
err = NULL;
|
||||||
|
visit_end_struct(v, &err);
|
||||||
|
out:
|
||||||
|
error_propagate(errp, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void balloon_stats_get_poll_interval(Object *obj, struct Visitor *v,
|
static void balloon_stats_get_poll_interval(Object *obj, struct Visitor *v,
|
||||||
|
|||||||
@@ -42,13 +42,9 @@ struct Visitor
|
|||||||
Error **errp);
|
Error **errp);
|
||||||
|
|
||||||
/* May be NULL */
|
/* May be NULL */
|
||||||
void (*start_optional)(Visitor *v, bool *present, const char *name,
|
void (*optional)(Visitor *v, bool *present, const char *name,
|
||||||
Error **errp);
|
Error **errp);
|
||||||
void (*end_optional)(Visitor *v, Error **errp);
|
|
||||||
|
|
||||||
void (*start_handle)(Visitor *v, void **obj, const char *kind,
|
|
||||||
const char *name, Error **errp);
|
|
||||||
void (*end_handle)(Visitor *v, Error **errp);
|
|
||||||
void (*type_uint8)(Visitor *v, uint8_t *obj, const char *name, Error **errp);
|
void (*type_uint8)(Visitor *v, uint8_t *obj, const char *name, Error **errp);
|
||||||
void (*type_uint16)(Visitor *v, uint16_t *obj, const char *name, Error **errp);
|
void (*type_uint16)(Visitor *v, uint16_t *obj, const char *name, Error **errp);
|
||||||
void (*type_uint32)(Visitor *v, uint32_t *obj, const char *name, Error **errp);
|
void (*type_uint32)(Visitor *v, uint32_t *obj, const char *name, Error **errp);
|
||||||
|
|||||||
@@ -39,9 +39,8 @@ void visit_end_implicit_struct(Visitor *v, Error **errp);
|
|||||||
void visit_start_list(Visitor *v, const char *name, Error **errp);
|
void visit_start_list(Visitor *v, const char *name, Error **errp);
|
||||||
GenericList *visit_next_list(Visitor *v, GenericList **list, Error **errp);
|
GenericList *visit_next_list(Visitor *v, GenericList **list, Error **errp);
|
||||||
void visit_end_list(Visitor *v, Error **errp);
|
void visit_end_list(Visitor *v, Error **errp);
|
||||||
void visit_start_optional(Visitor *v, bool *present, const char *name,
|
void visit_optional(Visitor *v, bool *present, const char *name,
|
||||||
Error **errp);
|
Error **errp);
|
||||||
void visit_end_optional(Visitor *v, Error **errp);
|
|
||||||
void visit_get_next_type(Visitor *v, int *obj, const int *qtypes,
|
void visit_get_next_type(Visitor *v, int *obj, const int *qtypes,
|
||||||
const char *name, Error **errp);
|
const char *name, Error **errp);
|
||||||
void visit_type_enum(Visitor *v, int *obj, const char *strings[],
|
void visit_type_enum(Visitor *v, int *obj, const char *strings[],
|
||||||
|
|||||||
153
monitor.c
153
monitor.c
@@ -4269,6 +4269,55 @@ static const char *next_arg_type(const char *typestr)
|
|||||||
return (p != NULL ? ++p : typestr);
|
return (p != NULL ? ++p : typestr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void add_completion_option(ReadLineState *rs, const char *str,
|
||||||
|
const char *option)
|
||||||
|
{
|
||||||
|
if (!str || !option) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!strncmp(option, str, strlen(str))) {
|
||||||
|
readline_add_completion(rs, option);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void chardev_add_completion(ReadLineState *rs, int nb_args, const char *str)
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
ChardevBackendInfoList *list, *start;
|
||||||
|
|
||||||
|
if (nb_args != 2) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
len = strlen(str);
|
||||||
|
readline_set_completion_index(rs, len);
|
||||||
|
|
||||||
|
start = list = qmp_query_chardev_backends(NULL);
|
||||||
|
while (list) {
|
||||||
|
const char *chr_name = list->value->name;
|
||||||
|
|
||||||
|
if (!strncmp(chr_name, str, len)) {
|
||||||
|
readline_add_completion(rs, chr_name);
|
||||||
|
}
|
||||||
|
list = list->next;
|
||||||
|
}
|
||||||
|
qapi_free_ChardevBackendInfoList(start);
|
||||||
|
}
|
||||||
|
|
||||||
|
void netdev_add_completion(ReadLineState *rs, int nb_args, const char *str)
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (nb_args != 2) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
len = strlen(str);
|
||||||
|
readline_set_completion_index(rs, len);
|
||||||
|
for (i = 0; NetClientOptionsKind_lookup[i]; i++) {
|
||||||
|
add_completion_option(rs, str, NetClientOptionsKind_lookup[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void device_add_completion(ReadLineState *rs, int nb_args, const char *str)
|
void device_add_completion(ReadLineState *rs, int nb_args, const char *str)
|
||||||
{
|
{
|
||||||
GSList *list, *elt;
|
GSList *list, *elt;
|
||||||
@@ -4339,6 +4388,29 @@ static void device_del_bus_completion(ReadLineState *rs, BusState *bus,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void chardev_remove_completion(ReadLineState *rs, int nb_args, const char *str)
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
ChardevInfoList *list, *start;
|
||||||
|
|
||||||
|
if (nb_args != 2) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
len = strlen(str);
|
||||||
|
readline_set_completion_index(rs, len);
|
||||||
|
|
||||||
|
start = list = qmp_query_chardev(NULL);
|
||||||
|
while (list) {
|
||||||
|
ChardevInfo *chr = list->value;
|
||||||
|
|
||||||
|
if (!strncmp(chr->label, str, len)) {
|
||||||
|
readline_add_completion(rs, chr->label);
|
||||||
|
}
|
||||||
|
list = list->next;
|
||||||
|
}
|
||||||
|
qapi_free_ChardevInfoList(start);
|
||||||
|
}
|
||||||
|
|
||||||
void device_del_completion(ReadLineState *rs, int nb_args, const char *str)
|
void device_del_completion(ReadLineState *rs, int nb_args, const char *str)
|
||||||
{
|
{
|
||||||
size_t len;
|
size_t len;
|
||||||
@@ -4376,6 +4448,77 @@ void object_del_completion(ReadLineState *rs, int nb_args, const char *str)
|
|||||||
qapi_free_ObjectPropertyInfoList(start);
|
qapi_free_ObjectPropertyInfoList(start);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sendkey_completion(ReadLineState *rs, int nb_args, const char *str)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char *sep;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if (nb_args != 2) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sep = strrchr(str, '-');
|
||||||
|
if (sep) {
|
||||||
|
str = sep + 1;
|
||||||
|
}
|
||||||
|
len = strlen(str);
|
||||||
|
readline_set_completion_index(rs, len);
|
||||||
|
for (i = 0; i < Q_KEY_CODE_MAX; i++) {
|
||||||
|
if (!strncmp(str, QKeyCode_lookup[i], len)) {
|
||||||
|
readline_add_completion(rs, QKeyCode_lookup[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_link_completion(ReadLineState *rs, int nb_args, const char *str)
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
len = strlen(str);
|
||||||
|
readline_set_completion_index(rs, len);
|
||||||
|
if (nb_args == 2) {
|
||||||
|
NetClientState *ncs[255];
|
||||||
|
int count, i;
|
||||||
|
count = qemu_find_net_clients_except(NULL, ncs,
|
||||||
|
NET_CLIENT_OPTIONS_KIND_NONE, 255);
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
const char *name = ncs[i]->name;
|
||||||
|
if (!strncmp(str, name, len)) {
|
||||||
|
readline_add_completion(rs, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (nb_args == 3) {
|
||||||
|
add_completion_option(rs, str, "on");
|
||||||
|
add_completion_option(rs, str, "off");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void netdev_del_completion(ReadLineState *rs, int nb_args, const char *str)
|
||||||
|
{
|
||||||
|
int len, count, i;
|
||||||
|
NetClientState *ncs[255];
|
||||||
|
|
||||||
|
if (nb_args != 2) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = strlen(str);
|
||||||
|
readline_set_completion_index(rs, len);
|
||||||
|
count = qemu_find_net_clients_except(NULL, ncs, NET_CLIENT_OPTIONS_KIND_NIC,
|
||||||
|
255);
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
QemuOpts *opts;
|
||||||
|
const char *name = ncs[i]->name;
|
||||||
|
if (strncmp(str, name, len)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
opts = qemu_opts_find(qemu_find_opts_err("netdev", NULL), name);
|
||||||
|
if (opts) {
|
||||||
|
readline_add_completion(rs, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void monitor_find_completion_by_table(Monitor *mon,
|
static void monitor_find_completion_by_table(Monitor *mon,
|
||||||
const mon_cmd_t *cmd_table,
|
const mon_cmd_t *cmd_table,
|
||||||
char **args,
|
char **args,
|
||||||
@@ -4444,15 +4587,7 @@ static void monitor_find_completion_by_table(Monitor *mon,
|
|||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
case 'S':
|
case 'S':
|
||||||
if (!strcmp(cmd->name, "sendkey")) {
|
if (!strcmp(cmd->name, "help|?")) {
|
||||||
char *sep = strrchr(str, '-');
|
|
||||||
if (sep)
|
|
||||||
str = sep + 1;
|
|
||||||
readline_set_completion_index(mon->rs, strlen(str));
|
|
||||||
for (i = 0; i < Q_KEY_CODE_MAX; i++) {
|
|
||||||
cmd_completion(mon, str, QKeyCode_lookup[i]);
|
|
||||||
}
|
|
||||||
} else if (!strcmp(cmd->name, "help|?")) {
|
|
||||||
monitor_find_completion_by_table(mon, cmd_table,
|
monitor_find_completion_by_table(mon, cmd_table,
|
||||||
&args[1], nb_args - 1);
|
&args[1], nb_args - 1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -633,7 +633,7 @@ int qemu_find_net_clients_except(const char *id, NetClientState **ncs,
|
|||||||
if (nc->info->type == type) {
|
if (nc->info->type == type) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!strcmp(nc->name, id)) {
|
if (!id || !strcmp(nc->name, id)) {
|
||||||
if (ret < max) {
|
if (ret < max) {
|
||||||
ncs[ret] = nc;
|
ncs[ret] = nc;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -484,8 +484,7 @@ opts_type_size(Visitor *v, uint64_t *obj, const char *name, Error **errp)
|
|||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
opts_start_optional(Visitor *v, bool *present, const char *name,
|
opts_optional(Visitor *v, bool *present, const char *name, Error **errp)
|
||||||
Error **errp)
|
|
||||||
{
|
{
|
||||||
OptsVisitor *ov = DO_UPCAST(OptsVisitor, visitor, v);
|
OptsVisitor *ov = DO_UPCAST(OptsVisitor, visitor, v);
|
||||||
|
|
||||||
@@ -528,7 +527,7 @@ opts_visitor_new(const QemuOpts *opts)
|
|||||||
/* type_number() is not filled in, but this is not the first visitor to
|
/* type_number() is not filled in, but this is not the first visitor to
|
||||||
* skip some mandatory methods... */
|
* skip some mandatory methods... */
|
||||||
|
|
||||||
ov->visitor.start_optional = &opts_start_optional;
|
ov->visitor.optional = &opts_optional;
|
||||||
|
|
||||||
ov->opts_root = opts;
|
ov->opts_root = opts;
|
||||||
|
|
||||||
|
|||||||
@@ -17,46 +17,27 @@
|
|||||||
#include "qapi/visitor.h"
|
#include "qapi/visitor.h"
|
||||||
#include "qapi/visitor-impl.h"
|
#include "qapi/visitor-impl.h"
|
||||||
|
|
||||||
void visit_start_handle(Visitor *v, void **obj, const char *kind,
|
|
||||||
const char *name, Error **errp)
|
|
||||||
{
|
|
||||||
if (!error_is_set(errp) && v->start_handle) {
|
|
||||||
v->start_handle(v, obj, kind, name, errp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void visit_end_handle(Visitor *v, Error **errp)
|
|
||||||
{
|
|
||||||
if (!error_is_set(errp) && v->end_handle) {
|
|
||||||
v->end_handle(v, errp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void visit_start_struct(Visitor *v, void **obj, const char *kind,
|
void visit_start_struct(Visitor *v, void **obj, const char *kind,
|
||||||
const char *name, size_t size, Error **errp)
|
const char *name, size_t size, Error **errp)
|
||||||
{
|
{
|
||||||
if (!error_is_set(errp)) {
|
|
||||||
v->start_struct(v, obj, kind, name, size, errp);
|
v->start_struct(v, obj, kind, name, size, errp);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void visit_end_struct(Visitor *v, Error **errp)
|
void visit_end_struct(Visitor *v, Error **errp)
|
||||||
{
|
{
|
||||||
assert(!error_is_set(errp));
|
|
||||||
v->end_struct(v, errp);
|
v->end_struct(v, errp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void visit_start_implicit_struct(Visitor *v, void **obj, size_t size,
|
void visit_start_implicit_struct(Visitor *v, void **obj, size_t size,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
if (!error_is_set(errp) && v->start_implicit_struct) {
|
if (v->start_implicit_struct) {
|
||||||
v->start_implicit_struct(v, obj, size, errp);
|
v->start_implicit_struct(v, obj, size, errp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void visit_end_implicit_struct(Visitor *v, Error **errp)
|
void visit_end_implicit_struct(Visitor *v, Error **errp)
|
||||||
{
|
{
|
||||||
assert(!error_is_set(errp));
|
|
||||||
if (v->end_implicit_struct) {
|
if (v->end_implicit_struct) {
|
||||||
v->end_implicit_struct(v, errp);
|
v->end_implicit_struct(v, errp);
|
||||||
}
|
}
|
||||||
@@ -64,45 +45,31 @@ void visit_end_implicit_struct(Visitor *v, Error **errp)
|
|||||||
|
|
||||||
void visit_start_list(Visitor *v, const char *name, Error **errp)
|
void visit_start_list(Visitor *v, const char *name, Error **errp)
|
||||||
{
|
{
|
||||||
if (!error_is_set(errp)) {
|
|
||||||
v->start_list(v, name, errp);
|
v->start_list(v, name, errp);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GenericList *visit_next_list(Visitor *v, GenericList **list, Error **errp)
|
GenericList *visit_next_list(Visitor *v, GenericList **list, Error **errp)
|
||||||
{
|
{
|
||||||
if (!error_is_set(errp)) {
|
|
||||||
return v->next_list(v, list, errp);
|
return v->next_list(v, list, errp);
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void visit_end_list(Visitor *v, Error **errp)
|
void visit_end_list(Visitor *v, Error **errp)
|
||||||
{
|
{
|
||||||
assert(!error_is_set(errp));
|
|
||||||
v->end_list(v, errp);
|
v->end_list(v, errp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void visit_start_optional(Visitor *v, bool *present, const char *name,
|
void visit_optional(Visitor *v, bool *present, const char *name,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
if (!error_is_set(errp) && v->start_optional) {
|
if (v->optional) {
|
||||||
v->start_optional(v, present, name, errp);
|
v->optional(v, present, name, errp);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void visit_end_optional(Visitor *v, Error **errp)
|
|
||||||
{
|
|
||||||
if (!error_is_set(errp) && v->end_optional) {
|
|
||||||
v->end_optional(v, errp);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void visit_get_next_type(Visitor *v, int *obj, const int *qtypes,
|
void visit_get_next_type(Visitor *v, int *obj, const int *qtypes,
|
||||||
const char *name, Error **errp)
|
const char *name, Error **errp)
|
||||||
{
|
{
|
||||||
if (!error_is_set(errp) && v->get_next_type) {
|
if (v->get_next_type) {
|
||||||
v->get_next_type(v, obj, qtypes, name, errp);
|
v->get_next_type(v, obj, qtypes, name, errp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -110,22 +77,18 @@ void visit_get_next_type(Visitor *v, int *obj, const int *qtypes,
|
|||||||
void visit_type_enum(Visitor *v, int *obj, const char *strings[],
|
void visit_type_enum(Visitor *v, int *obj, const char *strings[],
|
||||||
const char *kind, const char *name, Error **errp)
|
const char *kind, const char *name, Error **errp)
|
||||||
{
|
{
|
||||||
if (!error_is_set(errp)) {
|
|
||||||
v->type_enum(v, obj, strings, kind, name, errp);
|
v->type_enum(v, obj, strings, kind, name, errp);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void visit_type_int(Visitor *v, int64_t *obj, const char *name, Error **errp)
|
void visit_type_int(Visitor *v, int64_t *obj, const char *name, Error **errp)
|
||||||
{
|
{
|
||||||
if (!error_is_set(errp)) {
|
|
||||||
v->type_int(v, obj, name, errp);
|
v->type_int(v, obj, name, errp);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void visit_type_uint8(Visitor *v, uint8_t *obj, const char *name, Error **errp)
|
void visit_type_uint8(Visitor *v, uint8_t *obj, const char *name, Error **errp)
|
||||||
{
|
{
|
||||||
int64_t value;
|
int64_t value;
|
||||||
if (!error_is_set(errp)) {
|
|
||||||
if (v->type_uint8) {
|
if (v->type_uint8) {
|
||||||
v->type_uint8(v, obj, name, errp);
|
v->type_uint8(v, obj, name, errp);
|
||||||
} else {
|
} else {
|
||||||
@@ -138,13 +101,12 @@ void visit_type_uint8(Visitor *v, uint8_t *obj, const char *name, Error **errp)
|
|||||||
}
|
}
|
||||||
*obj = value;
|
*obj = value;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void visit_type_uint16(Visitor *v, uint16_t *obj, const char *name, Error **errp)
|
void visit_type_uint16(Visitor *v, uint16_t *obj, const char *name, Error **errp)
|
||||||
{
|
{
|
||||||
int64_t value;
|
int64_t value;
|
||||||
if (!error_is_set(errp)) {
|
|
||||||
if (v->type_uint16) {
|
if (v->type_uint16) {
|
||||||
v->type_uint16(v, obj, name, errp);
|
v->type_uint16(v, obj, name, errp);
|
||||||
} else {
|
} else {
|
||||||
@@ -157,13 +119,12 @@ void visit_type_uint16(Visitor *v, uint16_t *obj, const char *name, Error **errp
|
|||||||
}
|
}
|
||||||
*obj = value;
|
*obj = value;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void visit_type_uint32(Visitor *v, uint32_t *obj, const char *name, Error **errp)
|
void visit_type_uint32(Visitor *v, uint32_t *obj, const char *name, Error **errp)
|
||||||
{
|
{
|
||||||
int64_t value;
|
int64_t value;
|
||||||
if (!error_is_set(errp)) {
|
|
||||||
if (v->type_uint32) {
|
if (v->type_uint32) {
|
||||||
v->type_uint32(v, obj, name, errp);
|
v->type_uint32(v, obj, name, errp);
|
||||||
} else {
|
} else {
|
||||||
@@ -176,13 +137,12 @@ void visit_type_uint32(Visitor *v, uint32_t *obj, const char *name, Error **errp
|
|||||||
}
|
}
|
||||||
*obj = value;
|
*obj = value;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void visit_type_uint64(Visitor *v, uint64_t *obj, const char *name, Error **errp)
|
void visit_type_uint64(Visitor *v, uint64_t *obj, const char *name, Error **errp)
|
||||||
{
|
{
|
||||||
int64_t value;
|
int64_t value;
|
||||||
if (!error_is_set(errp)) {
|
|
||||||
if (v->type_uint64) {
|
if (v->type_uint64) {
|
||||||
v->type_uint64(v, obj, name, errp);
|
v->type_uint64(v, obj, name, errp);
|
||||||
} else {
|
} else {
|
||||||
@@ -190,13 +150,12 @@ void visit_type_uint64(Visitor *v, uint64_t *obj, const char *name, Error **errp
|
|||||||
v->type_int(v, &value, name, errp);
|
v->type_int(v, &value, name, errp);
|
||||||
*obj = value;
|
*obj = value;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void visit_type_int8(Visitor *v, int8_t *obj, const char *name, Error **errp)
|
void visit_type_int8(Visitor *v, int8_t *obj, const char *name, Error **errp)
|
||||||
{
|
{
|
||||||
int64_t value;
|
int64_t value;
|
||||||
if (!error_is_set(errp)) {
|
|
||||||
if (v->type_int8) {
|
if (v->type_int8) {
|
||||||
v->type_int8(v, obj, name, errp);
|
v->type_int8(v, obj, name, errp);
|
||||||
} else {
|
} else {
|
||||||
@@ -209,13 +168,12 @@ void visit_type_int8(Visitor *v, int8_t *obj, const char *name, Error **errp)
|
|||||||
}
|
}
|
||||||
*obj = value;
|
*obj = value;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void visit_type_int16(Visitor *v, int16_t *obj, const char *name, Error **errp)
|
void visit_type_int16(Visitor *v, int16_t *obj, const char *name, Error **errp)
|
||||||
{
|
{
|
||||||
int64_t value;
|
int64_t value;
|
||||||
if (!error_is_set(errp)) {
|
|
||||||
if (v->type_int16) {
|
if (v->type_int16) {
|
||||||
v->type_int16(v, obj, name, errp);
|
v->type_int16(v, obj, name, errp);
|
||||||
} else {
|
} else {
|
||||||
@@ -228,13 +186,12 @@ void visit_type_int16(Visitor *v, int16_t *obj, const char *name, Error **errp)
|
|||||||
}
|
}
|
||||||
*obj = value;
|
*obj = value;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void visit_type_int32(Visitor *v, int32_t *obj, const char *name, Error **errp)
|
void visit_type_int32(Visitor *v, int32_t *obj, const char *name, Error **errp)
|
||||||
{
|
{
|
||||||
int64_t value;
|
int64_t value;
|
||||||
if (!error_is_set(errp)) {
|
|
||||||
if (v->type_int32) {
|
if (v->type_int32) {
|
||||||
v->type_int32(v, obj, name, errp);
|
v->type_int32(v, obj, name, errp);
|
||||||
} else {
|
} else {
|
||||||
@@ -247,24 +204,21 @@ void visit_type_int32(Visitor *v, int32_t *obj, const char *name, Error **errp)
|
|||||||
}
|
}
|
||||||
*obj = value;
|
*obj = value;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void visit_type_int64(Visitor *v, int64_t *obj, const char *name, Error **errp)
|
void visit_type_int64(Visitor *v, int64_t *obj, const char *name, Error **errp)
|
||||||
{
|
{
|
||||||
if (!error_is_set(errp)) {
|
|
||||||
if (v->type_int64) {
|
if (v->type_int64) {
|
||||||
v->type_int64(v, obj, name, errp);
|
v->type_int64(v, obj, name, errp);
|
||||||
} else {
|
} else {
|
||||||
v->type_int(v, obj, name, errp);
|
v->type_int(v, obj, name, errp);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void visit_type_size(Visitor *v, uint64_t *obj, const char *name, Error **errp)
|
void visit_type_size(Visitor *v, uint64_t *obj, const char *name, Error **errp)
|
||||||
{
|
{
|
||||||
int64_t value;
|
int64_t value;
|
||||||
if (!error_is_set(errp)) {
|
|
||||||
if (v->type_size) {
|
if (v->type_size) {
|
||||||
v->type_size(v, obj, name, errp);
|
v->type_size(v, obj, name, errp);
|
||||||
} else if (v->type_uint64) {
|
} else if (v->type_uint64) {
|
||||||
@@ -274,28 +228,21 @@ void visit_type_size(Visitor *v, uint64_t *obj, const char *name, Error **errp)
|
|||||||
v->type_int(v, &value, name, errp);
|
v->type_int(v, &value, name, errp);
|
||||||
*obj = value;
|
*obj = value;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void visit_type_bool(Visitor *v, bool *obj, const char *name, Error **errp)
|
void visit_type_bool(Visitor *v, bool *obj, const char *name, Error **errp)
|
||||||
{
|
{
|
||||||
if (!error_is_set(errp)) {
|
|
||||||
v->type_bool(v, obj, name, errp);
|
v->type_bool(v, obj, name, errp);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void visit_type_str(Visitor *v, char **obj, const char *name, Error **errp)
|
void visit_type_str(Visitor *v, char **obj, const char *name, Error **errp)
|
||||||
{
|
{
|
||||||
if (!error_is_set(errp)) {
|
|
||||||
v->type_str(v, obj, name, errp);
|
v->type_str(v, obj, name, errp);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void visit_type_number(Visitor *v, double *obj, const char *name, Error **errp)
|
void visit_type_number(Visitor *v, double *obj, const char *name, Error **errp)
|
||||||
{
|
{
|
||||||
if (!error_is_set(errp)) {
|
|
||||||
v->type_number(v, obj, name, errp);
|
v->type_number(v, obj, name, errp);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void output_type_enum(Visitor *v, int *obj, const char *strings[],
|
void output_type_enum(Visitor *v, int *obj, const char *strings[],
|
||||||
@@ -321,13 +268,15 @@ void input_type_enum(Visitor *v, int *obj, const char *strings[],
|
|||||||
const char *kind, const char *name,
|
const char *kind, const char *name,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
|
Error *local_err = NULL;
|
||||||
int64_t value = 0;
|
int64_t value = 0;
|
||||||
char *enum_str;
|
char *enum_str;
|
||||||
|
|
||||||
assert(strings);
|
assert(strings);
|
||||||
|
|
||||||
visit_type_str(v, &enum_str, name, errp);
|
visit_type_str(v, &enum_str, name, &local_err);
|
||||||
if (error_is_set(errp)) {
|
if (local_err) {
|
||||||
|
error_propagate(errp, local_err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -286,8 +286,8 @@ static void qmp_input_type_number(Visitor *v, double *obj, const char *name,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void qmp_input_start_optional(Visitor *v, bool *present,
|
static void qmp_input_optional(Visitor *v, bool *present, const char *name,
|
||||||
const char *name, Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
QmpInputVisitor *qiv = to_qiv(v);
|
QmpInputVisitor *qiv = to_qiv(v);
|
||||||
QObject *qobj = qmp_input_get_object(qiv, name, true);
|
QObject *qobj = qmp_input_get_object(qiv, name, true);
|
||||||
@@ -329,7 +329,7 @@ QmpInputVisitor *qmp_input_visitor_new(QObject *obj)
|
|||||||
v->visitor.type_bool = qmp_input_type_bool;
|
v->visitor.type_bool = qmp_input_type_bool;
|
||||||
v->visitor.type_str = qmp_input_type_str;
|
v->visitor.type_str = qmp_input_type_str;
|
||||||
v->visitor.type_number = qmp_input_type_number;
|
v->visitor.type_number = qmp_input_type_number;
|
||||||
v->visitor.start_optional = qmp_input_start_optional;
|
v->visitor.optional = qmp_input_optional;
|
||||||
v->visitor.get_next_type = qmp_input_get_next_type;
|
v->visitor.get_next_type = qmp_input_get_next_type;
|
||||||
|
|
||||||
qmp_input_push(v, obj, NULL);
|
qmp_input_push(v, obj, NULL);
|
||||||
|
|||||||
@@ -120,8 +120,8 @@ static void parse_type_number(Visitor *v, double *obj, const char *name,
|
|||||||
*obj = val;
|
*obj = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void parse_start_optional(Visitor *v, bool *present,
|
static void parse_optional(Visitor *v, bool *present, const char *name,
|
||||||
const char *name, Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v);
|
StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v);
|
||||||
|
|
||||||
@@ -155,7 +155,7 @@ StringInputVisitor *string_input_visitor_new(const char *str)
|
|||||||
v->visitor.type_bool = parse_type_bool;
|
v->visitor.type_bool = parse_type_bool;
|
||||||
v->visitor.type_str = parse_type_str;
|
v->visitor.type_str = parse_type_str;
|
||||||
v->visitor.type_number = parse_type_number;
|
v->visitor.type_number = parse_type_number;
|
||||||
v->visitor.start_optional = parse_start_optional;
|
v->visitor.optional = parse_optional;
|
||||||
|
|
||||||
v->string = str;
|
v->string = str;
|
||||||
return v;
|
return v;
|
||||||
|
|||||||
@@ -2,16 +2,19 @@
|
|||||||
# QAPI command marshaller generator
|
# QAPI command marshaller generator
|
||||||
#
|
#
|
||||||
# Copyright IBM, Corp. 2011
|
# Copyright IBM, Corp. 2011
|
||||||
|
# Copyright (C) 2014 Red Hat, Inc.
|
||||||
#
|
#
|
||||||
# Authors:
|
# Authors:
|
||||||
# Anthony Liguori <aliguori@us.ibm.com>
|
# Anthony Liguori <aliguori@us.ibm.com>
|
||||||
# Michael Roth <mdroth@linux.vnet.ibm.com>
|
# Michael Roth <mdroth@linux.vnet.ibm.com>
|
||||||
|
# Markus Armbruster <armbru@redhat.com>
|
||||||
#
|
#
|
||||||
# This work is licensed under the terms of the GNU GPL, version 2.
|
# This work is licensed under the terms of the GNU GPL, version 2.
|
||||||
# See the COPYING file in the top-level directory.
|
# See the COPYING file in the top-level directory.
|
||||||
|
|
||||||
from ordereddict import OrderedDict
|
from ordereddict import OrderedDict
|
||||||
from qapi import *
|
from qapi import *
|
||||||
|
import re
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import getopt
|
import getopt
|
||||||
@@ -37,6 +40,15 @@ def generate_command_decl(name, args, ret_type):
|
|||||||
''',
|
''',
|
||||||
ret_type=c_type(ret_type), name=c_fun(name), args=arglist).strip()
|
ret_type=c_type(ret_type), name=c_fun(name), args=arglist).strip()
|
||||||
|
|
||||||
|
def gen_err_check(errvar):
|
||||||
|
if errvar:
|
||||||
|
return mcgen('''
|
||||||
|
if (local_err) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
''')
|
||||||
|
return ''
|
||||||
|
|
||||||
def gen_sync_call(name, args, ret_type, indent=0):
|
def gen_sync_call(name, args, ret_type, indent=0):
|
||||||
ret = ""
|
ret = ""
|
||||||
arglist=""
|
arglist=""
|
||||||
@@ -49,15 +61,14 @@ def gen_sync_call(name, args, ret_type, indent=0):
|
|||||||
arglist += "%s, " % (c_var(argname))
|
arglist += "%s, " % (c_var(argname))
|
||||||
push_indent(indent)
|
push_indent(indent)
|
||||||
ret = mcgen('''
|
ret = mcgen('''
|
||||||
%(retval)sqmp_%(name)s(%(args)serrp);
|
%(retval)sqmp_%(name)s(%(args)s&local_err);
|
||||||
|
|
||||||
''',
|
''',
|
||||||
name=c_fun(name), args=arglist, retval=retval).rstrip()
|
name=c_fun(name), args=arglist, retval=retval).rstrip()
|
||||||
if ret_type:
|
if ret_type:
|
||||||
|
ret += "\n" + gen_err_check('local_err')
|
||||||
ret += "\n" + mcgen(''''
|
ret += "\n" + mcgen(''''
|
||||||
if (!error_is_set(errp)) {
|
%(marshal_output_call)s
|
||||||
%(marshal_output_call)s
|
|
||||||
}
|
|
||||||
''',
|
''',
|
||||||
marshal_output_call=gen_marshal_output_call(name, ret_type)).rstrip()
|
marshal_output_call=gen_marshal_output_call(name, ret_type)).rstrip()
|
||||||
pop_indent(indent)
|
pop_indent(indent)
|
||||||
@@ -67,18 +78,19 @@ if (!error_is_set(errp)) {
|
|||||||
def gen_marshal_output_call(name, ret_type):
|
def gen_marshal_output_call(name, ret_type):
|
||||||
if not ret_type:
|
if not ret_type:
|
||||||
return ""
|
return ""
|
||||||
return "qmp_marshal_output_%s(retval, ret, errp);" % c_fun(name)
|
return "qmp_marshal_output_%s(retval, ret, &local_err);" % c_fun(name)
|
||||||
|
|
||||||
def gen_visitor_input_containers_decl(args):
|
def gen_visitor_input_containers_decl(args, obj):
|
||||||
ret = ""
|
ret = ""
|
||||||
|
|
||||||
push_indent()
|
push_indent()
|
||||||
if len(args) > 0:
|
if len(args) > 0:
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
QmpInputVisitor *mi;
|
QmpInputVisitor *mi = qmp_input_visitor_new_strict(%(obj)s);
|
||||||
QapiDeallocVisitor *md;
|
QapiDeallocVisitor *md;
|
||||||
Visitor *v;
|
Visitor *v;
|
||||||
''')
|
''',
|
||||||
|
obj=obj)
|
||||||
pop_indent()
|
pop_indent()
|
||||||
|
|
||||||
return ret.rstrip()
|
return ret.rstrip()
|
||||||
@@ -106,9 +118,10 @@ bool has_%(argname)s = false;
|
|||||||
pop_indent()
|
pop_indent()
|
||||||
return ret.rstrip()
|
return ret.rstrip()
|
||||||
|
|
||||||
def gen_visitor_input_block(args, obj, dealloc=False):
|
def gen_visitor_input_block(args, dealloc=False):
|
||||||
ret = ""
|
ret = ""
|
||||||
errparg = 'errp'
|
errparg = '&local_err'
|
||||||
|
errarg = 'local_err'
|
||||||
|
|
||||||
if len(args) == 0:
|
if len(args) == 0:
|
||||||
return ret
|
return ret
|
||||||
@@ -117,44 +130,44 @@ def gen_visitor_input_block(args, obj, dealloc=False):
|
|||||||
|
|
||||||
if dealloc:
|
if dealloc:
|
||||||
errparg = 'NULL'
|
errparg = 'NULL'
|
||||||
|
errarg = None;
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
|
qmp_input_visitor_cleanup(mi);
|
||||||
md = qapi_dealloc_visitor_new();
|
md = qapi_dealloc_visitor_new();
|
||||||
v = qapi_dealloc_get_visitor(md);
|
v = qapi_dealloc_get_visitor(md);
|
||||||
''')
|
''')
|
||||||
else:
|
else:
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
mi = qmp_input_visitor_new_strict(%(obj)s);
|
|
||||||
v = qmp_input_get_visitor(mi);
|
v = qmp_input_get_visitor(mi);
|
||||||
''',
|
''')
|
||||||
obj=obj)
|
|
||||||
|
|
||||||
for argname, argtype, optional, structured in parse_args(args):
|
for argname, argtype, optional, structured in parse_args(args):
|
||||||
if optional:
|
if optional:
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
visit_start_optional(v, &has_%(c_name)s, "%(name)s", %(errp)s);
|
visit_optional(v, &has_%(c_name)s, "%(name)s", %(errp)s);
|
||||||
if (has_%(c_name)s) {
|
|
||||||
''',
|
''',
|
||||||
c_name=c_var(argname), name=argname, errp=errparg)
|
c_name=c_var(argname), name=argname, errp=errparg)
|
||||||
|
ret += gen_err_check(errarg)
|
||||||
|
ret += mcgen('''
|
||||||
|
if (has_%(c_name)s) {
|
||||||
|
''',
|
||||||
|
c_name=c_var(argname))
|
||||||
push_indent()
|
push_indent()
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
%(visitor)s(v, &%(c_name)s, "%(name)s", %(errp)s);
|
%(visitor)s(v, &%(c_name)s, "%(name)s", %(errp)s);
|
||||||
''',
|
''',
|
||||||
c_name=c_var(argname), name=argname, argtype=argtype,
|
c_name=c_var(argname), name=argname, argtype=argtype,
|
||||||
visitor=type_visitor(argtype), errp=errparg)
|
visitor=type_visitor(argtype), errp=errparg)
|
||||||
|
ret += gen_err_check(errarg)
|
||||||
if optional:
|
if optional:
|
||||||
pop_indent()
|
pop_indent()
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
}
|
}
|
||||||
visit_end_optional(v, %(errp)s);
|
''')
|
||||||
''', errp=errparg)
|
|
||||||
|
|
||||||
if dealloc:
|
if dealloc:
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
qapi_dealloc_visitor_cleanup(md);
|
qapi_dealloc_visitor_cleanup(md);
|
||||||
''')
|
|
||||||
else:
|
|
||||||
ret += mcgen('''
|
|
||||||
qmp_input_visitor_cleanup(mi);
|
|
||||||
''')
|
''')
|
||||||
pop_indent()
|
pop_indent()
|
||||||
return ret.rstrip()
|
return ret.rstrip()
|
||||||
@@ -166,16 +179,22 @@ def gen_marshal_output(name, args, ret_type, middle_mode):
|
|||||||
ret = mcgen('''
|
ret = mcgen('''
|
||||||
static void qmp_marshal_output_%(c_name)s(%(c_ret_type)s ret_in, QObject **ret_out, Error **errp)
|
static void qmp_marshal_output_%(c_name)s(%(c_ret_type)s ret_in, QObject **ret_out, Error **errp)
|
||||||
{
|
{
|
||||||
QapiDeallocVisitor *md = qapi_dealloc_visitor_new();
|
Error *local_err = NULL;
|
||||||
QmpOutputVisitor *mo = qmp_output_visitor_new();
|
QmpOutputVisitor *mo = qmp_output_visitor_new();
|
||||||
|
QapiDeallocVisitor *md;
|
||||||
Visitor *v;
|
Visitor *v;
|
||||||
|
|
||||||
v = qmp_output_get_visitor(mo);
|
v = qmp_output_get_visitor(mo);
|
||||||
%(visitor)s(v, &ret_in, "unused", errp);
|
%(visitor)s(v, &ret_in, "unused", &local_err);
|
||||||
if (!error_is_set(errp)) {
|
if (local_err) {
|
||||||
*ret_out = qmp_output_get_qobject(mo);
|
goto out;
|
||||||
}
|
}
|
||||||
|
*ret_out = qmp_output_get_qobject(mo);
|
||||||
|
|
||||||
|
out:
|
||||||
|
error_propagate(errp, local_err);
|
||||||
qmp_output_visitor_cleanup(mo);
|
qmp_output_visitor_cleanup(mo);
|
||||||
|
md = qapi_dealloc_visitor_new();
|
||||||
v = qapi_dealloc_get_visitor(md);
|
v = qapi_dealloc_get_visitor(md);
|
||||||
%(visitor)s(v, &ret_in, "unused", NULL);
|
%(visitor)s(v, &ret_in, "unused", NULL);
|
||||||
qapi_dealloc_visitor_cleanup(md);
|
qapi_dealloc_visitor_cleanup(md);
|
||||||
@@ -200,13 +219,12 @@ def gen_marshal_input(name, args, ret_type, middle_mode):
|
|||||||
ret = mcgen('''
|
ret = mcgen('''
|
||||||
%(header)s
|
%(header)s
|
||||||
{
|
{
|
||||||
|
Error *local_err = NULL;
|
||||||
''',
|
''',
|
||||||
header=hdr)
|
header=hdr)
|
||||||
|
|
||||||
if middle_mode:
|
if middle_mode:
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
Error *local_err = NULL;
|
|
||||||
Error **errp = &local_err;
|
|
||||||
QDict *args = (QDict *)qdict;
|
QDict *args = (QDict *)qdict;
|
||||||
''')
|
''')
|
||||||
|
|
||||||
@@ -228,29 +246,32 @@ def gen_marshal_input(name, args, ret_type, middle_mode):
|
|||||||
%(visitor_input_block)s
|
%(visitor_input_block)s
|
||||||
|
|
||||||
''',
|
''',
|
||||||
visitor_input_containers_decl=gen_visitor_input_containers_decl(args),
|
visitor_input_containers_decl=gen_visitor_input_containers_decl(args, "QOBJECT(args)"),
|
||||||
visitor_input_vars_decl=gen_visitor_input_vars_decl(args),
|
visitor_input_vars_decl=gen_visitor_input_vars_decl(args),
|
||||||
visitor_input_block=gen_visitor_input_block(args, "QOBJECT(args)"))
|
visitor_input_block=gen_visitor_input_block(args))
|
||||||
else:
|
else:
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
|
|
||||||
(void)args;
|
(void)args;
|
||||||
''')
|
''')
|
||||||
|
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
if (error_is_set(errp)) {
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
%(sync_call)s
|
%(sync_call)s
|
||||||
''',
|
''',
|
||||||
sync_call=gen_sync_call(name, args, ret_type, indent=4))
|
sync_call=gen_sync_call(name, args, ret_type, indent=4))
|
||||||
|
if re.search('^ *goto out\\;', ret, re.MULTILINE):
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
''')
|
||||||
|
if not middle_mode:
|
||||||
|
ret += mcgen('''
|
||||||
|
error_propagate(errp, local_err);
|
||||||
''')
|
''')
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
%(visitor_input_block_cleanup)s
|
%(visitor_input_block_cleanup)s
|
||||||
''',
|
''',
|
||||||
visitor_input_block_cleanup=gen_visitor_input_block(args, None,
|
visitor_input_block_cleanup=gen_visitor_input_block(args,
|
||||||
dealloc=True))
|
dealloc=True))
|
||||||
|
|
||||||
if middle_mode:
|
if middle_mode:
|
||||||
|
|||||||
@@ -2,21 +2,47 @@
|
|||||||
# QAPI visitor generator
|
# QAPI visitor generator
|
||||||
#
|
#
|
||||||
# Copyright IBM, Corp. 2011
|
# Copyright IBM, Corp. 2011
|
||||||
|
# Copyright (C) 2014 Red Hat, Inc.
|
||||||
#
|
#
|
||||||
# Authors:
|
# Authors:
|
||||||
# Anthony Liguori <aliguori@us.ibm.com>
|
# Anthony Liguori <aliguori@us.ibm.com>
|
||||||
# Michael Roth <mdroth@linux.vnet.ibm.com>
|
# Michael Roth <mdroth@linux.vnet.ibm.com>
|
||||||
|
# Markus Armbruster <armbru@redhat.com>
|
||||||
#
|
#
|
||||||
# This work is licensed under the terms of the GNU GPL, version 2.
|
# This work is licensed under the terms of the GNU GPL, version 2.
|
||||||
# See the COPYING file in the top-level directory.
|
# See the COPYING file in the top-level directory.
|
||||||
|
|
||||||
from ordereddict import OrderedDict
|
from ordereddict import OrderedDict
|
||||||
from qapi import *
|
from qapi import *
|
||||||
|
import re
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import getopt
|
import getopt
|
||||||
import errno
|
import errno
|
||||||
|
|
||||||
|
implicit_structs = []
|
||||||
|
|
||||||
|
def generate_visit_implicit_struct(type):
|
||||||
|
global implicit_structs
|
||||||
|
if type in implicit_structs:
|
||||||
|
return ''
|
||||||
|
implicit_structs.append(type)
|
||||||
|
return mcgen('''
|
||||||
|
|
||||||
|
static void visit_type_implicit_%(c_type)s(Visitor *m, %(c_type)s **obj, Error **errp)
|
||||||
|
{
|
||||||
|
Error *err = NULL;
|
||||||
|
|
||||||
|
visit_start_implicit_struct(m, (void **)obj, sizeof(%(c_type)s), &err);
|
||||||
|
if (!err) {
|
||||||
|
visit_type_%(c_type)s_fields(m, obj, errp);
|
||||||
|
visit_end_implicit_struct(m, &err);
|
||||||
|
}
|
||||||
|
error_propagate(errp, err);
|
||||||
|
}
|
||||||
|
''',
|
||||||
|
c_type=type_name(type))
|
||||||
|
|
||||||
def generate_visit_struct_fields(name, field_prefix, fn_prefix, members, base = None):
|
def generate_visit_struct_fields(name, field_prefix, fn_prefix, members, base = None):
|
||||||
substructs = []
|
substructs = []
|
||||||
ret = ''
|
ret = ''
|
||||||
@@ -35,6 +61,19 @@ def generate_visit_struct_fields(name, field_prefix, fn_prefix, members, base =
|
|||||||
nested_field_prefix = "%s%s." % (field_prefix, argname)
|
nested_field_prefix = "%s%s." % (field_prefix, argname)
|
||||||
ret += generate_visit_struct_fields(name, nested_field_prefix,
|
ret += generate_visit_struct_fields(name, nested_field_prefix,
|
||||||
nested_fn_prefix, argentry)
|
nested_fn_prefix, argentry)
|
||||||
|
ret += mcgen('''
|
||||||
|
|
||||||
|
static void visit_type_%(full_name)s_field_%(c_name)s(Visitor *m, %(name)s **obj, Error **errp)
|
||||||
|
{
|
||||||
|
''',
|
||||||
|
name=name, full_name=full_name, c_name=c_var(argname))
|
||||||
|
ret += generate_visit_struct_body(full_name, argname, argentry)
|
||||||
|
ret += mcgen('''
|
||||||
|
}
|
||||||
|
''')
|
||||||
|
|
||||||
|
if base:
|
||||||
|
ret += generate_visit_implicit_struct(base)
|
||||||
|
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
|
|
||||||
@@ -47,12 +86,9 @@ static void visit_type_%(full_name)s_fields(Visitor *m, %(name)s ** obj, Error *
|
|||||||
|
|
||||||
if base:
|
if base:
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
visit_start_implicit_struct(m, (void**) &(*obj)->%(c_name)s, sizeof(%(type)s), &err);
|
visit_type_implicit_%(type)s(m, &(*obj)->%(c_prefix)s%(c_name)s, &err);
|
||||||
if (!err) {
|
if (err) {
|
||||||
visit_type_%(type)s_fields(m, &(*obj)->%(c_prefix)s%(c_name)s, &err);
|
goto out;
|
||||||
error_propagate(errp, err);
|
|
||||||
err = NULL;
|
|
||||||
visit_end_implicit_struct(m, &err);
|
|
||||||
}
|
}
|
||||||
''',
|
''',
|
||||||
c_prefix=c_var(field_prefix),
|
c_prefix=c_var(field_prefix),
|
||||||
@@ -61,15 +97,18 @@ if (!err) {
|
|||||||
for argname, argentry, optional, structured in parse_args(members):
|
for argname, argentry, optional, structured in parse_args(members):
|
||||||
if optional:
|
if optional:
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
visit_start_optional(m, &(*obj)->%(c_prefix)shas_%(c_name)s, "%(name)s", &err);
|
visit_optional(m, &(*obj)->%(c_prefix)shas_%(c_name)s, "%(name)s", &err);
|
||||||
if ((*obj)->%(prefix)shas_%(c_name)s) {
|
if (!err && (*obj)->%(prefix)shas_%(c_name)s) {
|
||||||
''',
|
''',
|
||||||
c_prefix=c_var(field_prefix), prefix=field_prefix,
|
c_prefix=c_var(field_prefix), prefix=field_prefix,
|
||||||
c_name=c_var(argname), name=argname)
|
c_name=c_var(argname), name=argname)
|
||||||
push_indent()
|
push_indent()
|
||||||
|
|
||||||
if structured:
|
if structured:
|
||||||
ret += generate_visit_struct_body(full_name, argname, argentry)
|
ret += mcgen('''
|
||||||
|
visit_type_%(full_name)s_field_%(c_name)s(m, obj, &err);
|
||||||
|
''',
|
||||||
|
full_name=full_name, c_name=c_var(argname))
|
||||||
else:
|
else:
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
visit_type_%(type)s(m, &(*obj)->%(c_prefix)s%(c_name)s, "%(name)s", &err);
|
visit_type_%(type)s(m, &(*obj)->%(c_prefix)s%(c_name)s, "%(name)s", &err);
|
||||||
@@ -82,12 +121,20 @@ visit_type_%(type)s(m, &(*obj)->%(c_prefix)s%(c_name)s, "%(name)s", &err);
|
|||||||
pop_indent()
|
pop_indent()
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
}
|
}
|
||||||
visit_end_optional(m, &err);
|
''')
|
||||||
|
ret += mcgen('''
|
||||||
|
if (err) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
''')
|
''')
|
||||||
|
|
||||||
pop_indent()
|
pop_indent()
|
||||||
|
if re.search('^ *goto out\\;', ret, re.MULTILINE):
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
|
|
||||||
|
out:
|
||||||
|
''')
|
||||||
|
ret += mcgen('''
|
||||||
error_propagate(errp, err);
|
error_propagate(errp, err);
|
||||||
}
|
}
|
||||||
''')
|
''')
|
||||||
@@ -96,9 +143,9 @@ visit_end_optional(m, &err);
|
|||||||
|
|
||||||
def generate_visit_struct_body(field_prefix, name, members):
|
def generate_visit_struct_body(field_prefix, name, members):
|
||||||
ret = mcgen('''
|
ret = mcgen('''
|
||||||
if (!error_is_set(errp)) {
|
Error *err = NULL;
|
||||||
|
|
||||||
''')
|
''')
|
||||||
push_indent()
|
|
||||||
|
|
||||||
if not field_prefix:
|
if not field_prefix:
|
||||||
full_name = name
|
full_name = name
|
||||||
@@ -107,36 +154,26 @@ if (!error_is_set(errp)) {
|
|||||||
|
|
||||||
if len(field_prefix):
|
if len(field_prefix):
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
Error **errp = &err; /* from outer scope */
|
visit_start_struct(m, NULL, "", "%(name)s", 0, &err);
|
||||||
Error *err = NULL;
|
|
||||||
visit_start_struct(m, NULL, "", "%(name)s", 0, &err);
|
|
||||||
''',
|
''',
|
||||||
name=name)
|
name=name)
|
||||||
else:
|
else:
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
Error *err = NULL;
|
visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(name)s), &err);
|
||||||
visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(name)s), &err);
|
|
||||||
''',
|
''',
|
||||||
name=name)
|
name=name)
|
||||||
|
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
if (!err) {
|
if (!err) {
|
||||||
if (*obj) {
|
if (*obj) {
|
||||||
visit_type_%(name)s_fields(m, obj, &err);
|
visit_type_%(name)s_fields(m, obj, errp);
|
||||||
error_propagate(errp, err);
|
|
||||||
err = NULL;
|
|
||||||
}
|
}
|
||||||
''',
|
|
||||||
name=full_name)
|
|
||||||
|
|
||||||
pop_indent()
|
|
||||||
ret += mcgen('''
|
|
||||||
/* Always call end_struct if start_struct succeeded. */
|
|
||||||
visit_end_struct(m, &err);
|
visit_end_struct(m, &err);
|
||||||
}
|
}
|
||||||
error_propagate(errp, err);
|
error_propagate(errp, err);
|
||||||
}
|
''',
|
||||||
''')
|
name=full_name)
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def generate_visit_struct(expr):
|
def generate_visit_struct(expr):
|
||||||
@@ -154,9 +191,7 @@ void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **
|
|||||||
''',
|
''',
|
||||||
name=name)
|
name=name)
|
||||||
|
|
||||||
push_indent()
|
|
||||||
ret += generate_visit_struct_body("", name, members)
|
ret += generate_visit_struct_body("", name, members)
|
||||||
pop_indent()
|
|
||||||
|
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
}
|
}
|
||||||
@@ -168,24 +203,26 @@ def generate_visit_list(name, members):
|
|||||||
|
|
||||||
void visit_type_%(name)sList(Visitor *m, %(name)sList ** obj, const char *name, Error **errp)
|
void visit_type_%(name)sList(Visitor *m, %(name)sList ** obj, const char *name, Error **errp)
|
||||||
{
|
{
|
||||||
GenericList *i, **prev = (GenericList **)obj;
|
|
||||||
Error *err = NULL;
|
Error *err = NULL;
|
||||||
|
GenericList *i, **prev;
|
||||||
|
|
||||||
if (!error_is_set(errp)) {
|
|
||||||
visit_start_list(m, name, &err);
|
visit_start_list(m, name, &err);
|
||||||
if (!err) {
|
if (err) {
|
||||||
for (; (i = visit_next_list(m, prev, &err)) != NULL; prev = &i) {
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (prev = (GenericList **)obj;
|
||||||
|
!err && (i = visit_next_list(m, prev, &err)) != NULL;
|
||||||
|
prev = &i) {
|
||||||
%(name)sList *native_i = (%(name)sList *)i;
|
%(name)sList *native_i = (%(name)sList *)i;
|
||||||
visit_type_%(name)s(m, &native_i->value, NULL, &err);
|
visit_type_%(name)s(m, &native_i->value, NULL, &err);
|
||||||
}
|
}
|
||||||
|
|
||||||
error_propagate(errp, err);
|
error_propagate(errp, err);
|
||||||
err = NULL;
|
err = NULL;
|
||||||
|
|
||||||
/* Always call end_list if start_list succeeded. */
|
|
||||||
visit_end_list(m, &err);
|
visit_end_list(m, &err);
|
||||||
}
|
out:
|
||||||
error_propagate(errp, err);
|
error_propagate(errp, err);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
''',
|
''',
|
||||||
name=name)
|
name=name)
|
||||||
@@ -207,9 +244,14 @@ void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **
|
|||||||
{
|
{
|
||||||
Error *err = NULL;
|
Error *err = NULL;
|
||||||
|
|
||||||
if (!error_is_set(errp)) {
|
|
||||||
visit_start_implicit_struct(m, (void**) obj, sizeof(%(name)s), &err);
|
visit_start_implicit_struct(m, (void**) obj, sizeof(%(name)s), &err);
|
||||||
|
if (err) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
visit_get_next_type(m, (int*) &(*obj)->kind, %(name)s_qtypes, name, &err);
|
visit_get_next_type(m, (int*) &(*obj)->kind, %(name)s_qtypes, name, &err);
|
||||||
|
if (err) {
|
||||||
|
goto out_end;
|
||||||
|
}
|
||||||
switch ((*obj)->kind) {
|
switch ((*obj)->kind) {
|
||||||
''',
|
''',
|
||||||
name=name)
|
name=name)
|
||||||
@@ -237,10 +279,12 @@ void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **
|
|||||||
default:
|
default:
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
out_end:
|
||||||
error_propagate(errp, err);
|
error_propagate(errp, err);
|
||||||
err = NULL;
|
err = NULL;
|
||||||
visit_end_implicit_struct(m, &err);
|
visit_end_implicit_struct(m, &err);
|
||||||
}
|
out:
|
||||||
|
error_propagate(errp, err);
|
||||||
}
|
}
|
||||||
''')
|
''')
|
||||||
|
|
||||||
@@ -277,39 +321,42 @@ def generate_visit_union(expr):
|
|||||||
del base_fields[discriminator]
|
del base_fields[discriminator]
|
||||||
ret += generate_visit_struct_fields(name, "", "", base_fields)
|
ret += generate_visit_struct_fields(name, "", "", base_fields)
|
||||||
|
|
||||||
|
if discriminator:
|
||||||
|
for key in members:
|
||||||
|
ret += generate_visit_implicit_struct(members[key])
|
||||||
|
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
|
|
||||||
void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **errp)
|
void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **errp)
|
||||||
{
|
{
|
||||||
Error *err = NULL;
|
Error *err = NULL;
|
||||||
|
|
||||||
if (!error_is_set(errp)) {
|
|
||||||
visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(name)s), &err);
|
visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(name)s), &err);
|
||||||
if (!err) {
|
if (err) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
if (*obj) {
|
if (*obj) {
|
||||||
''',
|
''',
|
||||||
name=name)
|
name=name)
|
||||||
|
|
||||||
|
|
||||||
push_indent()
|
|
||||||
push_indent()
|
|
||||||
push_indent()
|
|
||||||
|
|
||||||
if base:
|
if base:
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
visit_type_%(name)s_fields(m, obj, &err);
|
visit_type_%(name)s_fields(m, obj, &err);
|
||||||
|
if (err) {
|
||||||
|
goto out_obj;
|
||||||
|
}
|
||||||
''',
|
''',
|
||||||
name=name)
|
name=name)
|
||||||
|
|
||||||
pop_indent()
|
|
||||||
|
|
||||||
if not discriminator:
|
if not discriminator:
|
||||||
disc_key = "type"
|
disc_key = "type"
|
||||||
else:
|
else:
|
||||||
disc_key = discriminator
|
disc_key = discriminator
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
visit_type_%(disc_type)s(m, &(*obj)->kind, "%(disc_key)s", &err);
|
visit_type_%(disc_type)s(m, &(*obj)->kind, "%(disc_key)s", &err);
|
||||||
if (!err) {
|
if (err) {
|
||||||
|
goto out_obj;
|
||||||
|
}
|
||||||
switch ((*obj)->kind) {
|
switch ((*obj)->kind) {
|
||||||
''',
|
''',
|
||||||
disc_type = disc_type,
|
disc_type = disc_type,
|
||||||
@@ -319,13 +366,7 @@ void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **
|
|||||||
if not discriminator:
|
if not discriminator:
|
||||||
fmt = 'visit_type_%(c_type)s(m, &(*obj)->%(c_name)s, "data", &err);'
|
fmt = 'visit_type_%(c_type)s(m, &(*obj)->%(c_name)s, "data", &err);'
|
||||||
else:
|
else:
|
||||||
fmt = '''visit_start_implicit_struct(m, (void**) &(*obj)->%(c_name)s, sizeof(%(c_type)s), &err);
|
fmt = 'visit_type_implicit_%(c_type)s(m, &(*obj)->%(c_name)s, &err);'
|
||||||
if (!err) {
|
|
||||||
visit_type_%(c_type)s_fields(m, &(*obj)->%(c_name)s, &err);
|
|
||||||
error_propagate(errp, err);
|
|
||||||
err = NULL;
|
|
||||||
visit_end_implicit_struct(m, &err);
|
|
||||||
}'''
|
|
||||||
|
|
||||||
enum_full_value = generate_enum_full_value(disc_type, key)
|
enum_full_value = generate_enum_full_value(disc_type, key)
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
@@ -341,23 +382,14 @@ void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **
|
|||||||
default:
|
default:
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
}
|
out_obj:
|
||||||
error_propagate(errp, err);
|
error_propagate(errp, err);
|
||||||
err = NULL;
|
err = NULL;
|
||||||
}
|
}
|
||||||
''')
|
|
||||||
pop_indent()
|
|
||||||
ret += mcgen('''
|
|
||||||
/* Always call end_struct if start_struct succeeded. */
|
|
||||||
visit_end_struct(m, &err);
|
visit_end_struct(m, &err);
|
||||||
}
|
out:
|
||||||
error_propagate(errp, err);
|
error_propagate(errp, err);
|
||||||
}
|
}
|
||||||
''')
|
|
||||||
|
|
||||||
pop_indent();
|
|
||||||
ret += mcgen('''
|
|
||||||
}
|
|
||||||
''')
|
''')
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
@@ -476,7 +508,7 @@ fdecl.write(mcgen('''
|
|||||||
/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
|
/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* schema-defined QAPI visitor function
|
* schema-defined QAPI visitor functions
|
||||||
*
|
*
|
||||||
* Copyright IBM, Corp. 2011
|
* Copyright IBM, Corp. 2011
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -73,13 +73,18 @@ class QAPIExprError(Exception):
|
|||||||
|
|
||||||
class QAPISchema:
|
class QAPISchema:
|
||||||
|
|
||||||
def __init__(self, fp, input_relname=None, include_hist=[], parent_info=None):
|
def __init__(self, fp, input_relname=None, include_hist=[],
|
||||||
|
previously_included=[], parent_info=None):
|
||||||
|
""" include_hist is a stack used to detect inclusion cycles
|
||||||
|
previously_included is a global state used to avoid multiple
|
||||||
|
inclusions of the same file"""
|
||||||
input_fname = os.path.abspath(fp.name)
|
input_fname = os.path.abspath(fp.name)
|
||||||
if input_relname is None:
|
if input_relname is None:
|
||||||
input_relname = fp.name
|
input_relname = fp.name
|
||||||
self.input_dir = os.path.dirname(input_fname)
|
self.input_dir = os.path.dirname(input_fname)
|
||||||
self.input_file = input_relname
|
self.input_file = input_relname
|
||||||
self.include_hist = include_hist + [(input_relname, input_fname)]
|
self.include_hist = include_hist + [(input_relname, input_fname)]
|
||||||
|
previously_included.append(input_fname)
|
||||||
self.parent_info = parent_info
|
self.parent_info = parent_info
|
||||||
self.src = fp.read()
|
self.src = fp.read()
|
||||||
if self.src == '' or self.src[-1] != '\n':
|
if self.src == '' or self.src[-1] != '\n':
|
||||||
@@ -106,13 +111,16 @@ class QAPISchema:
|
|||||||
for elem in self.include_hist):
|
for elem in self.include_hist):
|
||||||
raise QAPIExprError(expr_info, "Inclusion loop for %s"
|
raise QAPIExprError(expr_info, "Inclusion loop for %s"
|
||||||
% include)
|
% include)
|
||||||
|
# skip multiple include of the same file
|
||||||
|
if include_path in previously_included:
|
||||||
|
continue
|
||||||
try:
|
try:
|
||||||
fobj = open(include_path, 'r')
|
fobj = open(include_path, 'r')
|
||||||
except IOError as e:
|
except IOError as e:
|
||||||
raise QAPIExprError(expr_info,
|
raise QAPIExprError(expr_info,
|
||||||
'%s: %s' % (e.strerror, include))
|
'%s: %s' % (e.strerror, include))
|
||||||
exprs_include = QAPISchema(fobj, include,
|
exprs_include = QAPISchema(fobj, include, self.include_hist,
|
||||||
self.include_hist, expr_info)
|
previously_included, expr_info)
|
||||||
self.exprs.extend(exprs_include.exprs)
|
self.exprs.extend(exprs_include.exprs)
|
||||||
else:
|
else:
|
||||||
expr_elem = {'expr': expr,
|
expr_elem = {'expr': expr,
|
||||||
|
|||||||
@@ -193,7 +193,8 @@ check-qapi-schema-y := $(addprefix tests/qapi-schema/, \
|
|||||||
flat-union-string-discriminator.json \
|
flat-union-string-discriminator.json \
|
||||||
include-simple.json include-relpath.json include-format-err.json \
|
include-simple.json include-relpath.json include-format-err.json \
|
||||||
include-non-file.json include-no-file.json include-before-err.json \
|
include-non-file.json include-no-file.json include-before-err.json \
|
||||||
include-nested-err.json include-self-cycle.json include-cycle.json)
|
include-nested-err.json include-self-cycle.json include-cycle.json \
|
||||||
|
include-repetition.json)
|
||||||
|
|
||||||
GENERATED_HEADERS += tests/test-qapi-types.h tests/test-qapi-visit.h tests/test-qmp-commands.h
|
GENERATED_HEADERS += tests/test-qapi-types.h tests/test-qapi-visit.h tests/test-qmp-commands.h
|
||||||
|
|
||||||
|
|||||||
2
tests/qapi-schema/include-repetition-sub.json
Normal file
2
tests/qapi-schema/include-repetition-sub.json
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
{ 'include': 'comments.json' }
|
||||||
|
{ 'include': 'comments.json' }
|
||||||
0
tests/qapi-schema/include-repetition.err
Normal file
0
tests/qapi-schema/include-repetition.err
Normal file
1
tests/qapi-schema/include-repetition.exit
Normal file
1
tests/qapi-schema/include-repetition.exit
Normal file
@@ -0,0 +1 @@
|
|||||||
|
0
|
||||||
3
tests/qapi-schema/include-repetition.json
Normal file
3
tests/qapi-schema/include-repetition.json
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{ 'include': 'comments.json' }
|
||||||
|
{ 'include': 'include-repetition-sub.json' }
|
||||||
|
{ 'include': 'comments.json' }
|
||||||
3
tests/qapi-schema/include-repetition.out
Normal file
3
tests/qapi-schema/include-repetition.out
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[OrderedDict([('enum', 'Status'), ('data', ['good', 'bad', 'ugly'])])]
|
||||||
|
[{'enum_name': 'Status', 'enum_values': ['good', 'bad', 'ugly']}]
|
||||||
|
[]
|
||||||
@@ -72,14 +72,30 @@ typedef struct TestStruct
|
|||||||
static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
|
static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
|
||||||
const char *name, Error **errp)
|
const char *name, Error **errp)
|
||||||
{
|
{
|
||||||
|
Error *err = NULL;
|
||||||
|
|
||||||
visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct),
|
visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct),
|
||||||
errp);
|
&err);
|
||||||
|
if (err) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
visit_type_int(v, &(*obj)->integer, "integer", errp);
|
visit_type_int(v, &(*obj)->integer, "integer", &err);
|
||||||
visit_type_bool(v, &(*obj)->boolean, "boolean", errp);
|
if (err) {
|
||||||
visit_type_str(v, &(*obj)->string, "string", errp);
|
goto out_end;
|
||||||
|
}
|
||||||
|
visit_type_bool(v, &(*obj)->boolean, "boolean", &err);
|
||||||
|
if (err) {
|
||||||
|
goto out_end;
|
||||||
|
}
|
||||||
|
visit_type_str(v, &(*obj)->string, "string", &err);
|
||||||
|
|
||||||
visit_end_struct(v, errp);
|
out_end:
|
||||||
|
error_propagate(errp, err);
|
||||||
|
err = NULL;
|
||||||
|
visit_end_struct(v, &err);
|
||||||
|
out:
|
||||||
|
error_propagate(errp, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_validate_struct(TestInputVisitorData *data,
|
static void test_validate_struct(TestInputVisitorData *data,
|
||||||
|
|||||||
@@ -199,16 +199,24 @@ static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
|
|||||||
|
|
||||||
visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct),
|
visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct),
|
||||||
&err);
|
&err);
|
||||||
if (!err) {
|
if (err) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
visit_type_int(v, &(*obj)->integer, "integer", &err);
|
visit_type_int(v, &(*obj)->integer, "integer", &err);
|
||||||
|
if (err) {
|
||||||
|
goto out_end;
|
||||||
|
}
|
||||||
visit_type_bool(v, &(*obj)->boolean, "boolean", &err);
|
visit_type_bool(v, &(*obj)->boolean, "boolean", &err);
|
||||||
|
if (err) {
|
||||||
|
goto out_end;
|
||||||
|
}
|
||||||
visit_type_str(v, &(*obj)->string, "string", &err);
|
visit_type_str(v, &(*obj)->string, "string", &err);
|
||||||
|
|
||||||
/* Always call end_struct if start_struct succeeded. */
|
out_end:
|
||||||
error_propagate(errp, err);
|
error_propagate(errp, err);
|
||||||
err = NULL;
|
err = NULL;
|
||||||
visit_end_struct(v, &err);
|
visit_end_struct(v, &err);
|
||||||
}
|
out:
|
||||||
error_propagate(errp, err);
|
error_propagate(errp, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -176,14 +176,30 @@ typedef struct TestStruct
|
|||||||
static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
|
static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
|
||||||
const char *name, Error **errp)
|
const char *name, Error **errp)
|
||||||
{
|
{
|
||||||
|
Error *err = NULL;
|
||||||
|
|
||||||
visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct),
|
visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct),
|
||||||
errp);
|
&err);
|
||||||
|
if (err) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
visit_type_int(v, &(*obj)->integer, "integer", errp);
|
visit_type_int(v, &(*obj)->integer, "integer", &err);
|
||||||
visit_type_bool(v, &(*obj)->boolean, "boolean", errp);
|
if (err) {
|
||||||
visit_type_str(v, &(*obj)->string, "string", errp);
|
goto out_end;
|
||||||
|
}
|
||||||
|
visit_type_bool(v, &(*obj)->boolean, "boolean", &err);
|
||||||
|
if (err) {
|
||||||
|
goto out_end;
|
||||||
|
}
|
||||||
|
visit_type_str(v, &(*obj)->string, "string", &err);
|
||||||
|
|
||||||
visit_end_struct(v, errp);
|
out_end:
|
||||||
|
error_propagate(errp, err);
|
||||||
|
err = NULL;
|
||||||
|
visit_end_struct(v, &err);
|
||||||
|
out:
|
||||||
|
error_propagate(errp, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_visitor_out_struct(TestOutputVisitorData *data,
|
static void test_visitor_out_struct(TestOutputVisitorData *data,
|
||||||
|
|||||||
@@ -195,13 +195,29 @@ typedef struct TestStruct
|
|||||||
static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
|
static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
|
||||||
const char *name, Error **errp)
|
const char *name, Error **errp)
|
||||||
{
|
{
|
||||||
visit_start_struct(v, (void **)obj, NULL, name, sizeof(TestStruct), errp);
|
Error *err = NULL;
|
||||||
|
|
||||||
visit_type_int(v, &(*obj)->integer, "integer", errp);
|
visit_start_struct(v, (void **)obj, NULL, name, sizeof(TestStruct), &err);
|
||||||
visit_type_bool(v, &(*obj)->boolean, "boolean", errp);
|
if (err) {
|
||||||
visit_type_str(v, &(*obj)->string, "string", errp);
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
visit_end_struct(v, errp);
|
visit_type_int(v, &(*obj)->integer, "integer", &err);
|
||||||
|
if (err) {
|
||||||
|
goto out_end;
|
||||||
|
}
|
||||||
|
visit_type_bool(v, &(*obj)->boolean, "boolean", &err);
|
||||||
|
if (err) {
|
||||||
|
goto out_end;
|
||||||
|
}
|
||||||
|
visit_type_str(v, &(*obj)->string, "string", &err);
|
||||||
|
|
||||||
|
out_end:
|
||||||
|
error_propagate(errp, err);
|
||||||
|
err = NULL;
|
||||||
|
visit_end_struct(v, &err);
|
||||||
|
out:
|
||||||
|
error_propagate(errp, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
static TestStruct *struct_create(void)
|
static TestStruct *struct_create(void)
|
||||||
|
|||||||
@@ -688,17 +688,21 @@ megasas_dcmd_ld_get_list(int cmd, int num, int max) "scmd %d: DCMD LD get list:
|
|||||||
megasas_dcmd_ld_get_info(int cmd, int ld_id) "scmd %d: DCMD LD get info for dev %d"
|
megasas_dcmd_ld_get_info(int cmd, int ld_id) "scmd %d: DCMD LD get info for dev %d"
|
||||||
megasas_dcmd_pd_get_info(int cmd, int pd_id) "scmd %d: DCMD PD get info for dev %d"
|
megasas_dcmd_pd_get_info(int cmd, int pd_id) "scmd %d: DCMD PD get info for dev %d"
|
||||||
megasas_dcmd_pd_list_query(int cmd, int flags) "scmd %d: DCMD PD list query flags %x"
|
megasas_dcmd_pd_list_query(int cmd, int flags) "scmd %d: DCMD PD list query flags %x"
|
||||||
|
megasas_dcmd_ld_list_query(int cmd, int flags) "scmd %d: DCMD LD list query flags %x"
|
||||||
megasas_dcmd_unsupported(int cmd, unsigned long size) "scmd %d: set properties len %ld"
|
megasas_dcmd_unsupported(int cmd, unsigned long size) "scmd %d: set properties len %ld"
|
||||||
megasas_abort_frame(int cmd, int abort_cmd) "scmd %d: aborting frame %x"
|
megasas_abort_frame(int cmd, int abort_cmd) "scmd %d: aborting frame %x"
|
||||||
megasas_abort_no_cmd(int cmd, uint64_t context) "scmd %d: no active command for frame context %" PRIx64 ""
|
megasas_abort_no_cmd(int cmd, uint64_t context) "scmd %d: no active command for frame context %" PRIx64 ""
|
||||||
megasas_abort_invalid_context(int cmd, uint64_t context, int abort_cmd) "scmd %d: invalid frame context %" PRIx64 " for abort frame %x"
|
megasas_abort_invalid_context(int cmd, uint64_t context, int abort_cmd) "scmd %d: invalid frame context %" PRIx64 " for abort frame %x"
|
||||||
megasas_reset(void) "Reset"
|
megasas_reset(void) "Reset"
|
||||||
megasas_init(int sges, int cmds, const char *intr, const char *mode) "Using %d sges, %d cmds, %s, %s mode"
|
megasas_init(int sges, int cmds, const char *mode) "Using %d sges, %d cmds, %s mode"
|
||||||
megasas_msix_raise(int vector) "vector %d"
|
megasas_msix_raise(int vector) "vector %d"
|
||||||
|
megasas_msi_raise(int vector) "vector %d"
|
||||||
megasas_irq_lower(void) "INTx"
|
megasas_irq_lower(void) "INTx"
|
||||||
megasas_irq_raise(void) "INTx"
|
megasas_irq_raise(void) "INTx"
|
||||||
megasas_intr_enabled(void) "Interrupts enabled"
|
megasas_intr_enabled(void) "Interrupts enabled"
|
||||||
megasas_intr_disabled(void) "Interrupts disabled"
|
megasas_intr_disabled(void) "Interrupts disabled"
|
||||||
|
megasas_msix_enabled(int vector) "vector %d"
|
||||||
|
megasas_msi_enabled(int vector) "vector %d"
|
||||||
megasas_mmio_readl(unsigned long addr, uint32_t val) "addr 0x%lx: 0x%x"
|
megasas_mmio_readl(unsigned long addr, uint32_t val) "addr 0x%lx: 0x%x"
|
||||||
megasas_mmio_invalid_readl(unsigned long addr) "addr 0x%lx"
|
megasas_mmio_invalid_readl(unsigned long addr) "addr 0x%lx"
|
||||||
megasas_mmio_writel(uint32_t addr, uint32_t val) "addr 0x%x: 0x%x"
|
megasas_mmio_writel(uint32_t addr, uint32_t val) "addr 0x%x: 0x%x"
|
||||||
|
|||||||
Reference in New Issue
Block a user