Cópia em gravação (cow)
De forma bastante simples e apenas para o entendimento, o sistema de cópia em gravação (copy-on-write), comumente referenciado apenas como
cow, consiste em uma técnica em que a cópia é apenas uma referência (quase como um link) do arquivo original.
Caso o arquivo original nunca mude seu estado (conteúdo), a cópia ainda será o mesmo arquivo e não ocupará o mesmo espaço do arquivo original, como um simples reflexo. Apenas quando o arquivo original sofrer alterações, apenas a diferença entre ambas é gravado no disco.
Esse conceito é extremamente útil quando usado para backup de arquivos ou do próprio sistema, já que reduz o número de ciclos de gravação no disco (algo desejável para SSD), diminuição do espaço ocupado e acelera qualquer operação deste tipo. Ainda traz a vantagem na facilidade de restauração deste arquivo ou diretório.
O conceito e funções de cow possui muitas outras características interessantes e variações possíveis dentro do BTRFS, porém, como algo que se propõe a ser simples e de fácil entendimento, outras opções mais avançadas cabem ao utilizador buscar na WIKI do BTRFS.
Subvolumes
Subvolumes são pontos de montagem virtuais para o sistema de arquivos, atuando como "discos virtuais", mas ao contrario de partições, são usados diretórios.
Exemplo: dentro da partição sda2, são criados três subvolumes, o "sistema", "usuario" e "snapshot" (local onde ficarão as cópias), sendo o primeiro montado como "/" (raiz), o segundo como "/home" e o terceiro em "/snapshot". Com esse modelo, em uma única partição temos algo parecido com o resultado de três partições independentes.
Ao observar a raiz da partição sda2, seriam encontrados três diretórios, como pode ser visto na imagem abaixo:
Outra forma de tentar exemplificar:
Sist. Arq. Tam. Usado Disp. Uso% Montado em
/dev/sda2 43G 14G 30G 31% /
/dev/sda2 43G 14G 30G 31% /home
/dev/sda2 43G 14G 30G 31% /snapshot
Cada um desses subvolumes criados, funciona de modo parecido a uma partição independente, onde o subvolume pode ser renomeado, clonado (espelhado), restaurado dentro da mesma partição ou em disco diferente, mas ao invés de partições, temos simples diretórios.
Mesmo em casos de quebra do sistema que esteja em um subvolume, não se perde outros subvolumes ou mesmo o seu conteúdo, mesmo em casos onde se precise reinstalar o sistema.
Neste exemplo, o sistema foi instalado no subvolume "sistema", e dentro deste subvolume estão os diretórios "home" e "snapshot". Se fosse fazer uma comparação ao uso de partições, seria algo como o "sistema" em sda2, "home" em sda3 e "snapshot" em sda4.
Dentro de sda2, teremos os três diretórios que representam os três subvolumes "sistema home snapshot", mas com o sistema em funcionamento, é como se sda2/home apontasse para sda2/sistema/home, e sda2/snapshot apontasse para sda2/sistema/snapshot, e ao se abrir sda2, estaríamos apenas na raiz do sistema, mas dentro do diretório "sistema".
Distros com Arch, Gentoo e Slackware são mais simples de instalar e gerenciar o sistema em subvolumes específicos, criados pelo usuário, já que nestas distros o sistema é instalado de forma manual, podendo qualquer diretório ser apontado para um disco ou subvolume.
O openSUSE, apesar de ter um instalador gráfico, também possui essa característica, porém, o esquema padrão proposto por eles é muito bom. Distros como Ubuntu/
GNU/Linux Mint ou Fedora, é necessário verificar a documentação, já que primeiro deve-se instalar o sistema, e depois em ambiente "chroot" ou outro sistema com acesso ao disco, criar os subvolumes e migrar os dados para eles, ajustar o FSTAB e o Grub. Sei que o Ubuntu cria, por padrão, um subvolume chamado "@" para o sistema, mas não tenho certeza de outras distros, pois não as uso.
**Esta é uma parte importante para o entendimento do parágrafo sobre "Imagem instantânea do sistema de arquivos (snapshot)", onde esse modelo fará maior sentido quando for explicado o conceito e uso de snapshot.
Criando e manipulando subvolumes
Subvolumes podem ser criados na raiz de uma partição, dentro de outros subvolumes ou diretórios (como demonstrado anteriormente), deletados, copiados, renomeados. A manipulação pode ser feita com o sistema em funcionamento, no caso de diretórios simples (diretório documentos ou fotos), porém, para a instalação do sistema ou subvolumes já montados como diretórios do sistema (/etc - /var - /home), devem ser manipulados com o sistema off line ou com o auxílio de um liveCD-USB.
Seguindo o modelo "btrfs subvolume <command> <args>", essas são as principais ações:
btrfs subvolume create [-i <qgroupid>] [<dest>/]<name>
Create a subvolume
btrfs subvolume delete [options] <subvolume> [<subvolume>...]
Delete subvolume(s)
btrfs subvolume list [options] <path>
List subvolumes and snapshots in the filesystem.
btrfs subvolume snapshot [-r] [-i <qgroupid>] <source> <dest>|[<dest>/]<name>
Create a snapshot of the subvolume
Exemplo de criação, considerando que o terminal esteja em
/de/sdax (onde "x" é a partição), caso contrário, é necessário especificar o diretório por extenso:
# btrfs subvolume create sistema
# btrfs subvolume create usuario
# btrfs subvolume create snapshot
Exemplos para deletar subvolumes:
# btrfs subvolume delete nomeoucaminhodosubvolume
Exemplo de uma instalação real, onde o subvolume no qual o sistema está instalado se chama "@":
# btrfs subvolume show /
@
Name: @
UUID: 8b5bb13c-3135-454f-a67b-b3ce326d5bea
Parent UUID: 233fd6b8-5df4-254b-9e28-269001eac655
Received UUID: -
Creation time: 2019-08-27 18:58:20 -0300
Subvolume ID: 277
Generation: 5084
Gen at creation: 575
Parent ID: 5
Top level ID: 5
Flags: -
Snapshot(s):
@snapshots/@-31-08-2019-04:04
@snapshots/@-05-09-2019-02:00
Quota group: 0/277
Limit referenced: -
Limit exclusive: -
Usage referenced: 5.40GiB
Usage exclusive: 1.59GiB
# btrfs filesystem df /
Data, single: total=12.01GiB, used=11.18GiB
System, single: total=32.00MiB, used=16.00KiB
Metadata, single: total=1.01GiB, used=835.59MiB
GlobalReserve, single: total=51.95MiB, used=16.00KiB
# btrfs filesystem usage /
Overall:
Device size: 40.04GiB
Device allocated: 13.05GiB
Device unallocated: 26.99GiB
Device missing: 0.00B
Used: 12.00GiB
Free (estimated): 27.82GiB (min: 27.82GiB)
Data ratio: 1.00
Metadata ratio: 1.00
Global reserve: 51.95MiB (used: 0.00B)
Data,single: Size:12.01GiB, Used:11.18GiB
/dev/sda2 12.01GiB
Metadata,single: Size:1.01GiB, Used:835.59MiB
/dev/sda2 1.01GiB
System,single: Size:32.00MiB, Used:16.00KiB
/dev/sda2 32.00MiB
Unallocated:
/dev/sda2 26.99GiB
Imagem instantânea do sistema de arquivos (snapshot)
As explicações anteriores são importantes para entendermos essa parte, já que snapshots podem ser feitos apenas em subvolumes ou partições diferentes, seja no mesmo ou em outro disco. O processo é muito semelhante como descrito no parágrafo "Criando e manipulando subvolumes", acima.
Esta é uma das mágicas mais legais do BTRFS, onde pode-se criar cópias de arquivos, diretórios e até do sistema inteiro, de modo a se ter um backup, ou uma espécie de ponto no tempo, onde é possível voltar sempre que necessário.
De modo simples, o snapshot "espelha" o conteúdo de uma origem para um destino. No caso de subvolumes, ou diretórios simples, "Imagens" no endereço "/home/seuusuario/Imagens", por exemplo, é possível apenas restaurar a um ponto anteriormente criado, com o sistema em funcionamento.
Já em casos em que o subvolume representa uma parte do sistema, o diretório
/var/cache/apt/, ou mesmo o
/opt ou algum outro, o snapshot pode ser realizado com o sistema em funcionamento, mas a restauração a um ponto anteriormente criado só pode ser realizada com o sistema desligado, ou seja, através de outro sistema ("chroot", por exemplo) ou mesmo através de um liveCD-USB. Em ambos os casos, o arquivo original será sobreposto pela cópia, sem possibilidade de recuperação, então se julgar necessário, pode ser interessante uma nova cópia (snapshot) do estado atual.
O comando para criação de snapshot é muito semelhante ao descrito anteriormente, mas ao invés de se usar o nome do subvolume, é usado o ponto ao qual ele esta montado:
# btrfs subvolume snapshot diretoriodeorigem diretoriodedestino
Exemplos:
# subvolume snapshot / /snapshots/sistema-$(date +%d-%m-%Y)
Create a snapshot of '/' in '/snapshot/sistema-09-09-2019'
Percebam que foi criado um diretório chamado "sistema-09-09-2019" dentro de "/snapshot". E para ter certeza de que o snapshot foi criado:
# ls -a /snapshot/
./ ../ sistema-09-09-2019/
Para restaurar esse snapshot, sabendo que o mesmo representa o sistema (necessário sistema desligado), usando um liveCD-USB (o uso de "chroot" muda de acordo com a distro) ou outro sistema com acesso ao disco onde estão os subvolumes e os snapshots, e com o terminal dentro do disco sdb2 e a partição montada em
/mnt:
# btrfs subvolume delete sistema
# btrfs subvolume snapshot /snapshot/sistema-09-09-2019 /mnt/sistema
Create a snapshot of '/snapshots/sistema-09-09-2019' in '/mnt/sistema'
Uma informação importantíssima, é que tanto para criação quanto para restauração, os outros subvolumes são apenas ignorados, ou seja, o snapshot é recursivo apenas para diretórios, arquivos comuns e links simbólicos (preservando todos os atributos e permissões de cada arquivo), mas ignora o conteúdo dos outros subvolumes, No exemplo acima, o conteúdo do diretório
/home e
/snapshot foi ignorado e não faz parte do snapshot.
Quando restaurar apenas um diretório, é necessário ter em mente que apenas uma parte do sistema voltou no tempo, deste modo, se for restaurado o sistema, menos os diretórios
/var e
/etc, vários erros podem acontecer, já que partes diferentes do sistema estarão em tempos e situações diferentes. Na restauração de partes não vitais do sistema (como diretórios da
/home), isso não terá grande influência, talvez apenas em alguns poucos aplicativos.
Em ações de restauração de snapshots, pode ser necessário fazer ajustes no FSTAB ou mesmo nas entradas do Grub, para que o sistema aponte para o subvolume correto durante o boot. Existe um script que cria entradas no Grub dos snapshots criado:
Compactação
O BTRFS, atualmente, suporta três métodos de compressão, sendo eles zlib, lzo e zstd. É indicado o uso de um kernel e do btrfs-progs o mais atualizado possível, já que certos recursos foram implementados apenas a partir da série 5 do kernel e em versões mais recentes do btrfs-progs.
A compressão pode ser aplicada em duas situações, ou com a opção ativada na montagem do sistema de arquivos (seja pelo comando "mount" ou pelo FSTAB), ou durante a desfragmentação de arquivos do disco. Na montagem do disco ou pelo FSTAB é possível escolher níveis de compressão, já durante a desfragmentação é usado o nível padrão.
O uso da compactação não é obrigatório em nenhum dos dois cenários descritos acima, mas em vários testes é possível encontrar resultados que demonstram a possibilidade de existir um ganho de desempenho em sistemas que usem compactação, porém, com o uso de níveis muito elevados, a taxa de leitura e escrita mesmo em SSD pode ser reduzida, além do impacto sobre o processador. Em hardware com pouco poder de processamento, é necessário testar.
Algumas considerações sobre os métodos de compressão:
- zlib :: extremamente lento para compactação, mas com bom resultado final e possui opção de nível de compactação, sendo possível escolher entre 1-9 possíveis, o padrão é 3;
- lzo :: o mais rápido para compactação ou descompactação, mas com menor nível de compactação, não possui opção quanto ao nível de compressão;
- zstd :: mais lento que o lzo, mas muito mais rápido que o zlib e com a melhor taxa de compactação, possui opção de nível de compactação sendo possível escolher entre 1-15 possíveis, o padrão também é 3.
Exemplos de uso:
# mount -o subvol=sistema compress=metododecompressao /dev/sda2 /mnt
Onde: "subvol=sistema" representa o subvolume (se não usar não é necessário especificar), "metododecompressao" deve ser substituído por zlib, lzo ou zstd, e no caso do zlib e zstd caso queira escolher o nível de compressão basta usar ":X" após o algorítimo escolhido, e onde "X" pode ser de 1 a 9 (zlib) e 1 a 15 (zstd).
Ficando assim:
# mount -o subvol=sistema compress=zstd:6 /dev/sda2 /mnt
O outro método é através da desfragmentação, onde pode se usar os seguintes comandos:
# btrfs filesystem defragment -rv -cmetododecompressao /
Onde: "metododecompressao" deve ser substituído por zlib, lzo ou zstd (observar que existe um "-c" junto com o algorítimo escolhido), neste método não é possível escolher o nível de compressão (é usado o padrão). Outra característica deste método, é que é possível usar um método de compressão especifico a apenas um diretório, por exemplo:
# btrfs filesystem defragment -rv -czlib /boot
# btrfs filesystem defragment -rv -czstd /var
*Atualmente, o Grub 2.02 não funciona com o diretório
/boot compactado em zstd (zlib e lzo funcionam normalmente), somente a partir da versão 2.04. Esta nova versão chegou ao Arch apenas em Julho de 2019, sendo esta uma das distros mais atualizadas que existe, então é fácil pressupor que a maioria das outras distros ainda usem a versão 2.02. A melhor soluçào é ter uma partição especifica para o
/boot, usar um subvolume específico para o
/boot com um método de compressão que funcione, ou resolver de forma manual através da desfragmentação com opção de compressão usando um algorítimo válido.