47. Criando subvolumes BTRFS durante a instalação do Debian, e criação de swapfile permitindo uso do Timeshift

Debian BTRFS Timeshift

Que título enorme né? Infelizmente não tinha como descrever esse conteúdo de forma mais resumida.

Criar subvolumes BTRFS é fácil, mas criá-los durante a instalação do sistema operacional pode ser complicado. Eu me deparei com essa situação quando a ideia de voltar pro Debian começou a crescer na minha cabeça. Ainda estou usando Mint, mas a lentidão na atualização do Mint, que está bem atrás do Ubuntu, já está me incomodando. E o Debian Testing é rolling realease sem ser bleeding edge (Debian Sid seria ambos).

Um problema com o qual me deparei quando fui usar o Timeshift para criar backups no Debian e no Linux Mint quando usando um sistema de arquivos BTRFS, é que o Timeshift não funciona quando o nome do volume raiz for diferente de @, e os sistemas Debian-like costumam usar @rootfs quando criados automaticamente pelo instalador do sistema.

Outra coisa que sempre quis fazer é criar, logo na instalação, os subvolumes raiz (@) e home (@home), para não ter o trabalho de renomear o subvolume de @rootfs para @ depois da instalação, e não ter que criar um subvolume @home e ter o trabalho de transferir meus muitos arquivos de uma partição para o novo home depois. Fora que o instalador não sabe criar volumes, só partições. Então, se você mandar criar / e /home, ele vair criar duas partições BTRFS, e não dois volumes em uma única partição!

Pra finalizar, não tenho mais usado partição swap, ultimamente prefiro swapfile que, inclusive, é mais fácil de redimensionar, sem ter que mexer nas partições. Mas tem um porém: o Timeshift (sempre ele!) não consegue criar backups se o swapfile estiver ativo e no mesmo subvolume do sistema raiz. Então a solução é simples: criar também o volume @swap, e montá-lo em /swap na inicialização do sistema, e colocar o swapfile nesse volume.

Faremos tudo isso, é mais fácil do que parece.

Baixando a ISO do Sistema

No meu exemplo vou usar o Debian testing, atualmente chamado "Trixie". Baixe-o diretamente no site do Debian: https://www.debian.org/CD/http-ftp.

Recentemente descobri o Jigdo, uma ferramenta oficial muito interessante para baixar as ISOs do projeto Debian, permitindo baixar as imagens além do CD/DVD 1: https://www.debian.org/CD/jigdo-cd.

Eu vou fazer os procedimentos numa Máquina Virtual, usando o Virt-manager como frontend para o QEMU. Aqui temos que tomar cuidado, porque a instalação do Sistema em máquinas virtuais do QEMU, com UEFI, vai falhar se não selecionarmos UEFI x86_64: /usr/share/OVMF/OVMF_CODE_4M.fd. A opção chipset pode deixar Q35 mesmo.

Desculpem, não vou mostrar todos os passos da instalação, não é o escopo deste artigo, mas eu tenho um artigo completo aqui: 41. Instalação mínima do Debian 12 (Bookworm).

Particionamento

Na parte do particionamento:

Optar pelo particionamento manual:

E aí criamos uma partição EFI e uma BTRFS:

Na primeira partição eu coloco "usar como:" Partição de Sistema EFI, flag inicializável ligada e tamanho 500 mib. Quando ele pedir o tamanho da partição (a primeira coisa que ele faz), você pode escrever desse jeito mesmo: "500 mib" (500 MiB = 523,2 MB). Qualquer coisa entre 300 MB e 500 MB está ok. A diferença entre MiB e MB para partições EFI é insignificante.

NOTA: a opção Partição de Sistema EFI só aparece se o seu PC suportar EFI. Se estiver testando esse tutorial numa máquina virtual, se assegure de que ela foi criada com suporte a UEFI.

Por fim criamos uma partição BTRFS no espaço restante com ponto de montagem /.

Então selecione "Finalizar o particionamento e escrever as mudanças no disco". O instalador vai reclamar que está faltando uma partição swap e pergunta se você quer voltar ao menu de particionamento. Diga que não, continue, escreva as mudanças no disco, continue. Ao voltar ao menu de instalação, não instale o sistema base ainda!

Console secreto – entrando na matriz

Agora começa a diversão. Dê um Ctrl+Alt+F2 (no menu do Virt-manager selecione "Enviar tecla"), vai abrir um console preto, dê um Enter e o console aparece piscando.

