Files in btrfs die eventuell ein defrag brauchen

:warning: Work in Progress !!!

Nachdem gefühlt jeder 2. Windows-umsteiger nachfragt, wie man manjaro defragmentieren kann, und ich selbst immer antworte dass das unnötig sei, will ich das jetzt an meiner schon länger bestehenden Installation kontrollieren.

Gibt es Fragmentierung in btrfs?

Erste Fußangel: Das sind wirklich 2 Themen die man nicht mischen sollte:

Fragmentierung des “free space” !

Das findet ständig statt. Wenn btrfs aber nicht zu voll ist (80%), wird das automatisch im normalen Betrieb ausreichend bereinigt.
Es muss aber unbedingt darauf geachtet werden, dass möglichst nie alle chunks “allocated” sind. Das ist dann das berühmt berüchtigte “out of space”.
Dabei nutzt es wenig, dass in dieser Situation eventuell noch 15% freier Platz verteilt auf der Platte da ist. Wenn jetzt ein Prozess (z.B. Update) läuft der btrfs beim Aufräumen stört, sitzt man in der Falle und der Prozess scheitert weil er nichts mehr Schreiben kann.
Hilfe gibts hier

Fragmentierung einzelner Dateien ?

Dateien in die regelmäßig Ergänzungen oder Änderungen geschrieben werden, neigen dazu unter btrfs stark zu fragmentieren. Das ist Prinzip-bedingt wegen CopyOnWrite und “kein Fehler”.

Welche Dateien kommen in Frage ?

  • Logdateien
  • Datenbanken
  • und womöglich andere Spezialitäten

Was das Internet sagt:

  • Fragmentierung spielt bei SSDs überhaupt keine Rolle :thinking:
  • Andere dagegen sprechen von drastischen Zahlen. In einem Beitrag ist von 17k extends die Rede. :rofl: Also eine Datei die in 17.000 Fragmente zersplittert ist.
    Da nutzt dann bestimmt die best SSD nix wenn die Datei gelesen werden muss

Selber untersuchen macht schlau

:man_factory_worker:

Wie findet man fragmentierte Dateien ?

Da gibt es ein Program namens filefrag das für einzelne Dateien anzeigt, aus wie vielen Teilen sie bestehen.
Das einzige Problem dabei ist, dass dieses Programm für ext4 geschrieben wurde. Es “soll” aber auch für andere Dateisysteme funktionieren. Wir werden sehen :wink:

zsh, filefrag, egrep … ein Einzeiler halt

for N in /var/**/*(.); do filefrag $N; done|egrep ': ([0-9]{3,}|[6-9][0-9]) extents found' >> /opt/defrag.txt  
  • Untersuche mit filefrag jede Datei *(.) die in irgendeinen Teil /**/ von /var liegt:
    for N in /var/**/*(.); do filefrag $N; done

  • Filtere |egrep diejenigen aus die mehr als 100 ([0-9]{3,} oder 60-99 |[6-9][0-9]) extends haben
    |egrep ': ([0-9]{3,}|[6-9][0-9]) extents found'

35k extends - Das ist heftig !

Der erste Streich:

  • /var/nosnap/VMs/manjaro19/manjaro19.vdi: 34999 extents found
    compsize bestätigt das aber. Un die VM war nichtmal oft im Einsatz :wink:
compsize /var/nosnap/VMs/manjaro19/manjaro19.vdi                                                                                                    
Processed 1 file, 35036 regular extents (35036 refs), 0 inline.
Type       Perc     Disk Usage   Uncompressed Referenced  
TOTAL       76%       10G          13G          13G       
none       100%      8.9G         8.9G         8.9G       
zstd        26%      1.1G         4.2G         4.2G    

Also defreagmentieren wir die Datei jetzt am besten schnell

Warning: most Linux kernels will break up the ref-links of COW data
    (e.g., files copied with 'cp --reflink', snapshots) which may cause
    considerable increase of space usage. See btrfs-filesystem(8) for
    more information.

Es ist klar dass wir dabei die Verbindung zu den Snapshots verlieren, aber auf diesem subvolume gibt es keine snapshots :wink:

 sudo btrfs filesystem defrag 
 var/nosnap/VMs/manjaro19/manjaro19.vdi

