Por que o nível de fragmentação é tão grande em arquivos que contêm outros sistemas de arquivos?

8

Acabei de descobrir quais arquivos esparsos e queria realizar alguns experimentos neles. Na wiki você pode ler que os arquivos podem ficar fragmentados facilmente. Eu queria checar o quanto isso é ruim. Eu criei um arquivo da seguinte maneira:

# truncate -s 10G sparse-file
# mkfs.ext4 -m 0 -L sparse ./sparse-file

Montei o arquivo esparso e coloquei um arquivo 600M nele. O nível de fragmentação é assim:

# filefrag -v "/media/Grafi/sparse-file"
Filesystem type is: ef53
File size of /media/Grafi/sparse-file is 10737418240 (2621440 blocks of 4096 bytes)
 ext:     logical_offset:        physical_offset: length:   expected: flags:
   0:        0..    1032:      36864..     37896:   1033:
   1:     1043..    1043:      37907..     37907:      1:
   2:     1059..    1059:      37923..     37923:      1:
   3:     9251..    9256:      46115..     46120:      6:
   4:    32768..   32770:      51200..     51202:      3:      69632:
   5:    34816..   55295:      77824..     98303:  20480:      53248:
   6:    55296..   57343:     114688..    116735:   2048:      98304:
   7:    57344..   69631:     120832..    133119:  12288:     116736:
   8:    69632..   81919:     102400..    114687:  12288:     133120:
   9:    81920..   98303:     135168..    151551:  16384:     114688:
  10:    98304..   98306:      57344..     57346:      3:     151552:
  11:   100352..  112639:     151552..    163839:  12288:      59392:
  12:   112640..  145407:     165888..    198655:  32768:     163840:
  13:   145408..  163839:     198656..    217087:  18432:
  14:   163840..  163842:      40960..     40962:      3:     217088:
  15:   165888..  178175:     217088..    229375:  12288:      43008:
  16:   178176..  202751:     231424..    255999:  24576:     229376:
  17:   202752..  206847:     258048..    262143:   4096:     256000:
  18:   206848..  216756:     276480..    286388:   9909:     262144:
  19:   229376..  229378:      43008..     43010:      3:     299008:
  20:   294912..  294914:      53248..     53250:      3:     108544:
  21:   524288..  524288:      55296..     55296:      1:     282624:
  22:   819200..  819202:      61440..     61442:      3:     350208:
  23:   884736..  884738:      63488..     63490:      3:     126976:
  24:  1048576.. 1048577:      67584..     67585:      2:     227328:
  25:  1081344.. 1081391:      69632..     69679:     48:     100352:
  26:  1572864.. 1572864:      71680..     71680:      1:     561152:
  27:  1605632.. 1605634:      73728..     73730:      3:     104448:
  28:  2097152.. 2097152:      75776..     75776:      1:     565248:
  29:  2097167.. 2097167:      75791..     75791:      1:             last
/media/Grafi/sparse-file: 25 extents found

Eu pensei que era por causa do recurso "esparso", mas parece que todos os arquivos que possuem outros sistemas de arquivos neles são fragmentados dessa maneira. Dê uma olhada no seguinte exemplo:

Crie um arquivo cheio de zeros:

# dd if=/dev/zero of=./zero bs=1M count=2048 

Verifique seu nível de fragmentação:

# filefrag -v /media/Grafi/zero
Filesystem type is: ef53
File size of /media/Grafi/zero is 2147483648 (524288 blocks of 4096 bytes)
 ext:     logical_offset:        physical_offset: length:   expected: flags:
   0:        0..   32767:    6172672..   6205439:  32768:
   1:    32768..   65535:    6205440..   6238207:  32768:
   2:    65536..   98303:    6238208..   6270975:  32768:
   3:    98304..  118783:    6270976..   6291455:  20480:
   4:   118784..  151551:    6324224..   6356991:  32768:    6291456:
   5:   151552..  184319:    6356992..   6389759:  32768:
   6:   184320..  217087:    6389760..   6422527:  32768:
   7:   217088..  249855:    6422528..   6455295:  32768:
   8:   249856..  282623:    6455296..   6488063:  32768:
   9:   282624..  315391:    6488064..   6520831:  32768:
  10:   315392..  348159:    6520832..   6553599:  32768:
  11:   348160..  380927:    6553600..   6586367:  32768:
  12:   380928..  413695:    6586368..   6619135:  32768:
  13:   413696..  446463:    6619136..   6651903:  32768:
  14:   446464..  479231:    6651904..   6684671:  32768:
  15:   479232..  511999:    6684672..   6717439:  32768:
  16:   512000..  524287:    6717440..   6729727:  12288:             last,eof
/media/Grafi/zero: 2 extents found

Então, basicamente, esse arquivo tem 17 extensões, mas do ponto de vista humano, o arquivo tem dois pedaços

Agora crie um sistema de arquivos neste arquivo:

# mkfs.ext4 -m 0 -L ext /media/Grafi/zero

Verifique sua fragmentação novamente:

