Як я можу мати два файли з тим самим іменем у каталозі, коли він встановлений з NFS?


8

У мене є тест додатків C ++, який створює 10 000 файлів у каталозі, встановленому NFS, але нещодавно мій тест не вдався через те, що один файл із цим іменем у цьому каталозі з’явився двічі з усіма іншими 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 є якась помилка. Також "umount", а потім "кріплення" накопичувача NFS, який має проблему, не вирішує це питання, повторний запис залишається після повторної перезавантаження.


Оновлення 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, неможливо два файли з однаковим іменем та розширенням coexisitng в одному каталозі в будь-якій файловій системі. Ви можете використати якийсь механізм винятку у вашій програмі для запобігання збоїв, іншого, ніж це ...
Doktoro Reichard

Яку файлову систему ви використовуєте?
Докторо Рейхард

Чи точно вони однакові? Наприклад, немає провідних чи задніх пробілів? немає символів UTF-16, ...
Hennes

Які ще тести я можу виконати, щоб підтвердити, що вони абсолютно однакові?
WilliamKF

Здається, що ви навчилися робити кінцевий пробіг навколо життєво важливої ​​перевірки стану ОС.
Лабораторії Фіаско

Відповіді:


8

Друг допоміг мені відстежити це і виявив, що це помилка, як записано в Bugzilla 38572 для ядра Linux тут . Помилка нібито виправлена ​​у версії 3.0.0 ядра, але присутня щонайменше у версії 2.6.38.

Проблема полягає в тому, що виклик RPC сервера ReadDIR () повертає неправильні результати. Це відбувається через:

Коли клієнт читає каталог, він вказує максимальний розмір буфера і нулює cookie. Якщо каталог занадто великий, у відповіді вказується, що відповідь є лише частковим, і оновлення файлу cookie. Тоді клієнт може повторно виконати RPC з оновленим файлом cookie, щоб отримати наступний фрагмент даних. (Дані - це набори ручок та імен файлів. У випадку ReadDirPlus () також є дані stat / inode / vnode.) У документації не вказано, що це помилка з ReadDirPlus (), але, ймовірно, вона є так само.

Справжня проблема полягає в тому, що останній файл у кожному фрагменті (ім'я, обробляючи кортеж) іноді повертається як перший файл у наступному фрагменті.

Відбувається погана взаємодія з базовими файловими системами. Ext4 демонструє це, XFS - ні.

Ось чому проблема виникає в одних ситуаціях, але не в інших і рідко виникає в невеликих каталогах. Як видно з опису питання, у файлах відображається однаковий номер inode, а імена однакові (не пошкоджені). Оскільки ядро ​​Linux викликає операції vnode для основних операцій, таких як open () тощо, основні підпрограми файлової системи вирішують, що відбувається. У цьому випадку клієнт NFS3 просто переводить операцію vnode в RPC, якщо потрібна інформація відсутня в кеші атрибутів. Це призводить до плутанини, оскільки клієнт вважає, що сервер цього не може зробити.


Це трапляється і у мене, з ядром 3.18.17-13.el6.x86_64 (CentOS 6). Я впевнений, що помилка базової системи NFS QNAP TS-212 NAS, на яку встановлений каталог, може хто-небудь підтверджує?
godzillante

6

Диск - це диск, встановлений на NFS. Коли я переходжу до хост-комп'ютера, який публікує диск, файл відображається лише один раз.

Можливо, стан помилки, проблема чи перегони з NFS.

Можна мати два файли з одним іменем, якщо ви безпосередньо редагуєте структури файлової системи за допомогою шестигранного редактора. Однак я не впевнений, що буде, якщо ви спробуєте видалити або відкрити файли. Я не впевнений, які інструменти існують у Linux для доступу до файлу за номером inode (який неможливо дублювати), але це може працювати.

Скопійовані назви файлів - це щось, fsckщо, швидше за все, захопить і спробувати виправити.

Переконайтесь, що жоден з файлів не має різних пробілів.


Я збирався припустити, що кількість записів на файлову систему в кінцевому підсумку щось порушило і дозволило існувати два однакових файли.
Докторо Рейхард

Біг fsckне знайшов жодних проблем. Перезавантажив і хост, і клієнтські машини, випуск все ще показує.
WilliamKF

Я мав би бути більш зрозумілим - 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");}'
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.