GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Linux – Warum wurden 2013 Probleme mit „usb-stick Stall“ gemeldet? Warum wurde dieses Problem nicht durch den bestehenden „no-i/o Dirty Throttling“-Code gelöst?

Das schädliche USB-Stick-Stall-Problem – LWN.net, November 2013.

Artem S. Tashkinov ist kürzlich auf ein Problem gestoßen, das zumindest einigen LWN-Lesern bekannt sein wird. Schließen Sie ein langsames Speichergerät (z. B. einen USB-Stick oder einen Mediaplayer) an einen Linux-Computer an und schreiben Sie viele Daten darauf. Das gesamte System hängt sich einfach auf , möglicherweise minutenlang.

Diesmal machte Artem jedoch eine interessante Beobachtung:Das System blieb stehen, wenn es mit einem 64-Bit-Kernel lief, aber kein solches Problem trat auf, wenn ein 32-Bit-Kernel auf derselben Hardware verwendet wurde.

Der Artikel erklärt, dass bei einem 64-Bit-Kernel der Dirty-Page-Cache (Writeback-Cache) standardmäßig auf 20 % des Speichers anwachsen durfte. Mit einem 32-Bit-Kernel war es effektiv auf ~180 MB begrenzt.

Linus schlug vor, es auch auf 64-Bit auf ~ 180 MB zu beschränken, aber das aktuelle Linux (v4.18) tut dies nicht. Vergleichen Sie den von Linus vorgeschlagenen Patch mit der aktuellen Funktion in Linux 4.18. Das größte Argument gegen solche Änderungen kam von Dave Chinner. Er wies darauf hin, dass eine zu starke Reduzierung der Pufferung dazu führen würde, dass Dateisysteme unter Fragmentierung leiden würden. Er erklärte auch, dass „wir für Streaming IO normalerweise mindestens
5 Sekunden zwischengespeicherter dirty benötigen Daten, um Verzögerungen auszugleichen.“

Ich bin verwirrt. Warum hat der USB-Stick-Stall das gesamte System zum Absturz gebracht?

Ich bin verwirrt, weil ich einen früheren Artikel gelesen habe, der Code beschreibt, der 2011 (Linux 3.2) zusammengeführt wurde. Es zeigt, dass der Kernel den Dirty-Page-Cache auf Gerätebasis hätte kontrollieren sollen:

No-I/O Dirty Throttling – LWN.net, 2011

Hier kommt Fengguangs Patch-Set ins Spiel. Er versucht, einen Regelkreis zu schaffen, der bestimmen kann, wie viele Seiten jeder Prozess zu einem bestimmten Zeitpunkt schmutzig machen darf. Prozesse, die ihr Limit überschreiten, werden einfach für eine Weile in den Ruhezustand versetzt, damit das Writeback-System sie einholen kann.

[…]

Das Ziel des Systems besteht darin, die Anzahl der schmutzigen Seiten auf dem Sollwert zu halten; Wenn die Dinge aus dem Ruder laufen, wird immer mehr Kraft aufgewendet, um die Dinge wieder dorthin zu bringen, wo sie sein sollten.

[…]

Dieses Verhältnis lässt sich aber ohne Berücksichtigung des Backing Device (BDI) nicht wirklich berechnen. Ein Prozess kann Seiten verschmutzen, die auf einer bestimmten BDI gespeichert sind, und das System kann im Moment einen Überfluss an schmutzigen Seiten haben, aber die Weisheit, diesen Prozess zu drosseln, hängt auch davon ab, wie viele schmutzige Seiten für diese BDI existieren. […] Ein BDI mit wenigen schmutzigen Seiten kann seinen Rückstand schnell auflösen, sodass er sich wahrscheinlich leisten kann, ein paar mehr zu haben, selbst wenn das System etwas schmutziger ist, als einem lieb ist. Das Patch-Set optimiert also das berechnete pos_ratio für einen bestimmten BDI unter Verwendung einer komplizierten Formel, die ansieht, wie weit dieser bestimmte BDI von seinem eigenen Sollwert und seiner beobachteten Bandbreite entfernt ist. Das Endergebnis ist ein modifiziertes pos_ratio, das beschreibt, ob das System mehr oder weniger Seiten verschmutzen sollte, die von der angegebenen BDI unterstützt werden, und um wie viel.

