Various testing and logging updates

- test tci with Travis
   - enable multiarch testing in Travis
   - default to out-of-tree builds
   - make changing logfile safe via RCU
   - remove redundant tests
   - remove gtester test from docker
   - convert DEBUG_MMAP to tracepoints
   - remove hand rolled glob function
   - trigger tcg re-configure when needed
 -----BEGIN PGP SIGNATURE-----
 
 iQEzBAABCgAdFiEEZoWumedRZ7yvyN81+9DbCVqeKkQFAl37M6gACgkQ+9DbCVqe
 KkQ0Rwf/d0lGDPQN1Uf0zqZRQQmDCqWVuqHhZJ5xWDjbyVT2eUwR07TvNZeUKEWX
 iO+u6S7Tv91oLjZN5WjhaiuSjtJaEzCdcpkIJAWXLP/lzse37HEwvLBsdg71y+46
 LNvBrJRPpQotdb7fjr8RgCwc1qg2Bz15ekSn7XIA175zTMmUsshLJBVhLbGNqrVm
 F2UmjB9oFJ0+nzrcEnpFmWw7xvVrX1dImZXv5C2pvuHF7efSjGwiFviTRZgDjOGs
 V7HiWRV1QcgTigncncxTMbhMTKTVKK+e7O+y0DZWt/NSrT/yLDy5rcwySpmvu6C+
 cRmh/0tMo1KAhiz8Xy8LookhVj6hdA==
 =OAkV
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/stsquad/tags/pull-tesing-and-misc-191219-1' into staging

Various testing and logging updates

  - test tci with Travis
  - enable multiarch testing in Travis
  - default to out-of-tree builds
  - make changing logfile safe via RCU
  - remove redundant tests
  - remove gtester test from docker
  - convert DEBUG_MMAP to tracepoints
  - remove hand rolled glob function
  - trigger tcg re-configure when needed

# gpg: Signature made Thu 19 Dec 2019 08:24:08 GMT
# gpg:                using RSA key 6685AE99E75167BCAFC8DF35FBD0DB095A9E2A44
# gpg: Good signature from "Alex Bennée (Master Work Key) <alex.bennee@linaro.org>" [full]
# Primary key fingerprint: 6685 AE99 E751 67BC AFC8  DF35 FBD0 DB09 5A9E 2A44

* remotes/stsquad/tags/pull-tesing-and-misc-191219-1: (25 commits)
  tests/tcg: ensure we re-configure if configure.sh is updated
  trace: replace hand-crafted pattern_glob with g_pattern_match_simple
  linux-user: convert target_munmap debug to a tracepoint
  linux-user: log page table changes under -d page
  linux-user: add target_mmap_complete tracepoint
  linux-user: convert target_mmap debug to tracepoint
  linux-user: convert target_mprotect debug to tracepoint
  travis.yml: Remove the redundant clang-with-MAIN_SOFTMMU_TARGETS entry
  docker: gtester is no longer used
  Added tests for close and change of logfile.
  Add use of RCU for qemu_logfile.
  qemu_log_lock/unlock now preserves the qemu_logfile handle.
  Add a mutex to guarantee single writer to qemu_logfile handle.
  Cleaned up flow of code in qemu_set_log(), to simplify and clarify.
  Fix double free issue in qemu_set_log_filename().
  ci: build out-of-tree
  travis.yml: Enable builds on arm64, ppc64le and s390x
  tests/test-util-filemonitor: Skip test on non-x86 Travis containers
  tests/hd-geo-test: Skip test when images can not be created
  iotests: Skip test 079 if it is not possible to create large files
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2019-12-20 14:00:49 +00:00
commit f59b31e6d0
47 changed files with 486 additions and 216 deletions

View file

@ -22,7 +22,9 @@ macos_task:
install_script:
- brew install pkg-config python gnu-sed glib pixman make sdl2
script:
- ./configure --python=/usr/local/bin/python3 || { cat config.log; exit 1; }
- mkdir build
- cd build
- ../configure --python=/usr/local/bin/python3 || { cat config.log; exit 1; }
- gmake -j$(sysctl -n hw.ncpu)
- gmake check -j$(sysctl -n hw.ncpu)
@ -33,6 +35,8 @@ macos_xcode_task:
install_script:
- brew install pkg-config gnu-sed glib pixman make sdl2
script:
- ./configure --cc=clang || { cat config.log; exit 1; }
- mkdir build
- cd build
- ../configure --cc=clang || { cat config.log; exit 1; }
- gmake -j$(sysctl -n hw.ncpu)
- gmake check -j$(sysctl -n hw.ncpu)

View file

@ -6,7 +6,9 @@ build-system1:
script:
- apt-get install -y -qq libgtk-3-dev libvte-dev nettle-dev libcacard-dev
libusb-dev libvde-dev libspice-protocol-dev libgl1-mesa-dev libvdeplug-dev
- ./configure --enable-werror --target-list="aarch64-softmmu alpha-softmmu
- mkdir build
- cd build
- ../configure --enable-werror --target-list="aarch64-softmmu alpha-softmmu
cris-softmmu hppa-softmmu lm32-softmmu moxie-softmmu microblazeel-softmmu
mips64el-softmmu m68k-softmmu ppc-softmmu riscv64-softmmu sparc-softmmu"
- make -j2
@ -16,7 +18,9 @@ build-system2:
script:
- apt-get install -y -qq libsdl2-dev libgcrypt-dev libbrlapi-dev libaio-dev
libfdt-dev liblzo2-dev librdmacm-dev libibverbs-dev libibumad-dev
- ./configure --enable-werror --target-list="tricore-softmmu unicore32-softmmu
- mkdir build
- cd build
- ../configure --enable-werror --target-list="tricore-softmmu unicore32-softmmu
microblaze-softmmu mips-softmmu riscv32-softmmu s390x-softmmu sh4-softmmu
sparc64-softmmu x86_64-softmmu xtensa-softmmu nios2-softmmu or1k-softmmu"
- make -j2
@ -24,7 +28,9 @@ build-system2:
build-disabled:
script:
- ./configure --enable-werror --disable-rdma --disable-slirp --disable-curl
- mkdir build
- cd build
- ../configure --enable-werror --disable-rdma --disable-slirp --disable-curl
--disable-capstone --disable-live-block-migration --disable-glusterfs
--disable-replication --disable-coroutine-pool --disable-smartcard
--disable-guest-agent --disable-curses --disable-libxml2 --disable-tpm
@ -37,7 +43,9 @@ build-disabled:
build-tcg-disabled:
script:
- apt-get install -y -qq clang libgtk-3-dev libusb-dev
- ./configure --cc=clang --enable-werror --disable-tcg --audio-drv-list=""
- mkdir build
- cd build
- ../configure --cc=clang --enable-werror --disable-tcg --audio-drv-list=""
- make -j2
- make check-unit
- make check-qapi-schema
@ -52,7 +60,9 @@ build-tcg-disabled:
build-user:
script:
- ./configure --enable-werror --disable-system --disable-guest-agent
- mkdir build
- cd build
- ../configure --enable-werror --disable-system --disable-guest-agent
--disable-capstone --disable-slirp --disable-fdt
- make -j2
- make run-tcg-tests-i386-linux-user run-tcg-tests-x86_64-linux-user
@ -61,7 +71,9 @@ build-clang:
script:
- apt-get install -y -qq clang libsdl2-dev libattr1-dev libcap-ng-dev
xfslibs-dev libiscsi-dev libnfs-dev libseccomp-dev gnutls-dev librbd-dev
- ./configure --cc=clang --cxx=clang++ --enable-werror
- mkdir build
- cd build
- ../configure --cc=clang --cxx=clang++ --enable-werror
--target-list="alpha-softmmu arm-softmmu m68k-softmmu mips64-softmmu
ppc-softmmu s390x-softmmu x86_64-softmmu arm-linux-user"
- make -j2
@ -70,7 +82,9 @@ build-clang:
build-tci:
script:
- TARGETS="aarch64 alpha arm hppa m68k microblaze moxie ppc64 s390x x86_64"
- ./configure --enable-tcg-interpreter
- mkdir build
- cd build
- ../configure --enable-tcg-interpreter
--target-list="$(for tg in $TARGETS; do echo -n ${tg}'-softmmu '; done)"
- make -j2
- make tests/boot-serial-test tests/cdrom-test tests/pxe-test