Dann zur Kontrolle nochmal anschauen:

compsize /var/nosnap/VMs/manjaro19/manjaro19.vdi                                                                                                    
Processed 1 file, 54678 regular extents (54678 refs), 0 inline.
Type       Perc     Disk Usage   Uncompressed Referenced  
TOTAL       64%      8.5G          13G          13G       
none       100%      6.7G         6.7G         6.7G       
zstd        27%      1.7G         6.4G         6.4G   

55k extends - Das kann ja wohl nicht sein ?

Also erstmal sieht es so aus als ob das genau das Gegenteil bewirkt hätte. Aber bei genauerer Betrachtung wird sichtbar, dass die Datei jetzt deutlich besser komprimiert ist als vorher.
Und da liegt auch das “scheinbare” Problem. Die Datei ist nicht wirklich fragmentiert im klassischen Sinn. Jedes einzeln komprimierte Häppchen zählt wohl als ein Fragment.
Wenn man also Kompression eingeschaltet hat, (was diese VM von 13G auf 8.5G drückt) kann man nicht so einfach die Erbsen(Extends) zählen.
Bei mir sind tatsächlich danach mehr als 2.5G im Dateisystem frei geworden :sunglasses:

969 extends - Eine zerstückelte Logdatei !

Der 2.Streich:

  • /var/log/snapper.log: 969 extents found (das war gestern)
    compsize bestätigt das heute (sogar etwas mehr)
compsize snapper.log                                                                                                                                 
Processed 1 file, 1022 regular extents (1022 refs), 0 inline.
Type       Perc     Disk Usage   Uncompressed Referenced  
TOTAL       61%      3.9M         6.5M         4.0M       
none       100%      1.5M         1.5M         1.5M       
zstd        49%      2.4M         4.9M         2.5M       

Also schnell mal defragmentieren

sudo btrfs filesystem defrag snapper.log
compsize snapper.log                                                                                                                                 
Processed 1 file, 1022 regular extents (1022 refs), 0 inline.
Type       Perc     Disk Usage   Uncompressed Referenced  
TOTAL       61%      3.9M         6.5M         4.0M       
none       100%      1.5M         1.5M         1.5M       
zstd        49%      2.4M         4.9M         2.5M       

Das ist jetzt aber ernüchternd. Anscheinend hat das Defragmentieren garnix gebracht. Offensichtlich ist die Datei nicht wirklich fragmentriert, sondern wie die VM einfach nur gut komprimiert. Die Aussage “das sind soundsoviel Bruchstücke” scheint also recht wenig zu bedeuten. Um zu wissen, ob das wirklich relevant ist, müsste man schon wissen, wo diese Buchstücke liegen. Sind sie alle in einem oder 2 “chunks”, dann ist die fragmentierung bedeutungslos weil alles gleichzeitig im Speicher vorliegt. Im Gegenteil, zusammen mit der Kompression ist die Datei vermutlich schneller gelesen, als wenn sie unkomprimiert an einem Stück gelesen werden könnte.

Und der 3. folgt sogleich :wink:

Ergebnisse:

  • betroffen sind VMs ganz heftig, aber eventuell ist die Datei nur halt sehr groß und sehr gut komprimiert (zstd:9). Ausserdem liegen die “Fragmente” in diesem Fall vermutlich nacheinander im selben “chunk” und werden somit extrem schnell gelesen
  • Auch Logdateien können ganz heftig fragmentiert sein. Das stellt sich bei mir aber auch als reiner Bluff heraus und stammt offensichtlich nur von der Kompression. Der Zugriff auf mehrere Generationen von Logs ist weit wertvoller als die möglichen Probleme
    Wenn die Größe der Logs begrenzt ist, scheint btrfs die Fragmentierung hier in einem vernünftigen Rahmen zu halten. Mit einer SSD also kein Problem

Randbedingungen