Die Steuerung pro Gerät wurde sogar noch früher hinzugefügt:Smarter Write Throttling, 2007 LWN.net. [PATCH 0/23] Dirty Throttling pro Gerät -v10. Es wurde in Linux-Version 2.6.24 zusammengeführt.

Akzeptierte Antwort:

  1. Der Artikel von 2013 ist falsch
  2. Ein Fehler in LWN? Sind Sie sicher?
  3. Lange Warteschlangen in E/A-Geräten, die durch „Hintergrund“-Rückschreiben erstellt wurden
  4. Einschränkungen von „no-I/O Dirty Throttling“?
  5. Echte Berichte über „USB-Stick-Stall“-Probleme
  6. Das Dirty Limit wurde falsch berechnet [2014]
  7. Riesige Seitenzuweisungen blockieren auf IO [2011]
  8. „Schmutzige Seiten erreichen das Ende der LRU“? [vor 2013]

1. Der Artikel von 2013 ist falsch

Der Artikel „USB-Stick Stall“ vermittelt einen sehr irreführenden Eindruck. Es stellt sowohl den ursprünglichen Bericht als auch die Reihe von Antworten falsch dar.

Artem hat nicht gemeldet, dass das gesamte System hängen geblieben ist, als es zwischengespeicherte Schreibvorgänge auf einen USB-Stick geleert hat. Sein ursprünglicher Bericht bemängelte lediglich, dass das Ausführen des Befehls „sync“ bis zu „Dutzende von Minuten“ dauern könne. Diese Unterscheidung wird in einer Antwort von Linus Torvalds explizit gemacht:

Es ist eigentlich ganz einfach, es zu reproduzieren, indem Sie einfach einen durchschnittlichen
USB-Stick nehmen und versuchen, darauf zu schreiben. Ich habe es gerade mit einem zufälligen ISO
-Image gemacht, und es ist schmerzhaft. Und es ist nicht so, dass es schmerzhaft ist,
die meisten anderen Dinge im Hintergrund zu erledigen, aber wenn Sie zufällig
irgendetwas ausführen, das "synchronisiert" (und es passiert in Skripten), ist das Ding einfach
kommt mit Vollbremsung zum Stillstand.
Minutenlang.

2. Ein Fehler in LWN? Sind Sie sicher?

Jon Corbet hatte fünfzehn Jahre Erfahrung und berichtete wöchentlich über die Entwicklung des Linux-Kernels. Ich hatte erwartet, dass der Artikel mindestens nah war um es in gewissem Sinne richtig zu machen. Ich möchte also die beiden unterschiedlichen Aufzeichnungen verarbeiten und nach detaillierten Punkten suchen, in denen sie übereinstimmen oder nicht übereinstimmen.

Ich habe die gesamte ursprüngliche Diskussion gelesen und dabei die Archive auf lore.kernel.org verwendet. Ich denke, die Botschaften sind ziemlich klar.

Ich bin mir zu 100% sicher, dass der Artikel die Diskussion falsch interpretiert. In Kommentaren unter dem Artikel wiederholten mindestens zwei Leser die falsche Behauptung in ihren eigenen Worten, und niemand korrigierte sie. Der Artikel setzt diese Verwirrung im dritten Absatz fort:

All diese Daten verstopfen die E/A-Warteschlangen und verzögern möglicherweise andere Operationen. Und sobald jemand sync() aufruft, hören die Dinge auf, bis die gesamte Warteschlange geschrieben ist.

Dies könnte eine Verwirrung sein, wenn Linus sagt:„Das Ding kommt einfach zum Stillstand“. „Das Ding“ bezieht sich auf „alles, was sync “. Aber Corbet schreibt, als ob „das Ding“ „das gesamte System“ meinte.

Laut Linus ist dies ein reales Problem. Aber die überwiegende Mehrheit der „Dinge“ tut das nicht Aufruf in die systemweite sync()-Operation.[1]

Warum könnte Corbet dies mit „dem gesamten System“ verwechseln? Ich schätze, es gab eine Reihe von Problemen, und nach einer Weile wird es schwierig, sie alle getrennt im Kopf zu behalten :-). Und obwohl LWN die Entwicklung von Dirty Throttling pro Gerät (und pro Prozess) beschrieben hat, nehme ich an, dass im Allgemeinen nicht viel über solche Details geschrieben wird. Viele Dokumente beschreiben nur die globalen Dirty-Limit-Einstellungen.

