Translated message

A translation of this page exists in English.

仮想ディスクの I/O 負荷が高くなると、qemu-kvm プロセスが停止し、コアダンプが発生する

Solution Unverified - Updated -

Environment

以下の Red Hat Enterprise Linux 7 ベースの環境で問題が発生したことが報告されています。

  • qemu-kvm-rhev-1.5.3-60.el7_0.10 を使用している Red Hat Enterprise Linux OpenStack プラットフォーム

  • qemu-kvm-1.5.3-60.el7_0.7 を使用している Red Hat Enterprise Linux

Issue

  • qemu-kvm プロセスが停止し、コアダンプが発生します。

  • 通常、仮想ディスクの I/O 負荷が高くなると問題が発生します。

Resolution

この問題は Red Hat Bugzilla 1142857 (非公開) で対応しています。詳細は、Red Hat サポート担当までお問い合わせください。

Root Cause

qemu-kvm プロセスは、KVM 仮想マシンに実行コンテキストを提供します。qemu-kvm には、仮想ディスクの I/O を模倣するタスクがあります。ディスクのI/O 要求が完了すると問題が発生します。I/O 要求の完了には、複数の CPU で同時に実行できる qemu-kvm 上の 2 種類のスレッドが関与しています。

  • ゲストの代わりにディスク I/O を実行するワーカースレッド

  • ワーカースレッドがディスクの I/O を完了したらゲストに通知するメインスレッド

qemu-kvm の worker_thread() 関数に不具合があり、メインスレッドが、ディスクの I/O 要求から無効な完了ステータスを取得して競合が発生する可能性があります。

worker thread on CPU A                | main thread on CPU B
--------------------------------------|-----------------------------------------
set the state of the request to DONE  |
                                      |
                                      | find the request in the state DONE
                                      | fetch completion status from the request
                                      |
set completion status in the request  |

このダイアグラムに示されるように、ワーカースレッドが実際にステータスを設定する前に、メインスレッドが要求の完了ステータスにアクセスすることができます。したがって、取得したステータスは無効です。その後、qemu-kvm の bdrv_error_action() 関数の妥当性チェックが無効のステータスを検出し、プロセスを停止します。

Diagnostic Steps

  • qemu-kvm メインスレッドのスタックトレースは以下のようになります。
(gdb) bt
#0  0x00007fa719ffb5c9 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
#1  0x00007fa719ffccd8 in __GI_abort () at abort.c:90
#2  0x00007fa719ff4536 in __assert_fail_base (fmt=0x7fa71a144008 "%s%s%s:%u:%s%sAssertion `%s' failed.\n%n", 
    assertion=assertion@entry=0x7fa71f649be9 "error >= 0", file=file@entry=0x7fa71f6497eb "block.c", line=line@entry=3322, 
    function=function@entry=0x7fa71f64a730 <__PRETTY_FUNCTION__.27538> "bdrv_error_action") at assert.c:92
#3  0x00007fa719ff45e2 in __GI___assert_fail (assertion=assertion@entry=0x7fa71f649be9 "error >= 0", file=file@entry=0x7fa71f6497eb "block.c", 
    line=line@entry=3322, function=function@entry=0x7fa71f64a730 <__PRETTY_FUNCTION__.27538> "bdrv_error_action") at assert.c:101
#4  0x00007fa71f402d57 in bdrv_error_action (bs=<optimized out>, action=action@entry=BDRV_ACTION_REPORT, is_read=is_read@entry=true, 
    error=error@entry=-1886218542) at block.c:3322
#5  0x00007fa71f551979 in virtio_blk_handle_rw_error (req=req@entry=0x7fa72399d930, error=-1886218542, is_read=true)
    at /usr/src/debug/qemu-1.5.3/hw/block/virtio-blk.c:69
#6  0x00007fa71f551a4f in virtio_blk_rw_complete (opaque=0x7fa72399d930, ret=<optimized out>)
    at /usr/src/debug/qemu-1.5.3/hw/block/virtio-blk.c:81
#7  0x00007fa71f3fbbde in bdrv_co_em_bh (opaque=0x7fa7269f3830) at block.c:4469
#8  0x00007fa71f3ee797 in aio_bh_poll (ctx=ctx@entry=0x7fa7205ec400) at async.c:81
#9  0x00007fa71f3ee3e8 in aio_poll (ctx=ctx@entry=0x7fa7205ec400, blocking=blocking@entry=false) at aio-posix.c:185
#10 0x00007fa71f3ee6a0 in aio_ctx_dispatch (source=source@entry=0x7fa7205ec400, callback=<optimized out>, user_data=<optimized out>)
    at async.c:194
#11 0x00007fa71e829ac6 in g_main_dispatch (context=0x7fa7205ece00) at gmain.c:3058
#12 g_main_context_dispatch (context=context@entry=0x7fa7205ece00) at gmain.c:3634
#13 0x00007fa71f4c8dda in glib_pollfds_poll () at main-loop.c:187
#14 os_host_main_loop_wait (timeout=<optimized out>) at main-loop.c:232
#15 main_loop_wait (nonblocking=<optimized out>) at main-loop.c:464
#16 0x00007fa71f3ea110 in main_loop () at vl.c:1988
#17 main (argc=<optimized out>, argv=<optimized out>, envp=<optimized out>) at vl.c:4359
  • bdrv_error_action() 関数 (ここではスタックフレーム #4) は、error が整数値であることを期待しています。しかし、実際には、非常に大きい負の値です (ここでは -1886218542)。
(gdb) up 4
#4  0x00007fa71f402d57 in bdrv_error_action (bs=<optimized out>, action=action@entry=BDRV_ACTION_REPORT, is_read=is_read@entry=true, 
    error=error@entry=-1886218542) at block.c:3322
3322        assert(error >= 0);
  • Component
  • kvm

This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.

Comments