29 Star 67 Fork 360

openEuler/qemu

【24.03 LTS】使用如下参数启动qemu-kvm报错,触发Assertion

已完成
缺陷
创建于  
2024-07-18 15:10

一、缺陷信息

内核信息:
4.19.90-89.11.v2401.ky10.x86_64
缺陷归属组件:
qemu-kvm
缺陷归属的版本:
qemu-8.2.0-13.oe2403.x86_64
缺陷简述:
使用基于openEuler24.03环境构建容器,在该容器中运行NestOS构建程序,使用libguestfs启动qemu失败,具体执行参数如下。
【环境信息】
软件信息

  • OS版本及分支信息
    基于openeuler 24.03 base容器镜像制作
    hostOS:kylinv10 SP3 2403
  • 内核信息
    4.19.90-89.11.v2401.ky10.x86_64
  • 发现问题的组件版本信息
    qemu-img-8.2.0-13.oe2403.x86_64
    qemu-hw-usb-host-8.2.0-13.oe2403.x86_64
    qemu-block-curl-8.2.0-13.oe2403.x86_64
    libvirt-daemon-driver-qemu-9.10.0-11.oe2403.x86_64
    qemu-block-iscsi-8.2.0-13.oe2403.x86_64
    qemu-8.2.0-13.oe2403.x86_64
    qemu-system-aarch64-8.2.0-13.oe2403.x86_64
    qemu-system-x86_64-8.2.0-13.oe2403.x86_64

【问题复现步骤】
[nestos-assembler]$ /usr/bin/qemu-kvm
-global virtio-blk-pci.scsi=off
-no-user-config
-nodefaults
-display none
-machine accel=kvm:tcg,graphics=off,hpet=off
-cpu max,la57=off
-smp 64
-m 1280
-no-reboot
-rtc driftfix=slew
-global kvm-pit.lost_tick_policy=discard
-kernel /var/tmp/.guestfs-0/appliance.d/kernel
-initrd /var/tmp/.guestfs-0/appliance.d/initrd
-object rng-random,filename=/dev/urandom,id=rng0
-device virtio-rng-pci,rng=rng0
-device virtio-scsi-pci,id=scsi
-drive file.file.filename=/tmp/libguestfsBK7Kt5/overlay1.qcow2,file.driver=qcow2,file.backing.file.locking=off,cache=unsafe,id=hd0,if=none
-device scsi-hd,drive=hd0
-drive file=/var/tmp/.guestfs-0/appliance.d/root,snapshot=on,id=appliance,cache=unsafe,if=none,format=raw
-device scsi-hd,drive=appliance
-device virtio-serial-pci
-serial stdio
-device virtserialport,chardev=channel0,name=org.libguestfs.channel.0
-append "panic=1 console=ttyS0 edd=off udevtimeout=6000 udev.event-timeout=6000 no_timer_check printk.time=1 cgroup_disable=memory usbcore.nousb cryptomgr.notests tsc=reliable 8250.nr_uarts=1 root=UUID=4312b3e9-f40c-41db-9542-510655647e53 selinux=0 guestfs_verbose=1 TERM=xterm"