3. Lange Warteschlangen in E/A-Geräten, die durch „Hintergrund“-Rückschreiben erstellt wurden

Artem hat einen zweiten Bericht im Thread gepostet, in dem „der Server fast zum Stillstand kommt und andere IO-Anforderungen viel mehr Zeit in Anspruch nehmen“.

Verwandte:Linux – Routing durch iptables?

Dieser zweite Bericht stimmt nicht mit Behauptungen über einen hängenden USB-Stick überein. Es geschah nach dem Erstellen einer 10-GB-Datei auf einem internen Scheibe. Das ist ein anderes Problem.

Der Bericht bestätigte nicht, ob dies durch eine Änderung der Dirty-Limits verbessert werden könnte. Und es gibt eine neuere Analyse solcher Fälle. Es gibt ein erhebliches Problem, wenn es die E/A-Warteschlange Ihrer Hauptfestplatte verstopft. Sie können lange Verzögerungen auf einer Festplatte erleiden, auf die Sie sich ständig verlassen, um Programmcode bei Bedarf zu laden, Dokumente und App-Daten mit write() + fsync() zu speichern usw.

Auf dem Weg zu einem weniger störenden Zurückschreiben im Hintergrund – LWN.net, 2016

Wenn der Speicherverwaltungscode entscheidet, eine Reihe von schmutzigen Daten zu schreiben, ist das Ergebnis eine E/A-Anforderung, die an das Blocksubsystem gesendet wird. Diese Anforderung kann einige Zeit im E/A-Scheduler verbringen, wird aber schließlich an den Treiber für das Zielgerät weitergeleitet.

Das Problem ist, dass, wenn viele schmutzige Daten geschrieben werden müssen, möglicherweise eine große Anzahl (wie Tausende) von Anforderungen für das Gerät in die Warteschlange gestellt werden. Selbst eine einigermaßen schnelle Fahrt kann einige Zeit in Anspruch nehmen, um so viele Anfragen zu bearbeiten. Wenn eine andere Aktivität (z. B. das Klicken auf einen Link in einem Webbrowser oder das Starten einer Anwendung) E/A-Anforderungen auf demselben Blockgerät generiert, werden diese Anforderungen an das Ende dieser langen Warteschlange gestellt und möglicherweise für einige Zeit nicht bedient. Wenn mehrere synchrone Anfragen generiert werden – beispielsweise Seitenfehler von einer neu gestarteten Anwendung – muss jede dieser Anfragen wiederum diese lange Warteschlange durchlaufen. Das ist der Punkt, an dem die Dinge einfach aufzuhören scheinen.

[…]

Die meisten Blocktreiber unterhalten auch intern eigene Warteschlangen. Diese Warteschlangen auf niedrigerer Ebene können besonders problematisch sein, da eine Anfrage, wenn sie dort ankommt, nicht mehr der Kontrolle des I/O-Schedulers unterliegt (falls es überhaupt einen I/O-Scheduler gibt).

Um dies zu verbessern, wurden die Patches Ende 2016 zusammengeführt (Linux 4.10). Dieser Code wird als „Writeback Throttling“ oder WBT bezeichnet. Suche im Internet nach wbt_lat_usec findet auch noch ein paar Geschichten dazu. (Das ursprüngliche Dokument schreibt über wb_lat_usec , ist aber veraltet). Beachten Sie, dass die Writeback-Drosselung nicht mit den CFQ- oder BFQ-I/O-Schedulern funktioniert. CFQ war als Standard-I/O-Scheduler beliebt, einschließlich in Standard-Kernel-Builds bis Linux v4.20. CFQ wurde in Kernel v5.0 entfernt.

Es gab Tests, um das Problem (und eine Prototyplösung) sowohl auf einer SSD (die wie NVMe aussah) als auch auf einer „normalen Festplatte“ zu veranschaulichen. Die Festplatte war „nicht ganz so schlimm wie Geräte mit tieferer Warteschlangentiefe, bei denen wir enorme E/A-Bursts haben“.

