使用NFS挂载时,如何在目录中有两个同名文件?


8

我有一个C ++应用程序测试,该测试在NFS挂载的目录中创建10,000个文件,但是我的测试最近一次失败,因为一个文件在同一目录中两次出现相同的名称,而其他所有10,000个文件却出现了两次。这可以在Linux Centos v4或v5(目录已安装NFS)上看到,而在磁盘所在的主机上看不到。

甚至怎么可能在同一目录中有两个具有相同名称的文件?

[centos4x32 destination] ls -al ./testfile03373
-rwx------  1 user root 3373 Sep  3 03:23 ./testfile03373*
[centos4x32 destination] ls -al ./testfile03373*
-rwx------  1 user root 3373 Sep  3 03:23 ./testfile03373*
-rwx------  1 user root 3373 Sep  3 03:23 ./testfile03373*
[centos4x32 destination] ls -al *testfile03373
-rwx------  1 user root 3373 Sep  3 03:23 testfile03373*
-rwx------  1 user root 3373 Sep  3 03:23 testfile03373*
[centos4x32 destination] ls -alb test*file03373
-rwx------  1 user root 3373 Sep  3 03:23 testfile03373*
-rwx------  1 user root 3373 Sep  3 03:23 testfile03373*

建议在以下答案之一中运行Perl脚本:

ls -la *03373* | perl -e 'while(<>){chomp();while(/(.)/g){$c=$1;if($c=~/[!-~]/){print("$c");}else{printf("\\x%.2x",ord($c));}}print("\n");}'

给出:

-rwx------\x20\x201\x20user\x20root\x203373\x20Sep\x20\x203\x2003:23\x20testfile03373*
-rwx------\x20\x201\x20user\x20root\x203373\x20Sep\x20\x203\x2003:23\x20testfile03373*

使用inode(-i)值打印将显示两个副本具有相同的inode条目(36733444):

[h3-centos4x32 destination] ls -alib te*stfile03373
36733444 -rwx------  1 user root 3373 Sep  3 03:23 testfile03373*
36733444 -rwx------  1 user root 3373 Sep  3 03:23 testfile03373*

看来目录条目以某种方式已损坏。

我的应用程序可能会合理地造成这种情况吗,或者这是操作系统中的错误?我可以在创建文件的程序中采取任何措施来防止这种情况吗?

我认为NFS挂载软件中存在某种错误。同样,有问题的NFS驱动器的'umount'和'mount'也不能解决,重新装入后重复的条目仍然存在。


更新1:几小时后,我现在第二次遇到这个问题,真正奇怪的是,它在完全相同的文件上发生了testfile03373,尽管这次对于加倍的文件有一个不同的索引节点213352984。我还要补充一点,该文件是在托管磁盘的Centos 5机器上创建的,因此它是在本地创建的,并在本地显示正确,但是NFS挂载它的所有其他机器都看到该条目增加了一倍。


更新2:我将驱动器安装在Centos v6机器上,并/var/log/messages在列出并在其中看到重复项后找到了以下内容:

[root@c6x64 double3373file]# ls -laiB testfile03373* ; tail -3 /var/log/messages
36733444 -rwx------. 1 user root 3373 Sep  3 03:23 testfile03373
36733444 -rwx------. 1 user root 3373 Sep  3 03:23 testfile03373
...
Sep  4 14:59:46 c6x64 kernel: NFS: directory user/double3373file contains a readdir loop.Please contact your server vendor.  The file: testfile03373 has duplicate cookie 7675190874049154909
Sep  4 14:59:46 c6x64 kernel: NFS: directory user/double3373file contains a readdir loop.Please contact your server vendor.  The file: testfile03373 has duplicate cookie 7675190874049154909

此外,我发现重命名文件会导致重复条目消失,但重命名文件会使其重新出现两倍,或者,仅触摸名称为的新文件testfile03373,就会出现重复条目​​,但这仅在在两个目录中已看到此双重条目。


AFAIK,在任何文件系统的同一目录中,两个具有相同名称和扩展名的文件都不可能存在。您可以在程序中使用某种异常机制来防止失败,这
除外

您正在使用什么文件系统?
Doktoro Reichard 2013年

它们完全一样吗?例如没有前导或尾随空格?没有UTF-16字符,...
Hennes 2013年

