diff options
51 files changed, 982 insertions, 291 deletions
diff --git a/.travis.yml b/.travis.yml index c13881e0d4..f30b10e4f7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -34,10 +34,13 @@ addons: - sparse - uuid-dev +# The channel name "irc.oftc.net#qemu" is encrypted against qemu/qemu +# to prevent IRC notifications from forks. This was created using: +# $ travis encrypt -r "qemu/qemu" "irc.oftc.net#qemu" notifications: irc: channels: - - "irc.oftc.net#qemu" + - secure: "F7GDRgjuOo5IUyRLqSkmDL7kvdU4UcH3Lm/W2db2JnDHTGCqgEdaYEYKciyCLZ57vOTsTsOgesN8iUT7hNHBd1KWKjZe9KDTZWppWRYVwAwQMzVeSOsbbU4tRoJ6Pp+3qhH1Z0eGYR9ZgKYAoTumDFgSAYRp4IscKS8jkoedOqM=" on_success: change on_failure: always env: diff --git a/MAINTAINERS b/MAINTAINERS index 83e0f1347d..d1439a8a44 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -971,7 +971,6 @@ F: hw/net/vmxnet* F: hw/scsi/vmw_pvscsi* Rocker -M: Scott Feldman <sfeldma@gmail.com> M: Jiri Pirko <jiri@resnulli.us> S: Maintained F: hw/net/rocker/ @@ -1,5 +1,5 @@ - QEMU README - =========== +QEMU +--- QEMU is a generic and open source machine & userspace emulator and virtualizer. @@ -31,31 +31,31 @@ version 2. For full licensing details, consult the LICENSE file. Building -======== +--- QEMU is multi-platform software intended to be buildable on all modern Linux platforms, OS-X, Win32 (via the Mingw64 toolchain) and a variety of other UNIX targets. The simple steps to build QEMU are: - mkdir build - cd build - ../configure - make + mkdir build + cd build + ../configure + make Complete details of the process for building and configuring QEMU for all supported host platforms can be found in the qemu-tech.html file. Additional information can also be found online via the QEMU website: - http://qemu-project.org/Hosts/Linux - http://qemu-project.org/Hosts/W32 + http://qemu-project.org/Hosts/Linux + http://qemu-project.org/Hosts/W32 Submitting patches -================== +--- The QEMU source code is maintained under the GIT version control system. - git clone git://git.qemu-project.org/qemu.git + git clone git://git.qemu-project.org/qemu.git When submitting patches, the preferred approach is to use 'git format-patch' and/or 'git send-email' to format & send the mail to the @@ -66,18 +66,18 @@ guidelines set out in the HACKING and CODING_STYLE files. Additional information on submitting patches can be found online via the QEMU website - http://qemu-project.org/Contribute/SubmitAPatch - http://qemu-project.org/Contribute/TrivialPatches + http://qemu-project.org/Contribute/SubmitAPatch + http://qemu-project.org/Contribute/TrivialPatches Bug reporting -============= +--- The QEMU project uses Launchpad as its primary upstream bug tracker. Bugs found when running code built from QEMU git or upstream released sources should be reported via: - https://bugs.launchpad.net/qemu/ + https://bugs.launchpad.net/qemu/ If using QEMU via an operating system vendor pre-built binary package, it is preferable to report bugs to the vendor's own bug tracker first. If @@ -86,22 +86,21 @@ reported via launchpad. For additional information on bug reporting consult: - http://qemu-project.org/Contribute/ReportABug + http://qemu-project.org/Contribute/ReportABug Contact -======= +--- The QEMU community can be contacted in a number of ways, with the two main methods being email and IRC - - qemu-devel@nongnu.org - http://lists.nongnu.org/mailman/listinfo/qemu-devel - - #qemu on irc.oftc.net + - Mailing List: qemu-devel@nongnu.org + - Archives: http://lists.nongnu.org/mailman/listinfo/qemu-devel + - IRC: #qemu on irc.oftc.net Information on additional methods of contacting the community can be found online via the QEMU website: http://qemu-project.org/Contribute/StartHere --- End @@ -234,6 +234,8 @@ BlockDriverState *bdrv_new(void) bs->refcnt = 1; bs->aio_context = qemu_get_aio_context(); + qemu_co_queue_init(&bs->flush_queue); + QTAILQ_INSERT_TAIL(&all_bdrv_states, bs, bs_list); return bs; @@ -2472,6 +2474,7 @@ int bdrv_truncate(BlockDriverState *bs, int64_t offset) ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS); bdrv_dirty_bitmap_truncate(bs); bdrv_parent_cb_resize(bs); + ++bs->write_gen; } return ret; } diff --git a/block/io.c b/block/io.c index 2887394633..cfda7148d8 100644 --- a/block/io.c +++ b/block/io.c @@ -1303,6 +1303,7 @@ static int coroutine_fn bdrv_aligned_pwritev(BlockDriverState *bs, } bdrv_debug_event(bs, BLKDBG_PWRITEV_DONE); + ++bs->write_gen; bdrv_set_dirty(bs, start_sector, end_sector - start_sector); if (bs->wr_highest_offset < offset + bytes) { @@ -2236,6 +2237,15 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs) tracked_request_begin(&req, bs, 0, 0, BDRV_TRACKED_FLUSH); + int current_gen = bs->write_gen; + + /* Wait until any previous flushes are completed */ + while (bs->flush_started_gen != bs->flushed_gen) { + qemu_co_queue_wait(&bs->flush_queue); + } + + bs->flush_started_gen = current_gen; + /* Write back all layers by calling one driver function */ if (bs->drv->bdrv_co_flush) { ret = bs->drv->bdrv_co_flush(bs); @@ -2256,6 +2266,11 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs) goto flush_parent; } + /* Check if we really need to flush anything */ + if (bs->flushed_gen == current_gen) { + goto flush_parent; + } + BLKDBG_EVENT(bs->file, BLKDBG_FLUSH_TO_DISK); if (bs->drv->bdrv_co_flush_to_disk) { ret = bs->drv->bdrv_co_flush_to_disk(bs); @@ -2286,6 +2301,7 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs) */ ret = 0; } + if (ret < 0) { goto out; } @@ -2296,6 +2312,10 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs) flush_parent: ret = bs->file ? bdrv_co_flush(bs->file->bs) : 0; out: + /* Notify any pending flushes that we have completed */ + bs->flushed_gen = current_gen; + qemu_co_queue_restart_all(&bs->flush_queue); + tracked_request_end(&req); return ret; } @@ -2421,6 +2441,7 @@ int coroutine_fn bdrv_co_discard(BlockDriverState *bs, int64_t sector_num, } ret = 0; out: + ++bs->write_gen; bdrv_set_dirty(bs, req.offset >> BDRV_SECTOR_BITS, req.bytes >> BDRV_SECTOR_BITS); tracked_request_end(&req); diff --git a/block/iscsi.c b/block/iscsi.c index cf1e9e7f66..129c3afa68 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -2,7 +2,7 @@ * QEMU Block driver for iSCSI images * * Copyright (c) 2010-2011 Ronnie Sahlberg <ronniesahlberg@gmail.com> - * Copyright (c) 2012-2015 Peter Lieven <pl@kamp.de> + * Copyright (c) 2012-2016 Peter Lieven <pl@kamp.de> * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -61,7 +61,23 @@ typedef struct IscsiLun { struct scsi_inquiry_logical_block_provisioning lbp; struct scsi_inquiry_block_limits bl; unsigned char *zeroblock; - unsigned long *allocationmap; + /* The allocmap tracks which clusters (pages) on the iSCSI target are + * allocated and which are not. In case a target returns zeros for + * unallocated pages (iscsilun->lprz) we can directly return zeros instead + * of reading zeros over the wire if a read request falls within an + * unallocated block. As there are 3 possible states we need 2 bitmaps to + * track. allocmap_valid keeps track if QEMU's information about a page is + * valid. allocmap tracks if a page is allocated or not. In case QEMU has no + * valid information about a page the corresponding allocmap entry should be + * switched to unallocated as well to force a new lookup of the allocation + * status as lookups are generally skipped if a page is suspect to be + * allocated. If a iSCSI target is opened with cache.direct = on the + * allocmap_valid does not exist turning all cached information invalid so + * that a fresh lookup is made for any page even if allocmap entry returns + * it's unallocated. */ + unsigned long *allocmap; + unsigned long *allocmap_valid; + long allocmap_size; int cluster_sectors; bool use_16_for_rw; bool write_protected; @@ -422,37 +438,135 @@ static bool is_sector_request_lun_aligned(int64_t sector_num, int nb_sectors, iscsilun); } -static unsigned long *iscsi_allocationmap_init(IscsiLun *iscsilun) +static void iscsi_allocmap_free(IscsiLun *iscsilun) { - return bitmap_try_new(DIV_ROUND_UP(sector_lun2qemu(iscsilun->num_blocks, - iscsilun), - iscsilun->cluster_sectors)); + g_free(iscsilun->allocmap); + g_free(iscsilun->allocmap_valid); + iscsilun->allocmap = NULL; + iscsilun->allocmap_valid = NULL; } -static void iscsi_allocationmap_set(IscsiLun *iscsilun, int64_t sector_num, - int nb_sectors) + +static int iscsi_allocmap_init(IscsiLun *iscsilun, int open_flags) { - if (iscsilun->allocationmap == NULL) { - return; + iscsi_allocmap_free(iscsilun); + + iscsilun->allocmap_size = + DIV_ROUND_UP(sector_lun2qemu(iscsilun->num_blocks, iscsilun), + iscsilun->cluster_sectors); + + iscsilun->allocmap = bitmap_try_new(iscsilun->allocmap_size); + if (!iscsilun->allocmap) { + return -ENOMEM; } - bitmap_set(iscsilun->allocationmap, - sector_num / iscsilun->cluster_sectors, - DIV_ROUND_UP(nb_sectors, iscsilun->cluster_sectors)); + + if (open_flags & BDRV_O_NOCACHE) { + /* in case that cache.direct = on all allocmap entries are + * treated as invalid to force a relookup of the block + * status on every read request */ + return 0; + } + + iscsilun->allocmap_valid = bitmap_try_new(iscsilun->allocmap_size); + if (!iscsilun->allocmap_valid) { + /* if we are under memory pressure free the allocmap as well */ + iscsi_allocmap_free(iscsilun); + return -ENOMEM; + } + + return 0; } -static void iscsi_allocationmap_clear(IscsiLun *iscsilun, int64_t sector_num, - int nb_sectors) +static void +iscsi_allocmap_update(IscsiLun *iscsilun, int64_t sector_num, + int nb_sectors, bool allocated, bool valid) { - int64_t cluster_num, nb_clusters; - if (iscsilun->allocationmap == NULL) { + int64_t cl_num_expanded, nb_cls_expanded, cl_num_shrunk, nb_cls_shrunk; + + if (iscsilun->allocmap == NULL) { return; } - cluster_num = DIV_ROUND_UP(sector_num, iscsilun->cluster_sectors); - nb_clusters = (sector_num + nb_sectors) / iscsilun->cluster_sectors - - cluster_num; - if (nb_clusters > 0) { - bitmap_clear(iscsilun->allocationmap, cluster_num, nb_clusters); + /* expand to entirely contain all affected clusters */ + cl_num_expanded = sector_num / iscsilun->cluster_sectors; + nb_cls_expanded = DIV_ROUND_UP(sector_num + nb_sectors, + iscsilun->cluster_sectors) - cl_num_expanded; + /* shrink to touch only completely contained clusters */ + cl_num_shrunk = DIV_ROUND_UP(sector_num, iscsilun->cluster_sectors); + nb_cls_shrunk = (sector_num + nb_sectors) / iscsilun->cluster_sectors + - cl_num_shrunk; + if (allocated) { + bitmap_set(iscsilun->allocmap, cl_num_expanded, nb_cls_expanded); + } else { + bitmap_clear(iscsilun->allocmap, cl_num_shrunk, nb_cls_shrunk); + } + + if (iscsilun->allocmap_valid == NULL) { + return; + } + if (valid) { + bitmap_set(iscsilun->allocmap_valid, cl_num_shrunk, nb_cls_shrunk); + } else { + bitmap_clear(iscsilun->allocmap_valid, cl_num_expanded, + nb_cls_expanded); + } +} + +static void +iscsi_allocmap_set_allocated(IscsiLun *iscsilun, int64_t sector_num, + int nb_sectors) +{ + iscsi_allocmap_update(iscsilun, sector_num, nb_sectors, true, true); +} + +static void +iscsi_allocmap_set_unallocated(IscsiLun *iscsilun, int64_t sector_num, + int nb_sectors) +{ + /* Note: if cache.direct=on the fifth argument to iscsi_allocmap_update + * is ignored, so this will in effect be an iscsi_allocmap_set_invalid. + */ + iscsi_allocmap_update(iscsilun, sector_num, nb_sectors, false, true); +} + +static void iscsi_allocmap_set_invalid(IscsiLun *iscsilun, int64_t sector_num, + int nb_sectors) +{ + iscsi_allocmap_update(iscsilun, sector_num, nb_sectors, false, false); +} + +static void iscsi_allocmap_invalidate(IscsiLun *iscsilun) +{ + if (iscsilun->allocmap) { + bitmap_zero(iscsilun->allocmap, iscsilun->allocmap_size); + } + if (iscsilun->allocmap_valid) { + bitmap_zero(iscsilun->allocmap_valid, iscsilun->allocmap_size); + } +} + +static inline bool +iscsi_allocmap_is_allocated(IscsiLun *iscsilun, int64_t sector_num, + int nb_sectors) +{ + unsigned long size; + if (iscsilun->allocmap == NULL) { + return true; } + size = DIV_ROUND_UP(sector_num + nb_sectors, iscsilun->cluster_sectors); + return !(find_next_bit(iscsilun->allocmap, size, + sector_num / iscsilun->cluster_sectors) == size); +} + +static inline bool iscsi_allocmap_is_valid(IscsiLun *iscsilun, + int64_t sector_num, int nb_sectors) +{ + unsigned long size; + if (iscsilun->allocmap_valid == NULL) { + return false; + } + size = DIV_ROUND_UP(sector_num + nb_sectors, iscsilun->cluster_sectors); + return (find_next_zero_bit(iscsilun->allocmap_valid, size, + sector_num / iscsilun->cluster_sectors) == size); } static int coroutine_fn @@ -515,26 +629,16 @@ retry: } if (iTask.status != SCSI_STATUS_GOOD) { + iscsi_allocmap_set_invalid(iscsilun, sector_num, nb_sectors); return iTask.err_code; } - iscsi_allocationmap_set(iscsilun, sector_num, nb_sectors); + iscsi_allocmap_set_allocated(iscsilun, sector_num, nb_sectors); return 0; } -static bool iscsi_allocationmap_is_allocated(IscsiLun *iscsilun, - int64_t sector_num, int nb_sectors) -{ - unsigned long size; - if (iscsilun->allocationmap == NULL) { - return true; - } - size = DIV_ROUND_UP(sector_num + nb_sectors, iscsilun->cluster_sectors); - return !(find_next_bit(iscsilun->allocationmap, size, - sector_num / iscsilun->cluster_sectors) == size); -} static int64_t coroutine_fn iscsi_co_get_block_status(BlockDriverState *bs, int64_t sector_num, @@ -619,9 +723,9 @@ retry: } if (ret & BDRV_BLOCK_ZERO) { - iscsi_allocationmap_clear(iscsilun, sector_num, *pnum); + iscsi_allocmap_set_unallocated(iscsilun, sector_num, *pnum); } else { - iscsi_allocationmap_set(iscsilun, sector_num, *pnum); + iscsi_allocmap_set_allocated(iscsilun, sector_num, *pnum); } if (*pnum > nb_sectors) { @@ -657,17 +761,32 @@ static int coroutine_fn iscsi_co_readv(BlockDriverState *bs, return -EINVAL; } - if (iscsilun->lbprz && nb_sectors >= ISCSI_CHECKALLOC_THRES && - !iscsi_allocationmap_is_allocated(iscsilun, sector_num, nb_sectors)) { - int64_t ret; + /* if cache.direct is off and we have a valid entry in our allocation map + * we can skip checking the block status and directly return zeroes if + * the request falls within an unallocated area */ + if (iscsi_allocmap_is_valid(iscsilun, sector_num, nb_sectors) && + !iscsi_allocmap_is_allocated(iscsilun, sector_num, nb_sectors)) { + qemu_iovec_memset(iov, 0, 0x00, iov->size); + return 0; + } + + if (nb_sectors >= ISCSI_CHECKALLOC_THRES && + !iscsi_allocmap_is_valid(iscsilun, sector_num, nb_sectors) && + !iscsi_allocmap_is_allocated(iscsilun, sector_num, nb_sectors)) { int pnum; BlockDriverState *file; - ret = iscsi_co_get_block_status(bs, sector_num, - BDRV_REQUEST_MAX_SECTORS, &pnum, &file); + /* check the block status from the beginning of the cluster + * containing the start sector */ + int64_t ret = iscsi_co_get_block_status(bs, + sector_num - sector_num % iscsilun->cluster_sectors, + BDRV_REQUEST_MAX_SECTORS, &pnum, &file); if (ret < 0) { return ret; } - if (ret & BDRV_BLOCK_ZERO && pnum >= nb_sectors) { + /* if the whole request falls into an unallocated area we can avoid + * to read and directly return zeroes instead */ + if (ret & BDRV_BLOCK_ZERO && + pnum >= nb_sectors + sector_num % iscsilun->cluster_sectors) { qemu_iovec_memset(iov, 0, 0x00, iov->size); return 0; } @@ -981,7 +1100,7 @@ retry: return iTask.err_code; } - iscsi_allocationmap_clear(iscsilun, sector_num, nb_sectors); + iscsi_allocmap_set_invalid(iscsilun, sector_num, nb_sectors); return 0; } @@ -1071,15 +1190,17 @@ retry: } if (iTask.status != SCSI_STATUS_GOOD) { + iscsi_allocmap_set_invalid(iscsilun, offset >> BDRV_SECTOR_BITS, + count >> BDRV_SECTOR_BITS); return iTask.err_code; } if (flags & BDRV_REQ_MAY_UNMAP) { - iscsi_allocationmap_clear(iscsilun, offset >> BDRV_SECTOR_BITS, - count >> BDRV_SECTOR_BITS); + iscsi_allocmap_set_invalid(iscsilun, offset >> BDRV_SECTOR_BITS, + count >> BDRV_SECTOR_BITS); } else { - iscsi_allocationmap_set(iscsilun, offset >> BDRV_SECTOR_BITS, - count >> BDRV_SECTOR_BITS); + iscsi_allocmap_set_allocated(iscsilun, offset >> BDRV_SECTOR_BITS, + count >> BDRV_SECTOR_BITS); } return 0; @@ -1652,10 +1773,7 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags, iscsilun->cluster_sectors = (iscsilun->bl.opt_unmap_gran * iscsilun->block_size) >> BDRV_SECTOR_BITS; if (iscsilun->lbprz) { - iscsilun->allocationmap = iscsi_allocationmap_init(iscsilun); - if (iscsilun->allocationmap == NULL) { - ret = -ENOMEM; - } + ret = iscsi_allocmap_init(iscsilun, bs->open_flags); } } @@ -1692,7 +1810,7 @@ static void iscsi_close(BlockDriverState *bs) } iscsi_destroy_context(iscsi); g_free(iscsilun->zeroblock); - g_free(iscsilun->allocationmap); + iscsi_allocmap_free(iscsilun); memset(iscsilun, 0, sizeof(IscsiLun)); } @@ -1756,6 +1874,16 @@ static int iscsi_reopen_prepare(BDRVReopenState *state, return 0; } +static void iscsi_reopen_commit(BDRVReopenState *reopen_state) +{ + IscsiLun *iscsilun = reopen_state->bs->opaque; + + /* the cache.direct status might have changed */ + if (iscsilun->allocmap != NULL) { + iscsi_allocmap_init(iscsilun, reopen_state->flags); + } +} + static int iscsi_truncate(BlockDriverState *bs, int64_t offset) { IscsiLun *iscsilun = bs->opaque; @@ -1775,9 +1903,8 @@ static int iscsi_truncate(BlockDriverState *bs, int64_t offset) return -EINVAL; } - if (iscsilun->allocationmap != NULL) { - g_free(iscsilun->allocationmap); - iscsilun->allocationmap = iscsi_allocationmap_init(iscsilun); + if (iscsilun->allocmap != NULL) { + iscsi_allocmap_init(iscsilun, bs->open_flags); } return 0; @@ -1837,6 +1964,13 @@ static int iscsi_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) return 0; } +static void iscsi_invalidate_cache(BlockDriverState *bs, + Error **errp) +{ + IscsiLun *iscsilun = bs->opaque; + iscsi_allocmap_invalidate(iscsilun); +} + static QemuOptsList iscsi_create_opts = { .name = "iscsi-create-opts", .head = QTAILQ_HEAD_INITIALIZER(iscsi_create_opts.head), @@ -1860,7 +1994,9 @@ static BlockDriver bdrv_iscsi = { .bdrv_close = iscsi_close, .bdrv_create = iscsi_create, .create_opts = &iscsi_create_opts, - .bdrv_reopen_prepare = iscsi_reopen_prepare, + .bdrv_reopen_prepare = iscsi_reopen_prepare, + .bdrv_reopen_commit = iscsi_reopen_commit, + .bdrv_invalidate_cache = iscsi_invalidate_cache, .bdrv_getlength = iscsi_getlength, .bdrv_get_info = iscsi_get_info, diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h index 53163b8a47..6ccc544e7d 100644 --- a/bsd-user/qemu.h +++ b/bsd-user/qemu.h @@ -358,7 +358,7 @@ static inline void *lock_user(int type, abi_ulong guest_addr, long len, int copy #ifdef DEBUG_REMAP { void *addr; - addr = malloc(len); + addr = g_malloc(len); if (copy) memcpy(addr, g2h(guest_addr), len); else @@ -384,7 +384,7 @@ static inline void unlock_user(void *host_ptr, abi_ulong guest_addr, return; if (len > 0) memcpy(g2h(guest_addr), host_ptr, len); - free(host_ptr); + g_free(host_ptr); #endif } diff --git a/cpu-exec.c b/cpu-exec.c index b840e1d2dd..5d9710a1ea 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -608,17 +608,16 @@ int cpu_exec(CPUState *cpu) init_delay_params(&sc, cpu); for(;;) { - TranslationBlock *tb, *last_tb; - int tb_exit = 0; - /* prepare setjmp context for exception handling */ if (sigsetjmp(cpu->jmp_env, 0) == 0) { + TranslationBlock *tb, *last_tb = NULL; + int tb_exit = 0; + /* if an exception is pending, we execute it here */ if (cpu_handle_exception(cpu, &ret)) { break; } - last_tb = NULL; /* forget the last executed TB after exception */ cpu->tb_flushed = false; /* reset before first TB lookup */ for(;;) { cpu_handle_interrupt(cpu, &last_tb); diff --git a/disas/arm.c b/disas/arm.c index 32f8ca992f..426270fe82 100644 --- a/disas/arm.c +++ b/disas/arm.c @@ -24,7 +24,6 @@ #include "qemu/osdep.h" #include "disas/bfd.h" -#define ATTRIBUTE_UNUSED __attribute__((unused)) #define ISSPACE(x) ((x) == ' ' || (x) == '\t' || (x) == '\n') #define ARM_EXT_V1 0 @@ -187,10 +187,12 @@ struct CPUAddressSpace { static void phys_map_node_reserve(PhysPageMap *map, unsigned nodes) { + static unsigned alloc_hint = 16; if (map->nodes_nb + nodes > map->nodes_nb_alloc) { - map->nodes_nb_alloc = MAX(map->nodes_nb_alloc * 2, 16); + map->nodes_nb_alloc = MAX(map->nodes_nb_alloc, alloc_hint); map->nodes_nb_alloc = MAX(map->nodes_nb_alloc, map->nodes_nb + nodes); map->nodes = g_renew(Node, map->nodes, map->nodes_nb_alloc); + alloc_hint = map->nodes_nb_alloc; } } diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 1b8baa8fee..719884ff88 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -812,11 +812,26 @@ static long get_file_size(FILE *f) return size; } +/* setup_data types */ +#define SETUP_NONE 0 +#define SETUP_E820_EXT 1 +#define SETUP_DTB 2 +#define SETUP_PCI 3 +#define SETUP_EFI 4 + +struct setup_data { + uint64_t next; + uint32_t type; + uint32_t len; + uint8_t data[0]; +} __attribute__((packed)); + static void load_linux(PCMachineState *pcms, FWCfgState *fw_cfg) { uint16_t protocol; int setup_size, kernel_size, initrd_size = 0, cmdline_size; + int dtb_size, setup_data_offset; uint32_t initrd_max; uint8_t header[8192], *setup, *kernel, *initrd_data; hwaddr real_addr, prot_addr, cmdline_addr, initrd_addr = 0; @@ -824,8 +839,10 @@ static void load_linux(PCMachineState *pcms, char *vmode; MachineState *machine = MACHINE(pcms); PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms); + struct setup_data *setup_data; const char *kernel_filename = machine->kernel_filename; const char *initrd_filename = machine->initrd_filename; + const char *dtb_filename = machine->dtb; const char *kernel_cmdline = machine->kernel_cmdline; /* Align to 16 bytes as a paranoia measure */ @@ -988,6 +1005,35 @@ static void load_linux(PCMachineState *pcms, exit(1); } fclose(f); + + /* append dtb to kernel */ + if (dtb_filename) { + if (protocol < 0x209) { + fprintf(stderr, "qemu: Linux kernel too old to load a dtb\n"); + exit(1); + } + + dtb_size = get_image_size(dtb_filename); + if (dtb_size <= 0) { + fprintf(stderr, "qemu: error reading dtb %s: %s\n", + dtb_filename, strerror(errno)); + exit(1); + } + + setup_data_offset = QEMU_ALIGN_UP(kernel_size, 16); + kernel_size = setup_data_offset + sizeof(struct setup_data) + dtb_size; + kernel = g_realloc(kernel, kernel_size); + + stq_p(header+0x250, prot_addr + setup_data_offset); + + setup_data = (struct setup_data *)(kernel + setup_data_offset); + setup_data->next = 0; + setup_data->type = cpu_to_le32(SETUP_DTB); + setup_data->len = cpu_to_le32(dtb_size); + + load_image_size(dtb_filename, setup_data->data, dtb_size); + } + memcpy(setup, header, MIN(sizeof(header), setup_size)); fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, prot_addr); diff --git a/hw/ide/core.c b/hw/ide/core.c index f2d131b0d3..b1daf967d6 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -466,6 +466,20 @@ void ide_abort_command(IDEState *s) s->error = ABRT_ERR; } +static void ide_set_retry(IDEState *s) +{ + s->bus->retry_unit = s->unit; + s->bus->retry_sector_num = ide_get_sector(s); + s->bus->retry_nsector = s->nsector; +} + +static void ide_clear_retry(IDEState *s) +{ + s->bus->retry_unit = -1; + s->bus->retry_sector_num = 0; + s->bus->retry_nsector = 0; +} + /* prepare data transfer and tell what to do after */ void ide_transfer_start(IDEState *s, uint8_t *buf, int size, EndTransferFunc *end_transfer_func) @@ -473,6 +487,7 @@ void ide_transfer_start(IDEState *s, uint8_t *buf, int size, s->end_transfer_func = end_transfer_func; s->data_ptr = buf; s->data_end = buf + size; + ide_set_retry(s); if (!(s->status & ERR_STAT)) { s->status |= DRQ_STAT; } @@ -756,9 +771,7 @@ void dma_buf_commit(IDEState *s, uint32_t tx_bytes) void ide_set_inactive(IDEState *s, bool more) { s->bus->dma->aiocb = NULL; - s->bus->retry_unit = -1; - s->bus->retry_sector_num = 0; - s->bus->retry_nsector = 0; + ide_clear_retry(s); if (s->bus->dma->ops->set_inactive) { s->bus->dma->ops->set_inactive(s->bus->dma, more); } @@ -914,9 +927,7 @@ static void ide_sector_start_dma(IDEState *s, enum ide_dma_cmd dma_cmd) void ide_start_dma(IDEState *s, BlockCompletionFunc *cb) { s->io_buffer_index = 0; - s->bus->retry_unit = s->unit; - s->bus->retry_sector_num = ide_get_sector(s); - s->bus->retry_nsector = s->nsector; + ide_set_retry(s); if (s->bus->dma->ops->start_dma) { s->bus->dma->ops->start_dma(s->bus->dma, s, cb); } @@ -1046,6 +1057,7 @@ static void ide_flush_cache(IDEState *s) } s->status |= BUSY_STAT; + ide_set_retry(s); block_acct_start(blk_get_stats(s->blk), &s->acct, 0, BLOCK_ACCT_FLUSH); s->pio_aiocb = blk_aio_flush(s->blk, ide_flush_cb, s); } diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c index 2f60096e6e..77e5cfa327 100644 --- a/hw/intc/arm_gicv3_redist.c +++ b/hw/intc/arm_gicv3_redist.c @@ -420,6 +420,8 @@ MemTxResult gicv3_redist_read(void *opaque, hwaddr offset, uint64_t *data, MemTxResult r; int cpuidx; + assert((offset & (size - 1)) == 0); + /* This region covers all the redistributor pages; there are * (for GICv3) two 64K pages per CPU. At the moment they are * all contiguous (ie in this one region), though we might later @@ -468,6 +470,8 @@ MemTxResult gicv3_redist_write(void *opaque, hwaddr offset, uint64_t data, MemTxResult r; int cpuidx; + assert((offset & (size - 1)) == 0); + /* This region covers all the redistributor pages; there are * (for GICv3) two 64K pages per CPU. At the moment they are * all contiguous (ie in this one region), though we might later diff --git a/hw/net/Makefile.objs b/hw/net/Makefile.objs index fe61e9fb2b..610ed3e7ae 100644 --- a/hw/net/Makefile.objs +++ b/hw/net/Makefile.objs @@ -7,6 +7,7 @@ common-obj-$(CONFIG_EEPRO100_PCI) += eepro100.o common-obj-$(CONFIG_PCNET_PCI) += pcnet-pci.o common-obj-$(CONFIG_PCNET_COMMON) += pcnet.o common-obj-$(CONFIG_E1000_PCI) += e1000.o e1000x_common.o +common-obj-$(CONFIG_E1000E_PCI) += net_tx_pkt.o net_rx_pkt.o common-obj-$(CONFIG_E1000E_PCI) += e1000e.o e1000e_core.o e1000x_common.o common-obj-$(CONFIG_RTL8139_PCI) += rtl8139.o common-obj-$(CONFIG_VMXNET3_PCI) += net_tx_pkt.o net_rx_pkt.o diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c index 6050d8b7f8..badb1feb7d 100644 --- a/hw/net/e1000e_core.c +++ b/hw/net/e1000e_core.c @@ -281,7 +281,7 @@ e1000e_intrmgr_delay_rx_causes(E1000ECore *core, uint32_t *causes) /* Check if delayed RX interrupts disabled by client or if there are causes that cannot be delayed */ - if ((rdtr == 0) || (causes != 0)) { + if ((rdtr == 0) || (*causes != 0)) { return false; } @@ -322,7 +322,7 @@ e1000e_intrmgr_delay_tx_causes(E1000ECore *core, uint32_t *causes) *causes &= ~delayable_causes; /* If there are causes that cannot be delayed */ - if (causes != 0) { + if (*causes != 0) { return false; } diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c index 52a41239cf..e968302fdc 100644 --- a/hw/scsi/megasas.c +++ b/hw/scsi/megasas.c @@ -1981,11 +1981,7 @@ static void megasas_handle_frame(MegasasState *s, uint64_t frame_addr, break; } if (frame_status != MFI_STAT_INVALID_STATUS) { - if (cmd->frame) { - cmd->frame->header.cmd_status = frame_status; - } else { - megasas_frame_set_cmd_status(s, frame_addr, frame_status); - } + cmd->frame->header.cmd_status = frame_status; megasas_unmap_frame(s, cmd); megasas_complete_frame(s, cmd->context); } diff --git a/include/block/block_int.h b/include/block/block_int.h index 805414619d..a6b13adb45 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -439,6 +439,11 @@ struct BlockDriverState { int copy_on_read; /* if nonzero, copy read backing sectors into image. note this is a reference count */ + CoQueue flush_queue; /* Serializing flush queue */ + unsigned int write_gen; /* Current data generation */ + unsigned int flush_started_gen; /* Generation for which flush has started */ + unsigned int flushed_gen; /* Flushed write generation */ + BlockDriver *drv; /* NULL means no media */ void *opaque; diff --git a/include/disas/bfd.h b/include/disas/bfd.h index 231e5fbf91..8a3488c2c5 100644 --- a/include/disas/bfd.h +++ b/include/disas/bfd.h @@ -477,7 +477,9 @@ int generic_symbol_at_address(bfd_vma, struct disassemble_info *); (INFO).disassembler_options = NULL, \ (INFO).insn_info_valid = 0 +#ifndef ATTRIBUTE_UNUSED #define ATTRIBUTE_UNUSED __attribute__((unused)) +#endif /* from libbfd */ diff --git a/include/qemu/compiler.h b/include/qemu/compiler.h index b64f899870..338d3a65b3 100644 --- a/include/qemu/compiler.h +++ b/include/qemu/compiler.h @@ -3,6 +3,9 @@ #ifndef COMPILER_H #define COMPILER_H +#if defined __clang_analyzer__ || defined __COVERITY__ +#define QEMU_STATIC_ANALYSIS 1 +#endif /*---------------------------------------------------------------------------- | The macro QEMU_GNUC_PREREQ tests for minimum version of the GNU C compiler. diff --git a/linux-user/aarch64/syscall_nr.h b/linux-user/aarch64/syscall_nr.h index 59511d855d..a3c9a3b679 100644 --- a/linux-user/aarch64/syscall_nr.h +++ b/linux-user/aarch64/syscall_nr.h @@ -86,8 +86,7 @@ #define TARGET_NR_sync 81 #define TARGET_NR_fsync 82 #define TARGET_NR_fdatasync 83 -#define TARGET_NR_sync_file_range2 84 -/* #define TARGET_NR_sync_file_range 84 */ +#define TARGET_NR_sync_file_range 84 #define TARGET_NR_timerfd_create 85 #define TARGET_NR_timerfd_settime 86 #define TARGET_NR_timerfd_gettime 87 diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h index e672655100..7e2c133ba1 100644 --- a/linux-user/ioctls.h +++ b/linux-user/ioctls.h @@ -76,10 +76,39 @@ IOCTL(BLKFLSBUF, 0, TYPE_NULL) IOCTL(BLKRASET, 0, TYPE_INT) IOCTL(BLKRAGET, IOC_R, MK_PTR(TYPE_LONG)) - IOCTL(BLKSSZGET, IOC_R, MK_PTR(TYPE_LONG)) + IOCTL(BLKSSZGET, IOC_R, MK_PTR(TYPE_INT)) IOCTL(BLKBSZGET, IOC_R, MK_PTR(TYPE_INT)) IOCTL_SPECIAL(BLKPG, IOC_W, do_ioctl_blkpg, MK_PTR(MK_STRUCT(STRUCT_blkpg_ioctl_arg))) + +#ifdef BLKDISCARD + IOCTL(BLKDISCARD, IOC_W, MK_PTR(MK_ARRAY(TYPE_ULONGLONG, 2))) +#endif +#ifdef BLKIOMIN + IOCTL(BLKIOMIN, IOC_R, MK_PTR(TYPE_INT)) +#endif +#ifdef BLKIOOPT + IOCTL(BLKIOOPT, IOC_R, MK_PTR(TYPE_INT)) +#endif +#ifdef BLKALIGNOFF + IOCTL(BLKALIGNOFF, IOC_R, MK_PTR(TYPE_INT)) +#endif +#ifdef BLKPBSZGET + IOCTL(BLKPBSZGET, IOC_R, MK_PTR(TYPE_INT)) +#endif +#ifdef BLKDISCARDZEROES + IOCTL(BLKDISCARDZEROES, IOC_R, MK_PTR(TYPE_INT)) +#endif +#ifdef BLKSECDISCARD + IOCTL(BLKSECDISCARD, IOC_W, MK_PTR(MK_ARRAY(TYPE_ULONGLONG, 2))) +#endif +#ifdef BLKROTATIONAL + IOCTL(BLKROTATIONAL, IOC_R, MK_PTR(TYPE_SHORT)) +#endif +#ifdef BLKZEROOUT + IOCTL(BLKZEROOUT, IOC_W, MK_PTR(MK_ARRAY(TYPE_ULONGLONG, 2))) +#endif + #ifdef FIBMAP IOCTL(FIBMAP, IOC_W | IOC_R, MK_PTR(TYPE_LONG)) #endif @@ -91,7 +120,7 @@ MK_PTR(MK_STRUCT(STRUCT_fiemap))) #endif - IOCTL(SIOCATMARK, 0, TYPE_NULL) + IOCTL(SIOCATMARK, IOC_R, MK_PTR(TYPE_INT)) IOCTL(SIOCGIFNAME, IOC_RW, MK_PTR(TYPE_INT)) IOCTL(SIOCGIFFLAGS, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_short_ifreq))) IOCTL(SIOCSIFFLAGS, IOC_W, MK_PTR(MK_STRUCT(STRUCT_short_ifreq))) @@ -322,11 +351,15 @@ IOCTL(LOOP_SET_FD, 0, TYPE_INT) IOCTL(LOOP_CLR_FD, 0, TYPE_INT) IOCTL(LOOP_SET_STATUS, IOC_W, MK_PTR(MK_STRUCT(STRUCT_loop_info))) - IOCTL(LOOP_GET_STATUS, IOC_W, MK_PTR(MK_STRUCT(STRUCT_loop_info))) + IOCTL(LOOP_GET_STATUS, IOC_R, MK_PTR(MK_STRUCT(STRUCT_loop_info))) IOCTL(LOOP_SET_STATUS64, IOC_W, MK_PTR(MK_STRUCT(STRUCT_loop_info64))) - IOCTL(LOOP_GET_STATUS64, IOC_W, MK_PTR(MK_STRUCT(STRUCT_loop_info64))) + IOCTL(LOOP_GET_STATUS64, IOC_R, MK_PTR(MK_STRUCT(STRUCT_loop_info64))) IOCTL(LOOP_CHANGE_FD, 0, TYPE_INT) + IOCTL(LOOP_CTL_ADD, 0, TYPE_INT) + IOCTL(LOOP_CTL_REMOVE, 0, TYPE_INT) + IOCTL(LOOP_CTL_GET_FREE, 0, TYPE_NULL) + IOCTL(MTIOCTOP, IOC_W, MK_PTR(MK_STRUCT(STRUCT_mtop))) IOCTL(MTIOCGET, IOC_R, MK_PTR(MK_STRUCT(STRUCT_mtget))) IOCTL(MTIOCPOS, IOC_R, MK_PTR(MK_STRUCT(STRUCT_mtpos))) diff --git a/linux-user/linux_loop.h b/linux-user/linux_loop.h index 1f52403814..c69fea11e4 100644 --- a/linux-user/linux_loop.h +++ b/linux-user/linux_loop.h @@ -1,4 +1,6 @@ -/* Copied from 2.6.25 kernel headers to avoid problems on older hosts. */ +/* Copied from 2.6.25 kernel headers to avoid problems on older hosts, + * and subsequently updated to match newer additions to the API. + */ #ifndef LINUX_LOOP_H #define LINUX_LOOP_H @@ -92,5 +94,12 @@ struct loop_info64 { #define LOOP_SET_STATUS64 0x4C04 #define LOOP_GET_STATUS64 0x4C05 #define LOOP_CHANGE_FD 0x4C06 +#define LOOP_SET_CAPACITY 0x4C07 +#define LOOP_SET_DIRECT_IO 0x4C08 + +/* /dev/loop-control interface */ +#define LOOP_CTL_ADD 0x4C80 +#define LOOP_CTL_REMOVE 0x4C81 +#define LOOP_CTL_GET_FREE 0x4C82 #endif diff --git a/linux-user/signal.c b/linux-user/signal.c index 9d980456ec..9a4d894e3a 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -5826,7 +5826,8 @@ long do_rt_sigreturn(CPUArchState *env) #endif -static void handle_pending_signal(CPUArchState *cpu_env, int sig) +static void handle_pending_signal(CPUArchState *cpu_env, int sig, + struct emulated_sigtable *k) { CPUState *cpu = ENV_GET_CPU(cpu_env); abi_ulong handler; @@ -5834,7 +5835,6 @@ static void handle_pending_signal(CPUArchState *cpu_env, int sig) target_sigset_t target_old_set; struct target_sigaction *sa; TaskState *ts = cpu->opaque; - struct emulated_sigtable *k = &ts->sigtab[sig - 1]; trace_user_handle_signal(cpu_env, sig); /* dequeue signal */ @@ -5937,7 +5937,7 @@ void process_pending_signals(CPUArchState *cpu_env) sigact_table[sig - 1]._sa_handler = TARGET_SIG_DFL; } - handle_pending_signal(cpu_env, sig); + handle_pending_signal(cpu_env, sig, &ts->sync_signal); } for (sig = 1; sig <= TARGET_NSIG; sig++) { @@ -5947,7 +5947,7 @@ void process_pending_signals(CPUArchState *cpu_env) if (ts->sigtab[sig - 1].pending && (!sigismember(blocked_set, target_to_host_signal_table[sig]))) { - handle_pending_signal(cpu_env, sig); + handle_pending_signal(cpu_env, sig, &ts->sigtab[sig - 1]); /* Restart scan from the beginning */ sig = 1; } diff --git a/linux-user/sparc/syscall_nr.h b/linux-user/sparc/syscall_nr.h index 732b1052a4..e713c9d5f4 100644 --- a/linux-user/sparc/syscall_nr.h +++ b/linux-user/sparc/syscall_nr.h @@ -179,6 +179,9 @@ #define TARGET_NR_readahead 205 /* Linux Specific */ #define TARGET_NR_socketcall 206 /* Linux Specific */ #define TARGET_NR_syslog 207 /* Linux Specific */ +#define TARGET_NR_lookup_dcookie 208 /* Linux Specific */ +#define TARGET_NR_fadvise64 209 /* Linux Specific */ +#define TARGET_NR_fadvise64_64 210 /* Linux Specific */ #define TARGET_NR_tgkill 211 /* Linux Specific */ #define TARGET_NR_waitpid 212 /* Linux Specific */ #define TARGET_NR_swapoff 213 /* Linux Specific */ diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 8bf6205dc2..ca6a2b495a 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -100,9 +100,11 @@ int __clone2(int (*fn)(void *), void *child_stack_base, #include <linux/route.h> #include <linux/filter.h> #include <linux/blkpg.h> +#include <netpacket/packet.h> #include <linux/netlink.h> #ifdef CONFIG_RTNETLINK #include <linux/rtnetlink.h> +#include <linux/if_bridge.h> #endif #include <linux/audit.h> #include "linux_loop.h" @@ -1374,15 +1376,26 @@ static inline abi_long host_to_target_sockaddr(abi_ulong target_addr, { struct target_sockaddr *target_saddr; + if (len == 0) { + return 0; + } + target_saddr = lock_user(VERIFY_WRITE, target_addr, len, 0); if (!target_saddr) return -TARGET_EFAULT; memcpy(target_saddr, addr, len); - target_saddr->sa_family = tswap16(addr->sa_family); - if (addr->sa_family == AF_NETLINK) { + if (len >= offsetof(struct target_sockaddr, sa_family) + + sizeof(target_saddr->sa_family)) { + target_saddr->sa_family = tswap16(addr->sa_family); + } + if (addr->sa_family == AF_NETLINK && len >= sizeof(struct sockaddr_nl)) { struct sockaddr_nl *target_nl = (struct sockaddr_nl *)target_saddr; target_nl->nl_pid = tswap32(target_nl->nl_pid); target_nl->nl_groups = tswap32(target_nl->nl_groups); + } else if (addr->sa_family == AF_PACKET) { + struct sockaddr_ll *target_ll = (struct sockaddr_ll *)target_saddr; + target_ll->sll_ifindex = tswap32(target_ll->sll_ifindex); + target_ll->sll_hatype = tswap16(target_ll->sll_hatype); } unlock_user(target_saddr, target_addr, len); @@ -1707,6 +1720,33 @@ static abi_long target_to_host_for_each_nlmsg(struct nlmsghdr *nlh, } #ifdef CONFIG_RTNETLINK +static abi_long host_to_target_for_each_nlattr(struct nlattr *nlattr, + size_t len, void *context, + abi_long (*host_to_target_nlattr) + (struct nlattr *, + void *context)) +{ + unsigned short nla_len; + abi_long ret; + + while (len > sizeof(struct nlattr)) { + nla_len = nlattr->nla_len; + if (nla_len < sizeof(struct nlattr) || + nla_len > len) { + break; + } + ret = host_to_target_nlattr(nlattr, context); + nlattr->nla_len = tswap16(nlattr->nla_len); + nlattr->nla_type = tswap16(nlattr->nla_type); + if (ret < 0) { + return ret; + } + len -= NLA_ALIGN(nla_len); + nlattr = (struct nlattr *)(((char *)nlattr) + NLA_ALIGN(nla_len)); + } + return 0; +} + static abi_long host_to_target_for_each_rtattr(struct rtattr *rtattr, size_t len, abi_long (*host_to_target_rtattr) @@ -1733,12 +1773,292 @@ static abi_long host_to_target_for_each_rtattr(struct rtattr *rtattr, return 0; } +#define NLA_DATA(nla) ((void *)((char *)(nla)) + NLA_HDRLEN) + +static abi_long host_to_target_data_bridge_nlattr(struct nlattr *nlattr, + void *context) +{ + uint16_t *u16; + uint32_t *u32; + uint64_t *u64; + + switch (nlattr->nla_type) { + /* no data */ + case IFLA_BR_FDB_FLUSH: + break; + /* binary */ + case IFLA_BR_GROUP_ADDR: + break; + /* uint8_t */ + case IFLA_BR_VLAN_FILTERING: + case IFLA_BR_TOPOLOGY_CHANGE: + case IFLA_BR_TOPOLOGY_CHANGE_DETECTED: + case IFLA_BR_MCAST_ROUTER: + case IFLA_BR_MCAST_SNOOPING: + case IFLA_BR_MCAST_QUERY_USE_IFADDR: + case IFLA_BR_MCAST_QUERIER: + case IFLA_BR_NF_CALL_IPTABLES: + case IFLA_BR_NF_CALL_IP6TABLES: + case IFLA_BR_NF_CALL_ARPTABLES: + break; + /* uint16_t */ + case IFLA_BR_PRIORITY: + case IFLA_BR_VLAN_PROTOCOL: + case IFLA_BR_GROUP_FWD_MASK: + case IFLA_BR_ROOT_PORT: + case IFLA_BR_VLAN_DEFAULT_PVID: + u16 = NLA_DATA(nlattr); + *u16 = tswap16(*u16); + break; + /* uint32_t */ + case IFLA_BR_FORWARD_DELAY: + case IFLA_BR_HELLO_TIME: + case IFLA_BR_MAX_AGE: + case IFLA_BR_AGEING_TIME: + case IFLA_BR_STP_STATE: + case IFLA_BR_ROOT_PATH_COST: + case IFLA_BR_MCAST_HASH_ELASTICITY: + case IFLA_BR_MCAST_HASH_MAX: + case IFLA_BR_MCAST_LAST_MEMBER_CNT: + case IFLA_BR_MCAST_STARTUP_QUERY_CNT: + u32 = NLA_DATA(nlattr); + *u32 = tswap32(*u32); + break; + /* uint64_t */ + case IFLA_BR_HELLO_TIMER: + case IFLA_BR_TCN_TIMER: + case IFLA_BR_GC_TIMER: + case IFLA_BR_TOPOLOGY_CHANGE_TIMER: + case IFLA_BR_MCAST_LAST_MEMBER_INTVL: + case IFLA_BR_MCAST_MEMBERSHIP_INTVL: + case IFLA_BR_MCAST_QUERIER_INTVL: + case IFLA_BR_MCAST_QUERY_INTVL: + case IFLA_BR_MCAST_QUERY_RESPONSE_INTVL: + case IFLA_BR_MCAST_STARTUP_QUERY_INTVL: + u64 = NLA_DATA(nlattr); + *u64 = tswap64(*u64); + break; + /* ifla_bridge_id: uin8_t[] */ + case IFLA_BR_ROOT_ID: + case IFLA_BR_BRIDGE_ID: + break; + default: + gemu_log("Unknown IFLA_BR type %d\n", nlattr->nla_type); + break; + } + return 0; +} + +static abi_long host_to_target_slave_data_bridge_nlattr(struct nlattr *nlattr, + void *context) +{ + uint16_t *u16; + uint32_t *u32; + uint64_t *u64; + + switch (nlattr->nla_type) { + /* uint8_t */ + case IFLA_BRPORT_STATE: + case IFLA_BRPORT_MODE: + case IFLA_BRPORT_GUARD: + case IFLA_BRPORT_PROTECT: + case IFLA_BRPORT_FAST_LEAVE: + case IFLA_BRPORT_LEARNING: + case IFLA_BRPORT_UNICAST_FLOOD: + case IFLA_BRPORT_PROXYARP: + case IFLA_BRPORT_LEARNING_SYNC: + case IFLA_BRPORT_PROXYARP_WIFI: + case IFLA_BRPORT_TOPOLOGY_CHANGE_ACK: + case IFLA_BRPORT_CONFIG_PENDING: + case IFLA_BRPORT_MULTICAST_ROUTER: + break; + /* uint16_t */ + case IFLA_BRPORT_PRIORITY: + case IFLA_BRPORT_DESIGNATED_PORT: + case IFLA_BRPORT_DESIGNATED_COST: + case IFLA_BRPORT_ID: + case IFLA_BRPORT_NO: + u16 = NLA_DATA(nlattr); + *u16 = tswap16(*u16); + break; + /* uin32_t */ + case IFLA_BRPORT_COST: + u32 = NLA_DATA(nlattr); + *u32 = tswap32(*u32); + break; + /* uint64_t */ + case IFLA_BRPORT_MESSAGE_AGE_TIMER: + case IFLA_BRPORT_FORWARD_DELAY_TIMER: + case IFLA_BRPORT_HOLD_TIMER: + u64 = NLA_DATA(nlattr); + *u64 = tswap64(*u64); + break; + /* ifla_bridge_id: uint8_t[] */ + case IFLA_BRPORT_ROOT_ID: + case IFLA_BRPORT_BRIDGE_ID: + break; + default: + gemu_log("Unknown IFLA_BRPORT type %d\n", nlattr->nla_type); + break; + } + return 0; +} + +struct linkinfo_context { + int len; + char *name; + int slave_len; + char *slave_name; +}; + +static abi_long host_to_target_data_linkinfo_nlattr(struct nlattr *nlattr, + void *context) +{ + struct linkinfo_context *li_context = context; + + switch (nlattr->nla_type) { + /* string */ + case IFLA_INFO_KIND: + li_context->name = NLA_DATA(nlattr); + li_context->len = nlattr->nla_len - NLA_HDRLEN; + break; + case IFLA_INFO_SLAVE_KIND: + li_context->slave_name = NLA_DATA(nlattr); + li_context->slave_len = nlattr->nla_len - NLA_HDRLEN; + break; + /* stats */ + case IFLA_INFO_XSTATS: + /* FIXME: only used by CAN */ + break; + /* nested */ + case IFLA_INFO_DATA: + if (strncmp(li_context->name, "bridge", + li_context->len) == 0) { + return host_to_target_for_each_nlattr(NLA_DATA(nlattr), + nlattr->nla_len, + NULL, + host_to_target_data_bridge_nlattr); + } else { + gemu_log("Unknown IFLA_INFO_KIND %s\n", li_context->name); + } + break; + case IFLA_INFO_SLAVE_DATA: + if (strncmp(li_context->slave_name, "bridge", + li_context->slave_len) == 0) { + return host_to_target_for_each_nlattr(NLA_DATA(nlattr), + nlattr->nla_len, + NULL, + host_to_target_slave_data_bridge_nlattr); + } else { + gemu_log("Unknown IFLA_INFO_SLAVE_KIND %s\n", + li_context->slave_name); + } + break; + default: + gemu_log("Unknown host IFLA_INFO type: %d\n", nlattr->nla_type); + break; + } + + return 0; +} + +static abi_long host_to_target_data_inet_nlattr(struct nlattr *nlattr, + void *context) +{ + uint32_t *u32; + int i; + + switch (nlattr->nla_type) { + case IFLA_INET_CONF: + u32 = NLA_DATA(nlattr); + for (i = 0; i < (nlattr->nla_len - NLA_HDRLEN) / sizeof(*u32); + i++) { + u32[i] = tswap32(u32[i]); + } + break; + default: + gemu_log("Unknown host AF_INET type: %d\n", nlattr->nla_type); + } + return 0; +} + +static abi_long host_to_target_data_inet6_nlattr(struct nlattr *nlattr, + void *context) +{ + uint32_t *u32; + uint64_t *u64; + struct ifla_cacheinfo *ci; + int i; + + switch (nlattr->nla_type) { + /* binaries */ + case IFLA_INET6_TOKEN: + break; + /* uint8_t */ + case IFLA_INET6_ADDR_GEN_MODE: + break; + /* uint32_t */ + case IFLA_INET6_FLAGS: + u32 = NLA_DATA(nlattr); + *u32 = tswap32(*u32); + break; + /* uint32_t[] */ + case IFLA_INET6_CONF: + u32 = NLA_DATA(nlattr); + for (i = 0; i < (nlattr->nla_len - NLA_HDRLEN) / sizeof(*u32); + i++) { + u32[i] = tswap32(u32[i]); + } + break; + /* ifla_cacheinfo */ + case IFLA_INET6_CACHEINFO: + ci = NLA_DATA(nlattr); + ci->max_reasm_len = tswap32(ci->max_reasm_len); + ci->tstamp = tswap32(ci->tstamp); + ci->reachable_time = tswap32(ci->reachable_time); + ci->retrans_time = tswap32(ci->retrans_time); + break; + /* uint64_t[] */ + case IFLA_INET6_STATS: + case IFLA_INET6_ICMP6STATS: + u64 = NLA_DATA(nlattr); + for (i = 0; i < (nlattr->nla_len - NLA_HDRLEN) / sizeof(*u64); + i++) { + u64[i] = tswap64(u64[i]); + } + break; + default: + gemu_log("Unknown host AF_INET6 type: %d\n", nlattr->nla_type); + } + return 0; +} + +static abi_long host_to_target_data_spec_nlattr(struct nlattr *nlattr, + void *context) +{ + switch (nlattr->nla_type) { + case AF_INET: + return host_to_target_for_each_nlattr(NLA_DATA(nlattr), nlattr->nla_len, + NULL, + host_to_target_data_inet_nlattr); + case AF_INET6: + return host_to_target_for_each_nlattr(NLA_DATA(nlattr), nlattr->nla_len, + NULL, + host_to_target_data_inet6_nlattr); + default: + gemu_log("Unknown host AF_SPEC type: %d\n", nlattr->nla_type); + break; + } + return 0; +} + static abi_long host_to_target_data_link_rtattr(struct rtattr *rtattr) { uint32_t *u32; struct rtnl_link_stats *st; struct rtnl_link_stats64 *st64; struct rtnl_link_ifmap *map; + struct linkinfo_context li_context; switch (rtattr->rta_type) { /* binary stream */ @@ -1846,11 +2166,15 @@ static abi_long host_to_target_data_link_rtattr(struct rtattr *rtattr) map->irq = tswap16(map->irq); break; /* nested */ - case IFLA_AF_SPEC: case IFLA_LINKINFO: - /* FIXME: implement nested type */ - gemu_log("Unimplemented nested type %d\n", rtattr->rta_type); - break; + memset(&li_context, 0, sizeof(li_context)); + return host_to_target_for_each_nlattr(RTA_DATA(rtattr), rtattr->rta_len, + &li_context, + host_to_target_data_linkinfo_nlattr); + case IFLA_AF_SPEC: + return host_to_target_for_each_nlattr(RTA_DATA(rtattr), rtattr->rta_len, + NULL, + host_to_target_data_spec_nlattr); default: gemu_log("Unknown host IFLA type: %d\n", rtattr->rta_type); break; @@ -2826,12 +3150,26 @@ static TargetFdTrans target_packet_trans = { #ifdef CONFIG_RTNETLINK static abi_long netlink_route_target_to_host(void *buf, size_t len) { - return target_to_host_nlmsg_route(buf, len); + abi_long ret; + + ret = target_to_host_nlmsg_route(buf, len); + if (ret < 0) { + return ret; + } + + return len; } static abi_long netlink_route_host_to_target(void *buf, size_t len) { - return host_to_target_nlmsg_route(buf, len); + abi_long ret; + + ret = host_to_target_nlmsg_route(buf, len); + if (ret < 0) { + return ret; + } + + return len; } static TargetFdTrans target_netlink_route_trans = { @@ -2842,12 +3180,26 @@ static TargetFdTrans target_netlink_route_trans = { static abi_long netlink_audit_target_to_host(void *buf, size_t len) { - return target_to_host_nlmsg_audit(buf, len); + abi_long ret; + + ret = target_to_host_nlmsg_audit(buf, len); + if (ret < 0) { + return ret; + } + + return len; } static abi_long netlink_audit_host_to_target(void *buf, size_t len) { - return host_to_target_nlmsg_audit(buf, len); + abi_long ret; + + ret = host_to_target_nlmsg_audit(buf, len); + if (ret < 0) { + return ret; + } + + return len; } static TargetFdTrans target_netlink_audit_trans = { @@ -2989,13 +3341,22 @@ static abi_long do_sendrecvmsg_locked(int fd, struct target_msghdr *msgp, if (send) { if (fd_trans_target_to_host_data(fd)) { - ret = fd_trans_target_to_host_data(fd)(msg.msg_iov->iov_base, + void *host_msg; + + host_msg = g_malloc(msg.msg_iov->iov_len); + memcpy(host_msg, msg.msg_iov->iov_base, msg.msg_iov->iov_len); + ret = fd_trans_target_to_host_data(fd)(host_msg, msg.msg_iov->iov_len); + if (ret >= 0) { + msg.msg_iov->iov_base = host_msg; + ret = get_errno(safe_sendmsg(fd, &msg, flags)); + } + g_free(host_msg); } else { ret = target_to_host_cmsg(&msg, msgp); - } - if (ret == 0) { - ret = get_errno(safe_sendmsg(fd, &msg, flags)); + if (ret == 0) { + ret = get_errno(safe_sendmsg(fd, &msg, flags)); + } } } else { ret = get_errno(safe_recvmsg(fd, &msg, flags)); @@ -3211,6 +3572,7 @@ static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags, { void *addr; void *host_msg; + void *copy_msg = NULL; abi_long ret; if ((int)addrlen < 0) { @@ -3221,23 +3583,29 @@ static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags, if (!host_msg) return -TARGET_EFAULT; if (fd_trans_target_to_host_data(fd)) { + copy_msg = host_msg; + host_msg = g_malloc(len); + memcpy(host_msg, copy_msg, len); ret = fd_trans_target_to_host_data(fd)(host_msg, len); if (ret < 0) { - unlock_user(host_msg, msg, 0); - return ret; + goto fail; } } if (target_addr) { addr = alloca(addrlen+1); ret = target_to_host_sockaddr(fd, addr, target_addr, addrlen); if (ret) { - unlock_user(host_msg, msg, 0); - return ret; + goto fail; } ret = get_errno(safe_sendto(fd, host_msg, len, flags, addr, addrlen)); } else { ret = get_errno(safe_sendto(fd, host_msg, len, flags, NULL, 0)); } +fail: + if (copy_msg) { + g_free(host_msg); + host_msg = copy_msg; + } unlock_user(host_msg, msg, 0); return ret; } @@ -3272,6 +3640,9 @@ static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags, ret = get_errno(safe_recvfrom(fd, host_msg, len, flags, NULL, 0)); } if (!is_error(ret)) { + if (fd_trans_host_to_target_data(fd)) { + ret = fd_trans_host_to_target_data(fd)(host_msg, ret); + } if (target_addr) { host_to_target_sockaddr(target_addr, addr, addrlen); if (put_user_u32(addrlen, target_addrlen)) { @@ -7614,7 +7985,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #if defined(TARGET_ALPHA) struct target_sigaction act, oact, *pact = 0; struct target_rt_sigaction *rt_act; - /* ??? arg4 == sizeof(sigset_t). */ + + if (arg4 != sizeof(target_sigset_t)) { + ret = -TARGET_EINVAL; + break; + } if (arg2) { if (!lock_user_struct(VERIFY_READ, rt_act, arg2, 1)) goto efault; @@ -7638,6 +8013,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, struct target_sigaction *act; struct target_sigaction *oact; + if (arg4 != sizeof(target_sigset_t)) { + ret = -TARGET_EINVAL; + break; + } if (arg2) { if (!lock_user_struct(VERIFY_READ, act, arg2, 1)) goto efault; @@ -7769,6 +8148,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, int how = arg1; sigset_t set, oldset, *set_ptr; + if (arg4 != sizeof(target_sigset_t)) { + ret = -TARGET_EINVAL; + break; + } + if (arg2) { switch(how) { case TARGET_SIG_BLOCK: @@ -7819,6 +8203,17 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, case TARGET_NR_rt_sigpending: { sigset_t set; + + /* Yes, this check is >, not != like most. We follow the kernel's + * logic and it does it like this because it implements + * NR_sigpending through the same code path, and in that case + * the old_sigset_t is smaller in size. + */ + if (arg2 > sizeof(target_sigset_t)) { + ret = -TARGET_EINVAL; + break; + } + ret = get_errno(sigpending(&set)); if (!is_error(ret)) { if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0))) @@ -7852,6 +8247,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, case TARGET_NR_rt_sigsuspend: { TaskState *ts = cpu->opaque; + + if (arg2 != sizeof(target_sigset_t)) { + ret = -TARGET_EINVAL; + break; + } if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1))) goto efault; target_to_host_sigset(&ts->sigsuspend_mask, p); @@ -7869,6 +8269,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, struct timespec uts, *puts; siginfo_t uinfo; + if (arg4 != sizeof(target_sigset_t)) { + ret = -TARGET_EINVAL; + break; + } + if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1))) goto efault; target_to_host_sigset(&set, p); @@ -9120,6 +9525,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, } if (arg4) { + if (arg5 != sizeof(target_sigset_t)) { + unlock_user(target_pfd, arg1, 0); + ret = -TARGET_EINVAL; + break; + } + target_set = lock_user(VERIFY_READ, arg4, sizeof(target_sigset_t), 1); if (!target_set) { unlock_user(target_pfd, arg1, 0); @@ -10939,6 +11350,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, sigset_t _set, *set = &_set; if (arg5) { + if (arg6 != sizeof(target_sigset_t)) { + ret = -TARGET_EINVAL; + break; + } + target_set = lock_user(VERIFY_READ, arg5, sizeof(target_sigset_t), 1); if (!target_set) { diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index b43966ece0..783565463f 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -985,6 +985,17 @@ struct target_pollfd { #define TARGET_BLKGETSIZE64 TARGET_IOR(0x12,114,abi_ulong) /* return device size in bytes (u64 *arg) */ + +#define TARGET_BLKDISCARD TARGET_IO(0x12, 119) +#define TARGET_BLKIOMIN TARGET_IO(0x12, 120) +#define TARGET_BLKIOOPT TARGET_IO(0x12, 121) +#define TARGET_BLKALIGNOFF TARGET_IO(0x12, 122) +#define TARGET_BLKPBSZGET TARGET_IO(0x12, 123) +#define TARGET_BLKDISCARDZEROES TARGET_IO(0x12, 124) +#define TARGET_BLKSECDISCARD TARGET_IO(0x12, 125) +#define TARGET_BLKROTATIONAL TARGET_IO(0x12, 126) +#define TARGET_BLKZEROOUT TARGET_IO(0x12, 127) + #define TARGET_FIBMAP TARGET_IO(0x00,1) /* bmap access */ #define TARGET_FIGETBSZ TARGET_IO(0x00,2) /* get the block size used for bmap */ #define TARGET_FS_IOC_FIEMAP TARGET_IOWR('f',11,struct fiemap) @@ -1117,6 +1128,10 @@ struct target_pollfd { #define TARGET_LOOP_GET_STATUS64 0x4C05 #define TARGET_LOOP_CHANGE_FD 0x4C06 +#define TARGET_LOOP_CTL_ADD 0x4C80 +#define TARGET_LOOP_CTL_REMOVE 0x4C81 +#define TARGET_LOOP_CTL_GET_FREE 0x4C82 + /* fb ioctls */ #define TARGET_FBIOGET_VSCREENINFO 0x4600 #define TARGET_FBIOPUT_VSCREENINFO 0x4601 diff --git a/linux-user/syscall_types.h b/linux-user/syscall_types.h index 1fd4ee0bfd..af79fbf1de 100644 --- a/linux-user/syscall_types.h +++ b/linux-user/syscall_types.h @@ -103,10 +103,11 @@ STRUCT(loop_info64, TYPE_ULONGLONG, /* lo_inode */ TYPE_ULONGLONG, /* lo_rdevice */ TYPE_ULONGLONG, /* lo_offset */ - TYPE_ULONG, /* lo_number */ - TYPE_ULONG, /* lo_encrypt_type */ - TYPE_ULONG, /* lo_encrypt_key_size */ - TYPE_ULONG, /* lo_flags */ + TYPE_ULONGLONG, /* lo_sizelimit */ + TYPE_INT, /* lo_number */ + TYPE_INT, /* lo_encrypt_type */ + TYPE_INT, /* lo_encrypt_key_size */ + TYPE_INT, /* lo_flags */ MK_ARRAY(TYPE_CHAR, 64), /* lo_name */ MK_ARRAY(TYPE_CHAR, 64), /* lo_crypt_name */ MK_ARRAY(TYPE_CHAR, 32), /* lo_encrypt_key */ diff --git a/linux-user/x86_64/termbits.h b/linux-user/x86_64/termbits.h index 1c3445c6a2..387e742592 100644 --- a/linux-user/x86_64/termbits.h +++ b/linux-user/x86_64/termbits.h @@ -209,12 +209,12 @@ struct target_termios { #define TARGET_TIOCSBRK 0x5427 /* BSD compatibility */ #define TARGET_TIOCCBRK 0x5428 /* BSD compatibility */ #define TARGET_TIOCGSID 0x5429 /* Return the session ID of FD */ -#define TARGET_TCGETS2 _IOR('T',0x2A, struct termios2) -#define TARGET_TCSETS2 _IOW('T',0x2B, struct termios2) -#define TARGET_TCSETSW2 _IOW('T',0x2C, struct termios2) -#define TARGET_TCSETSF2 _IOW('T',0x2D, struct termios2) -#define TARGET_TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ -#define TARGET_TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ +#define TARGET_TCGETS2 TARGET_IOR('T',0x2A, struct termios2) +#define TARGET_TCSETS2 TARGET_IOW('T',0x2B, struct termios2) +#define TARGET_TCSETSW2 TARGET_IOW('T',0x2C, struct termios2) +#define TARGET_TCSETSF2 TARGET_IOW('T',0x2D, struct termios2) +#define TARGET_TIOCGPTN TARGET_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ +#define TARGET_TIOCSPTLCK TARGET_IOW('T',0x31, int) /* Lock/unlock Pty */ #define TARGET_FIONCLEX 0x5450 /* these numbers need to be adjusted. */ #define TARGET_FIOCLEX 0x5451 @@ -211,7 +211,7 @@ void eth_get_protocols(const struct iovec *iov, int iovcnt, *l4hdr_off, sizeof(l4hdr_info->hdr.tcp), &l4hdr_info->hdr.tcp); - if (istcp) { + if (*istcp) { *l5hdr_off = *l4hdr_off + TCP_HEADER_DATA_OFFSET(&l4hdr_info->hdr.tcp); @@ -418,7 +418,7 @@ _eth_get_rss_ex_dst_addr(const struct iovec *pkt, int pkt_frags, bytes_read = iov_to_buf(pkt, pkt_frags, rthdr_offset + sizeof(*ext_hdr), - dst_addr, sizeof(dst_addr)); + dst_addr, sizeof(*dst_addr)); return bytes_read == sizeof(dst_addr); } @@ -467,7 +467,7 @@ _eth_get_rss_ex_src_addr(const struct iovec *pkt, int pkt_frags, bytes_read = iov_to_buf(pkt, pkt_frags, opt_offset + sizeof(opthdr), - src_addr, sizeof(src_addr)); + src_addr, sizeof(*src_addr)); return bytes_read == sizeof(src_addr); } @@ -787,8 +787,8 @@ int net_init_tap(const Netdev *netdev, const char *name, return -1; } } else if (tap->has_fds) { - char **fds = g_new(char *, MAX_TAP_QUEUES); - char **vhost_fds = g_new(char *, MAX_TAP_QUEUES); + char **fds = g_new0(char *, MAX_TAP_QUEUES); + char **vhost_fds = g_new0(char *, MAX_TAP_QUEUES); int nfds, nvhosts; if (tap->has_ifname || tap->has_script || tap->has_downscript || @@ -806,7 +806,7 @@ int net_init_tap(const Netdev *netdev, const char *name, if (nfds != nvhosts) { error_setg(errp, "The number of fds passed does not match " "the number of vhostfds passed"); - return -1; + goto free_fail; } } @@ -814,7 +814,7 @@ int net_init_tap(const Netdev *netdev, const char *name, fd = monitor_fd_param(cur_mon, fds[i], &err); if (fd == -1) { error_propagate(errp, err); - return -1; + goto free_fail; } fcntl(fd, F_SETFL, O_NONBLOCK); @@ -824,7 +824,7 @@ int net_init_tap(const Netdev *netdev, const char *name, } else if (vnet_hdr != tap_probe_vnet_hdr(fd)) { error_setg(errp, "vnet_hdr not consistent across given tap fds"); - return -1; + goto free_fail; } net_init_tap_one(tap, peer, "tap", name, ifname, @@ -833,11 +833,21 @@ int net_init_tap(const Netdev *netdev, const char *name, vnet_hdr, fd, &err); if (err) { error_propagate(errp, err); - return -1; + goto free_fail; } } g_free(fds); g_free(vhost_fds); + return 0; + +free_fail: + for (i = 0; i < nfds; i++) { + g_free(fds[i]); + g_free(vhost_fds[i]); + } + g_free(fds); + g_free(vhost_fds); + return -1; } else if (tap->has_helper) { if (tap->has_ifname || tap->has_script || tap->has_downscript || tap->has_vnet_hdr || tap->has_queues || tap->has_vhostfds) { diff --git a/os-posix.c b/os-posix.c index 3755265582..c6ddb7d830 100644 --- a/os-posix.c +++ b/os-posix.c @@ -89,7 +89,7 @@ char *os_find_datadir(void) if (exec_dir == NULL) { return NULL; } - dir = dirname(exec_dir); + dir = g_path_get_dirname(exec_dir); max_len = strlen(dir) + MAX(strlen(SHARE_SUFFIX), strlen(BUILD_SUFFIX)) + 1; @@ -103,6 +103,7 @@ char *os_find_datadir(void) } } + g_free(dir); g_free(exec_dir); return res; } diff --git a/pc-bios/openbios-ppc b/pc-bios/openbios-ppc Binary files differindex 84075bfc24..d913fd007f 100644 --- a/pc-bios/openbios-ppc +++ b/pc-bios/openbios-ppc diff --git a/pc-bios/openbios-sparc32 b/pc-bios/openbios-sparc32 Binary files differindex 8d61947464..c8c6fcbe77 100644 --- a/pc-bios/openbios-sparc32 +++ b/pc-bios/openbios-sparc32 diff --git a/pc-bios/openbios-sparc64 b/pc-bios/openbios-sparc64 Binary files differindex 1277ddb0dd..73f03a04a3 100644 --- a/pc-bios/openbios-sparc64 +++ b/pc-bios/openbios-sparc64 diff --git a/roms/openbios b/roms/openbios -Subproject b747b6acc272f6ab839728193042455c9b36e26 +Subproject e79bca64838c96ec44fd7acd508879c5284233d diff --git a/target-arm/machine.c b/target-arm/machine.c index 2dbeb826cd..7a6ca31a8e 100644 --- a/target-arm/machine.c +++ b/target-arm/machine.c @@ -340,10 +340,9 @@ const char *gicv3_class_name(void) #else error_report("KVM GICv3 acceleration is not supported on this " "platform"); + exit(1); #endif } else { return "arm-gicv3"; } - - exit(1); } diff --git a/target-i386/cpu.c b/target-i386/cpu.c index fc209ee1cb..6e49e4ca82 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -2725,9 +2725,6 @@ static void x86_cpu_reset(CPUState *s) /* init to reset state */ -#ifdef CONFIG_SOFTMMU - env->hflags |= HF_SOFTMMU_MASK; -#endif env->hflags2 |= HF2_GIF_MASK; cpu_x86_update_cr0(env, 0x60000010); diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 776efe630e..5b14a72baa 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -130,8 +130,6 @@ positions to ease oring with eflags. */ /* current cpl */ #define HF_CPL_SHIFT 0 -/* true if soft mmu is being used */ -#define HF_SOFTMMU_SHIFT 2 /* true if hardware interrupts must be disabled for next instruction */ #define HF_INHIBIT_IRQ_SHIFT 3 /* 16 or 32 segments */ @@ -161,7 +159,6 @@ #define HF_MPX_IU_SHIFT 26 /* BND registers in-use */ #define HF_CPL_MASK (3 << HF_CPL_SHIFT) -#define HF_SOFTMMU_MASK (1 << HF_SOFTMMU_SHIFT) #define HF_INHIBIT_IRQ_MASK (1 << HF_INHIBIT_IRQ_SHIFT) #define HF_CS32_MASK (1 << HF_CS32_SHIFT) #define HF_SS32_MASK (1 << HF_SS32_SHIFT) diff --git a/target-i386/translate.c b/target-i386/translate.c index 7dea18bd63..e81fce7bc2 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -8224,9 +8224,9 @@ void gen_intermediate_code(CPUX86State *env, TranslationBlock *tb) dc->popl_esp_hack = 0; /* select memory access functions */ dc->mem_index = 0; - if (flags & HF_SOFTMMU_MASK) { - dc->mem_index = cpu_mmu_index(env, false); - } +#ifdef CONFIG_SOFTMMU + dc->mem_index = cpu_mmu_index(env, false); +#endif dc->cpuid_features = env->features[FEAT_1_EDX]; dc->cpuid_ext_features = env->features[FEAT_1_ECX]; dc->cpuid_ext2_features = env->features[FEAT_8000_0001_EDX]; @@ -8239,11 +8239,7 @@ void gen_intermediate_code(CPUX86State *env, TranslationBlock *tb) #endif dc->flags = flags; dc->jmp_opt = !(dc->tf || cs->singlestep_enabled || - (flags & HF_INHIBIT_IRQ_MASK) -#ifndef CONFIG_SOFTMMU - || (flags & HF_SOFTMMU_MASK) -#endif - ); + (flags & HF_INHIBIT_IRQ_MASK)); /* Do not optimize repz jumps at all in icount mode, because rep movsS instructions are execured with different paths in !repz_opt and repz_opt modes. The first one was used @@ -191,7 +191,7 @@ typedef uint64_t tcg_insn_unit; #endif -#ifdef CONFIG_DEBUG_TCG +#if defined CONFIG_DEBUG_TCG || defined QEMU_STATIC_ANALYSIS # define tcg_debug_assert(X) do { assert(X); } while (0) #elif QEMU_GNUC_PREREQ(4, 5) # define tcg_debug_assert(X) \ diff --git a/tests/ahci-test.c b/tests/ahci-test.c index 57dc44cf3b..9c0adce220 100644 --- a/tests/ahci-test.c +++ b/tests/ahci-test.c @@ -1063,11 +1063,34 @@ static void test_dma_fragmented(void) g_free(tx); } +/* + * Write sector 1 with random data to make AHCI storage dirty + * Needed for flush tests so that flushes actually go though the block layer + */ +static void make_dirty(AHCIQState* ahci, uint8_t port) +{ + uint64_t ptr; + unsigned bufsize = 512; + + ptr = ahci_alloc(ahci, bufsize); + g_assert(ptr); + + ahci_guest_io(ahci, port, CMD_WRITE_DMA, ptr, bufsize, 1); + ahci_free(ahci, ptr); +} + static void test_flush(void) { AHCIQState *ahci; + uint8_t port; ahci = ahci_boot_and_enable(NULL); + + port = ahci_port_select(ahci); + ahci_port_clear(ahci, port); + + make_dirty(ahci, port); + ahci_test_flush(ahci); ahci_shutdown(ahci); } @@ -1087,10 +1110,13 @@ static void test_flush_retry(void) debug_path, tmp_path, imgfmt); - /* Issue Flush Command and wait for error */ port = ahci_port_select(ahci); ahci_port_clear(ahci, port); + /* Issue write so that flush actually goes to disk */ + make_dirty(ahci, port); + + /* Issue Flush Command and wait for error */ cmd = ahci_guest_io_halt(ahci, port, CMD_FLUSH_CACHE, 0, 0, 0); ahci_guest_io_resume(ahci, cmd); @@ -1343,9 +1369,13 @@ static void test_flush_migrate(void) set_context(src->parent); - /* Issue Flush Command */ px = ahci_port_select(src); ahci_port_clear(src, px); + + /* Dirty device so that flush reaches disk */ + make_dirty(src, px); + + /* Issue Flush Command */ cmd = ahci_command_create(CMD_FLUSH_CACHE); ahci_command_commit(src, cmd, px); ahci_command_issue_async(src, cmd); diff --git a/tests/ide-test.c b/tests/ide-test.c index fed1b2ec2e..1e51af2a94 100644 --- a/tests/ide-test.c +++ b/tests/ide-test.c @@ -499,6 +499,39 @@ static void test_identify(void) ide_test_quit(); } +/* + * Write sector 1 with random data to make IDE storage dirty + * Needed for flush tests so that flushes actually go though the block layer + */ +static void make_dirty(uint8_t device) +{ + uint8_t status; + size_t len = 512; + uintptr_t guest_buf; + void* buf; + + guest_buf = guest_alloc(guest_malloc, len); + buf = g_malloc(len); + g_assert(guest_buf); + g_assert(buf); + + memwrite(guest_buf, buf, len); + + PrdtEntry prdt[] = { + { + .addr = cpu_to_le32(guest_buf), + .size = cpu_to_le32(len | PRDT_EOT), + }, + }; + + status = send_dma_request(CMD_WRITE_DMA, 1, 1, prdt, + ARRAY_SIZE(prdt), NULL); + g_assert_cmphex(status, ==, BM_STS_INTR); + assert_bit_clear(inb(IDE_BASE + reg_status), DF | ERR); + + g_free(buf); +} + static void test_flush(void) { uint8_t data; @@ -507,6 +540,11 @@ static void test_flush(void) "-drive file=blkdebug::%s,if=ide,cache=writeback,format=raw", tmp_path); + qtest_irq_intercept_in(global_qtest, "ioapic"); + + /* Dirty media so that CMD_FLUSH_CACHE will actually go to disk */ + make_dirty(0); + /* Delay the completion of the flush request until we explicitly do it */ g_free(hmp("qemu-io ide0-hd0 \"break flush_to_os A\"")); @@ -549,6 +587,11 @@ static void test_retry_flush(const char *machine) "rerror=stop,werror=stop", debug_path, tmp_path); + qtest_irq_intercept_in(global_qtest, "ioapic"); + + /* Dirty media so that CMD_FLUSH_CACHE will actually go to disk */ + make_dirty(0); + /* FLUSH CACHE command on device 0*/ outb(IDE_BASE + reg_device, 0); outb(IDE_BASE + reg_command, CMD_FLUSH_CACHE); diff --git a/tests/qemu-iotests/026.out b/tests/qemu-iotests/026.out index d84d82c112..853173572b 100644 --- a/tests/qemu-iotests/026.out +++ b/tests/qemu-iotests/026.out @@ -14,7 +14,6 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_update; errno: 5; imm: off; once: off; write -Failed to flush the L2 table cache: Input/output error Failed to flush the refcount block cache: Input/output error write failed: Input/output error @@ -23,7 +22,6 @@ This means waste of disk space, but no harm to data. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_update; errno: 5; imm: off; once: off; write -b -Failed to flush the L2 table cache: Input/output error Failed to flush the refcount block cache: Input/output error write failed: Input/output error @@ -42,7 +40,6 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_update; errno: 28; imm: off; once: off; write -Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device write failed: No space left on device @@ -51,7 +48,6 @@ This means waste of disk space, but no harm to data. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_update; errno: 28; imm: off; once: off; write -b -Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device write failed: No space left on device @@ -78,11 +74,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_load; errno: 5; imm: off; once: off; write wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -Failed to flush the L2 table cache: Input/output error -Failed to flush the refcount block cache: Input/output error write failed: Input/output error -Failed to flush the L2 table cache: Input/output error -Failed to flush the refcount block cache: Input/output error read failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -90,11 +82,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_load; errno: 5; imm: off; once: off; write -b wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -Failed to flush the L2 table cache: Input/output error -Failed to flush the refcount block cache: Input/output error write failed: Input/output error -Failed to flush the L2 table cache: Input/output error -Failed to flush the refcount block cache: Input/output error read failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -118,11 +106,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_load; errno: 28; imm: off; once: off; write wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -Failed to flush the L2 table cache: No space left on device -Failed to flush the refcount block cache: No space left on device write failed: No space left on device -Failed to flush the L2 table cache: No space left on device -Failed to flush the refcount block cache: No space left on device read failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -130,11 +114,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_load; errno: 28; imm: off; once: off; write -b wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -Failed to flush the L2 table cache: No space left on device -Failed to flush the refcount block cache: No space left on device write failed: No space left on device -Failed to flush the L2 table cache: No space left on device -Failed to flush the refcount block cache: No space left on device read failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -306,14 +286,12 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_load; errno: 5; imm: off; once: off; write -Failed to flush the L2 table cache: Input/output error Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_load; errno: 5; imm: off; once: off; write -b -Failed to flush the L2 table cache: Input/output error Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. @@ -330,14 +308,12 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_load; errno: 28; imm: off; once: off; write -Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_load; errno: 28; imm: off; once: off; write -b -Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. @@ -354,14 +330,12 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_update_part; errno: 5; imm: off; once: off; write -Failed to flush the L2 table cache: Input/output error Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_update_part; errno: 5; imm: off; once: off; write -b -Failed to flush the L2 table cache: Input/output error Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. @@ -378,14 +352,12 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_update_part; errno: 28; imm: off; once: off; write -Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_update_part; errno: 28; imm: off; once: off; write -b -Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. @@ -402,14 +374,12 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc; errno: 5; imm: off; once: off; write -Failed to flush the L2 table cache: Input/output error Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc; errno: 5; imm: off; once: off; write -b -Failed to flush the L2 table cache: Input/output error Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. @@ -426,14 +396,12 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc; errno: 28; imm: off; once: off; write -Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc; errno: 28; imm: off; once: off; write -b -Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. @@ -450,15 +418,11 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: cluster_alloc; errno: 5; imm: off; once: off; write -Failed to flush the L2 table cache: Input/output error -Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: cluster_alloc; errno: 5; imm: off; once: off; write -b -Failed to flush the L2 table cache: Input/output error -Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -474,15 +438,11 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: cluster_alloc; errno: 28; imm: off; once: off; write -Failed to flush the L2 table cache: No space left on device -Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: cluster_alloc; errno: 28; imm: off; once: off; write -b -Failed to flush the L2 table cache: No space left on device -Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. @@ -553,7 +513,6 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc_write_blocks; errno: 28; imm: off; once: off; write -Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device write failed: No space left on device @@ -562,7 +521,6 @@ This means waste of disk space, but no harm to data. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc_write_blocks; errno: 28; imm: off; once: off; write -b -Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device write failed: No space left on device @@ -581,7 +539,6 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc_write_table; errno: 28; imm: off; once: off; write -Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device write failed: No space left on device @@ -590,7 +547,6 @@ This means waste of disk space, but no harm to data. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc_write_table; errno: 28; imm: off; once: off; write -b -Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device write failed: No space left on device @@ -635,8 +591,6 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_grow_alloc_table; errno: 5; imm: off; once: off -Failed to flush the L2 table cache: Input/output error -Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -647,8 +601,6 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_grow_alloc_table; errno: 28; imm: off; once: off -Failed to flush the L2 table cache: No space left on device -Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -659,7 +611,6 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_grow_write_table; errno: 5; imm: off; once: off -Failed to flush the L2 table cache: Input/output error Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. @@ -671,7 +622,6 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_grow_write_table; errno: 28; imm: off; once: off -Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. diff --git a/tests/qemu-iotests/026.out.nocache b/tests/qemu-iotests/026.out.nocache index 9c2c8a9486..672d77c6ec 100644 --- a/tests/qemu-iotests/026.out.nocache +++ b/tests/qemu-iotests/026.out.nocache @@ -14,7 +14,6 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_update; errno: 5; imm: off; once: off; write -Failed to flush the L2 table cache: Input/output error Failed to flush the refcount block cache: Input/output error write failed: Input/output error @@ -23,7 +22,6 @@ This means waste of disk space, but no harm to data. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_update; errno: 5; imm: off; once: off; write -b -Failed to flush the L2 table cache: Input/output error Failed to flush the refcount block cache: Input/output error write failed: Input/output error @@ -42,7 +40,6 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_update; errno: 28; imm: off; once: off; write -Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device write failed: No space left on device @@ -51,7 +48,6 @@ This means waste of disk space, but no harm to data. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_update; errno: 28; imm: off; once: off; write -b -Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device write failed: No space left on device @@ -78,11 +74,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_load; errno: 5; imm: off; once: off; write wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -Failed to flush the L2 table cache: Input/output error -Failed to flush the refcount block cache: Input/output error write failed: Input/output error -Failed to flush the L2 table cache: Input/output error -Failed to flush the refcount block cache: Input/output error read failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -90,11 +82,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_load; errno: 5; imm: off; once: off; write -b wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -Failed to flush the L2 table cache: Input/output error -Failed to flush the refcount block cache: Input/output error write failed: Input/output error -Failed to flush the L2 table cache: Input/output error -Failed to flush the refcount block cache: Input/output error read failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -118,11 +106,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_load; errno: 28; imm: off; once: off; write wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -Failed to flush the L2 table cache: No space left on device -Failed to flush the refcount block cache: No space left on device write failed: No space left on device -Failed to flush the L2 table cache: No space left on device -Failed to flush the refcount block cache: No space left on device read failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -130,11 +114,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_load; errno: 28; imm: off; once: off; write -b wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -Failed to flush the L2 table cache: No space left on device -Failed to flush the refcount block cache: No space left on device write failed: No space left on device -Failed to flush the L2 table cache: No space left on device -Failed to flush the refcount block cache: No space left on device read failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -314,14 +294,12 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_load; errno: 5; imm: off; once: off; write -Failed to flush the L2 table cache: Input/output error Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_load; errno: 5; imm: off; once: off; write -b -Failed to flush the L2 table cache: Input/output error Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. @@ -338,14 +316,12 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_load; errno: 28; imm: off; once: off; write -Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_load; errno: 28; imm: off; once: off; write -b -Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. @@ -362,14 +338,12 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_update_part; errno: 5; imm: off; once: off; write -Failed to flush the L2 table cache: Input/output error Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_update_part; errno: 5; imm: off; once: off; write -b -Failed to flush the L2 table cache: Input/output error Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. @@ -386,14 +360,12 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_update_part; errno: 28; imm: off; once: off; write -Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_update_part; errno: 28; imm: off; once: off; write -b -Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. @@ -410,14 +382,12 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc; errno: 5; imm: off; once: off; write -Failed to flush the L2 table cache: Input/output error Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc; errno: 5; imm: off; once: off; write -b -Failed to flush the L2 table cache: Input/output error Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. @@ -434,14 +404,12 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc; errno: 28; imm: off; once: off; write -Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc; errno: 28; imm: off; once: off; write -b -Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. @@ -458,15 +426,11 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: cluster_alloc; errno: 5; imm: off; once: off; write -Failed to flush the L2 table cache: Input/output error -Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: cluster_alloc; errno: 5; imm: off; once: off; write -b -Failed to flush the L2 table cache: Input/output error -Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -482,15 +446,11 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: cluster_alloc; errno: 28; imm: off; once: off; write -Failed to flush the L2 table cache: No space left on device -Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: cluster_alloc; errno: 28; imm: off; once: off; write -b -Failed to flush the L2 table cache: No space left on device -Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. @@ -561,7 +521,6 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc_write_blocks; errno: 28; imm: off; once: off; write -Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device write failed: No space left on device @@ -570,7 +529,6 @@ This means waste of disk space, but no harm to data. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc_write_blocks; errno: 28; imm: off; once: off; write -b -Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device write failed: No space left on device @@ -589,7 +547,6 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc_write_table; errno: 28; imm: off; once: off; write -Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device write failed: No space left on device @@ -598,7 +555,6 @@ This means waste of disk space, but no harm to data. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc_write_table; errno: 28; imm: off; once: off; write -b -Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device write failed: No space left on device @@ -643,8 +599,6 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_grow_alloc_table; errno: 5; imm: off; once: off -Failed to flush the L2 table cache: Input/output error -Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -655,8 +609,6 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_grow_alloc_table; errno: 28; imm: off; once: off -Failed to flush the L2 table cache: No space left on device -Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -667,7 +619,6 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_grow_write_table; errno: 5; imm: off; once: off -Failed to flush the L2 table cache: Input/output error Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. @@ -679,7 +630,6 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_grow_write_table; errno: 28; imm: off; once: off -Failed to flush the L2 table cache: No space left on device Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. diff --git a/tests/qemu-iotests/071.out b/tests/qemu-iotests/071.out index 2b40eadae3..8c6851e792 100644 --- a/tests/qemu-iotests/071.out +++ b/tests/qemu-iotests/071.out @@ -30,14 +30,10 @@ blkverify: read sector_num=0 nb_sectors=1 contents mismatch in sector 0 === Testing blkdebug through filename === -Failed to flush the L2 table cache: Input/output error -Failed to flush the refcount block cache: Input/output error read failed: Input/output error === Testing blkdebug through file blockref === -Failed to flush the L2 table cache: Input/output error -Failed to flush the refcount block cache: Input/output error read failed: Input/output error === Testing blkdebug on existing block device === @@ -51,8 +47,6 @@ read failed: Input/output error {"return": ""} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"} -QEMU_PROG: Failed to flush the L2 table cache: Input/output error -QEMU_PROG: Failed to flush the refcount block cache: Input/output error === Testing blkverify on existing block device === @@ -92,7 +86,5 @@ read failed: Input/output error {"return": ""} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"} -QEMU_PROG: Failed to flush the L2 table cache: Input/output error -QEMU_PROG: Failed to flush the refcount block cache: Input/output error *** done diff --git a/tests/qemu-iotests/089.out b/tests/qemu-iotests/089.out index 5b541a340c..18f5fdda7a 100644 --- a/tests/qemu-iotests/089.out +++ b/tests/qemu-iotests/089.out @@ -24,8 +24,6 @@ read 512/512 bytes at offset 0 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 wrote 512/512 bytes at offset 229376 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -Failed to flush the L2 table cache: Input/output error -Failed to flush the refcount block cache: Input/output error read failed: Input/output error === Testing qemu-img info output === diff --git a/tests/qemu-iotests/141.out b/tests/qemu-iotests/141.out index adceac1817..eaf1e603ed 100644 --- a/tests/qemu-iotests/141.out +++ b/tests/qemu-iotests/141.out @@ -18,8 +18,8 @@ Formatting 'TEST_DIR/o.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t. {"return": {}} Formatting 'TEST_DIR/o.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT backing_fmt=IMGFMT -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "drv0", "len": 0, "offset": 0, "speed": 0, "type": "mirror"}} +{"return": {}} {"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: mirror"}} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "drv0", "len": 0, "offset": 0, "speed": 0, "type": "mirror"}} @@ -28,8 +28,8 @@ Formatting 'TEST_DIR/o.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t. === Testing active block-commit === {"return": {}} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "drv0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}} +{"return": {}} {"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: commit"}} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "drv0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}} diff --git a/tests/qemu-iotests/144.out b/tests/qemu-iotests/144.out index 410d74180a..387855c378 100644 --- a/tests/qemu-iotests/144.out +++ b/tests/qemu-iotests/144.out @@ -12,9 +12,9 @@ Formatting 'TEST_DIR/tmp.qcow2', fmt=qcow2 size=536870912 backing_file=TEST_DIR/ === Performing block-commit on active layer === -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "virtio0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}} {"return": {}} +{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "virtio0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}} === Performing Live Snapshot 2 === diff --git a/ui/vnc-enc-tight.c b/ui/vnc-enc-tight.c index b8581dd2e9..49df85e763 100644 --- a/ui/vnc-enc-tight.c +++ b/ui/vnc-enc-tight.c @@ -461,9 +461,10 @@ static int tight_fill_palette(VncState *vs, int x, int y, \ src = (uint##bpp##_t *) buf; \ \ - for (i = 0; i < count; i++) { \ + for (i = 0; i < count; ) { \ \ rgb = *src++; \ + i++; \ rep = 0; \ while (i < count && *src == rgb) { \ rep++, src++, i++; \ @@ -1457,11 +1458,17 @@ static int send_sub_rect_jpeg(VncState *vs, int x, int y, int w, int h, } #endif -static __thread VncPalette color_count_palette; +static __thread VncPalette *color_count_palette; +static __thread Notifier vnc_tight_cleanup_notifier; + +static void vnc_tight_cleanup(Notifier *n, void *value) +{ + g_free(color_count_palette); + color_count_palette = NULL; +} static int send_sub_rect(VncState *vs, int x, int y, int w, int h) { - VncPalette *palette = &color_count_palette; uint32_t bg = 0, fg = 0; int colors; int ret = 0; @@ -1470,6 +1477,12 @@ static int send_sub_rect(VncState *vs, int x, int y, int w, int h) bool allow_jpeg = true; #endif + if (!color_count_palette) { + color_count_palette = g_malloc(sizeof(VncPalette)); + vnc_tight_cleanup_notifier.notify = vnc_tight_cleanup; + qemu_thread_atexit_add(&vnc_tight_cleanup_notifier); + } + vnc_framebuffer_update(vs, x, y, w, h, vs->tight.type); vnc_tight_start(vs); @@ -1490,17 +1503,19 @@ static int send_sub_rect(VncState *vs, int x, int y, int w, int h) } #endif - colors = tight_fill_palette(vs, x, y, w * h, &bg, &fg, palette); + colors = tight_fill_palette(vs, x, y, w * h, &bg, &fg, color_count_palette); #ifdef CONFIG_VNC_JPEG if (allow_jpeg && vs->tight.quality != (uint8_t)-1) { - ret = send_sub_rect_jpeg(vs, x, y, w, h, bg, fg, colors, palette, - force_jpeg); + ret = send_sub_rect_jpeg(vs, x, y, w, h, bg, fg, colors, + color_count_palette, force_jpeg); } else { - ret = send_sub_rect_nojpeg(vs, x, y, w, h, bg, fg, colors, palette); + ret = send_sub_rect_nojpeg(vs, x, y, w, h, bg, fg, colors, + color_count_palette); } #else - ret = send_sub_rect_nojpeg(vs, x, y, w, h, bg, fg, colors, palette); + ret = send_sub_rect_nojpeg(vs, x, y, w, h, bg, fg, colors, + color_count_palette); #endif return ret; @@ -1024,6 +1024,11 @@ static int find_and_clear_dirty_height(VncState *vs, static int vnc_update_client(VncState *vs, int has_dirty, bool sync) { + if (vs->disconnecting) { + vnc_disconnect_finish(vs); + return 0; + } + vs->has_dirty += has_dirty; if (vs->need_update && !vs->disconnecting) { VncDisplay *vd = vs->vd; diff --git a/util/oslib-posix.c b/util/oslib-posix.c index d8e5dcfede..6d70d9a706 100644 --- a/util/oslib-posix.c +++ b/util/oslib-posix.c @@ -299,9 +299,11 @@ void qemu_init_exec_dir(const char *argv0) return; } } - dir = dirname(p); + dir = g_path_get_dirname(p); pstrcpy(exec_dir, sizeof(exec_dir), dir); + + g_free(dir); } char *qemu_get_exec_dir(void) |