Ich bin mir bei den „Tausenden“ von Anfragen in der Warteschlange nicht sicher, aber es gibt zumindest NVMe-Geräte, die Hunderte von Anfragen in die Warteschlange stellen können. Bei den meisten SATA-Festplatten können 32 Anfragen in die Warteschlange gestellt werden („NCQ“). Natürlich würde die Festplatte länger brauchen, um jede Anfrage abzuschließen.

4. Einschränkungen von „no-I/O Dirty Throttling“?

„No-I/O Dirty Throttling“ ist ein recht komplexes technisches System. Es wurde auch im Laufe der Zeit optimiert. Ich bin mir sicher, dass es einige gab und immer noch gibt Einschränkungen innerhalb dieses Codes.

Der LWN-Bericht, die Code-/Patch-Kommentare und die Folien der ausführlichen Präsentation zeigen, dass eine große Anzahl von Szenarien berücksichtigt wurde. Dazu gehört der notorisch langsame USB-Stick vs. schneller Hauptantrieb. Die Testfälle enthalten den Ausdruck „1000 gleichzeitige DDs“ (d. h. sequentielle Schreiber).

Bisher weiß ich nicht, wie ich irgendwelche Einschränkungen innerhalb des schmutzigen Drosselungscodes demonstrieren und reproduzieren soll.

Ich habe mehrere Beschreibungen von Problembehebungen gesehen, die außerhalb des schmutzigen Drosselungscodes lagen. Die letzte Lösung, die ich gefunden habe, stammt aus dem Jahr 2014 – siehe nachfolgende Abschnitte. In dem Thread, über den LWN berichtet, erfahren wir:

In den letzten Releases wurden solche Probleme
durch Probleme bei der Wiederherstellung verursacht, die es satt hatten, viele schmutzige
/ Under-Writeback-Seiten zu sehen, und am Ende hängen blieben, während sie darauf warteten, dass IO fertig war.

[…] Das Systemtap-Skript hat diese Art von Bereichen erfasst und ich
glaube, dass sie behoben sind.

Mel Gorman sagte auch, es gebe einige „offene Probleme“.

Es gibt aber immer noch Probleme. Wenn alle Dirty Pages von einem langsamen Gerät unterstützt würden, dann würde Dirty Limiting immer noch dazu führen, dass der Dirty Page Balancing blockiert wird […]

Diese Passage war das einzige, was ich in dem gemeldeten Diskussionsthread finden konnte, das auch nur annähernd die LWN-Interpretation unterstützt. Ich wünschte, ich hätte verstanden, worauf es sich bezog :-(. Oder wie man es demonstriert und warum es in den Tests, die Artem und Linus durchführten, nicht als signifikantes Problem auftauchte.

5. Echte Berichte über „USB-Stick-Stall“-Probleme

Obwohl weder Artem noch Linux einen „USB-Stick-Stall“ gemeldet haben, der das gesamte System betraf, finden wir an anderer Stelle mehrere Berichte darüber. Dazu gehören Berichte aus den letzten Jahren – weit nach der letzten bekannten Lösung.

Ich weiß nicht, was der Unterschied ist. Vielleicht waren ihre Testbedingungen in irgendeiner Weise anders, oder vielleicht wurden seit 2013 ein oder mehrere neue Probleme im Kernel erstellt …

  • https://utcc.utoronto.ca/~cks/space/blog/linux/USBDrivesKillMyPerformance / https://utcc.utoronto.ca/~cks/space/blog/linux/FixingUSBDriveResponsiveness [2017]
  • Warum friert mein PC ein, während ich eine Datei auf einen USB-Stick kopiere? [Januar 2014]
  • Systemverzögerungen bei umfangreichen R/W-Vorgängen auf externen Festplatten [2018]
  • Die Linux-GUI reagiert bei intensiver Festplatten-E/A nicht mehr – was tun? [2019]

6. Das Dirty Limit wurde falsch berechnet [2014]

Im Januar 2014 gab es einen interessanten Fix (angewendet in Kernel v3.14). In der Frage sagten wir, dass das Standardlimit auf 20 % des Arbeitsspeichers festgelegt wurde. Tatsächlich ist es auf 20 % des Speichers eingestellt, der für den Dirty-Page-Cache verfügbar ist. Beispielsweise puffert der Kernel gesendete Daten für TCP/IP-Netzwerk-Sockets. Die Socket-Puffer können nicht gelöscht und durch den Dirty-Page-Cache ersetzt werden :-).

