Por que minha partição de exatamente 100 MiB com tamanho de bloco de 1 KiB não possui os blocos / espaço disponíveis correspondentes?

33

Eu tenho um ambiente virtualizado de densidade muito alta com contêineres, então estou tentando tornar cada contêiner muito pequeno. "Muito pequeno" significa 87 MB no Ubuntu base 14.04 (Trusty Tahr) sem quebrar a compatibilidade do gerenciador de pacotes.

Então, eu uso o LVM como armazenamento de apoio para meus contêineres e recentemente encontrei números muito estranhos. Aqui estão eles.

Vamos criar um volume lógico de 100 MiB (sim, potência de 2).

sudo lvcreate -L100M -n test1 /dev/purgatory

Gostaria de verificar o tamanho, então emito sudo lvs --units k

test1             purgatory  -wi-a----  102400.00k

Doce, isso é realmente 100 MiB.

Agora vamos criar um sistema de arquivos ext4 . E, claro, lembramos do -m 0parâmetro, que evita o desperdício de espaço.

sudo mkfs.ext4 -m 0 /dev/purgatory/test1

mke2fs 1.42.9 (4-Feb-2014)
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
Stride=0 blocks, Stripe width=0 blocks
25688 inodes, 102400 blocks
0 blocks (0.00%) reserved for the super user
First data block=1
Maximum filesystem blocks=67371008
13 block groups
8192 blocks per group, 8192 fragments per group
1976 inodes per group
Superblock backups stored on blocks:
        8193, 24577, 40961, 57345, 73729

Allocating group tables: done
Writing inode tables: done
Creating journal (4096 blocks): done
Writing superblocks and filesystem accounting information: done

Doce e limpo. Observe o tamanho do bloco - nosso volume lógico é pequeno, então o mkfs.ext4 decidiu criar um bloco do tamanho de 1 KiB, não o habitual de 4 KiB.

Agora vamos montá-lo.

sudo mount /dev/purgatory/test1 /mnt/test1

E vamos chamar dfsem parâmetros (gostaríamos de ver 1 bloco KiB)

/dev/mapper/purgatory-test1     95054    1550     91456   2% /mnt/test1

Espere, oh shi ~

Temos 95054 blocos no total. Mas o próprio dispositivo possui 102400 blocos de 1 KiB. Temos apenas 92,8% de nosso armazenamento. Onde estão meus blocos, cara?

Vamos dar uma olhada em um dispositivo de bloco real. A possui um disco virtual de 16 GiB, 16777216 blocos de 1 K, mas apenas 15396784 estão na saída df. 91,7%, o que é isso?

Agora segue a investigação (spoiler: sem resultados)

  1. O sistema de arquivos pode começar não no início do dispositivo. Isso é estranho, mas possível. Felizmente, o ext4 tem bytes mágicos, vamos verificar a presença deles.

    sudo hexdump -C / dev / purgatory / test1 | grep "53 ef"

Isso mostra o superbloco:

00000430  a9 10 e7 54 01 00 ff ff  53 ef 01 00 01 00 00 00  |...T....S.......|

Hex 430 = 1072 de dezembro, então em algum lugar após o primeiro kilobyte. Parece razoável, o ext4 ignora os primeiros 1024 bytes por esquisitices como o VBR, etc.

  1. Este é o diário!

Não não é. O diário ocupa espaço em Disponível se saída df.

  1. Ah, nós temos o dump2fs e pudemos verificar os tamanhos lá!

... muitos cumprimentos ...

sudo dumpe2fs /dev/purgatory/test1 | grep "Free blocks"

Ai.

Free blocks:              93504
  Free blocks: 3510-8192
  Free blocks: 8451-16384
  Free blocks: 16385-24576
  Free blocks: 24835-32768
  Free blocks: 32769-40960
  Free blocks: 41219-49152
  Free blocks: 53249-57344
  Free blocks: 57603-65536
  Free blocks: 65537-73728
  Free blocks: 73987-81920
  Free blocks: 81921-90112
  Free blocks: 90113-98304
  Free blocks: 98305-102399

