このトピックでは、特定の最近のカーネルバージョンを実行するElastic Compute Service (ECS) インスタンスからvirtioデバイスをホットプラグ解除するときにOops例外が発生する問題を解決する方法について説明します。
問題の説明
特定の最近のカーネルバージョンを実行するECSインスタンスからディスクやネットワークインターフェースコントローラー (NIC) などのvirtioデバイスをホットプラグインすると、次のOops例外が発生します。
カーネルパニックは、
Kernel. panic_on_oops
パラメーターが1に設定されているECSインスタンスで発生します。kernel.panic_on_oops
パラメーターが0に設定されているECSインスタンス上のカーネルは応答しません。
kernel.panic_on_oops
は、カーネルがOops例外を検出したときにカーネルの動作を制御するために使用されるLinuxカーネルパラメーターです。 Oopsは、無効なメモリアドレスへのアクセスなどの例外が発生したときにカーネルがスローするエラーです。
カーネルパニックが発生した場合、システムは進行中のすべてのタスクを直ちに停止し、特定のデバッグ情報を保存し、再起動またはシャットダウンして問題を解決し、潜在的な影響を軽減します。
カーネルが応答しなくなると、カーネルは動作を継続しようとする。 データの損失やその他の悪影響を防ぐため、本番環境ではkernel.panic_on_oopsパラメーターを0に設定しないことを推奨します。
原因
Linuxアップストリームコミュニティは、virtioデバイスのadmin virtqueueのサポートを追加します。 詳細については、「コミット」をご参照ください。
コミットで:
is_avq関数ポインターをvirtio_pci_device定義に追加して、admin virtqueueが存在するかどうかを判断します。
is_avq関数ポインターの値は、最新のvirtioデバイスを初期化するために使用されるvirtio_pci_modern_probe関数に追加されます。
virtioデバイスをホットプラグインすると、現在のキューがadmin virtqueueであるかどうかがチェックされます。
Linuxアップストリームコミュニティは、virtioデバイスが最新のvirtioデバイスではなく、レガシvirtioデバイスであり、is_avq関数ポインターに値が割り当てられていない場合、レガシvirtioデバイスのvirtio_pci_device構造体のis_avq関数ポインターがnullポインターであるという問題を見落としています。 virtioデバイスのホットプラグを抜くときに、コードがif (vp_dev->is_avq(vdev, vq->index))
を呼び出すと、CPUの命令ポインタレジスタ (RIP) はヌルポインタアドレスを指します。 この場合、nullポインタ例外がスローされます。これは、システムが無効なメモリアドレスを実行しようとしていることを示します。 その結果、プログラムのクラッシュやシステムエラーが発生します。
影響の範囲
Linuxアップストリームコミュニティ
Linuxアップストリームコミュニティはすでに問題を解決しています。 詳細については、「コミット」をご参照ください。 コミットでは、is_avq関数ポインタがnullかどうかをチェックするパッチが提供されます。
オペレーティングシステム
Ubuntu 24
カーネルバージョンが6.8に近いオペレーティングシステムでは、admin virtqueue機能 (virtio-pci: Introduce admin virtqueue) が提供され、is_avq関数ポインターの問題を解決するためにvirtio-pci: Check if is_avq is NULLパッチがインストールされていません。
説明uname -r
コマンドを実行して、カーネルのバージョンを表示できます。
Virtioデバイス
ECSインスタンスで使用され、ホットアンプラグされているレガシーvirtioデバイス。
解決策
解決策1: 最新のvirtioデバイスが存在するECSインスタンスのインスタンスファミリーを変更します。 詳細は、「インスタンスタイプの変更」をご参照ください。
次のインスタンスファミリーを使用することを推奨します。 最新のvirtioデバイスは、次のインスタンスファミリーのインスタンスで使用されている場合、このトピックで説明されている問題の影響を受けません。
ecs.c8i, ecs.g8i, ecs.r8i, ecs.c8ae、ecs.g8ae、ecs.r8ae、ecs.c8a、ecs.g8a、およびecs.r8a。 詳細については、「インスタンスファミリーの概要」をご参照ください。
ソリューション 2
最新のカーネルソフトウェアパッケージにアップグレードし、virtio-pci: Check if is_avq is NULLパッチが最新のカーネルソフトウェアパッケージに含まれていることを確認して、is_avq関数ポインターがnullかどうかを確認します。
(オプション) 上記のパッチが最新のカーネルソフトウェアパッケージに含まれていない場合は、パッチをインストールします。
付録: 用語
次の表に、このトピックで使用される用語を示します。
期間 | 説明 |
virtioデバイス | Virtioは、仮想マシンがホスト上の仮想ハードウェアと効率的に通信できるようにする標準化フレームワークです。 Virtioデバイスは、仮想化環境でエミュレートされるディスクやNICなどのハードウェアデバイスです。 Virtioデバイスは、従来のvirtioデバイスと最新のvirtioデバイスに分類されます。 従来のvirtioデバイスと最新のvirtioデバイスは、異なる設定インターフェイスを使用します。 |
admin virtqueue. | デバイスステータスの取得やデバイスの設定など、デバイスの管理と操作に使用される特別なvirtioキュー。 admin virtqueueは、すべてのvirtioデバイスでサポートされていません。 |
virtio_pci_device | virtio Peripheral Component Interconnect (PCI) デバイスを示すためにカーネルで使用されるデータ構造。 このデータ構造には、特定のvirtioキューがadmin virtqueueであるかどうかを判断するために追加されるis_avq関数ポインターなど、さまざまな関数へのポインターが含まれています。 |
is_avq | 特定のvirtioキューがadmin virtqueueであるかどうかを判断するために使用される関数。 |
virtio_pci_modern_probe | virtio PCIデバイスを検出して初期化するために使用される関数。 デバイスが検出された後、この関数が呼び出されて、構成スペースの読み取り、デバイス機能のチェック、必要なリソースの割り当てなどのデバイスを構成します。 |
RIP | 実行される次の命令のアドレスを格納するx86 CPUのレジスタ。 プログラムが、ヌルポインタがポイントされるアドレスで命令を実行しようと試みるときなど、プログラムが例外に遭遇した場合、RIPは、例外を引き起こした命令のアドレスをポイントする。 |