Noções básicas sobre arquivos esparsos, dd, busca, estrutura de blocos inode

6

No trabalho, usamos arquivos esparsos como parte do ambiente do Oracle VM para as imagens de disco do convidado. Depois de algumas perguntas de um colega (que já foram respondidas) fiquei com mais perguntas sobre arquivos esparsos e talvez mais amplamente sobre a estrutura do inode - lendo as páginas man do stat (2) e statfs (2) (no FreeBSD) I tenho a impressão de que eu entenderia mais prontamente se eu soubesse mais C, mas, infelizmente, meu conhecimento de C é mínimo na melhor das hipóteses ...

Eu entendo que parte disso depende do tipo de sistema de arquivos. Eu estou principalmente interessado em UFS no FreeBSD / Solaris e ext4 - ZFS seria um plus, mas eu não vou segurar a esperança :)
Estou usando regularmente o Solaris 10, o FreeBSD 10.3 e o CentOS 6.7. Os comandos aqui estão sendo executados em uma máquina virtual CentOS 6.7, mas foram cruzados com o FreeBSD. Se possível, estou interessado em obter um entendimento de um ponto de vista POSIX e favorecer o FreeBSD sobre o Linux, se isso não for possível.

Considere o seguinte conjunto de comandos:

printf "BIL" > /tmp/BIL

dd of=/tmp/sparse bs=1 count=0 seek=10
dd if=/tmp/BIL of=/tmp/sparse bs=1 count=3 seek=10

dd if=/tmp/BIL of=/tmp/sparse bs=1 count=3 seek=17

dd of=/tmp/sparse bs=1 count=0 seek=30
dd if=/tmp/BIL of=/tmp/sparse bs=1 count=3 seek=30

O arquivo /tmp/BIL deve ter o conteúdo (em hexadecimal) de 4942 004c , portanto, quando eu hexdump do arquivo /tmp/sparse , eu devo ver um punhado dessa combinação:

%>hexdump sparse
0000000 0000 4942 004c 0000 0000 4942 004c 0000
0000010 4200 4c49 0000 0000 0000 0000 0000 4942
0000020 004c
0000021

%>cat sparse
BILBILBILBIL%

1. Por que a segunda ocorrência de "BIL" aparece fora de ordem? , ou seja, 4200 4c49 em vez de 4942 004c ? Isso foi escrito pelo terceiro comando dd .

2. Como cat e outras ferramentas sabem imprimir na ordem correta?

Usando ls , podemos ver o espaço supostamente usado e os blocos alocados:

%>ls -ls /tmp/sparse
8.0K -rw-r--r--. 1 bil bil 33 May 26 14:17 /tmp/sparse

Podemos ver que o tamanho alegado é de 33 bytes, mas o tamanho alocado é de 8 kilobytes (o tamanho do bloco do sistema de arquivos é 4K).

3. Como programas como ls discernem entre o tamanho "alegado" e o tamanho alocado?

Gostaria de saber se a figura "alegada" armazenada no inode enquanto o tamanho alocado foi calculado andando nos blocos direto e indireto - embora isso não possa ser correto, pois o cálculo via caminhada levaria tempo e ferramentas como ls retornariam rapidamente , mesmo para arquivos muito grandes.

4. Quais ferramentas posso usar para interrogar inode information?

Eu sei de stat , mas não parece imprimir os valores de todos os campos em um inode ...

5. Existe uma ferramenta onde eu possa andar nos blocos diretos e indiretos?

Seria interessante ver cada endereço no disco e o conteúdo para entender um pouco mais como os dados são armazenados

Se eu executar o seguinte comando após os outros acima, o arquivo /tmp/sparse será truncado:

%>dd of=/tmp/sparse bs=1 count=0 seek=5
%>hexdump sparse
0000000 0000 4942 004c
0000005

6. Por que dd trunca meu arquivo e pode dd ou outra ferramenta gravar no meio de um arquivo?

Por fim, arquivos esparsos parecem ser uma boa idéia para pré-alocar espaço, mas parece não haver garantia de nível de sistema de arquivos ou sistema operacional de que o comando a não truncará ou aumentará arbitrariamente o arquivo.

7. Existem mecanismos para evitar que arquivos esparsos sejam reduzidos / aumentados? E se não, por que arquivos esparsos são úteis?

Embora cada questão acima possa possivelmente ser uma pergunta SO separada, não posso dissecá-las, pois todas estão relacionadas ao entendimento subjacente.

    
por forquare 26.05.2016 / 16:41