# filefrag -v /media/Grafi/zero

Filesystem type is: ef53
File size of /media/Grafi/zero is 2147483648 (524288 blocks of 4096 bytes)
 ext:     logical_offset:        physical_offset: length:   expected: flags:
   0:        0..     257:    5505024..   5505281:    258:
   1:      265..     265:    5505289..   5505289:      1:
   2:      272..     273:    5505296..   5505297:      2:
   3:      289..     289:    5505313..   5505313:      1:
   4:     8481..    8486:    5507361..   5507366:      6:    5513505:
   5:    32768..   32769:    5509120..   5509121:      2:    5531648:
   6:    98304..   98305:    5511168..   5511169:      2:    5574656:
   7:   163840..  163841:    5513216..   5513217:      2:    5576704:
   8:   229376..  229377:    5515264..   5515265:      2:    5578752:
   9:   262144..  262144:    5517312..   5517312:      1:    5548032:
  10:   294912..  294913:    5519360..   5519361:      2:    5550080: last
/media/Grafi/zero: 8 extents found

Alguém sabe o que realmente aconteceu aqui? Por que o arquivo foi fragmentado criando um sistema de arquivos nele? O que aconteceu com o length ?

Adicionado:

O mkfs.ext4 parameter -Enodiscard não funciona. Com essa opção, posso ver a estrutura do arquivo em filefrag (os blocos zerados). Mas depois de criar o sistema de arquivos dessa maneira, o arquivo fica fragmentado por algum motivo, não importa o quê. Talvez seja por causa dos metadados do sistema de arquivos que estão escritos, e faz algo no arquivo zerado. Eu não sei. Mas quando vejo a saída de filefrag , vejo que sempre há +6 extensões (no caso do arquivo 2G). Talvez seja por causa do superbloco e suas 5 cópias? Mas isso ainda não explica porque o arquivo inteiro está fragmentado - ainda é o mesmo arquivo.

Existe outra coisa. Quando eu recrio o sistema de arquivos neste arquivo:

# mkfs.ext4 -Enodiscard /media/Grafi/zero
mke2fs 1.43 (17-May-2016)
/media/Grafi/zero contains a ext4 file system
        created on Thu Jun  2 13:02:28 2016
Proceed anyway? (y,n) y
Creating filesystem with 524288 4k blocks and 131072 inodes
Filesystem UUID: 6d58dddc-439b-4175-9af6-8628f0d2a278
Superblock backups stored on blocks:
        32768, 98304, 163840, 229376, 294912

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

As extensões adicionadas desaparecem magicamente.

    
por Mikhail Morfikov 02.06.2016 / 10:39

2 respostas

2

Parece que esse foi um bug no mke2fs que causou o uso de fallocate(fd, PUNCH_HOLE, ...) em vez de fallocate(fd, DISCARD_ZERO, ...) ao zerar o espaço nas tabelas de inode (mesmo quando -E nodiscard foi usado).

Enviei um relatório de erros para a lista de discussão [email protected] do upstream depois de verificar esse comportamento localmente e recebi um patch em uma hora, assunto:

e2fprogs: block zero/discard cleanups

Eles devem ser incluídos na versão e2fsprogs-1.45 e provavelmente na versão de manutenção 1.44.x. Se você os quiser em um release de e2fsprogs do fornecedor, recomendo que você compacte seu e2fsprogs para verificar se isso está funcionando para você, informe o sucesso para linux-ext4 para que os patches pousem mais cedo e envie um relatório de bug para sua distro de escolha, então eles colocam os patches upstream em seus lançamentos.

    
por 17.04.2018 / 23:21
0
$ /sbin/mkfs.ext4 test1
mke2fs 1.42.12 (29-Aug-2014)
Discarding device blocks: done
[...]

Agora há uma dica. Vamos ver o que o manual diz:

-E extended-options
discard
  Attempt  to  discard blocks at mkfs time (discarding blocks initially is useful
  on solid state devices and sparse / thin-provisioned storage). When the  device
  advertises that discard also zeroes data (any subsequent read after the discard
  and before write returns zero), then mark all not-yet-zeroed  inode  tables  as
  zeroed.  This significantly speeds up filesystem initialization. This is set as
  default.

Então, basicamente, o mkfs sabe que os dados antigos no armazenamento subjacente não importam mais, então ele pode ser descartado, e o armazenamento subjacente pode ter uma maneira melhor de fazer isso, do que simplesmente sobrescrevendo-se com zeros. O que ele tem, o sistema de arquivos aqui pode simplesmente esquecer os blocos de dados.

Depois disso, o mkfs constrói as estruturas do sistema de arquivos necessárias, em um padrão de acesso aleatório, resultando na alocação de novos blocos de dados. O arquivo é esparso novamente e há alguma fragmentação.

Com -Enodiscard , o resultado talvez seja o esperado:

$ /sbin/mkfs.ext4 -Enodiscard test2
$ /usr/sbin/filefrag test2
test2: 2 extents found
    
por 02.06.2016 / 11:21