私有执行和共享状态之间的编排边界。
层栈拥有持久历史记录,命名空间进程拥有执行边界,OverlayFS 拥有可写视图。工作区会话将句柄组合在一起,并决定生命周期边缘何时可以交叉。
- 租约
- 固定用作会话的发布基础的不可变层栈视图。
- holder + 命名空间 FD
- 保持用户、挂载、PID 和可选网络边界处于活动状态。
- 覆盖层句柄
- 命名为upperdir、workdir,并合并了此会话拥有的工作区。
- 准入闸门
- 序列化生命周期边缘,而不序列化承认的 命令运行时。
- 命令账本
- 跟踪哪些命名空间执行仍属于会话。
- 终结政策
- 保留显式会话或发布,然后保留 销毁 为隐式会话。
向前建设,向后补偿。
会话的创建跨越了存储、进程、网络、挂载、持久性和登记表的边界。故障永远不会使后来的资源保持活动状态,同时默默地删除早期的所有者。
- 01
获取租约
在任何运行时状态存在之前固定活动的 manifest。
失败时
发布租约
- 02
创建草稿
分配upperdir、workdir、运行目录和会话标识。
失败时
删除运行树
- 03
生成 holder
创建命名空间、捕获FD,并准备可选的隔离网络。
失败时
杀holder+免费网络
- 04
挂载 OverlayFS
使用私有 upperdir 投影 已租借 下链。
失败时
命名空间拆卸
- 05
Persist + register
写入管理器状态,准备cgroup叶子,然后插入活动会话。
失败时
销毁或表面回滚故障
将决策序列化,而不是 命令运行时。
每个会话一个互斥锁可保护 准入、完成、终结、文件操作、重新挂载和受保护的 销毁。互斥体在附加 命令 后被释放,因此承认 命令 仍然并发执行。
一个 命令 生命周期
- 01
锁闸门
解决实时会话并阻止并发 终结、重新挂载、文件操作或 销毁。
- 02
插入账本条目
在 runner 完成之前附加命名空间执行 ID。
- 03
Launch + attach
预留执行能力,启动runner,连接其终端输出。
- 04
发布闸门
命令 在其生命周期边缘为 已提交后并发运行。
- 05
完成
删除账本条目;空的账本可以将会话转换为 终结。
活动中
命令可以录取;账本耗尽后仍保留显式会话。
敲定
当捕获、发布和隐式拆解在闸门下运行时,没有新的工作进入。
FinalizeFailed
会话仍然是可摧毁的,但不能安静地恢复到正常的准入。
upperdir 将环路闭合回到层栈。
捕获读取实际的 OverlayFS upperdir。 Planning 仅使用不可变的会话基数;冲突解决移至 写入锁 下方,并与当前活动的 head 进行比较。
- 01
捕获
遍历 upperdir 并从内核 OverlayFS 元数据派生写入、符号链接、whiteout 和不透明目录。
- 02
规划
根据会话的不可变 已租借 基础路由路径并记录预期内容 指纹。
- 03
Lock + resolve
获取层栈写入锁 并将实际 指纹 与当前活动的 head 进行比较。
- 04
合并或拒绝
接受相等路径、三向合并符合条件的文本,或拒绝冲突时的完整发布。
- 05
Commit + attribute
提升一阶段的不可变层,前置 manifest,然后附加所有权证据。
依靠内核元数据,而不是文件名惯例
捕获可识别设备或 xattr 元数据中的 OverlayFS whiteout 和不透明目录。用户创建的文件名以 .wh. 不会被默默地重新解释为删除标记。
允许陈旧的清单。冲突的路径则不然。
每个更改的源路径都携带来自 已租借 基础的预期 指纹。在写入锁下,层栈从当前的head解析出实际的指纹。这种每路径比较(而不是 manifest 新鲜度)才是真正的并发控制。
符合条件的文本在行区域上合并。运行时发出干净的字节和结构起源范围 - 绝不冲突标记。
head 不变
expected = actual接受命令变更
不相交的文本编辑
合并(基础,head,命令)发布合并字节
重叠编辑
不同的替换区域拒绝源冲突
非文字或超大尺寸
合并不合格拒绝,无冲突标记
忽略规则路由归属;他们不只是简单地删除更改。源路由路径接收 指纹 验证和线路来源,而忽略的路径使用来自会话基本策略的整体归因。
首先是耐用的有效载荷。 manifest 可见度最后。
解析后的 更改集 被写入随机数 暂存 目录中。文件和目录在重命名之前同步;在新的不可变层激活之前立即重新检查 manifest。
- 01
写暂存
在唯一的临时层目录下实现每个已解决的更改。
- 02
Sync + rename
fsync 有效负载和树,然后以原子方式将 暂存 重命名为其最终的 L* 路径。
- 03
复查head
如果解决后 manifest 发生更改,请删除升级的层并报告冲突。
- 04
前置 manifest
先用L*写下一个版本;只有这样新租约才能观察到它。
空或字节相同的输出是无操作。拒绝不会产生部分层,并且会在触发 终结 的 命令 上显示。
协调随着状态的改变而变化,而不是基本结帐。
共享基础保持固定且不可变。会话设置可通过下链元数据进行扩展; 终结 随着 已捕获路径和受影响的字节进行扩展。
| 操作 | 主导界 | 原因 |
|---|---|---|
| 会话创建 | θ(L) | 构建并固定 L-层下链条;没有 θ(B) 基础副本。 |
| 捕获 | O(C log C + 访问的字节数) | 步行并确定地排序 C upperdir 变化。 |
| 解决 | O(C·L·P + H) | 找到通过 L层的 C 路径,并对 H 受影响的字节进行散列或合并。 |
| 提交 | O(改变的字节+manifest) | 编写一棵 暂存 树,同步、重命名和添加元数据。 |
归因遵循解决结果
合并记录最终行范围是否来自活动历史记录或 命令。在提交之后,这些源被映射到运行时所有者,并附加到可压缩的层存储之外。
相关层栈模型
文件-操作怪
