GNU/Linux >> Tutoriels Linux >  >> Linux

Linux – Pourquoi des problèmes de « blocage de clé USB » ont-ils été signalés en 2013 ? Pourquoi ce problème n'a-t-il pas été résolu par le code existant "no-i/o Dirty Throttling" ?

Le problème pernicieux du décrochage de la clé USB – LWN.net, novembre 2013.

Artem S. Tashkinov a récemment rencontré un problème qui sera familier à au moins certains lecteurs de LWN. Branchez un périphérique de stockage lent (une clé USB, par exemple, ou un lecteur multimédia) sur une machine Linux et écrivez-y beaucoup de données. L'ensemble du système se bloque simplement , éventuellement pendant quelques minutes.

Cette fois-ci, cependant, Artem a fait une observation intéressante :le système bloquait lors de l'exécution avec un noyau 64 bits, mais aucun problème de ce type n'a été rencontré lors de l'utilisation d'un noyau 32 bits sur le même matériel.

L'article explique qu'avec un noyau 64 bits, le cache de page sale (cache d'écriture différée) était autorisé à atteindre 20 % de la mémoire par défaut. Avec un noyau 32 bits, il était effectivement limité à environ 180 Mo.

Linus a également suggéré de le limiter à ~ 180 Mo sur 64 bits, mais Linux actuel (v4.18) ne le fait pas. Comparez le correctif suggéré par Linus à la fonction actuelle de Linux 4.18. Le plus grand argument contre de tels changements est venu de Dave Chinner. Il a souligné que trop réduire la mise en mémoire tampon entraînerait une fragmentation des systèmes de fichiers. Il a également expliqué que "pour le streaming IO, nous avons généralement besoin d'au moins
5s de cache dirty données pour niveler les retards.”

Je suis confus. Pourquoi le blocage de la clé USB a-t-il provoqué le blocage de tout le système ?

Je suis confus parce que j'ai lu un article précédent décrivant le code fusionné en 2011 (Linux 3.2). Cela montre que le noyau aurait dû contrôler le cache des pages modifiées pour chaque appareil :

Limitation sale sans E/S – LWN.net, 2011

C'est là que le jeu de correctifs de Fengguang entre en jeu. Il tente de créer une boucle de contrôle capable de déterminer le nombre de pages que chaque processus doit être autorisé à salir à un moment donné. Les processus dépassant leur limite sont simplement mis en sommeil pendant un certain temps pour permettre au système d'écriture différée de les rattraper.

[…]

Le but du système est de maintenir le nombre de pages sales au point de consigne ; si les choses sortent de la ligne, des quantités croissantes de force seront appliquées pour ramener les choses là où elles devraient être.

[…]

Cependant, ce ratio ne peut pas vraiment être calculé sans prendre en compte le dispositif de support (BDI). Un processus peut salir des pages stockées sur un BDI donné, et le système peut avoir une surabondance de pages sales en ce moment, mais la sagesse de limiter ce processus dépend également du nombre de pages sales existantes pour ce BDI. […] Un BDI avec peu de pages sales peut rapidement éliminer son arriéré, il peut donc probablement se permettre d'en avoir quelques autres, même si le système est un peu plus sale qu'on ne le souhaiterait. Ainsi, l'ensemble de correctifs modifie le pos_ratio calculé pour un BDI spécifique à l'aide d'une formule compliquée examinant à quelle distance ce BDI spécifique se trouve de son propre point de consigne et de sa bande passante observée. Le résultat final est un pos_ratio modifié décrivant si le système doit salir plus ou moins de pages soutenues par le BDI donné, et de combien.

Le contrôle par appareil a été ajouté encore plus tôt :limitation d'écriture plus intelligente, 2007 LWN.net. [PATCH 0/23] par périphérique sale throttling -v10. Il a été fusionné dans la version Linux 2.6.24.

Réponse acceptée :

  1. L'article de 2013 est faux
  2. Une erreur dans LWN ? Êtes-vous sûr ?
  3. Longues files d'attente dans les périphériques d'E/S, créées par la réécriture "en arrière-plan"
  4. Limites de la "régulation sale sans E/S" ?
  5. Rapports authentiques de problèmes de "blocage de clé USB"
  6. La limite sale a été calculée de manière incorrecte [2014]
  7. Blocage d'énormes allocations de pages sur IO [2011]
  8. "Pages sales atteignant la fin de la LRU" ? [pré-2013]

1. L'article de 2013 est faux

L'article « Décrochage de la clé USB » vous donne une impression très trompeuse. Il déforme à la fois le rapport original et la série de réponses.

Artem n'a pas signalé que tout le système était suspendu lorsqu'il a vidé les écritures en cache sur une clé USB. Son rapport initial se plaignait seulement que l'exécution de la commande "sync" pouvait prendre jusqu'à "des dizaines de minutes". Cette distinction est rendue explicite dans une réponse de Linus Torvalds :

C'est en fait très facile à reproduire en prenant simplement votre clé USB
moyenne et en essayant d'y écrire. Je viens de le faire avec une image ISO
aléatoire, et c'est douloureux. Et ce n'est pas que c'est pénible de faire
la plupart des autres choses en arrière-plan, mais s'il vous arrive d'exécuter
tout ce qui se "synchronise" (et cela se produit dans les scripts), la chose est juste
s'arrête brutalement.
Pendant quelques minutes.

2. Une erreur dans LWN ? Êtes-vous sûr ?

Jon Corbet avait quinze ans d'expérience, rapportant le développement du noyau Linux sur une base hebdomadaire. Je m'attendais à ce que l'article soit au moins fermé pour bien faire les choses, dans un certain sens. Je souhaite donc traiter les deux enregistrements différents et rechercher les points détaillés sur lesquels ils sont d'accord ou non.

J'ai lu toute la discussion originale, en utilisant les archives sur lore.kernel.org. Je pense que les messages sont assez clairs.

Je suis certain à 100% que l'article interprète mal la discussion. Dans les commentaires sous l'article, au moins deux lecteurs ont répété la fausse affirmation dans leurs propres mots, et personne ne les a corrigés. L'article continue cette confusion dans le troisième paragraphe :

Toutes ces données obstruent les files d'attente d'E/S, retardant éventuellement d'autres opérations. Et, dès que quelqu'un appelle sync(), les choses s'arrêtent jusqu'à ce que toute la file d'attente soit écrite.

Cela pourrait être une confusion de la part de Linus disant "la chose s'arrête brutalement". "La chose" fait référence à "tout ce qui fait de la sync “. Mais Corbet écrit comme si « la chose » signifiait « tout le système ».

Selon Linus, il s'agit d'un problème du monde réel. Mais la grande majorité des "choses" ne le font pas appeler l'opération sync() à l'échelle du système.[1]

Pourquoi Corbet pourrait-il confondre cela avec "l'ensemble du système" ? Je suppose qu'il y a eu un certain nombre de problèmes, et après un certain temps, il devient difficile de les garder tous séparés dans votre tête :-). Et bien que LWN ait décrit le développement de la limitation sale par périphérique (et par processus), en général, je suppose qu'il n'y a pas beaucoup d'écrits sur ces détails. De nombreux documents ne décrivent que les paramètres de limite de saleté globale.

3. Longues files d'attente dans les périphériques d'E/S, créées par la réécriture "en arrière-plan"

Artem a publié un deuxième rapport dans le fil, où "le serveur se bloque presque et les autres demandes d'E/S prennent beaucoup plus de temps à se terminer".

Connexe :Linux – Routage via iptables ?

Ce deuxième rapport ne correspond pas aux affirmations concernant un blocage de clé USB. C'est arrivé après la création d'un fichier de 10 Go sur un interne disque. C'est un problème différent.

Le rapport n'a pas confirmé si cela pouvait être amélioré en modifiant les limites sales. Et il y a une analyse plus récente de cas comme celui-ci. Il y a un problème important lorsqu'il obstrue la file d'attente d'E/S de votre disque principal. Vous pouvez subir de longs retards sur un disque sur lequel vous comptez constamment, pour charger le code du programme à la demande, enregistrer des documents et des données d'application à l'aide de write() + fsync(), etc.

Vers une écriture en arrière-plan moins gênante – LWN.net, 2016

Lorsque le code de gestion de la mémoire décide d'écrire une plage de données modifiées, le résultat est une demande d'E/S soumise au sous-système de bloc. Cette demande peut passer un certain temps dans le planificateur d'E/S, mais elle est finalement envoyée au pilote du périphérique de destination.

Le problème est que, s'il y a beaucoup de données sales à écrire, il peut y avoir un grand nombre (par exemple des milliers) de requêtes en file d'attente pour le périphérique. Même un lecteur raisonnablement rapide peut prendre un certain temps pour traiter autant de demandes. Si une autre activité (cliquer sur un lien dans un navigateur Web, par exemple, ou lancer une application) génère des requêtes d'E/S sur le même périphérique de bloc, ces requêtes vont à l'arrière de cette longue file d'attente et peuvent ne pas être traitées pendant un certain temps. Si plusieurs requêtes synchrones sont générées (défauts de page d'une application nouvellement lancée, par exemple), chacune de ces requêtes peut, à son tour, devoir passer par cette longue file d'attente. C'est le point où les choses semblent s'arrêter.

