尽管进行了 fsync,stat() mtime 仍是过去时间

尽管进行了 fsync,stat() mtime 仍是过去时间

这可能有点深奥,但我在 stat() 方面遇到了一个奇怪的问题。

具体来说 - 在 Linux 系统上,安装了 Isilon 存储 NFS。我有一个进程在运行fstat同一个文件时会出现时间差异。

我可以使用一点 C 语言来重现这一点,它所做的并不比 open-write-stat-close; open-stat-close 更复杂。

这两个数字有时会相差几毫秒,即文件看起来可能比实际情况“更旧”。

我不清楚“stat”是从主机读取时间,还是从服务器读取时间。我也不清楚问题是否出在 Isilon 上(尽管这似乎不会发生在 NetApp 存储上)。

有人可以告诉我可能发生的情况吗?

举个例子:

time mismatch: 1468936451.862865611 != 1468936451.860183107

第一个是文件句柄打开时读取的时间。第二个是关闭(和fsync)后读取的时间。

正如您所看到的 - 服务器上的文件比客户端上的文件稍微旧一些。

测试方法C是:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>

int main ()
{
  while (1)
  {
    struct stat sb[2];

    /*
     * Open file
     */
    int fd = open ("test.dat", O_CREAT | O_RDWR | O_APPEND, 0644);
    if (fd < 0)
    {
      perror ("failed to open file (1)");
      return EXIT_FAILURE;
    }

    /*
     * Write to it
     */
    write (fd, "", 1);

    /*
     * Ensure it's sync'd to disk
     */
    if (fsync (fd) < 0)
    {
      perror ("failed to fsync file");
      return EXIT_FAILURE;
    }

    /*
     * Stat the file
     */
    if (fstat (fd, &(sb[0])) < 0)
    {
      perror ("failed to fstat file (1)");
      return EXIT_FAILURE;
    }

    /*
     * Close it
     */
    close (fd);

    /*
     * Open file
     */
    fd = open ("test.dat", O_RDONLY);
    if (fd < 0)
    {
      perror ("failed to open file (2)");
      return EXIT_FAILURE;
    }

    /*
     * Stat it again
     */
    if (fstat (fd, &(sb[1])) < 0)
    {
      perror ("failed to fstat file (2)");
      return EXIT_FAILURE;
    }

    /*
     * Close it
     */
    close (fd);

    /*
     * Check the times match
     */
    if (sb[0].st_mtime != sb[1].st_mtime ||
        sb[0].st_mtim.tv_nsec !=sb[1].st_mtim.tv_nsec)
    {
      printf ("time mismatch: %d.%09ld != %d.%09ld\n",
              (int)(sb[0].st_mtime), sb[0].st_mtim.tv_nsec,
              (int)(sb[1].st_mtime), sb[1].st_mtim.tv_nsec);
    }
  }
}

您可以通过在 NFS 挂载中运行此命令来触发它,然后从另一个系统调用“stat”(shell 命令也可以)。例如在 isilon 本身上:

while true
do 
    stat test.dat
done

这导致我出现如下错误:

time mismatch: 1468936613.313045037 != 1468936613.310174576
time mismatch: 1468936613.547768543 != 1468936613.544878047
time mismatch: 1468936615.228495345 != 1468936615.225862947
time mismatch: 1468936619.036053897 != 1468936619.033362349
time mismatch: 1468936619.988151772 != 1468936619.985529620
time mismatch: 1468936664.541226541 != 1468936664.538549678
time mismatch: 1468936666.165674866 != 1468936666.163171366
time mismatch: 1468936666.787528027 != 1468936666.784797051
time mismatch: 1468936711.334376729 != 1468936711.331868927

而且......我不认为应该如此。

编辑:

情节变得复杂起来——运行上述程序并捕获数据包时,来自服务器的 NFS GETATTR 调用的响应不一致。我得到了两个不同的时间戳。

安装选项似乎没有什么区别 - 但我们已经尝试设置noac和等等actimeo=0sync lookupcache=none

我们的 isilon 节点都与相同的源进行 ntp 同步。通常,它们之间会有少量的漂移。

我们发现可以采用以下形式的解决方法isi export modify --zone <zoneid> <exportnumber> --time-delta 1

这会将时间戳的分辨率设置为 1s,而不是 1ns。然而,虽然这会降低问题发生的频率,但它仍然会发生 - 只是频率较低,因为它只发生在“1s”边界。

相关内容