2 respostas

8

Algumas respostas rápidas: primeiro, você não criou um arquivo esparso. Tente estes comandos extras

dd if=/tmp/BIL of=/tmp/sparse seek=1000
ls -ls /tmp/sparse

Você verá que o tamanho é 512003 bytes, mas leva apenas 8 blocos. Os bytes nulos devem ocupar um bloco inteiro e estar em um limite de bloco para que eles sejam possivelmente esparsos no sistema de arquivos.

  1. Por que a segunda ocorrência de "BIL" aparece fora de ordem?

    porque você está em um sistema little-endian e está escrevendo saída em shorts. Use bytes, como o gato faz.

  2. Como o gato e outras ferramentas sabem imprimir na ordem correta?

    eles trabalham em bytes.

  3. Como programas como ls discernem entre o tamanho "alegado" e o tamanho alocado?

    ls e assim por diante usam a chamada de sistema stat(2) que retorna 2 valores:

    st_size;             /* total size, in bytes */ 
    blkcnt_t  st_blocks; /* number of 512B blocks allocated */
    
  4. Quais ferramentas posso usar para interrogar inode information?

    stat é bom.

  5. Existe uma ferramenta onde eu possa andar nos blocos diretos e indiretos?

    No ext2 / 3/4 você pode usar hdparm --fibmap com o nome do arquivo:

    $ sudo hdparm --fibmap ~/sparse 
    filesystem blocksize 4096, begins at LBA 25167872; assuming 512 byte sectors.
    byte_offset  begin_LBA    end_LBA    sectors
         512000  226080744  226080751          8
    

    Você também pode usar debugfs :

    $ sudo debugfs /dev/sda3
    debugfs:  stat <1040667>
    Inode: 1040667   Type: regular    Mode:  0644   Flags: 0x0
    Generation: 1161905167    Version: 0x00000000
    User:   127   Group:   500   Size: 335360
    File ACL: 0    Directory ACL: 0
    Links: 1   Blockcount: 664
    Fragment:  Address: 0    Number: 0    Size: 0
    ctime: 0x4dd61e6c -- Fri May 20 09:55:24 2011
    atime: 0x4dd61e29 -- Fri May 20 09:54:17 2011
    mtime: 0x4dd61e6c -- Fri May 20 09:55:24 2011
    Size of extra inode fields: 4
    BLOCKS:
    (0-11):4182714-4182725, (IND):4182726, (12-81):4182727-4182796
    TOTAL: 83
    
  6. Por que o dd trunca meu arquivo e o dd ou outra ferramenta pode gravar no meio de um arquivo?

    Sim, dd pode escrever no meio. Adicione conv=notrunc .

  7. Existem mecanismos para evitar que arquivos esparsos sejam reduzidos / aumentados? E se não, por que os arquivos esparsos são úteis?

    Não. Porque eles ocupam menos espaço.

O aspecto esparso de um arquivo deve ser totalmente transparente para um programa, o que às vezes significa que a dispersão pode ser perdida quando o programa atualiza um arquivo.

Alguns utilitários de cópia têm opções para preservar a dispersão, por exemplo, tar --sparse , rsync --sparse .

Note que você pode converter explicitamente os blocos zero alinhados adequadamente em um arquivo em esparsidade usando cp --sparse=always e o inverso, convertendo o espaço esparso em zeros reais, com cp --sparse=never .

    
por 26.05.2016 / 17:21
2

Uma ferramenta melhor para descartar o layout do arquivo no Linux é o utilitário filefrag incluído no pacote e2fsprogs . Isso despejará todas as extensões em um arquivo de maneira eficiente e compacta:

$ dd of=/var/tmp/sparse if=/dev/zero count=1
$ dd of=/var/tmp/sparse if=/dev/zero seek=1000 count=1
$ filefrag -v /var/tmp/sparse
Filesystem type is: ef53
File size of /var/tmp/sparse is 512512 (126 blocks of 4096 bytes)
ext:     logical_offset:        physical_offset: length:   expected: flags:
  0:        0..       0:    3441408..   3441408:      1: 
  1:      125..     125:    3441533..   3441533:      1:    3441409: last,eof
/var/tmp/sparse: 2 extents found

O FIEMAP ioctl está disponível para os sistemas de arquivos Linux mais comuns (ext4, XFS, Btrfs, etc), mas ainda não para o ZFS (embora isso esteja em desenvolvimento).

    
por 23.01.2018 / 23:01