Das Problem war, dass der Kernel austauschbaren Speicher zählte, als ob er Daten zugunsten des Dirty-Page-Cache auslagern könnte. Obwohl dies theoretisch möglich ist, ist der Kernel stark darauf ausgerichtet, Auslagerungen zu vermeiden, und zieht es vor, stattdessen den Seiten-Cache zu löschen. Dieses Problem wurde durch – raten Sie mal – ein Test veranschaulicht, bei dem auf einen langsamen USB-Stick geschrieben wurde und festgestellt wurde, dass dies zu Blockierungen im gesamten System führte :-).

Siehe auch:Linux – Warum die Ausgabe auf 2>&1 und 1>&2 umleiten?

Siehe Re:[Patch 0/2] mm:Reclaim-Stalls mit Heavy Anon und Dirty Cache reduzieren

Die Lösung ist das dirty_ratio wird jetzt nur als Anteil des Datei-Cache behandelt.

Laut dem Kernel-Entwickler, der unter dem Problem litt, „scheinen die Auslösebedingungen ziemlich plausibel – hohe anonische Speicherauslastung mit stark gepuffertem IO und konfiguriertem Swap – und es ist sehr wahrscheinlich, dass dies in freier Wildbahn passiert.“ Das könnte also einige ausmachen Benutzerberichte um 2013 oder früher.

7. Riesige Seitenzuweisungen blockieren auf IO [2011]

Dies war ein weiteres Problem:Riesige Seiten, langsame Laufwerke und lange Verzögerungen (LWN.net, November 2011). Dieses Problem mit riesigen Seiten sollte nun behoben sein.

Außerdem denke ich, dass die meisten aktuellen Linux-PCs entgegen dem, was der Artikel sagt, nicht wirklich riesige Seiten verwenden. Dies könnte sich ab Debian 10 ändern. Aber auch wenn Debian 10 anfängt, wenn möglich riesige Seiten zuzuweisen, scheint es mir klar, dass es keine Verzögerungen geben wird, es sei denn, Sie ändern eine andere Einstellung namens defrag auf „immer“.

8. „Schmutzige Seiten erreichen das Ende der LRU“ [vor 2013]

Ich habe mir das nicht angesehen, aber ich fand es interessant:

mgorman 2011:Dies ist eine neue Art von USB-bezogenem Blockieren, da es auf synchrones Komprimierungsschreiben zurückzuführen ist, bei dem wie in der Vergangenheit das große Problem darin bestand, dass schmutzige
Seiten das Ende der LRU erreichten und durch Reclaim geschrieben wurden .

mgorman 2013:Die Arbeit in diesem allgemeinen Bereich befasste sich mit
solchen Problemen wie schmutzigen Seiten, die das Ende der LRU (übermäßige CPU
-Nutzung)
erreichten

Wenn dies zwei verschiedene Probleme sind, „das Ende der LRU zu erreichen“, dann klingt das erste so, als könnte es sehr schlimm sein. Es hört sich so an, als würde jeder Versuch, Speicher zuzuweisen, verzögert werden, wenn eine schmutzige Seite zur am längsten nicht verwendeten Seite wird, bis das Schreiben dieser schmutzigen Seite abgeschlossen ist.

Was auch immer es bedeutet, er sagt, dass das Problem jetzt behoben ist.

[1] Eine Ausnahme:für eine Weile der Debian-Paketmanager dpkg verwendet sync(), um die Leistung zu verbessern. Dies wurde aufgrund des genauen Problems entfernt, dass sync() extrem lange dauern konnte. Sie wechselten zu einem Ansatz mit sync_file_range() auf Linux. Siehe Ubuntu-Bug #624877, Kommentar 62.

Teil eines früheren Versuchs, diese Frage zu beantworten – dies sollte größtenteils überflüssig sein:

Ich denke, wir können beide Berichte von Artem so erklären, dass sie mit dem Code „No-I/O Dirty Throttling“ übereinstimmen.

