Como o Linux lida com dispositivos de bloco?

4

Hoje eu aprendi que o FreeBSD removeu o suporte para dispositivos de bloco inteiramente. Enquanto lia o racional para a decisão, me deparei com isso:

Block devices are disk devices for which the kernel provides caching. This caching makes block-devices almost unusable, or at least dangerously unreliable. The caching will reorder the sequence of write operations, depriving the application of the ability to know the exact disk contents at any one instant in time. This makes predictable and reliable crash recovery of on-disk data structures (filesystems, databases etc.) impossible. Since writes may be delayed, there is no way the kernel can report to the application which particular write operation encountered a write error, this further compounds the consistency problem.

(De link )

No entanto, sei que o Linux quase que exclusivamente usa dispositivos de bloco (embora um possa solicitar um dispositivo bruto).

Como então o Linux contorna os problemas mencionados nesta citação? Ou a maioria dos drivers apenas solicita um dispositivo bruto?

    
por Zigsaz 21.09.2015 / 01:04

1 resposta

5

O pessoal do BSD é realmente hardcore e geralmente faz coisas surpreendentes :-) Remover a camada de dispositivo de bloco não é um problema na minha opinião (por exemplo, o nfs nem tem um dispositivo de bloco subjacente), mas esse raciocínio não é contra os dispositivos de bloco, mas contra o cache de gravação. E remover o cache de gravação é, na minha opinião, uma coisa ruim, muito ruim. Se o seu processo escreve alguma coisa no disco, você não recupera o controle até que ele não tenha sucesso?

Mas não acho que eles não soubessem o que fazem. Espero que alguém explique suas razões em outra resposta.

Para explicar isso claramente, preciso explicar como funcionam os sistemas de arquivos. Um driver de sistema de arquivos é essencialmente uma camada de tradução entre as operações do sistema de arquivos (diretório aberto, criação de arquivo, leitura-gravação, exclusão, etc) e entre as operações de bloco (por exemplo: "escreva a página 0xfce2ea31 no bloco 0xc0deebed").

Mas as operações do bloco não alcançam o disco rígido no local. Primeiro, eles estão indo para o cache de blocos. O que significa que, se o sistema de arquivos quiser gravar uma página de memória no disco, primeiro ele gravará em uma área de memória reservada. O gerenciamento de memória do kernel irá gravar esses dados no disco rígido, se achar que está ótimo. Isso permite várias melhorias de velocidade: por exemplo, muitas operações de gravação acontecem no início e no final do disco, o kernel pode combiná-las de tal maneira, que o cabeçote do disco deve se reposicionar o mais raramente possível.

Há outro aprimoramento: se o seu programa gravar em um arquivo, ele terá uma operação tão rápida, como se fosse um ramdisk. Claro que só é possível até que a RAM do sistema não esteja cheia, depois disso eles devem esperar pelo esvaziamento do cache de gravação. Mas isso acontece somente se houver muita operação de gravação de uma só vez (por exemplo, você está copiando arquivos grandes).

No caso de sistemas de arquivos, existe uma grande diferença entre os sistemas de arquivos que estão sendo executados em um disco (ou seja, dispositivos de bloco) e que não são (por exemplo, nfs). No caso do segundo, não há possibilidade de armazenamento em bloco, porque não há blocos. No caso deles, há um "cache de buffer" assim chamado, que essencialmente significa cache ainda (lido e gravado), mas não é organizado em torno de blocos de memória, mas fragmentos de E / S de qualquer tamanho.

Sim, no Linux, existem os dispositivos de bloco "brutos" que permitem o uso de dispositivos de disco sem o mecanismo de armazenamento em cache de blocos. Mas esse problema não é resolvido por eles.

Em vez disso, existem os chamados "journaling filesystems". No caso dos sistemas de arquivos de registro no diário, o sistema de arquivos tem a oportunidade de instruir o kernel, quais páginas devem ser gravadas antes de outras. Se não houver um mecanismo de registro no diário em um sistema de arquivos, ele apenas grava blocos no disco (mais precisamente: no cache de blocos), e o kernel irá realmente executar a operação de gravação real se achar que é ideal.

Você pode imaginar os sistemas de arquivos de registro no diário como se cada operação de gravação ocorresse duas vezes: primeiro, em um "diário", que é uma área reservada no disco, e somente depois disso para seu local real. Em caso de falha do sistema ou erro de disco, o conteúdo do último estado não danificado do disco pode ser muito rápido e facilmente reconstruído no diário.

Mas isso diminui significativamente o desempenho de gravação, porque cada gravação deve ser feita duas vezes. É por isso que, na realidade, os sistemas de arquivos de journaling trabalham de uma maneira muito mais complexa, eles estão usando várias manipulações complexas de dados de estrutura para reduzir essa sobrecarga para um nível quase invisível. Mas isso é difícil: por exemplo, a principal melhoria do ext3 em relação ao ext2 foi a inclusão do journaling, que multiplicou seu tamanho de código.

No Linux, a API da camada de bloco possui um mecanismo de "barreira". Os sistemas de arquivos podem configurar "barreiras" entre suas operações de gravação. Uma barreira significa que os dados após a barreira serão gravados no disco somente após todos os dados antes da barreira já terem sido gravados. Os sistemas de arquivos de registro no diário estão usando os mecanismos de barreira para instruir a camada de bloco sobre o ordenamento necessário das operações reais de gravação. Como eu sei, eles não usam o mapeamento de dispositivos brutos.

Eu não sei, o que o FreeBSD faz sobre o caso. Talvez a eliminação dos dispositivos de bloco signifique apenas que tudo irá com o cache de buffer e não com o cache de bloco. Ou eles têm algo que não está escrito aqui. Nos sistemas internos de arquivos existem grandes diferenças entre o mundo do * BSD e o do Linux.

    
por 21.09.2015 / 01:43