[…]

La plupart des pilotes de bloc gèrent également leurs propres files d'attente en interne. Ces files d'attente de niveau inférieur peuvent être particulièrement problématiques car, au moment où une requête y parvient, elle n'est plus soumise au contrôle du planificateur d'E/S (s'il existe un planificateur d'E/S).

Les correctifs ont été fusionnés pour améliorer cela fin 2016 (Linux 4.10). Ce code est appelé « limitation de l'écriture différée » ou WBT. Recherche sur le Web pour wbt_lat_usec trouve également quelques autres histoires à ce sujet. (La doc initiale parle de wb_lat_usec , mais il est obsolète). Sachez que la limitation de l'écriture différée ne fonctionne pas avec les planificateurs d'E/S CFQ ou BFQ. CFQ a été populaire en tant que planificateur d'E/S par défaut, y compris dans les versions de noyau par défaut jusqu'à Linux v4.20. CFQ est supprimé dans le noyau v5.0.

Il y avait des tests pour illustrer le problème (et la solution prototype) à la fois sur un SSD (qui ressemblait à NVMe) et sur un "disque dur normal". Le disque dur n'était "pas aussi mauvais que les périphériques à profondeur de file d'attente plus profonde, où nous avons des E/S extrêmement rafales".

Je ne suis pas sûr des "milliers" de requêtes en file d'attente, mais il existe au moins des périphériques NVMe qui peuvent mettre en file d'attente des centaines de requêtes. La plupart des disques durs SATA permettent la mise en file d'attente de 32 requêtes (« NCQ »). Bien sûr, le disque dur prendrait plus de temps pour traiter chaque requête.

