Entendendo subvolumes no BTRFS

Exercícios

1) Criar, formatar e montar um volume btrfs em arquivo de imagem no seu diretório de usuário.

mkdir testesBTRFS
cd testesBTRFS
truncate -s 200M imagem.img
mkfs.btrfs -L MinhaImagemBTRFS imagem.img
mkdir imagemMontada
sudo mount -o loop imagem.img imagemMontada/

Notas: O comando truncate somente aloca espaço no disco, portanto o conteúdo do arquivo é desconhecido. O mkfs.btrfs faz a formatação desse espaço reservado para organizar o sistema de arquivos e gravar a informação de espaço livre. Se não há esse comando instale o pacote btrfs-progs ou btrfs-tools (depende da distribuição). A opção -o loop no comando mount serve para montar arquivos como se fossem dispositivos de bloco.

2) Criar dois subvolumes, @raiz e @home.

sudo btrfs subvolume create imagemMontada/@raiz
sudo btrfs subvolu crea imagemMontada/@home

Nota: As opções do comando btrfs podem ser abreviadas desde que não causem confusão com outras opções.

3) Verificar os ID’s dos subvolumes criados

sudo btrfs subvol list ./imagemMontada

4) Qual o ID padrão do volume btrfs?

sudo btrfs subv get-default ./imagemMontada

5) Crie um diretório e copie um arquivo para dentro do imagemMontada:

mkdir ./imagemMontada/novodir
cp /etc/fstab ./imagemMontada/novodir

Nota: Saber trabalhar com permissões de arquivos é pré-requisito para esse tutorial. Caso não saiba veja a cola: sudo chown SeuUsuario imagemMontada/.

6) Liste o conteúdo da imagemMontada:

ls -la ./imagemMontada
Nota: Além do diretório criado também há “diretórios” que são subvolumes!

7) Copie um arquivo para um subvolume sem precisar montá-lo especificamente

sudo cp /etc/profile ./imagemMontada/@raiz
ls -la ./imagemMontada/@raiz

Nota: O autocompletar não funciona muito bem com o @, portanto as vezes tem que escrever tudo…

8) Monte um subvolume:

mkdir subvolumeMontado
sudo mount -o loop,subvol=@raiz imagem.img ./subvolumeMontado

Nota: A opção loop só e necessária por causa do arquivo ser imagem. Como o arquivo imagem.img já está montado, é possível também montar usando o dispositivo de bloco já configurado. O comando seria sudo mount -o subvol=@raiz /dev/loop0 ./subvolumeMontado .

9) Liste o conteúdo do subvolume Montado

ls -la ./subvolumeMontado

Nota: Veja que já está lá o arquivo que foi copiado via Árvore!

10) Altere o id-padrão do volume para o subvolume @home

sudo btrfs sub li ./imagemMontada
sudo btrfs subvolume set-default XXX ./imagemMontada

Nota: Substitua o valor XXX pelo ID mostrado pelo list.

11) Liste o id-padrão do subvolume @raiz

sudo btrfs subvolume get-default ./subvolumeMontado

Nota: Ao se alterar o ID-padrão de qualquer subvolume, será alterado o ID-padrão do volume como um todo. Da mesma forma pegar a variável id-padrão de qualquer subvolume retornará o valor do id-padrão da Árvore.

12) Desmonte tudo

sudo umount ./imagemMontada
sudo umount ./subvolumeMontado

13) Monte a imagem sem especificar subvolume e liste seu conteúdo

sudo mount -o loop imagem.img ./imagemMontada
ls -la ./imagemMontada

Nota: Como era de se esperar, foi montado o subvolume @home, que está vazio.

14) Liste os subvolumes do diretório imagemMontada

sudo btrfs subvo lis ./imagemMontada

Nota: Foram mostrados todos os subvolumes da Árvore. Talvez alguns esperassem que fosse mostrado apenas os subvolumes do subvolume @home, mas não é assim que funciona. O list sempre mostra todos os subvolumes!