Die Randbedingungen für btrfs sind sicher nicht bei jedem gleich. Bei meiner Installation ist einiges btrfs-freundlich

  • 2 Partitionen auf 2 verschiedenen SSDs im btrfs volume als RAID2
  • Die Kompression des volume ist auf zstd:9 eingestellt (langsam beim schreiben, aber hohe kompression)
  • Das Volume ist nur zu weniger als 50% voll ! (Da hat btrfs platz zum atmen)
  • Ich mach jedes manjaro update zeitnah (keine sammelupdates)
  • snapper löscht die snapshots die es macht (zeitgesteuert).
  • Die snapshots beginnen stündlich und enden in Stufen nach 3 Monaten. (keine älteren Snapshots !!!)
  • Der Rechner hat 48GB RAM (viel Puffer beim lesen, kein swapping)
  • Die CPU verarbeitet 16 Threads
  • Das system hat bestimmt schon 30 oder mehr Rollbacks erlebt (Cleanup nicht vergessen)
7 Likes

Danke Andreas, das ist mal sehr gut erklärt. :+1:

Das heißt, die BTRFS-Defragmentierung verarbeitet nur die Komprimierung?


Ich habe mein Subvolumen @home bisschen geprüft:

Vorher:

❯ sudo btrfs filesystem du -s /btrfs/@home/                                                                                      
     Total   Exclusive  Set shared  Filename
  76.76GiB    65.16MiB    72.11GiB  /btrfs/@home/

“Set shared”: 72.11 GB wurde noch nicht defragmentiert.

BTRFS-Defragmentierung ausführen:

sudo btrfs filesystem defragment -czstd -r /btrfs/@home/

Nachher:

❯ sudo btrfs filesystem du -s /btrfs/@home/
     Total   Exclusive  Set shared  Filename
  76.76GiB    76.75GiB     8.02MiB  /btrfs/@home/

“Set shared”: 8 MB nähert sich 0 MB. “Exclusive” is ähnlich wie “Total”.

Aber wenn man ein neues Snapshot erstellt, dann wird “Set shared” automatisch zurückgesetzt:

❯ sudo btrfs filesystem du -s /btrfs/@home/                                                                                       
     Total   Exclusive  Set shared  Filename
  76.76GiB   308.00KiB    73.47GiB  /btrfs/@home/

Nein, das kann beides.

  • Dateifragmente zusammensuchen
  • Und beim speichern dann gleich auch neu komprimieren

Das macht ja auch Sinn. Zum neu komprimieren muß man ja zuerst alles zusammensammeln. Und wegen CoW kann es ja nicht dahin geschrieben werden, wo es herkommt.

Beim defragmentieren werden immer die Reflinks zu den Snapshots gebrochen. Deswegen geht das shared gegen NULL. Neue Snapshots sind dann wieder shared.

1 Like

Hallo @andreas85 :wink:

Das ist zwar interessant, was du hier schreibst, aber ich blicke da jetzt nicht durch.

Kannst du vielleicht ein wenig spezifischer und konkreter werden, wie man fragmentierte Dateien identifizieren kann? Was sind die konkreten Indikatoren?

Ich hab zum Beispiel das hier geschrieben:

Path=$1
Ext=$2

[[ -z $Path ]] && exit
[[ -z $Ext ]] && exit

sync

echo "Searching in $Path for files with extents higher than $Ext"

find $Path -type f -exec filefrag -s {} \; | while read line; do
p=$(echo $line | sed -r "s/(.+): (.+)/\\1/g" )
e=$(echo $line | sed -r "s/(.+): (.+) extent(.+)/\\2/g" )
if [[ $e -gt $Ext ]]; then
echo "$p has $e extents: defragmenting..."
btrfs filesystem defragment -f "$p"
p=$(filefrag -s "$p" | sed -r "s/(.+): (.+)/\\1/g" )
e=$(filefrag -s "$p" | sed -r "s/(.+): (.+) extent(.+)/\\2/g" )
echo "$p has now $e extents."
fi
done

Dann:

sudo bash script.sh /path/to/defrag <number of extents>

Zum Beispiel:

sudo bash script.sh /storage/@games 100

Es sucht dann mittels filefrag ob Dateien einen Wert übersteigen, defragmentiert es und zeigt mittels filefrag das Resultat.

Aber irgendwie sieht das so aus, also ob es gar nichts bringt.

