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

6
我们正在开发一种SSD类型的存储硬件设备,它可以一次性接收大于4KB的读/写请求(甚至是MB级别的大小)。
我的理解是,Linux及其文件系统将文件“切割”成4KB块大小,并将其传递给块设备驱动程序,后者需要从设备中实际填充块数据(例如,用于写入)。
我也知道内核页大小在此限制中起着作用,因为它被设置为4KB。
为了进行实验,我想找出是否有一种方法可以实际增加这个块大小,以便我们可以节省时间(而不是进行多个4KB写操作,我们可以使用更大的块大小进行操作)。
是否有任何文件系统或任何现有项目可以供我查看?
如果没有,需要修改Linux的哪些部分来进行这项实验?
试图了解所需的难度和资源水平。或者,是否根本不需要这样做以及任何原因,我们不需要这样做。感谢您的评论。

1
这对需要进行大容量连续传输的应用程序来说是一个真正的问题。若有一位 Linux 内核专家能够前来解释如何实现大写入(最高可达 SATA 的 32k lbas),那将会非常出色。现有的每次 8 lba 写入的硬性限制会使设备变得缓慢。 - Christopher Biessener
2个回答

4
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专家来进行此项工作(硬盘厂商也会深深地爱着您,因为他们还希望能够部署具有32k或64k物理扇区大小的HDD),在经过5-7年之后,这样修改的VM层将出现在Red Hat Enterprise Linux内核中,或SuSE或Ubuntu等企业或LTS内核的等效版本中。因此,如果您正在为希望将SSD产品销售到企业市场的初创公司工作--在您耗尽资金之前,最好放弃这种方法。您没有机会。

现在,如果您正在为制造自己的硬件的大型云公司工作(例如Facebook、Amazon、Google等),也许您可以走这条特殊的道路,因为他们不使用企业内核以极其缓慢的速度添加新功能,但出于这个原因,他们希望保持比较接近上游内核,以最小化其维护成本。

如果您为这些大型云公司之一工作,强烈建议您联系在同一领域的其他公司,也许您可以与他们合作,看看是否能够一起进行这种开发工作,并尝试将此类更改上游。不过这确实不是一个琐碎的变化,特别是由于上游Linux内核开发人员将要求此举不会对常见情况下的性能产生负面影响,而这种情况在不久的将来不会涉及大于4k的块设备。如果您在Facebook,Google,Amazon等公司工作,这不是您想作为内核私有更改维护的那种变化,而是您想获取上游支持的变化,否则,作为离线补丁支持它将是巨大的头疼。

0

虽然我从未为 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是否显示了显着的吞吐量增加。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接