RFC-0223:zx_vmo_transfer_data

RFC-0223:zx_vmo_transfer_data
状态已接受
领域
  • 内核
说明

引入了一个名为 zx_vmo_transfer_data 的新系统调用,可以高效地将数据从一个 VMO 移动到另一个 VMO。

问题
Gerrit 更改
  • 859841
作者
审核人
提交日期(年-月-日)2023-05-22
审核日期(年-月-日)2023-08-14

总结

我们提议添加新的系统调用 zx_vmo_transfer_data,以允许调用方将页面从一个 VMO 移动到另一个 VMO。可以将其视为效率提升,允许在不产生复制开销的情况下进行数据移动。

设计初衷

过去对 Fuchsia 性能的分析发现,Bootfs 的深层 CoW 克隆链导致在查找页面时需要较长的搜索时间。此系统调用将克隆链替换为包含 Bootfs 各个条目的“拼接”VMO,从而减少此开销。

虽然目前的动机是 Bootfs,但未来可能还有其他一些情况,因为能够移动页面可以提高性能。

利益相关方

谁与此 RFC 被接受是否相关?(本部分为可选内容,但建议阅读。)

教员:cpu@

审核者:rashaeqbal@、jamesr@

咨询人员:mcgrathr@、maniscalco@、adanis@、eieio@

社交:此提案以简明介绍向 Zircon 团队进行社交推广。

设计

我们会将以下系统调用添加到 Zircon 系统调用 API:

zx_status_t zx_vmo_transfer_data(zx_handle_t dst_vmo,
                                 uint32_t options,
                                 uint64_t offset,
                                 uint64_t length,
                                 zx_handle_t src_vmo,
                                 uint64_t src_offset);

其中:

  • dst_vmo 是目标 VMO 的句柄。此句柄必须具有 ZX_RIGHT_WRITE
  • options 是当前未使用的字段,未来可用于扩展 API。
  • offset 是页面移至目标位置的偏移量。
  • length 是要移动到目标位置的字节数。
  • src_vmo 是来源 VMO 的句柄。此句柄必须具有 ZX_RIGHT_READZX_RIGHT_WRITE
  • src_offset 是从来源检索页面的偏移量。

此系统调用会将 [src_offset, src_offset + length) 中的页面从 dst_vmo 中的 src_vmo 移至 [offset, offset + length)。它在功能上等同于从 src_vmodst_vmo,后跟 src_vmo 中的关联页面。memmove但是,实现这一目的的机制是不同的;后备页面实际上是在 VMO 之间移动,而不是复制数据。这样可以获得更好的性能。尽管存在这种不同的机制,但此系统调用呈现的语义与 memmove 相同,因为支持提供重叠的来源和目标区域。

读者可能想知道,如果系统调用移动页面,为什么称为 zx_vmo_transfer_data 而不是 zx_vmo_transfer_pages。这是我们有意做出的选择,是为了防止我们日后想要放宽严格的页面对齐要求。例如,我们可能需要支持用户请求传输 1 个半网页这一用例。在本例中,我们会移动第一页,然后复制剩下的半页。这样做仍然比用户执行简单副本更高效,因为它可以让我们避免将目标网页归零。请注意,初始实现不支持此用例;此处提及它只是为了提供与命名选择有关的背景信息。

目标范围内的现有页面会被覆盖。目标 VMO 的所有映射也将看到新内容。如果目标 VMO 有子级,则子级的类型将影响子级看到的内容。ZX_VMO_CHILD_SNAPSHOTZX_VMO_CHILD_SNAPSHOT_MODIFIED 类型的子项将继续看到旧内容。所有其他类型的子项都将看到新内容。移动完成后,src_vmo 中的页面将会清零。

移动可能会由于各种原因而失败。请参阅下面的“错误”部分,全面了解可能出现的错误代码以及返回这些错误代码的场景。

如果移动失败,则 src_vmo VMO 中任意数量的页面可能已移至 dst_vmo。我们无法保证转移的确切数据量。 不过,我们可以保证在满足以下条件时,调用会成功:

  1. 不满足会导致下列错误的所有条件。
  2. 此操作运行期间,src_vmodst_vmo 不会被任何其他线程修改。

在此上下文中,“修改”是指直接对 VMO 或对 VMO 的引用(例如切片、引用子项等)进行写入/调整大小/固定。修改任何类型的快照的父快照、子快照或同级快照不应导致任何错误,但根据快照的不同,可能会发生写入撕裂。如果您操纵 SNAPSHOT_AT_LEAST_ON_WRITE VMO 的父项,则可能会出现写入撕裂,因为实际转移没有承诺的原子性。请注意,在传输 SNAPSHOT 子项的页面的情况下,如果特定页面尚未写入,则我们可能需要执行副本(即分配新页面)。

