diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2016-08-04 10:24:27 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2016-08-04 10:24:27 +0100 |
commit | 09704e6ded83fa0bec14baf32f800f6512156ca0 (patch) | |
tree | 72647b9a6c3b35984749926c21a9d2c17e86b3ee | |
parent | 29b2517ac79ecd42c169248668e4007dee90dc5a (diff) | |
parent | e911765cbb9e9ddf5d952c88bb52180a62c6cea0 (diff) |
Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging
* xsetbv fix (x86 targets TCG)
* remove unused functions
* qht segfault and memory leak fixes
* NBD fixes
* Fix for non-power-of-2 discard granularity
* Memory hotplug fixes
* Migration regressions
* IOAPIC fixes and (disabled by default) EOI register support
* Various other small fixes
# gpg: Signature made Wed 03 Aug 2016 18:01:05 BST
# gpg: using RSA key 0xBFFBD25F78C7AE83
# gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>"
# gpg: aka "Paolo Bonzini <pbonzini@redhat.com>"
# Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1
# Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83
* remotes/bonzini/tags/for-upstream: (25 commits)
util: Fix assertion in iov_copy() upon zero 'bytes' and non-zero 'offset'
qdev: Fix use after free in qdev_init_nofail error path
Reorganize help output of '-display' option
x86: ioapic: add support for explicit EOI
x86: ioapic: ignore level irq during processing
apic: fix broken migration for kvm-apic
fw_cfg: Make base type "fw_cfg" abstract
block: Cater to iscsi with non-power-of-2 discard
osdep: Document differences in rounding macros
nbd: Limit nbdflags to 16 bits
nbd: Fix bad flag detection on server
i2c: fix migration regression introduced by broadcast support
mptsas: really fix migration compatibility
qdist: return "(empty)" instead of NULL when printing an empty dist
qdist: use g_renew and g_new instead of g_realloc and g_malloc.
qdist: fix memory leak during binning
target-i386: fix typo in xsetbv implementation
qht: do not segfault when gathering stats from an uninitialized qht
util: Drop inet_listen()
util: drop unix_nonblocking_connect()
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r-- | backends/hostmem.c | 18 | ||||
-rw-r--r-- | block/io.c | 15 | ||||
-rw-r--r-- | block/nbd-client.h | 2 | ||||
-rw-r--r-- | exec.c | 10 | ||||
-rw-r--r-- | hw/core/qdev.c | 2 | ||||
-rw-r--r-- | hw/i2c/core.c | 10 | ||||
-rw-r--r-- | hw/intc/ioapic.c | 36 | ||||
-rw-r--r-- | hw/nvram/fw_cfg.c | 1 | ||||
-rw-r--r-- | hw/scsi/mptsas.c | 4 | ||||
-rw-r--r-- | hw/scsi/mptsas.h | 2 | ||||
-rw-r--r-- | include/block/block_int.h | 37 | ||||
-rw-r--r-- | include/block/nbd.h | 6 | ||||
-rw-r--r-- | include/hw/i386/ioapic_internal.h | 4 | ||||
-rw-r--r-- | include/hw/i386/pc.h | 2 | ||||
-rw-r--r-- | include/qemu/osdep.h | 8 | ||||
-rw-r--r-- | include/qemu/qht.h | 5 | ||||
-rw-r--r-- | include/qemu/sockets.h | 8 | ||||
-rw-r--r-- | nbd/client.c | 28 | ||||
-rw-r--r-- | nbd/server.c | 13 | ||||
-rw-r--r-- | numa.c | 1 | ||||
-rw-r--r-- | qemu-nbd.c | 4 | ||||
-rw-r--r-- | qemu-options.hx | 29 | ||||
-rwxr-xr-x | scripts/checkpatch.pl | 5 | ||||
-rw-r--r-- | target-i386/translate.c | 2 | ||||
-rw-r--r-- | tests/test-qdist.c | 10 | ||||
-rw-r--r-- | tests/test-qht.c | 4 | ||||
-rw-r--r-- | translate-all.c | 70 | ||||
-rw-r--r-- | util/iov.c | 3 | ||||
-rw-r--r-- | util/oslib-posix.c | 26 | ||||
-rw-r--r-- | util/oslib-win32.c | 2 | ||||
-rw-r--r-- | util/qdist.c | 13 | ||||
-rw-r--r-- | util/qemu-sockets.c | 74 | ||||
-rw-r--r-- | util/qht.c | 14 |
33 files changed, 251 insertions, 217 deletions
diff --git a/backends/hostmem.c b/backends/hostmem.c index ac802570a8..b7a208d0da 100644 --- a/backends/hostmem.c +++ b/backends/hostmem.c @@ -203,6 +203,7 @@ static bool host_memory_backend_get_prealloc(Object *obj, Error **errp) static void host_memory_backend_set_prealloc(Object *obj, bool value, Error **errp) { + Error *local_err = NULL; HostMemoryBackend *backend = MEMORY_BACKEND(obj); if (backend->force_prealloc) { @@ -223,7 +224,11 @@ static void host_memory_backend_set_prealloc(Object *obj, bool value, void *ptr = memory_region_get_ram_ptr(&backend->mr); uint64_t sz = memory_region_size(&backend->mr); - os_mem_prealloc(fd, ptr, sz); + os_mem_prealloc(fd, ptr, sz, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } backend->prealloc = true; } } @@ -286,8 +291,7 @@ host_memory_backend_memory_complete(UserCreatable *uc, Error **errp) if (bc->alloc) { bc->alloc(backend, &local_err); if (local_err) { - error_propagate(errp, local_err); - return; + goto out; } ptr = memory_region_get_ram_ptr(&backend->mr); @@ -343,9 +347,15 @@ host_memory_backend_memory_complete(UserCreatable *uc, Error **errp) * specified NUMA policy in place. */ if (backend->prealloc) { - os_mem_prealloc(memory_region_get_fd(&backend->mr), ptr, sz); + os_mem_prealloc(memory_region_get_fd(&backend->mr), ptr, sz, + &local_err); + if (local_err) { + goto out; + } } } +out: + error_propagate(errp, local_err); } static bool diff --git a/block/io.c b/block/io.c index 7323f0fb7b..d5493ba349 100644 --- a/block/io.c +++ b/block/io.c @@ -1180,10 +1180,11 @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs, int alignment = MAX(bs->bl.pwrite_zeroes_alignment, bs->bl.request_alignment); - assert(is_power_of_2(alignment)); - head = offset & (alignment - 1); - tail = (offset + count) & (alignment - 1); - max_write_zeroes &= ~(alignment - 1); + assert(alignment % bs->bl.request_alignment == 0); + head = offset % alignment; + tail = (offset + count) % alignment; + max_write_zeroes = QEMU_ALIGN_DOWN(max_write_zeroes, alignment); + assert(max_write_zeroes >= bs->bl.request_alignment); while (count > 0 && !ret) { int num = count; @@ -2429,9 +2430,10 @@ int coroutine_fn bdrv_co_pdiscard(BlockDriverState *bs, int64_t offset, /* Discard is advisory, so ignore any unaligned head or tail */ align = MAX(bs->bl.pdiscard_alignment, bs->bl.request_alignment); - assert(is_power_of_2(align)); - head = MIN(count, -offset & (align - 1)); + assert(align % bs->bl.request_alignment == 0); + head = offset % align; if (head) { + head = MIN(count, align - head); count -= head; offset += head; } @@ -2449,6 +2451,7 @@ int coroutine_fn bdrv_co_pdiscard(BlockDriverState *bs, int64_t offset, max_pdiscard = QEMU_ALIGN_DOWN(MIN_NON_ZERO(bs->bl.max_pdiscard, INT_MAX), align); + assert(max_pdiscard); while (count > 0) { int ret; diff --git a/block/nbd-client.h b/block/nbd-client.h index fa9817b7d7..044aca4530 100644 --- a/block/nbd-client.h +++ b/block/nbd-client.h @@ -20,7 +20,7 @@ typedef struct NbdClientSession { QIOChannelSocket *sioc; /* The master data channel */ QIOChannel *ioc; /* The current I/O channel which may differ (eg TLS) */ - uint32_t nbdflags; + uint16_t nbdflags; off_t size; CoMutex send_mutex; @@ -1226,7 +1226,7 @@ static void *file_ram_alloc(RAMBlock *block, char *filename; char *sanitized_name; char *c; - void *area; + void *area = MAP_FAILED; int fd = -1; int64_t page_size; @@ -1314,13 +1314,19 @@ static void *file_ram_alloc(RAMBlock *block, } if (mem_prealloc) { - os_mem_prealloc(fd, area, memory); + os_mem_prealloc(fd, area, memory, errp); + if (errp && *errp) { + goto error; + } } block->fd = fd; return area; error: + if (area != MAP_FAILED) { + qemu_ram_munmap(area, memory); + } if (unlink_on_error) { unlink(path); } diff --git a/hw/core/qdev.c b/hw/core/qdev.c index ee4a083e64..57834423b9 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -354,12 +354,14 @@ void qdev_init_nofail(DeviceState *dev) assert(!dev->realized); + object_ref(OBJECT(dev)); object_property_set_bool(OBJECT(dev), true, "realized", &err); if (err) { error_reportf_err(err, "Initialization of device %s failed: ", object_get_typename(OBJECT(dev))); exit(1); } + object_unref(OBJECT(dev)); } void qdev_machine_creation_done(void) diff --git a/hw/i2c/core.c b/hw/i2c/core.c index abb3efb1db..4afbe0bde5 100644 --- a/hw/i2c/core.c +++ b/hw/i2c/core.c @@ -17,6 +17,8 @@ struct I2CNode { QLIST_ENTRY(I2CNode) next; }; +#define I2C_BROADCAST 0x00 + struct I2CBus { BusState qbus; @@ -47,6 +49,8 @@ static void i2c_bus_pre_save(void *opaque) if (!QLIST_EMPTY(&bus->current_devs)) { if (!bus->broadcast) { bus->saved_address = QLIST_FIRST(&bus->current_devs)->elt->address; + } else { + bus->saved_address = I2C_BROADCAST; } } } @@ -58,7 +62,6 @@ static const VMStateDescription vmstate_i2c_bus = { .pre_save = i2c_bus_pre_save, .fields = (VMStateField[]) { VMSTATE_UINT8(saved_address, I2CBus), - VMSTATE_BOOL(broadcast, I2CBus), VMSTATE_END_OF_LIST() } }; @@ -93,7 +96,7 @@ int i2c_start_transfer(I2CBus *bus, uint8_t address, int recv) I2CSlaveClass *sc; I2CNode *node; - if (address == 0x00) { + if (address == I2C_BROADCAST) { /* * This is a broadcast, the current_devs will be all the devices of the * bus. @@ -221,7 +224,8 @@ static int i2c_slave_post_load(void *opaque, int version_id) I2CNode *node; bus = I2C_BUS(qdev_get_parent_bus(DEVICE(dev))); - if ((bus->saved_address == dev->address) || (bus->broadcast)) { + if ((bus->saved_address == dev->address) || + (bus->saved_address == I2C_BROADCAST)) { node = g_malloc(sizeof(struct I2CNode)); node->elt = dev; QLIST_INSERT_HEAD(&bus->current_devs, node, next); diff --git a/hw/intc/ioapic.c b/hw/intc/ioapic.c index 2d3282a864..31791b0986 100644 --- a/hw/intc/ioapic.c +++ b/hw/intc/ioapic.c @@ -21,6 +21,7 @@ */ #include "qemu/osdep.h" +#include "qemu/error-report.h" #include "monitor/monitor.h" #include "hw/hw.h" #include "hw/i386/pc.h" @@ -117,21 +118,25 @@ static void ioapic_service(IOAPICCommonState *s) s->ioredtbl[i] |= IOAPIC_LVT_REMOTE_IRR; } + if (coalesce) { + /* We are level triggered interrupts, and the + * guest should be still working on previous one, + * so skip it. */ + continue; + } + #ifdef CONFIG_KVM if (kvm_irqchip_is_split()) { if (info.trig_mode == IOAPIC_TRIGGER_EDGE) { kvm_set_irq(kvm_state, i, 1); kvm_set_irq(kvm_state, i, 0); } else { - if (!coalesce) { - kvm_set_irq(kvm_state, i, 1); - } + kvm_set_irq(kvm_state, i, 1); } continue; } -#else - (void)coalesce; #endif + /* No matter whether IR is enabled, we translate * the IOAPIC message into a MSI one, and its * address space will decide whether we need a @@ -265,7 +270,7 @@ ioapic_mem_read(void *opaque, hwaddr addr, unsigned int size) val = s->id << IOAPIC_ID_SHIFT; break; case IOAPIC_REG_VER: - val = IOAPIC_VERSION | + val = s->version | ((IOAPIC_NUM_PINS - 1) << IOAPIC_VER_ENTRIES_SHIFT); break; default: @@ -354,6 +359,13 @@ ioapic_mem_write(void *opaque, hwaddr addr, uint64_t val, } } break; + case IOAPIC_EOI: + /* Explicit EOI is only supported for IOAPIC version 0x20 */ + if (size != 4 || s->version != 0x20) { + break; + } + ioapic_eoi_broadcast(val); + break; } ioapic_update_kvm_routes(s); @@ -387,6 +399,12 @@ static void ioapic_realize(DeviceState *dev, Error **errp) { IOAPICCommonState *s = IOAPIC_COMMON(dev); + if (s->version != 0x11 && s->version != 0x20) { + error_report("IOAPIC only supports version 0x11 or 0x20 " + "(default: 0x11)."); + exit(1); + } + memory_region_init_io(&s->io_memory, OBJECT(s), &ioapic_io_ops, s, "ioapic", 0x1000); @@ -397,6 +415,11 @@ static void ioapic_realize(DeviceState *dev, Error **errp) qemu_add_machine_init_done_notifier(&s->machine_done); } +static Property ioapic_properties[] = { + DEFINE_PROP_UINT8("version", IOAPICCommonState, version, 0x11), + DEFINE_PROP_END_OF_LIST(), +}; + static void ioapic_class_init(ObjectClass *klass, void *data) { IOAPICCommonClass *k = IOAPIC_COMMON_CLASS(klass); @@ -404,6 +427,7 @@ static void ioapic_class_init(ObjectClass *klass, void *data) k->realize = ioapic_realize; dc->reset = ioapic_reset_common; + dc->props = ioapic_properties; } static const TypeInfo ioapic_info = { diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c index 2873030ade..f10d5ec9c8 100644 --- a/hw/nvram/fw_cfg.c +++ b/hw/nvram/fw_cfg.c @@ -990,6 +990,7 @@ static void fw_cfg_class_init(ObjectClass *klass, void *data) static const TypeInfo fw_cfg_info = { .name = TYPE_FW_CFG, .parent = TYPE_SYS_BUS_DEVICE, + .abstract = true, .instance_size = sizeof(FWCfgState), .class_init = fw_cfg_class_init, }; diff --git a/hw/scsi/mptsas.c b/hw/scsi/mptsas.c index bebe5130fe..0e0a22f696 100644 --- a/hw/scsi/mptsas.c +++ b/hw/scsi/mptsas.c @@ -1295,6 +1295,8 @@ static void mptsas_scsi_init(PCIDevice *dev, Error **errp) /* With msi=auto, we fall back to MSI off silently */ error_free(err); + /* Only used for migration. */ + s->msi_in_use = (ret == 0); } memory_region_init_io(&s->mmio_io, OBJECT(s), &mptsas_mmio_ops, s, @@ -1370,7 +1372,7 @@ static const VMStateDescription vmstate_mptsas = { .post_load = mptsas_post_load, .fields = (VMStateField[]) { VMSTATE_PCI_DEVICE(dev, MPTSASState), - VMSTATE_UNUSED(sizeof(bool)), /* Was msi_in_use */ + VMSTATE_BOOL(msi_in_use, MPTSASState), VMSTATE_UINT32(state, MPTSASState), VMSTATE_UINT8(who_init, MPTSASState), VMSTATE_UINT8(doorbell_state, MPTSASState), diff --git a/hw/scsi/mptsas.h b/hw/scsi/mptsas.h index da014a397e..0436a33911 100644 --- a/hw/scsi/mptsas.h +++ b/hw/scsi/mptsas.h @@ -31,6 +31,8 @@ struct MPTSASState { OnOffAuto msi; uint64_t sas_addr; + bool msi_in_use; + /* Doorbell register */ uint32_t state; uint8_t who_init; diff --git a/include/block/block_int.h b/include/block/block_int.h index 1fe0fd9ff6..47665be81e 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -330,36 +330,39 @@ typedef struct BlockLimits { * otherwise. */ uint32_t request_alignment; - /* maximum number of bytes that can be discarded at once (since it - * is signed, it must be < 2G, if set), should be multiple of + /* Maximum number of bytes that can be discarded at once (since it + * is signed, it must be < 2G, if set). Must be multiple of * pdiscard_alignment, but need not be power of 2. May be 0 if no * inherent 32-bit limit */ int32_t max_pdiscard; - /* optimal alignment for discard requests in bytes, must be power - * of 2, less than max_pdiscard if that is set, and multiple of - * bl.request_alignment. May be 0 if bl.request_alignment is good - * enough */ + /* Optimal alignment for discard requests in bytes. A power of 2 + * is best but not mandatory. Must be a multiple of + * bl.request_alignment, and must be less than max_pdiscard if + * that is set. May be 0 if bl.request_alignment is good enough */ uint32_t pdiscard_alignment; - /* maximum number of bytes that can zeroized at once (since it is - * signed, it must be < 2G, if set), should be multiple of + /* Maximum number of bytes that can zeroized at once (since it is + * signed, it must be < 2G, if set). Must be multiple of * pwrite_zeroes_alignment. May be 0 if no inherent 32-bit limit */ int32_t max_pwrite_zeroes; - /* optimal alignment for write zeroes requests in bytes, must be - * power of 2, less than max_pwrite_zeroes if that is set, and - * multiple of bl.request_alignment. May be 0 if - * bl.request_alignment is good enough */ + /* Optimal alignment for write zeroes requests in bytes. A power + * of 2 is best but not mandatory. Must be a multiple of + * bl.request_alignment, and must be less than max_pwrite_zeroes + * if that is set. May be 0 if bl.request_alignment is good + * enough */ uint32_t pwrite_zeroes_alignment; - /* optimal transfer length in bytes (must be power of 2, and - * multiple of bl.request_alignment), or 0 if no preferred size */ + /* Optimal transfer length in bytes. A power of 2 is best but not + * mandatory. Must be a multiple of bl.request_alignment, or 0 if + * no preferred size */ uint32_t opt_transfer; - /* maximal transfer length in bytes (need not be power of 2, but - * should be multiple of opt_transfer), or 0 for no 32-bit limit. - * For now, anything larger than INT_MAX is clamped down. */ + /* Maximal transfer length in bytes. Need not be power of 2, but + * must be multiple of opt_transfer and bl.request_alignment, or 0 + * for no 32-bit limit. For now, anything larger than INT_MAX is + * clamped down. */ uint32_t max_transfer; /* memory alignment, in bytes so that no bounce buffer is needed */ diff --git a/include/block/nbd.h b/include/block/nbd.h index cb91820f38..1897557a9b 100644 --- a/include/block/nbd.h +++ b/include/block/nbd.h @@ -90,11 +90,11 @@ ssize_t nbd_wr_syncv(QIOChannel *ioc, size_t niov, size_t length, bool do_read); -int nbd_receive_negotiate(QIOChannel *ioc, const char *name, uint32_t *flags, +int nbd_receive_negotiate(QIOChannel *ioc, const char *name, uint16_t *flags, QCryptoTLSCreds *tlscreds, const char *hostname, QIOChannel **outioc, off_t *size, Error **errp); -int nbd_init(int fd, QIOChannelSocket *sioc, uint32_t flags, off_t size); +int nbd_init(int fd, QIOChannelSocket *sioc, uint16_t flags, off_t size); ssize_t nbd_send_request(QIOChannel *ioc, struct nbd_request *request); ssize_t nbd_receive_reply(QIOChannel *ioc, struct nbd_reply *reply); int nbd_client(int fd); @@ -104,7 +104,7 @@ typedef struct NBDExport NBDExport; typedef struct NBDClient NBDClient; NBDExport *nbd_export_new(BlockBackend *blk, off_t dev_offset, off_t size, - uint32_t nbdflags, void (*close)(NBDExport *), + uint16_t nbdflags, void (*close)(NBDExport *), Error **errp); void nbd_export_close(NBDExport *exp); void nbd_export_get(NBDExport *exp); diff --git a/include/hw/i386/ioapic_internal.h b/include/hw/i386/ioapic_internal.h index d89ea1b63b..a11d86de46 100644 --- a/include/hw/i386/ioapic_internal.h +++ b/include/hw/i386/ioapic_internal.h @@ -29,8 +29,6 @@ #define MAX_IOAPICS 1 -#define IOAPIC_VERSION 0x11 - #define IOAPIC_LVT_DEST_SHIFT 56 #define IOAPIC_LVT_DEST_IDX_SHIFT 48 #define IOAPIC_LVT_MASKED_SHIFT 16 @@ -71,6 +69,7 @@ #define IOAPIC_IOREGSEL 0x00 #define IOAPIC_IOWIN 0x10 +#define IOAPIC_EOI 0x40 #define IOAPIC_REG_ID 0x00 #define IOAPIC_REG_VER 0x01 @@ -109,6 +108,7 @@ struct IOAPICCommonState { uint32_t irr; uint64_t ioredtbl[IOAPIC_NUM_PINS]; Notifier machine_done; + uint8_t version; }; void ioapic_reset_common(DeviceState *dev); diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index c87c5c1eec..74c175c1e5 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -388,7 +388,7 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *); .value = "off",\ },\ {\ - .driver = "apic",\ + .driver = "apic-common",\ .property = "legacy-instance-id",\ .value = "on",\ }, diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h index fbb875959f..9e9fa61546 100644 --- a/include/qemu/osdep.h +++ b/include/qemu/osdep.h @@ -158,7 +158,8 @@ extern int daemon(int, int); /* Round number down to multiple */ #define QEMU_ALIGN_DOWN(n, m) ((n) / (m) * (m)) -/* Round number up to multiple */ +/* Round number up to multiple. Safe when m is not a power of 2 (see + * ROUND_UP for a faster version when a power of 2 is guaranteed) */ #define QEMU_ALIGN_UP(n, m) QEMU_ALIGN_DOWN((n) + (m) - 1, (m)) /* Check if n is a multiple of m */ @@ -175,6 +176,9 @@ extern int daemon(int, int); /* Check if pointer p is n-bytes aligned */ #define QEMU_PTR_IS_ALIGNED(p, n) QEMU_IS_ALIGNED((uintptr_t)(p), (n)) +/* Round number up to multiple. Requires that d be a power of 2 (see + * QEMU_ALIGN_UP for a safer but slower version on arbitrary + * numbers) */ #ifndef ROUND_UP #define ROUND_UP(n,d) (((n) + (d) - 1) & -(d)) #endif @@ -379,7 +383,7 @@ unsigned long qemu_getauxval(unsigned long type); void qemu_set_tty_echo(int fd, bool echo); -void os_mem_prealloc(int fd, char *area, size_t sz); +void os_mem_prealloc(int fd, char *area, size_t sz, Error **errp); int qemu_read_password(char *buf, int buf_size); diff --git a/include/qemu/qht.h b/include/qemu/qht.h index 70bfc68b8d..311139b85a 100644 --- a/include/qemu/qht.h +++ b/include/qemu/qht.h @@ -69,6 +69,9 @@ void qht_destroy(struct qht *ht); * Attempting to insert a NULL @p is a bug. * Inserting the same pointer @p with different @hash values is a bug. * + * In case of successful operation, smp_wmb() is implied before the pointer is + * inserted into the hash table. + * * Returns true on sucess. * Returns false if the @p-@hash pair already exists in the hash table. */ @@ -83,6 +86,8 @@ bool qht_insert(struct qht *ht, void *p, uint32_t hash); * * Needs to be called under an RCU read-critical section. * + * smp_read_barrier_depends() is implied before the call to @func. + * * The user-provided @func compares pointers in QHT against @userp. * If the function returns true, a match has been found. * diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h index 5fe01fbc6c..9eb24707df 100644 --- a/include/qemu/sockets.h +++ b/include/qemu/sockets.h @@ -33,20 +33,12 @@ int socket_set_fast_reuse(int fd); typedef void NonBlockingConnectHandler(int fd, Error *err, void *opaque); InetSocketAddress *inet_parse(const char *str, Error **errp); -int inet_listen(const char *str, char *ostr, int olen, - int socktype, int port_offset, Error **errp); int inet_connect(const char *str, Error **errp); -int inet_nonblocking_connect(const char *str, - NonBlockingConnectHandler *callback, - void *opaque, Error **errp); NetworkAddressFamily inet_netfamily(int family); int unix_listen(const char *path, char *ostr, int olen, Error **errp); int unix_connect(const char *path, Error **errp); -int unix_nonblocking_connect(const char *str, - NonBlockingConnectHandler *callback, - void *opaque, Error **errp); SocketAddress *socket_parse(const char *str, Error **errp); int socket_connect(SocketAddress *addr, Error **errp, diff --git a/nbd/client.c b/nbd/client.c index 78a7195c45..a92f1e2275 100644 --- a/nbd/client.c +++ b/nbd/client.c @@ -408,7 +408,7 @@ static QIOChannel *nbd_receive_starttls(QIOChannel *ioc, } -int nbd_receive_negotiate(QIOChannel *ioc, const char *name, uint32_t *flags, +int nbd_receive_negotiate(QIOChannel *ioc, const char *name, uint16_t *flags, QCryptoTLSCreds *tlscreds, const char *hostname, QIOChannel **outioc, off_t *size, Error **errp) @@ -468,7 +468,6 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char *name, uint32_t *flags, uint32_t opt; uint32_t namesize; uint16_t globalflags; - uint16_t exportflags; bool fixedNewStyle = false; if (read_sync(ioc, &globalflags, sizeof(globalflags)) != @@ -477,7 +476,6 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char *name, uint32_t *flags, goto fail; } globalflags = be16_to_cpu(globalflags); - *flags = globalflags << 16; TRACE("Global flags are %" PRIx32, globalflags); if (globalflags & NBD_FLAG_FIXED_NEWSTYLE) { fixedNewStyle = true; @@ -545,17 +543,15 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char *name, uint32_t *flags, goto fail; } *size = be64_to_cpu(s); - TRACE("Size is %" PRIu64, *size); - if (read_sync(ioc, &exportflags, sizeof(exportflags)) != - sizeof(exportflags)) { + if (read_sync(ioc, flags, sizeof(*flags)) != sizeof(*flags)) { error_setg(errp, "Failed to read export flags"); goto fail; } - exportflags = be16_to_cpu(exportflags); - *flags |= exportflags; - TRACE("Export flags are %" PRIx16, exportflags); + be16_to_cpus(flags); } else if (magic == NBD_CLIENT_MAGIC) { + uint32_t oldflags; + if (name) { error_setg(errp, "Server does not support export names"); goto fail; @@ -572,16 +568,22 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char *name, uint32_t *flags, *size = be64_to_cpu(s); TRACE("Size is %" PRIu64, *size); - if (read_sync(ioc, flags, sizeof(*flags)) != sizeof(*flags)) { + if (read_sync(ioc, &oldflags, sizeof(oldflags)) != sizeof(oldflags)) { error_setg(errp, "Failed to read export flags"); goto fail; } - *flags = be32_to_cpu(*flags); + be32_to_cpus(&oldflags); + if (oldflags & ~0xffff) { + error_setg(errp, "Unexpected export flags %0x" PRIx32, oldflags); + goto fail; + } + *flags = oldflags; } else { error_setg(errp, "Bad magic received"); goto fail; } + TRACE("Size is %" PRIu64 ", export flags %" PRIx16, *size, *flags); if (read_sync(ioc, &buf, 124) != 124) { error_setg(errp, "Failed to read reserved block"); goto fail; @@ -593,7 +595,7 @@ fail: } #ifdef __linux__ -int nbd_init(int fd, QIOChannelSocket *sioc, uint32_t flags, off_t size) +int nbd_init(int fd, QIOChannelSocket *sioc, uint16_t flags, off_t size) { unsigned long sectors = size / BDRV_SECTOR_SIZE; if (size / BDRV_SECTOR_SIZE != sectors) { @@ -689,7 +691,7 @@ int nbd_disconnect(int fd) } #else -int nbd_init(int fd, QIOChannelSocket *ioc, uint32_t flags, off_t size) +int nbd_init(int fd, QIOChannelSocket *ioc, uint16_t flags, off_t size) { return -ENOTSUP; } diff --git a/nbd/server.c b/nbd/server.c index 29e2099b5e..80fbb4da1d 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -63,7 +63,7 @@ struct NBDExport { char *name; off_t dev_offset; off_t size; - uint32_t nbdflags; + uint16_t nbdflags; QTAILQ_HEAD(, NBDClient) clients; QTAILQ_ENTRY(NBDExport) next; @@ -544,8 +544,8 @@ static coroutine_fn int nbd_negotiate(NBDClientNewData *data) NBDClient *client = data->client; char buf[8 + 8 + 8 + 128]; int rc; - const int myflags = (NBD_FLAG_HAS_FLAGS | NBD_FLAG_SEND_TRIM | - NBD_FLAG_SEND_FLUSH | NBD_FLAG_SEND_FUA); + const uint16_t myflags = (NBD_FLAG_HAS_FLAGS | NBD_FLAG_SEND_TRIM | + NBD_FLAG_SEND_FLUSH | NBD_FLAG_SEND_FUA); bool oldStyle; /* Old style negotiation header without options @@ -575,7 +575,6 @@ static coroutine_fn int nbd_negotiate(NBDClientNewData *data) oldStyle = client->exp != NULL && !client->tlscreds; if (oldStyle) { - assert ((client->exp->nbdflags & ~65535) == 0); TRACE("advertising size %" PRIu64 " and flags %x", client->exp->size, client->exp->nbdflags | myflags); stq_be_p(buf + 8, NBD_CLIENT_MAGIC); @@ -606,7 +605,6 @@ static coroutine_fn int nbd_negotiate(NBDClientNewData *data) goto fail; } - assert ((client->exp->nbdflags & ~65535) == 0); TRACE("advertising size %" PRIu64 " and flags %x", client->exp->size, client->exp->nbdflags | myflags); stq_be_p(buf + 18, client->exp->size); @@ -810,7 +808,7 @@ static void nbd_eject_notifier(Notifier *n, void *data) } NBDExport *nbd_export_new(BlockBackend *blk, off_t dev_offset, off_t size, - uint32_t nbdflags, void (*close)(NBDExport *), + uint16_t nbdflags, void (*close)(NBDExport *), Error **errp) { NBDExport *exp = g_malloc0(sizeof(NBDExport)); @@ -1057,7 +1055,8 @@ static ssize_t nbd_co_receive_request(NBDRequest *req, if (request->type & ~NBD_CMD_MASK_COMMAND & ~NBD_CMD_FLAG_FUA) { LOG("unsupported flags (got 0x%x)", request->type & ~NBD_CMD_MASK_COMMAND); - return -EINVAL; + rc = -EINVAL; + goto out; } rc = 0; @@ -463,6 +463,7 @@ void memory_region_allocate_system_memory(MemoryRegion *mr, Object *owner, exit(1); } + host_memory_backend_set_mapped(backend, true); memory_region_add_subregion(mr, addr, seg); vmstate_register_ram_global(seg); addr += size; diff --git a/qemu-nbd.c b/qemu-nbd.c index 321f02bd15..e3571c2025 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -251,7 +251,7 @@ static void *nbd_client_thread(void *arg) { char *device = arg; off_t size; - uint32_t nbdflags; + uint16_t nbdflags; QIOChannelSocket *sioc; int fd; int ret; @@ -465,7 +465,7 @@ int main(int argc, char **argv) BlockBackend *blk; BlockDriverState *bs; off_t dev_offset = 0; - uint32_t nbdflags = 0; + uint16_t nbdflags = 0; bool disconnect = false; const char *bindto = "0.0.0.0"; const char *port = NULL; diff --git a/qemu-options.hx b/qemu-options.hx index 8e0d9a51bf..a71aaf8ea8 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -927,10 +927,25 @@ ETEXI DEF("display", HAS_ARG, QEMU_OPTION_display, "-display sdl[,frame=on|off][,alt_grab=on|off][,ctrl_grab=on|off]\n" - " [,window_close=on|off]|curses|none|\n" - " gtk[,grab_on_hover=on|off]|\n" - " vnc=<display>[,<optargs>]\n" - " select display type\n", QEMU_ARCH_ALL) + " [,window_close=on|off][,gl=on|off]|curses|none|\n" + "-display gtk[,grab_on_hover=on|off][,gl=on|off]|\n" + "-display vnc=<display>[,<optargs>]\n" + "-display curses\n" + "-display none" + " select display type\n" + "The default display is equivalent to\n" +#if defined(CONFIG_GTK) + "\t\"-display gtk\"\n" +#elif defined(CONFIG_SDL) + "\t\"-display sdl\"\n" +#elif defined(CONFIG_COCOA) + "\t\"-display cocoa\"\n" +#elif defined(CONFIG_VNC) + "\t\"-vnc localhost:0,to=99,id=default\"\n" +#else + "\t\"-display none\"\n" +#endif + , QEMU_ARCH_ALL) STEXI @item -display @var{type} @findex -display @@ -977,7 +992,7 @@ the console and monitor. ETEXI DEF("curses", 0, QEMU_OPTION_curses, - "-curses use a curses/ncurses interface instead of SDL\n", + "-curses shorthand for -display curses\n", QEMU_ARCH_ALL) STEXI @item -curses @@ -1027,7 +1042,7 @@ Disable SDL window close capability. ETEXI DEF("sdl", 0, QEMU_OPTION_sdl, - "-sdl enable SDL\n", QEMU_ARCH_ALL) + "-sdl shorthand for -display sdl\n", QEMU_ARCH_ALL) STEXI @item -sdl @findex -sdl @@ -1224,7 +1239,7 @@ Set the initial graphical resolution and depth (PPC, SPARC only). ETEXI DEF("vnc", HAS_ARG, QEMU_OPTION_vnc , - "-vnc display start a VNC server on display\n", QEMU_ARCH_ALL) + "-vnc <display> shorthand for -display vnc=<display>\n", QEMU_ARCH_ALL) STEXI @item -vnc @var{display}[,@var{option}[,@var{option}[,...]]] @findex -vnc diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index afa7f79f83..b7cb4ab478 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -2544,7 +2544,7 @@ sub process { } } -# check for non-portable ffs() calls that have portable alternatives in QEMU +# check for non-portable libc calls that have portable alternatives in QEMU if ($line =~ /\bffs\(/) { ERROR("use ctz32() instead of ffs()\n" . $herecurr); } @@ -2554,6 +2554,9 @@ sub process { if ($line =~ /\bffsll\(/) { ERROR("use ctz64() instead of ffsll()\n" . $herecurr); } + if ($line =~ /\bbzero\(/) { + ERROR("use memset() instead of bzero()\n" . $herecurr); + } } # If we have no input at all, then there is nothing to report on diff --git a/target-i386/translate.c b/target-i386/translate.c index e81fce7bc2..fa2ac48173 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -7176,7 +7176,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[R_ECX]); gen_helper_xsetbv(cpu_env, cpu_tmp2_i32, cpu_tmp1_i64); /* End TB because translation flags may change. */ - gen_jmp_im(s->pc - pc_start); + gen_jmp_im(s->pc - s->cs_base); gen_eob(s); break; diff --git a/tests/test-qdist.c b/tests/test-qdist.c index 0298986ac9..9541ce31eb 100644 --- a/tests/test-qdist.c +++ b/tests/test-qdist.c @@ -360,10 +360,16 @@ static void test_none(void) g_assert(isnan(qdist_xmax(&dist))); pr = qdist_pr_plain(&dist, 0); - g_assert(pr == NULL); + g_assert_cmpstr(pr, ==, "(empty)"); + g_free(pr); pr = qdist_pr_plain(&dist, 2); - g_assert(pr == NULL); + g_assert_cmpstr(pr, ==, "(empty)"); + g_free(pr); + + pr = qdist_pr(&dist, 0, QDIST_PR_BORDER); + g_assert_cmpstr(pr, ==, "(empty)"); + g_free(pr); qdist_destroy(&dist); } diff --git a/tests/test-qht.c b/tests/test-qht.c index f1d628371d..46a64b6731 100644 --- a/tests/test-qht.c +++ b/tests/test-qht.c @@ -95,8 +95,12 @@ static void iter_check(unsigned int count) static void qht_do_test(unsigned int mode, size_t init_entries) { + /* under KVM we might fetch stats from an uninitialized qht */ + check_n(0); + qht_init(&ht, 0, mode); + check_n(0); insert(0, N); check(0, N, true); check_n(N); diff --git a/translate-all.c b/translate-all.c index 0d47c1c0cf..efeba298b9 100644 --- a/translate-all.c +++ b/translate-all.c @@ -1663,15 +1663,50 @@ void tb_flush_jmp_cache(CPUState *cpu, target_ulong addr) TB_JMP_PAGE_SIZE * sizeof(TranslationBlock *)); } +static void print_qht_statistics(FILE *f, fprintf_function cpu_fprintf, + struct qht_stats hst) +{ + uint32_t hgram_opts; + size_t hgram_bins; + char *hgram; + + if (!hst.head_buckets) { + return; + } + cpu_fprintf(f, "TB hash buckets %zu/%zu (%0.2f%% head buckets used)\n", + hst.used_head_buckets, hst.head_buckets, + (double)hst.used_head_buckets / hst.head_buckets * 100); + + hgram_opts = QDIST_PR_BORDER | QDIST_PR_LABELS; + hgram_opts |= QDIST_PR_100X | QDIST_PR_PERCENT; + if (qdist_xmax(&hst.occupancy) - qdist_xmin(&hst.occupancy) == 1) { + hgram_opts |= QDIST_PR_NODECIMAL; + } + hgram = qdist_pr(&hst.occupancy, 10, hgram_opts); + cpu_fprintf(f, "TB hash occupancy %0.2f%% avg chain occ. Histogram: %s\n", + qdist_avg(&hst.occupancy) * 100, hgram); + g_free(hgram); + + hgram_opts = QDIST_PR_BORDER | QDIST_PR_LABELS; + hgram_bins = qdist_xmax(&hst.chain) - qdist_xmin(&hst.chain); + if (hgram_bins > 10) { + hgram_bins = 10; + } else { + hgram_bins = 0; + hgram_opts |= QDIST_PR_NODECIMAL | QDIST_PR_NOBINRANGE; + } + hgram = qdist_pr(&hst.chain, hgram_bins, hgram_opts); + cpu_fprintf(f, "TB hash avg chain %0.3f buckets. Histogram: %s\n", + qdist_avg(&hst.chain), hgram); + g_free(hgram); +} + void dump_exec_info(FILE *f, fprintf_function cpu_fprintf) { int i, target_code_size, max_target_code_size; int direct_jmp_count, direct_jmp2_count, cross_page; TranslationBlock *tb; struct qht_stats hst; - uint32_t hgram_opts; - size_t hgram_bins; - char *hgram; target_code_size = 0; max_target_code_size = 0; @@ -1724,34 +1759,7 @@ void dump_exec_info(FILE *f, fprintf_function cpu_fprintf) tcg_ctx.tb_ctx.nb_tbs : 0); qht_statistics_init(&tcg_ctx.tb_ctx.htable, &hst); - - cpu_fprintf(f, "TB hash buckets %zu/%zu (%0.2f%% head buckets used)\n", - hst.used_head_buckets, hst.head_buckets, - (double)hst.used_head_buckets / hst.head_buckets * 100); - - hgram_opts = QDIST_PR_BORDER | QDIST_PR_LABELS; - hgram_opts |= QDIST_PR_100X | QDIST_PR_PERCENT; - if (qdist_xmax(&hst.occupancy) - qdist_xmin(&hst.occupancy) == 1) { - hgram_opts |= QDIST_PR_NODECIMAL; - } - hgram = qdist_pr(&hst.occupancy, 10, hgram_opts); - cpu_fprintf(f, "TB hash occupancy %0.2f%% avg chain occ. Histogram: %s\n", - qdist_avg(&hst.occupancy) * 100, hgram); - g_free(hgram); - - hgram_opts = QDIST_PR_BORDER | QDIST_PR_LABELS; - hgram_bins = qdist_xmax(&hst.chain) - qdist_xmin(&hst.chain); - if (hgram_bins > 10) { - hgram_bins = 10; - } else { - hgram_bins = 0; - hgram_opts |= QDIST_PR_NODECIMAL | QDIST_PR_NOBINRANGE; - } - hgram = qdist_pr(&hst.chain, hgram_bins, hgram_opts); - cpu_fprintf(f, "TB hash avg chain %0.3f buckets. Histogram: %s\n", - qdist_avg(&hst.chain), hgram); - g_free(hgram); - + print_qht_statistics(f, cpu_fprintf, hst); qht_statistics_destroy(&hst); cpu_fprintf(f, "\nStatistics:\n"); diff --git a/util/iov.c b/util/iov.c index 003fcce66f..74e6ca8ed7 100644 --- a/util/iov.c +++ b/util/iov.c @@ -247,7 +247,8 @@ unsigned iov_copy(struct iovec *dst_iov, unsigned int dst_iov_cnt, { size_t len; unsigned int i, j; - for (i = 0, j = 0; i < iov_cnt && j < dst_iov_cnt && bytes; i++) { + for (i = 0, j = 0; + i < iov_cnt && j < dst_iov_cnt && (offset || bytes); i++) { if (offset >= iov[i].iov_len) { offset -= iov[i].iov_len; continue; diff --git a/util/oslib-posix.c b/util/oslib-posix.c index 6d70d9a706..f2d4e9e592 100644 --- a/util/oslib-posix.c +++ b/util/oslib-posix.c @@ -318,7 +318,7 @@ static void sigbus_handler(int signal) siglongjmp(sigjump, 1); } -void os_mem_prealloc(int fd, char *area, size_t memory) +void os_mem_prealloc(int fd, char *area, size_t memory, Error **errp) { int ret; struct sigaction act, oldact; @@ -330,8 +330,9 @@ void os_mem_prealloc(int fd, char *area, size_t memory) ret = sigaction(SIGBUS, &act, &oldact); if (ret) { - perror("os_mem_prealloc: failed to install signal handler"); - exit(1); + error_setg_errno(errp, errno, + "os_mem_prealloc: failed to install signal handler"); + return; } /* unblock SIGBUS */ @@ -340,9 +341,8 @@ void os_mem_prealloc(int fd, char *area, size_t memory) pthread_sigmask(SIG_UNBLOCK, &set, &oldset); if (sigsetjmp(sigjump, 1)) { - fprintf(stderr, "os_mem_prealloc: Insufficient free host memory " - "pages available to allocate guest RAM\n"); - exit(1); + error_setg(errp, "os_mem_prealloc: Insufficient free host memory " + "pages available to allocate guest RAM\n"); } else { int i; size_t hpagesize = qemu_fd_getpagesize(fd); @@ -352,15 +352,15 @@ void os_mem_prealloc(int fd, char *area, size_t memory) for (i = 0; i < numpages; i++) { memset(area + (hpagesize * i), 0, 1); } + } - ret = sigaction(SIGBUS, &oldact, NULL); - if (ret) { - perror("os_mem_prealloc: failed to reinstall signal handler"); - exit(1); - } - - pthread_sigmask(SIG_SETMASK, &oldset, NULL); + ret = sigaction(SIGBUS, &oldact, NULL); + if (ret) { + /* Terminate QEMU since it can't recover from error */ + perror("os_mem_prealloc: failed to reinstall signal handler"); + exit(1); } + pthread_sigmask(SIG_SETMASK, &oldset, NULL); } diff --git a/util/oslib-win32.c b/util/oslib-win32.c index 6debc2b8a6..4c1dcf1e66 100644 --- a/util/oslib-win32.c +++ b/util/oslib-win32.c @@ -539,7 +539,7 @@ int getpagesize(void) return system_info.dwPageSize; } -void os_mem_prealloc(int fd, char *area, size_t memory) +void os_mem_prealloc(int fd, char *area, size_t memory, Error **errp) { int i; size_t pagesize = getpagesize(); diff --git a/util/qdist.c b/util/qdist.c index 56f573837d..5f75e24c29 100644 --- a/util/qdist.c +++ b/util/qdist.c @@ -14,9 +14,11 @@ #define NAN (0.0 / 0.0) #endif +#define QDIST_EMPTY_STR "(empty)" + void qdist_init(struct qdist *dist) { - dist->entries = g_malloc(sizeof(*dist->entries)); + dist->entries = g_new(struct qdist_entry, 1); dist->size = 1; dist->n = 0; } @@ -62,8 +64,7 @@ void qdist_add(struct qdist *dist, double x, long count) if (unlikely(dist->n == dist->size)) { dist->size *= 2; - dist->entries = g_realloc(dist->entries, - sizeof(*dist->entries) * (dist->size)); + dist->entries = g_renew(struct qdist_entry, dist->entries, dist->size); } dist->n++; entry = &dist->entries[dist->n - 1]; @@ -188,7 +189,7 @@ void qdist_bin__internal(struct qdist *to, const struct qdist *from, size_t n) } } /* they're equally spaced, so copy the dist and bail out */ - to->entries = g_new(struct qdist_entry, from->n); + to->entries = g_renew(struct qdist_entry, to->entries, n); to->n = from->n; memcpy(to->entries, from->entries, sizeof(*to->entries) * to->n); return; @@ -234,7 +235,7 @@ char *qdist_pr_plain(const struct qdist *dist, size_t n) char *ret; if (dist->n == 0) { - return NULL; + return g_strdup(QDIST_EMPTY_STR); } qdist_bin__internal(&binned, dist, n); ret = qdist_pr_internal(&binned); @@ -309,7 +310,7 @@ char *qdist_pr(const struct qdist *dist, size_t n_bins, uint32_t opt) GString *s; if (dist->n == 0) { - return NULL; + return g_strdup(QDIST_EMPTY_STR); } s = g_string_new(""); diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c index 777af49d53..2aed799e97 100644 --- a/util/qemu-sockets.c +++ b/util/qemu-sockets.c @@ -624,34 +624,6 @@ fail: return NULL; } -int inet_listen(const char *str, char *ostr, int olen, - int socktype, int port_offset, Error **errp) -{ - char *optstr; - int sock = -1; - InetSocketAddress *addr; - - addr = inet_parse(str, errp); - if (addr != NULL) { - sock = inet_listen_saddr(addr, port_offset, true, errp); - if (sock != -1 && ostr) { - optstr = strchr(str, ','); - if (addr->ipv6) { - snprintf(ostr, olen, "[%s]:%s%s", - addr->host, - addr->port, - optstr ? optstr : ""); - } else { - snprintf(ostr, olen, "%s:%s%s", - addr->host, - addr->port, - optstr ? optstr : ""); - } - } - qapi_free_InetSocketAddress(addr); - } - return sock; -} /** * Create a blocking socket and connect it to an address. @@ -674,36 +646,6 @@ int inet_connect(const char *str, Error **errp) return sock; } -/** - * Create a non-blocking socket and connect it to an address. - * Calls the callback function with fd in case of success or -1 in case of - * error. - * - * @str: address string - * @callback: callback function that is called when connect completes, - * cannot be NULL. - * @opaque: opaque for callback function - * @errp: set in case of an error - * - * Returns: -1 on immediate error, file descriptor on success. - **/ -int inet_nonblocking_connect(const char *str, - NonBlockingConnectHandler *callback, - void *opaque, Error **errp) -{ - int sock = -1; - InetSocketAddress *addr; - - g_assert(callback != NULL); - - addr = inet_parse(str, errp); - if (addr != NULL) { - sock = inet_connect_saddr(addr, errp, callback, opaque); - qapi_free_InetSocketAddress(addr); - } - return sock; -} - #ifndef _WIN32 static int unix_listen_saddr(UnixSocketAddress *saddr, @@ -893,22 +835,6 @@ int unix_connect(const char *path, Error **errp) } -int unix_nonblocking_connect(const char *path, - NonBlockingConnectHandler *callback, - void *opaque, Error **errp) -{ - UnixSocketAddress *saddr; - int sock = -1; - - g_assert(callback != NULL); - - saddr = g_new0(UnixSocketAddress, 1); - saddr->path = g_strdup(path); - sock = unix_connect_saddr(saddr, errp, callback, opaque); - qapi_free_UnixSocketAddress(saddr); - return sock; -} - SocketAddress *socket_parse(const char *str, Error **errp) { SocketAddress *addr; diff --git a/util/qht.c b/util/qht.c index 40d6e218f7..16a8d7950e 100644 --- a/util/qht.c +++ b/util/qht.c @@ -445,7 +445,11 @@ void *qht_do_lookup(struct qht_bucket *head, qht_lookup_func_t func, do { for (i = 0; i < QHT_BUCKET_ENTRIES; i++) { if (b->hashes[i] == hash) { - void *p = atomic_read(&b->pointers[i]); + /* The pointer is dereferenced before seqlock_read_retry, + * so (unlike qht_insert__locked) we need to use + * atomic_rcu_read here. + */ + void *p = atomic_rcu_read(&b->pointers[i]); if (likely(p) && likely(func(p, userp))) { return p; @@ -535,6 +539,7 @@ static bool qht_insert__locked(struct qht *ht, struct qht_map *map, atomic_rcu_set(&prev->next, b); } b->hashes[i] = hash; + /* smp_wmb() implicit in seqlock_write_begin. */ atomic_set(&b->pointers[i], p); seqlock_write_end(&head->sequence); return true; @@ -784,11 +789,16 @@ void qht_statistics_init(struct qht *ht, struct qht_stats *stats) map = atomic_rcu_read(&ht->map); - stats->head_buckets = map->n_buckets; stats->used_head_buckets = 0; stats->entries = 0; qdist_init(&stats->chain); qdist_init(&stats->occupancy); + /* bail out if the qht has not yet been initialized */ + if (unlikely(map == NULL)) { + stats->head_buckets = 0; + return; + } + stats->head_buckets = map->n_buckets; for (i = 0; i < map->n_buckets; i++) { struct qht_bucket *head = &map->buckets[i]; |