Nós vamos inserir o comando df -h para listar o que estiver montado: precisamos saber o nome dos dispositivos e os pontos de montagem. Em seguida desmontamos as partições "target", começando pela EFI, depois vamos montar em /mnt a partição que definimos anteriormente como /, para podermos renomear o subvolume raiz e criar os subvolumes @home e @swap. Aí desmontamos o /mnt.

~ # df -h
(...)
~ # umount /target/boot/efi
~ # umount /target
~ # mount /dev/vda2 /mnt
~ # ls /mnt
@rootfs
~ # mv /mnt/@rootfs /mnt/@
~ # ls /mnt
@
~ # btrfs subvolume create /mnt/@home /mnt/@swap
Create subvolume '/mnt/@home'
Create subvolume '/mnt/@swap'
~ # ls /mnt
@    @home    @swap
~ # umount /mnt
~ # ls /mnt
~ #

Agora vamos montar os subvolumes, para o instalador poder usá-los depois:

~ # mount -o defaults,noatime,autodefrag,subvol=@ /dev/vda2 /target
~ # mkdir -pv /target/boot/efi /target/home /target/swap
created directory: '/target/home'
created directory: '/target/swap'
~ # mount -o defaults,noatime,autodefrag,subvol=@home /dev/vda2 /target/home
~ # mount -o defaults,noatime,autodefrag,subvol=@swap /dev/vda2 /target/swap
~ # mount /dev/vda1 /target/boot/efi
NOTA: Recomendo a leitura das páginas de manual fstab(5), mount(8) e btrfs(5). Para entender todas as opções disponíveis para o BTRFS, a página Read the Docs: Btrfs specific mount options é muito boa. As opções de montagem que escolhi foram defaults, noatime e autodefrag:
  • defaults: O conjunto real de todas as opções de montagem padrão depende do kernel e do tipo de sistema de arquivos. O linux é capaz de detectar se você está usando SSD ou não, então você pode omitir muitas opções apenas usando o "defaults". Eu tenho um SSD M.2 NVME, e a opção "defaults" inclui: rw, ssd, discard=async e space_cache=v2. Faça um teste, monte um volume aí no seu PC apenas com a opção defaults, depois digite mount | column -t num terminal. Ele listará as opções que foram usadas.
  • autodefrag: Esta é específica do BTRFS, mas não está inclusa em "defaults", ela ativa a desfragmentação automática de arquivos (você vai querer isso!). Quando ativado, pequenas gravações aleatórias em arquivos (em um intervalo de dezenas de kilobytes, atualmente são 64 KB) são detectadas e colocadas na fila para o processo de desfragmentação.
  • noatime: Essa opção não é específica para o BTRFS, mas é recomendada. Noatime não atualiza os tempos de acesso dos inodes (por exemplo, para acesso mais rápido no spool de notícias para acelerar os servidores de notícias). Isso funciona para todos os tipos de inode (diretórios também), portanto implica "nodiratime". Melhora significativamente o desempenho porque nenhuma nova informação de tempo de acesso precisa ser gravada.
  • nodatacow: Desabilita a copy-on-write (COW) dos dados para arquivos recém-criados. Nodatacow implica nodatasum e desativa a compactação (compress, abaixo). Todos os arquivos criados em nodatacow também recebem o atributo de arquivo NOCOW (consulte chattr(1)). Não usamos esta opção. Ela só seria útil se o subvolume da swap estivesse em outra partição, mas se o volume swap fosse colocado em outra partição, seria melhor usar logo uma partição swap. Isso porque o BTRFS não suporta a montagem de subvolumes da mesma partição com configurações diferentes em relação ao COW. Se você montar primeiro um subvolume da partição com o COW habilitado (o padrão), todos os outros subvolumes na mesma partição também serão montados com o COW habilitado, mesmo se você tiver especificado nodatacow no fstab. Então essa opção não nos ajuda. Descrevi ela apenas para instruir o leitor deste tutorial.

Essa opção é interessante, eu já cheguei a usar, não é ruim, mas eu não preciso dela:

  • compress=<type[:level]>: se você tem pouco espaço em disco, e se usa um SSD, e opte por um algoritmo MUITO rápido como o ZSTD (compress=zstd), ele comprime todos os arquivos na partição montada com essa opção. Então você pode usá-la no subvolume @home, por exemplo. A queda de desempenho é pequena, mesmo assim é melhor só usar se tiver um SSD.