View file

@ -35,5 +35,7 @@ build:
options: "-e HOME=/root"
ci:
- unset CC
- ./configure ${QEMU_CONFIGURE_OPTS} --target-list=${TARGET_LIST}
- mkdir build
- cd build
- ../configure ${QEMU_CONFIGURE_OPTS} --target-list=${TARGET_LIST}
- make -j$(($(getconf _NPROCESSORS_ONLN) + 1))

View file

@ -73,8 +73,8 @@ notifications:
env:
global:
- SRC_DIR="."
- BUILD_DIR="."
- SRC_DIR=".."
- BUILD_DIR="build"
- BASE_CONFIG="--disable-docs --disable-tools"
- TEST_CMD="make check V=1"
# This is broadly a list of "mainline" softmmu targets which have support across the major distros
@ -180,18 +180,13 @@ matrix:
compiler: clang
- env:
- CONFIG="--disable-user --target-list=${MAIN_SOFTMMU_TARGETS}"
- CACHE_NAME="${TRAVIS_BRANCH}-linux-clang-default"
compiler: clang
- env:
- CONFIG="--target-list=${MAIN_SOFTMMU_TARGETS} "
- CACHE_NAME="${TRAVIS_BRANCH}-linux-clang-sanitize"
compiler: clang
before_script:
- ./configure ${CONFIG} --extra-cflags="-fsanitize=undefined -Werror" || { cat config.log && exit 1; }
- mkdir -p ${BUILD_DIR} && cd ${BUILD_DIR}
- ${SRC_DIR}/configure ${CONFIG} --extra-cflags="-fsanitize=undefined -Werror" || { cat config.log && exit 1; }
- env:
@ -214,10 +209,11 @@ matrix:
- TEST_CMD=""
# We manually include builds which we disable "make check" for
# Check the TCG interpreter (TCI)
- env:
- CONFIG="--enable-debug --enable-tcg-interpreter"
- TEST_CMD=""
- CONFIG="--enable-debug-tcg --enable-tcg-interpreter --disable-kvm --disable-containers
--target-list=alpha-softmmu,arm-softmmu,hppa-softmmu,m68k-softmmu,microblaze-softmmu,moxie-softmmu,ppc-softmmu,s390x-softmmu,x86_64-softmmu"
- TEST_CMD="make check-qtest check-tcg V=1"
# We don't need to exercise every backend with every front-end
@ -322,7 +318,8 @@ matrix:
- CONFIG="--cc=gcc-9 --cxx=g++-9 --disable-pie --disable-linux-user"
- TEST_CMD=""
before_script:
- ./configure ${CONFIG} --extra-cflags="-g3 -O0 -Wno-error=stringop-truncation -fsanitize=thread -fuse-ld=gold" || { cat config.log && exit 1; }
- mkdir -p ${BUILD_DIR} && cd ${BUILD_DIR}
- ${SRC_DIR}/configure ${CONFIG} --extra-cflags="-g3 -O0 -Wno-error=stringop-truncation -fsanitize=thread -fuse-ld=gold" || { cat config.log && exit 1; }
# Run check-tcg against linux-user
@ -353,6 +350,92 @@ matrix:
- TEST_CMD="make -j3 check-tcg V=1"
- CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-debug-tcg"
- arch: arm64
dist: xenial
addons:
apt_packages:
- libaio-dev
- libattr1-dev
- libbrlapi-dev
- libcap-ng-dev
- libgcrypt20-dev
- libgnutls28-dev
- libgtk-3-dev
- libiscsi-dev
- liblttng-ust-dev
- libncurses5-dev
- libnfs-dev
- libnss3-dev
- libpixman-1-dev
- libpng-dev
- librados-dev
- libsdl2-dev
- libseccomp-dev
- liburcu-dev
- libusb-1.0-0-dev
- libvdeplug-dev
- libvte-2.91-dev
env:
- TEST_CMD="make check check-tcg V=1"
- CONFIG="--disable-containers --target-list=${MAIN_SOFTMMU_TARGETS}"
- arch: ppc64le
dist: xenial
addons:
apt_packages:
- libaio-dev
- libattr1-dev
- libbrlapi-dev
- libcap-ng-dev
- libgcrypt20-dev
- libgnutls28-dev
- libgtk-3-dev
- libiscsi-dev
- liblttng-ust-dev
- libncurses5-dev
- libnfs-dev
- libnss3-dev
- libpixman-1-dev
- libpng-dev
- librados-dev
- libsdl2-dev
- libseccomp-dev
- liburcu-dev
- libusb-1.0-0-dev
- libvdeplug-dev
- libvte-2.91-dev
env:
- TEST_CMD="make check check-tcg V=1"
- CONFIG="--disable-containers --target-list=${MAIN_SOFTMMU_TARGETS},ppc64le-linux-user"
- arch: s390x
dist: bionic
addons:
apt_packages:
- libaio-dev
- libattr1-dev
- libbrlapi-dev
- libcap-ng-dev
- libgcrypt20-dev
- libgnutls28-dev
- libgtk-3-dev
- libiscsi-dev
- liblttng-ust-dev
- libncurses5-dev
- libnfs-dev
- libnss3-dev
- libpixman-1-dev
- libpng-dev
- librados-dev
- libsdl2-dev
- libseccomp-dev
- liburcu-dev
- libusb-1.0-0-dev
- libvdeplug-dev
- libvte-2.91-dev
env:
- TEST_CMD="make check check-tcg V=1"
- CONFIG="--disable-containers --target-list=${MAIN_SOFTMMU_TARGETS},s390x-linux-user"
# Release builds
# The make-release script expect a QEMU version, so our tag must start with a 'v'.
@ -373,5 +456,6 @@ matrix:
- make -C ${SRC_DIR} qemu-${QEMU_VERSION}.tar.bz2
- ls -l ${SRC_DIR}/qemu-${QEMU_VERSION}.tar.bz2
- tar -xf ${SRC_DIR}/qemu-${QEMU_VERSION}.tar.bz2 && cd qemu-${QEMU_VERSION}
- ./configure ${BASE_CONFIG} ${CONFIG} || { cat config.log && exit 1; }
- mkdir -p release-build && cd release-build
- ../configure ${BASE_CONFIG} ${CONFIG} || { cat config.log && exit 1; }
- make install