Das war auch mein Ergebnis !

  • Anscheinend wird eine Datei als fragmentiert bezeichnet, wenn sie aus mehreren Teilen besteht :grinning:
  • Die Kompression teilt anscheinend die Dateien automatisch in einzelne Teile :rofl:
  • Selbst Teile die im jeweiligen “chunk” direkt hintereinander liegen (und daher schnell gelesen werden können) werden als getrennte Teile gemeldet :thinking:
  • Das defragmentieren bringt nix wenn das Komprimieren danach wieder Teile draus macht :crazy_face:

→ Wenn du Kompression nutzt, ist das Zählen der Teile scheinbar eine unnötige Fleißaufgabe :bomb:

Da ich auf Kompression nicht verzichten möchte, :smiling_face_with_three_hearts: habe ich weitere Untersuchungen eingestellt. Der Thread soll nur andere davon abhalten den Messergebnissen zu hohe Bedeutung zuzumessen.

Ein anderer Test mit einer frischen und großen Datei von Steam:

$ du -hs "/games/GameLibrary/SteamLibrary/steamapps/common/Guild Wars 2/Gw2.dat" 
64G	Gw2.dat
$ filefrag  "/games/GameLibrary/SteamLibrary/steamapps/common/Guild Wars 2/Gw2.dat"                
Gw2.dat: 48373 extents found
$ sudo btrfs filesystem defragment "/games/GameLibrary/SteamLibrary/steamapps/common/Guild Wars 2/Gw2.dat" 
$ filefrag "/games/GameLibrary/SteamLibrary/steamapps/common/Guild Wars 2/Gw2.dat" 
Gw2.dat: 306 extents found

Hier scheint es doch eine Wirkung zu haben… seltsam.

Eventuell hängt die “Mindestanzahl” von Fragmenten davon ab, wie leicht die Datei komprimierbar ist (je besser, desto mehr Teile) und/oder wie stark sie komprimiert wird (bei mir zstd:9).
Ich vermute, dass unkomprimierte Teile immer getrennte Fragmente sind. Wenn also öfters zwischen “Kompression” und “unkomprimiert speichern” gewechselt wird, entstehen eventuell die Fragmente :thinking:

Hallo andreas85,
Deine erste Antwort ist prima: “… unnötig …”, wenn ich aber weiter lese, dann schwirrt es nur so von Fachbegriffen.
Ich bin ein leidenschaftlicher Windows-Umsteiger und ein begeisterter Btrfs Nutzer, wegen den Snapshots. Doch lese ich, dass einige Dateien tausendfach fragmentiert sein könnten.
Ich sehe, dass selbst Ihr Profis ganz schön ins Schwitzen kommt, um da eine gute Lösung zu finden. Doch was sollen da die (ewigen) Neulinge wie ich tun? Einfach cool bleiben?
Frage: Gibt es eine Lösung, ein Vorgang, den Ihr empfehlen könnt, den ich ausführen könnte, um eine mögliche oder sehr wahrscheinliche Fragmentierung zu verringern?
Was tun bei / mit Btrfs auf SSD und
bei /home, ebenfalls auf SSD und
bei einer großen 6TB HDD mit ext4?

:smiling_face_with_three_hearts:
Die oben beschriebene Fragmentierung von Dateien (wenn sie aufgrund von Kompression angezeigt wird) ist nicht nachteilig !
Im Gegenteil werden komprimierte Daten deutlich schneller geladen als unkomprimierte. Die angezeigte Anzahl an Fragmenten ist kein Anzeichen dafür dass die Datei weit verstreut ist, sondern nur dass sie in Teilen vorliegt. Diese Teile können auch (und vermutlich ist das hier der Fall) direkt hintereinander liegen.

1 Like

Heißt das (für mich und alle, die nicht viel davon verstehen), man muss bei Linux und auch bei Btrfs sich ums Defragmentieren nicht kümmern?
Das wäre prima.

Generell nein. Allerdings: Je weniger Speicher verfügbar desto stärker fragmentieren Dateien. Logisch oder? Solange du, ich würde mal sagen: 20-30% Luft nach oben hast, sollte Fragmentierung kein Problem darstellen. Das selbe gilt auch für ext4. Jedes Dateisystem fragmentiert, jedoch bleibt es bei Linux durch diverse Schreibtechniken in erträglichen Grenzen, anders wie unter Windows mit NTFS.

1 Like

