Warum ist die Fragmentierungsstufe in Dateien, die andere Dateisysteme enthalten, so groß?

8

Ich habe gerade herausgefunden, was spärliche Dateien sind und wollte einige Experimente mit ihnen durchführen. Im Wiki können Sie lesen, dass die Dateien leicht fragmentiert werden können. Ich wollte überprüfen, wie schlimm das ist. Ich habe eine Datei folgendermaßen erstellt:

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

Ich habe die Sparse-Datei gemountet und eine 600M-Datei darin abgelegt. Die Fragmentierungsstufe sieht folgendermaßen aus:

# 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

Ich dachte, das liegt an der "spärlichen" Funktion, aber es sieht so aus, als würden alle Dateien, in denen andere Dateisysteme enthalten sind, auf diese Weise fragmentiert. Schauen Sie sich das folgende Beispiel an:

Erstellen Sie eine Datei voller Nullen:

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

Überprüfen Sie die Fragmentierungsstufe:

# 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

Im Grunde hat diese Datei 17 Ausmaße, aber aus menschlicher Sicht hat die Datei zwei Blöcke

Erstellen Sie nun ein Dateisystem in dieser Datei:

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

Überprüfen Sie die Fragmentierung erneut:

# 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

Weiß jemand, was hier tatsächlich passiert ist? Warum wurde die Datei durch Erstellen eines Dateisystems fragmentiert? Was ist mit dem passiert length?

Hinzugefügt:

Der mkfs.ext4Parameter -Enodiscardfunktioniert nicht. Mit dieser Option kann ich die Struktur der Datei in filefrag(die Nullblöcke) sehen. Nachdem das Dateisystem auf diese Weise erstellt wurde, wird die Datei aus irgendeinem Grund fragmentiert, egal was passiert. Möglicherweise liegt es an den Metadaten des Dateisystems, die geschrieben wurden, und es hat etwas mit der auf Null gesetzten Datei zu tun. Ich weiß es nicht. Aber wenn ich mir die Ausgabe von filefragansehe, kann ich sehen, dass es immer +6 Extents gibt (im Fall einer 2G-Datei). Vielleicht liegt es am Superblock und seinen 5 Kopien? Dies erklärt jedoch immer noch nicht, warum die gesamte Datei fragmentiert ist - es ist immer noch dieselbe Datei.

Es gibt noch eine andere Sache. Wenn ich das Dateisystem in dieser Datei neu erstelle:

# 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

Die hinzugefügten Ausmaße verschwinden auf magische Weise.

Mikhail Morfikov
quelle

Antworten:

2

Es sieht so aus, als ob dies ein Fehler war mke2fs, der dazu führte, dass es verwendet wurde, fallocate(fd, PUNCH_HOLE, ...)anstatt fallocate(fd, DISCARD_ZERO, ...)den Speicherplatz in den Inode-Tabellen auf Null zu setzen (selbst wenn -E nodiscardes verwendet wurde).

Ich habe einen Fehlerbericht an die Upstream- [email protected]Mailingliste gesendet, nachdem ich dieses Verhalten lokal überprüft hatte, und innerhalb einer Stunde einen Patch erhalten, Betreff:

e2fprogs: block zero/discard cleanups

Sie sollten in der Version e2fsprogs-1.45 und wahrscheinlich in der Wartungsversion 1.44.x enthalten sein. Wenn Sie sie in einer Vendor- e2fsprogsVersion haben möchten , würde ich empfehlen, Ihre e2fsprogs zu patchen + zu erstellen, um zu überprüfen, ob dies für Sie funktioniert, den Erfolg zu melden, linux-ext4damit die Patches früher landen, und dann einen Fehlerbericht an die Distribution Ihrer Wahl zu senden, damit sie Ziehen Sie die Upstream-Patches in ihre Releases.

LustreOne
quelle
Redest du darüber? patchwork.ozlabs.org/cover/899596
Mikhail Morfikov
Das ist derjenige ... Ted sagte, dass er auch in der Wartungsversion 1.44 enthalten sein würde.
LustreOne
0
$ /sbin/mkfs.ext4 test1
mke2fs 1.42.12 (29-Aug-2014)
Discarding device blocks: done
[...]

Jetzt gibt es einen Hinweis. Mal sehen, was im Handbuch steht:

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

Im Grunde weiß mkfs also, dass die alten Daten im zugrunde liegenden Speicher keine Rolle mehr spielen, sodass sie verworfen werden können, und der zugrunde liegende Speicher kann dies möglicherweise besser tun, als nur mit Nullen zu überschreiben. Was es hat, kann das Dateisystem hier einfach die Datenblöcke vergessen.

Danach erstellt mkfs alle benötigten Dateisystemstrukturen in einem etwas zufälligen Zugriffsmuster, was dazu führt, dass neue Datenblöcke zugewiesen werden. Die Datei ist wieder spärlich und es gibt einige Fragmentierungen.

Mit -Enodiscarddem Ergebnis ist vielleicht das, was Sie erwartet haben:

$ /sbin/mkfs.ext4 -Enodiscard test2
$ /usr/sbin/filefrag test2
test2: 2 extents found
ilkkachu
quelle
Ich habe gerade die Frage aktualisiert. Weitere Informationen finden Sie hier.
Mikhail Morfikov