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_READ
和ZX_RIGHT_WRITE
。src_offset
是从源中检索页面时的偏移量。
此系统调用将移动 [src_offset, src_offset + length)
中的页面
dst_vmo
从src_vmo
飞往[offset, offset + length)
。它在功能上
等同于从 src_vmo
到 dst_vmo
的 memmove
,后跟
src_vmo
中的关联网页。不过,这种机制
实现的差异后备页面实际上会在 VMO 之间移动
而无需复制数据这可以大幅提升性能。尽管如此,
不同的机制,此系统调用提供的语义与 memmove
相同,
支持提供重叠的来源区域和目标区域。
读者可能想知道为什么系统调用称为 zx_vmo_transfer_data
如果移动页面,则不会返回 zx_vmo_transfer_pages
。这是故意做出的选择
以防我们想要放宽
。例如,我们可能需要支持
请求传输 1.5 页半。在本例中,我们把
然后复制剩下的半页内容这仍然是
比用户简单的复制更有效,因为它可以让我们绕过零
目标网页请注意,初始实现不支持
这个应用场景此处提到的只是为了提供有关命名的上下文
选择。
目标范围内的现有页面将被覆盖。的所有映射
目标 VMO 也将看到新内容。如果目标 VMO 具有
子元素的类型将影响其看到的内容。
ZX_VMO_CHILD_SNAPSHOT
和 ZX_VMO_CHILD_SNAPSHOT_MODIFIED
类型的子项
仍会看到之前的内容所有其他类型的子级都会看到
新内容。移动完成后,src_vmo
中的页面将归零
。
转移失败的原因可能有多种。请参阅“错误”部分 有关可能的错误代码的完整枚举,以及 返回。
如果移动失败,则 src_vmo
VMO 中任意数量的页面
已移至dst_vmo
。我们无法保证具体移动了多少数据。
不过,我们可以保证,在以下情况下调用会成功:
条件:
- 导致下列错误的条件均未得到满足。
- 在此过程中,
src_vmo
和dst_vmo
不会被任何其他线程修改 操作正在运行。
“修改”这里是指在 VMO 上执行写入/调整大小/固定操作
或对 VMO 的引用(如切片、引用子项等)。
不应修改任何类型的快照的父级、子级或同级快照
但可能出现写入撕裂,具体取决于快照。
如果您操纵
SNAPSHOT_AT_LEAST_ON_WRITE
VMO,因为未承诺实际转移
原子性。请注意,如果要从 SNAPSHOT 子级传输页面,
可能需要复制(即分配新页面)
尚未进行过复制。
此系统调用可能返回的错误及其含义如下:
ZX_ERR_BAD_HANDLE
:src_vmo
或dst_vmo
不是有效的 VMO 句柄。ZX_ERR_INVALID_ARGS
:“offset
”、“length
”或“src_offset
”不是页面 对齐。如前所述,我们可能需要在 。ZX_ERR_ACCESS_DENIED
:“src_vmo
”没有ZX_RIGHT_WRITE
,并且ZX_RIGHT_READ
或dst_vmo
不包含ZX_RIGHT_WRITE
。ZX_ERR_BAD_STATE
:src_vmo
或dst_vmo
中指定范围内的网页 已固定。ZX_ERR_NOT_SUPPORTED
:src_vmo
或dst_vmo
是实体设备, 连续或分页器支持的 VMO。我们也许能够支持由分页器支持的 未来的 VMO。ZX_ERR_OUT_OF_RANGE
:dst_vmo
或src_vmo
中指定的范围为 无效。ZX_ERR_NO_MEMORY
:由于内存不足而失败。
实现
这应该是一组相对简单的 CL,因为我们
系统调用 zx_pager_supply_pages
,它针对分页器执行非常类似的操作
支持的 VMO因此,我们可以重复使用大量支持该系统调用的代码。
但是,我们需要进行一些更改以支持这一新用例:
zx_pager_supply_pages
用于验证所提供的 VMO 是否由 指定的分页器对象。这将需要在新的系统调用中移除。SupplyPages
,zx_pager_supply_pages
用于插入页面的函数 转换为 VMO,则假设存在一个分页器(在代码中称为page_source_
。我们必须通过添加 NULL 检查来消除这种假设, 对page_source_
执行操作并移除对其存在的任何断言。SupplyPages
还会解压缩所有压缩的网页并在前面添加标记 将页面拼接到目标页面 。对于匿名 VMO,不需要这样做,因此我们需要 它取决于目标网页是否受分页器支持。SupplyPages
目前会跳过目标网页中存在的所有网页,但 但仍会在源代码中释放相应网页。如前所述, 始终覆盖目标位置。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 克隆。但是,这会使启动时间明显缩短, 额外的复制开销