Como descobrir se um arquivo no btrfs é copy-on-write?

6

Eu sei que cp tem uma opção --reflink para controlar cópias completas versus cópias "copy-on-write".

Em btrfs, posso usar ls (ou algum outro comando) para descobrir se um arquivo compartilha (em uma cópia-em-gravação detecta) algum armazenamento com outro arquivo?

EDIT: @ StéphaneChazelas me aponta para filefrag , mas isso falha para mim:

root@void:/tmp/mount# mount | tail -1
/tmp/back on /tmp/mount type btrfs (rw,relatime,space_cache)
root@void:/tmp/mount# df -h | tail -1
/dev/loop0       32M   13M   20M  38% /tmp/mount
root@void:/tmp/mount# ls -lh
total 8.0M
-rw-r--r-- 1 root root 8.0M Jan 19 08:43 one
root@void:/tmp/mount# cp --reflink=always one two
root@void:/tmp/mount# sync
root@void:/tmp/mount# ls -lh
total 16M
-rw-r--r-- 1 root root 8.0M Jan 19 08:43 one
-rw-r--r-- 1 root root 8.0M Jan 19 08:45 two
root@void:/tmp/mount# df -h | tail -1
/dev/loop0       32M   13M   20M  38% /tmp/mount
root@void:/tmp/mount# filefrag -kvx one 
Filesystem type is: 9123683e
File size of one is 8388608 (8192 blocks of 1024 bytes)
FIEMAP failed with unknown flags 2
one: FIBMAP unsupported
root@void:/tmp/mount# uname -a
Linux void 4.1.7+ #817 PREEMPT Sat Sep 19 15:25:36 BST 2015 armv6l GNU/Linux
    
por not-a-user 18.01.2016 / 15:32

2 respostas

5

Eu não sei como encontrá-lo através do comando ls . Mas se você realmente quiser, você pode usar o btrfs-progs / btrfs-debug-tree .

Com reflink = sempre , os arquivos compartilharão um bloco de dados comum. Este bloco de dados comum (também conhecido como extents) tem mais de 1.

  1. Primeiro você precisa encontrar o objeto para os arquivos um e dois

    #./btrfs-debug-tree  /dev/xvdc
    (Check under FS_TREE)
      <snip>
        item 8 key (256 DIR_INDEX 4) itemoff 15842 itemsize 33
            location key (259 INODE_ITEM 0) type FILE
            namelen 3 datalen 0 name: one
        item 9 key (256 DIR_INDEX 5) itemoff 15809 itemsize 33
            location key (260 INODE_ITEM 0) type FILE
            namelen 3 datalen 0 name: two
      </snip>
    

De cima podemos ver o seu 259 (um) e 260 (dois) .

  1. Agora encontre seus refs. da árvore de extensão. Abaixo, o comando encontrará o bloco de dados compartilhado entre dois arquivos.

    # ./btrfs-debug-tree  /dev/xvdc | grep -A2 "refs 2"
            extent refs 2 gen 9 flags DATA
            extent data backref root 5 objectid 260 offset 0 count 1
            extent data backref root 5 objectid 259 offset 0 count 1
    

Bônus: crie outra referência:

# cp --reflink=always one three

verifique se a referência é incrementada em 1.

# ./btrfs-debug-tree   /dev/xvdc | grep -A3 "refs 3"
        extent refs 3 gen 9 flags DATA
        extent data backref root 5 objectid 260 offset 0 count 1
        extent data backref root 5 objectid 261 offset 0 count 1
        extent data backref root 5 objectid 259 offset 0 count 1

Aqui, o bloco de dados é compartilhado entre três arquivos apontados pelo objectid 259,260,261 .

    
por 25.01.2016 / 11:08
0

Acabei de lançar um programa chamado fienode (← link) que calcula um hash SHA1 das extensões físicas de um Arquivo. Cópias idênticas do CoW têm o mesmo hash.

Há também uma resposta mais detalhada aqui, explicando por que isso é necessário.

Note, no entanto, que o BTRFS tem a liberdade de alterar as extensões físicas. Eu observei que um grande arquivo com link refletido muda suas extensões físicas sem provocação, tornando a saída fienode diferente, mesmo que a maioria das extensões físicas ainda sejam compartilhadas.

    
por 17.04.2016 / 10:24