diff options
-rw-r--r-- | hw/block/xen-block.c | 14 | ||||
-rw-r--r-- | hw/i386/xen/xen-hvm.c | 9 | ||||
-rw-r--r-- | hw/i386/xen/xen-mapcache.c | 15 | ||||
-rw-r--r-- | include/hw/xen/xen_common.h | 6 |
4 files changed, 39 insertions, 5 deletions
diff --git a/hw/block/xen-block.c b/hw/block/xen-block.c index 83754a4..674953f 100644 --- a/hw/block/xen-block.c +++ b/hw/block/xen-block.c @@ -728,6 +728,8 @@ static XenBlockDrive *xen_block_drive_create(const char *id, XenBlockDrive *drive = NULL; QDict *file_layer; QDict *driver_layer; + struct stat st; + int rc; if (params) { char **v = g_strsplit(params, ":", 2); @@ -761,7 +763,17 @@ static XenBlockDrive *xen_block_drive_create(const char *id, file_layer = qdict_new(); driver_layer = qdict_new(); - qdict_put_str(file_layer, "driver", "file"); + rc = stat(filename, &st); + if (rc) { + error_setg_errno(errp, errno, "Could not stat file '%s'", filename); + goto done; + } + if (S_ISBLK(st.st_mode)) { + qdict_put_str(file_layer, "driver", "host_device"); + } else { + qdict_put_str(file_layer, "driver", "file"); + } + qdict_put_str(file_layer, "filename", filename); g_free(filename); diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c index c53fa17..9b43277 100644 --- a/hw/i386/xen/xen-hvm.c +++ b/hw/i386/xen/xen-hvm.c @@ -108,6 +108,7 @@ typedef struct XenIOState { shared_iopage_t *shared_page; shared_vmport_iopage_t *shared_vmport_page; buffered_iopage_t *buffered_io_page; + xenforeignmemory_resource_handle *fres; QEMUTimer *buffered_io_timer; CPUState **cpu_by_vcpu_id; /* the evtchn port for polling the notification, */ @@ -1253,6 +1254,9 @@ static void xen_exit_notifier(Notifier *n, void *data) XenIOState *state = container_of(n, XenIOState, exit); xen_destroy_ioreq_server(xen_domid, state->ioservid); + if (state->fres != NULL) { + xenforeignmemory_unmap_resource(xen_fmem, state->fres); + } xenevtchn_close(state->xce_handle); xs_daemon_close(state->xenstore); @@ -1320,7 +1324,6 @@ static void xen_wakeup_notifier(Notifier *notifier, void *data) static int xen_map_ioreq_server(XenIOState *state) { void *addr = NULL; - xenforeignmemory_resource_handle *fres; xen_pfn_t ioreq_pfn; xen_pfn_t bufioreq_pfn; evtchn_port_t bufioreq_evtchn; @@ -1332,12 +1335,12 @@ static int xen_map_ioreq_server(XenIOState *state) */ QEMU_BUILD_BUG_ON(XENMEM_resource_ioreq_server_frame_bufioreq != 0); QEMU_BUILD_BUG_ON(XENMEM_resource_ioreq_server_frame_ioreq(0) != 1); - fres = xenforeignmemory_map_resource(xen_fmem, xen_domid, + state->fres = xenforeignmemory_map_resource(xen_fmem, xen_domid, XENMEM_resource_ioreq_server, state->ioservid, 0, 2, &addr, PROT_READ | PROT_WRITE, 0); - if (fres != NULL) { + if (state->fres != NULL) { trace_xen_map_resource_ioreq(state->ioservid, addr); state->buffered_io_page = addr; state->shared_page = addr + TARGET_PAGE_SIZE; diff --git a/hw/i386/xen/xen-mapcache.c b/hw/i386/xen/xen-mapcache.c index 5b120ed..e82b7dc 100644 --- a/hw/i386/xen/xen-mapcache.c +++ b/hw/i386/xen/xen-mapcache.c @@ -171,7 +171,20 @@ static void xen_remap_bucket(MapCacheEntry *entry, if (!(entry->flags & XEN_MAPCACHE_ENTRY_DUMMY)) { ram_block_notify_remove(entry->vaddr_base, entry->size); } - if (munmap(entry->vaddr_base, entry->size) != 0) { + + /* + * If an entry is being replaced by another mapping and we're using + * MAP_FIXED flag for it - there is possibility of a race for vaddr + * address with another thread doing an mmap call itself + * (see man 2 mmap). To avoid that we skip explicit unmapping here + * and allow the kernel to destroy the previous mappings by replacing + * them in mmap call later. + * + * Non-identical replacements are not allowed therefore. + */ + assert(!vaddr || (entry->vaddr_base == vaddr && entry->size == size)); + + if (!vaddr && munmap(entry->vaddr_base, entry->size) != 0) { perror("unmap fails"); exit(-1); } diff --git a/include/hw/xen/xen_common.h b/include/hw/xen/xen_common.h index 82e5633..a8118b4 100644 --- a/include/hw/xen/xen_common.h +++ b/include/hw/xen/xen_common.h @@ -134,6 +134,12 @@ static inline xenforeignmemory_resource_handle *xenforeignmemory_map_resource( return NULL; } +static inline int xenforeignmemory_unmap_resource( + xenforeignmemory_handle *fmem, xenforeignmemory_resource_handle *fres) +{ + return 0; +} + #endif /* CONFIG_XEN_CTRL_INTERFACE_VERSION < 41100 */ #if CONFIG_XEN_CTRL_INTERFACE_VERSION < 41000 |