15) Crie um arquivo e um subvolume no subvolume @home

sudo touch ./imagemMontada/arquivo.txt
sudo btrfs subv creat ./imagemMontada/temp-files

16) Liste o conteúdo do diretório imagemMontada

ls -la ./imagemMontada

Nota: Essa é uma estratégia que pode ser usada para snapshots, onde os subvolumes não são monitorados. Neste caso um futuro snapshot do @home não conterá os arquivos dentro do temp-files.

17) Crie mais um subvolume na Árvore, nomeado @tmp.

Nota: a árvore não está montada, então primeiro teremos que montá-la para depois criar o subvolume. Não é possível acessá-la pelo ponto de montagem imagemMontada, pois ele está montado como um subvolume e não é possível acessar volumes de hieraquia anterior a ele.

mkdir arvoreMontada
sudo mount -o loop,subvolid=5 imagem.img ./arvoreMontada
sudo btrfs subvol create ./arvoreMontada/@tmp
sudo btrfs sub list ./arvoreMontada

Nota: Número mágico 5 aparecendo aqui para montar a Árvore, pois não é possível montá-la pelo nome. Note também que com a árvore montada é possível criar subvolumes em qualquer subvolume! Outro ponto é perceber o relacionamento dos subvolumes, com o top level indicando o subvolume pai. Neste caso apenas o temp-files não é filho direto da árvore, mas sim do subvolume @home (perceba pelo id do top level)

18) Renomeie o subvolume @raiz para @rootfs

Nota: Não existe um comando específico do btrfs para renomear o volume. Porém mover o subvolume como se fosse um diretório resolve a situação. Para essas operações monte a Árvore. Mover um subvolume não altera seu ID, então se ele for o ID-padrão, continuará sendo.

mv ./arvoreMontada/@raiz ./arvoreMontada/@rootfs
sudo btrfs sub list ./arvoreMontada

19) Mova o subvolume @tmp para dentro do subvolume @home, renomeando-o para tmp

sudo mv ./arvoreMontada/@tmp ./arvoreMontada/@home
sudo mv ./arvoreMontada/@home/@tmp ./arvoreMontada/@home/tmp
sudo btrfs sub list ./arvoreMontada

Nota: Mover um subvolume para dentro de outro subvolume não altera seu ID, mas altera o subvolume pai. Veja como o top level do subvolume tmp mudou.

20) Monte o subvolume padrão e crie um arquivo de 120MB

sudo mount -o loop imagem.img ./imagemMontada
truncate -s 120M ./imagemMontada/arquivogrande.lixo
ls -la ./imagemMontada/arquivogrande.lixo

21) Crie uma cópia desse arquivo no subvolume temp-files.

cp ./imagemMontada/arquivogrande.lixo ./imagemMontada/tmp-files

Nota: Como era de se esperar, não há espaço suficiente no disco para dois arquivos de 120M, a imagem foi criada com 200MB. Porém uma das vantagens do btrfs é que ele não precisa copiar o conteúdo, ele pode apenas indicar que o mesmo conteúdo está em outro lugar do disco. Para tal usamos a opção –reflink=always ao copiar.

cp --reflink=always ./imagemMontada/arquivogrande.lixo ./imagemMontada/tmp-files

A cópia foi efetuada! Esse é o princípio de funcionamento dos snapshots, onde uma grande quantidade de arquivos parece estar duplicada, mas guardam suas referências de conteúdo.

22) Remova o arquivo do volume padrão e verifique o espaço livre:

rm ./imagemMontada/arquivogrande.lixo
df ./imagemMontada

Nota: O espaço livre não foi liberado pois o conteúdo ainda é referenciado em outro local.

23) Remova o arquivo do subvolume e verifique o espaço livre:

rm ./imagemMontada/tmp-files/arquivogrande.lixo
df ./imagemMontada