View file

@ -156,7 +156,7 @@ static inline tcg_target_ulong cpu_tb_exec(CPUState *cpu, TranslationBlock *itb)
#if defined(DEBUG_DISAS)
if (qemu_loglevel_mask(CPU_LOG_TB_CPU)
&& qemu_log_in_addr_range(itb->pc)) {
qemu_log_lock();
FILE *logfile = qemu_log_lock();
int flags = 0;
if (qemu_loglevel_mask(CPU_LOG_TB_FPU)) {
flags |= CPU_DUMP_FPU;
@ -165,7 +165,7 @@ static inline tcg_target_ulong cpu_tb_exec(CPUState *cpu, TranslationBlock *itb)
flags |= CPU_DUMP_CCOP;
#endif
log_cpu_state(cpu, flags);
qemu_log_unlock();
qemu_log_unlock(logfile);
}
#endif /* DEBUG_DISAS */

View file

@ -1804,7 +1804,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM) &&
qemu_log_in_addr_range(tb->pc)) {
qemu_log_lock();
FILE *logfile = qemu_log_lock();
qemu_log("OUT: [size=%d]\n", gen_code_size);
if (tcg_ctx->data_gen_ptr) {
size_t code_size = tcg_ctx->data_gen_ptr - tb->tc.ptr;
@ -1829,7 +1829,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
}
qemu_log("\n");
qemu_log_flush();
qemu_log_unlock();
qemu_log_unlock(logfile);
}
#endif

View file

@ -138,11 +138,11 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
&& qemu_log_in_addr_range(db->pc_first)) {
qemu_log_lock();
FILE *logfile = qemu_log_lock();
qemu_log("----------------\n");
ops->disas_log(db, cpu);
qemu_log("\n");
qemu_log_unlock();
qemu_log_unlock(logfile);
}
#endif
}

View file

@ -963,7 +963,7 @@ int main(int argc, char **argv)
if (qemu_loglevel_mask(CPU_LOG_PAGE)) {
qemu_log("guest_base 0x%lx\n", guest_base);
log_page_dump();
log_page_dump("binary load");
qemu_log("start_brk 0x" TARGET_ABI_FMT_lx "\n", info->start_brk);
qemu_log("end_code 0x" TARGET_ABI_FMT_lx "\n", info->end_code);

9
configure vendored
View file

@ -302,6 +302,7 @@ audio_win_int=""
libs_qga=""
debug_info="yes"
stack_protector=""
use_containers="yes"
if test -e "$source_path/.git"
then
@ -1535,6 +1536,10 @@ for opt do
;;
--disable-plugins) plugins="no"
;;
--enable-containers) use_containers="yes"
;;
--disable-containers) use_containers="no"
;;
*)
echo "ERROR: unknown option $opt"
echo "Try '$0 --help' for more information"
@ -1718,6 +1723,7 @@ Advanced options (experts only):
track the maximum stack usage of stacks created by qemu_alloc_stack
--enable-plugins
enable plugins via shared library loading
--disable-containers don't use containers for cross-building
Optional features, enabled with --enable-FEATURE and
disabled with --disable-FEATURE, default is enabled if available:
@ -6399,6 +6405,7 @@ else
echo "local state directory queried at runtime"
echo "Windows SDK $win_sdk"
fi
echo "Build directory $(pwd)"
echo "Source path $source_path"
echo "GIT binary $git"
echo "GIT submodules $git_submodules"
@ -7996,7 +8003,7 @@ done
(for i in $cross_cc_vars; do
export $i
done
export target_list source_path
export target_list source_path use_containers
$source_path/tests/tcg/configure.sh)
# temporary config to build submodules

View file

@ -418,13 +418,15 @@ access, so they SHOULD NOT be exposed to external interfaces if you are
concerned about attackers taking control of the guest and potentially
exploiting a QEMU security bug to compromise the host.
QEMU binary
-----------
QEMU binaries
-------------
By default, qemu-system-x86_64 is searched in $PATH to run the guest. If there
isn't one, or if it is older than 2.10, the test won't work. In this case,
provide the QEMU binary in env var: ``QEMU=/path/to/qemu-2.10+``.
Likewise the path to qemu-img can be set in QEMU_IMG environment variable.
Make jobs
---------

4
exec.c
View file

@ -1225,13 +1225,13 @@ void cpu_abort(CPUState *cpu, const char *fmt, ...)
fprintf(stderr, "\n");
cpu_dump_state(cpu, stderr, CPU_DUMP_FPU | CPU_DUMP_CCOP);
if (qemu_log_separate()) {
qemu_log_lock();
FILE *logfile = qemu_log_lock();
qemu_log("qemu: fatal: ");
qemu_log_vprintf(fmt, ap2);
qemu_log("\n");
log_cpu_state(cpu, CPU_DUMP_FPU | CPU_DUMP_CCOP);
qemu_log_flush();
qemu_log_unlock();
qemu_log_unlock(logfile);
qemu_log_close();
}
va_end(ap2);

View file

