Debian Bullseyeは、コマンドライン(novirsh
またはその他のヘルパー/ラッパー)を介してQEMU / KVMを使用して仮想マシンを起動します。仮想マシンの1つは、次のように宣言されたブロックデバイスで起動されます。
-blockdev driver=file,node-name=q1,filename=/dev/loop0 \
今日、偶然にこのVMを起動すると、QEMUが次の警告を発行することがわかりました。
Opening a block device as a file using the 'file' driver is deprecated
いくつかの研究ではこの警告が知られており、@Stephen Kittが承認したものと同じ解決策があることを示唆しています。ここに答えてください次の声明を行いますblockdev
。
-blockdev node-name=q1,driver=raw,file.driver=host_device,file.filename=/dev/loop0 \
この解決策は間違いなく有効ですが、これについては何も見つかりませんfile.driver=host_device
。それで、私は他のオプションをテストして動作するように見える次の解決策を思いつきました。
-blockdev driver=host_device,node-name=q1,filename=/dev/loop0 \
誰かがこれら2つのステートメントの違いを簡単に説明できますか?特に、待ち時間やスループットの観点から、他のものよりも優れていますか?
ボーナスの質問で、文書がどこにあるかをhost_device
知っている人はいますか?上記にリンクされている他の質問/回答にはリンクがあります。提出するこのドライバを実装できます。ただし、そのリンクの後ろにある文書も見つかりません。
ベストアンサー1
~によるとQEMU変更ログ、QEMUバージョン3.0では、file
ホストブロックデバイスにアクセスするときにドライバが廃止され、導入されました。host_device
これあなたが言及したStephen Kittの答えに対するPDFプレゼンテーション(20〜24ページを参照)QEMUストレージを定義する最も徹底的な方法は、最初に(file
またはhost_device
)を使用してデータの場所を設定してから、node_name=
データ--blockdev
型の例などです。これはユーザーに優れた制御を提供しますが、ほとんどの基本的な状況では過剰です。file=<previously_defined_node_name>
raw
qcow2
QEMUソースコードストアからqemu-options.hx
書類-blockdev
これまでに見たオプションの中で最もよく説明されているようです。
file.<something>=<something>
この謎を解決することにインスピレーションを与えることができる詩があります。
他のノード(例えば)への参照を期待する
file
オプションは、2つの方法で提供できます。既存のノードのノード名を指定するか()、ポイント()の後にノードを参照するオプションを追加して、file=node-name
新しいノードインラインを定義できます。file.filename=path,file.aio=native
したがって、file.<something>=
構文は、本質的に-blockdev
異なる宣言を指定し、同時にnode_name
名前空間を乱す「中間ノード」名を避ける簡単な方法です。
したがって、Stephen Jeterのblockdev
声明は次のとおりです。
-blockdev node-name=q1,driver=raw,file.driver=host_device,file.filename=/dev/loop0
拡張形式と同じように見えます。
-blockdev node_name=<hidden_node>,driver=host_device,filename=/dev/loop0 \
-blockdev node_name=q1,driver=raw,file=<hidden_node>
この馬とあなたの馬の違い
-blockdev driver=host_device,node-name=q1,filename=/dev/loop0
これは難しい質問であり、これを理解するにはQEMUソースコードの詳細な分析が必要です。
QEMU-blockdev
ドライバーfile
であり、さまざまなホスト アーキテクチャの複数のhost_device
バージョンhost_cdrom
があります。 Linuxの場合、そのエントリは次の場所にあります。block/file-posix.c
。文字列インスタンスを検索すると、BlockDriver bdrv_
すべてのインスタンスを見つけることができます。 (また、host_cdrom
何らかの理由でFreeBSDが完全に別々の定義を持っていることがわかります。)
それぞれはBlockDriver
(主に)関数ポインタの構造として定義されているようです。これらのポインタは、ドライバ固有の機能を指すか、他のドライバと共有される共通の実装を参照できます。
ドライバはfile
次のように定義されます。
BlockDriver bdrv_file = {
.format_name = "file",
.protocol_name = "file",
.instance_size = sizeof(BDRVRawState),
.bdrv_needs_filename = true,
.bdrv_probe = NULL, /* no probe for protocols */
.bdrv_parse_filename = raw_parse_filename,
.bdrv_file_open = raw_open,
.bdrv_reopen_prepare = raw_reopen_prepare,
.bdrv_reopen_commit = raw_reopen_commit,
.bdrv_reopen_abort = raw_reopen_abort,
.bdrv_close = raw_close,
.bdrv_co_create = raw_co_create,
.bdrv_co_create_opts = raw_co_create_opts,
.bdrv_has_zero_init = bdrv_has_zero_init_1,
.bdrv_co_block_status = raw_co_block_status,
.bdrv_co_invalidate_cache = raw_co_invalidate_cache,
.bdrv_co_pwrite_zeroes = raw_co_pwrite_zeroes,
.bdrv_co_delete_file = raw_co_delete_file,
.bdrv_co_preadv = raw_co_preadv,
.bdrv_co_pwritev = raw_co_pwritev,
.bdrv_co_flush_to_disk = raw_co_flush_to_disk,
.bdrv_co_pdiscard = raw_co_pdiscard,
.bdrv_co_copy_range_from = raw_co_copy_range_from,
.bdrv_co_copy_range_to = raw_co_copy_range_to,
.bdrv_refresh_limits = raw_refresh_limits,
.bdrv_attach_aio_context = raw_aio_attach_aio_context,
.bdrv_co_truncate = raw_co_truncate,
.bdrv_co_getlength = raw_co_getlength,
.bdrv_co_get_info = raw_co_get_info,
.bdrv_get_specific_info = raw_get_specific_info,
.bdrv_co_get_allocated_file_size = raw_co_get_allocated_file_size,
.bdrv_get_specific_stats = raw_get_specific_stats,
.bdrv_check_perm = raw_check_perm,
.bdrv_set_perm = raw_set_perm,
.bdrv_abort_perm_update = raw_abort_perm_update,
.create_opts = &raw_create_opts,
.mutable_opts = mutable_opts,
};
したがって、これは本質的にドライバの複製であり、ほとんどraw
すべての機能がこれを参照します。
定義はhost_device
もう少し複雑です。
static BlockDriver bdrv_host_device = {
.format_name = "host_device",
.protocol_name = "host_device",
.instance_size = sizeof(BDRVRawState),
.bdrv_needs_filename = true,
.bdrv_probe_device = hdev_probe_device,
.bdrv_parse_filename = hdev_parse_filename,
.bdrv_file_open = hdev_open,
.bdrv_close = raw_close,
.bdrv_reopen_prepare = raw_reopen_prepare,
.bdrv_reopen_commit = raw_reopen_commit,
.bdrv_reopen_abort = raw_reopen_abort,
.bdrv_co_create_opts = bdrv_co_create_opts_simple,
.create_opts = &bdrv_create_opts_simple,
.mutable_opts = mutable_opts,
.bdrv_co_invalidate_cache = raw_co_invalidate_cache,
.bdrv_co_pwrite_zeroes = hdev_co_pwrite_zeroes,
.bdrv_co_preadv = raw_co_preadv,
.bdrv_co_pwritev = raw_co_pwritev,
.bdrv_co_flush_to_disk = raw_co_flush_to_disk,
.bdrv_co_pdiscard = hdev_co_pdiscard,
.bdrv_co_copy_range_from = raw_co_copy_range_from,
.bdrv_co_copy_range_to = raw_co_copy_range_to,
.bdrv_refresh_limits = raw_refresh_limits,
.bdrv_attach_aio_context = raw_aio_attach_aio_context,
.bdrv_co_truncate = raw_co_truncate,
.bdrv_co_getlength = raw_co_getlength,
.bdrv_co_get_info = raw_co_get_info,
.bdrv_get_specific_info = raw_get_specific_info,
.bdrv_co_get_allocated_file_size = raw_co_get_allocated_file_size,
.bdrv_get_specific_stats = hdev_get_specific_stats,
.bdrv_check_perm = raw_check_perm,
.bdrv_set_perm = raw_set_perm,
.bdrv_abort_perm_update = raw_abort_perm_update,
.bdrv_probe_blocksizes = hdev_probe_blocksizes,
.bdrv_probe_geometry = hdev_probe_geometry,
/* generic scsi device */
#ifdef __linux__
.bdrv_co_ioctl = hdev_co_ioctl,
#endif
/* zoned device */
#if defined(CONFIG_BLKZONED)
/* zone management operations */
.bdrv_co_zone_report = raw_co_zone_report,
.bdrv_co_zone_mgmt = raw_co_zone_mgmt,
.bdrv_co_zone_append = raw_co_zone_append,
#endif
};
raw
また、ほとんどのドライバ機能を参照しますが、次のような専用機能もあります。
- 検出装置
- ファイル名を解析します(おそらく有効なホストデバイスを解決するため)。
- デバイスを開きます(詳しくは、MacOSでユーザーとしてブロックデバイスにアクセスするにはかなりの追加コードが必要なため、OSごとに必要になる可能性があります)
- 大きなゼロの塊をすばやく書く
- データの削除
- デバイス権限の確認と設定
- デバイス統計のインポート
- デバイスブロックサイズとドライブ構造の検出
- 一般的なSCSIコマンドの配信
これらのhost_device
特定の機能のいくつかは単に追加のエラーチェックを実行し、ドライバの対応するraw
機能を呼び出します。しかし、これはおそらくhost_device
ほとんどのドライバー価値を提供する最後のものでしょう。これにより、仮想マシンはホストデバイスの実際のブロックサイズとジオメトリ(該当する場合)を明示的に表示できます。汎用SCSIコマンドにより、VMにはテープライブラリロボット、大容量テープドライブ、DVDバーナーなど、さまざまなアイテムへのアクセス権が付与されます。
ほとんどの場合、host_device
宣言は本質的にドライバの機能に置き換えられるため、より短い宣言が機能します。raw
上記はPOSIXスタイルのオペレーティングシステムにのみ適用されます。 WindowsでQEMUを実行している場合、デバイスアクセスは通常のファイルアクセスとは全く異なる必要があり、短い文はまったく機能しない可能性があります。file
との違いは、host_device
主にQEMUをデバイスアクセスが通常のファイルとは大きく異なる他のシステムアーキテクチャに移植することです。
パフォーマンスについて心配しますが、パフォーマンスは基本的に同じであると予想し、3つのドライバはすべて、コア機能を実装するためにまったく同じコードを呼び出すことになるからです。、bdrv_co_preadv
およびbdrv_co_pwritev
機能。
ドライバを互いに階層化するとき、特定のドライバがその上に階層化されるドライバとまったく同じ機能を使用しているかどうかを検出し、重複を排除するように最適化することは非常に簡単です。私の最初の推測は、あらゆる種類の愚かな行動を避けるために、そのような最適化が実際に非常に必要であるということです。したがって、構成がまったく同じことを行う場合は、宣言方法に関係なく同じことをしたいと思います。