绕过块层/设备上的4KB块大小限制



我们正在开发一种ssd类型的存储硬件设备,它可以一次接受>4KB的大块(即使是mb大小)的读/写请求。我的理解是,linux和它的文件系统将把文件"剁碎"成4KB的块大小,然后传递给块设备驱动程序,这将需要用来自设备的数据物理地填充块(例如,用于写)

我也意识到内核页面大小在这个限制中有一个作用,因为它被设置为4KB。

对于实验,我想知道是否有一种方法可以实际增加这个块大小,这样我们就可以节省一些时间(而不是做多个4KB的写入,我们可以用更大的块大小来做)。

是否有任何FS或任何现有的项目,我可以看看这个?如果没有,做这个实验需要什么——linux的哪些部分需要修改?试图找出困难的程度和所需的资源。或者,如果这样做是不可能的和/或我们甚至不需要这样做的任何理由。如有任何意见,欢迎。

谢谢。

4k的限制是由于页面缓存。主要问题是,如果页面大小为4k,但块大小为32k,那么如果文件只有2000字节长,那么只分配4k页面来覆盖块的前4k会发生什么。现在有人试图偏移20000,并写入单个字节。现在假设系统在很大的内存压力下,前2000字节的4k页面被从内存中推出。如何跟踪32k块的哪些部分包含有效数据,以及当系统需要在偏移量20000处写出脏页时会发生什么?

同样,让我们假设系统处于巨大的内存压力下,我们需要写出最后一页;如果没有足够的内存来实例化32k块中的另外28k,那么我们可以执行读-修改-写周期来更新偏移量20000处的一个脏4k页面,那该怎么办?

这些问题都可以解决,但这需要在VM层进行大量的手术。VM层需要知道,对于这个文件系统,页面需要一次实例化为8个页面的块,如果有内存压力来推出特定的页面,如果它是脏的,您需要同时写出所有8个页面,然后同时从页面缓存中删除所有8个页面。所有这些都意味着您想要跟踪页面使用情况和页面污染,而不是在4k页面级别,而是在复合的32k页面/"块"级别。它基本上会涉及到VM子系统的几乎每个部分的更改,从页面清理器到页面错误处理程序,页面扫描程序,回写算法,等等,等等。

还要考虑到,即使你雇佣了一个Linux VM专家来做这项工作,(HDD供应商会非常喜欢你的,因为他们也希望能够部署具有32k或64k物理扇区大小的HDD),在这样一个修改过的VM层出现在红帽企业Linux内核中,或者在SuSE或Ubuntu的同等企业或LTS内核中,也需要5-7年的时间。因此,如果你在一家希望将你的SSD产品销售到企业市场的初创公司工作,那么你最好现在就放弃这种方法。在你没钱之前,这是行不通的。

现在,如果你恰好在一家大型云计算公司工作,他们正在制作自己的硬件(如Facebook,亚马逊,谷歌等),也许你可以沿着这条特殊的道路走下去,因为他们不使用企业内核,以缓慢的速度添加新功能——但出于这个原因,他们希望相对接近上游内核,以尽量减少维护成本。

如果您在这些大型云公司工作,我强烈建议您联系同一领域的其他公司,也许您可以与他们合作,看看你们是否可以一起做这种开发工作,并共同努力实现这种上游变化。这真的,真的不是一个微不足道的改变,特别是因为上游linux内核开发人员将要求这在通常情况下不会对性能产生负面影响,这将在不久的将来涉及> 4k块设备。如果你在Facebook、谷歌、亚马逊等公司工作,这不是你想要维护的那种对内核的私有更改,而是你想要在上游进行的更改,因为否则它将是一个巨大的、侵入性的更改,支持它作为一个out-of-tree补丁将是非常令人头疼的。

虽然我从未为Linux编写过设备驱动程序,但我发现这不大可能是驱动程序接口的真正限制。我猜您可能希望将I/O分解为分散-收集列表,其中列表中的每个条目都是一页长(以提高内存分配性能并减少内存碎片),但是现在大多数设备类型都可以直接处理这些,而且我认为驱动程序接口中的任何内容实际上都不需要它。事实上,向块设备发出请求的最简单方式(在该文本的第13页描述-标记为第476页)看起来像它接收:

  • 扇区起始号
  • 要转移的扇区数量(没有提到限制,更不用说8 512B扇区的限制了)
  • 一个将数据写入/读取数据的指针(不是这个简单的情况下的分散收集列表,我猜)
  • 这是读还是写

我怀疑,如果你只看到4K访问,这可能是调用者一次请求不超过4K的结果——如果你在设备上运行的文件系统只发出4K读取,或者任何使用文件系统的东西一次只访问一个块,你的设备驱动程序无法自己改变这一点!

一次使用一个块对于随机访问模式(如数据库读取工作负载)是常见的,但是数据库日志或FS日志写入或传统(不是写时复制)文件系统上的大型串行文件读取将发出更大的I/o,这更像您所期望的。如果您想尝试直接对您的设备发出大的读取,看看是否可以通过您现在拥有的任何驱动程序,您可以使用dd if=/dev/rdiskN of=/dev/null bs=N来查看将bs参数从4K增加到1M是否会显示显着的吞吐量增加。

相关内容

  • 没有找到相关文章

最新更新