ti-enxame.com

rebanho (2) contra fcntl (2) em um NFS

A documentação do Perl 5.x afirma que sua implementação de flock (..) usará uma das seguintes chamadas nativas, começando em 1 e trabalhando em direção a 3 se indisponível:

  1. rebanho (2)
  2. fcntl (2)
  3. lockf (3)

Isso é bom. No entanto, você deve ter notado o aviso de que flock (2) não deve ser usado em um NFS. O documento sugere o uso de um sinalizador -Ud_flock para forçar o Perl a usar o flock (2). A página de manual do flock (2) (no Redhat) afirma uma isenção de responsabilidade semelhante sobre questões de NFS.

Minha pergunta é: por quê!?!? Não consigo encontrar um artigo detalhado ou uma explicação de POR QUE o rebanho (2) não é seguro em um NFS.

Eu escrevi vários scripts de teste em C e Perl, no Redhat (onde flock (2) está sendo usado) e no Solaris (onde fcntl (2) está sendo usado). Executei strace/truss para garantir que o Perl estava realmente usando flock (2) e fcntl (2), respectivamente. Não consegui reproduzir nenhum problema em que um bloqueio não estava sendo respeitado! O que da??

21
Jmoney38

Lennart Poettering recentemente fez algumas pesquisas sobre o comportamento de bloqueio do sistema de arquivos do Linux, o que não apresenta um quadro particularmente otimista para o bloqueio por NFS (especialmente o acompanhamento ao qual ele faz um link na parte inferior do post).

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

3
Ivatar

Tenho certeza de que você está analisando questões de legado. Lembre-se de que o manual do Perl5 foi lançado em 1994 e era apenas uma edição do manual do Perl4 de 1991. Naquela época, provavelmente poderia ser dito sobre o frequentemente chamado Nightmare File System que "não é o quão bem o urso dança que espanta, mas que dança mesmo ".

O NFS2 na Época de 1991 estava lentamente saindo da Sun para outras plataformas e era relativamente bruto. O modelo de segurança era essencialmente inexistente (o root em uma máquina cliente poderia ler o conteúdo completo de uma montagem NFS) e o bloqueio - via nfs.lockd - estava do lado de fora do experimental. Você teria sido tolo se esperasse que a semântica do rebanho funcionasse corretamente entre duas implementações supostamente interoperáveis ​​diferentes. Coax era o Ethernet PHY dominante na época que muitos usuários de rede nunca tiveram o desagrado de usar (o que quer dizer que você esqueceu de colocar o resistor de terminação 50 ????) se isso lhe dá um melhor controle do estado de intranets então.

Larry Wall e sua equipe tinham todos os motivos para fazer suposições pessimistas sobre a exatidão dos bloqueios NFS na época, e este é o tipo de programação defensiva que futuros código-jóqueis relutam em remover porque é muito difícil provar a ausência de defeito por removendo código antigo que é reintroduzido em interoperabilidade com um sistema legado do qual você nunca ouviu falar.

Desde então, o NFS melhorou consideravelmente e o lockd migrou com o tempo para um recurso do kernel Linux 2.6. Para uma coleção de sistemas 2003+, o bloqueio de arquivo NFS provavelmente pode ser confiável, especialmente se bem testado em seu aplicativo nas várias plataformas em que ele pode estar sendo executado.

Todos os itens acima foram copiados de memória e provavelmente poderiam ser comprovados por meio de pesquisas (por exemplo, http://nfs.sourceforge.net/ ) mas a prova - como eles dizem - está no bloqueio, e se você não o testou, presume-se que esteja quebrado.

16
msw

Outro, direto do FAQ do Linux-NFS: nfs.sf.net

Estou tentando usar bloqueios flock ()/BSD para bloquear arquivos usados ​​em vários clientes, mas os arquivos foram corrompidos. Por quê? A. Os bloqueios flock ()/BSD atuam apenas localmente em clientes Linux NFS anteriores ao 2.6.12. Use bloqueios fcntl ()/POSIX para garantir que os bloqueios de arquivo sejam visíveis para outros clientes.

Aqui estão algumas maneiras de serializar o acesso a um arquivo NFS.

Use a API de bloqueio fcntl ()/POSIX. Este tipo de bloqueio fornece bloqueio de intervalo de bytes em vários clientes por meio do protocolo NLM ou por meio do NFSv4. Use um arquivo de bloqueio separado e crie links físicos para ele. Veja a descrição na seção O_EXCL da página do manual creat (2). É importante notar que até os primeiros kernels 2.6, os criações O_EXCL não eram atômicos em clientes NFS Linux. Não use criações O_EXCL e espere comportamento atômico entre vários clientes NFS, a menos que você esteja executando um kernel mais recente que 2.6.5.

É um problema conhecido que o Perl usa o bloqueio flock ()/BSD por padrão. Isso pode interromper programas portados de outros sistemas operacionais, como Solaris, que esperam que os bloqueios flock/BSD funcionem como os bloqueios POSIX.

No Linux, usar o bloqueio de arquivo em vez de um link físico tem o benefício adicional de marcar o cache do cliente com o servidor. Quando um bloqueio de arquivo é obtido, o cliente descarrega o cache da página desse arquivo para que qualquer leitura subsequente obtenha novos dados do servidor. Quando um bloqueio de arquivo é liberado, todas as alterações no arquivo desse cliente são descarregadas de volta para o servidor antes que o bloqueio seja liberado para que outros clientes que aguardam para bloquear aquele arquivo possam ver as alterações.

O cliente NFS em 2.6.12 fornece suporte para bloqueios flock ()/BSD em arquivos NFS, emulando os bloqueios de estilo BSD em termos de bloqueios de intervalo de bytes POSIX. Outros clientes NFS que usam o mesmo mecanismo de emulação, ou que usam bloqueios fcntl ()/POSIX, verão os mesmos bloqueios que o cliente NFS Linux vê.

Em sistemas de arquivos Linux locais, os bloqueios POSIX e os bloqueios BSD são invisíveis um para o outro. Assim, devido a esta emulação, os aplicativos em execução em um servidor NFS Linux ainda verão os arquivos bloqueados por clientes NFS como sendo bloqueados com um bloqueio fcntl ()/POSIX, se o aplicativo no cliente estiver usando um estilo BSD ou um POSIX- bloqueio de estilo. Se o aplicativo do servidor usar bloqueios BSD flock (), ele não verá os bloqueios que os clientes NFS usam.

3
Nikhil Mulley

Isso está desatualizado agora. NFS4 suporta bloqueio dentro do protocolo (nenhum daemon lockd ou mecanismo de retorno de chamada RPC é necessário) e o método flock() do Perl funciona bem - estamos usando-o na produção.

Versões muito antigas do kernel implementadas flock (o syscall) como um no-op no NFS, e outras coisas como bloqueio de intervalo de bytes não eram suportadas adequadamente. É daí que vem a histeria.

3
rjh