diff options
-rw-r--r-- | .travis.yml | 111 | ||||
-rw-r--r-- | HACKING | 55 | ||||
-rw-r--r-- | MAINTAINERS | 6 | ||||
-rw-r--r-- | block/io.c | 1 | ||||
-rw-r--r-- | blockjob.c | 6 | ||||
-rw-r--r-- | hw/arm/imx25_pdk.c | 7 | ||||
-rw-r--r-- | hw/arm/kzm.c | 7 | ||||
-rw-r--r-- | hw/arm/netduino2.c | 7 | ||||
-rw-r--r-- | hw/arm/xlnx-ep108.c | 7 | ||||
-rw-r--r-- | include/block/blockjob.h | 5 | ||||
-rw-r--r-- | include/qapi/error.h | 15 | ||||
-rw-r--r-- | include/qemu/iov.h | 34 | ||||
-rw-r--r-- | util/iov.c | 8 | ||||
-rw-r--r-- | vl.c | 7 |
14 files changed, 192 insertions, 84 deletions
diff --git a/.travis.yml b/.travis.yml index 0428aed0ec..9e5873b28c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,38 @@ +sudo: false language: c python: - "2.4" compiler: - gcc - clang +cache: ccache +addons: + apt: + packages: + - libaio-dev + - libattr1-dev + - libbrlapi-dev + - libcap-ng-dev + - libgnutls-dev + - libgtk-3-dev + - libiscsi-dev + - liblttng-ust-dev + - libncurses5-dev + - libnss3-dev + - libpixman-1-dev + - libpng12-dev + - librados-dev + - libsdl1.2-dev + - libseccomp-dev + - libspice-protocol-dev + - libspice-server-dev + - libssh2-1-dev + - liburcu-dev + - libusb-1.0-0-dev + - libvte-2.90-dev + - sparse + - uuid-dev + notifications: irc: channels: @@ -12,29 +41,16 @@ notifications: on_failure: always env: global: - - TEST_CMD="" + - TEST_CMD="make check" - EXTRA_CONFIG="" - # Development packages, EXTRA_PKGS saved for additional builds - - CORE_PKGS="libusb-1.0-0-dev libiscsi-dev librados-dev libncurses5-dev" - - NET_PKGS="libseccomp-dev libgnutls-dev libssh2-1-dev libspice-server-dev libspice-protocol-dev libnss3-dev" - - GUI_PKGS="libgtk-3-dev libvte-2.90-dev libsdl1.2-dev libpng12-dev libpixman-1-dev" - - EXTRA_PKGS="" matrix: # Group major targets together with their linux-user counterparts - - TARGETS=alpha-softmmu,alpha-linux-user + - TARGETS=alpha-softmmu,alpha-linux-user,cris-softmmu,cris-linux-user,m68k-softmmu,m68k-linux-user,microblaze-softmmu,microblazeel-softmmu,microblaze-linux-user,microblazeel-linux-user - TARGETS=arm-softmmu,arm-linux-user,armeb-linux-user,aarch64-softmmu,aarch64-linux-user - - TARGETS=cris-softmmu,cris-linux-user - TARGETS=i386-softmmu,i386-linux-user,x86_64-softmmu,x86_64-linux-user - - TARGETS=m68k-softmmu,m68k-linux-user - - TARGETS=microblaze-softmmu,microblazeel-softmmu,microblaze-linux-user,microblazeel-linux-user - - TARGETS=mips-softmmu,mips64-softmmu,mips64el-softmmu,mipsel-softmmu - - TARGETS=mips-linux-user,mips64-linux-user,mips64el-linux-user,mipsel-linux-user,mipsn32-linux-user,mipsn32el-linux-user - - TARGETS=or32-softmmu,or32-linux-user - - TARGETS=ppc-softmmu,ppc64-softmmu,ppcemb-softmmu,ppc-linux-user,ppc64-linux-user,ppc64abi32-linux-user,ppc64le-linux-user - - TARGETS=s390x-softmmu,s390x-linux-user - - TARGETS=sh4-softmmu,sh4eb-softmmu,sh4-linux-user sh4eb-linux-user - - TARGETS=sparc-softmmu,sparc64-softmmu,sparc-linux-user,sparc32plus-linux-user,sparc64-linux-user - - TARGETS=unicore32-softmmu,unicore32-linux-user + - TARGETS=mips-softmmu,mips64-softmmu,mips64el-softmmu,mipsel-softmmu,mips-linux-user,mips64-linux-user,mips64el-linux-user,mipsel-linux-user,mipsn32-linux-user,mipsn32el-linux-user + - TARGETS=or32-softmmu,or32-linux-user,ppc-softmmu,ppc64-softmmu,ppcemb-softmmu,ppc-linux-user,ppc64-linux-user,ppc64abi32-linux-user,ppc64le-linux-user + - TARGETS=s390x-softmmu,s390x-linux-user,sh4-softmmu,sh4eb-softmmu,sh4-linux-user,sh4eb-linux-user,sparc-softmmu,sparc64-softmmu,sparc-linux-user,sparc32plus-linux-user,sparc64-linux-user,unicore32-softmmu,unicore32-linux-user # Group remaining softmmu only targets into one build - TARGETS=lm32-softmmu,moxie-softmmu,tricore-softmmu,xtensa-softmmu,xtensaeb-softmmu git: @@ -43,8 +59,6 @@ git: before_install: - wget -O - http://people.linaro.org/~alex.bennee/qemu-submodule-git-seed.tar.xz | tar -xvJ - git submodule update --init --recursive - - sudo apt-get update -qq - - sudo apt-get install -qq ${CORE_PKGS} ${NET_PKGS} ${GUI_PKGS} ${EXTRA_PKGS} before_script: - ./configure --target-list=${TARGETS} --enable-debug-tcg ${EXTRA_CONFIG} script: @@ -52,44 +66,59 @@ script: matrix: # We manually include a number of additional build for non-standard bits include: - # Make check target (we only do this once) - - env: - - TARGETS=alpha-softmmu,arm-softmmu,aarch64-softmmu,cris-softmmu,i386-softmmu,x86_64-softmmu,m68k-softmmu,microblaze-softmmu,microblazeel-softmmu,mips-softmmu,mips64-softmmu,mips64el-softmmu,mipsel-softmmu,or32-softmmu,ppc-softmmu,ppc64-softmmu,ppcemb-softmmu,s390x-softmmu,sh4-softmmu,sh4eb-softmmu,sparc-softmmu,sparc64-softmmu,unicore32-softmmu,unicore32-linux-user,lm32-softmmu,moxie-softmmu,tricore-softmmu,xtensa-softmmu,xtensaeb-softmmu - TEST_CMD="make check" - compiler: gcc # Debug related options - - env: TARGETS=i386-softmmu,x86_64-softmmu + - env: TARGETS=x86_64-softmmu EXTRA_CONFIG="--enable-debug" compiler: gcc - - env: TARGETS=i386-softmmu,x86_64-softmmu + # We currently disable "make check" + - env: TARGETS=alpha-softmmu EXTRA_CONFIG="--enable-debug --enable-tcg-interpreter" + TEST_CMD="" compiler: gcc - # All the extra -dev packages - - env: TARGETS=i386-softmmu,x86_64-softmmu - EXTRA_PKGS="libaio-dev libcap-ng-dev libattr1-dev libbrlapi-dev uuid-dev libusb-1.0.0-dev" + # Disable a few of the optional features + - env: TARGETS=x86_64-softmmu + EXTRA_CONFIG="--disable-linux-aio --disable-cap-ng --disable-attr --disable-brlapi --disable-uuid --disable-libusb" compiler: gcc # Currently configure doesn't force --disable-pie - - env: TARGETS=i386-softmmu,x86_64-softmmu + - env: TARGETS=x86_64-softmmu EXTRA_CONFIG="--enable-gprof --enable-gcov --disable-pie" compiler: gcc - - env: TARGETS=i386-softmmu,x86_64-softmmu - EXTRA_PKGS="sparse" + # Sparse + - env: TARGETS=x86_64-softmmu EXTRA_CONFIG="--enable-sparse" compiler: gcc + # Modules + - env: TARGETS=arm-softmmu,x86_64-softmmu + EXTRA_CONFIG="--enable-modules" + compiler: gcc # All the trace backends (apart from dtrace) - - env: TARGETS=i386-softmmu,x86_64-softmmu + - env: TARGETS=i386-softmmu EXTRA_CONFIG="--enable-trace-backends=log" compiler: gcc - - env: TARGETS=i386-softmmu,x86_64-softmmu + # We currently disable "make check" (until 41fc57e44ed regression fixed) + - env: TARGETS=x86_64-softmmu EXTRA_CONFIG="--enable-trace-backends=simple" + TEST_CMD="" compiler: gcc - - env: TARGETS=i386-softmmu,x86_64-softmmu + # We currently disable "make check" + - env: TARGETS=x86_64-softmmu EXTRA_CONFIG="--enable-trace-backends=ftrace" + TEST_CMD="" compiler: gcc - - env: TARGETS=i386-softmmu,x86_64-softmmu - EXTRA_PKGS="liblttng-ust-dev liburcu-dev" - EXTRA_CONFIG="--enable-trace-backends=ust" + # We currently disable "make check" + - env: TARGETS=x86_64-softmmu + EXTRA_CONFIG="--enable-trace-backends=ust" + TEST_CMD="" compiler: gcc - - env: TARGETS=i386-softmmu,x86_64-softmmu - EXTRA_CONFIG="--enable-modules" + # All the co-routine backends (apart from windows) + # We currently disable "make check" + - env: TARGETS=x86_64-softmmu + EXTRA_CONFIG="--with-coroutine=gthread" + TEST_CMD="" + compiler: gcc + - env: TARGETS=x86_64-softmmu + EXTRA_CONFIG="--with-coroutine=ucontext" + compiler: gcc + - env: TARGETS=x86_64-softmmu + EXTRA_CONFIG="--with-coroutine=sigaltstack" compiler: gcc @@ -157,3 +157,58 @@ painful. These are: * you may assume that integers are 2s complement representation * you may assume that right shift of a signed integer duplicates the sign bit (ie it is an arithmetic shift, not a logical shift) + +7. Error handling and reporting + +7.1 Reporting errors to the human user + +Do not use printf(), fprintf() or monitor_printf(). Instead, use +error_report() or error_vreport() from error-report.h. This ensures the +error is reported in the right place (current monitor or stderr), and in +a uniform format. + +Use error_printf() & friends to print additional information. + +error_report() prints the current location. In certain common cases +like command line parsing, the current location is tracked +automatically. To manipulate it manually, use the loc_*() from +error-report.h. + +7.2 Propagating errors + +An error can't always be reported to the user right where it's detected, +but often needs to be propagated up the call chain to a place that can +handle it. This can be done in various ways. + +The most flexible one is Error objects. See error.h for usage +information. + +Use the simplest suitable method to communicate success / failure to +callers. Stick to common methods: non-negative on success / -1 on +error, non-negative / -errno, non-null / null, or Error objects. + +Example: when a function returns a non-null pointer on success, and it +can fail only in one way (as far as the caller is concerned), returning +null on failure is just fine, and certainly simpler and a lot easier on +the eyes than propagating an Error object through an Error ** parameter. + +Example: when a function's callers need to report details on failure +only the function really knows, use Error **, and set suitable errors. + +Do not report an error to the user when you're also returning an error +for somebody else to handle. Leave the reporting to the place that +consumes the error returned. + +7.3 Handling errors + +Calling exit() is fine when handling configuration errors during +startup. It's problematic during normal operation. In particular, +monitor commands should never exit(). + +Do not call exit() or abort() to handle an error that can be triggered +by the guest (e.g., some unimplemented corner case in guest code +translation or device emulation). Guests should not be able to +terminate QEMU. + +Note that &error_fatal is just another way to exit(1), and &error_abort +is just another way to abort(). diff --git a/MAINTAINERS b/MAINTAINERS index 2d78eea5d6..02710f857c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1571,6 +1571,12 @@ L: qemu-block@nongnu.org S: Supported F: tests/image-fuzzer/ +Build and test automation +------------------------- +M: Alex Bennée <alex.bennee@linaro.org> +L: qemu-devel@nongnu.org +S: Supported +F: .travis.yml Documentation ------------- diff --git a/block/io.c b/block/io.c index 343ff1f233..a69bfc4197 100644 --- a/block/io.c +++ b/block/io.c @@ -301,6 +301,7 @@ void bdrv_drain_all(void) if (bs->job) { block_job_pause(bs->job); } + bdrv_drain_recurse(bs); aio_context_release(aio_context); if (!g_slist_find(aio_ctxs, aio_context)) { diff --git a/blockjob.c b/blockjob.c index a402181835..9fc37ca965 100644 --- a/blockjob.c +++ b/blockjob.c @@ -296,7 +296,9 @@ static int block_job_finish_sync(BlockJob *job, return -EBUSY; } while (!job->completed) { - aio_poll(bdrv_get_aio_context(bs), true); + aio_poll(job->deferred_to_main_loop ? qemu_get_aio_context() : + bdrv_get_aio_context(bs), + true); } ret = (job->cancelled && job->ret == 0) ? -ECANCELED : job->ret; block_job_unref(job); @@ -470,6 +472,7 @@ static void block_job_defer_to_main_loop_bh(void *opaque) aio_context = bdrv_get_aio_context(data->job->bs); aio_context_acquire(aio_context); + data->job->deferred_to_main_loop = false; data->fn(data->job, data->opaque); aio_context_release(aio_context); @@ -489,6 +492,7 @@ void block_job_defer_to_main_loop(BlockJob *job, data->aio_context = bdrv_get_aio_context(job->bs); data->fn = fn; data->opaque = opaque; + job->deferred_to_main_loop = true; qemu_bh_schedule(data->bh); } diff --git a/hw/arm/imx25_pdk.c b/hw/arm/imx25_pdk.c index b167e19f5a..e3cffd190c 100644 --- a/hw/arm/imx25_pdk.c +++ b/hw/arm/imx25_pdk.c @@ -65,7 +65,6 @@ static struct arm_boot_info imx25_pdk_binfo; static void imx25_pdk_init(MachineState *machine) { IMX25PDK *s = g_new0(IMX25PDK, 1); - Error *err = NULL; unsigned int ram_size; unsigned int alias_offset; int i; @@ -74,11 +73,7 @@ static void imx25_pdk_init(MachineState *machine) object_property_add_child(OBJECT(machine), "soc", OBJECT(&s->soc), &error_abort); - object_property_set_bool(OBJECT(&s->soc), true, "realized", &err); - if (err != NULL) { - error_report_err(err); - exit(1); - } + object_property_set_bool(OBJECT(&s->soc), true, "realized", &error_fatal); /* We need to initialize our memory */ if (machine->ram_size > (FSL_IMX25_SDRAM0_SIZE + FSL_IMX25_SDRAM1_SIZE)) { diff --git a/hw/arm/kzm.c b/hw/arm/kzm.c index 55fb36021c..2eeb9d8973 100644 --- a/hw/arm/kzm.c +++ b/hw/arm/kzm.c @@ -64,7 +64,6 @@ static struct arm_boot_info kzm_binfo = { static void kzm_init(MachineState *machine) { IMX31KZM *s = g_new0(IMX31KZM, 1); - Error *err = NULL; unsigned int ram_size; unsigned int alias_offset; unsigned int i; @@ -73,11 +72,7 @@ static void kzm_init(MachineState *machine) object_property_add_child(OBJECT(machine), "soc", OBJECT(&s->soc), &error_abort); - object_property_set_bool(OBJECT(&s->soc), true, "realized", &err); - if (err != NULL) { - error_report_err(err); - exit(1); - } + object_property_set_bool(OBJECT(&s->soc), true, "realized", &error_fatal); /* Check the amount of memory is compatible with the SOC */ if (machine->ram_size > (FSL_IMX31_SDRAM0_SIZE + FSL_IMX31_SDRAM1_SIZE)) { diff --git a/hw/arm/netduino2.c b/hw/arm/netduino2.c index 86065d360a..49da6e360d 100644 --- a/hw/arm/netduino2.c +++ b/hw/arm/netduino2.c @@ -30,18 +30,13 @@ static void netduino2_init(MachineState *machine) { DeviceState *dev; - Error *err = NULL; dev = qdev_create(NULL, TYPE_STM32F205_SOC); if (machine->kernel_filename) { qdev_prop_set_string(dev, "kernel-filename", machine->kernel_filename); } qdev_prop_set_string(dev, "cpu-model", "cortex-m3"); - object_property_set_bool(OBJECT(dev), true, "realized", &err); - if (err != NULL) { - error_report_err(err); - exit(1); - } + object_property_set_bool(OBJECT(dev), true, "realized", &error_fatal); } static void netduino2_machine_init(MachineClass *mc) diff --git a/hw/arm/xlnx-ep108.c b/hw/arm/xlnx-ep108.c index 2cd69b5faf..0de132abd2 100644 --- a/hw/arm/xlnx-ep108.c +++ b/hw/arm/xlnx-ep108.c @@ -32,7 +32,6 @@ static void xlnx_ep108_init(MachineState *machine) { XlnxEP108 *s = g_new0(XlnxEP108, 1); int i; - Error *err = NULL; uint64_t ram_size = machine->ram_size; /* Create the memory region to pass to the SoC */ @@ -58,11 +57,7 @@ static void xlnx_ep108_init(MachineState *machine) object_property_set_link(OBJECT(&s->soc), OBJECT(&s->ddr_ram), "ddr-ram", &error_abort); - object_property_set_bool(OBJECT(&s->soc), true, "realized", &err); - if (err) { - error_report_err(err); - exit(1); - } + object_property_set_bool(OBJECT(&s->soc), true, "realized", &error_fatal); for (i = 0; i < XLNX_ZYNQMP_NUM_SPIS; i++) { SSIBus *spi_bus; diff --git a/include/block/blockjob.h b/include/block/blockjob.h index d84ccd8d2c..8bedc4936c 100644 --- a/include/block/blockjob.h +++ b/include/block/blockjob.h @@ -130,6 +130,11 @@ struct BlockJob { */ bool ready; + /** + * Set to true when the job has deferred work to the main loop. + */ + bool deferred_to_main_loop; + /** Status that is published by the query-block-jobs QMP API */ BlockDeviceIoStatus iostatus; diff --git a/include/qapi/error.h b/include/qapi/error.h index 45d6c72dee..e64fe54cf9 100644 --- a/include/qapi/error.h +++ b/include/qapi/error.h @@ -27,11 +27,11 @@ * error_setg(&err, "invalid quark\n" * "Valid quarks are up, down, strange, charm, top, bottom."); * - * Report an error to stderr: + * Report an error to the current monitor if we have one, else stderr: * error_report_err(err); * This frees the error object. * - * Report an error to stderr with additional text prepended: + * Likewise, but with additional text prepended: * error_reportf_err(err, "Could not frobnicate '%s': ", name); * * Report an error somewhere else: @@ -162,6 +162,9 @@ ErrorClass error_get_class(const Error *err); * human-readable error message is made from printf-style @fmt, ... * The resulting message should be a single phrase, with no newline or * trailing punctuation. + * Please don't error_setg(&error_fatal, ...), use error_report() and + * exit(), because that's more obvious. + * Likewise, don't error_setg(&error_abort, ...), use assert(). */ #define error_setg(errp, fmt, ...) \ error_setg_internal((errp), __FILE__, __LINE__, __func__, \ @@ -213,6 +216,8 @@ void error_setg_win32_internal(Error **errp, * the error object. * Else, move the error object from @local_err to *@dst_errp. * On return, @local_err is invalid. + * Please don't error_propagate(&error_fatal, ...), use + * error_report_err() and exit(), because that's more obvious. */ void error_propagate(Error **dst_errp, Error *local_err); @@ -291,12 +296,14 @@ void error_set_internal(Error **errp, GCC_FMT_ATTR(6, 7); /* - * Pass to error_setg() & friends to abort() on error. + * Special error destination to abort on error. + * See error_setg() and error_propagate() for details. */ extern Error *error_abort; /* - * Pass to error_setg() & friends to exit(1) on error. + * Special error destination to exit(1) on error. + * See error_setg() and error_propagate() for details. */ extern Error *error_fatal; diff --git a/include/qemu/iov.h b/include/qemu/iov.h index 569b2c2a23..28475516eb 100644 --- a/include/qemu/iov.h +++ b/include/qemu/iov.h @@ -39,10 +39,36 @@ size_t iov_size(const struct iovec *iov, const unsigned int iov_cnt); * such "large" value is -1 (sinice size_t is unsigned), * so specifying `-1' as `bytes' means 'up to the end of iovec'. */ -size_t iov_from_buf(const struct iovec *iov, unsigned int iov_cnt, - size_t offset, const void *buf, size_t bytes); -size_t iov_to_buf(const struct iovec *iov, const unsigned int iov_cnt, - size_t offset, void *buf, size_t bytes); +size_t iov_from_buf_full(const struct iovec *iov, unsigned int iov_cnt, + size_t offset, const void *buf, size_t bytes); +size_t iov_to_buf_full(const struct iovec *iov, const unsigned int iov_cnt, + size_t offset, void *buf, size_t bytes); + +static inline size_t +iov_from_buf(const struct iovec *iov, unsigned int iov_cnt, + size_t offset, const void *buf, size_t bytes) +{ + if (__builtin_constant_p(bytes) && iov_cnt && + offset <= iov[0].iov_len && bytes <= iov[0].iov_len - offset) { + memcpy(iov[0].iov_base + offset, buf, bytes); + return bytes; + } else { + return iov_from_buf_full(iov, iov_cnt, offset, buf, bytes); + } +} + +static inline size_t +iov_to_buf(const struct iovec *iov, const unsigned int iov_cnt, + size_t offset, void *buf, size_t bytes) +{ + if (__builtin_constant_p(bytes) && iov_cnt && + offset <= iov[0].iov_len && bytes <= iov[0].iov_len - offset) { + memcpy(buf, iov[0].iov_base + offset, bytes); + return bytes; + } else { + return iov_to_buf_full(iov, iov_cnt, offset, buf, bytes); + } +} /** * Set data bytes pointed out by iovec `iov' of size `iov_cnt' elements, diff --git a/util/iov.c b/util/iov.c index e802ee15bc..062f4e50c3 100644 --- a/util/iov.c +++ b/util/iov.c @@ -20,8 +20,8 @@ #include "qemu/iov.h" #include "qemu/sockets.h" -size_t iov_from_buf(const struct iovec *iov, unsigned int iov_cnt, - size_t offset, const void *buf, size_t bytes) +size_t iov_from_buf_full(const struct iovec *iov, unsigned int iov_cnt, + size_t offset, const void *buf, size_t bytes) { size_t done; unsigned int i; @@ -39,8 +39,8 @@ size_t iov_from_buf(const struct iovec *iov, unsigned int iov_cnt, return done; } -size_t iov_to_buf(const struct iovec *iov, const unsigned int iov_cnt, - size_t offset, void *buf, size_t bytes) +size_t iov_to_buf_full(const struct iovec *iov, const unsigned int iov_cnt, + size_t offset, void *buf, size_t bytes) { size_t done; unsigned int i; @@ -4557,12 +4557,7 @@ int main(int argc, char **argv, char **envp) net_check_clients(); if (boot_once) { - Error *local_err = NULL; - qemu_boot_set(boot_once, &local_err); - if (local_err) { - error_report_err(local_err); - exit(1); - } + qemu_boot_set(boot_once, &error_fatal); qemu_register_reset(restore_boot_order, g_strdup(boot_order)); } |