这可能有点深奥,但我在 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=0
。sync
lookupcache=none
我们的 isilon 节点都与相同的源进行 ntp 同步。通常,它们之间会有少量的漂移。
我们发现可以采用以下形式的解决方法isi export modify --zone <zoneid> <exportnumber> --time-delta 1
这会将时间戳的分辨率设置为 1s,而不是 1ns。然而,虽然这会降低问题发生的频率,但它仍然会发生 - 只是频率较低,因为它只发生在“1s”边界。