首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Linux页面缓存一致性

Linux页面缓存一致性
EN

Unix & Linux用户
提问于 2019-10-11 15:17:38
回答 2查看 379关注 0票数 1

我有几个关于Linux页面缓存的一般性问题。据我所知,块设备上的块至少有三种方法可以与页面缓存中的块缓冲区相关:

  1. 通过磁盘设备文件,例如,/dev/sda
  2. 通过分区设备文件,例如,/dev/sda1
  3. 由一个常规文件,例如,/home/me/hello

假设/dev/sda1包含一个典型的linux文件系统,比如ext2,它安装在/上,/home文件夹在这个文件系统中。

这三种方法具有不同的页面缓存,因为它们的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_block对象上循环并搜索脏的inode时,会丢失上面方法1和方法2中的页面缓存,因此需要手动同步到磁盘?
  2. 在上述三种方法中,用户是否有可能在磁盘上读写属于文件/home/me/hello的块,从而使三个页面缓存中的内容不同步?我可以在内核2.6.11代码中看到,在方法3中编写文件是很费劲的,它等待设备缓存同步,然后继续进行,尽管这个设备可以是磁盘设备(方法1),也可以是分区设备(方法2),但不能两者兼而有之。我也没有在内核5.3中找到类似的代码:

等待设备缓存的代码:

代码语言:javascript
复制
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内核仍然是新的,因此这些问题可能没有多大意义。指针很感激!

EN

回答 2

Unix & Linux用户

发布于 2019-10-13 17:28:57

将对文件系统上的文件的写入(或读取)与对文件系统所在的块设备的写入(或读取)混合起来是不正常的。后者仅用于创建分区或在分区上创建文件系统等任务。

在创建和挂载文件系统时,写入块设备可以使缓存不同步,但这并不是唯一的问题:绕过文件系统并直接写入块设备是破坏文件系统的一种肯定方法。

写到块设备是只有根可以做的事情。Linux为root提供了很多方法来自投罗网,并且假设您可以相信root不会这样做。

票数 1
EN

Unix & Linux用户

发布于 2019-10-13 17:37:33

Q1 ...,因为bdev并没有真正挂载到任何地方,所以它没有super_block对象。因此,当writeback_inodes()在super_block对象上循环并搜索脏的inode时,将忽略方法1&2中的页面缓存( ... )。

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

代码语言:javascript
复制
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 */
}
票数 1
EN
页面原文内容由Unix & Linux提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://unix.stackexchange.com/questions/546345

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档