@ -247,8 +247,8 @@ int can_sja_accept_filter(CanSJA1000State *s,
static void can_display_msg(const char *prefix, const qemu_can_frame *msg)
{
int i;
FILE *logfile = qemu_log_lock();
qemu_log_lock();
qemu_log("%s%03X [%01d] %s %s",
prefix,
msg->can_id & QEMU_CAN_EFF_MASK,
@ -261,7 +261,7 @@ static void can_display_msg(const char *prefix, const qemu_can_frame *msg)
}
qemu_log("\n");
qemu_log_flush();
qemu_log_unlock();
qemu_log_unlock(logfile);
}
static void buff2frame_pel(const uint8_t *buff, qemu_can_frame *frame)

View file

@ -15,8 +15,15 @@
*/
static inline void log_cpu_state(CPUState *cpu, int flags)
{
QemuLogFile *logfile;
if (qemu_log_enabled()) {
cpu_dump_state(cpu, qemu_logfile, flags);
rcu_read_lock();
logfile = atomic_rcu_read(&qemu_logfile);
if (logfile) {
cpu_dump_state(cpu, logfile->fd, flags);
}
rcu_read_unlock();
}
}
@ -40,19 +47,36 @@ static inline void log_cpu_state_mask(int mask, CPUState *cpu, int flags)
static inline void log_target_disas(CPUState *cpu, target_ulong start,
target_ulong len)
{
target_disas(qemu_logfile, cpu, start, len);
QemuLogFile *logfile;
rcu_read_lock();
logfile = atomic_rcu_read(&qemu_logfile);
if (logfile) {
target_disas(logfile->fd, cpu, start, len);
}
rcu_read_unlock();
}
static inline void log_disas(void *code, unsigned long size)
{
disas(qemu_logfile, code, size);
QemuLogFile *logfile;
rcu_read_lock();
logfile = atomic_rcu_read(&qemu_logfile);
if (logfile) {
disas(logfile->fd, code, size);
}
rcu_read_unlock();
}
#if defined(CONFIG_USER_ONLY)
/* page_dump() output to the log file: */
static inline void log_page_dump(void)
static inline void log_page_dump(const char *operation)
{
page_dump(qemu_logfile);
FILE *logfile = qemu_log_lock();
if (logfile) {
qemu_log("page layout changed following %s\n", operation);
page_dump(logfile);
}
qemu_log_unlock(logfile);
}
#endif
#endif

View file

@ -3,9 +3,16 @@
/* A small part of this API is split into its own header */
#include "qemu/log-for-trace.h"
#include "qemu/rcu.h"
typedef struct QemuLogFile {
struct rcu_head rcu;
FILE *fd;
} QemuLogFile;
/* Private global variable, don't use */
extern FILE *qemu_logfile;
extern QemuLogFile *qemu_logfile;
/*
* The new API:
@ -25,7 +32,16 @@ static inline bool qemu_log_enabled(void)
*/
static inline bool qemu_log_separate(void)
{
return qemu_logfile != NULL && qemu_logfile != stderr;
QemuLogFile *logfile;
bool res = false;
rcu_read_lock();
logfile = atomic_rcu_read(&qemu_logfile);
if (logfile && logfile->fd != stderr) {
res = true;
}
rcu_read_unlock();
return res;
}
#define CPU_LOG_TB_OUT_ASM (1 << 0)
@ -53,14 +69,25 @@ static inline bool qemu_log_separate(void)
* qemu_loglevel is never set when qemu_logfile is unset.
*/
static inline void qemu_log_lock(void)
static inline FILE *qemu_log_lock(void)
{
qemu_flockfile(qemu_logfile);
QemuLogFile *logfile;
rcu_read_lock();
logfile = atomic_rcu_read(&qemu_logfile);
if (logfile) {
qemu_flockfile(logfile->fd);
return logfile->fd;
} else {
return NULL;
}
}
static inline void qemu_log_unlock(void)
static inline void qemu_log_unlock(FILE *fd)
{
qemu_funlockfile(qemu_logfile);
if (fd) {
qemu_funlockfile(fd);
}
rcu_read_unlock();
}
/* Logging functions: */
@ -70,9 +97,14 @@ static inline void qemu_log_unlock(void)
static inline void GCC_FMT_ATTR(1, 0)
qemu_log_vprintf(const char *fmt, va_list va)
{
if (qemu_logfile) {
vfprintf(qemu_logfile, fmt, va);
QemuLogFile *logfile;
rcu_read_lock();
logfile = atomic_rcu_read(&qemu_logfile);
if (logfile) {
vfprintf(logfile->fd, fmt, va);
}
rcu_read_unlock();
}
/* log only if a bit is set on the current loglevel mask:

View file

@ -826,7 +826,7 @@ int main(int argc, char **argv, char **envp)
if (qemu_loglevel_mask(CPU_LOG_PAGE)) {
qemu_log("guest_base 0x%lx\n", guest_base);
log_page_dump();
log_page_dump("binary load");
qemu_log("start_brk 0x" TARGET_ABI_FMT_lx "\n", info->start_brk);
qemu_log("end_code 0x" TARGET_ABI_FMT_lx "\n", info->end_code);

View file

@ -17,11 +17,10 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "qemu/osdep.h"
#include "trace.h"
#include "exec/log.h"
#include "qemu.h"
//#define DEBUG_MMAP
static pthread_mutex_t mmap_mutex = PTHREAD_MUTEX_INITIALIZER;
static __thread int mmap_lock_count;
@ -66,13 +65,7 @@ int target_mprotect(abi_ulong start, abi_ulong len, int prot)
abi_ulong end, host_start, host_end, addr;
int prot1, ret;
#ifdef DEBUG_MMAP
printf("mprotect: start=0x" TARGET_ABI_FMT_lx
"len=0x" TARGET_ABI_FMT_lx " prot=%c%c%c\n", start, len,
prot & PROT_READ ? 'r' : '-',
prot & PROT_WRITE ? 'w' : '-',
prot & PROT_EXEC ? 'x' : '-');
#endif
trace_target_mprotect(start, len, prot);
if ((start & ~TARGET_PAGE_MASK) != 0)
return -TARGET_EINVAL;
@ -369,32 +362,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
abi_ulong ret, end, real_start, real_end, retaddr, host_offset, host_len;
mmap_lock();
#ifdef DEBUG_MMAP
{
printf("mmap: start=0x" TARGET_ABI_FMT_lx
" len=0x" TARGET_ABI_FMT_lx " prot=%c%c%c flags=",
start, len,
prot & PROT_READ ? 'r' : '-',
prot & PROT_WRITE ? 'w' : '-',
prot & PROT_EXEC ? 'x' : '-');
if (flags & MAP_FIXED)
printf("MAP_FIXED ");
if (flags & MAP_ANONYMOUS)
printf("MAP_ANON ");
switch(flags & MAP_TYPE) {
case MAP_PRIVATE:
printf("MAP_PRIVATE ");
break;
case MAP_SHARED:
printf("MAP_SHARED ");
break;
default:
printf("[MAP_TYPE=0x%x] ", flags & MAP_TYPE);
break;
}
printf("fd=%d offset=" TARGET_ABI_FMT_lx "\n", fd, offset);
}
#endif
trace_target_mmap(start, len, prot, flags, fd, offset);
if (!len) {
errno = EINVAL;
@ -569,11 +537,10 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
the_end1:
page_set_flags(start, start + len, prot | PAGE_VALID);
the_end:
#ifdef DEBUG_MMAP
printf("ret=0x" TARGET_ABI_FMT_lx "\n", start);
page_dump(stdout);
printf("\n");
#endif
trace_target_mmap_complete(start);
if (qemu_loglevel_mask(CPU_LOG_PAGE)) {
log_page_dump(__func__);
}
tb_invalidate_phys_range(start, start + len);
mmap_unlock();
return start;
@ -628,11 +595,8 @@ int target_munmap(abi_ulong start, abi_ulong len)
abi_ulong end, real_start, real_end, addr;
int prot, ret;
#ifdef DEBUG_MMAP
printf("munmap: start=0x" TARGET_ABI_FMT_lx " len=0x"
TARGET_ABI_FMT_lx "\n",
start, len);
#endif
trace_target_munmap(start, len);
if (start & ~TARGET_PAGE_MASK)
return -TARGET_EINVAL;
len = TARGET_PAGE_ALIGN(len);

View file

@ -11,3 +11,9 @@ user_handle_signal(void *env, int target_sig) "env=%p signal %d"
user_host_signal(void *env, int host_sig, int target_sig) "env=%p signal %d (target %d("
user_queue_signal(void *env, int target_sig) "env=%p signal %d"
user_s390x_restore_sigregs(void *env, uint64_t sc_psw_addr, uint64_t env_psw_addr) "env=%p frame psw.addr 0x%"PRIx64 " current psw.addr 0x%"PRIx64
# mmap.c
target_mprotect(uint64_t start, uint64_t len, int flags) "start=0x%"PRIx64 " len=0x%"PRIx64 " prot=0x%x"
target_mmap(uint64_t start, uint64_t len, int pflags, int mflags, int fd, uint64_t offset) "start=0x%"PRIx64 " len=0x%"PRIx64 " prot=0x%x flags=0x%x fd=%d offset=0x%"PRIx64
target_mmap_complete(uint64_t retaddr) "retaddr=0x%"PRIx64
target_munmap(uint64_t start, uint64_t len) "start=0x%"PRIx64" len=0x%"PRIx64

View file

@ -76,8 +76,7 @@ QEMU_BUILD_BUG_ON(offsetof(qemu_can_frame, data)
static void can_host_socketcan_display_msg(struct qemu_can_frame *msg)
{
int i;
qemu_log_lock();
FILE *logfile = qemu_log_lock();
qemu_log("[cansocketcan]: %03X [%01d] %s %s",
msg->can_id & QEMU_CAN_EFF_MASK,
msg->can_dlc,
@ -89,7 +88,7 @@ static void can_host_socketcan_display_msg(struct qemu_can_frame *msg)
}
qemu_log("\n");
qemu_log_flush();
qemu_log_unlock();
qemu_log_unlock(logfile);
}
static void can_host_socketcan_read(void *opaque)

View file

@ -3273,11 +3273,11 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
#if !DISAS_CRIS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
&& qemu_log_in_addr_range(pc_start)) {
qemu_log_lock();
FILE *logfile = qemu_log_lock();
qemu_log("--------------\n");
qemu_log("IN: %s\n", lookup_symbol(pc_start));
log_target_disas(cs, pc_start, dc->pc - pc_start);
qemu_log_unlock();
qemu_log_unlock(logfile);
}
#endif
#endif

View file

@ -2502,14 +2502,15 @@ static void gen_unknown_opcode(CPUX86State *env, DisasContext *s)
gen_illegal_opcode(s);
if (qemu_loglevel_mask(LOG_UNIMP)) {
FILE *logfile = qemu_log_lock();
target_ulong pc = s->pc_start, end = s->pc;
qemu_log_lock();
qemu_log("ILLOPC: " TARGET_FMT_lx ":", pc);
for (; pc < end; ++pc) {
qemu_log(" %02x", cpu_ldub_code(env, pc));
}
qemu_log("\n");
qemu_log_unlock();
qemu_log_unlock(logfile);
}
}

View file

@ -1137,10 +1137,10 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
&& qemu_log_in_addr_range(pc_start)) {
qemu_log_lock();
FILE *logfile = qemu_log_lock();
qemu_log("\n");
log_target_disas(cs, pc_start, dc->pc - pc_start);
qemu_log_unlock();
qemu_log_unlock(logfile);
}
#endif
}

View file

@ -1765,10 +1765,10 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
#if !SIM_COMPAT
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
&& qemu_log_in_addr_range(pc_start)) {
qemu_log_lock();
FILE *logfile = qemu_log_lock();
qemu_log("--------------\n");
log_target_disas(cs, pc_start, dc->pc - pc_start);
qemu_log_unlock();
qemu_log_unlock(logfile);
}
#endif
#endif

View file

@ -892,11 +892,11 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
&& qemu_log_in_addr_range(tb->pc)) {
qemu_log_lock();
FILE *logfile = qemu_log_lock();
qemu_log("IN: %s\n", lookup_symbol(tb->pc));
log_target_disas(cs, tb->pc, dc->pc - tb->pc);
qemu_log("\n");
qemu_log_unlock();
qemu_log_unlock(logfile);
}
#endif
}

View file

@ -2388,7 +2388,6 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
dc->zero = NULL;
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
qemu_log_lock();
qemu_log("IN: %s\n", lookup_symbol(pc_start));
}
gen_tb_start(tb);
@ -2417,11 +2416,6 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
gen_tb_end(tb, num_insns);
tb->size = dc->pc - pc_start;
tb->icount = num_insns;
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
qemu_log("\n");
qemu_log_unlock();
}
}
void restore_state_to_opc(CPUTLGState *env, TranslationBlock *tb,

View file

@ -1994,12 +1994,12 @@ done_generating:
#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
&& qemu_log_in_addr_range(pc_start)) {
qemu_log_lock();
FILE *logfile = qemu_log_lock();
qemu_log("----------------\n");
qemu_log("IN: %s\n", lookup_symbol(pc_start));
log_target_disas(cs, pc_start, dc->pc - pc_start);
qemu_log("\n");
qemu_log_unlock();
qemu_log_unlock(logfile);
}
#endif
tb->size = dc->pc - pc_start;

View file

@ -1085,7 +1085,7 @@ void tcg_prologue_init(TCGContext *s)
#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM)) {
qemu_log_lock();
FILE *logfile = qemu_log_lock();
qemu_log("PROLOGUE: [size=%zu]\n", prologue_size);
if (s->data_gen_ptr) {
size_t code_size = s->data_gen_ptr - buf0;
@ -1110,7 +1110,7 @@ void tcg_prologue_init(TCGContext *s)
}
qemu_log("\n");
qemu_log_flush();
qemu_log_unlock();
qemu_log_unlock(logfile);
}
#endif
@ -2114,9 +2114,17 @@ static void tcg_dump_ops(TCGContext *s, bool have_prefs)
}
if (have_prefs || op->life) {
for (; col < 40; ++col) {
putc(' ', qemu_logfile);
QemuLogFile *logfile;
rcu_read_lock();
logfile = atomic_rcu_read(&qemu_logfile);
if (logfile) {
for (; col < 40; ++col) {
putc(' ', logfile->fd);
}
}
rcu_read_unlock();
}
if (op->life) {
@ -4041,11 +4049,11 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb)
#ifdef DEBUG_DISAS
if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)
&& qemu_log_in_addr_range(tb->pc))) {
qemu_log_lock();
FILE *logfile = qemu_log_lock();
qemu_log("OP:\n");
tcg_dump_ops(s, false);
qemu_log("\n");
qemu_log_unlock();
qemu_log_unlock(logfile);
}
#endif
@ -4086,11 +4094,11 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb)
#ifdef DEBUG_DISAS
if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_IND)
&& qemu_log_in_addr_range(tb->pc))) {
qemu_log_lock();
FILE *logfile = qemu_log_lock();
qemu_log("OP before indirect lowering:\n");
tcg_dump_ops(s, false);
qemu_log("\n");
qemu_log_unlock();
qemu_log_unlock(logfile);
}
#endif
/* Replace indirect temps with direct temps. */
@ -4107,11 +4115,11 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb)
#ifdef DEBUG_DISAS
if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT)
&& qemu_log_in_addr_range(tb->pc))) {
qemu_log_lock();
FILE *logfile = qemu_log_lock();
qemu_log("OP after optimization and liveness analysis:\n");
tcg_dump_ops(s, true);
qemu_log("\n");
qemu_log_unlock();
qemu_log_unlock(logfile);
}
#endif

