摘要
- 在 9P2000 中,只有 Twalk 给出的全部名字元素都成功解析后,原本未占用的 newfid 才代表结果;部分 Rwalk 可以报告已经走通的前缀,却不会改变两个 fid。
- Topen 是另一项请求:它提出访问模式,促使服务器检查权限,并为后续读写准备 fid。Ropen 本身既不是读取,也不是写入完成证明。
- Rob Pike 的作用必须放回共同创造的历史:Ken Thompson 开始协议工作,Pike 把命名系统整合进去,Dave Presotto 建立网络部分;Plan 9 论文与后续方言也各有自己的合作者。
事故报告里常见一句话:“路径检查成功,因此文件已经可用。”在 9P 中,这句话至少越过了 open 请求、访问模式判断和后续 I/O 三层事实。walk 成功不是没有价值,而是价值比那句话更精确。
9P2000 的 Twalk 从一个现有 fid 出发,提供 newfid,再附上一列名字元素。除非客户端有意让两者相同,newfid 必须尚未使用。服务器逐个处理名字;穿过每一级目录时,都要满足搜索权限。只有整列名字都成功,Rwalk 才返回与元素数相同的 qid,并让 newfid 指向解析结果。
这张回执证明:在这台服务器、这条连接、这个起点上,有序名字在当时得到了完整解析。它没有证明结果已经打开。协议导言把 fid 描述为客户端选择的 32 位标识符,用来表示当前文件,无论文件是否已 open;同一连接上的参与者共享 fid 空间。重新协商版本会重新初始化会话并中止未完成 I/O。因此,fid 天生属于连接上下文,不是可跨会话保存的万能句柄。
失败语义更能看出设计的克制。如果第一个元素无法走通,服务器直接返回错误;若后续元素失败,Rwalk 可以带回已解析前缀的 qid。但 9P2000 明确规定:没有走完所有元素时,原 fid 与 newfid 都不受影响。若监控平台看到“九段中成功七段”,就登记一个可继续使用的新句柄,它创造了协议没有创造的状态。
零元素 Twalk 也不等于“什么都没做”。它把起始 fid 克隆到 newfid,却没有跨越任何名字。一次消息最多携带十六个元素的 MAXWELEM 限制,也不是逻辑路径最多十六段;客户端可以继续发下一次 walk。还原报文时,这些细节决定日志是在描述路径、克隆,还是消息分片。
open 另答一个问题。Topen 针对 fid 已代表的文件请求读、写、读写或执行等模式,并可携带 9P2000 规定的附加标志。服务器在这里检查访问权限,准备 fid 供后续 I/O 使用;Ropen 返回 qid 与 iounit。只有再往后的 Tread 或 Twrite,才能产生关于具体数据传输的回执。
时间也从这道边界进入证据。open 手册说,权限在打开时检查;文件一旦打开,之后的权限变化不会撤销已有访问能力。由此可见,walk 时的目录搜索权限与 open 时的文件访问权限既不是一回事,也不是永恒事实。完整 walk 后 open 被拒绝,不一定自相矛盾;请求模式、文件权限或服务状态可能已经不同。反过来,策略改变后,先前已打开的 fid 仍可能继续访问。审计必须保存两个事件和先后顺序。
qid 同样需要准确表述。9P 用它在同一服务器层级内唯一标识文件;文件删除后重建时,qid 的 path 部分应改变。它比界面显示的路径字符串更有辨识力,却不是跨独立服务器的全球身份,也不是内容哈希,更不能证明两个挂载点背后就是同一对象。
这种局部性不是系统缺陷。Rob Pike、Dave Presotto、Ken Thompson、Howard Trickey 与 Phil Winterbottom 合著的《The Use of Name Spaces in Plan 9》描述了每进程命名空间;资源通过简洁的消息协议组合起来。《Plan 9 from Bell Labs》由 Pike、Presotto、Sean Dorward、Bob Flandrena、Thompson、Trickey 与 Winterbottom 共同署名,并强调命名空间的组合保存在客户端。系统要提供的正是可控的局部视图,而不是一棵假想的全球目录树。
人物归属也应保留边界。第二版前言记载,Thompson 开始协议工作,Pike 整合命名系统,Presotto 负责网络,同时列出 Winterbottom 等众多贡献者。把 9P 简化成 Pike 的个人发明,反而抹去了他真正完成的整合工作。第四版前言还说明,新版 9P 主要为了摆脱旧有名字元素 27 字节限制,同时提高效率、灵活性与封装。Linux v9fs 可协商 9p2000、9p2000.u、9p2000.L;UNIX 扩展与 Linux 方言各有自己的文档。9P2000.L 保留 walk 结构,却使用 Linux 化的 Tlopen/Rlopen。可以比较两阶段边界,不能把所有字段混成一个协议。
部署层还可能加入缓存。Linux v9fs 的不同缓存模式会改变客户端观察与服务器实时状态的贴合程度。报文、缓存与存储结果可以都是真实的,却属于不同时间点。解决办法不是否认任何一层,而是记录协商方言、连接、服务器与导出、attach 上下文、起始 fid/qid、有序名字、所有返回 qid、完整或部分状态、newfid、open 模式与标志、Ropen 的 qid/iounit、后续 I/O、缓存策略以及会话终止。
这样,“walk 成功”仍是一句很强的话:它准确说明名字在指定上下文中走通了。它之所以可信,恰恰因为无需假装同时打开了什么。
Sources
- https://9p.io/magic/man2html/5/walk
- https://9p.io/magic/man2html/5/open
- https://9p.io/magic/man2html/5/intro
- https://9p.io/sys/doc/names.html
- https://9p.io/sys/doc/9.html
- https://9p.io/sys/man/preface.html
- https://9p.io/sys/man/preface4.html
- https://docs.kernel.org/filesystems/9p.html
- https://ericvh.github.io/9p-rfc/rfc9p2000.u.html
- https://github.com/chaos/diod/blob/master/protocol.md
会员简报
档案背景详情
使用相应会员等级登录,即可解锁完整简报与来源注释。
仅限 Strategic Circle
Strategic Circle
所有读者均可浏览。加入并登录后可解锁档案简报。
加入 Strategic Circle仅限 Leadership Alliance
Leadership Alliance
符合条件的 IP 资产所有者和管理层可登录查看 Leadership Alliance 简报。
加入 Leadership Alliance