4. Limitations de la "régulation sale sans E/S" ?

"L'étranglement sale sans E / S" est un système d'ingénierie assez complexe. Il a également été modifié au fil du temps. Je suis sûr qu'il y en avait, et qu'il y en a toujours, quelques limitations à l'intérieur de ce code.

La rédaction de LWN, les commentaires sur le code/correctif et les diapositives de la présentation détaillée montrent qu'un grand nombre de scénarios ont été envisagés. Cela inclut la fameuse clé USB lente v.s. entraînement principal rapide. Les cas de test incluent l'expression "1000 dd simultanés" (c'est-à-dire des écrivains séquentiels).

Jusqu'à présent, je ne sais pas comment démontrer et reproduire toute limitation à l'intérieur du code de limitation sale.

J'ai vu plusieurs descriptions de correctifs de problèmes qui étaient en dehors du code de limitation sale. Le correctif le plus récent que j'ai trouvé remonte à 2014 - voir les sections suivantes. Dans le fil de discussion sur lequel LWN fait rapport, nous apprenons :

Dans les dernières versions, des problèmes comme celui-ci étaient
causés par des problèmes de récupération qui en avaient marre de voir beaucoup de pages sales
/ under writeback et finissaient par rester bloqués en attendant la fin de l'IO.

[…] Le script systemtap a détecté ce type de zones et je
pense qu'elles sont corrigées.

Mel Gorman a également déclaré qu'il y avait des "problèmes en suspens".

Il y a quand même des problèmes. Si toutes les pages sales étaient sauvegardées par un appareil lent, la limitation sale finira toujours par provoquer des blocages dans l'équilibrage des pages sales […]

Ce passage était la seule chose que j'ai pu trouver dans le fil de discussion rapporté, qui vient n'importe où près de sauvegarder l'interprétation LWN. J'aimerais comprendre à quoi cela faisait référence :-(. Ou comment le démontrer, et pourquoi cela ne semble pas être un problème important dans les tests effectués par Artem et Linus.

5. Rapports authentiques de problèmes de "blocage de clé USB"

Bien que ni Artem ni Linux n'aient signalé un "blocage de clé USB" affectant l'ensemble du système, nous pouvons trouver plusieurs rapports à ce sujet ailleurs. Cela inclut les rapports des dernières années, bien après le dernier correctif connu.

Je ne sais pas quelle est la différence. Peut-être que leurs conditions de test étaient différentes d'une certaine manière, ou peut-être y a-t-il de nouveaux problèmes créés dans le noyau depuis 2013…

  • https://utcc.utoronto.ca/~cks/space/blog/linux/USBDrivesKillMyPerformance / https://utcc.utoronto.ca/~cks/space/blog/linux/FixingUSBDriveResponsiveness [2017]
  • Pourquoi mon PC se bloque-t-il pendant que je copie un fichier sur une clé USB ? [Janvier 2014]
  • Le système est à la traîne lors d'opérations R/W volumineuses sur des disques externes [2018]
  • L'interface graphique de Linux ne répond plus lorsque vous effectuez des E/S de disque intensives. Que régler ? [2019]

6. La limite sale a été mal calculée [2014]

Il y a eu un correctif intéressant en janvier 2014 (appliqué dans le noyau v3.14). Dans la question, nous avons dit que la limite par défaut était fixée à 20 % de la mémoire. En fait, il est défini sur 20 % de la mémoire disponible pour le cache des pages modifiées. Par exemple, les tampons du noyau envoyaient des données pour les sockets réseau TCP/IP. Les tampons de socket ne peuvent pas être supprimés et remplacés par un cache de page sale :-).

Le problème était que le noyau comptait la mémoire échangeable, comme s'il pouvait échanger des données en faveur du cache de pages sales. Bien que cela soit possible en théorie, le noyau est fortement biaisé pour éviter l'échange et préfère supprimer le cache de page à la place. Ce problème a été illustré par - devinez quoi - un test impliquant l'écriture sur une clé USB lente, et en remarquant que cela provoquait des blocages sur l'ensemble du système :-).

