flock (2) versus fcntl (2) sobre un NFS

19

La documentación de Perl 5.x establece que su implementación de flock (..) utilizará una de las siguientes llamadas nativas, comenzando en 1 y trabajando hacia 3 si no está disponible:

  1. rebaño (2)
  2. fcntl (2)
  3. lockf (3)

Esta bien. Sin embargo, es posible que haya notado su descargo de responsabilidad de que el lote (2) no debe usarse sobre un NFS. El documento sugiere usar una bandera -Ud_flock para obligar a Perl a usar flock (2). La página de manual de flock (2) (en Redhat) establece un descargo de responsabilidad similar sobre los problemas de NFS.

Mi pregunta es, ¿por qué? Parece que no puedo encontrar un artículo en profundidad o una explicación de POR QUÉ el lote (2) no es seguro en un NFS.

He escrito varios scripts de prueba en C y Perl, tanto en Redhat (donde se usa flock (2)) como en Solaris (donde se usa fcntl (2)). Ejecuté strace / truss para asegurarme de que Perl estaba usando flock (2) y fcntl (2) respectivamente. ¡No pude replicar ningún problema en el que no se respetara un bloqueo! ¿¿Lo que da??

Jmoney38
fuente

Respuestas:

3

Lennart Poettering recientemente investigó el comportamiento de bloqueo del sistema de archivos de Linux, que no pinta una imagen particularmente optimista para bloquear sobre NFS (especialmente el seguimiento al que se vincula en la parte inferior de la publicación).

http://0pointer.de/blog/projects/locking.html

Ivatar
fuente
1
Ese es el tipo exacto de información que estaba buscando. ¡Gracias! Después de varias semanas de investigación, es una resolución muy similar a la que llegué, pero es genial leer un artículo que confirma mis sospechas (y sugiere otras). El enlace de los comentarios de esa página también fue una buena referencia y un buen artículo sobre POSIX y su historia): samba.org/samba/news/articles/low_point/tale_two_stds_os2.html
Jmoney38
15

Estoy bastante seguro de que está analizando los problemas heredados. Recuerde que el manual de Perl5 fue lanzado en 1994 y que era solo una edición del manual de Perl4 de 1991. En esos días, probablemente se podría decir sobre el sistema de archivos Nightmare, que a menudo se llama "no es qué tan bien baila el oso lo que sorprende, pero que baila en absoluto ".

El NFS2 en la época de 1991 se arrastraba lentamente del Sol hacia otras plataformas y era relativamente crudo. El modelo de seguridad era esencialmente inexistente (la raíz en una máquina cliente podía leer el contenido completo de un montaje NFS) y el bloqueo, a través de nfs.lockd, era este lado de la experimentación. Habría sido una tontería esperar que la semántica de bandada funcione correctamente si es que existe entre dos implementaciones supuestamente interoperables diferentes. Coax era el PHY de Ethernet dominante en el momento en que muchos usuarios de la red nunca habían tenido el desagrado de usar (¿qué quiere decir que olvidó poner la resistencia de terminación de 50𝛀?) Si eso le da un mejor control del estado de las intranets.

Larry Wall y su equipo tenían todas las razones para hacer suposiciones pesimistas sobre la corrección de las cerraduras de NFS en ese momento, y este es el tipo de programación defensiva que los futuros codificadores no quieren eliminar porque es muy difícil demostrar la ausencia de un defecto. eliminar el código antiguo que se reintroduce en interoperabilidad con un sistema heredado del que nunca has oído hablar.

Desde entonces, NFS ha mejorado considerablemente y lockd ha migrado a tiempo a una característica del núcleo Linux 2.6. Para una colección de sistemas 2003+, es probable que se pueda confiar en el bloqueo de archivos NFS, especialmente si se prueba bien dentro de su aplicación en las muchas plataformas en las que se está ejecutando.