Nota: Agora sim o espaço foi liberado. Lembre-se que o espaço só será liberado quando não houver nenhuma referência ao conteúdo do arquivo. Isso pode ser fácil quando há poucos subvolumes, mas quando há 50 snapshots fica difícil. Nessa hora que os programas que auxiliam essa tarefa entram em jogo, como o snapper. Mas isso é assunto para um próximo tutorial!

Exercícios solucionados

john@MintVM:~$ # 1
john@MintVM:~$ mkdir testesBTRFS
john@MintVM:~$ cd testesBTRFS
john@MintVM:~/testesBTRFS$ truncate -s 200M imagem.img
john@MintVM:~/testesBTRFS$ mkfs.btrfs -L MinhaImagemBTRFS imagem.img
btrfs-progs v4.15.1
See http://btrfs.wiki.kernel.org for more information.

Label:              MinhaImagemBTRFS
UUID:               0e507c12-de93-4d14-be5a-c361660af3ce
Node size:          16384
Sector size:        4096
Filesystem size:    200.00MiB
Block group profiles:
  Data:             single            8.00MiB
  Metadata:         DUP              32.00MiB
  System:           DUP               8.00MiB
SSD detected:       no
Incompat features:  extref, skinny-metadata
Number of devices:  1
Devices:
   ID        SIZE  PATH
    1   200.00MiB  imagem.img

