Як я можу мати два файли з тим самим іменем у каталозі, коли він встановлений з 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.