摘要
- 对设置了新属性的目录,遵守规则的客户端不能用另一轮枚举所得的 READDIR 结果满足本轮读取,也不能为本轮返回的条目报告早于最近一次 READDIR 的属性值。
- 这不是“所有缓存归零”。规则只约束某个目录路径、本轮实际返回的条目和应用可见答案;持有写委托的客户端若掌握比服务器更新的值,也不必倒退。
- 它能降低备份与同步程序因旧尺寸、旧时间而漏掉新数据的风险,但会增加元数据负载,而且协议没有给服务器一张“客户端确已遵守”的收据。
同一个目录里有两只钟
目录的名字列表可以是对的,名字旁边的文件属性却已经过时。原因并不神秘:目录条目记录名字和 fileid,创建、删除或重命名会推动父目录的 change 属性;另一台客户端继续写一个已有文件,只会改变该文件的 size、time_modify 等属性,不必改变父目录的名字集合。
NFS 客户端可以把 READDIR 随条目返回的文件属性留在本地,让后续 stat 不再为每个文件发送 GETATTR。在稳定目录里,这是合理的效率交换。在高性能计算输出目录或高速落盘区里,成百上千个写入者会让任何正数缓存寿命都可能显得太长。名字快照仍有效,尺寸却属于上一个时刻。
这会改变业务结果。增量备份或目录树同步若依赖尺寸和修改时间决定是否复制,可能把已增长的文件判成未变化,静默漏掉数据。fattr4_uncacheable_dirent_metadata 让服务器指出哪些目录值得为每轮枚举重新取一次服务器观测。它没有给未设置属性的目录颁发“缓存可靠”证书。
第 11 版终于写出了禁止哪种答案
draft-ietf-nfsv4-uncacheable-directories-11 于 2026 年 9 月 5 日提交,是 NFSv4 工作组的活跃标准轨草案。文档报告了 Hammerspace 服务器与 Linux 客户端原型,但仍只是 Internet-Draft,不是 RFC、IETF 批准或生产部署证明。
第 10 版要求客户端“每次 READDIR 都从服务器获取元数据”。READDIR 本来就是发往服务器的协议操作,这句话没有封住真正漏洞:客户端可以重新拿到名字,却仍从普通 inode 属性缓存里把旧尺寸交给应用。
第 11 版改为规定外部行为。若目录设置了该属性,遵守规则的客户端不得用另一轮枚举的 READDIR 结果满足本轮 readdir。对最近一次 READDIR 返回的某个条目,它不得报告在那次 READDIR 之前已经收到的属性值,无论旧值原先由 READDIR、GETATTR 还是别的操作填入。
因此,合规测试不必检查内核怎样排布缓存。第一次枚举后,让另一台客户端写大文件,再做第二次枚举和 stat。被禁止的是早于第二轮 READDIR 的旧值。实现可以删除、覆盖、分代保存甚至继续持有旧记录,只要不拿它回答这次问题。
一轮枚举不是每个名字一次网络请求
新版本专门定义了容易混淆的单位。小写 readdir 是应用发起的目录读取;大写 READDIR 是 NFSv4.2 线上操作;enumeration 是对目录的一轮遍历,可能包含许多应用调用和若干续传 READDIR。一次 READDIR 通常能供给多个 readdir。
所以草案没有要求每返回一个名字就访问一次网络。它要求本轮遍历由本轮 READDIR 奠基。客户端应在 attr_request 中请求打算报告的属性;也允许事后逐项 GETATTR,只是那会重新制造每个条目一次请求的流量。
本轮取得的元数据在遍历结束后仍可保留。两轮之间,RFC 8881 的普通属性缓存寿命继续生效。下一轮枚举到来时,早于本轮 READDIR 的值才对本轮返回条目失去资格。所谓“不可缓存”实际是一条报告时限,不是对内存结构的禁令。
开关生效也不是一个瞬间
服务器把属性从 FALSE 改成 TRUE 时,客户端可能仍缓存着目录属性。草案允许它在尚未观察到变化时继续原行为。延迟由两种常规机制收敛:目录属性缓存达到上限后过期,或客户端重新验证时看到目录 change 已移动。
运维记录必须把三个时点分开:服务器写入政策的时间、每类客户端第一次看到新值的时间、应用第一次得到符合新规则答案的时间。只记录第一个时点,会把尚未发生的执行当成既成事实。
目录委托更直接地冲突:它让客户端不回服务器即可提供目录状态,而新属性要求每轮枚举回到服务器。因此属性为真时,服务器必须收回已存在的目录委托,也不得新发委托。子属性变更通知不是普遍替代品;它是可选能力,很多环境不实现,而且成本会随客户端数与变更数相乘。
服务器也可能不是最新权威
若客户端持有某文件的 OPEN_DELEGATE_WRITE,最新的 size 或 change 可能在客户端手里,服务器本地副本反而落后。RFC 8881 允许服务器通过 CB_GETATTR 向受委托客户端取回这些值。强迫它拿旧的服务器副本覆盖新值,会把正确答案改错。
第 11 版为此写出例外:规则针对“比服务器将返回的值更旧”的数据,不要求写委托持有者倒退。可见,“走了一次服务器”不是新鲜度定义;当前写权威属于谁,同样决定答案顺序。
即使没有委托,READDIR 返回的也只是服务器在那个观察时点能陈述的状态。下一次写入可以马上发生。新属性缩短并明确了旧观测被错误沿用的边界,没有创造文件数据与元数据的全局原子快照。
属性管的是一条路径,不是整个文件
属性设置在目录上。一个文件若通过硬链接同时出现在已标记目录和未标记目录,从后者访问不受前者约束。草案也不规定对子目录自动继承;若服务器选择继承,那是本地策略,不能从父目录的一个值推断整棵树。
第 11 版还修正了对象类型处理。属性支持能力按文件系统公布,因此支持它的服务器对非目录对象收到 GETATTR 时要返回 FALSE,而不是把属性假装成“不支持”;对非目录执行 SETATTR 则返回 NFS4ERR_WRONG_TYPE。文件系统认识某属性,不等于每个对象都适合设置它。
会查询,不等于会执行
该属性是建议性的。客户端查询 GETATTR 或发送 SETATTR,只证明它知道字段编号,不能证明它实施了答案边界。服务器无法仅凭协议动作区分“遵守”“理解但忽略”和“完全不支持”三类客户端,因此不应让自身正确性依赖所有客户端一致服从。
成本同样真实。标记目录的每轮遍历都会产生服务器工作;若客户端只取名字再逐项 GETATTR,负担更重。若普通用户能在热点目录任意切换属性,一次元数据修改就可能迫使所有遵守规则的客户端放弃复用,形成负载放大。设置权限、导出策略与容量上限必须和正确性目标一起设计。
公开材料能证明草案文本、版本历史、基础 RFC、公开提交说明与贡献者所称原型,不能证明 Linux 已发布版本、Hammerspace 产品行为、采用率、基准、事故或实际收益。另一份“不可缓存文件数据”草案处理文件内容与写持久性,不扩大本篇的目录元数据范围。
按 Heng Lu 的现实层原则,服务器属性是声明,客户端缓存是私有运行状态,READDIR 是服务器观测,stat 才是应用收到的陈述。第 11 版最有价值的变化,是允许这四层各自保持准确含义。
来源
会员简报
档案背景详情
使用相应会员等级登录,即可解锁完整简报与来源注释。
仅限 Strategic Circle
Strategic Circle
所有读者均可浏览。加入并登录后可解锁档案简报。
加入 Strategic Circle仅限 Leadership Alliance
Leadership Alliance
符合条件的 IP 资产所有者和管理层可登录查看 Leadership Alliance 简报。
加入 Leadership Alliance
