「dd」を使用してブロックデバイスに書き込むときに「同期」が必要であることが証明されていますか?

「dd」を使用してブロックデバイスに書き込むときに「同期」が必要であることが証明されていますか?

空の生ブロックデバイスにファイルを書き込むたびに。

# dd if=image.iso of=/dev/sdb status=progress

私はいかなるタイプも使用したことがありませんsync(例:sync;;;;)。conv=fsyncconv=fdatasyncoflag=syncoflag=dsync

私はこれではddないことがわかりました。一度すべての書き込みが完了するまで終了します。

私はいつもConkyのI / Oツールを使用していますがgrep Dirty /proc/meminfo、デバイスのチェックサムは常にそのデバイスに作成されたファイルのチェックサムと一致します。したがって、私は常にファイル全体がデバイスに書き込まれたと確信しています。

比較のために、ファイルをext4ボリュームに書き込んだ。たとえば、次のようにします。

$ dd if=/dev/urandom of=~/file bs=1M count=50 iflag=fullblock

ext4ボリュームに書き込むとき、ddデータが実際にディスクに書き込まれる前にシャットダウン後、常に約20秒の遅延があります。

多くの人は、ブロックデバイスに書き込むときにコマンドの後にこのコマンドを使用するか、コマンドにいくつかのsyncオプションddの1つを含めることを勧めます。例えばsyncddここそしてここ。しかし、私はこれが必要であることを実際に証明した人をまだ知っていません。

コメントの1つはこのページ例:

syncここでは意味がありません[つまり、直接作成/dev/sdX]。ファイルシステムの操作にのみ影響します。

5人がこのレビューに同意しましたが、これは私の経験と一致しています。

ddそれでは、ブロックデバイスへの書き込み時にすべての書き込みが完全に完了する前に終了する状況はありますか?このようなことは本当に誰にでも起こりますか?

などの他の書き込みオプションはcpどうですかcat?ブロックデバイスへの書き込みが完了する前に終了できますか?

答え1

今この質問に答える時間です。

長い間、私はブロックデバイスではなくファイルシステムへの書き込みだけがキャッシュされていると思いましたが、わかりましたが、私の考えは間違っていました。ブロックデバイスへの書き込みはキャッシュされます。

技術的に言えば、公式ソースを明らかにして回答を受け取ったら、更新します。しかし、ここでいくつかの情報を見つけることができます。linux - ブロックデバイスキャッシュとファイルシステム。申し訳ありません。あなたもこの質問を見たことが確認されました。

実際に画像をUSBスティックに追加してから、操作が完了したら取り出すのに問題があり、画像が破損していることがわかりました。完全な同期がデバイスで最後に完了したように見えるため、これを行うことはできませんclose()。そのため、デバイスにデータが破損しているか、まだブロックデバイスが開いているプロセスがありません。しかし、どちらにしてももう冒険しないでください。

はい。ブロックデバイスに書き込むときに同期オプションを追加することはdd都市伝説ではないようです。私はconv=fdatasyncこれで十分で最高のパフォーマンスを発揮する必要があると思います(最終的にはファイルメタデータは追加されず、プロセスの終わりに同期するだけです)。しかし、私たちの極端主義者はoflag=sync(すべての書き込み後にデータ全体とメタデータを同期させる)を好むかもしれません。確認して、man 2 openよりman 2 fdatasync多くのインサイトを入手してください。

私が読んだところ(残念ながらまだ正式なものはありません)、デバイスが起動したときにいくつかのSYNCフラグを使用して明示的に要求しない限り、他のプロセスがまだ開いているcp場合、ブロックデバイスは同期する前に実際にシャットダウンする可能性があります。はい、またはもっと誇張して言うと、これらのコマンドのどれもありません...catopen()fdatasync()fsync()sync()

答え2

だから私はそのようなものをテストしてきたので、私たちに知らせるのはddプロセスのスタックトレースです。

私はステータス=進行を含むブロックデバイスを直接追加しました(ページキャッシュをバイパスするoflag=directはありません)。そして私が得たものは次のとおりです。ステータスは非常に高速な187MB / sを示します(ページキャッシュを迂回する量と同じ)。書き込み時間)ページキャッシュは小さい。ただし、ddはブロックデバイスでblkdev_closeを呼び出して待機し、完了すると書き込みに必要な合計時間に基づいて速度がはるかに遅くなります(閉じるとフラッシュを含む)。呼ぶ)。

echo;echo;echo;date; dd if=/dev/urandom bs=1M of=/dev/mockdevice status=progress; date

Thu 08 Oct 2020 10:47:36 AM EDT
3172990976 bytes (3.2 GB, 3.0 GiB) copied, 17 s, 187 MB/s
dd: error writing '/dev/mockdevice': No space left on device
3073+0 records in
3072+0 records out
3221225472 bytes (3.2 GB, 3.0 GiB) copied, 1681.94 s, 1.9 MB/s
Thu 08 Oct 2020 11:15:38 AM EDT

dd完了後にフラッシュしたときのスタックトレースは次のとおりです(私の場合、ディスクがいっぱいになったときにエラーが発生しました)。

cat /proc/1130961/stack
[<0>] __lock_page+0x128/0x230
[<0>] write_cache_pages+0x354/0x4b0
[<0>] generic_writepages+0x57/0x90
[<0>] blkdev_writepages+0xe/0x10
[<0>] do_writepages+0x43/0xd0
[<0>] __filemap_fdatawrite_range+0xd5/0x110
[<0>] filemap_write_and_wait+0x44/0xa0
[<0>] __blkdev_put+0x72/0x1e0
[<0>] blkdev_put+0x4e/0xe0
[<0>] blkdev_close+0x26/0x30
[<0>] __fput+0xcc/0x260
[<0>] ____fput+0xe/0x10
[<0>] task_work_run+0x8f/0xb0
[<0>] exit_to_usermode_loop+0x131/0x160
[<0>] do_syscall_64+0x163/0x190
[<0>] entry_SYSCALL_64_after_hwframe+0x44/0xa9

ddを使用してページキャッシュを埋めると、ページキャッシュが一度に1ページずつブロックデバイスにフラッシュされることも注目に値します。ファイルシステムはBioをフラッシュするために多数のページを含むBIOSを送信しますが、上記のスタックトレースのページキャッシュフラッシュはBioごとに1ページだけプッシュするように見えます。

したがって、私の経験では、blkdev_closeは返し、ddが完了する前に実際にすべてのダーティキャッシュページをブロックデバイスにフラッシュするため、syncを呼び出す必要はありません。

関連情報