Todo lo anterior fue eliminado de la memoria, y probablemente podría confirmarse a través de la investigación (por ejemplo, http://nfs.sourceforge.net/ ), pero la prueba, como dicen, está en el bloqueo, y si no lo probó , se presume roto.

msw
fuente
Ese es un gran análisis. De hecho, he llegado a la misma conclusión hasta ahora. Leí nuevamente la página de nfs sourceforge después de que publicaste ese enlace, ¡y finalmente encontré lo que estaba buscando! ¡Aquí hay un análisis en profundidad directamente de la boca del caballo!
Jmoney38
2
Ups , presioné enter ... vaya a nfs.sourceforge.net , la sección D10 hacia abajo discute este problema en detalle.
Jmoney38
3

Otro, directamente de las preguntas frecuentes de Linux-NFS: nfs.sf.net

Estoy tratando de usar los bloqueos flock () / BSD para bloquear archivos utilizados en múltiples clientes, pero los archivos se corrompen. ¿Cómo? A. Los bloqueos flock () / BSD actúan solo localmente en clientes NFS de Linux anteriores a 2.6.12. Utilice los bloqueos fcntl () / POSIX para garantizar que los bloqueos de archivos sean visibles para otros clientes.

Aquí hay algunas formas de serializar el acceso a un archivo NFS.

Utilice la API de bloqueo fcntl () / POSIX. Este tipo de bloqueo proporciona un bloqueo de rango de bytes a través de múltiples clientes a través del protocolo NLM o NFSv4. Use un archivo de bloqueo separado y cree enlaces duros a él. Consulte la descripción en la sección O_EXCL de la página del comando man creat (2). Vale la pena señalar que hasta principios de 2.6 núcleos, las creaciones de O_EXCL no eran atómicas en los clientes NFS de Linux. No use O_EXCL crea y espera un comportamiento atómico entre múltiples clientes NFS a menos que esté ejecutando un núcleo más nuevo que 2.6.5.

Es un problema conocido que Perl usa el bloqueo flock () / BSD por defecto. Esto puede interrumpir los programas portados desde otros sistemas operativos, como Solaris, que esperan que los bloqueos flock / BSD funcionen como los bloqueos POSIX.

En Linux, el uso del bloqueo de archivos en lugar de un enlace duro tiene el beneficio adicional de señalar el caché del cliente con el servidor. Cuando se adquiere un bloqueo de archivo, el cliente vaciará la memoria caché de la página para ese archivo para que cualquier lectura posterior obtenga nuevos datos del servidor. Cuando se libera un bloqueo de archivo, cualquier cambio en el archivo en ese cliente se devuelve al servidor antes de que se libere el bloqueo para que otros clientes que esperan bloquear ese archivo puedan ver los cambios.

El cliente NFS en 2.6.12 proporciona soporte para bloqueos flock () / BSD en archivos NFS emulando los bloqueos de estilo BSD en términos de bloqueos de rango de bytes POSIX. Otros clientes NFS que usan el mismo mecanismo de emulación, o que usan bloqueos fcntl () / POSIX, verán los mismos bloqueos que ve el cliente NFS de Linux.

En los sistemas de archivos locales de Linux, los bloqueos POSIX y los bloqueos BSD son invisibles entre sí. Por lo tanto, debido a esta emulación, las aplicaciones que se ejecutan en un servidor NFS de Linux aún verán los archivos bloqueados por los clientes NFS como bloqueados con un bloqueo fcntl () / POSIX, ya sea que la aplicación en el cliente esté usando un estilo BSD o POSIX- cerradura de estilo. Si la aplicación del servidor usa bloqueos BSD flock (), no verá los bloqueos que usan los clientes NFS.

Nikhil Mulley
fuente
Entonces, ¿dos clientes NFS que ejecutan el kernel 3.13. * Ven los flock () s del otro?
reinierpost
Si estoy entendiendo correctamente, la respuesta es no. A menos que me haya perdido algo, flockno lo ha hecho, no lo hace y no se bloqueará en los montajes nfs.
Daniel Farrell
Lo hace, al menos en NFS4.
rjh
3

Esto está desactualizado ahora. NFS4 admite el bloqueo dentro del protocolo (no se requiere un demonio lockd o un mecanismo de devolución de llamada RPC) y el flock()método de Perl funciona bien: lo estamos usando en producción.

Se implementaron versiones muy antiguas del kernel flock(syscall) como no operativas en NFS, y otras cosas como el bloqueo de rango de bytes no se admitían correctamente. De aquí viene la histeria.

rjh
fuente
Muchas gracias por la pista. El montaje con NFS4 resolvió mi problema. Seguido access.redhat.com/documentation/en-us/red_hat_enterprise_linux/… para obtener la configuración correcta de fstab.
maraspin