E nós temos outro número. 93504 blocos livres.

A questão é: o que está acontecendo?

  • Dispositivo de bloco: 102400k (diz o lvs)
  • Tamanho do sistema de arquivos: 95054k (diz df)
  • Blocos gratuitos: 93504k (diz dumpe2fs)
  • Tamanho disponível: 91456k (df diz)
maniaque
fonte
É por isso que eu ainda uso ext2para partições pequenas.
21915 frostschutz
@frostschutz ext2aparência razoáveis aqui, com certeza
maniaque

Respostas:

32

Tente o seguinte: mkfs.ext4 -N 104 -m0 -O ^has_journal,^resize_inode /dev/purgatory/test1

Eu acho que isso permite que você entenda "o que está acontecendo".

-N 104 (defina o número de iNodes que seu sistema de arquivos deve ter)

  • todo iNode "custa" espaço utilizável (128 bytes)

-m 0(sem blocos reservados)
-O ^has_journal,^resize_inode(desative os recursos has_journaleresize_inode

  • resize_inode"custos" de espaço livre (a maioria dos 1550 1K-Blocks / 2% que você vê no seu df- 12K são usados ​​para a pasta "perdidos + achados")
  • has_journal"custos" de espaço útil (4096 blocos de 1K no seu caso)

Saímos 102348de 102400outros 52 blocos inutilizáveis ​​(se tivermos excluído a pasta "perdido + encontrado"). Portanto, mergulhamos em dumpe2fs:

Group 0: (Blocks 1-8192) [ITABLE_ZEROED]
  Checksum 0x5ee2, unused inodes 65533
  Primary superblock at 1, Group descriptors at 2-2
  Block bitmap at 3 (+2), Inode bitmap at 19 (+18)
  Inode table at 35-35 (+34)
  8150 free blocks, 0 free inodes, 1 directories, 65533 unused inodes
  Free blocks: 17-18, 32-34, 48-8192
  Free inodes: 
Group 1: (Blocks 8193-16384) [BLOCK_UNINIT, ITABLE_ZEROED]
  Checksum 0x56cf, unused inodes 5
  Backup superblock at 8193, Group descriptors at 8194-8194
  Block bitmap at 4 (+4294959107), Inode bitmap at 20 (+4294959123)
  Inode table at 36-36 (+4294959139)
  8190 free blocks, 6 free inodes, 0 directories, 5 unused inodes
  Free blocks: 8193-16384
  Free inodes: 11-16
Group 2: (Blocks 16385-24576) [INODE_UNINIT, BLOCK_UNINIT, ITABLE_ZEROED]
  Checksum 0x51eb, unused inodes 8
  Block bitmap at 5 (+4294950916), Inode bitmap at 21 (+4294950932)
  Inode table at 37-37 (+4294950948)
  8192 free blocks, 8 free inodes, 0 directories, 8 unused inodes
  Free blocks: 16385-24576
  Free inodes: 17-24
Group 3: (Blocks 24577-32768) [INODE_UNINIT, BLOCK_UNINIT, ITABLE_ZEROED]
  Checksum 0x3de1, unused inodes 8
  Backup superblock at 24577, Group descriptors at 24578-24578
  Block bitmap at 6 (+4294942725), Inode bitmap at 22 (+4294942741)
  Inode table at 38-38 (+4294942757)
  8190 free blocks, 8 free inodes, 0 directories, 8 unused inodes
  Free blocks: 24577-32768
  Free inodes: 25-32
Group 4: (Blocks 32769-40960) [INODE_UNINIT, BLOCK_UNINIT, ITABLE_ZEROED]
  Checksum 0x79b9, unused inodes 8
  Block bitmap at 7 (+4294934534), Inode bitmap at 23 (+4294934550)
  Inode table at 39-39 (+4294934566)
  8192 free blocks, 8 free inodes, 0 directories, 8 unused inodes
  Free blocks: 32769-40960
  Free inodes: 33-40
Group 5: (Blocks 40961-49152) [INODE_UNINIT, BLOCK_UNINIT, ITABLE_ZEROED]
  Checksum 0x0059, unused inodes 8
  Backup superblock at 40961, Group descriptors at 40962-40962
  Block bitmap at 8 (+4294926343), Inode bitmap at 24 (+4294926359)
  Inode table at 40-40 (+4294926375)
  8190 free blocks, 8 free inodes, 0 directories, 8 unused inodes
  Free blocks: 40961-49152
  Free inodes: 41-48
Group 6: (Blocks 49153-57344) [INODE_UNINIT, BLOCK_UNINIT, ITABLE_ZEROED]
  Checksum 0x3000, unused inodes 8
  Block bitmap at 9 (+4294918152), Inode bitmap at 25 (+4294918168)
  Inode table at 41-41 (+4294918184)
  8192 free blocks, 8 free inodes, 0 directories, 8 unused inodes
  Free blocks: 49153-57344
  Free inodes: 49-56
Group 7: (Blocks 57345-65536) [INODE_UNINIT, BLOCK_UNINIT, ITABLE_ZEROED]
  Checksum 0x5c0a, unused inodes 8
  Backup superblock at 57345, Group descriptors at 57346-57346
  Block bitmap at 10 (+4294909961), Inode bitmap at 26 (+4294909977)
  Inode table at 42-42 (+4294909993)
  8190 free blocks, 8 free inodes, 0 directories, 8 unused inodes
  Free blocks: 57345-65536
  Free inodes: 57-64
Group 8: (Blocks 65537-73728) [INODE_UNINIT, BLOCK_UNINIT, ITABLE_ZEROED]
  Checksum 0xf050, unused inodes 8
  Block bitmap at 11 (+4294901770), Inode bitmap at 27 (+4294901786)
  Inode table at 43-43 (+4294901802)
  8192 free blocks, 8 free inodes, 0 directories, 8 unused inodes
  Free blocks: 65537-73728
  Free inodes: 65-72
Group 9: (Blocks 73729-81920) [INODE_UNINIT, BLOCK_UNINIT, ITABLE_ZEROED]
  Checksum 0x50fd, unused inodes 8
  Backup superblock at 73729, Group descriptors at 73730-73730
  Block bitmap at 12 (+4294893579), Inode bitmap at 28 (+4294893595)
  Inode table at 44-44 (+4294893611)
  8190 free blocks, 8 free inodes, 0 directories, 8 unused inodes
  Free blocks: 73729-81920
  Free inodes: 73-80
Group 10: (Blocks 81921-90112) [INODE_UNINIT, BLOCK_UNINIT, ITABLE_ZEROED]
  Checksum 0x60a4, unused inodes 8
  Block bitmap at 13 (+4294885388), Inode bitmap at 29 (+4294885404)
  Inode table at 45-45 (+4294885420)
  8192 free blocks, 8 free inodes, 0 directories, 8 unused inodes
  Free blocks: 81921-90112
  Free inodes: 81-88
Group 11: (Blocks 90113-98304) [INODE_UNINIT, BLOCK_UNINIT, ITABLE_ZEROED]
  Checksum 0x28de, unused inodes 8
  Block bitmap at 14 (+4294877197), Inode bitmap at 30 (+4294877213)
  Inode table at 46-46 (+4294877229)
  8192 free blocks, 8 free inodes, 0 directories, 8 unused inodes
  Free blocks: 90113-98304
  Free inodes: 89-96
Group 12: (Blocks 98305-102399) [INODE_UNINIT, ITABLE_ZEROED]
  Checksum 0x9223, unused inodes 8
  Block bitmap at 15 (+4294869006), Inode bitmap at 31 (+4294869022)
  Inode table at 47-47 (+4294869038)
  4095 free blocks, 8 free inodes, 0 directories, 8 unused inodes
  Free blocks: 98305-102399
  Free inodes: 97-104

e conte os blocos usados ​​(para superbloco de backup, descritores de grupo, bitmap de bloco, bitmap de Inode e tabela Inode) ou we grepe count:

LANG=C dumpe2fs /dev/mapper/vg_vms-test1 | grep ' at ' | grep -v ',' | wc -l

o que nos dá a contagem de linhas que possuem um único bloco (no nosso exemplo) e

LANG=C dumpe2fs /dev/mapper/vg_vms-test1 | grep ' at ' | grep ',' | wc -l

o que nos dá a contagem de linhas que têm dois blocos (no nosso exemplo).

Portanto, temos (em nosso exemplo) 13linhas com um bloco cada e 19linhas com dois blocos cada.

13+19*2

o que nos dá 51blocos que são usados ​​pelo próprio ext4. Finalmente, resta apenas um quarteirão. O bloco 0, que são os 1024bytes ignorados no início para coisas como o setor de inicialização.

xx4h
fonte
E se o diário levar apenas 4096k, não tenho esse número (95054 - 4096)! = 91456?
maniaque
Todos os números aqui estão em k, então 95054k total - 4096k de diário! = 91456k disponível.
maniaque
1
dfno fs com diário: 95054k - dfno fs sem jorunal 99150k - e não misture espaço "utilizável" e "livre".
xx4h
Alguns sistemas de arquivos, por exemplo, xfs, alocam dinamicamente espaço para inodes, conforme necessário. Você pode tentar xfs e btrfs, se estiver curioso. mkfs.xfs -l size=512 -d agcount=1criará um sistema de arquivos com o tamanho mínimo absoluto de log (também conhecido como diário), mas o desempenho da gravação pode sofrer. Eu não acho que o código XFS suporte a operar sem um log. Possivelmente somente leitura, para suportar casos em que um dispositivo de log externo está quebrado. (também, agcount=1é provavelmente uma outra idéia terrível para o desempenho de gravação, esp paralelo e cabeçalhos de grupo de alocação são provavelmente pequenos, também...)
Peter Cordes
Fiquei curioso e tentei o XFS. Se houver uma combinação de opções para o Linux XFS que permitirá que o tamanho mínimo do log desça para o mínimo absoluto de 512 blocos, faça o IDK. mkfs.xfs -d agcount=1em uma partição de 100MiB, um FS de 95980kiB foi usado, com 5196k usados ​​e 90784k disponíveis. A conta padrão é 4 e o tamanho padrão do log é 1605 blocos (também o mínimo). Portanto, o XFS usa um log tão pequeno quanto deseja permitir que você especifique, para FSes pequenos.
Peter Cordes
19

A resposta curta:

Nem todo o espaço no dispositivo de bloco se torna espaço disponível para seus dados: parte do espaço bruto é necessária para o sistema interno de arquivos, a contabilidade dos bastidores.

Essa contabilidade inclui o super bloco, os descritores do grupo de blocos, os bitmaps de bloco e inode e a tabela de inode. Além disso, cópias do super bloco para fins de backup / recuperação são criadas em vários locais. Uma longa leitura sobre os aspectos internos do sistema de arquivos EXT4 pode ser encontrada em ext4.wiki.kernel.org .

Como o EXT4 é um sistema de arquivos com diário, também ocupa algum espaço.

Além disso, algum espaço é reservado para futuras expansões do sistema de arquivos.

A resposta longa:

Recriei seu cenário em um dos meus sistemas de teste:

lvcreate -L 100M -n test MyVG
mkfs.ext4 -b 1024 /dev/MyVG/test 

Antes mesmo de montar o sistema de arquivos, a dumpe2fsmostra:

Filesystem state:         clean
Errors behavior:          Continue
Filesystem OS type:       Linux
Inode count:              25688
Block count:              102400
Reserved block count:     5120
Free blocks:              93504
Free inodes:              25677
First block:              1
Block size:               1024
Fragment size:            1024
Reserved GDT blocks:      256
Blocks per group:         8192
Fragments per group:      8192
Inodes per group:         1976
Inode blocks per group:   247
Flex block group size:    16
Filesystem created:       Fri Feb 20 13:20:54 2015
Last mount time:          n/a
Last write time:          Fri Feb 20 13:20:55 2015
...
Journal size:             4096k  
...

e após a montagem:

df /tmp/test/
Filesystem              1K-blocks  Used Available Use% Mounted on
/dev/mapper/MyVG-test       99150  5646     88384   7% /tmp/test

Então, o que dfnos mostra? Dos 102400 blocos da capacidade do dispositivo de armazenamento bruto, 99150 blocos de 1K são visíveis para o sistema de arquivos, o que significa que 3250 blocos de 1 kilobyte de espaço de armazenamento bruto tornaram-se inutilizáveis ​​para o armazenamento de dados real.

Para onde foram esses blocos? Rolar para baixo na dumpe2fssaída mostra exatamente onde:

Group 0: (Blocks 1-8192) [ITABLE_ZEROED]
  Checksum 0x0d67, unused inodes 1965
  Primary superblock at 1, Group descriptors at 2-2
  Reserved GDT blocks at 3-258
  Block bitmap at 259 (+258), Inode bitmap at 275 (+274)
  Inode table at 291-537 (+290)
  4683 free blocks, 1965 free inodes, 2 directories, 1965 unused inodes
  Free blocks: 3510-8192
  Free inodes: 12-1976

1 block (bloco 0) Os primeiros 1024 bytes são ignorados para permitir a instalação de setores de inicialização x86 e outras curiosidades.
1 block é ocupado pelo super bloco Primário.
1 block contém os descritores do grupo.
256 blockssão reservados para a tabela de descritores de grupo para permitir redimensionamento futuro do sistema de arquivos. 16 blocks são atribuídos ao bitmap do bloco.
16 blockssão designados para o bitmap do inode.
246 blockssão designados para a tabela de inodes.

Isso já responde por 537 dos 3250 blocos ausentes. Um sistema de arquivos ext4 é dividido em uma série de grupos de blocos e a rolagem para baixo mostra ainda uma alocação semelhante da capacidade de armazenamento bruto aos internos do sistema de arquivos nos outros grupos de blocos:

Group 1: (Blocks 8193-16384) [INODE_UNINIT, ITABLE_ZEROED]
  Checksum 0x0618, unused inodes 1976
  Backup superblock at 8193, Group descriptors at 8194-8194
  Reserved GDT blocks at 8195-8450
  Block bitmap at 260 (+4294959363), Inode bitmap at 276 (+4294959379)
  Inode table at 538-784 (+4294959641)
  7934 free blocks, 1976 free inodes, 0 directories, 1976 unused inodes
  Free blocks: 8451-16384
  Free inodes: 1977-3952
Group 2: (Blocks 16385-24576) [INODE_UNINIT, BLOCK_UNINIT, ITABLE_ZEROED]
  Checksum 0xcfd3, unused inodes 1976
  Block bitmap at 261 (+4294951172), Inode bitmap at 277 (+4294951188)
  Inode table at 785-1031 (+4294951696)
  8192 free blocks, 1976 free inodes, 0 directories, 1976 unused inodes
  Free blocks: 16385-24576
  Free inodes: 3953-5928 
Group ....

Agora, de volta à dfsaída:

df /tmp/test/
Filesystem              1K-blocks  Used Available Use% Mounted on
/dev/mapper/MyVG-test       99150  5646     88384   7% /tmp/test

A razão pela qual nesse sistema de arquivos novo já 7% da capacidade é marcada como em uso é:

99150 (o tamanho do sistema de arquivos) menos 5120 (a contagem de blocos reservada) menos 5646 (blocos usados, 4096 dos quais são do diário (novamente parte da saída do dumpe2fs`))
= 88384

A contagem de blocos livres no dumpe2fs é o tamanho disponível do sistema de arquivos menos o uso real (e não leva em consideração os blocos reservados), portanto 99150 - 5646 = 93504.

HBruijn
fonte
0

Não é uma resposta para a pergunta, mas fiquei curioso, então imagino que outras pessoas o farão. Como eu já tinha um liveCD inicializado e tinha um disco rígido com o qual eu poderia mexer sem me preocupar com erros de digitação que danificassem qualquer coisa, fui em frente e testei.

Fiz partições com todos os FSes para os quais o Ubuntu 14.10 envia um mkfs, em partições 100MiB. (exceto o minix, que suporta apenas 64MiB, e o bfs, que é uma coisa de SCO da qual nunca ouvi falar.)

Primeiro, examinei o df -kespaço disponível (com as configurações padrão do mkfs) e depois ddeditei /dev/zeroum arquivo em cada FS para garantir que eles pudessem ser preenchidos até o fim. (ou seja, verifique se a reivindicação available spaceestava realmente disponível.)
for i in /media/ubuntu/small-*;do sudo dd if=/dev/zero of="$i/fill" bs=16k;done

* FS: empty `df -k` : non-zero `df -k` when full (false bottom)
* jfs:  101020k
* fat32:100808k  : 4
* ntfs:  99896k
* btrfs: 98276k  : 4428
* ext2:  92480k
* xfs:   90652k  : 20
* ext4:  86336k
* ext3:  88367k
* reiserfs(v3): 69552k

Por que o btrfs tem tanto espaço inutilizável? Talvez para metadados? bem não:

$ for i in /media/ubuntu/small-*;do sudo touch "$i/touched";done
touch: cannot touch ‘/media/ubuntu/small-btrfs/touched’: No space left on device
touch: cannot touch ‘/media/ubuntu/small-reiser/touched’: No space left on device

Ambos os sistemas de arquivos baseados em árvore não podem compactar um arquivo vazio em nenhum lugar, mas todos os outros podem.

Ou apenas veja o tamanho de um arquivo que você pode criar:

$ ls -SdlG --block-size=1k /media/ubuntu/small-*/*
-rw-r--r-- 1 root   101020 Feb 21 11:55 /media/ubuntu/small-jfs/fill
-rw-r--r-- 1 ubuntu 100804 Feb 21 11:55 /media/ubuntu/small-fat/fill
-rw------- 1 ubuntu  99848 Feb 21 11:55 /media/ubuntu/small-ntfs/fill
-rw-r--r-- 1 root    97216 Feb 21 11:55 /media/ubuntu/small-ext2/fill
-rw-r--r-- 1 root    93705 Feb 21 11:27 /media/ubuntu/small-btrfs/foo
-rw-r--r-- 1 root    93120 Feb 21 11:55 /media/ubuntu/small-ext3/fill
-rw-r--r-- 1 root    91440 Feb 21 11:55 /media/ubuntu/small-ext/fill
-rw-r--r-- 1 root    90632 Feb 21 11:55 /media/ubuntu/small-xfs/fill
-rw-r--r-- 1 root    69480 Feb 21 11:55 /media/ubuntu/small-reiser/fill
drwx------ 2 root       12 Feb 21 11:33 /media/ubuntu/small-ext2/lost+found
drwx------ 2 root       12 Feb 21 11:43 /media/ubuntu/small-ext3/lost+found
drwx------ 2 root       12 Feb 21 11:29 /media/ubuntu/small-ext/lost+found

(Chamei minha partição ext4 de "small-ext" porque não estava planejando enlouquecer e criar todos os sistemas de arquivos. Então ext = ext4 aqui. NÃO o original pré-ext2 ext.)

E df -ksaída após removê-los novamente:

/dev/sdd6          95980    5328     90652   6% /media/ubuntu/small-xfs
/dev/sdd7          95054    1550     86336   2% /media/ubuntu/small-ext
/dev/sdd5         102400   93880    101020  96% /media/ubuntu/small-btrfs
/dev/sdd8         101168  101168         0 100% /media/ubuntu/small-jfs
/dev/sdd9          99150    1550     92480   2% /media/ubuntu/small-ext2
/dev/sdd10        102392   32840     69552  33% /media/ubuntu/small-reiser
/dev/sdd11        100808       1    100808   1% /media/ubuntu/small-fat
/dev/sdd12        102396    2548     99848   3% /media/ubuntu/small-ntfs
/dev/sdd13         95054    1567     88367   2% /media/ubuntu/small-ext3

(O jfs voltou a 1% usado depois que eu removi o "toque" também. Houve um atraso ou demorou outra gravação para obter o tamanho disponível para atualização.)

Enfim, acho que é isso por curiosidade.

Peter Cordes
fonte