¿Cómo puedo tener dos archivos con el mismo nombre en un directorio cuando se montan con NFS?

8

Tengo una prueba de aplicación C ++ que crea 10,000 archivos en un directorio montado en NFS, pero mi prueba recientemente falló una vez debido a que un archivo aparece dos veces con el mismo nombre en ese directorio con todos los otros 10,000 archivos. Esto se puede ver en Linux Centos v4 o v5 donde el directorio está montado en NFS, pero no en la máquina host donde reside el disco.

¿Cómo es posible tener dos archivos con el mismo nombre en el mismo directorio?

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

Ejecutar el script Perl sugerido en una de las respuestas a continuación:

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

da:

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

La impresión con los valores de inodo (-i) muestra que las dos copias tienen la misma entrada de inodo (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*

Parece que la entrada del directorio está dañada de alguna manera.

¿Podría mi aplicación haber creado legítimamente esta situación o es un error en el sistema operativo? ¿Hay algo que pueda hacer para proteger contra esto en mi programa que crea los archivos?

Estoy pensando que hay algún tipo de error en el software de montaje NFS. También 'umount' y luego 'mount' de la unidad NFS que tiene el problema no lo resuelve, la entrada repetida permanece después del remontaje.


Actualización 1: ahora he tocado este problema por segunda vez, unas horas más tarde, y lo realmente extraño es que sucedió exactamente en el mismo archivo testfile03373, aunque esta vez obtuvo un inodo diferente, 213352984, para los archivos duplicados. También agregaré que el archivo se está creando en la máquina Centos 5 donde se aloja el disco, por lo que se está creando localmente y se muestra correctamente localmente, pero todas las otras máquinas que NFS lo montan están viendo la entrada duplicada.


Actualización 2: monté el disco en una máquina Centos v6 y encontré lo siguiente /var/log/messagesdespués de enumerar y ver la doble entrada allí:

[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

Además, descubrí que cambiar el nombre del archivo hace que la doble entrada desaparezca, pero cambiar el nombre de nuevo hace que vuelva a aparecer duplicado, o alternativamente, solo tocar un nuevo archivo con el nombre testfile03373, hace que aparezca una doble entrada, pero esto solo sucede en el dos directorios donde se ha visto esta doble entrada.

WilliamKF
fuente
AFAIK, es imposible que dos archivos con el mismo nombre y extensión coexistan en el mismo directorio en cualquier sistema de archivos. Podría utilizar algún mecanismo de excepción en su programa para evitar fallas, aparte de esto ...
Doktoro Reichard
¿Qué sistema de archivos estás usando?
Doktoro Reichard
¿Son exactamente lo mismo? Por ejemplo, ¿no hay espacios en blanco iniciales o finales? sin caracteres UTF-16, ...
Hennes
¿Qué otras pruebas puedo realizar para confirmar que son exactamente iguales?
WilliamKF
Parece que aprendiste a hacer una ejecución final en torno a una comprobación vital del sistema operativo.
Fiasco Labs

Respuestas:

8

Un amigo me ayudó a rastrear esto y descubrió que se trata de un error registrado en Bugzilla 38572 para el kernel de Linux aquí . El error supuestamente se corrige en la versión 3.0.0 del núcleo, pero está presente al menos en la versión 2.6.38.

El problema es que la llamada RPC ReadDIR () del servidor devuelve resultados incorrectos. Esto ocurre debido a lo siguiente:

Cuando el cliente lee un directorio, especifica un tamaño máximo de búfer y pone a cero una cookie. Si el directorio es demasiado grande, la respuesta indica que la respuesta es solo parcial y actualiza la cookie. Luego, el cliente puede volver a ejecutar el RPC con la cookie actualizada para obtener la siguiente porción de datos. (Los datos son conjuntos de identificadores y nombres de archivos. En el caso de ReadDirPlus (), también hay datos stat / inode / vnode). La documentación no indica que se trata de un error con ReadDirPlus (), pero probablemente esté allí. también.

El problema real es que el último archivo en cada fragmento (nombre, tupla de identificador) a veces se devuelve como el primer archivo en el siguiente fragmento.

Hay una mala interacción con los sistemas de archivos subyacentes. Ext4 exhibe esto, XFS no.

Es por eso que el problema aparece en algunas situaciones pero no en otras y rara vez ocurre en directorios pequeños. Como se ve en la descripción de la pregunta, los archivos muestran el mismo número de inodo y los nombres son idénticos (no están dañados). Dado que el kernel de Linux llama a las operaciones vnode para operaciones subyacentes como open (), etc., las rutinas subyacentes del sistema de archivos deciden qué sucede. En este caso, el cliente NFS3 solo traduce la operación vnode en un RPC si la información requerida no está en su caché de atributos. Esto lleva a confusión ya que el cliente cree que el servidor no puede hacer esto.

WilliamKF
fuente
A mí también me está sucediendo, con el kernel 3.18.17-13.el6.x86_64 (CentOS 6). Estoy bastante seguro de que es un error del sistema NFS subyacente del QNAP TS-212 NAS en el que está montado el directorio, puede alguien confirma?
godzillante
6

El disco es un disco montado en NFS. Cuando voy a la computadora host que publica la unidad, el archivo solo aparece una vez.

Probablemente un error, problema o condición de carrera con NFS.

Es posible tener dos archivos con el mismo nombre si edita directamente las estructuras del sistema de archivos utilizando un editor hexadecimal. Sin embargo, no estoy seguro de lo que sucedería si intenta eliminar o abrir los archivos. No estoy seguro de qué herramientas existen en Linux para acceder a un archivo por número de inodo (que no se puede duplicar), pero eso puede funcionar.

Los nombres de archivo duplicados son algo fsckque probablemente atraparía e intentaría solucionar.

Sin embargo, asegúrese de que ninguno de los archivos tenga espacios finales diferentes.

LawrenceC
fuente
Iba a sugerir que la cantidad de escritura en el sistema de archivos finalmente rompió algo y permitió la existencia de dos archivos idénticos.
Doktoro Reichard
Correr fsckno encontró problemas. Se reiniciaron las máquinas host y cliente, el problema aún se muestra.
WilliamKF
Debería haber sido más claro: fsckprobablemente solo funcione en el sistema de archivos local, no en uno montado en NFS. Probablemente necesite actualizar / parchear sus paquetes nfs y posiblemente su kernel. Como @somequixotic menciona, su CentOS es viejo y los problemas que tiene pueden haberse resuelto en futuras actualizaciones.
LawrenceC
4

Existe la posibilidad de que tenga un carácter oculto no imprimible o un espacio en blanco en uno de los nombres de archivo. Puede consultar proporcionando la -bopción de ls, por ejemplo:

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\

Tenga en cuenta que \significa el espacio al final de ese nombre de archivo.

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

Como alternativa (aunque lo anterior debería funcionar), puede canalizar la salida a través de este script perl para reemplazar cualquier cosa que no sea un carácter ASCII imprimible con su código hexadecimal. Por ejemplo, un espacio se convierte \x20.

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

Uso:

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