Connexe :Linux – Pourquoi rediriger la sortie vers 2>&1 et 1>&2 ?

Voir Re :[patch 0/2] mm :réduire les blocages de récupération avec anon lourd et cache sale

Le correctif est que dirty_ratio est désormais traité comme une proportion du cache de fichiers uniquement.

Selon le développeur du noyau qui a rencontré le problème, "les conditions de déclenchement semblent tout à fait plausibles - une utilisation élevée de la mémoire avec des E/S tamponnées lourdes et un swap configuré - et il est fort probable que cela se produise dans la nature". Cela pourrait donc expliquer certains rapports d'utilisateurs vers 2013 ou avant.

7. Blocage d'énormes allocations de pages sur IO [2011]

C'était un autre problème :des pages volumineuses, des lecteurs lents et de longs délais (LWN.net, novembre 2011). Ce problème avec les pages volumineuses devrait maintenant être résolu.

De plus, malgré ce que dit l'article, je pense que la plupart des PC Linux actuels n'utilisent pas vraiment de pages volumineuses. Cela pourrait changer à partir de Debian 10. Cependant, même si Debian 10 commence à allouer des pages volumineuses dans la mesure du possible, il me semble clair qu'elle n'imposera aucun retard, à moins que vous ne changiez un autre paramètre appelé defrag à "toujours".

8. "Pages sales atteignant la fin de la LRU" [pre-2013]

Je n'ai pas étudié cela, mais j'ai trouvé cela intéressant :

mgorman 2011 :Il s'agit d'un nouveau type de décrochage lié à l'USB car il est dû à l'écriture de compactage synchrone où, comme par le passé, le gros problème était les pages sales
atteignant la fin du LRU et étant écrites par reclaim .

mgorman 2013 :Le travail dans ce domaine général a traité
des problèmes tels que les pages sales atteignant la fin de la LRU (utilisation excessive du processeur
)

S'il s'agit de deux problèmes différents "atteindre la fin du LRU", alors le premier semble être très grave. Il semble que lorsqu'une page sale devient la page la moins récemment utilisée, toute tentative d'allocation de mémoire serait retardée, jusqu'à ce que cette page sale ait fini d'être écrite.

Quoi que cela signifie, il dit que le problème est maintenant résolu.

