Pourquoi le niveau de fragmentation est-il si énorme dans les fichiers qui contiennent d'autres systèmes de fichiers?

8

Je viens de découvrir ce que sont les fichiers clairsemés et je voulais faire des expériences sur eux. Sur wiki, vous pouvez lire que les fichiers peuvent facilement être fragmentés. Je voulais vérifier à quel point c'est mauvais. J'ai créé un fichier de la manière suivante:

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

J'ai monté le fichier clairsemé et j'ai mis un fichier 600M dedans. Le niveau de fragmentation ressemble à ceci:

# 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

Je pensais que c'était à cause de la fonctionnalité "clairsemée", mais il semble que tous les fichiers contenant d'autres systèmes de fichiers soient fragmentés de cette façon. Jetez un œil à l'exemple suivant:

Créez un fichier plein de zéros:

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

Vérifiez son niveau de fragmentation:

# 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

Donc, fondamentalement, ce fichier a 17 étendues, mais du point de vue humain, le fichier a deux morceaux

Créez maintenant un système de fichiers dans ce fichier:

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

Vérifiez à nouveau sa fragmentation:

# 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

Est-ce que quelqu'un sait ce qui s'est réellement passé ici? Pourquoi le fichier s'est-il fragmenté en créant un système de fichiers dessus? Qu'est-il arrivé au length?

Ajoutée:

Le mkfs.ext4paramètre -Enodiscardne fonctionne pas. Avec cette option, je peux voir la structure du fichier dans filefrag(les blocs mis à zéro). Mais après avoir créé le système de fichiers de cette manière, le fichier devient fragmenté pour une raison quelconque, quoi qu'il arrive. C'est peut-être à cause des métadonnées du système de fichiers qui sont écrites, et cela fait quelque chose pour le fichier mis à zéro. Je ne sais pas. Mais quand je regarde la sortie de filefrag, je peux voir qu'il y a toujours +6 extensions (dans le cas d'un fichier 2G). C'est peut-être à cause du superbloc et de ses 5 copies? Mais cela n'explique toujours pas pourquoi le fichier entier est fragmenté - c'est toujours le même fichier.

Il y a autre chose. Lorsque je recrée le système de fichiers dans ce fichier:

# 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

Les étendues ajoutées disparaissent comme par magie.

Mikhail Morfikov
la source

Réponses:

2

Il semble que ce soit un bug mke2fsqui l'a amené à utiliser fallocate(fd, PUNCH_HOLE, ...)au lieu de mettre fallocate(fd, DISCARD_ZERO, ...)à zéro l'espace dans les tables d'inode (même lorsqu'il a -E nodiscardété utilisé).

J'ai soumis un rapport de bogue à la [email protected]liste de diffusion en amont après avoir vérifié ce comportement localement, et j'ai obtenu un correctif dans l'heure, sous réserve:

e2fprogs: block zero/discard cleanups

Ils devraient être inclus dans la version e2fsprogs-1.45 et probablement dans la version de maintenance 1.44.x. Si vous les voulez dans une e2fsprogsversion du fournisseur , je vous recommande de patcher + construire vos e2fsprogs pour vérifier que cela fonctionne pour vous, de signaler le succès pour linux-ext4que les correctifs arrivent plus tôt, puis de soumettre un rapport de bogue à votre distribution de choix afin qu'ils tirez les correctifs en amont dans leurs versions.

LustreOne
la source
Parlez-vous de cela? patchwork.ozlabs.org/cover/899596
Mikhail Morfikov
C'est celui-là ... Ted a dit qu'il serait également inclus dans la version de maintenance 1.44.
LustreOne
0
$ /sbin/mkfs.ext4 test1
mke2fs 1.42.12 (29-Aug-2014)
Discarding device blocks: done
[...]

Maintenant, il y a un indice. Voyons ce que dit le manuel:

-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.

Donc, fondamentalement, mkfs sait que les anciennes données sur le stockage sous-jacent n'ont plus d'importance, donc elles peuvent être supprimées, et le stockage sous-jacent pourrait avoir une meilleure façon de le faire, que simplement en écrasant avec des zéros. Ce qu'il a, le système de fichiers ici peut simplement oublier les blocs de données.

Après cela, mkfs construit toutes les structures de système de fichiers dont il a besoin, dans un modèle d'accès quelque peu aléatoire, ce qui entraîne l'allocation de nouveaux blocs de données. Le fichier est à nouveau clairsemé et il y a une certaine fragmentation.

Le -Enodiscardrésultat est peut-être ce que vous attendiez:

$ /sbin/mkfs.ext4 -Enodiscard test2
$ /usr/sbin/filefrag test2
test2: 2 extents found
ilkkachu
la source
Je viens de mettre à jour la question, consultez-la pour plus d'informations.
Mikhail Morfikov