Editando o FSTAB e Instalando o Sistema

Para encerrar nosso tutorial, editamos o fstab do sistema "target":

~ # nano /target/etc/fstab

Seu fstab deve estar parecido com o meu:

# /etc/fstab: static file system information.
#
# Use 'blkid' to print the universally unique identifier for a
# device; this may be used with UUID= as a more robust way to name devices
# that works even if disks are added and removed. See fstab(5).
#
# systemd generates mount units based on this file, see systemd.mount(5).
# Please run 'systemctl daemon reload' after making changes here.
#
# <file system>  <mount point>  <type>  <options>  <dump>  <pass>
# / was on /dev/vda2 during installation
UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx /  btrfs  defaults,subvol=@rootfs  0  0
# /boot/efi was on /dev/vda1 during installation
UUID=xxxx-xxxx /boot/efi      vfat         umask=0777   0  1
/dev/sr0       /media/cdrom0  udf,iso9660  user,noauto  0  0

Vamos alterar daqui pra baixo:

# <file system>  <mount point>  <type>  <options>  <dump>  <pass>

Não altere o UUID, aqui eu deixei (...) pra economizar "colunas" e caber na página. Como @, @home e @swap estão todos no mesmo disco físico, eles terão todos o mesmo UUID. Perceba também que mudamos @rootfs para @:

UUID=(...)      /              btrfs        defaults,autodefrag,noatime,subvol=@      0  1
UUID=(...)      /home          btrfs        defaults,autodefrag,noatime,subvol=@home  0  2
UUID=(...)      /swap          btrfs        defaults,autodefrag,noatime,subvol=@swap  0  0
/swap/swapfile  none           swap         sw                                        0  0
UUID=(...)      /boot/efi      vfat         umask=0777                                0  1
/dev/sr0        /media/cdrom0  udf,iso9660  user,noauto                               0  0

Desconfio de que, se colocarmos apenas "subvol=@swap" nas opções de /swap, já será suficiente.

Feito isso, salve e saia do nano. Para voltar ao processo de instalação, do ponto onde parou, pressione Ctrl+Alt+F5 (no Debian é F5, no Devuan é F1, se não funcionar teste as outras teclas F: F3, F4 etc). De volta ao menu de instalação, você já pode instalar os pacotes básicos e seguir o jogo.

Criando o Swapfile após a Instalação

Como visto, não temos como montar o subvolume de swap com a opção nodatacow, porque ele está na mesma partição dos demais volumes montados com COW. Então teríamos que criar um swapfile na partição swap e definir seus atributos como No_COW usando o comando chattr:

~ # chattr +C /target/swap/swapfile

(*) Com "+C" maiúsculo.

NO ENTANTO, o comando chattr não está disponível durante a instalação! A ÚNICA coisa a fazer é criar a swapfile DEPOIS da instalação. Nós já montamos o subvolume swap, já inserimos ele no fstab, onde também inserimos o swapfile que ainda não existe! Quando o sistema inicializar, ele vai tentar montar o swapfile que não existe e vai dar uma mensagem de erro, mas o sistema vai inicializar de qualquer modo, mesmo sem a swap, e o subvolume swap será montado!

Já logado no Debian, crie um arquivo de swap no subvolume montado em /swap, defina permissões apropriadas, formate e monte o swapfile:

$ sudo dd if=/dev/zero of=/swap/swapfile bs=1M count=4096
4096+0 records in
4096+0 records out
$ sudo chmod 600 /swap/swapfile
$ sudo chattr +C /swap/swapfile
$ sudo mkswap /swap/swapfile
Setting up swapspace version 1, size = 4294963200 bytes
UUID=...
$ sudo swapon -a

Perceba que swapon -a só funciona porque já inserimos o local do swapfile em /etc/fstab, se não estivesse lá ele não seria montado, teríamos que usar swapon /swap/swapfile.

NOTA: a swap criada no exemplo tem 4 GB. O tamanho ideal varia, consulte este site como referência. Alterando a opção count=4096 você define outros tamanhos (múltiplos de 1024 = 1 GB).

Alternativa: definir os atributos do subvolume como No_COW

Podemos aplicar o atributo No_COW direto sobre a pasta /swap e, com isso, qualquer arquivo criado nela será automaticamente definido como No_COW.

$ sudo chattr +C /swap

Claro que a ideia é fazer isso ANTES de criar o swapfile.

Comentários