以下是此系统调用可能返回的错误及其含义:

  • ZX_ERR_BAD_HANDLEsrc_vmodst_vmo 不是有效的 VMO 句柄。
  • ZX_ERR_INVALID_ARGSoffsetlengthsrc_offset 未对齐页面。如前所述,我们以后可能需要移除此限制条件。
  • ZX_ERR_ACCESS_DENIEDsrc_vmo 没有 ZX_RIGHT_WRITEZX_RIGHT_READ,或 dst_vmo 没有 ZX_RIGHT_WRITE
  • ZX_ERR_BAD_STATE:固定 src_vmodst_vmo 指定范围内的页面。
  • ZX_ERR_NOT_SUPPORTEDsrc_vmodst_vmo 是物理、连续或由分页器支持的 VMO。我们未来或许能够支持由分页器支持的 VMO。
  • ZX_ERR_OUT_OF_RANGEdst_vmosrc_vmo 中指定的范围无效。
  • ZX_ERR_NO_MEMORY:因内存不足而失败。

实现

这应该是一组相对简单的 CL,因为我们现有的系统调用 zx_pager_supply_pages 可以对由分页器支持的 VMO 执行非常相似的操作。因此,我们可以重复使用很多支持该系统调用的代码。 不过,我们需要进行多项更改来支持这一新用例:

  1. zx_pager_supply_pages 用于验证提供的 VMO 是否由给定的分页器对象提供支持。这需要在新的系统调用中删除。
  2. SupplyPageszx_pager_supply_pages 用于将页面插入 VMO 的函数,它会假定存在分页器(在代码中称为 page_source_)。我们必须通过添加 NULL 检查来消除这种假设,然后再对 page_source_ 执行操作并移除对其存在的任何断言。
  3. 此外,SupplyPages 还会在将页面拼接到目标页面之前解压缩所有压缩页面并添加标记,因为它要求该页面由分页器提供支持。匿名 VMO 不需要这样做,因此我们需要根据目标位置是否由分页器支持来设定条件。
  4. SupplyPages 目前会跳过目标位置中存在的任何页面,但仍释放来源中现有的页面。如前所述,我们会将其更改为始终覆盖目标位置。
  5. SupplyPages 目前不考虑有父级的 VMO。在大多数情况下,这并不是问题。不过,如果目的地是 ZX_VMO_CHILD_SNAPSHOT 类型的子级,则需要更新父级中的拆分位,以表明 VMO 已偏离隐藏的父级。

性能

我们预计这可以显著提高 Bootfs 中的 VMO 页面查找性能。具体而言,从当前使用的 CoW 克隆链切换到使用此系统调用移动页面,应该可以使 bootfs 查询量提高约 20%。请注意,通过创建 VMO 的副本,而不是像系统调用建议的那样移动页面,我们也可以实现类似的 bootfs 查找改进。不过,这种方法确实会使系统的启动时间缩短多达 70%(具体取决于我们运行的目标硬件)。使用此 RFC 提议的方法可以收回大部分此类回归问题。

向后兼容性

我们不打算移除现有的 zx_pager_supply_pages 系统调用,因此预计不会出现向后兼容性方面的问题。

安全注意事项

我们预计该方案不会产生任何安全影响,因为新操作在功能上等同于现有操作(memcpy() + 取消提交),但性能更好。但不允许进程执行其无法执行的操作。

不过,这样会增加攻击面。如果系统调用实现中存在可利用的错误,任何进程都可能会利用这些错误。

隐私注意事项

我们预计此提案不会在隐私权方面产生任何影响。

测试

我们将添加使用新系统调用的核心测试,并验证上述所有行为(页面移动、限制和源页面清零)。我们还将添加用于衡量此系统调用性能的基准测试,然后可以将该基准与副本的性能进行比较。

文档

我们将添加介绍 zx_vmo_transfer_data 的新文档。

缺点、替代方案和未知情况

我们可以泛化 zx_pager_supply_pages 来处理匿名 VMO。这会大大增加该系统调用的实现复杂性,并且可能仍然需要修改 API 才能接受匿名 VMO 作为输入。

如果我们的唯一目标是提高 bootfs 的 CoW 克隆层次结构中的页面查找性能,我们也可以只使用 VMO 的副本,而不是创建 CoW 克隆。但是,由于产生额外的复制开销,这会显著缩短启动时间。