john@MintVM:~/testesBTRFS$ mkdir imagemMontada
john@MintVM:~/testesBTRFS$ sudo mount -o loop imagem.img imagemMontada/
[sudo] senha para john:     
john@MintVM:~/testesBTRFS$ # 2
john@MintVM:~/testesBTRFS$ sudo btrfs subvolume create imagemMontada/@raiz
Create subvolume 'imagemMontada/@raiz'
john@MintVM:~/testesBTRFS$ sudo btrfs subvolu crea imagemMontada/@home
Create subvolume 'imagemMontada/@home'
john@MintVM:~/testesBTRFS$ # 3
john@MintVM:~/testesBTRFS$ sudo btrfs sub list ./arvoreMontada
ID 256 gen 18 top level 5 path @raiz
ID 257 gen 25 top level 5 path @home
john@MintVM:~/testesBTRFS$ # 4
john@MintVM:~/testesBTRFS$ sudo btrfs subvolume get-default ./imagemMontada
ID 5 (FS_TREE)
john@MintVM:~/testesBTRFS$ # 5
john@MintVM:~/testesBTRFS$ mkdir ./imagemMontada/novodir
mkdir: não foi possível criar o diretório “./imagemMontada/novodir”: Permissão negada
john@MintVM:~/testesBTRFS$ ls -la ./imagemMontada/
total 16
drwxr-xr-x 1 root root 20 fev 29 10:56 .
drwxr-xr-x 1 john john 46 fev 29 10:56 ..
drwxr-xr-x 1 root root  0 fev 29 10:59 @home
drwxr-xr-x 1 root root  0 fev 29 10:59 @raiz
john@MintVM:~/testesBTRFS$ sudo chown john:john imagemMontada/.
john@MintVM:~/testesBTRFS$ ls -la ./imagemMontada/
total 16
drwxr-xr-x 1 john john 20 fev 29 10:56 .
drwxr-xr-x 1 john john 46 fev 29 10:56 ..
drwxr-xr-x 1 root root  0 fev 29 10:59 @home
drwxr-xr-x 1 root root  0 fev 29 10:59 @raiz
john@MintVM:~/testesBTRFS$ mkdir ./imagemMontada/novodir
john@MintVM:~/testesBTRFS$ cp /etc/fstab ./imagemMontada/novodir
john@MintVM:~/testesBTRFS$ # 6
john@MintVM:~/testesBTRFS$ ls -la ./imagemMontada/
total 16
drwxr-xr-x 1 john john 34 fev 29 11:04 .
drwxr-xr-x 1 john john 46 fev 29 10:56 ..
drwxr-xr-x 1 root root  0 fev 29 10:59 @home
drwxr-xr-x 1 john john  0 fev 29 11:04 novodir
drwxr-xr-x 1 root root  0 fev 29 10:59 @raiz
john@MintVM:~/testesBTRFS$ # 7
john@MintVM:~/testesBTRFS$ sudo cp /etc/profile ./imagemMontada/@raiz
john@MintVM:~/testesBTRFS$ ls -la ./imagemMontada/@raiz
total 20
drwxr-xr-x 1 root root  14 fev 29 11:16 .
drwxr-xr-x 1 john john  34 fev 29 11:04 ..
-rw-r--r-- 1 root root 581 fev 29 11:16 profile
john@MintVM:~/testesBTRFS$ # 8
john@MintVM:~/testesBTRFS$ mkdir subvolumeMontado
john@MintVM:~/testesBTRFS$ sudo mount -o loop,subvol=@raiz imagem.img ./subvolumeMontado
john@MintVM:~/testesBTRFS$ # 9
john@MintVM:~/testesBTRFS$ ls -la ./subvolumeMontado
total 8
drwxr-xr-x 1 root root  24 fev 29 11:17 .
drwxr-xr-x 1 john john  78 fev 29 11:22 ..
-rw-r--r-- 1 root root 581 fev 29 11:16 profile
john@MintVM:~/testesBTRFS$ # 10
john@MintVM:~/testesBTRFS$ sudo btrfs sub li ./imagemMontada
ID 256 gen 18 top level 5 path @raiz
ID 257 gen 10 top level 5 path @home
john@MintVM:~/testesBTRFS$ sudo btrfs subvolume set-default 257 ./imagemMontada
john@MintVM:~/testesBTRFS$ # 11
john@MintVM:~/testesBTRFS$ sudo btrfs subvolume get-default ./subvolumeMontado
ID 257 gen 10 top level 5 path @home
john@MintVM:~/testesBTRFS$ 
john@MintVM:~/testesBTRFS$ # 12
john@MintVM:~/testesBTRFS$ sudo umount ./imagemMontada
john@MintVM:~/testesBTRFS$ sudo umount ./subvolumeMontado
john@MintVM:~/testesBTRFS$ # 13
john@MintVM:~/testesBTRFS$ sudo mount -o loop imagem.img ./imagemMontada
john@MintVM:~/testesBTRFS$ ls -la ./imagemMontada
total 0
drwxr-xr-x 1 root root  0 fev 29 10:59 .
drwxr-xr-x 1 john john 78 fev 29 11:22 ..
john@MintVM:~/testesBTRFS$ # 14
john@MintVM:~/testesBTRFS$ sudo btrfs subvo lis ./imagemMontada
ID 256 gen 18 top level 5 path @raiz
ID 257 gen 10 top level 5 path @home
john@MintVM:~/testesBTRFS$ # 15
john@MintVM:~/testesBTRFS$ sudo touch ./imagemMontada/arquivo.txt
john@MintVM:~/testesBTRFS$ sudo btrfs subv creat ./imagemMontada/temp-files
Create subvolume './imagemMontada/temp-files'
john@MintVM:~/testesBTRFS$ # 16
john@MintVM:~/testesBTRFS$ ls -la ./imagemMontada
total 0
drwxr-xr-x 1 root root 42 fev 29 11:51 .
drwxr-xr-x 1 john john 78 fev 29 11:22 ..
-rw-r--r-- 1 root root  0 fev 29 11:51 arquivo.txt
drwxr-xr-x 1 root root  0 fev 29 11:51 temp-files
john@MintVM:~/testesBTRFS$ # 17
john@MintVM:~/testesBTRFS$ mkdir arvoreMontada
john@MintVM:~/testesBTRFS$ sudo mount -o loop,subvolid=5 imagem.img ./arvoreMontada
john@MintVM:~/testesBTRFS$ sudo btrfs subvol create ./arvoreMontada/@tmp
Create subvolume './arvoreMontada/@tmp'
john@MintVM:~/testesBTRFS$ sudo btrfs sub list ./arvoreMontada
ID 256 gen 18 top level 5 path @raiz
ID 257 gen 25 top level 5 path @home
ID 258 gen 24 top level 257 path @home/temp-files
ID 259 gen 26 top level 5 path @tmp
john@MintVM:~/testesBTRFS$ # 18
john@MintVM:~/testesBTRFS$ mv ./arvoreMontada/@raiz ./arvoreMontada/@rootfs
john@MintVM:~/testesBTRFS$ sudo btrfs sub list ./arvoreMontada
ID 256 gen 18 top level 5 path @rootfs
ID 257 gen 25 top level 5 path @home
ID 258 gen 24 top level 257 path @home/temp-files
ID 259 gen 26 top level 5 path @tmp
john@MintVM:~/testesBTRFS$ 
john@MintVM:~/testesBTRFS$ # 19
john@MintVM:~/testesBTRFS$ sudo mv ./arvoreMontada/@tmp ./arvoreMontada/@home
john@MintVM:~/testesBTRFS$ sudo mv ./arvoreMontada/@home/@tmp ./arvoreMontada/@home/tmp
john@MintVM:~/testesBTRFS$ sudo btrfs sub list ./arvoreMontada
ID 256 gen 28 top level 5 path @rootfs
ID 257 gen 28 top level 5 path @home
ID 258 gen 28 top level 257 path @home/temp-files
ID 259 gen 28 top level 257 path @home/tmp
john@MintVM:~/testesBTRFS$ # 20
john@MintVM:~/testesBTRFS$ sudo dd if=/dev/urandom of=./imagemMontada/arquivogrande.lixo bs=1M count=100
100+0 registros de entrada
100+0 registros de saída
104857600 bytes (105 MB, 100 MiB) copiados, 1,756 s, 59,7 MB/s
john@MintVM:~/testesBTRFS$ ls -la ./imagemMontada
total 102400
drwxr-xr-x 1 root root        62 fev 29 13:41 .
drwxr-xr-x 1 john john       104 fev 29 11:55 ..
-rw-r--r-- 1 root root 104857600 fev 29 13:41 arquivogrande.lixo
drwxr-xr-x 1 root root         0 fev 29 13:34 temp-files
drwxr-xr-x 1 root root         0 fev 29 13:34 tmp

