RFC-0223:zx_vmo_transfer_data

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

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

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

摘要

我们提议添加新的系统调用 zx_vmo_transfer_data,以允许调用方 将页面从一个 VMO 移动到另一个 VMO。可以把它看作是 改进功能,在不产生复制开销的情况下允许数据移动。

设计初衷

过去对 Fuchsia 性能的分析发现,深度分层的 CoW 模型 Bootfs 克隆链导致在查找页面时搜索时间较长。 此系统调用会将克隆链替换为 “spliced”包含各 Bootfs 条目的 VMO。

虽然 Bootfs 是当前的动机,但未来可能会存在 移动页面的功能可以提高性能。

利益相关方

谁对是否接受此 RFC 有影响?(此部分为可选内容, encouraged.)

教员: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_vmosrc_vmo飞往[offset, offset + length)。它在功能上 等同于从 src_vmodst_vmomemmove,后跟 src_vmo 中的关联网页。不过,这种机制 实现的差异后备页面实际上会在 VMO 之间移动 而无需复制数据这可以大幅提升性能。尽管如此, 不同的机制,此系统调用提供的语义与 memmove 相同, 支持提供重叠的来源区域和目标区域。

读者可能想知道为什么系统调用称为 zx_vmo_transfer_data 如果移动页面,则不会返回 zx_vmo_transfer_pages。这是故意做出的选择 以防我们想要放宽 。例如,我们可能需要支持 请求传输 1.5 页半。在本例中,我们把 然后复制剩下的半页内容这仍然是 比用户简单的复制更有效,因为它可以让我们绕过零 目标网页请注意,初始实现不支持 这个应用场景此处提到的只是为了提供有关命名的上下文 选择。

目标范围内的现有页面将被覆盖。的所有映射 目标 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_ARGS:“offset”、“length”或“src_offset”不是页面 对齐。如前所述,我们可能需要在 。
  • ZX_ERR_ACCESS_DENIED:“src_vmo”没有 ZX_RIGHT_WRITE,并且 ZX_RIGHT_READdst_vmo 不包含 ZX_RIGHT_WRITE
  • ZX_ERR_BAD_STATEsrc_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%。 请注意,我们可以通过创建副本来获得类似的 bootfs 查找改进 而不是像这种系统调用建议那样移动页面。不过, 这种方法可将系统的启动时间回归多达 70%(具体取决于 )。采用本文提出的方法, RFC 收回了大部分此类回归问题。

向后兼容性

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

安全注意事项

我们预计此方案不会给安全带来任何影响, 新操作在功能上等同于现有操作, 操作 (memcpy() + uncommit),但具有更好的性能。不是 允许进程执行其目前无法执行的操作。

但是,这样会增加攻击面。如果 系统调用实现时,任何进程都可能会利用它们。

隐私注意事项

我们预计此提案不会对隐私权造成任何影响。

测试

我们将添加利用新系统调用的核心测试,并验证所有 上面记录的行为(页面移动、约束和源数据归零) 网页)。我们还将添加用于衡量 系统调用,然后我们可以将其与副本的性能进行比较。

文档

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

缺点、替代方案和未知问题

我们可以泛化 zx_pager_supply_pages 以与匿名 VMO 配合使用。这个 会显著增加该系统调用的实现复杂性,以及 仍可能需要修改 API 才能接受匿名 VMO,因为 输入。

如果我们的唯一目标是提高 CoW 克隆中的网页查询性能 层次结构,我们还可以直接使用 VMO 的副本,而不是 创建 CoW 克隆。但是,这会使启动时间明显缩短, 额外的复制开销