aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--block/file-posix.c50
-rw-r--r--block/mirror.c5
-rw-r--r--block/nbd-client.c12
-rw-r--r--disas/microblaze.c2
-rw-r--r--hw/display/cirrus_vga_rop2.h4
-rw-r--r--hw/i386/amd_iommu.c3
-rw-r--r--hw/i386/trace-events1
-rw-r--r--hw/input/virtio-input.c33
-rw-r--r--hw/scsi/megasas.c6
-rw-r--r--include/hw/virtio/virtio-input.h5
-rw-r--r--nbd/client.c2
-rw-r--r--qemu-img.c196
-rw-r--r--tests/boot-serial-test.c4
-rw-r--r--ui/egl-helpers.c58
-rw-r--r--ui/vnc.c17
15 files changed, 276 insertions, 122 deletions
diff --git a/block/file-posix.c b/block/file-posix.c
index 53febd3767..0841a08785 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
@@ -144,6 +144,7 @@ typedef struct BDRVRawState {
bool has_write_zeroes:1;
bool discard_zeroes:1;
bool use_linux_aio:1;
+ bool page_cache_inconsistent:1;
bool has_fallocate;
bool needs_alignment;
} BDRVRawState;
@@ -219,28 +220,28 @@ static int probe_logical_blocksize(int fd, unsigned int *sector_size_p)
{
unsigned int sector_size;
bool success = false;
+ int i;
errno = ENOTSUP;
-
- /* Try a few ioctls to get the right size */
+ static const unsigned long ioctl_list[] = {
#ifdef BLKSSZGET
- if (ioctl(fd, BLKSSZGET, &sector_size) >= 0) {
- *sector_size_p = sector_size;
- success = true;
- }
+ BLKSSZGET,
#endif
#ifdef DKIOCGETBLOCKSIZE
- if (ioctl(fd, DKIOCGETBLOCKSIZE, &sector_size) >= 0) {
- *sector_size_p = sector_size;
- success = true;
- }
+ DKIOCGETBLOCKSIZE,
#endif
#ifdef DIOCGSECTORSIZE
- if (ioctl(fd, DIOCGSECTORSIZE, &sector_size) >= 0) {
- *sector_size_p = sector_size;
- success = true;
- }
+ DIOCGSECTORSIZE,
#endif
+ };
+
+ /* Try a few ioctls to get the right size */
+ for (i = 0; i < (int)ARRAY_SIZE(ioctl_list); i++) {
+ if (ioctl(fd, ioctl_list[i], &sector_size) >= 0) {
+ *sector_size_p = sector_size;
+ success = true;
+ }
+ }
return success ? 0 : -errno;
}
@@ -824,10 +825,31 @@ static ssize_t handle_aiocb_ioctl(RawPosixAIOData *aiocb)
static ssize_t handle_aiocb_flush(RawPosixAIOData *aiocb)
{
+ BDRVRawState *s = aiocb->bs->opaque;
int ret;
+ if (s->page_cache_inconsistent) {
+ return -EIO;
+ }
+
ret = qemu_fdatasync(aiocb->aio_fildes);
if (ret == -1) {
+ /* There is no clear definition of the semantics of a failing fsync(),
+ * so we may have to assume the worst. The sad truth is that this
+ * assumption is correct for Linux. Some pages are now probably marked
+ * clean in the page cache even though they are inconsistent with the
+ * on-disk contents. The next fdatasync() call would succeed, but no
+ * further writeback attempt will be made. We can't get back to a state
+ * in which we know what is on disk (we would have to rewrite
+ * everything that was touched since the last fdatasync() at least), so
+ * make bdrv_flush() fail permanently. Given that the behaviour isn't
+ * really defined, I have little hope that other OSes are doing better.
+ *
+ * Obviously, this doesn't affect O_DIRECT, which bypasses the page
+ * cache. */
+ if ((s->open_flags & O_DIRECT) == 0) {
+ s->page_cache_inconsistent = true;
+ }
return -errno;
}
return 0;
diff --git a/block/mirror.c b/block/mirror.c
index ca4baa510a..9e2fecc15e 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -634,7 +634,8 @@ static int coroutine_fn mirror_dirty_init(MirrorBlockJob *s)
}
if (s->in_flight >= MAX_IN_FLIGHT) {
- trace_mirror_yield(s, s->in_flight, s->buf_free_count, -1);
+ trace_mirror_yield(s, UINT64_MAX, s->buf_free_count,
+ s->in_flight);
mirror_wait_for_io(s);
continue;
}
@@ -809,7 +810,7 @@ static void coroutine_fn mirror_run(void *opaque)
s->common.iostatus == BLOCK_DEVICE_IO_STATUS_OK) {
if (s->in_flight >= MAX_IN_FLIGHT || s->buf_free_count == 0 ||
(cnt == 0 && s->in_flight > 0)) {
- trace_mirror_yield(s, s->in_flight, s->buf_free_count, cnt);
+ trace_mirror_yield(s, cnt, s->buf_free_count, s->in_flight);
mirror_wait_for_io(s);
continue;
} else if (cnt != 0) {
diff --git a/block/nbd-client.c b/block/nbd-client.c
index 0dc12c2d67..1e2952fdae 100644
--- a/block/nbd-client.c
+++ b/block/nbd-client.c
@@ -33,17 +33,15 @@
#define HANDLE_TO_INDEX(bs, handle) ((handle) ^ ((uint64_t)(intptr_t)bs))
#define INDEX_TO_HANDLE(bs, index) ((index) ^ ((uint64_t)(intptr_t)bs))
-static void nbd_recv_coroutines_enter_all(BlockDriverState *bs)
+static void nbd_recv_coroutines_enter_all(NBDClientSession *s)
{
- NBDClientSession *s = nbd_get_client_session(bs);
int i;
for (i = 0; i < MAX_NBD_REQUESTS; i++) {
if (s->recv_coroutine[i]) {
- qemu_coroutine_enter(s->recv_coroutine[i]);
+ aio_co_wake(s->recv_coroutine[i]);
}
}
- BDRV_POLL_WHILE(bs, s->read_reply_co);
}
static void nbd_teardown_connection(BlockDriverState *bs)
@@ -58,7 +56,7 @@ static void nbd_teardown_connection(BlockDriverState *bs)
qio_channel_shutdown(client->ioc,
QIO_CHANNEL_SHUTDOWN_BOTH,
NULL);
- nbd_recv_coroutines_enter_all(bs);
+ BDRV_POLL_WHILE(bs, client->read_reply_co);
nbd_client_detach_aio_context(bs);
object_unref(OBJECT(client->sioc));
@@ -76,7 +74,7 @@ static coroutine_fn void nbd_read_reply_entry(void *opaque)
for (;;) {
assert(s->reply.handle == 0);
ret = nbd_receive_reply(s->ioc, &s->reply);
- if (ret < 0) {
+ if (ret <= 0) {
break;
}
@@ -103,6 +101,8 @@ static coroutine_fn void nbd_read_reply_entry(void *opaque)
aio_co_wake(s->recv_coroutine[i]);
qemu_coroutine_yield();
}
+
+ nbd_recv_coroutines_enter_all(s);
s->read_reply_co = NULL;
}
diff --git a/disas/microblaze.c b/disas/microblaze.c
index 407c0a3ffa..7795a0bdb9 100644
--- a/disas/microblaze.c
+++ b/disas/microblaze.c
@@ -159,7 +159,7 @@ enum microblaze_instr_type {
#define MIN_PVR_REGNUM 0
#define MAX_PVR_REGNUM 15
-#define REG_PC 32 /* PC */
+/* 32 is REG_PC */
#define REG_MSR 33 /* machine status reg */
#define REG_EAR 35 /* Exception reg */
#define REG_ESR 37 /* Exception reg */
diff --git a/hw/display/cirrus_vga_rop2.h b/hw/display/cirrus_vga_rop2.h
index b86bcd6e09..b208b7348a 100644
--- a/hw/display/cirrus_vga_rop2.h
+++ b/hw/display/cirrus_vga_rop2.h
@@ -29,8 +29,8 @@
#elif DEPTH == 24
#define PUTPIXEL(s, a, c) do { \
ROP_OP(s, a, c); \
- ROP_OP(s, a + 1, (col >> 8)); \
- ROP_OP(s, a + 2, (col >> 16)); \
+ ROP_OP(s, a + 1, (c >> 8)); \
+ ROP_OP(s, a + 2, (c >> 16)); \
} while (0)
#elif DEPTH == 32
#define PUTPIXEL(s, a, c) ROP_OP_32(s, a, c)
diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
index e0732ccaf1..f86a40aa30 100644
--- a/hw/i386/amd_iommu.c
+++ b/hw/i386/amd_iommu.c
@@ -572,8 +572,7 @@ static uint64_t amdvi_mmio_read(void *opaque, hwaddr addr, unsigned size)
uint64_t val = -1;
if (addr + size > AMDVI_MMIO_SIZE) {
- trace_amdvi_mmio_read("error: addr outside region: max ",
- (uint64_t)AMDVI_MMIO_SIZE, addr, size);
+ trace_amdvi_mmio_read_invalid(AMDVI_MMIO_SIZE, addr, size);
return (uint64_t)-1;
}
diff --git a/hw/i386/trace-events b/hw/i386/trace-events
index 88ad5e4c43..baed874a80 100644
--- a/hw/i386/trace-events
+++ b/hw/i386/trace-events
@@ -37,6 +37,7 @@ amdvi_cache_update(uint16_t domid, uint8_t bus, uint8_t slot, uint8_t func, uint
amdvi_completion_wait_fail(uint64_t addr) "error: fail to write at address 0x%"PRIx64
amdvi_mmio_write(const char *reg, uint64_t addr, unsigned size, uint64_t val, uint64_t offset) "%s write addr 0x%"PRIx64", size %u, val 0x%"PRIx64", offset 0x%"PRIx64
amdvi_mmio_read(const char *reg, uint64_t addr, unsigned size, uint64_t offset) "%s read addr 0x%"PRIx64", size %u offset 0x%"PRIx64
+amdvi_mmio_read_invalid(int max, uint64_t addr, unsigned size) "error: addr outside region (max 0x%x): read addr 0x%" PRIx64 ", size %u"
amdvi_command_error(uint64_t status) "error: Executing commands with command buffer disabled 0x%"PRIx64
amdvi_command_read_fail(uint64_t addr, uint32_t head) "error: fail to access memory at 0x%"PRIx64" + 0x%"PRIx32
amdvi_command_exec(uint32_t head, uint32_t tail, uint64_t buf) "command buffer head at 0x%"PRIx32" command buffer tail at 0x%"PRIx32" command buffer base at 0x%"PRIx64
diff --git a/hw/input/virtio-input.c b/hw/input/virtio-input.c
index b678ee9f20..0e42f0d02c 100644
--- a/hw/input/virtio-input.c
+++ b/hw/input/virtio-input.c
@@ -22,7 +22,6 @@
void virtio_input_send(VirtIOInput *vinput, virtio_input_event *event)
{
VirtQueueElement *elem;
- unsigned have, need;
int i, len;
if (!vinput->active) {
@@ -32,10 +31,10 @@ void virtio_input_send(VirtIOInput *vinput, virtio_input_event *event)
/* queue up events ... */
if (vinput->qindex == vinput->qsize) {
vinput->qsize++;
- vinput->queue = realloc(vinput->queue, vinput->qsize *
- sizeof(virtio_input_event));
+ vinput->queue = g_realloc(vinput->queue, vinput->qsize *
+ sizeof(vinput->queue[0]));
}
- vinput->queue[vinput->qindex++] = *event;
+ vinput->queue[vinput->qindex++].event = *event;
/* ... until we see a report sync ... */
if (event->type != cpu_to_le16(EV_SYN) ||
@@ -44,24 +43,24 @@ void virtio_input_send(VirtIOInput *vinput, virtio_input_event *event)
}
/* ... then check available space ... */
- need = sizeof(virtio_input_event) * vinput->qindex;
- virtqueue_get_avail_bytes(vinput->evt, &have, NULL, need, 0);
- if (have < need) {
- vinput->qindex = 0;
- trace_virtio_input_queue_full();
- return;
- }
-
- /* ... and finally pass them to the guest */
for (i = 0; i < vinput->qindex; i++) {
elem = virtqueue_pop(vinput->evt, sizeof(VirtQueueElement));
if (!elem) {
- /* should not happen, we've checked for space beforehand */
- fprintf(stderr, "%s: Huh? No vq elem available ...\n", __func__);
+ while (--i >= 0) {
+ virtqueue_unpop(vinput->evt, vinput->queue[i].elem, 0);
+ }
+ vinput->qindex = 0;
+ trace_virtio_input_queue_full();
return;
}
+ vinput->queue[i].elem = elem;
+ }
+
+ /* ... and finally pass them to the guest */
+ for (i = 0; i < vinput->qindex; i++) {
+ elem = vinput->queue[i].elem;
len = iov_from_buf(elem->in_sg, elem->in_num,
- 0, vinput->queue+i, sizeof(virtio_input_event));
+ 0, &vinput->queue[i].event, sizeof(virtio_input_event));
virtqueue_push(vinput->evt, elem, len);
g_free(elem);
}
@@ -272,6 +271,8 @@ static void virtio_input_finalize(Object *obj)
QTAILQ_REMOVE(&vinput->cfg_list, cfg, node);
g_free(cfg);
}
+
+ g_free(vinput->queue);
}
static void virtio_input_device_unrealize(DeviceState *dev, Error **errp)
{
diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
index e3d59b7c83..84b8caf901 100644
--- a/hw/scsi/megasas.c
+++ b/hw/scsi/megasas.c
@@ -291,7 +291,7 @@ static int megasas_map_sgl(MegasasState *s, MegasasCmd *cmd, union mfi_sgl *sgl)
if (cmd->iov_size > iov_size) {
trace_megasas_iovec_overflow(cmd->index, iov_size, cmd->iov_size);
} else if (cmd->iov_size < iov_size) {
- trace_megasas_iovec_underflow(cmd->iov_size, iov_size, cmd->iov_size);
+ trace_megasas_iovec_underflow(cmd->index, iov_size, cmd->iov_size);
}
cmd->iov_offset = 0;
return 0;
@@ -1924,8 +1924,8 @@ static int megasas_handle_abort(MegasasState *s, MegasasCmd *cmd)
abort_ctx &= (uint64_t)0xFFFFFFFF;
}
if (abort_cmd->context != abort_ctx) {
- trace_megasas_abort_invalid_context(cmd->index, abort_cmd->index,
- abort_cmd->context);
+ trace_megasas_abort_invalid_context(cmd->index, abort_cmd->context,
+ abort_cmd->index);
s->event_count++;
return MFI_STAT_ABORT_NOT_POSSIBLE;
}
diff --git a/include/hw/virtio/virtio-input.h b/include/hw/virtio/virtio-input.h
index 55db31087a..91df57eca4 100644
--- a/include/hw/virtio/virtio-input.h
+++ b/include/hw/virtio/virtio-input.h
@@ -62,7 +62,10 @@ struct VirtIOInput {
VirtQueue *evt, *sts;
char *serial;
- virtio_input_event *queue;
+ struct {
+ virtio_input_event event;
+ VirtQueueElement *elem;
+ } *queue;
uint32_t qindex, qsize;
bool active;
diff --git a/nbd/client.c b/nbd/client.c
index 3dc2564cd0..a58fb02cb4 100644
--- a/nbd/client.c
+++ b/nbd/client.c
@@ -812,6 +812,6 @@ ssize_t nbd_receive_reply(QIOChannel *ioc, NBDReply *reply)
LOG("invalid magic (got 0x%" PRIx32 ")", magic);
return -EINVAL;
}
- return 0;
+ return sizeof(buf);
}
diff --git a/qemu-img.c b/qemu-img.c
index 98b836b030..b220cf71d7 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -88,6 +88,16 @@ static void QEMU_NORETURN GCC_FMT_ATTR(1, 2) error_exit(const char *fmt, ...)
exit(EXIT_FAILURE);
}
+static void QEMU_NORETURN missing_argument(const char *option)
+{
+ error_exit("missing argument for option '%s'", option);
+}
+
+static void QEMU_NORETURN unrecognized_option(const char *option)
+{
+ error_exit("unrecognized option '%s'", option);
+}
+
/* Please keep in synch with qemu-img.texi */
static void QEMU_NORETURN help(void)
{
@@ -406,13 +416,18 @@ static int img_create(int argc, char **argv)
{"object", required_argument, 0, OPTION_OBJECT},
{0, 0, 0, 0}
};
- c = getopt_long(argc, argv, "F:b:f:he6o:q",
+ c = getopt_long(argc, argv, ":F:b:f:he6o:q",
long_options, NULL);
if (c == -1) {
break;
}
switch(c) {
+ case ':':
+ missing_argument(argv[optind - 1]);
+ break;
case '?':
+ unrecognized_option(argv[optind - 1]);
+ break;
case 'h':
help();
break;
@@ -651,13 +666,18 @@ static int img_check(int argc, char **argv)
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
{0, 0, 0, 0}
};
- c = getopt_long(argc, argv, "hf:r:T:q",
+ c = getopt_long(argc, argv, ":hf:r:T:q",
long_options, &option_index);
if (c == -1) {
break;
}
switch(c) {
+ case ':':
+ missing_argument(argv[optind - 1]);
+ break;
case '?':
+ unrecognized_option(argv[optind - 1]);
+ break;
case 'h':
help();
break;
@@ -855,13 +875,18 @@ static int img_commit(int argc, char **argv)
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
{0, 0, 0, 0}
};
- c = getopt_long(argc, argv, "f:ht:b:dpq",
+ c = getopt_long(argc, argv, ":f:ht:b:dpq",
long_options, NULL);
if (c == -1) {
break;
}
switch(c) {
+ case ':':
+ missing_argument(argv[optind - 1]);
+ break;
case '?':
+ unrecognized_option(argv[optind - 1]);
+ break;
case 'h':
help();
break;
@@ -1190,13 +1215,18 @@ static int img_compare(int argc, char **argv)
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
{0, 0, 0, 0}
};
- c = getopt_long(argc, argv, "hf:F:T:pqs",
+ c = getopt_long(argc, argv, ":hf:F:T:pqs",
long_options, NULL);
if (c == -1) {
break;
}
switch (c) {
+ case ':':
+ missing_argument(argv[optind - 1]);
+ break;
case '?':
+ unrecognized_option(argv[optind - 1]);
+ break;
case 'h':
help();
break;
@@ -1926,13 +1956,18 @@ static int img_convert(int argc, char **argv)
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
{0, 0, 0, 0}
};
- c = getopt_long(argc, argv, "hf:O:B:ce6o:s:l:S:pt:T:qnm:W",
+ c = getopt_long(argc, argv, ":hf:O:B:ce6o:s:l:S:pt:T:qnm:W",
long_options, NULL);
if (c == -1) {
break;
}
switch(c) {
+ case ':':
+ missing_argument(argv[optind - 1]);
+ break;
case '?':
+ unrecognized_option(argv[optind - 1]);
+ break;
case 'h':
help();
break;
@@ -2502,13 +2537,18 @@ static int img_info(int argc, char **argv)
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
{0, 0, 0, 0}
};
- c = getopt_long(argc, argv, "f:h",
+ c = getopt_long(argc, argv, ":f:h",
long_options, &option_index);
if (c == -1) {
break;
}
switch(c) {
+ case ':':
+ missing_argument(argv[optind - 1]);
+ break;
case '?':
+ unrecognized_option(argv[optind - 1]);
+ break;
case 'h':
help();
break;
@@ -2713,13 +2753,18 @@ static int img_map(int argc, char **argv)
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
{0, 0, 0, 0}
};
- c = getopt_long(argc, argv, "f:h",
+ c = getopt_long(argc, argv, ":f:h",
long_options, &option_index);
if (c == -1) {
break;
}
switch (c) {
+ case ':':
+ missing_argument(argv[optind - 1]);
+ break;
case '?':
+ unrecognized_option(argv[optind - 1]);
+ break;
case 'h':
help();
break;
@@ -2835,13 +2880,18 @@ static int img_snapshot(int argc, char **argv)
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
{0, 0, 0, 0}
};
- c = getopt_long(argc, argv, "la:c:d:hq",
+ c = getopt_long(argc, argv, ":la:c:d:hq",
long_options, NULL);
if (c == -1) {
break;
}
switch(c) {
+ case ':':
+ missing_argument(argv[optind - 1]);
+ break;
case '?':
+ unrecognized_option(argv[optind - 1]);
+ break;
case 'h':
help();
return 0;
@@ -2988,13 +3038,18 @@ static int img_rebase(int argc, char **argv)
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
{0, 0, 0, 0}
};
- c = getopt_long(argc, argv, "hf:F:b:upt:T:q",
+ c = getopt_long(argc, argv, ":hf:F:b:upt:T:q",
long_options, NULL);
if (c == -1) {
break;
}
switch(c) {
+ case ':':
+ missing_argument(argv[optind - 1]);
+ break;
case '?':
+ unrecognized_option(argv[optind - 1]);
+ break;
case 'h':
help();
return 0;
@@ -3355,13 +3410,18 @@ static int img_resize(int argc, char **argv)
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
{0, 0, 0, 0}
};
- c = getopt_long(argc, argv, "f:hq",
+ c = getopt_long(argc, argv, ":f:hq",
long_options, NULL);
if (c == -1) {
break;
}
switch(c) {
+ case ':':
+ missing_argument(argv[optind - 1]);
+ break;
case '?':
+ unrecognized_option(argv[optind - 1]);
+ break;
case 'h':
help();
break;
@@ -3493,54 +3553,59 @@ static int img_amend(int argc, char **argv)
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
{0, 0, 0, 0}
};
- c = getopt_long(argc, argv, "ho:f:t:pq",
+ c = getopt_long(argc, argv, ":ho:f:t:pq",
long_options, NULL);
if (c == -1) {
break;
}
switch (c) {
- case 'h':
- case '?':
- help();
- break;
- case 'o':
- if (!is_valid_option_list(optarg)) {
- error_report("Invalid option list: %s", optarg);
- ret = -1;
- goto out_no_progress;
- }
- if (!options) {
- options = g_strdup(optarg);
- } else {
- char *old_options = options;
- options = g_strdup_printf("%s,%s", options, optarg);
- g_free(old_options);
- }
- break;
- case 'f':
- fmt = optarg;
- break;
- case 't':
- cache = optarg;
- break;
- case 'p':
- progress = true;
- break;
- case 'q':
- quiet = true;
- break;
- case OPTION_OBJECT:
- opts = qemu_opts_parse_noisily(&qemu_object_opts,
- optarg, true);
- if (!opts) {
- ret = -1;
- goto out_no_progress;
- }
- break;
- case OPTION_IMAGE_OPTS:
- image_opts = true;
- break;
+ case ':':
+ missing_argument(argv[optind - 1]);
+ break;
+ case '?':
+ unrecognized_option(argv[optind - 1]);
+ break;
+ case 'h':
+ help();
+ break;
+ case 'o':
+ if (!is_valid_option_list(optarg)) {
+ error_report("Invalid option list: %s", optarg);
+ ret = -1;
+ goto out_no_progress;
+ }
+ if (!options) {
+ options = g_strdup(optarg);
+ } else {
+ char *old_options = options;
+ options = g_strdup_printf("%s,%s", options, optarg);
+ g_free(old_options);
+ }
+ break;
+ case 'f':
+ fmt = optarg;
+ break;
+ case 't':
+ cache = optarg;
+ break;
+ case 'p':
+ progress = true;
+ break;
+ case 'q':
+ quiet = true;
+ break;
+ case OPTION_OBJECT:
+ opts = qemu_opts_parse_noisily(&qemu_object_opts,
+ optarg, true);
+ if (!opts) {
+ ret = -1;
+ goto out_no_progress;
+ }
+ break;
+ case OPTION_IMAGE_OPTS:
+ image_opts = true;
+ break;
}
}
@@ -3759,14 +3824,19 @@ static int img_bench(int argc, char **argv)
{"no-drain", no_argument, 0, OPTION_NO_DRAIN},
{0, 0, 0, 0}
};
- c = getopt_long(argc, argv, "hc:d:f:no:qs:S:t:w", long_options, NULL);
+ c = getopt_long(argc, argv, ":hc:d:f:no:qs:S:t:w", long_options, NULL);
if (c == -1) {
break;
}
switch (c) {
- case 'h':
+ case ':':
+ missing_argument(argv[optind - 1]);
+ break;
case '?':
+ unrecognized_option(argv[optind - 1]);
+ break;
+ case 'h':
help();
break;
case 'c':
@@ -4093,7 +4163,7 @@ static int img_dd(int argc, char **argv)
{ 0, 0, 0, 0 }
};
- while ((c = getopt_long(argc, argv, "hf:O:", long_options, NULL))) {
+ while ((c = getopt_long(argc, argv, ":hf:O:", long_options, NULL))) {
if (c == EOF) {
break;
}
@@ -4104,10 +4174,12 @@ static int img_dd(int argc, char **argv)
case 'f':
fmt = optarg;
break;
+ case ':':
+ missing_argument(argv[optind - 1]);
+ break;
case '?':
- error_report("Try 'qemu-img --help' for more information.");
- ret = -1;
- goto out;
+ unrecognized_option(argv[optind - 1]);
+ break;
case 'h':
help();
break;
@@ -4336,8 +4408,14 @@ int main(int argc, char **argv)
qemu_add_opts(&qemu_source_opts);
qemu_add_opts(&qemu_trace_opts);
- while ((c = getopt_long(argc, argv, "+hVT:", long_options, NULL)) != -1) {
+ while ((c = getopt_long(argc, argv, "+:hVT:", long_options, NULL)) != -1) {
switch (c) {
+ case ':':
+ missing_argument(argv[optind - 1]);
+ return 0;
+ case '?':
+ unrecognized_option(argv[optind - 1]);
+ return 0;
case 'h':
help();
return 0;
diff --git a/tests/boot-serial-test.c b/tests/boot-serial-test.c
index 57edf6af33..11f48b049c 100644
--- a/tests/boot-serial-test.c
+++ b/tests/boot-serial-test.c
@@ -79,8 +79,8 @@ static void test_machine(const void *data)
g_assert(fd != -1);
args = g_strdup_printf("-M %s,accel=tcg -chardev file,id=serial0,path=%s"
- " -serial chardev:serial0 %s", test->machine,
- tmpname, test->extra);
+ " -no-shutdown -serial chardev:serial0 %s",
+ test->machine, tmpname, test->extra);
qtest_start(args);
unlink(tmpname);
diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c
index 584dd1b04d..b7b6b2e3cc 100644
--- a/ui/egl-helpers.c
+++ b/ui/egl-helpers.c
@@ -192,6 +192,56 @@ EGLSurface qemu_egl_init_surface_x11(EGLContext ectx, Window win)
/* ---------------------------------------------------------------------- */
+/*
+ * Taken from glamor_egl.h from the Xorg xserver, which is MIT licensed
+ *
+ * Create an EGLDisplay from a native display type. This is a little quirky
+ * for a few reasons.
+ *
+ * 1: GetPlatformDisplayEXT and GetPlatformDisplay are the API you want to
+ * use, but have different function signatures in the third argument; this
+ * happens not to matter for us, at the moment, but it means epoxy won't alias
+ * them together.
+ *
+ * 2: epoxy 1.3 and earlier don't understand EGL client extensions, which
+ * means you can't call "eglGetPlatformDisplayEXT" directly, as the resolver
+ * will crash.
+ *
+ * 3: You can't tell whether you have EGL 1.5 at this point, because
+ * eglQueryString(EGL_VERSION) is a property of the display, which we don't
+ * have yet. So you have to query for extensions no matter what. Fortunately
+ * epoxy_has_egl_extension _does_ let you query for client extensions, so
+ * we don't have to write our own extension string parsing.
+ *
+ * 4. There is no EGL_KHR_platform_base to complement the EXT one, thus one
+ * needs to know EGL 1.5 is supported in order to use the eglGetPlatformDisplay
+ * function pointer.
+ * We can workaround this (circular dependency) by probing for the EGL 1.5
+ * platform extensions (EGL_KHR_platform_gbm and friends) yet it doesn't seem
+ * like mesa will be able to advertise these (even though it can do EGL 1.5).
+ */
+static EGLDisplay qemu_egl_get_display(void *native)
+{
+ EGLDisplay dpy = EGL_NO_DISPLAY;
+
+#ifdef EGL_MESA_platform_gbm
+ /* In practise any EGL 1.5 implementation would support the EXT extension */
+ if (epoxy_has_egl_extension(NULL, "EGL_EXT_platform_base")) {
+ PFNEGLGETPLATFORMDISPLAYEXTPROC getPlatformDisplayEXT =
+ (void *) eglGetProcAddress("eglGetPlatformDisplayEXT");
+ if (getPlatformDisplayEXT) {
+ dpy = getPlatformDisplayEXT(EGL_PLATFORM_GBM_MESA, native, NULL);
+ }
+ }
+#endif
+
+ if (dpy == EGL_NO_DISPLAY) {
+ /* fallback */
+ dpy = eglGetDisplay(native);
+ }
+ return dpy;
+}
+
int qemu_egl_init_dpy(EGLNativeDisplayType dpy, bool gles, bool debug)
{
static const EGLint conf_att_gl[] = {
@@ -222,12 +272,8 @@ int qemu_egl_init_dpy(EGLNativeDisplayType dpy, bool gles, bool debug)
setenv("LIBGL_DEBUG", "verbose", true);
}
- egl_dbg("eglGetDisplay (dpy %p) ...\n", dpy);
-#ifdef EGL_MESA_platform_gbm
- qemu_egl_display = eglGetPlatformDisplayEXT(EGL_PLATFORM_GBM_MESA, dpy, NULL);
-#else
- qemu_egl_display = eglGetDisplay(dpy);
-#endif
+ egl_dbg("qemu_egl_get_display (dpy %p) ...\n", dpy);
+ qemu_egl_display = qemu_egl_get_display(dpy);
if (qemu_egl_display == EGL_NO_DISPLAY) {
error_report("egl: eglGetDisplay failed");
return -1;
diff --git a/ui/vnc.c b/ui/vnc.c
index 6e93b883b5..821acdd8b0 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -3401,6 +3401,7 @@ vnc_display_create_creds(bool x509,
static int vnc_display_get_address(const char *addrstr,
bool websocket,
+ bool reverse,
int displaynum,
int to,
bool has_ipv4,
@@ -3480,21 +3481,22 @@ static int vnc_display_get_address(const char *addrstr,
inet->port = g_strdup(port);
}
} else {
+ int offset = reverse ? 0 : 5900;
if (parse_uint_full(port, &baseport, 10) < 0) {
error_setg(errp, "can't convert to a number: %s", port);
goto cleanup;
}
if (baseport > 65535 ||
- baseport + 5900 > 65535) {
+ baseport + offset > 65535) {
error_setg(errp, "port %s out of range", port);
goto cleanup;
}
inet->port = g_strdup_printf(
- "%d", (int)baseport + 5900);
+ "%d", (int)baseport + offset);
if (to) {
inet->has_to = true;
- inet->to = to + 5900;
+ inet->to = to + offset;
}
}
@@ -3516,6 +3518,7 @@ static int vnc_display_get_address(const char *addrstr,
}
static int vnc_display_get_addresses(QemuOpts *opts,
+ bool reverse,
SocketAddress ***retsaddr,
size_t *retnsaddr,
SocketAddress ***retwsaddr,
@@ -3555,7 +3558,7 @@ static int vnc_display_get_addresses(QemuOpts *opts,
qemu_opt_iter_init(&addriter, opts, "vnc");
while ((addr = qemu_opt_iter_next(&addriter)) != NULL) {
int rv;
- rv = vnc_display_get_address(addr, false, 0, to,
+ rv = vnc_display_get_address(addr, false, reverse, 0, to,
has_ipv4, has_ipv6,
ipv4, ipv6,
&saddr, errp);
@@ -3580,7 +3583,7 @@ static int vnc_display_get_addresses(QemuOpts *opts,
qemu_opt_iter_init(&addriter, opts, "websocket");
while ((addr = qemu_opt_iter_next(&addriter)) != NULL) {
- if (vnc_display_get_address(addr, true, displaynum, to,
+ if (vnc_display_get_address(addr, true, reverse, displaynum, to,
has_ipv4, has_ipv6,
ipv4, ipv6,
&wsaddr, errp) < 0) {
@@ -3777,7 +3780,8 @@ void vnc_display_open(const char *id, Error **errp)
return;
}
- if (vnc_display_get_addresses(opts, &saddr, &nsaddr,
+ reverse = qemu_opt_get_bool(opts, "reverse", false);
+ if (vnc_display_get_addresses(opts, reverse, &saddr, &nsaddr,
&wsaddr, &nwsaddr, errp) < 0) {
goto fail;
}
@@ -3803,7 +3807,6 @@ void vnc_display_open(const char *id, Error **errp)
}
}
- reverse = qemu_opt_get_bool(opts, "reverse", false);
lock_key_sync = qemu_opt_get_bool(opts, "lock-key-sync", true);
key_delay_ms = qemu_opt_get_number(opts, "key-delay-ms", 1);
sasl = qemu_opt_get_bool(opts, "sasl", false);