Segfault в LinuxKVM

09 января 2019

Segfault при запуске виртуальной машины в LinuxKVM

  • Дано: виртуальная машина (далее VM) запускается и сразу завершается.
  • В dmesg и /var/log/syslog появляется сообщение:
  • Dec 20 19:26:23 proxmox-server1 kernel: [1426017.156968] kvm[24299]: segfault at 0 ip 0000560db309e7bf sp 00007ffc817b1550 error 6 in qemu-system-x86_64[560db2aa7000+8df000]
  • Полное содержимое /var/log/syslog:
  • Dec 12 11:22:33 proxmox-server1 qm[24281]:  starting task UPID:proxmox-server1:00005EE1:087FE37D:5C1BC2AE:qmstart:100:root@pam:
    Dec 12 11:22:33 proxmox-server1 qm[24289]: start VM 100: UPID:proxmox-server1:00005EE1:087FE37D:5C1BC2AE:qmstart:100:root@pam:
    Dec 12 11:22:33 proxmox-server1 systemd[1]: Started 100.scope.
    Dec 12 11:22:33 proxmox-server1 systemd-udevd[24302]: Could not generate persistent MAC address for tap100i0: No such file or directory
    Dec 12 11:22:33 proxmox-server1 kernel: [1426016.978762] vmbr0: port 7(tap100i0) entered blocking state
    Dec 12 11:22:34 proxmox-server1 qm[24281]:  end task UPID:proxmox-server1:00005EE1:087FE37D:5C1BC2AE:qmstart:100:root@pam: OK
    Dec 12 11:22:34 proxmox-server1 kernel: [1426017.156968] kvm[24299]: segfault at 0 ip 0000560db309e7bf sp 00007ffc817b1550 error 6 in qemu-system-x86_64[560db2aa7000+8df000]
    Dec 12 11:22:34 proxmox-server1 kernel: [1426017.179860] vmbr0: port 7(tap100i0) entered disabled state
    Dec 12 11:22:34 proxmox-server1 qmeventd[979]: Starting cleanup for 100
    Dec 12 11:22:34 proxmox-server1 qmeventd[979]: Finished cleanup for 100
  • Проблема исчезает, если запускать VM без образов жёсткого диска (далее HDD).
  • Если подключить к VM образ LiveCD, то загрузка с него происходит успешно, но VM закрывается при первом же обращении к HDD.
  • Проблема проявляется у нас только на одном сервере, но с почти 100% вероятностью. Разумеется, процессоры, память и диски неоднократно проверены и проблем с ними не выявлено.
  • Версия qemu-kvm — 2.12.1-1. На тот момент — самая последняя для нашего дистрибутива — Proxmox PVE 5.2.

Что мы пробовали менять, но безуспешно?

  • Форматы образа HDD — raw и qcow2.
  • Тип эмуляции HDD — IDE, SATA, SCSI и virtio.

Как мы искали проблему?

  • Сначала узнаём, какую полную системную команду оболочка Proxmox использует для запуска VM. Для этого в консоли выполняем:
  • qm showcmd 100
  • Вывод будет примерно такой (у нас он занял 12 строк, поэтому приводить его полностью не станем):
  • /usr/bin/kvm -id 100 -name bugtest1 -chardev ...  -machine 'type=pc'
  • Эту команду мы будем выполнять вручную. Но вначале установим отладчик GDB и отладочную информацию для утилиты /usr/bin/kvm:
  • apt install gdb pve-qemu-kvm-dbg
  • И разрешим создание coredump'ов:
  • ulimit -c unlimited
    sysctl kernel.core_pattern
  • По умолчанию в kernel.core_pattern установлена маска “/var/tmp/core.%e.%p”, т.е. снимки аварийно завершённых процессов ядро сохраняет в каталог /var/tmp с именами вида “core.имя_команды.pid_процесса”.
  • После этого выполняем команду /usr/bin/kvm -id 100 ... — она завершается и оставляет после себя файл /var/tmp/core.kvm.1234.
  • Теперь запускаем отладчик (замените 1234 на фактический номер):
  • gdb /usr/bin/kvm /var/tmp/core.kvm.1234
  • И в отладчике смотрим стек вызова функций процесса, сохранённый системой в coredump в момент ошибки:
  • (gdb) bt
    #0 laio_attach_aio_context (s=0x0, new_context=new_context@entry=0x7fd2649a1c80) at block/linux-aio.c:466
    #1 0x0000558e04f3bf7b in aio_get_linux_aio (ctx=0x7fd2649a1c80) at util/async.c:329
    #2 0x0000558e04eab7f1 in raw_aio_plug (bs=0x7fd2649e6000) at block/file-posix.c:1613
    #3 0x0000558e04eb7840 in bdrv_io_plug (bs=0x7fd2649dc000) at block/io.c:2778
    #4 0x0000558e04ea6306 in blk_io_plug (blk=) at block/block-backend.c:1960
    #5 0x0000558e04bb2e6b in virtio_blk_handle_vq (s=0x7fd05c17b170, vq=0x7fd05c183000) at /home/builder/source/qemu.tmp/hw/block/virtio-blk.c:602
    #6 0x0000558e04be15d6 in virtio_queue_notify_aio_vq (vq=0x7fd05c183000) at /home/builder/source/qemu.tmp/hw/virtio/virtio.c:1515
    #7 0x0000558e04f3e72c in aio_dispatch_handlers (ctx=ctx@entry=0x7fd2649a1c80) at util/aio-posix.c:406
    #8 0x0000558e04f3efd8 in aio_dispatch (ctx=0x7fd2649a1c80) at util/aio-posix.c:437
    #9 0x0000558e04f3bc6e in aio_ctx_dispatch (source=, callback=, user_data=) at util/async.c:261
    #10 0x00007fd27342b7f7 in g_main_context_dispatch () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
    #11 0x0000558e04f3e278 in glib_pollfds_poll () at util/main-loop.c:215
    #12 os_host_main_loop_wait (timeout=) at util/main-loop.c:263
    #13 main_loop_wait (nonblocking=) at util/main-loop.c:522
    #14 0x0000558e04b34b8f in main_loop () at vl.c:1948
    #15 main (argc=, argv=, envp=) at vl.c:4757
  • Далее переходим к изучению функции laio_attach_aio_context в исходных текстах Qemu: https://github.com/qemu/qemu/blob/master/block/linux-aio.c
  • Сразу становится ясно, что проблема вызвана передачей нулевого указателя.
  • Поиск исправления и написание патча для qemu являются отдельной задачей, которая выходит за рамки данной заметки.

Ищем обходной вариант:

  • Обходной вариант может заключаться в отказе от использования вызовов Linux AIO. Это может снизить быстродействие, но решит проблему.
  • Для этого попробуем поменять не формат образа диска или способ эмуляции, а порядок обращения к нему — с быстрого асинхронного на более медленный синхронный.
  • Список доступных режимов перечислен в https://pve.proxmox.com/wiki/Performance_Tweaks#Disk_Cache:
    • none
    • writethrough
    • writeback
    • directsync
    • unsafe
  • По умолчанию используется режим “Default (no cache)”.
  • Меняем его в свойствах диска на “Write through” и получаем нормально запускающуюся VM.


← Назад в Блог