john@MintVM:~/testesBTRFS$ # 21
john@MintVM:~/testesBTRFS$ sudo cp ./imagemMontada/arquivogrande.lixo ./imagemMontada/tmp
cp: erro de escrita de './imagemMontada/tmp/arquivogrande.lixo': Não há espaço disponível no dispositivo
john@MintVM:~/testesBTRFS$ sudo cp --reflink=always ./imagemMontada/arquivogrande.lixo ./imagemMontada/tmp
john@MintVM:~/testesBTRFS$ # 22
john@MintVM:~/testesBTRFS$ ls -laR ./imagemMontada/
./imagemMontada/:
total 204800
drwxr-xr-x 1 root root        80 fev 29 13:43 .
drwxr-xr-x 1 john john       104 fev 29 11:55 ..
-rw-r--r-- 1 root root 104857600 fev 29 13:41 arquivogrande.lixo
drwxr-xr-x 1 root root         0 fev 29 13:56 temp-files
drwxr-xr-x 1 root root        36 fev 29 13:57 tmp

./imagemMontada/temp-files:
total 0
drwxr-xr-x 1 root root  0 fev 29 13:56 .
drwxr-xr-x 1 root root 80 fev 29 13:43 ..

./imagemMontada/tmp:
total 102400
drwxr-xr-x 1 root root        36 fev 29 13:57 .
drwxr-xr-x 1 root root        80 fev 29 13:43 ..
-rw-r--r-- 1 root root 104857600 fev 29 13:58 arquivogrande.lixo
john@MintVM:~/testesBTRFS$ # 23
john@MintVM:~/testesBTRFS$ sudo btrfs filesystem usage ./imagemMontada
Overall:
    Device size:		 200.00MiB
    Device allocated:		 188.00MiB
    Device unallocated:		  12.00MiB
    Device missing:		     0.00B
    Used:			 100.59MiB
    Free (estimated):		   8.00MiB	(min: 8.00MiB)
    Data ratio:			      1.00
    Metadata ratio:		      2.00
    Global reserve:		  16.00MiB	(used: 0.00B)