[1] Une exception :pendant un certain temps, le gestionnaire de paquets Debian dpkg utilisé sync() pour améliorer les performances. Cela a été supprimé, en raison du problème exact que sync() pouvait prendre extrêmement longtemps. Ils sont passés à une approche utilisant sync_file_range() sur Linux. Voir le bogue Ubuntu #624877, commentaire 62.

Partie d'une précédente tentative de réponse à cette question - cela devrait être redondant :

Je pense que nous pouvons expliquer les deux rapports d'Artem comme étant cohérents avec le code "No-I/O dirty throttling".

Le code de limitation sale vise à accorder à chaque périphérique de support une part équitable du "cache de réécriture total", "qui se rapporte à sa vitesse d'écriture moyenne actuelle par rapport aux autres périphériques". Cette formulation provient de la documentation de /sys/class/bdi/.[2]

Dans le cas le plus simple, un seul périphérique de support est en cours d'écriture. Dans ce cas, la part équitable de l'appareil est de 100 %. les appels write() sont limités pour contrôler le cache d'écriture différée global et le maintenir à un "point de consigne".

Les écritures commencent à être limitées à mi-chemin entre dirty_background_ratio – le point qui initie l'écriture en arrière-plan – et dirty_ratio – la limite stricte du cache en écriture différée. Par défaut, ce sont 10 % et 20 % de la mémoire disponible.

Par exemple, vous pouvez toujours remplir jusqu'à 15 % d'écriture sur votre disque principal uniquement. Vous pourriez avoir des gigaoctets d'écritures en cache, selon la quantité de RAM dont vous disposez. À ce stade, les appels write() commenceront à être limités pour correspondre à la vitesse de réécriture - mais ce n'est pas un problème. Je m'attends à ce que les problèmes de blocage concernent les appels read() et fsync(), qui restent bloqués derrière de grandes quantités d'E/S non liées. C'est le problème spécifique résolu par le code de "limitation de l'écriture différée". Certaines des soumissions de correctifs WBT incluent des descriptions de problèmes, montrant les retards horribles que cela entraîne.

De même, vous pouvez remplir entièrement les 15 % avec des écritures sur une clé USB. D'autres écritures sur l'USB seront limitées. Mais le disque principal n'utiliserait rien de sa juste part. Si vous commencez à appeler write() sur votre système de fichiers principal, il ne sera pas limité, ou du moins sera beaucoup moins retardé. Et je pense que les écritures USB seraient encore plus limitées, pour équilibrer les deux graveurs.

Je m'attends à ce que le cache d'écriture différée global puisse temporairement dépasser le point de consigne. Dans certains cas plus exigeants, vous pouvez atteindre la limite stricte du cache d'écriture différée global. La limite stricte est par défaut de 20 % de la mémoire disponible ; l'option de configuration est dirty_ratio / dirty_bytes . Vous pouvez peut-être le faire parce qu'un périphérique peut ralentir (peut-être à cause d'un modèle d'E/S plus aléatoire), et la limitation sale ne reconnaît pas immédiatement le changement de vitesse.

[2] Vous remarquerez peut-être que ce document suggère que vous pouvez manuellement limiter la proportion de cache en écriture différée, qui peut être utilisée pour une partition/un système de fichiers spécifique. Le paramètre s'appelle /sys/class/bdi/*/max_ratio . Sachez que "si l'appareil que vous souhaitez limiter est le seul sur lequel on écrit actuellement, la limitation n'a pas un grand effet".


Linux
  1. Linux - Pourquoi n'y a-t-il pas de système de fichiers Rootfs présent sur le système ?

  2. Linux - Pourquoi les utilitaires Linux n'utilisent-ils pas un appel système pour obtenir l'heure actuelle ?

  3. Pourquoi la commande suivante tue-t-elle un système ?

  4. Quelles parties de ce code assembleur HelloWorld sont essentielles si je devais écrire le programme en assembleur ?

  5. Linux :'Username' n'est pas dans le fichier sudoers. Cet incident sera signalé

Introduction au système de fichiers Linux

Gestion du swap dans le système Linux moderne

Les effets de l'ajout d'utilisateurs à un système Linux

Comment changer le shell par défaut dans le système Linux

Comment utiliser la commande fd sur le système Linux

Pourquoi l'utilisateur le plus puissant d'un système Unix/Linux s'appelle-t-il "root ?"