View file

@ -53,12 +53,7 @@ check_qemu()
INVOCATION="$@"
fi
if command -v gtester > /dev/null 2>&1 && \
gtester --version > /dev/null 2>&1; then
make $MAKEFLAGS $INVOCATION
else
echo "No working gtester, skipping make $INVOCATION"
fi
make $MAKEFLAGS $INVOCATION
}
test_fail()

View file

@ -34,8 +34,13 @@ static char *create_test_img(int secs)
fd = mkstemp(template);
g_assert(fd >= 0);
ret = ftruncate(fd, (off_t)secs * 512);
g_assert(ret == 0);
close(fd);
if (ret) {
free(template);
template = NULL;
}
return template;
}
@ -934,6 +939,10 @@ int main(int argc, char **argv)
for (i = 0; i < backend_last; i++) {
if (img_secs[i] >= 0) {
img_file_name[i] = create_test_img(img_secs[i]);
if (!img_file_name[i]) {
g_test_message("Could not create test images.");
goto test_add_done;
}
} else {
img_file_name[i] = NULL;
}
@ -965,6 +974,7 @@ int main(int argc, char **argv)
"skipping hd-geo/override/* tests");
}
test_add_done:
ret = g_test_run();
for (i = 0; i < backend_last; i++) {

View file

@ -59,10 +59,7 @@ fi
# Sanity check: For raw, we require a file system that permits the creation
# of a HUGE (but very sparse) file. Check we can create it before continuing.
if [ "$IMGFMT" = "raw" ]; then
if ! truncate --size=5T "$TEST_IMG"; then
_notrun "file system on $TEST_DIR does not support large enough files"
fi
rm "$TEST_IMG"
_require_large_file 5T
fi
echo

View file

@ -49,6 +49,9 @@ _supported_fmt qcow2
_supported_proto file
_supported_os Linux
# The repair process will create a large file - so check for availability first
_require_large_file 64G
rt_offset=65536 # 0x10000 (XXX: just an assumption)
rb_offset=131072 # 0x20000 (XXX: just an assumption)
l1_offset=196608 # 0x30000 (XXX: just an assumption)

View file

@ -39,6 +39,9 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
_supported_fmt qcow2
_supported_proto file nfs
# Some containers (e.g. non-x86 on Travis) do not allow large files
_require_large_file 4G
echo "=== Check option preallocation and cluster_size ==="
echo
cluster_sizes="16384 32768 65536 131072 262144 524288 1048576 2097152 4194304"

View file

@ -42,10 +42,8 @@ echo "== Creating huge file =="
# Sanity check: We require a file system that permits the creation
# of a HUGE (but very sparse) file. tmpfs works, ext4 does not.
if ! truncate --size=513T "$TEST_IMG"; then
_notrun "file system on $TEST_DIR does not support large enough files"
fi
rm "$TEST_IMG"
_require_large_file 513T
IMGOPTS='cluster_size=2M,refcount_bits=1' _make_test_img 513T
echo "== Populating refcounts =="

View file

@ -643,5 +643,15 @@ _require_drivers()
done
}
# Check that we have a file system that allows huge (but very sparse) files
#
_require_large_file()
{
if ! truncate --size="$1" "$TEST_IMG"; then
_notrun "file system on $TEST_DIR does not support large enough files"
fi
rm "$TEST_IMG"
}
# make sure this script returns success
true

