Linuxページキャッシュの一貫性

Linuxページキャッシュの一貫性

Linuxページのキャッシュに関する一般的な質問がいくつかあります。私が知る限り、ブロックデバイスのブロックをページキャッシュのブロックバッファに関連付ける方法は(少なくとも)3つあります。

  1. ディスクデバイスファイルを介して、例:/dev/sda
  2. たとえば、デバイスファイルを分割して/dev/sda1
  3. 通常のファイルを介して(例:/home/me/hello

/dev/sda1ext2などの一般的なLinuxファイルシステムがマウントされており、/その/home中にフォルダがあるとします。

これら3つのメソッドのaddress_spaceオブジェクトは異なるオブジェクトに含まれているため、異なるページキャッシュを持ちますinode

  1. bdev特殊ファイルinodeシステム/dev/sda
  2. bdev特殊ファイルinodeシステム/dev/sda1
  3. ext2ファイルシステムinode/home/me/hello

今問題は次のとおりです。

  1. super_blockマウントされたファイルシステムにのみオブジェクトを割り当てただけで、bdev実際にはどこにもマウントされていないため、オブジェクトがないようですsuper_block。それでは、writeback_inodes()オブジェクトを繰り返してsuper_blockdirtyを検索すると、上記のinode方法1と2のページキャッシュが失われるため、手動でディスクに同期する必要がありますか?

  2. /home/me/helloユーザーが上記の3つの方法すべてを介してファイルに属するディスクのブロックを読み書きできるため、3ページのキャッシュの内容が同期されない可能性がありますか?カーネル2.6.11コードでは、方法3でファイルを書くのに努力が必要であることがわかります。デバイスはディスクデバイス(方法1)またはパーティションですが、続行する前にデバイスキャッシュが同期されるのを待ちます。デバイス(方法2))ですが、両方を持つことは不可能です。そしてカーネル5.3では同様のコードが見つかりませんでした。

デバイスキャッシュを待つコード:

static int __block_prepare_write(struct inode *inode, struct page *page,
        unsigned from, unsigned to, get_block_t *get_block)
{
    ...
    unmap_underlying_metadata(bh->b_bdev, bh->b_blocknr);
    ...
}

void unmap_underlying_metadata(struct block_device *bdev, sector_t block)
{
    ...
    old_bh = __find_get_block_slow(bdev, block, 0);
    if (old_bh) {
        clear_buffer_dirty(old_bh);
        wait_on_buffer(old_bh);
        clear_buffer_req(old_bh);
        __brelse(old_bh);
    }
}

まだLinuxカーネルに慣れていないので、これらの質問はあまり意味がないかもしれません...ポインターありがとうございます!

答え1

ファイルシステム内のファイルの書き込み(または読み取り)とファイルシステムを持つブロックデバイスへの書き込みを混在させることは一般的ではありません。後者は、パーティションの作成やパーティションへのファイルシステムの作成などの操作にのみ使用されます。

ファイルシステムが作成されマウントされたときにブロックデバイスに書き込むと、キャッシュは同期されない可能性がありますが、これは唯一の問題ではありません。ファイルシステムをバイパスし、ブロックデバイスに直接書き込むと、確実にファイルシステムが破損します。

ブロックデバイスへの書き込みは、ルートのみを実行できる操作です。 Linuxは、ルートが自分で足を撃つためのさまざまな方法を提供し、ルートはそうしないと信じることができると仮定しています。

答え2

Q1 [...]bdev実際にどこにもインストールされていないため、super_blockオブジェクトがありません。したがって、writeback_inodes()super_blockオブジェクトを繰り返してdirtyを検索すると、inode上記の方法1と2のページキャッシュが失われます[...]

Linux/v5.3/source/fs/block_dev.c:841

struct super_block *blockdev_superblock __read_mostly;
EXPORT_SYMBOL_GPL(blockdev_superblock);

void __init bdev_cache_init(void)
{
    int err;
    static struct vfsmount *bd_mnt;

    bdev_cachep = kmem_cache_create("bdev_cache", sizeof(struct bdev_inode),
            0, (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|
                SLAB_MEM_SPREAD|SLAB_ACCOUNT|SLAB_PANIC),
            init_once);
    err = register_filesystem(&bd_type);
    if (err)
        panic("Cannot register bdev pseudo-fs");
    bd_mnt = kern_mount(&bd_type);
    if (IS_ERR(bd_mnt))
        panic("Cannot create bdev pseudo-fs");
    blockdev_superblock = bd_mnt->mnt_sb;   /* For writeback */
}

関連情報