Làm thế nào tôi có thể có hai tệp có cùng tên trong một thư mục khi được gắn với NFS?


8

Tôi có một thử nghiệm ứng dụng C ++ tạo ra 10.000 tệp trong thư mục được gắn NFS, nhưng thử nghiệm của tôi gần đây đã thất bại một lần do một tệp xuất hiện hai lần với cùng tên trong thư mục đó với tất cả 10.000 tệp khác. Điều này có thể được nhìn thấy trên Linux Centos v4 hoặc v5 nơi thư mục được gắn NFS, nhưng không phải trên máy chủ lưu trữ đĩa.

Làm thế nào thậm chí có thể có hai tệp có cùng tên trong cùng một thư mục?

[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*

Chạy tập lệnh Perl được đề xuất trong một trong các câu trả lời dưới đây:

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

cho:

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

In bằng các giá trị inode (-i) cho thấy hai bản sao có cùng mục nhập 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*

Có vẻ như mục nhập thư mục bị hỏng bằng cách nào đó.

Ứng dụng của tôi có thể tạo ra tình huống này một cách hợp pháp hay đây là một lỗi trong hệ điều hành? Có bất cứ điều gì tôi có thể làm để bảo vệ chống lại điều này trong chương trình tạo các tệp này không?

Tôi nghĩ rằng có một số loại lỗi trong phần mềm gắn NFS. Ngoài ra 'umount' và sau đó 'mount' của ổ đĩa NFS có vấn đề không giải quyết được, mục nhập lặp lại vẫn còn sau khi kết thúc.


Cập nhật 1: Bây giờ tôi đã gặp sự cố này lần thứ hai, một vài giờ sau đó và điều thực sự kỳ lạ là nó đã xảy ra trên cùng một tệp testfile03373, mặc dù lần này nó có một nút inode khác, 213352984, cho các tệp được nhân đôi. Tôi cũng sẽ thêm rằng tệp đang được tạo trên máy Centos 5 nơi đĩa đang được lưu trữ, vì vậy nó đang được tạo cục bộ và hiển thị chính xác cục bộ, nhưng tất cả các máy khác mà NFS gắn kết đều nhìn thấy mục nhập được nhân đôi.


Cập nhật 2: Tôi đã gắn ổ đĩa trên máy Centos v6 và tìm thấy mục sau đây /var/log/messagessau khi liệt kê và thấy mục nhập kép ở đó:

[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

Ngoài ra, tôi thấy rằng việc đổi tên tệp làm cho mục nhập kép biến mất, nhưng việc đổi tên lại khiến nó xuất hiện lại gấp đôi, hoặc thay vào đó, chỉ cần chạm vào một tệp mới có tên testfile03373, khiến mục nhập kép xuất hiện, nhưng điều này chỉ xảy ra trong hai thư mục mà mục nhập kép này đã được nhìn thấy.


AFAIK, không thể cho hai tệp có cùng tên và phần mở rộng coexisitng trong cùng một thư mục trong bất kỳ hệ thống tệp nào. Bạn có thể sử dụng một số cơ chế ngoại lệ trong chương trình của mình để ngăn chặn sự thất bại, khác là ...
Doktoro Reichard

Bạn đang sử dụng hệ thống tập tin nào?
Doktoro Reichard

Họ có chính xác như nhau không? Ví dụ: không có khoảng trắng hàng đầu hoặc dấu? không có ký tự UTF-16, ...
Hennes

Những thử nghiệm nào khác tôi có thể thực hiện để xác nhận chúng giống hệt nhau?
WilliamKF

Âm thanh như bạn đã học được cách kết thúc chạy xung quanh kiểm tra vệ sinh hệ điều hành quan trọng.
Phòng thí nghiệm Fiasco

Câu trả lời:


8

Một người bạn đã giúp tôi theo dõi điều này và thấy đây là một lỗi như được ghi trong Bugzilla 38572 cho nhân Linux ở đây . Lỗi được cho là đã được sửa trong phiên bản 3.0.0 của kernel, nhưng hiện diện ít nhất là trong phiên bản 2.6,38.

Vấn đề là cuộc gọi RPC ReadDIR () của máy chủ trả về kết quả không chính xác. Điều này xảy ra vì những điều sau đây:

Khi khách hàng đọc một thư mục, nó chỉ định kích thước bộ đệm tối đa và thay đổi cookie. Nếu thư mục quá lớn, phản hồi chỉ ra rằng trả lời chỉ là một phần và cập nhật cookie. Sau đó, khách hàng có thể thực hiện lại RPC với cookie được cập nhật để lấy đoạn dữ liệu tiếp theo. (Dữ liệu là tập hợp các thẻ và tên tệp. Trong trường hợp ReadDirPlus (), cũng có dữ liệu stat / inode / vnode.) Tài liệu không chỉ ra rằng đây là lỗi với ReadDirPlus (), nhưng có lẽ nó ở đó cũng.

Vấn đề thực tế là tệp cuối cùng trong mỗi đoạn (tên, xử lý tuple) đôi khi được trả về làm tệp đầu tiên trong đoạn tiếp theo.

Có một sự tương tác xấu với các hệ thống tập tin cơ bản. Ext4 thể hiện điều này, XFS thì không.

Đây là lý do tại sao vấn đề xuất hiện trong một số tình huống nhưng không phải trong những tình huống khác và hiếm khi xảy ra trên các thư mục nhỏ. Như đã thấy trong phần mô tả câu hỏi, các tệp hiển thị cùng số inode và tên giống hệt nhau (không bị hỏng). Vì nhân Linux gọi các hoạt động vnode cho các hoạt động cơ bản như open (), v.v., các thói quen cơ bản của hệ thống tệp quyết định điều gì sẽ xảy ra. Trong trường hợp này, máy khách NFS3 chỉ dịch hoạt động vnode thành RPC nếu thông tin bắt buộc không có trong bộ đệm thuộc tính của nó. Điều này dẫn đến sự nhầm lẫn vì khách hàng tin rằng máy chủ không thể làm điều này.


Điều đó cũng xảy ra với tôi, với kernel 3.18.17-13.el6.x86_64 (CentOS 6). Tôi khá chắc chắn đó là lỗi của hệ thống NFS cơ bản của NAS QNAP TS-212 mà thư mục được gắn vào, có thể có ai xác nhận không?
godzillante

6

Đĩa là một đĩa gắn NFS. Khi tôi đến máy tính chủ phát hành ổ đĩa, tệp chỉ được liệt kê một lần.

Có lẽ là một lỗi, vấn đề hoặc điều kiện cuộc đua với NFS.

Có thể có hai tệp cùng tên nếu bạn chỉnh sửa trực tiếp cấu trúc hệ thống tệp bằng trình chỉnh sửa hex. Tuy nhiên tôi không chắc điều gì sẽ xảy ra nếu bạn cố xóa hoặc mở tệp. Tôi không chắc chắn về những công cụ tồn tại trên Linux để truy cập tệp bằng số inode (không thể sao chép) nhưng điều đó có thể hoạt động.

Tên tệp trùng lặp là một cái gì đó fsckcó thể sẽ bắt và cố gắng sửa.

Hãy chắc chắn rằng không có tệp nào có dấu cách khác nhau.


Tôi sẽ đề nghị rằng số lượng ghi trên hệ thống tập tin cuối cùng đã phá vỡ một cái gì đó và cho phép sự tồn tại của hai tập tin giống hệt nhau.
Doktoro Reichard

Chạy fsckkhông tìm thấy vấn đề. Khởi động lại cả máy chủ và máy khách, vấn đề vẫn hiển thị.
WilliamKF

Tôi nên rõ ràng hơn - fsckcó lẽ chỉ hoạt động trên hệ thống tệp cục bộ, không phải là một NFS gắn kết. Bạn có thể cần nâng cấp / vá các gói nfs và có thể là kernel của bạn. Như @somequixotic đề cập, CentOS của bạn đã cũ và các vấn đề bạn đang gặp phải có thể đã được giải quyết trong các bản cập nhật trong tương lai.
LawrenceC

4

Có khả năng bạn có một ký tự hoặc khoảng trắng không thể in được ẩn trong một trong các tên tệp. Bạn có thể kiểm tra bằng cách cung cấp -btùy chọn ls, vd:

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\

Lưu ý việc \biểu thị khoảng trắng ở cuối tên tệp đó.

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

Để thay thế (mặc dù cách trên sẽ hoạt động), bạn có thể dẫn đầu ra thông qua tập lệnh perl này để thay thế bất cứ thứ gì không phải là ký tự ASCII có thể in bằng mã hex của nó. Ví dụ, một không gian trở thành \x20.

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

Sử dụng:

ls -la | perl -e 'while(<>){chomp();while(/(.)/g){$c=$1;if($c=~/[!-~]/){print("$c");}else{printf("\\x%.2x",ord($c));}}print("\n");}'
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.