Der schmutzige Drosselungscode zielt darauf ab, jedem unterstützenden Gerät einen fairen Anteil am „gesamten Write-Back-Cache“ zu gewähren, „der sich auf seine aktuelle durchschnittliche Schreibgeschwindigkeit im Verhältnis zu den anderen Geräten bezieht“. Diese Formulierung stammt aus der Dokumentation von /sys/class/bdi/.[2]

Im einfachsten Fall wird nur ein Sicherungsgerät beschrieben. In diesem Fall beträgt der faire Anteil des Geräts 100 %. write()-Aufrufe werden gedrosselt, um den gesamten Writeback-Cache zu steuern und auf einem „Sollwert“ zu halten.

Schreibvorgänge werden auf halbem Weg zwischen dirty_background_ratio gedrosselt – der Punkt, der das Schreiben im Hintergrund initiiert – und dirty_ratio – die harte Grenze für den Writeback-Cache. Standardmäßig sind dies 10 % und 20 % des verfügbaren Speichers.

Sie könnten beispielsweise immer noch bis zu 15 % auffüllen, indem Sie nur auf Ihre Hauptfestplatte schreiben. Sie könnten Gigabyte an zwischengespeicherten Schreibvorgängen haben, je nachdem, wie viel RAM Sie haben. An diesem Punkt werden die Aufrufe von write() gedrosselt, um sie an die Writeback-Geschwindigkeit anzupassen – aber das ist kein Problem. Ich gehe davon aus, dass die Hängeprobleme für read()- und fsync()-Aufrufe auftreten, die hinter großen Mengen unabhängiger E/A hängen bleiben. Dies ist das spezifische Problem, das durch den „Writeback Throttling“-Code angesprochen wird. Einige der eingereichten WBT-Patches enthalten Problembeschreibungen, die die schrecklichen Verzögerungen zeigen, die dies verursacht.

Ebenso könnten Sie die 15 % komplett mit Schreibvorgängen auf einen USB-Stick auffüllen. Weitere Write(s) auf den USB werden gedrosselt. Aber die Hauptfestplatte würde keinen ihrer fairen Anteile nutzen. Wenn Sie write() auf Ihrem Hauptdateisystem aufrufen, wird es nicht gedrosselt oder zumindest viel weniger verzögert. Und ich denke, die USB-Write(s) würden noch mehr gedrosselt, um die beiden Writer ins Gleichgewicht zu bringen.

Ich gehe davon aus, dass der gesamte Writeback-Cache vorübergehend über den Sollwert steigen könnte. In einigen anspruchsvolleren Fällen können Sie die harte Grenze für den gesamten Writeback-Cache erreichen. Die feste Grenze beträgt standardmäßig 20 % des verfügbaren Arbeitsspeichers; die Konfigurationsoption ist dirty_ratio / dirty_bytes . Vielleicht können Sie dies erreichen, weil ein Gerät langsamer werden kann (vielleicht aufgrund eines eher zufälligen I/O-Musters) und Dirty Throttling die Geschwindigkeitsänderung nicht sofort erkennt.

[2] Möglicherweise bemerken Sie, dass dieses Dokument vorschlägt, dass Sie dies manuell tun können Begrenzen Sie den Anteil des Writeback-Cache, der für eine bestimmte Partition / ein bestimmtes Dateisystem verwendet werden kann. Die Einstellung heißt /sys/class/bdi/*/max_ratio . Beachten Sie Folgendes:„Wenn das Gerät, das Sie einschränken möchten, das einzige ist, auf das derzeit geschrieben wird, hat die Beschränkung keine große Auswirkung.“


Linux
  1. Was ist der aktuelle Runlevel des Linux-Systems?

  2. Linux – Warum ist kein Rootfs-Dateisystem auf dem System vorhanden?

  3. Linux – Warum kann der Kernel Init nicht ausführen?

  4. Überprüfen Sie die Systemlast unter Linux

  5. Besteht das Problem der Donnernden Herde unter Linux noch?

Einführung in das Linux-Dateisystem

Verwalten von Swap im modernen Linux-System

Die Auswirkungen des Hinzufügens von Benutzern zu einem Linux-System

So ändern Sie die Standard-Shell im Linux-System

Warum tötet der folgende Befehl ein System?

So verwenden Sie den fd-Befehl auf einem Linux-System