Data,single: Size:108.00MiB, Used:100.00MiB
   /dev/loop0	 108.00MiB

Metadata,DUP: Size:32.00MiB, Used:288.00KiB
   /dev/loop0	  64.00MiB

System,DUP: Size:8.00MiB, Used:16.00KiB
   /dev/loop0	  16.00MiB

Unallocated:
   /dev/loop0	  12.00MiB
john@MintVM:~/testesBTRFS$ sudo btrfs filesystem du ./imagemMontada
     Total   Exclusive  Set shared  Filename
     0.00B       0.00B           -  ./imagemMontada/temp-files
 100.00MiB       0.00B           -  ./imagemMontada/tmp/arquivogrande.lixo
 100.00MiB       0.00B           -  ./imagemMontada/tmp
 100.00MiB       0.00B           -  ./imagemMontada/arquivogrande.lixo
 200.00MiB       0.00B   100.00MiB  ./imagemMontada
john@MintVM:~/testesBTRFS$ # 24
john@MintVM:~/testesBTRFS$ sudo rm ./imagemMontada/arquivogrande.lixo
john@MintVM:~/testesBTRFS$ sudo btrfs filesystem sync ./imagemMontada
john@MintVM:~/testesBTRFS$ sudo btrfs file us ./imagemMontada
Overall:
    Device size:		 200.00MiB
    Device allocated:		 188.00MiB
    Device unallocated:		  12.00MiB
    Device missing:		     0.00B
    Used:			 100.59MiB
    Free (estimated):		   8.00MiB	(min: 8.00MiB)
    Data ratio:			      1.00
    Metadata ratio:		      2.00
    Global reserve:		  16.00MiB	(used: 0.00B)

Data,single: Size:108.00MiB, Used:100.00MiB
   /dev/loop0	 108.00MiB

Metadata,DUP: Size:32.00MiB, Used:288.00KiB
   /dev/loop0	  64.00MiB

System,DUP: Size:8.00MiB, Used:16.00KiB
   /dev/loop0	  16.00MiB

Unallocated:
   /dev/loop0	  12.00MiB
john@MintVM:~/testesBTRFS$ # 25
john@MintVM:~/testesBTRFS$ sudo rm ./imagemMontada/tmp/arquivogrande.lixo
john@MintVM:~/testesBTRFS$ sudo btrfs filesystem sync ./imagemMontada
john@MintVM:~/testesBTRFS$ sudo btrfs filesystem usage ./imagemMontada
Overall:
    Device size:		 200.00MiB
    Device allocated:		  92.00MiB
    Device unallocated:		 108.00MiB
    Device missing:		     0.00B
    Used:			 384.00KiB
    Free (estimated):		 120.00MiB	(min: 66.00MiB)
    Data ratio:			      1.00
    Metadata ratio:		      2.00
    Global reserve:		  16.00MiB	(used: 32.00KiB)

Data,single: Size:12.00MiB, Used:0.00B
   /dev/loop0	  12.00MiB

Metadata,DUP: Size:32.00MiB, Used:176.00KiB
   /dev/loop0	  64.00MiB

System,DUP: Size:8.00MiB, Used:16.00KiB
   /dev/loop0	  16.00MiB

Unallocated:
   /dev/loop0	 108.00MiB
john@MintVM:~/testesBTRFS$ 
10 curtidas