多粒度时间戳

简介

历史上,内核总是使用粗略的时间值来标记 inode。这个值每经过一个节拍(jiffy)就会更新一次,因此在同一个节拍内发生的任何更改都将具有相同的时间戳。

当内核要去标记一个 inode(由于读取或写入)时,它首先获取当前时间,然后将其与现有的时间戳进行比较,以查看是否会发生任何变化。如果没有变化,则可以避免更新 inode 的元数据。

因此,从性能的角度来看,粗略时间戳是好的,因为它们减少了对元数据更新的需求,但从确定是否发生了任何变化的角度来看,它们是不好的,因为在一个节拍内可能会发生很多事情。

它们在 NFSv3 中尤其麻烦,在 NFSv3 中,不变的时间戳可能难以判断是否要使缓存失效。NFSv4 提供了一个专用的更改属性,该属性应始终显示可见的更改,但并非所有文件系统都正确实现了这一点,导致 NFS 服务器在许多情况下替换为 ctime。

多粒度时间戳旨在通过在最近查询过文件的时间戳并且当前粗粒度时间不会导致更改时,有选择地使用细粒度时间戳来补救此问题。

Inode 时间戳

目前,inode 中有 3 个时间戳在不同的活动中被更新为当前挂钟时间

ctime

inode 更改时间。每当 inode 的元数据更改时,都会用当前时间标记此值。请注意,此值无法从用户空间设置。

mtime

inode 修改时间。每当文件的内容发生更改时,都会用当前时间标记此值。

atime

inode 访问时间。每当读取 inode 的内容时,都会标记此值。被广泛认为是一个可怕的错误。通常使用诸如 noatime 或 relatime 之类的选项来避免它。

更新 mtime 始终意味着对 ctime 的更改,但是由于读取请求而更新 atime 则不是。

多粒度时间戳仅针对 ctime 和 mtime 进行跟踪。atime 不受影响,并且始终使用粗粒度值(受限制于 floor)。

Inode 时间戳排序

除了提供有关单个文件更改的信息之外,文件时间戳还在诸如“make”之类的应用程序中起着重要作用。这些程序测量时间戳以确定源文件是否可能比缓存的对象新。

诸如 make 之类的用户空间应用程序只能基于操作边界来确定排序。对于系统调用,这些边界是系统调用的入口点和出口点。对于 io_uring 或 nfsd 操作,则是请求提交和响应。在并发操作的情况下,用户空间无法确定事情发生的顺序。

例如,如果单个线程按顺序修改一个文件,然后修改另一个文件,则第二个文件必须显示等于或晚于第一个文件的 mtime。如果两个线程正在发出不重叠的类似操作,则情况也是如此。

但是,如果两个线程有重叠的时间竞争系统调用,则不能保证这种顺序,并且第二个文件可能看起来是在第一个文件之前、之后或同时被修改的,而不管哪个先提交。

请注意,以上假设系统不会经历实时时钟的向后跳跃。如果在不合时宜的时间发生这种情况,则即使在正常运行的系统上,时间戳也可能会向后退。

多粒度时间戳实现

多粒度时间戳旨在确保对单个文件的更改始终可识别,而不会违反修改多个不同文件时的排序保证。这会影响 mtime 和 ctime,但 atime 将始终使用粗粒度时间戳。

它使用 i_ctime_nsec 字段中未使用的位来指示是否已查询 mtime 或 ctime。如果查询了一个或两个,则内核会特别注意确保下一个时间戳更新将显示可见的更改。这确保了诸如 NFS 之类的用例的紧密缓存一致性,而不会在未监视文件时牺牲减少元数据更新的好处。

Ctime Floor 值

仅根据是否查询了 mtime 或 ctime 来简单地使用细粒度或粗粒度时间戳是不够的。一个文件可能会获得一个细粒度时间戳,然后稍后修改的第二个文件可能会获得一个看起来比第一个文件早的粗粒度时间戳,这将打破内核的时间戳排序保证。

为了缓解此问题,请维护一个全局 floor 值,以确保不会发生这种情况。在这种情况下,上述示例中的两个文件可能看起来是在同一时间被修改的,但它们永远不会显示相反的顺序。为了避免实时时钟跳跃的问题,floor 作为单调 ktime_t 进行管理,并且值会根据需要转换为实时时钟值。

实现说明

多粒度时间戳旨在供从本地时钟获取 ctime 值的本地文件系统使用。这与仅镜像来自服务器的时间戳值的网络文件系统等形成对比。

对于大多数文件系统,只需在 fstype->fs_flags 中设置 FS_MGTIME 标志即可选择加入,前提是 ctime 仅通过 inode_set_ctime_current() 进行设置。如果文件系统具有一个不调用 generic_fillattr 的 ->getattr 例程,则它应该调用 fill_mg_cmtime() 来填充这些值。对于 setattr,它应该使用 setattr_copy() 来更新时间戳,或者以其他方式模仿其行为。