これら2つのblockdev宣言の違いは何ですか?

これら2つのblockdev宣言の違いは何ですか?

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>rawqcow2

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機能。

ドライバを互いに階層化するとき、特定のドライバがその上に階層化されるドライバとまったく同じ機能を使用しているかどうかを検出し、重複を排除するように最適化することは非常に簡単です。私の最初の推測は、あらゆる種類の愚かな行動を避けるために、そのような最適化が実際に非常に必要であるということです。したがって、構成がまったく同じことを行う場合は、宣言方法に関係なく同じことをしたいと思います。

おすすめ記事