mirror of https://github.com/xqemu/xqemu.git
* 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 -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQExBAABCAAbBQJXoiNRFBxwYm9uemluaUByZWRoYXQuY29tAAoJEL/70l94x66D ZwMH/1HmEYIAyyd9T8z2sNjdN7vKCNsphS7OXALDnwTp+VX4icUbf41NC6Eeg/e+ 6OKA90KSBTquG3wxsXrUK5Nwy7EKMoCXVQrdYw5T04OidQLtJosKgPx4MrvPSx8h caFUXo9WynT/aGRNc14gnZZiooQxsy/JoNhuml/WL0nupEmoUb/Ns3Yo++HRHntR rFmJvvD9SrQsWzd9+aJ8zm+Qi09gXsbj1grr6LHCLVmwDWAJooFev6MqBvplkL50 OLqCJfAXJ2srUoEboVdg3V+sFtB8Eru+iMdpZyLwo07V4BBK7heEsXx6JJkTObMC 90MSnMo6BauUO/R/bMvvLlNWykU= =XqbI -----END PGP SIGNATURE----- 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>
This commit is contained in:
commit
09704e6ded
|
@ -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,
|
static void host_memory_backend_set_prealloc(Object *obj, bool value,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
|
Error *local_err = NULL;
|
||||||
HostMemoryBackend *backend = MEMORY_BACKEND(obj);
|
HostMemoryBackend *backend = MEMORY_BACKEND(obj);
|
||||||
|
|
||||||
if (backend->force_prealloc) {
|
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);
|
void *ptr = memory_region_get_ram_ptr(&backend->mr);
|
||||||
uint64_t sz = memory_region_size(&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;
|
backend->prealloc = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -286,8 +291,7 @@ host_memory_backend_memory_complete(UserCreatable *uc, Error **errp)
|
||||||
if (bc->alloc) {
|
if (bc->alloc) {
|
||||||
bc->alloc(backend, &local_err);
|
bc->alloc(backend, &local_err);
|
||||||
if (local_err) {
|
if (local_err) {
|
||||||
error_propagate(errp, local_err);
|
goto out;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr = memory_region_get_ram_ptr(&backend->mr);
|
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.
|
* specified NUMA policy in place.
|
||||||
*/
|
*/
|
||||||
if (backend->prealloc) {
|
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
|
static bool
|
||||||
|
|
15
block/io.c
15
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,
|
int alignment = MAX(bs->bl.pwrite_zeroes_alignment,
|
||||||
bs->bl.request_alignment);
|
bs->bl.request_alignment);
|
||||||
|
|
||||||
assert(is_power_of_2(alignment));
|
assert(alignment % bs->bl.request_alignment == 0);
|
||||||
head = offset & (alignment - 1);
|
head = offset % alignment;
|
||||||
tail = (offset + count) & (alignment - 1);
|
tail = (offset + count) % alignment;
|
||||||
max_write_zeroes &= ~(alignment - 1);
|
max_write_zeroes = QEMU_ALIGN_DOWN(max_write_zeroes, alignment);
|
||||||
|
assert(max_write_zeroes >= bs->bl.request_alignment);
|
||||||
|
|
||||||
while (count > 0 && !ret) {
|
while (count > 0 && !ret) {
|
||||||
int num = count;
|
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 */
|
/* Discard is advisory, so ignore any unaligned head or tail */
|
||||||
align = MAX(bs->bl.pdiscard_alignment, bs->bl.request_alignment);
|
align = MAX(bs->bl.pdiscard_alignment, bs->bl.request_alignment);
|
||||||
assert(is_power_of_2(align));
|
assert(align % bs->bl.request_alignment == 0);
|
||||||
head = MIN(count, -offset & (align - 1));
|
head = offset % align;
|
||||||
if (head) {
|
if (head) {
|
||||||
|
head = MIN(count, align - head);
|
||||||
count -= head;
|
count -= head;
|
||||||
offset += 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),
|
max_pdiscard = QEMU_ALIGN_DOWN(MIN_NON_ZERO(bs->bl.max_pdiscard, INT_MAX),
|
||||||
align);
|
align);
|
||||||
|
assert(max_pdiscard);
|
||||||
|
|
||||||
while (count > 0) {
|
while (count > 0) {
|
||||||
int ret;
|
int ret;
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
typedef struct NbdClientSession {
|
typedef struct NbdClientSession {
|
||||||
QIOChannelSocket *sioc; /* The master data channel */
|
QIOChannelSocket *sioc; /* The master data channel */
|
||||||
QIOChannel *ioc; /* The current I/O channel which may differ (eg TLS) */
|
QIOChannel *ioc; /* The current I/O channel which may differ (eg TLS) */
|
||||||
uint32_t nbdflags;
|
uint16_t nbdflags;
|
||||||
off_t size;
|
off_t size;
|
||||||
|
|
||||||
CoMutex send_mutex;
|
CoMutex send_mutex;
|
||||||
|
|
10
exec.c
10
exec.c
|
@ -1226,7 +1226,7 @@ static void *file_ram_alloc(RAMBlock *block,
|
||||||
char *filename;
|
char *filename;
|
||||||
char *sanitized_name;
|
char *sanitized_name;
|
||||||
char *c;
|
char *c;
|
||||||
void *area;
|
void *area = MAP_FAILED;
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
int64_t page_size;
|
int64_t page_size;
|
||||||
|
|
||||||
|
@ -1314,13 +1314,19 @@ static void *file_ram_alloc(RAMBlock *block,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mem_prealloc) {
|
if (mem_prealloc) {
|
||||||
os_mem_prealloc(fd, area, memory);
|
os_mem_prealloc(fd, area, memory, errp);
|
||||||
|
if (errp && *errp) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
block->fd = fd;
|
block->fd = fd;
|
||||||
return area;
|
return area;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
if (area != MAP_FAILED) {
|
||||||
|
qemu_ram_munmap(area, memory);
|
||||||
|
}
|
||||||
if (unlink_on_error) {
|
if (unlink_on_error) {
|
||||||
unlink(path);
|
unlink(path);
|
||||||
}
|
}
|
||||||
|
|
|
@ -354,12 +354,14 @@ void qdev_init_nofail(DeviceState *dev)
|
||||||
|
|
||||||
assert(!dev->realized);
|
assert(!dev->realized);
|
||||||
|
|
||||||
|
object_ref(OBJECT(dev));
|
||||||
object_property_set_bool(OBJECT(dev), true, "realized", &err);
|
object_property_set_bool(OBJECT(dev), true, "realized", &err);
|
||||||
if (err) {
|
if (err) {
|
||||||
error_reportf_err(err, "Initialization of device %s failed: ",
|
error_reportf_err(err, "Initialization of device %s failed: ",
|
||||||
object_get_typename(OBJECT(dev)));
|
object_get_typename(OBJECT(dev)));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
object_unref(OBJECT(dev));
|
||||||
}
|
}
|
||||||
|
|
||||||
void qdev_machine_creation_done(void)
|
void qdev_machine_creation_done(void)
|
||||||
|
|
|
@ -17,6 +17,8 @@ struct I2CNode {
|
||||||
QLIST_ENTRY(I2CNode) next;
|
QLIST_ENTRY(I2CNode) next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define I2C_BROADCAST 0x00
|
||||||
|
|
||||||
struct I2CBus
|
struct I2CBus
|
||||||
{
|
{
|
||||||
BusState qbus;
|
BusState qbus;
|
||||||
|
@ -47,6 +49,8 @@ static void i2c_bus_pre_save(void *opaque)
|
||||||
if (!QLIST_EMPTY(&bus->current_devs)) {
|
if (!QLIST_EMPTY(&bus->current_devs)) {
|
||||||
if (!bus->broadcast) {
|
if (!bus->broadcast) {
|
||||||
bus->saved_address = QLIST_FIRST(&bus->current_devs)->elt->address;
|
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,
|
.pre_save = i2c_bus_pre_save,
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT8(saved_address, I2CBus),
|
VMSTATE_UINT8(saved_address, I2CBus),
|
||||||
VMSTATE_BOOL(broadcast, I2CBus),
|
|
||||||
VMSTATE_END_OF_LIST()
|
VMSTATE_END_OF_LIST()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -93,7 +96,7 @@ int i2c_start_transfer(I2CBus *bus, uint8_t address, int recv)
|
||||||
I2CSlaveClass *sc;
|
I2CSlaveClass *sc;
|
||||||
I2CNode *node;
|
I2CNode *node;
|
||||||
|
|
||||||
if (address == 0x00) {
|
if (address == I2C_BROADCAST) {
|
||||||
/*
|
/*
|
||||||
* This is a broadcast, the current_devs will be all the devices of the
|
* This is a broadcast, the current_devs will be all the devices of the
|
||||||
* bus.
|
* bus.
|
||||||
|
@ -221,7 +224,8 @@ static int i2c_slave_post_load(void *opaque, int version_id)
|
||||||
I2CNode *node;
|
I2CNode *node;
|
||||||
|
|
||||||
bus = I2C_BUS(qdev_get_parent_bus(DEVICE(dev)));
|
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 = g_malloc(sizeof(struct I2CNode));
|
||||||
node->elt = dev;
|
node->elt = dev;
|
||||||
QLIST_INSERT_HEAD(&bus->current_devs, node, next);
|
QLIST_INSERT_HEAD(&bus->current_devs, node, next);
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
|
#include "qemu/error-report.h"
|
||||||
#include "monitor/monitor.h"
|
#include "monitor/monitor.h"
|
||||||
#include "hw/hw.h"
|
#include "hw/hw.h"
|
||||||
#include "hw/i386/pc.h"
|
#include "hw/i386/pc.h"
|
||||||
|
@ -117,21 +118,25 @@ static void ioapic_service(IOAPICCommonState *s)
|
||||||
s->ioredtbl[i] |= IOAPIC_LVT_REMOTE_IRR;
|
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
|
#ifdef CONFIG_KVM
|
||||||
if (kvm_irqchip_is_split()) {
|
if (kvm_irqchip_is_split()) {
|
||||||
if (info.trig_mode == IOAPIC_TRIGGER_EDGE) {
|
if (info.trig_mode == IOAPIC_TRIGGER_EDGE) {
|
||||||
kvm_set_irq(kvm_state, i, 1);
|
kvm_set_irq(kvm_state, i, 1);
|
||||||
kvm_set_irq(kvm_state, i, 0);
|
kvm_set_irq(kvm_state, i, 0);
|
||||||
} else {
|
} else {
|
||||||
if (!coalesce) {
|
kvm_set_irq(kvm_state, i, 1);
|
||||||
kvm_set_irq(kvm_state, i, 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
(void)coalesce;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* No matter whether IR is enabled, we translate
|
/* No matter whether IR is enabled, we translate
|
||||||
* the IOAPIC message into a MSI one, and its
|
* the IOAPIC message into a MSI one, and its
|
||||||
* address space will decide whether we need a
|
* 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;
|
val = s->id << IOAPIC_ID_SHIFT;
|
||||||
break;
|
break;
|
||||||
case IOAPIC_REG_VER:
|
case IOAPIC_REG_VER:
|
||||||
val = IOAPIC_VERSION |
|
val = s->version |
|
||||||
((IOAPIC_NUM_PINS - 1) << IOAPIC_VER_ENTRIES_SHIFT);
|
((IOAPIC_NUM_PINS - 1) << IOAPIC_VER_ENTRIES_SHIFT);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -354,6 +359,13 @@ ioapic_mem_write(void *opaque, hwaddr addr, uint64_t val,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
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);
|
ioapic_update_kvm_routes(s);
|
||||||
|
@ -387,6 +399,12 @@ static void ioapic_realize(DeviceState *dev, Error **errp)
|
||||||
{
|
{
|
||||||
IOAPICCommonState *s = IOAPIC_COMMON(dev);
|
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,
|
memory_region_init_io(&s->io_memory, OBJECT(s), &ioapic_io_ops, s,
|
||||||
"ioapic", 0x1000);
|
"ioapic", 0x1000);
|
||||||
|
|
||||||
|
@ -397,6 +415,11 @@ static void ioapic_realize(DeviceState *dev, Error **errp)
|
||||||
qemu_add_machine_init_done_notifier(&s->machine_done);
|
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)
|
static void ioapic_class_init(ObjectClass *klass, void *data)
|
||||||
{
|
{
|
||||||
IOAPICCommonClass *k = IOAPIC_COMMON_CLASS(klass);
|
IOAPICCommonClass *k = IOAPIC_COMMON_CLASS(klass);
|
||||||
|
@ -404,6 +427,7 @@ static void ioapic_class_init(ObjectClass *klass, void *data)
|
||||||
|
|
||||||
k->realize = ioapic_realize;
|
k->realize = ioapic_realize;
|
||||||
dc->reset = ioapic_reset_common;
|
dc->reset = ioapic_reset_common;
|
||||||
|
dc->props = ioapic_properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo ioapic_info = {
|
static const TypeInfo ioapic_info = {
|
||||||
|
|
|
@ -990,6 +990,7 @@ static void fw_cfg_class_init(ObjectClass *klass, void *data)
|
||||||
static const TypeInfo fw_cfg_info = {
|
static const TypeInfo fw_cfg_info = {
|
||||||
.name = TYPE_FW_CFG,
|
.name = TYPE_FW_CFG,
|
||||||
.parent = TYPE_SYS_BUS_DEVICE,
|
.parent = TYPE_SYS_BUS_DEVICE,
|
||||||
|
.abstract = true,
|
||||||
.instance_size = sizeof(FWCfgState),
|
.instance_size = sizeof(FWCfgState),
|
||||||
.class_init = fw_cfg_class_init,
|
.class_init = fw_cfg_class_init,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1295,6 +1295,8 @@ static void mptsas_scsi_init(PCIDevice *dev, Error **errp)
|
||||||
/* With msi=auto, we fall back to MSI off silently */
|
/* With msi=auto, we fall back to MSI off silently */
|
||||||
error_free(err);
|
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,
|
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,
|
.post_load = mptsas_post_load,
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_PCI_DEVICE(dev, MPTSASState),
|
VMSTATE_PCI_DEVICE(dev, MPTSASState),
|
||||||
VMSTATE_UNUSED(sizeof(bool)), /* Was msi_in_use */
|
VMSTATE_BOOL(msi_in_use, MPTSASState),
|
||||||
VMSTATE_UINT32(state, MPTSASState),
|
VMSTATE_UINT32(state, MPTSASState),
|
||||||
VMSTATE_UINT8(who_init, MPTSASState),
|
VMSTATE_UINT8(who_init, MPTSASState),
|
||||||
VMSTATE_UINT8(doorbell_state, MPTSASState),
|
VMSTATE_UINT8(doorbell_state, MPTSASState),
|
||||||
|
|
|
@ -31,6 +31,8 @@ struct MPTSASState {
|
||||||
OnOffAuto msi;
|
OnOffAuto msi;
|
||||||
uint64_t sas_addr;
|
uint64_t sas_addr;
|
||||||
|
|
||||||
|
bool msi_in_use;
|
||||||
|
|
||||||
/* Doorbell register */
|
/* Doorbell register */
|
||||||
uint32_t state;
|
uint32_t state;
|
||||||
uint8_t who_init;
|
uint8_t who_init;
|
||||||
|
|
|
@ -330,36 +330,39 @@ typedef struct BlockLimits {
|
||||||
* otherwise. */
|
* otherwise. */
|
||||||
uint32_t request_alignment;
|
uint32_t request_alignment;
|
||||||
|
|
||||||
/* maximum number of bytes that can be discarded at once (since it
|
/* Maximum number of bytes that can be discarded at once (since it
|
||||||
* is signed, it must be < 2G, if set), should be multiple of
|
* 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
|
* pdiscard_alignment, but need not be power of 2. May be 0 if no
|
||||||
* inherent 32-bit limit */
|
* inherent 32-bit limit */
|
||||||
int32_t max_pdiscard;
|
int32_t max_pdiscard;
|
||||||
|
|
||||||
/* optimal alignment for discard requests in bytes, must be power
|
/* Optimal alignment for discard requests in bytes. A power of 2
|
||||||
* of 2, less than max_pdiscard if that is set, and multiple of
|
* is best but not mandatory. Must be a multiple of
|
||||||
* bl.request_alignment. May be 0 if bl.request_alignment is good
|
* bl.request_alignment, and must be less than max_pdiscard if
|
||||||
* enough */
|
* that is set. May be 0 if bl.request_alignment is good enough */
|
||||||
uint32_t pdiscard_alignment;
|
uint32_t pdiscard_alignment;
|
||||||
|
|
||||||
/* maximum number of bytes that can zeroized at once (since it is
|
/* Maximum number of bytes that can zeroized at once (since it is
|
||||||
* signed, it must be < 2G, if set), should be multiple of
|
* signed, it must be < 2G, if set). Must be multiple of
|
||||||
* pwrite_zeroes_alignment. May be 0 if no inherent 32-bit limit */
|
* pwrite_zeroes_alignment. May be 0 if no inherent 32-bit limit */
|
||||||
int32_t max_pwrite_zeroes;
|
int32_t max_pwrite_zeroes;
|
||||||
|
|
||||||
/* optimal alignment for write zeroes requests in bytes, must be
|
/* Optimal alignment for write zeroes requests in bytes. A power
|
||||||
* power of 2, less than max_pwrite_zeroes if that is set, and
|
* of 2 is best but not mandatory. Must be a multiple of
|
||||||
* multiple of bl.request_alignment. May be 0 if
|
* bl.request_alignment, and must be less than max_pwrite_zeroes
|
||||||
* bl.request_alignment is good enough */
|
* if that is set. May be 0 if bl.request_alignment is good
|
||||||
|
* enough */
|
||||||
uint32_t pwrite_zeroes_alignment;
|
uint32_t pwrite_zeroes_alignment;
|
||||||
|
|
||||||
/* optimal transfer length in bytes (must be power of 2, and
|
/* Optimal transfer length in bytes. A power of 2 is best but not
|
||||||
* multiple of bl.request_alignment), or 0 if no preferred size */
|
* mandatory. Must be a multiple of bl.request_alignment, or 0 if
|
||||||
|
* no preferred size */
|
||||||
uint32_t opt_transfer;
|
uint32_t opt_transfer;
|
||||||
|
|
||||||
/* maximal transfer length in bytes (need not be power of 2, but
|
/* 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.
|
* must be multiple of opt_transfer and bl.request_alignment, or 0
|
||||||
* For now, anything larger than INT_MAX is clamped down. */
|
* for no 32-bit limit. For now, anything larger than INT_MAX is
|
||||||
|
* clamped down. */
|
||||||
uint32_t max_transfer;
|
uint32_t max_transfer;
|
||||||
|
|
||||||
/* memory alignment, in bytes so that no bounce buffer is needed */
|
/* memory alignment, in bytes so that no bounce buffer is needed */
|
||||||
|
|
|
@ -90,11 +90,11 @@ ssize_t nbd_wr_syncv(QIOChannel *ioc,
|
||||||
size_t niov,
|
size_t niov,
|
||||||
size_t length,
|
size_t length,
|
||||||
bool do_read);
|
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,
|
QCryptoTLSCreds *tlscreds, const char *hostname,
|
||||||
QIOChannel **outioc,
|
QIOChannel **outioc,
|
||||||
off_t *size, Error **errp);
|
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_send_request(QIOChannel *ioc, struct nbd_request *request);
|
||||||
ssize_t nbd_receive_reply(QIOChannel *ioc, struct nbd_reply *reply);
|
ssize_t nbd_receive_reply(QIOChannel *ioc, struct nbd_reply *reply);
|
||||||
int nbd_client(int fd);
|
int nbd_client(int fd);
|
||||||
|
@ -104,7 +104,7 @@ typedef struct NBDExport NBDExport;
|
||||||
typedef struct NBDClient NBDClient;
|
typedef struct NBDClient NBDClient;
|
||||||
|
|
||||||
NBDExport *nbd_export_new(BlockBackend *blk, off_t dev_offset, off_t size,
|
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);
|
Error **errp);
|
||||||
void nbd_export_close(NBDExport *exp);
|
void nbd_export_close(NBDExport *exp);
|
||||||
void nbd_export_get(NBDExport *exp);
|
void nbd_export_get(NBDExport *exp);
|
||||||
|
|
|
@ -29,8 +29,6 @@
|
||||||
|
|
||||||
#define MAX_IOAPICS 1
|
#define MAX_IOAPICS 1
|
||||||
|
|
||||||
#define IOAPIC_VERSION 0x11
|
|
||||||
|
|
||||||
#define IOAPIC_LVT_DEST_SHIFT 56
|
#define IOAPIC_LVT_DEST_SHIFT 56
|
||||||
#define IOAPIC_LVT_DEST_IDX_SHIFT 48
|
#define IOAPIC_LVT_DEST_IDX_SHIFT 48
|
||||||
#define IOAPIC_LVT_MASKED_SHIFT 16
|
#define IOAPIC_LVT_MASKED_SHIFT 16
|
||||||
|
@ -71,6 +69,7 @@
|
||||||
|
|
||||||
#define IOAPIC_IOREGSEL 0x00
|
#define IOAPIC_IOREGSEL 0x00
|
||||||
#define IOAPIC_IOWIN 0x10
|
#define IOAPIC_IOWIN 0x10
|
||||||
|
#define IOAPIC_EOI 0x40
|
||||||
|
|
||||||
#define IOAPIC_REG_ID 0x00
|
#define IOAPIC_REG_ID 0x00
|
||||||
#define IOAPIC_REG_VER 0x01
|
#define IOAPIC_REG_VER 0x01
|
||||||
|
@ -109,6 +108,7 @@ struct IOAPICCommonState {
|
||||||
uint32_t irr;
|
uint32_t irr;
|
||||||
uint64_t ioredtbl[IOAPIC_NUM_PINS];
|
uint64_t ioredtbl[IOAPIC_NUM_PINS];
|
||||||
Notifier machine_done;
|
Notifier machine_done;
|
||||||
|
uint8_t version;
|
||||||
};
|
};
|
||||||
|
|
||||||
void ioapic_reset_common(DeviceState *dev);
|
void ioapic_reset_common(DeviceState *dev);
|
||||||
|
|
|
@ -388,7 +388,7 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *);
|
||||||
.value = "off",\
|
.value = "off",\
|
||||||
},\
|
},\
|
||||||
{\
|
{\
|
||||||
.driver = "apic",\
|
.driver = "apic-common",\
|
||||||
.property = "legacy-instance-id",\
|
.property = "legacy-instance-id",\
|
||||||
.value = "on",\
|
.value = "on",\
|
||||||
},
|
},
|
||||||
|
|
|
@ -158,7 +158,8 @@ extern int daemon(int, int);
|
||||||
/* Round number down to multiple */
|
/* Round number down to multiple */
|
||||||
#define QEMU_ALIGN_DOWN(n, m) ((n) / (m) * (m))
|
#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))
|
#define QEMU_ALIGN_UP(n, m) QEMU_ALIGN_DOWN((n) + (m) - 1, (m))
|
||||||
|
|
||||||
/* Check if n is a multiple of 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 */
|
/* Check if pointer p is n-bytes aligned */
|
||||||
#define QEMU_PTR_IS_ALIGNED(p, n) QEMU_IS_ALIGNED((uintptr_t)(p), (n))
|
#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
|
#ifndef ROUND_UP
|
||||||
#define ROUND_UP(n,d) (((n) + (d) - 1) & -(d))
|
#define ROUND_UP(n,d) (((n) + (d) - 1) & -(d))
|
||||||
#endif
|
#endif
|
||||||
|
@ -379,7 +383,7 @@ unsigned long qemu_getauxval(unsigned long type);
|
||||||
|
|
||||||
void qemu_set_tty_echo(int fd, bool echo);
|
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);
|
int qemu_read_password(char *buf, int buf_size);
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,9 @@ void qht_destroy(struct qht *ht);
|
||||||
* Attempting to insert a NULL @p is a bug.
|
* Attempting to insert a NULL @p is a bug.
|
||||||
* Inserting the same pointer @p with different @hash values 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 true on sucess.
|
||||||
* Returns false if the @p-@hash pair already exists in the hash table.
|
* 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.
|
* 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.
|
* The user-provided @func compares pointers in QHT against @userp.
|
||||||
* If the function returns true, a match has been found.
|
* If the function returns true, a match has been found.
|
||||||
*
|
*
|
||||||
|
|
|
@ -33,20 +33,12 @@ int socket_set_fast_reuse(int fd);
|
||||||
typedef void NonBlockingConnectHandler(int fd, Error *err, void *opaque);
|
typedef void NonBlockingConnectHandler(int fd, Error *err, void *opaque);
|
||||||
|
|
||||||
InetSocketAddress *inet_parse(const char *str, Error **errp);
|
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_connect(const char *str, Error **errp);
|
||||||
int inet_nonblocking_connect(const char *str,
|
|
||||||
NonBlockingConnectHandler *callback,
|
|
||||||
void *opaque, Error **errp);
|
|
||||||
|
|
||||||
NetworkAddressFamily inet_netfamily(int family);
|
NetworkAddressFamily inet_netfamily(int family);
|
||||||
|
|
||||||
int unix_listen(const char *path, char *ostr, int olen, Error **errp);
|
int unix_listen(const char *path, char *ostr, int olen, Error **errp);
|
||||||
int unix_connect(const char *path, 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);
|
SocketAddress *socket_parse(const char *str, Error **errp);
|
||||||
int socket_connect(SocketAddress *addr, Error **errp,
|
int socket_connect(SocketAddress *addr, Error **errp,
|
||||||
|
|
28
nbd/client.c
28
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,
|
QCryptoTLSCreds *tlscreds, const char *hostname,
|
||||||
QIOChannel **outioc,
|
QIOChannel **outioc,
|
||||||
off_t *size, Error **errp)
|
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 opt;
|
||||||
uint32_t namesize;
|
uint32_t namesize;
|
||||||
uint16_t globalflags;
|
uint16_t globalflags;
|
||||||
uint16_t exportflags;
|
|
||||||
bool fixedNewStyle = false;
|
bool fixedNewStyle = false;
|
||||||
|
|
||||||
if (read_sync(ioc, &globalflags, sizeof(globalflags)) !=
|
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;
|
goto fail;
|
||||||
}
|
}
|
||||||
globalflags = be16_to_cpu(globalflags);
|
globalflags = be16_to_cpu(globalflags);
|
||||||
*flags = globalflags << 16;
|
|
||||||
TRACE("Global flags are %" PRIx32, globalflags);
|
TRACE("Global flags are %" PRIx32, globalflags);
|
||||||
if (globalflags & NBD_FLAG_FIXED_NEWSTYLE) {
|
if (globalflags & NBD_FLAG_FIXED_NEWSTYLE) {
|
||||||
fixedNewStyle = true;
|
fixedNewStyle = true;
|
||||||
|
@ -545,17 +543,15 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char *name, uint32_t *flags,
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
*size = be64_to_cpu(s);
|
*size = be64_to_cpu(s);
|
||||||
TRACE("Size is %" PRIu64, *size);
|
|
||||||
|
|
||||||
if (read_sync(ioc, &exportflags, sizeof(exportflags)) !=
|
if (read_sync(ioc, flags, sizeof(*flags)) != sizeof(*flags)) {
|
||||||
sizeof(exportflags)) {
|
|
||||||
error_setg(errp, "Failed to read export flags");
|
error_setg(errp, "Failed to read export flags");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
exportflags = be16_to_cpu(exportflags);
|
be16_to_cpus(flags);
|
||||||
*flags |= exportflags;
|
|
||||||
TRACE("Export flags are %" PRIx16, exportflags);
|
|
||||||
} else if (magic == NBD_CLIENT_MAGIC) {
|
} else if (magic == NBD_CLIENT_MAGIC) {
|
||||||
|
uint32_t oldflags;
|
||||||
|
|
||||||
if (name) {
|
if (name) {
|
||||||
error_setg(errp, "Server does not support export names");
|
error_setg(errp, "Server does not support export names");
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -572,16 +568,22 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char *name, uint32_t *flags,
|
||||||
*size = be64_to_cpu(s);
|
*size = be64_to_cpu(s);
|
||||||
TRACE("Size is %" PRIu64, *size);
|
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");
|
error_setg(errp, "Failed to read export flags");
|
||||||
goto fail;
|
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 {
|
} else {
|
||||||
error_setg(errp, "Bad magic received");
|
error_setg(errp, "Bad magic received");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TRACE("Size is %" PRIu64 ", export flags %" PRIx16, *size, *flags);
|
||||||
if (read_sync(ioc, &buf, 124) != 124) {
|
if (read_sync(ioc, &buf, 124) != 124) {
|
||||||
error_setg(errp, "Failed to read reserved block");
|
error_setg(errp, "Failed to read reserved block");
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -593,7 +595,7 @@ fail:
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __linux__
|
#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;
|
unsigned long sectors = size / BDRV_SECTOR_SIZE;
|
||||||
if (size / BDRV_SECTOR_SIZE != sectors) {
|
if (size / BDRV_SECTOR_SIZE != sectors) {
|
||||||
|
@ -689,7 +691,7 @@ int nbd_disconnect(int fd)
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#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;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
13
nbd/server.c
13
nbd/server.c
|
@ -63,7 +63,7 @@ struct NBDExport {
|
||||||
char *name;
|
char *name;
|
||||||
off_t dev_offset;
|
off_t dev_offset;
|
||||||
off_t size;
|
off_t size;
|
||||||
uint32_t nbdflags;
|
uint16_t nbdflags;
|
||||||
QTAILQ_HEAD(, NBDClient) clients;
|
QTAILQ_HEAD(, NBDClient) clients;
|
||||||
QTAILQ_ENTRY(NBDExport) next;
|
QTAILQ_ENTRY(NBDExport) next;
|
||||||
|
|
||||||
|
@ -544,8 +544,8 @@ static coroutine_fn int nbd_negotiate(NBDClientNewData *data)
|
||||||
NBDClient *client = data->client;
|
NBDClient *client = data->client;
|
||||||
char buf[8 + 8 + 8 + 128];
|
char buf[8 + 8 + 8 + 128];
|
||||||
int rc;
|
int rc;
|
||||||
const int myflags = (NBD_FLAG_HAS_FLAGS | NBD_FLAG_SEND_TRIM |
|
const uint16_t myflags = (NBD_FLAG_HAS_FLAGS | NBD_FLAG_SEND_TRIM |
|
||||||
NBD_FLAG_SEND_FLUSH | NBD_FLAG_SEND_FUA);
|
NBD_FLAG_SEND_FLUSH | NBD_FLAG_SEND_FUA);
|
||||||
bool oldStyle;
|
bool oldStyle;
|
||||||
|
|
||||||
/* Old style negotiation header without options
|
/* Old style negotiation header without options
|
||||||
|
@ -575,7 +575,6 @@ static coroutine_fn int nbd_negotiate(NBDClientNewData *data)
|
||||||
|
|
||||||
oldStyle = client->exp != NULL && !client->tlscreds;
|
oldStyle = client->exp != NULL && !client->tlscreds;
|
||||||
if (oldStyle) {
|
if (oldStyle) {
|
||||||
assert ((client->exp->nbdflags & ~65535) == 0);
|
|
||||||
TRACE("advertising size %" PRIu64 " and flags %x",
|
TRACE("advertising size %" PRIu64 " and flags %x",
|
||||||
client->exp->size, client->exp->nbdflags | myflags);
|
client->exp->size, client->exp->nbdflags | myflags);
|
||||||
stq_be_p(buf + 8, NBD_CLIENT_MAGIC);
|
stq_be_p(buf + 8, NBD_CLIENT_MAGIC);
|
||||||
|
@ -606,7 +605,6 @@ static coroutine_fn int nbd_negotiate(NBDClientNewData *data)
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert ((client->exp->nbdflags & ~65535) == 0);
|
|
||||||
TRACE("advertising size %" PRIu64 " and flags %x",
|
TRACE("advertising size %" PRIu64 " and flags %x",
|
||||||
client->exp->size, client->exp->nbdflags | myflags);
|
client->exp->size, client->exp->nbdflags | myflags);
|
||||||
stq_be_p(buf + 18, client->exp->size);
|
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,
|
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)
|
Error **errp)
|
||||||
{
|
{
|
||||||
NBDExport *exp = g_malloc0(sizeof(NBDExport));
|
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) {
|
if (request->type & ~NBD_CMD_MASK_COMMAND & ~NBD_CMD_FLAG_FUA) {
|
||||||
LOG("unsupported flags (got 0x%x)",
|
LOG("unsupported flags (got 0x%x)",
|
||||||
request->type & ~NBD_CMD_MASK_COMMAND);
|
request->type & ~NBD_CMD_MASK_COMMAND);
|
||||||
return -EINVAL;
|
rc = -EINVAL;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = 0;
|
rc = 0;
|
||||||
|
|
1
numa.c
1
numa.c
|
@ -463,6 +463,7 @@ void memory_region_allocate_system_memory(MemoryRegion *mr, Object *owner,
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
host_memory_backend_set_mapped(backend, true);
|
||||||
memory_region_add_subregion(mr, addr, seg);
|
memory_region_add_subregion(mr, addr, seg);
|
||||||
vmstate_register_ram_global(seg);
|
vmstate_register_ram_global(seg);
|
||||||
addr += size;
|
addr += size;
|
||||||
|
|
|
@ -251,7 +251,7 @@ static void *nbd_client_thread(void *arg)
|
||||||
{
|
{
|
||||||
char *device = arg;
|
char *device = arg;
|
||||||
off_t size;
|
off_t size;
|
||||||
uint32_t nbdflags;
|
uint16_t nbdflags;
|
||||||
QIOChannelSocket *sioc;
|
QIOChannelSocket *sioc;
|
||||||
int fd;
|
int fd;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -465,7 +465,7 @@ int main(int argc, char **argv)
|
||||||
BlockBackend *blk;
|
BlockBackend *blk;
|
||||||
BlockDriverState *bs;
|
BlockDriverState *bs;
|
||||||
off_t dev_offset = 0;
|
off_t dev_offset = 0;
|
||||||
uint32_t nbdflags = 0;
|
uint16_t nbdflags = 0;
|
||||||
bool disconnect = false;
|
bool disconnect = false;
|
||||||
const char *bindto = "0.0.0.0";
|
const char *bindto = "0.0.0.0";
|
||||||
const char *port = NULL;
|
const char *port = NULL;
|
||||||
|
|
|
@ -927,10 +927,25 @@ ETEXI
|
||||||
|
|
||||||
DEF("display", HAS_ARG, QEMU_OPTION_display,
|
DEF("display", HAS_ARG, QEMU_OPTION_display,
|
||||||
"-display sdl[,frame=on|off][,alt_grab=on|off][,ctrl_grab=on|off]\n"
|
"-display sdl[,frame=on|off][,alt_grab=on|off][,ctrl_grab=on|off]\n"
|
||||||
" [,window_close=on|off]|curses|none|\n"
|
" [,window_close=on|off][,gl=on|off]|curses|none|\n"
|
||||||
" gtk[,grab_on_hover=on|off]|\n"
|
"-display gtk[,grab_on_hover=on|off][,gl=on|off]|\n"
|
||||||
" vnc=<display>[,<optargs>]\n"
|
"-display vnc=<display>[,<optargs>]\n"
|
||||||
" select display type\n", QEMU_ARCH_ALL)
|
"-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
|
STEXI
|
||||||
@item -display @var{type}
|
@item -display @var{type}
|
||||||
@findex -display
|
@findex -display
|
||||||
|
@ -977,7 +992,7 @@ the console and monitor.
|
||||||
ETEXI
|
ETEXI
|
||||||
|
|
||||||
DEF("curses", 0, QEMU_OPTION_curses,
|
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)
|
QEMU_ARCH_ALL)
|
||||||
STEXI
|
STEXI
|
||||||
@item -curses
|
@item -curses
|
||||||
|
@ -1027,7 +1042,7 @@ Disable SDL window close capability.
|
||||||
ETEXI
|
ETEXI
|
||||||
|
|
||||||
DEF("sdl", 0, QEMU_OPTION_sdl,
|
DEF("sdl", 0, QEMU_OPTION_sdl,
|
||||||
"-sdl enable SDL\n", QEMU_ARCH_ALL)
|
"-sdl shorthand for -display sdl\n", QEMU_ARCH_ALL)
|
||||||
STEXI
|
STEXI
|
||||||
@item -sdl
|
@item -sdl
|
||||||
@findex -sdl
|
@findex -sdl
|
||||||
|
@ -1224,7 +1239,7 @@ Set the initial graphical resolution and depth (PPC, SPARC only).
|
||||||
ETEXI
|
ETEXI
|
||||||
|
|
||||||
DEF("vnc", HAS_ARG, QEMU_OPTION_vnc ,
|
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
|
STEXI
|
||||||
@item -vnc @var{display}[,@var{option}[,@var{option}[,...]]]
|
@item -vnc @var{display}[,@var{option}[,@var{option}[,...]]]
|
||||||
@findex -vnc
|
@findex -vnc
|
||||||
|
|
|
@ -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\(/) {
|
if ($line =~ /\bffs\(/) {
|
||||||
ERROR("use ctz32() instead of ffs()\n" . $herecurr);
|
ERROR("use ctz32() instead of ffs()\n" . $herecurr);
|
||||||
}
|
}
|
||||||
|
@ -2554,6 +2554,9 @@ sub process {
|
||||||
if ($line =~ /\bffsll\(/) {
|
if ($line =~ /\bffsll\(/) {
|
||||||
ERROR("use ctz64() instead of ffsll()\n" . $herecurr);
|
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
|
# If we have no input at all, then there is nothing to report on
|
||||||
|
|
|
@ -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]);
|
tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[R_ECX]);
|
||||||
gen_helper_xsetbv(cpu_env, cpu_tmp2_i32, cpu_tmp1_i64);
|
gen_helper_xsetbv(cpu_env, cpu_tmp2_i32, cpu_tmp1_i64);
|
||||||
/* End TB because translation flags may change. */
|
/* 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);
|
gen_eob(s);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -360,10 +360,16 @@ static void test_none(void)
|
||||||
g_assert(isnan(qdist_xmax(&dist)));
|
g_assert(isnan(qdist_xmax(&dist)));
|
||||||
|
|
||||||
pr = qdist_pr_plain(&dist, 0);
|
pr = qdist_pr_plain(&dist, 0);
|
||||||
g_assert(pr == NULL);
|
g_assert_cmpstr(pr, ==, "(empty)");
|
||||||
|
g_free(pr);
|
||||||
|
|
||||||
pr = qdist_pr_plain(&dist, 2);
|
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);
|
qdist_destroy(&dist);
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,8 +95,12 @@ static void iter_check(unsigned int count)
|
||||||
|
|
||||||
static void qht_do_test(unsigned int mode, size_t init_entries)
|
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);
|
qht_init(&ht, 0, mode);
|
||||||
|
|
||||||
|
check_n(0);
|
||||||
insert(0, N);
|
insert(0, N);
|
||||||
check(0, N, true);
|
check(0, N, true);
|
||||||
check_n(N);
|
check_n(N);
|
||||||
|
|
|
@ -1663,15 +1663,50 @@ void tb_flush_jmp_cache(CPUState *cpu, target_ulong addr)
|
||||||
TB_JMP_PAGE_SIZE * sizeof(TranslationBlock *));
|
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)
|
void dump_exec_info(FILE *f, fprintf_function cpu_fprintf)
|
||||||
{
|
{
|
||||||
int i, target_code_size, max_target_code_size;
|
int i, target_code_size, max_target_code_size;
|
||||||
int direct_jmp_count, direct_jmp2_count, cross_page;
|
int direct_jmp_count, direct_jmp2_count, cross_page;
|
||||||
TranslationBlock *tb;
|
TranslationBlock *tb;
|
||||||
struct qht_stats hst;
|
struct qht_stats hst;
|
||||||
uint32_t hgram_opts;
|
|
||||||
size_t hgram_bins;
|
|
||||||
char *hgram;
|
|
||||||
|
|
||||||
target_code_size = 0;
|
target_code_size = 0;
|
||||||
max_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);
|
tcg_ctx.tb_ctx.nb_tbs : 0);
|
||||||
|
|
||||||
qht_statistics_init(&tcg_ctx.tb_ctx.htable, &hst);
|
qht_statistics_init(&tcg_ctx.tb_ctx.htable, &hst);
|
||||||
|
print_qht_statistics(f, cpu_fprintf, 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);
|
|
||||||
|
|
||||||
qht_statistics_destroy(&hst);
|
qht_statistics_destroy(&hst);
|
||||||
|
|
||||||
cpu_fprintf(f, "\nStatistics:\n");
|
cpu_fprintf(f, "\nStatistics:\n");
|
||||||
|
|
|
@ -247,7 +247,8 @@ unsigned iov_copy(struct iovec *dst_iov, unsigned int dst_iov_cnt,
|
||||||
{
|
{
|
||||||
size_t len;
|
size_t len;
|
||||||
unsigned int i, j;
|
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) {
|
if (offset >= iov[i].iov_len) {
|
||||||
offset -= iov[i].iov_len;
|
offset -= iov[i].iov_len;
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -318,7 +318,7 @@ static void sigbus_handler(int signal)
|
||||||
siglongjmp(sigjump, 1);
|
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;
|
int ret;
|
||||||
struct sigaction act, oldact;
|
struct sigaction act, oldact;
|
||||||
|
@ -330,8 +330,9 @@ void os_mem_prealloc(int fd, char *area, size_t memory)
|
||||||
|
|
||||||
ret = sigaction(SIGBUS, &act, &oldact);
|
ret = sigaction(SIGBUS, &act, &oldact);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
perror("os_mem_prealloc: failed to install signal handler");
|
error_setg_errno(errp, errno,
|
||||||
exit(1);
|
"os_mem_prealloc: failed to install signal handler");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* unblock SIGBUS */
|
/* unblock SIGBUS */
|
||||||
|
@ -340,9 +341,8 @@ void os_mem_prealloc(int fd, char *area, size_t memory)
|
||||||
pthread_sigmask(SIG_UNBLOCK, &set, &oldset);
|
pthread_sigmask(SIG_UNBLOCK, &set, &oldset);
|
||||||
|
|
||||||
if (sigsetjmp(sigjump, 1)) {
|
if (sigsetjmp(sigjump, 1)) {
|
||||||
fprintf(stderr, "os_mem_prealloc: Insufficient free host memory "
|
error_setg(errp, "os_mem_prealloc: Insufficient free host memory "
|
||||||
"pages available to allocate guest RAM\n");
|
"pages available to allocate guest RAM\n");
|
||||||
exit(1);
|
|
||||||
} else {
|
} else {
|
||||||
int i;
|
int i;
|
||||||
size_t hpagesize = qemu_fd_getpagesize(fd);
|
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++) {
|
for (i = 0; i < numpages; i++) {
|
||||||
memset(area + (hpagesize * i), 0, 1);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -539,7 +539,7 @@ int getpagesize(void)
|
||||||
return system_info.dwPageSize;
|
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;
|
int i;
|
||||||
size_t pagesize = getpagesize();
|
size_t pagesize = getpagesize();
|
||||||
|
|
13
util/qdist.c
13
util/qdist.c
|
@ -14,9 +14,11 @@
|
||||||
#define NAN (0.0 / 0.0)
|
#define NAN (0.0 / 0.0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define QDIST_EMPTY_STR "(empty)"
|
||||||
|
|
||||||
void qdist_init(struct qdist *dist)
|
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->size = 1;
|
||||||
dist->n = 0;
|
dist->n = 0;
|
||||||
}
|
}
|
||||||
|
@ -62,8 +64,7 @@ void qdist_add(struct qdist *dist, double x, long count)
|
||||||
|
|
||||||
if (unlikely(dist->n == dist->size)) {
|
if (unlikely(dist->n == dist->size)) {
|
||||||
dist->size *= 2;
|
dist->size *= 2;
|
||||||
dist->entries = g_realloc(dist->entries,
|
dist->entries = g_renew(struct qdist_entry, dist->entries, dist->size);
|
||||||
sizeof(*dist->entries) * (dist->size));
|
|
||||||
}
|
}
|
||||||
dist->n++;
|
dist->n++;
|
||||||
entry = &dist->entries[dist->n - 1];
|
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 */
|
/* 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;
|
to->n = from->n;
|
||||||
memcpy(to->entries, from->entries, sizeof(*to->entries) * to->n);
|
memcpy(to->entries, from->entries, sizeof(*to->entries) * to->n);
|
||||||
return;
|
return;
|
||||||
|
@ -234,7 +235,7 @@ char *qdist_pr_plain(const struct qdist *dist, size_t n)
|
||||||
char *ret;
|
char *ret;
|
||||||
|
|
||||||
if (dist->n == 0) {
|
if (dist->n == 0) {
|
||||||
return NULL;
|
return g_strdup(QDIST_EMPTY_STR);
|
||||||
}
|
}
|
||||||
qdist_bin__internal(&binned, dist, n);
|
qdist_bin__internal(&binned, dist, n);
|
||||||
ret = qdist_pr_internal(&binned);
|
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;
|
GString *s;
|
||||||
|
|
||||||
if (dist->n == 0) {
|
if (dist->n == 0) {
|
||||||
return NULL;
|
return g_strdup(QDIST_EMPTY_STR);
|
||||||
}
|
}
|
||||||
|
|
||||||
s = g_string_new("");
|
s = g_string_new("");
|
||||||
|
|
|
@ -624,34 +624,6 @@ fail:
|
||||||
return NULL;
|
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.
|
* Create a blocking socket and connect it to an address.
|
||||||
|
@ -674,36 +646,6 @@ int inet_connect(const char *str, Error **errp)
|
||||||
return sock;
|
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
|
#ifndef _WIN32
|
||||||
|
|
||||||
static int unix_listen_saddr(UnixSocketAddress *saddr,
|
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 *socket_parse(const char *str, Error **errp)
|
||||||
{
|
{
|
||||||
SocketAddress *addr;
|
SocketAddress *addr;
|
||||||
|
|
14
util/qht.c
14
util/qht.c
|
@ -445,7 +445,11 @@ void *qht_do_lookup(struct qht_bucket *head, qht_lookup_func_t func,
|
||||||
do {
|
do {
|
||||||
for (i = 0; i < QHT_BUCKET_ENTRIES; i++) {
|
for (i = 0; i < QHT_BUCKET_ENTRIES; i++) {
|
||||||
if (b->hashes[i] == hash) {
|
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))) {
|
if (likely(p) && likely(func(p, userp))) {
|
||||||
return p;
|
return p;
|
||||||
|
@ -535,6 +539,7 @@ static bool qht_insert__locked(struct qht *ht, struct qht_map *map,
|
||||||
atomic_rcu_set(&prev->next, b);
|
atomic_rcu_set(&prev->next, b);
|
||||||
}
|
}
|
||||||
b->hashes[i] = hash;
|
b->hashes[i] = hash;
|
||||||
|
/* smp_wmb() implicit in seqlock_write_begin. */
|
||||||
atomic_set(&b->pointers[i], p);
|
atomic_set(&b->pointers[i], p);
|
||||||
seqlock_write_end(&head->sequence);
|
seqlock_write_end(&head->sequence);
|
||||||
return true;
|
return true;
|
||||||
|
@ -784,11 +789,16 @@ void qht_statistics_init(struct qht *ht, struct qht_stats *stats)
|
||||||
|
|
||||||
map = atomic_rcu_read(&ht->map);
|
map = atomic_rcu_read(&ht->map);
|
||||||
|
|
||||||
stats->head_buckets = map->n_buckets;
|
|
||||||
stats->used_head_buckets = 0;
|
stats->used_head_buckets = 0;
|
||||||
stats->entries = 0;
|
stats->entries = 0;
|
||||||
qdist_init(&stats->chain);
|
qdist_init(&stats->chain);
|
||||||
qdist_init(&stats->occupancy);
|
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++) {
|
for (i = 0; i < map->n_buckets; i++) {
|
||||||
struct qht_bucket *head = &map->buckets[i];
|
struct qht_bucket *head = &map->buckets[i];
|
||||||
|
|
Loading…
Reference in New Issue