我还可以执行哪些其他测试来确认它们完全相同?
WilliamKF 2013年

听起来您已经学会了如何完成至关重要的OS健全性检查。
Fiasco Labs 2013年

Answers:


8

一位朋友帮助我进行了跟踪,发现这是Bugzilla 38572中针对Linux内核记录的错误。该错误据说已在内核的3.0.0版本中修复,但至少在2.6.38版本中存在。

问题是服务器的ReadDIR()RPC调用返回错误的结果。发生这种情况是由于以下原因:

客户端读取目录时,它将指定最大缓冲区大小并将cookie归零。如果目录太大,则答复指示答复只是部分答复,并更新cookie。然后,客户端可以使用更新的cookie重新执行RPC,以获取下一个数据块。(数据是文件句柄和名称的集合。对于ReadDirPlus(),还包含stat / inode / vnode数据。)文档未指出这是ReadDirPlus()的错误,但可能存在也一样

实际的问题是每个块中的最后一个文件(名称,句柄元组)有时会作为下一个块中的第一个文件返回。

与基础文件系统的交互不良。Ext4展示了这一点,XFS则没有。

这就是为什么该问题在某些情况下会出现,而在其他情况下却不会出现,并且在小型目录中很少出现的原因。从问题描述中可以看出,文件显示相同的inode编号,并且名称相同(未损坏)。由于Linux内核为基础操作(例如open()等)调用vnode操作,因此文件系统的基础例程决定了会发生什么。在这种情况下,如果所需的信息不在其属性缓存中,则NFS3客户端仅将vnode操作转换为RPC。这导致混乱,因为客户端认为服务器无法执行此操作。


内核3.18.17-13.el6.x86_64(CentOS 6)也发生在我身上,我很确定这是QNAP TS-212 NAS底层NFS系统的错误,该目录已安装在该目录下,可以有人确认吗?
godzillante 2015年

6

该磁盘是NFS安装的磁盘。当我转到发布驱动器的主机时,该文件仅列出一次。

NFS可能是错误,问题或竞争状况。

如果使用十六进制编辑器直接编辑文件系统结构,则可能会有两个同名文件。但是我不确定如果尝试删除或打开文件会发生什么。我不确定Linux上存在哪些工具可以通过inode编号(不能重复)访问文件,但这可能有效。

重复的文件名fsck可能会捕获并尝试修复。

确保所有文件的尾随空格都不同。


我将建议在文件系统上进行大量写操作最终会破坏某些功能并允许存在两个相同的文件。
Doktoro Reichard

运行fsck中没有发现问题。重新启动主机和客户端计算机,问题仍然显示。
WilliamKF 2013年

我应该更加清楚- fsck可能只会在本地文件系统上工作,而不是在NFS挂载的系统上工作。您可能需要升级/修补nfs软件包以及内核。正如@somequixotic提到的那样,您的CentOS较旧,并且您遇到的问题可能在将来的更新中已解决。
LawrenceC

4

您可能会在其中一个文件名中包含隐藏的不可打印字符或空格。您可以通过提供的-b选项进行检查ls,例如:

user@server:~/test$ ls -lab
total 8
drwxr-xr-x 2 user user 4096 Sep  3 12:20 .
drwx------ 8 user user 4096 Sep  3 12:20 ..
-rw-r--r-- 1 user user    0 Sep  3 12:19 hello
-rw-r--r-- 1 user user    0 Sep  3 12:19 hello\

请注意该\文件名末尾的空格。

   -b, --escape
          print C-style escapes for nongraphic characters

作为替代方法(尽管上面的方法应该起作用),您可以通过此perl脚本通过管道输出,以十六进制代码替换不是可打印ASCII字符的任何内容。例如,空格变为\x20

while (<>) {
    chomp();
    while (/(.)/g) {
        $c = $1;
        if ($c=~/[!-~]/) {
            print("$c");
        } else {
            printf("\\x%.2x", ord($c));
        }
    }
    print("\n");
}

用法:

ls -la | perl -e 'while(<>){chomp();while(/(.)/g){$c=$1;if($c=~/[!-~]/){print("$c");}else{printf("\\x%.2x",ord($c));}}print("\n");}'
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.