View file

@ -13,6 +13,6 @@ DOCKER_IMAGE:=
ifneq ($(DOCKER_IMAGE),)
build-tcg-tests-$(PROBE_TARGET): docker-image-$(DOCKER_IMAGE)
endif
$(BUILD_DIR)/tests/tcg/config_$(PROBE_TARGET).mak: config-host.mak
config-host.mak: $(SRC_PATH)/tests/tcg/configure.sh
endif

View file

@ -36,8 +36,10 @@ TMPC="${TMPDIR1}/qemu-conf.c"
TMPE="${TMPDIR1}/qemu-conf.exe"
container="no"
if has "docker" || has "podman"; then
container=$($python $source_path/tests/docker/docker.py probe)
if test $use_containers = "yes"; then
if has "docker" || has "podman"; then
container=$($python $source_path/tests/docker/docker.py probe)
fi
fi
# cross compilers defaults, can be overridden with --cross-cc-ARCH

View file

@ -108,6 +108,82 @@ static void test_parse_path(gconstpointer data)
error_free_or_abort(&err);
}
static void test_logfile_write(gconstpointer data)
{
QemuLogFile *logfile;
QemuLogFile *logfile2;
gchar const *dir = data;
Error *err = NULL;
g_autofree gchar *file_path;
g_autofree gchar *file_path1;
FILE *orig_fd;
/*
* Before starting test, set log flags, to ensure the file gets
* opened below with the call to qemu_set_log_filename().
* In cases where a logging backend other than log is used,
* this is needed.
*/
qemu_set_log(CPU_LOG_TB_OUT_ASM);
file_path = g_build_filename(dir, "qemu_test_log_write0.log", NULL);
file_path1 = g_build_filename(dir, "qemu_test_log_write1.log", NULL);
/*
* Test that even if an open file handle is changed,
* our handle remains valid due to RCU.
*/
qemu_set_log_filename(file_path, &err);
g_assert(!err);
rcu_read_lock();
logfile = atomic_rcu_read(&qemu_logfile);
orig_fd = logfile->fd;
g_assert(logfile && logfile->fd);
fprintf(logfile->fd, "%s 1st write to file\n", __func__);
fflush(logfile->fd);
/* Change the logfile and ensure that the handle is still valid. */
qemu_set_log_filename(file_path1, &err);
g_assert(!err);
logfile2 = atomic_rcu_read(&qemu_logfile);
g_assert(logfile->fd == orig_fd);
g_assert(logfile2->fd != logfile->fd);
fprintf(logfile->fd, "%s 2nd write to file\n", __func__);
fflush(logfile->fd);
rcu_read_unlock();
}
static void test_logfile_lock(gconstpointer data)
{
FILE *logfile;
gchar const *dir = data;
Error *err = NULL;
g_autofree gchar *file_path;
file_path = g_build_filename(dir, "qemu_test_logfile_lock0.log", NULL);
/*
* Test the use of the logfile lock, such
* that even if an open file handle is closed,
* our handle remains valid for use due to RCU.
*/
qemu_set_log_filename(file_path, &err);
logfile = qemu_log_lock();
g_assert(logfile);
fprintf(logfile, "%s 1st write to file\n", __func__);
fflush(logfile);
/*
* Initiate a close file and make sure our handle remains
* valid since we still have the logfile lock.
*/
qemu_log_close();
fprintf(logfile, "%s 2nd write to file\n", __func__);
fflush(logfile);
qemu_log_unlock(logfile);
g_assert(!err);
}
/* Remove a directory and all its entries (non-recursive). */
static void rmdir_full(gchar const *root)
{
@ -134,6 +210,10 @@ int main(int argc, char **argv)
g_test_add_func("/logging/parse_range", test_parse_range);
g_test_add_data_func("/logging/parse_path", tmp_path, test_parse_path);
g_test_add_data_func("/logging/logfile_write_path",
tmp_path, test_logfile_write);
g_test_add_data_func("/logging/logfile_lock_path",
tmp_path, test_logfile_lock);
rc = g_test_run();

View file

@ -406,10 +406,21 @@ test_file_monitor_events(void)
char *pathdst = NULL;
QFileMonitorTestData data;
GHashTable *ids = g_hash_table_new(g_int64_hash, g_int64_equal);
char *travis_arch;
qemu_mutex_init(&data.lock);
data.records = NULL;
/*
* This test does not work on Travis LXD containers since some
* syscalls are blocked in that environment.
*/
travis_arch = getenv("TRAVIS_ARCH");
if (travis_arch && !g_str_equal(travis_arch, "x86_64")) {
g_test_skip("Test does not work on non-x86 Travis containers.");
return;
}
/*
* The file monitor needs the main loop running in
* order to receive events from inotify. We must

View file

@ -34,6 +34,7 @@ vm-help vm-test:
@echo " DEBUG=1 - Enable verbose output on host and interactive debugging"
@echo " V=1 - Enable verbose ouput on host and guest commands"
@echo " QEMU=/path/to/qemu - Change path to QEMU binary"
@echo " QEMU_IMG=/path/to/qemu-img - Change path to qemu-img tool"
vm-build-all: $(addprefix vm-build-, $(IMAGES))

View file

@ -152,6 +152,11 @@ def ssh_root_check(self, *cmd):
def build_image(self, img):
raise NotImplementedError
def exec_qemu_img(self, *args):
cmd = [os.environ.get("QEMU_IMG", "qemu-img")]
cmd.extend(list(args))
subprocess.check_call(cmd)
def add_source_dir(self, src_dir):
name = "data-" + hashlib.sha1(src_dir.encode("utf-8")).hexdigest()[:5]
tarfile = os.path.join(self._tmpdir, name + ".tar")

View file

@ -68,7 +68,7 @@ class CentosVM(basevm.BaseVM):
sys.stderr.write("Extracting the image...\n")
subprocess.check_call(["ln", "-f", cimg, img_tmp + ".xz"])
subprocess.check_call(["xz", "--keep", "-dvf", img_tmp + ".xz"])
subprocess.check_call(["qemu-img", "resize", img_tmp, "50G"])
self.exec_qemu_img("resize", img_tmp, "50G")
self.boot(img_tmp, extra_args = ["-cdrom", self._gen_cloud_init_iso()])
self.wait_ssh()
self.ssh_root_check("touch /etc/cloud/cloud-init.disabled")

View file

@ -74,9 +74,7 @@ class FedoraVM(basevm.BaseVM):
self.print_step("Preparing iso and disk image")
subprocess.check_call(["cp", "-f", cimg, iso])
subprocess.check_call(["qemu-img", "create", "-f", "qcow2",
img_tmp, self.size])
self.exec_qemu_img("create", "-f", "qcow2", img_tmp, self.size)
self.print_step("Booting installer")
self.boot(img_tmp, extra_args = [
"-bios", "pc-bios/bios-256k.bin",

View file

@ -82,8 +82,7 @@ class FreeBSDVM(basevm.BaseVM):
self.print_step("Preparing iso and disk image")
subprocess.check_call(["cp", "-f", cimg, iso_xz])
subprocess.check_call(["xz", "-dvf", iso_xz])
subprocess.check_call(["qemu-img", "create", "-f", "qcow2",
img_tmp, self.size])
self.exec_qemu_img("create", "-f", "qcow2", img_tmp, self.size)
self.print_step("Booting installer")
self.boot(img_tmp, extra_args = [

View file

@ -77,8 +77,7 @@ class NetBSDVM(basevm.BaseVM):
self.print_step("Preparing iso and disk image")
subprocess.check_call(["ln", "-f", cimg, iso])
subprocess.check_call(["qemu-img", "create", "-f", "qcow2",
img_tmp, self.size])
self.exec_qemu_img("create", "-f", "qcow2", img_tmp, self.size)
self.print_step("Booting installer")
self.boot(img_tmp, extra_args = [

View file

@ -73,8 +73,7 @@ class OpenBSDVM(basevm.BaseVM):
self.print_step("Preparing iso and disk image")
subprocess.check_call(["cp", "-f", cimg, iso])
subprocess.check_call(["qemu-img", "create", "-f", "qcow2",
img_tmp, self.size])
self.exec_qemu_img("create", "-f", "qcow2", img_tmp, self.size)
self.print_step("Booting installer")
self.boot(img_tmp, extra_args = [

View file

@ -70,7 +70,7 @@ class UbuntuX86VM(basevm.BaseVM):
sha256sum="28969840626d1ea80bb249c08eef1a4533e8904aa51a327b40f37ac4b4ff04ef")
img_tmp = img + ".tmp"
subprocess.check_call(["cp", "-f", cimg, img_tmp])
subprocess.check_call(["qemu-img", "resize", img_tmp, "50G"])
self.exec_qemu_img("resize", img_tmp, "50G")
self.boot(img_tmp, extra_args = ["-cdrom", self._gen_cloud_init_iso()])
self.wait_ssh()
self.ssh_root_check("touch /etc/cloud/cloud-init.disabled")

View file

@ -98,38 +98,6 @@ TraceEvent *trace_event_name(const char *name)
return NULL;
}
static bool pattern_glob(const char *pat, const char *ev)
{
while (*pat != '\0' && *ev != '\0') {
if (*pat == *ev) {
pat++;
ev++;
}
else if (*pat == '*') {
if (pattern_glob(pat, ev+1)) {
return true;
} else if (pattern_glob(pat+1, ev)) {
return true;
} else {
return false;
}
} else {
return false;
}
}
while (*pat == '*') {
pat++;
}
if (*pat == '\0' && *ev == '\0') {
return true;
} else {
return false;
}
}
void trace_event_iter_init(TraceEventIter *iter, const char *pattern)
{
iter->event = 0;
@ -148,8 +116,7 @@ TraceEvent *trace_event_iter_next(TraceEventIter *iter)
iter->group++;
}
if (!iter->pattern ||
pattern_glob(iter->pattern,
trace_event_get_name(ev))) {
g_pattern_match_simple(iter->pattern, trace_event_get_name(ev))) {
return ev;
}
}

View file

@ -24,9 +24,11 @@
#include "qapi/error.h"
#include "qemu/cutils.h"
#include "trace/control.h"
#include "qemu/thread.h"
static char *logfilename;
FILE *qemu_logfile;
static QemuMutex qemu_logfile_mutex;
QemuLogFile *qemu_logfile;
int qemu_loglevel;
static int log_append = 0;
static GArray *debug_regions;
@ -35,10 +37,14 @@ static GArray *debug_regions;
int qemu_log(const char *fmt, ...)
{
int ret = 0;
if (qemu_logfile) {
QemuLogFile *logfile;
rcu_read_lock();
logfile = atomic_rcu_read(&qemu_logfile);
if (logfile) {
va_list ap;
va_start(ap, fmt);
ret = vfprintf(qemu_logfile, fmt, ap);
ret = vfprintf(logfile->fd, fmt, ap);
va_end(ap);
/* Don't pass back error results. */
@ -46,57 +52,91 @@ int qemu_log(const char *fmt, ...)
ret = 0;
}
}
rcu_read_unlock();
return ret;
}
static void __attribute__((__constructor__)) qemu_logfile_init(void)
{
qemu_mutex_init(&qemu_logfile_mutex);
}
static void qemu_logfile_free(QemuLogFile *logfile)
{
g_assert(logfile);
if (logfile->fd != stderr) {
fclose(logfile->fd);
}
g_free(logfile);
}
static bool log_uses_own_buffers;
/* enable or disable low levels log */
void qemu_set_log(int log_flags)
{
bool need_to_open_file = false;
QemuLogFile *logfile;
qemu_loglevel = log_flags;
#ifdef CONFIG_TRACE_LOG
qemu_loglevel |= LOG_TRACE;
#endif
if (!qemu_logfile &&
(is_daemonized() ? logfilename != NULL : qemu_loglevel)) {
/*
* In all cases we only log if qemu_loglevel is set.
* Also:
* If not daemonized we will always log either to stderr
* or to a file (if there is a logfilename).
* If we are daemonized,
* we will only log if there is a logfilename.
*/
if (qemu_loglevel && (!is_daemonized() || logfilename)) {
need_to_open_file = true;
}
qemu_mutex_lock(&qemu_logfile_mutex);
if (qemu_logfile && !need_to_open_file) {
logfile = qemu_logfile;
atomic_rcu_set(&qemu_logfile, NULL);
call_rcu(logfile, qemu_logfile_free, rcu);
} else if (!qemu_logfile && need_to_open_file) {
logfile = g_new0(QemuLogFile, 1);
if (logfilename) {
qemu_logfile = fopen(logfilename, log_append ? "a" : "w");
if (!qemu_logfile) {
logfile->fd = fopen(logfilename, log_append ? "a" : "w");
if (!logfile->fd) {
g_free(logfile);
perror(logfilename);
_exit(1);
}
/* In case we are a daemon redirect stderr to logfile */
if (is_daemonized()) {
dup2(fileno(qemu_logfile), STDERR_FILENO);
fclose(qemu_logfile);
dup2(fileno(logfile->fd), STDERR_FILENO);
fclose(logfile->fd);
/* This will skip closing logfile in qemu_log_close() */
qemu_logfile = stderr;
logfile->fd = stderr;
}
} else {
/* Default to stderr if no log file specified */
assert(!is_daemonized());
qemu_logfile = stderr;
logfile->fd = stderr;
}
/* must avoid mmap() usage of glibc by setting a buffer "by hand" */
if (log_uses_own_buffers) {
static char logfile_buf[4096];
setvbuf(qemu_logfile, logfile_buf, _IOLBF, sizeof(logfile_buf));
setvbuf(logfile->fd, logfile_buf, _IOLBF, sizeof(logfile_buf));
} else {
#if defined(_WIN32)
/* Win32 doesn't support line-buffering, so use unbuffered output. */
setvbuf(qemu_logfile, NULL, _IONBF, 0);
setvbuf(logfile->fd, NULL, _IONBF, 0);
#else
setvbuf(qemu_logfile, NULL, _IOLBF, 0);
setvbuf(logfile->fd, NULL, _IOLBF, 0);
#endif
log_append = 1;
}
atomic_rcu_set(&qemu_logfile, logfile);
}
if (qemu_logfile &&
(is_daemonized() ? logfilename == NULL : !qemu_loglevel)) {
qemu_log_close();
}
qemu_mutex_unlock(&qemu_logfile_mutex);
}
void qemu_log_needs_buffers(void)
@ -113,6 +153,7 @@ void qemu_set_log_filename(const char *filename, Error **errp)
{
char *pidstr;
g_free(logfilename);
logfilename = NULL;
pidstr = strstr(filename, "%");
if (pidstr) {
@ -224,18 +265,29 @@ out:
/* fflush() the log file */
void qemu_log_flush(void)
{
fflush(qemu_logfile);
QemuLogFile *logfile;
rcu_read_lock();
logfile = atomic_rcu_read(&qemu_logfile);
if (logfile) {
fflush(logfile->fd);
}
rcu_read_unlock();
}
/* Close the log file */
void qemu_log_close(void)
{
if (qemu_logfile) {
if (qemu_logfile != stderr) {
fclose(qemu_logfile);
}
qemu_logfile = NULL;
QemuLogFile *logfile;
qemu_mutex_lock(&qemu_logfile_mutex);
logfile = qemu_logfile;
if (logfile) {
atomic_rcu_set(&qemu_logfile, NULL);
call_rcu(logfile, qemu_logfile_free, rcu);
}
qemu_mutex_unlock(&qemu_logfile_mutex);
}
const QEMULogItem qemu_log_items[] = {