ブロックデバイスのキャッシュとファイルシステム

ブロックデバイスのキャッシュとファイルシステム

ブロック装置はバッファリングを提供する。。これはwrite()、カーネルがデバイスにデータを書き込む前にブロックデバイスから成功を返す可能性があることを意味します。プログラムはを呼び出して、すべてのバッファリングされた書き込みを待つことができますfsync()

dd(または)を使用してcatファイルシステムイメージをデバイスに書き込みました。これらのコマンドはデフォルトでは呼び出されませんfsync()

mount次に、ブロックデバイスにファイルシステムとして書きたいとします。

私の考えの最も安全な方法は、syncインストールする前にこのコマンドを使用することです。しかし、ブロックデバイスを同期しないとどうなりますか?ファイルシステムがまだデバイスに書き込まれていないいくつかのブロックを読み取ろうとする可能性はありますか?それでは、ファイルシステムイメージの正しいデータの代わりにデバイスの以前の内容を読み取ることができますか?

私の主な関心はLinuxの動作です。 (StackExchangeは私に特定の質問をするように勧めましたが、代替または歴史的措置に賛成票を与えることもできます:-)。

ベストアンサー1

プログラムがブロックデバイスファイルを閉じると、Linuxは関連キャッシュをフラッシュしてプログラムを待機します。ただし、これは最後の項目にのみ適用されますclose()。他のデバイスがまだブロックデバイスを開いたままにしている場合、これは発生しません。次の場合を含めるすべてのパーティション同じ機器がまだ開いています。

したがって、通常、どのような方法でもデバイスを同期することをお勧めします。

安全のためにデバイスを同期する方法は、ddoptionsでコマンドを実行することですconv=fsync。これがなければ、カーネルは書き込みエラーを返しません。したがって、カーネルログ()を見るとdmesgエラーだけがわかります。

キャッシュされたすべての書き込みを待つだけでなく、最後の書き込みはすべてのclose()キャッシュを破棄します(kill_bdev())。私はコマンドの出力を観察してこれを直接確認しましたfree

linux-4.20/fs/block_dev.c:1778

static void __blkdev_put(struct block_device *bdev, fmode_t mode, int for_part)
{
    struct gendisk *disk = bdev->bd_disk;
    struct block_device *victim = NULL;

    mutex_lock_nested(&bdev->bd_mutex, for_part);
    if (for_part)
        bdev->bd_part_count--;

    if (!--bdev->bd_openers) {
        WARN_ON_ONCE(bdev->bd_holders);
        sync_blockdev(bdev);
        kill_bdev(bdev);

Cコードに慣れていない場合、上記の最後のブロックは次のようになります。

    bdev->bd_openers = bdev->bd_openers - 1;
    if (bdev->bd_openers == 0) {
        WARN_ON_ONCE(bdev->bd_holders);
        sync_blockdev(bdev);
        kill_bdev(bdev);

おすすめ記事