【实际结果】,请描述出问题的结果和影响
qemu-kvm: ../blockdev.c:629: blockdev_init: Assertion `(bdrv_flags & BDRV_O_CACHE_MASK) == 0' failed.
Aborted (core dumped)
【其他相关附件信息】

评论 (7)

wangyueliang 创建了缺陷 11个月前
openeuler-ci-bot 添加了
 
sig/Virt
标签
11个月前

进一步分析,是guestfish初始化qemu-kvm时,添加磁盘中存在cache=unsafe参数,触发该断言。经排查,oe22.03-sp4版本的1.40.2和oe24.03版本的1.49.5版本的guestfish均在添加磁盘时添加cache=unsafe参数,且该参数为代码中硬编码添加。但oe22.03sp4版本qemu可正常工作,oe24.03版本出现此问题。初步认为需qemu组件进行修改适配。

代码分析:

    assert((bdrv_flags & BDRV_O_CACHE_MASK) == 0);

在断言错误的代码上,BDRV_O_CACHE_MASK宏定义是固定的:

 #define BDRV_O_CACHE_MASK  (BDRV_O_NOCACHE | BDRV_O_NO_FLUSH)

在上游社区原始版本的qemu-8.2.0中,bdrv_flags可能的赋值只有BDRV_O_COPY_ON_READ和BDRV_O_SNAPSHOT标志,完全不会与 BDRV_O_CACHE_MASK 冲突。
在qemu-6.2.0中添加了一段代码:

    if (!file || !*file) {
        cache = qdict_get_try_str(bs_opts, BDRV_OPT_CACHE_NO_FLUSH);
        if (cache && !strcmp(cache, "on")) { 
            bdrv_flags |= BDRV_O_NO_FLUSH;
        }   
            
        cache = qdict_get_try_str(bs_opts, BDRV_OPT_CACHE_DIRECT);
        if (cache && !strcmp(cache, "on")) {
            bdrv_flags |= BDRV_O_NOCACHE;
        }   
        
        qdict_del(bs_opts, BDRV_OPT_CACHE_NO_FLUSH);
        qdict_del(bs_opts, BDRV_OPT_CACHE_DIRECT);
    }

这段代码来自block-enable-cache-mode-of-empty-cdrom.patch,目的是在cdrom文件为空的情况下启用缓存模式。但是这部分代码中给 bdrv_flags 添加的参数,与后面 assert((bdrv_flags & BDRV_O_CACHE_MASK) == 0) 的操作出现巨大冲突,导致在该测试用例的场景下,qemu会因断言失败而启动失败。
并且,在对代码的分析中,BDRV_OPT_CACHE_NO_FLUSH 和 BDRV_OPT_CACHE_DIRECT 宏定义一般是在bdrv_parse_cache_mode函数中,通过对 QemuOpts 对象的选项进行判断,来进行赋值的:

int bdrv_parse_cache_mode(const char *mode, int *flags, bool *writethrough)
{
    *flags &= ~BDRV_O_CACHE_MASK;

    if (!strcmp(mode, "off") || !strcmp(mode, "none")) {
        *writethrough = false;
        *flags |= BDRV_O_NOCACHE;
    } else if (!strcmp(mode, "directsync")) {
        *writethrough = true;
        *flags |= BDRV_O_NOCACHE;
    } else if (!strcmp(mode, "writeback")) {
        *writethrough = false;
    } else if (!strcmp(mode, "unsafe")) {
        *writethrough = false;
        *flags |= BDRV_O_NO_FLUSH;
    } else if (!strcmp(mode, "writethrough")) {
        *writethrough = true;
    } else {
        return -1;
    }

    return 0;
}
----------------------------------------------------
在 blockdev.c 的 drive_new 函数中:

    value = qemu_opt_get(all_opts, "cache");
    if (value) {
        int flags = 0;
        bool writethrough;

        if (bdrv_parse_cache_mode(value, &flags, &writethrough) != 0) {
            error_setg(errp, "invalid cache option");
            return NULL;
        }

        /* Specific options take precedence */
        if (!qemu_opt_get(all_opts, BDRV_OPT_CACHE_WB)) {
            qemu_opt_set_bool(all_opts, BDRV_OPT_CACHE_WB,
                              !writethrough, &error_abort);
        }
        if (!qemu_opt_get(all_opts, BDRV_OPT_CACHE_DIRECT)) {
            qemu_opt_set_bool(all_opts, BDRV_OPT_CACHE_DIRECT,
                              !!(flags & BDRV_O_NOCACHE), &error_abort);
        }
        if (!qemu_opt_get(all_opts, BDRV_OPT_CACHE_NO_FLUSH)) {
            qemu_opt_set_bool(all_opts, BDRV_OPT_CACHE_NO_FLUSH,
                              !!(flags & BDRV_O_NO_FLUSH), &error_abort);
        }
        qemu_opt_unset(all_opts, "cache");
    }

从这方面看,对 bdrv_flags 进行宏赋值是没有必要的,qemu 原本的设计中主要是通过对 QemuOpts 对象赋值 BDRV_OPT_CACHE_NO_FLUSH 和 BDRV_OPT_CACHE_DIRECT 宏。并且当前添加的 bdrv_flags 赋值会触发assert failed问题,建议回退代码,取消对 bdrv_flags 的赋值。

并且在上述代码问题下,在使用问题描述中的qemu命令行参数时,如果修改cache=none 或是 cache=directsync 都会触发给 bdrv_flags 赋值,造成qemu Assertion `(bdrv_flags & BDRV_O_CACHE_MASK) == 0' failed.

登录 后才可以发表评论

状态
负责人
项目
预计工期 (小时)
开始日期   -   截止日期
-
置顶选项
优先级
里程碑
分支
参与者(3)
5329419 openeuler ci bot 1632792936 wangyueliang-wangyueliang 8736668 xiao yuliang 1647851881
C
1
https://gitee.com/openeuler/qemu.git
git@gitee.com:openeuler/qemu.git
openeuler
qemu
qemu

搜索帮助