Hallo megavolt,
ja, darauf hast Du mich schon mal hingewiesen, dass Btrfs genug Platz braucht… , das habe ich mir gemerkt.
Gilt das nicht defragmentieren Müssen auch für eine HDD mit ext4? Ich habe ja mit digiKam viele Anmerkungen und Stichworte in die Fotos schreiben lassen, so dass sie alle jeweils um ein paar KB größer wurden. Und deshalb gehe ich davon aus, dass jedes Foto allein dadurch ordentlich fragmentiert worden ist.
Kann ich das ignorieren? Oder besser doch defragmentieren? Falls das überhaupt bei Linux geht. Oder soll man ab und zu die ganzen Fotos auslagern, löschen und dann wieder zurück kopieren? Quasi als Defragmentierungs-Ersatz?

Dann überprüfe das doch einfach:

Fragmentierung prüfen:

sudo e4defdrag -c -v /pfad/zum/ziel

Defragmentieren:

sudo e4defdrag -v /pfad/zum/ziel

Aber ext4 hat eine automatische online Defragmentierung beim Schreiben im Treiber mit drin, deswegen wollte man sich da keine Sorgen machen.

Bei BTRFS muss man das zusätzlich aktivieren, da es hier auch negative Effekte haben kann: zb: bei SSDs oder snapshots.

[michae1@T7-Manjaro ~]$ e4defrag -c -v /MEDIEN/Bilder/alle_neuen_Fotos/03/20220903_172915_Kronach.jpg
e4defrag 1.46.5 (30-Dec-2021)

[ext 1]: start 113647616: logical 0: len 907

Jetzt kann ich leider nicht lesen, ob das Foto fragmentiert ist.

Oder ein anderes Foto:
[michae1@T7-Manjaro ~]$ e4defrag -c -v /MEDIEN/Bilder/alle_neuen_Fotos/03/20220903_184645_Kronach.jpg
e4defrag 1.46.5 (30-Dec-2021)

[ext 1]: start 113681920: logical 0: len 512
[ext 2]: start 113683968: logical 512: len 500

@Michi Ich denke du hast nicht alles kopiert…

Beispiel:

$ sudo e4defrag -c -v /backup/borg/repo/data/0/9                                             ✔  11m 10s  
[sudo] Passwort für user:         
e4defrag 1.46.5 (30-Dec-2021)
<File>
[ext 1]:	start 346310656:	logical 0:	len 32768
[ext 2]:	start 346343424:	logical 32768:	len 95568

 Total/best extents				2/1
 Average size per extent			256672 KB
 Fragmentation score				0
 [0-30 no problem: 31-55 a little bit fragmented: 56- needs defrag]
 This file (/backup/borg/repo/data/0/9) does not need defragmentation.

Es hat 2 extents: Die Datei selbst und ein “Extent”.

Das hier ist wichtig:

 Fragmentation score				0
 [0-30 no problem: 31-55 a little bit fragmented: 56- needs defrag]

Du kannst auch einen Ordner als Ziel wählen.

wenn ich den Ordner als Ziel nehme, kommt das:
e4defrag -c -v /MEDIEN/Bilder/alle_neuen_Fotos/03/
e4defrag 1.46.5 (30-Dec-2021)
now/best size/ext
[1/25] “/MEDIEN/Bilder/alle_neuen_Fotos/03”
File is not regular file
[2/25]

und dann lange nichts, und danach die Auflistung aller Fotos in diesem Ordner.

Mach es mal mit sudo wie ich es gemacht habe :wink:

Gerne, hier die Ausgabe mit sudo:
Total/best extents 28/24
Average size per extent 3433 KB
Fragmentation score 0
[0-30 no problem: 31-55 a little bit fragmented: 56- needs defrag]
This directory (/MEDIEN/Bilder/alle_neuen_Fotos/03/) does not need defragmentation.

sieht gut aus, oder?

Also ich denke du hast keine herausragende Affinität für Technik, aber Englisch lesen und verstehen, das traue ich dir schon zu.

Bitte stell dich nicht dümmer, als du bist. Danke. Nein es ist nicht böse gemeint, aber das ist doch wirklich offensichtlich. Da steht sogar eine Schlussfolgerung: