GNU/Linux >> Linux Esercitazione >  >> Linux

Linux:perché nel 2013 sono stati segnalati problemi di "stallo della chiavetta USB"? Perché questo problema non è stato risolto dal codice esistente "no-i/o Dirty Throttling"?

Il pernicioso problema dello stallo della chiavetta USB – LWN.net, novembre 2013.

Artem S. Tashkinov ha recentemente riscontrato un problema che sarà familiare almeno ad alcuni lettori di LWN. Collega un dispositivo di archiviazione lento (una chiavetta USB, per esempio, o un lettore multimediale) a una macchina Linux e scrivici molti dati. L'intero sistema si blocca , possibilmente per minuti.

Questa volta, tuttavia, Artem ha fatto un'osservazione interessante:il sistema si bloccherebbe quando girava con un kernel a 64 bit, ma non si verificava alcun problema quando si utilizzava un kernel a 32 bit sullo stesso hardware.

L'articolo spiega che con un kernel a 64 bit, la cache della pagina sporca (cache di writeback) poteva crescere fino al 20% della memoria per impostazione predefinita. Con un kernel a 32 bit, era effettivamente limitato a ~180 MB.

Linus ha suggerito di limitarlo a ~180 MB anche a 64 bit, tuttavia l'attuale Linux (v4.18) non lo fa. Confronta la patch suggerita da Linus con la funzione corrente in Linux 4.18. Il più grande argomento contro tali cambiamenti è venuto da Dave Chinner. Ha sottolineato che una riduzione eccessiva del buffering causerebbe la frammentazione dei filesystem. Ha anche spiegato che "per lo streaming di IO in genere abbiamo bisogno di almeno
5 secondi di sporco nella cache dati per compensare i ritardi."

Sono confuso. Perché lo stallo della chiavetta USB ha causato il blocco dell'intero sistema?

Sono confuso perché ho letto un articolo precedente che descriveva il codice unito nel 2011 (Linux 3.2). Mostra che il kernel avrebbe dovuto controllare la cache della pagina sporca in base al dispositivo:

Limitazione sporca senza I/O – LWN.net, 2011

È qui che entra in gioco il set di patch di Fengguang. Sta tentando di creare un ciclo di controllo in grado di determinare quante pagine ogni processo dovrebbe sporcare in un dato momento. I processi che superano il limite vengono semplicemente messi in pausa per un po' per consentire al sistema di writeback di raggiungerli.

[…]

L'obiettivo del sistema è mantenere il numero di pagine sporche al valore impostato; se le cose vanno fuori linea, verrà applicata una forza crescente per riportare le cose dove dovrebbero essere.

[…]

Questo rapporto non può essere realmente calcolato, tuttavia, senza tenere conto del dispositivo di supporto (BDI). Un processo potrebbe sporcare le pagine memorizzate su un dato BDI e il sistema potrebbe avere un eccesso di pagine sporche al momento, ma la saggezza di limitare quel processo dipende anche da quante pagine sporche esistono per quel BDI. […] Un BDI con poche pagine sporche può cancellare rapidamente il suo backlog, quindi probabilmente può permettersi di averne qualcuna in più, anche se il sistema è un po' più sporco di quanto si potrebbe desiderare. Quindi il set di patch modifica la pos_ratio calcolata per un BDI specifico utilizzando una formula complicata che esamina la distanza di quel BDI specifico dal proprio setpoint e dalla larghezza di banda osservata. Il risultato finale è un pos_ratio modificato che descrive se il sistema deve sporcare più o meno pagine supportate dal BDI specificato e di quanto.

Il controllo per dispositivo è stato aggiunto anche prima di questo:limitazione della scrittura più intelligente, 2007 LWN.net. [PATCH 0/23] per dispositivo sporco throttling -v10. È stato unito alla versione Linux 2.6.24.

Risposta accettata:

  1. L'articolo del 2013 è sbagliato
  2. Un errore in LWN? Sei sicuro?
  3. Lunghe code nei dispositivi I/O, create dal writeback "in background"
  4. Limitazioni del "no-I/O dirty throttling"?
  5. Report autentici di problemi di "stallo della chiavetta USB"
  6. Il limite sporco è stato calcolato in modo errato [2014]
  7. Blocco di allocazioni di pagine enormi su IO [2011]
  8. "Pagine sporche che raggiungono la fine della LRU"? [pre-2013]

1. L'articolo del 2013 è sbagliato

L'articolo "Stallo della chiavetta USB" ti dà un'impressione molto fuorviante. Rappresenta in modo errato sia il rapporto originale che la serie di risposte.

Artem non ha segnalato che l'intero sistema si è bloccato quando ha scaricato le scritture memorizzate nella cache su una chiavetta USB. Il suo rapporto originale si lamentava solo del fatto che l'esecuzione del comando "sync" poteva richiedere fino a "dozzine di minuti". Questa distinzione è esplicitata in una risposta di Linus Torvalds:

In realtà è davvero facile da riprodurre semplicemente prendendo la tua chiave USB
media e provando a scriverci. L'ho appena fatto con un'immagine ISO
casuale ed è doloroso. E non è che sia doloroso fare
la maggior parte delle altre cose in background, ma se ti capita di eseguire
qualsiasi cosa che "sincronizza" (e accade negli script), la cosa semplicemente
si ferma bruscamente.
Per minuti.

2. Un errore in LWN? Sei sicuro?

Jon Corbet aveva quindici anni di esperienza, riportando lo sviluppo del kernel Linux su base settimanale. Mi aspettavo che l'articolo fosse almeno vicino per farlo bene, in un certo senso. Quindi voglio elaborare i due diversi record e cercare i punti dettagliati in cui sono d'accordo o in disaccordo.

Ho letto tutta la discussione originale, usando gli archivi su lore.kernel.org. Penso che i messaggi siano abbastanza chiari.

Sono sicuro al 100% che l'articolo interpreta male la discussione. Nei commenti sotto l'articolo, almeno due lettori hanno ripetuto la falsa affermazione con le loro stesse parole e nessuno le ha corrette. L'articolo continua questa confusione nel terzo paragrafo:

Tutti questi dati intasano le code di I/O, eventualmente ritardando altre operazioni. E, non appena qualcuno chiama sync(), le cose si fermano finché l'intera coda non viene scritta.

Questa potrebbe essere confusione da parte di Linus che dice "la cosa si ferma bruscamente". "La cosa" si riferisce a "qualsiasi cosa che sync “. Ma Corbet scrive come se “la cosa” significasse “l'intero sistema”.

Secondo Linus, questo è un problema del mondo reale. Ma la stragrande maggioranza delle "cose" non chiamata nell'operazione sync() a livello di sistema.[1]

Perché Corbet potrebbe confonderlo con "l'intero sistema"? Immagino che ci siano stati un certo numero di problemi, e dopo un po' diventa difficile tenerli tutti separati nella tua testa :-). E sebbene LWN abbia descritto lo sviluppo del throttling sporco per dispositivo (e per processo), in generale suppongo che non si sia scritto molto su tali dettagli. Molti documenti descrivono solo le impostazioni del limite di sporco globale.

3. Code lunghe nei dispositivi I/O, create dal writeback "in background"

Artem ha pubblicato un secondo rapporto nel thread, in cui "il server è quasi in stallo e altre richieste di I/O richiedono molto più tempo per essere completate".

Correlati:Linux – Routing tramite iptables?

Questo secondo rapporto non corrisponde alle affermazioni su un blocco di una chiavetta USB. È successo dopo aver creato un file da 10 GB su un interno disco. Questo è un problema diverso.

Il rapporto non ha confermato se ciò potesse essere migliorato modificando i limiti di sporco. E c'è un'analisi più recente di casi come questo. C'è un problema significativo quando intasa la coda di I/O del tuo disco principale. Puoi subire lunghi ritardi su un disco su cui fai costantemente affidamento, per caricare il codice del programma su richiesta, salvare documenti e dati delle app usando write() + fsync(), ecc.

Verso un writeback in background meno fastidioso — LWN.net, 2016

Quando il codice di gestione della memoria decide di scrivere un intervallo di dati sporchi, il risultato è una richiesta di I/O inviata al sottosistema a blocchi. Tale richiesta potrebbe trascorrere del tempo nello scheduler I/O, ma alla fine viene inviata al driver per il dispositivo di destinazione.

Il problema è che, se ci sono molti dati sporchi da scrivere, potrebbe finire per esserci un numero enorme (come in migliaia) di richieste in coda per il dispositivo. Anche un'unità ragionevolmente veloce può richiedere del tempo per elaborare così tante richieste. Se qualche altra attività (ad esempio, fare clic su un collegamento in un browser Web o avviare un'applicazione) genera richieste di I/O sullo stesso dispositivo a blocchi, tali richieste vanno in fondo a quella lunga coda e potrebbero non essere gestite per un po' di tempo. Se vengono generate più richieste sincrone, ad esempio errori di pagina da un'applicazione appena avviata, ciascuna di queste richieste potrebbe, a sua volta, dover passare attraverso questa lunga coda. Questo è il punto in cui le cose sembrano fermarsi.

[…]

La maggior parte dei driver di blocco mantiene anche le proprie code internamente. Quelle code di livello inferiore possono essere particolarmente problematiche poiché, nel momento in cui una richiesta arriva, non è più soggetta al controllo dello scheduler I/O (se è presente uno scheduler I/O).

Le patch sono state unite per migliorarlo alla fine del 2016 (Linux 4.10). Questo codice è denominato "limitazione del writeback" o WBT. Ricerca sul Web di wbt_lat_usec trova anche alcune altre storie su questo. (Il documento iniziale scrive di wb_lat_usec , ma non è aggiornato). Tenere presente che la limitazione del writeback non funziona con gli scheduler I/O CFQ o BFQ. CFQ è stato popolare come pianificatore di I/O predefinito, incluso nelle build del kernel predefinite fino a Linux v4.20. CFQ è stato rimosso nel kernel v5.0.

C'erano test per illustrare il problema (e la soluzione prototipo) sia su un SSD (che sembrava NVMe) che su un "normale hard disk". Il disco rigido "non era così male come i dispositivi con profondità di coda più profonda, dove abbiamo un IO estremamente burst".

Non sono sicuro delle "migliaia" di richieste in coda, ma ci sono almeno dispositivi NVMe che possono mettere in coda centinaia di richieste. La maggior parte dei dischi rigidi SATA consente di accodare 32 richieste ("NCQ"). Ovviamente il disco rigido impiegherebbe più tempo per completare ogni richiesta.

4. Limitazioni del "no-I/O dirty throttling"?

"No-I/O dirty throttling" è un sistema ingegnerizzato piuttosto complesso. È stato anche modificato nel tempo. Sono sicuro che c'erano e ci sono ancora alcuni limitazioni all'interno di questo codice.

Il resoconto LWN, i commenti sul codice/la patch e le diapositive della presentazione dettagliata mostrano che è stato considerato un gran numero di scenari. Ciò include la famigerata chiavetta USB lenta vs. azionamento principale veloce. I casi di test includono la frase "1000 dd simultanei" (cioè autori sequenziali).

Finora, non so come dimostrare e riprodurre alcuna limitazione all'interno del codice di limitazione sporca.

Ho visto diverse descrizioni di soluzioni di problemi che erano al di fuori del codice di limitazione sporco. La correzione più recente che ho trovato è stata nel 2014 – vedere le sezioni successive. Nel thread su cui sta segnalando LWN, apprendiamo:

Nelle ultime versioni problemi come questo sono stati
causati da problemi di reclamo che si sono stufati vedendo molte pagine sporche
/ sotto le pagine di writeback e sono finite bloccate in attesa del termine dell'IO.

[…] Lo script systemtap ha catturato quel tipo di aree e
credo che siano state sistemate.

Mel Gorman ha anche affermato che c'erano alcuni "problemi in sospeso".

Ci sono ancora problemi però. Se tutte le pagine sporche sono state supportate da un dispositivo lento, la limitazione dello sporco alla fine causerà ancora stalli nel bilanciamento delle pagine sporche […]

Questo passaggio è stata l'unica cosa che ho trovato nel thread di discussione riportato, che si avvicina a sostenere l'interpretazione LWN. Vorrei aver capito a cosa si riferiva :-(. O come dimostrarlo, e perché non sembrava essere un problema significativo nei test eseguiti da Artem e Linus.

5. Rapporti autentici di problemi di "stallo della chiavetta USB"

Sebbene né Artem né Linux abbiano segnalato uno "stallo della chiavetta USB" che ha interessato l'intero sistema, possiamo trovare diversi rapporti in merito altrove. Ciò include i rapporti degli ultimi anni, ben dopo l'ultima correzione nota.

Non so quale sia la differenza. Forse le loro condizioni di test erano diverse in qualche modo, o forse ci sono dei nuovi problemi creati nel kernel dal 2013...

  • https://utcc.utoronto.ca/~cks/space/blog/linux/USBDrivesKillMyPerformance / https://utcc.utoronto.ca/~cks/space/blog/linux/FixingUSBDriveResponsiveness [2017]
  • Perché il mio PC si blocca mentre sto copiando un file su una pendrive? [gennaio 2014]
  • Il sistema è in ritardo durante l'esecuzione di operazioni R/W di grandi dimensioni su dischi esterni [2018]
  • L'interfaccia grafica di Linux non risponde molto quando si esegue un pesante I/O del disco:cosa regolare? [2019]

6. Il limite sporco è stato calcolato in modo errato [2014]

C'è stata una soluzione interessante a gennaio 2014 (applicata nel kernel v3.14). Nella domanda, abbiamo detto che il limite predefinito era impostato sul 20% della memoria. In realtà, è impostato sul 20% della memoria disponibile per la cache della pagina sporca. Ad esempio, i buffer del kernel hanno inviato i dati per i socket di rete TCP/IP. I buffer dei socket non possono essere eliminati e sostituiti con cache di pagine sporche :-).

Il problema era che il kernel stava contando la memoria sostituibile, come se potesse scambiare i dati a favore della cache delle pagine sporche. Sebbene ciò sia possibile in teoria, il kernel è fortemente prevenuto per evitare lo scambio e preferisce invece eliminare la cache delle pagine. Questo problema è stato illustrato da - indovina un po' - un test che prevedeva la scrittura su una chiavetta USB lenta e la nota che causava stalli nell'intero sistema :-).

Correlati:Linux – Perché reindirizzare l'output a 2>&1 e 1>&2?

Vedi Re:[patch 0/2] mm:riduci gli stalli di recupero con anon pesanti e cache sporca

La correzione è che dirty_ratio ora viene considerato solo come una proporzione della cache dei file.

Secondo lo sviluppatore del kernel che ha subito il problema, "le condizioni di trigger sembrano abbastanza plausibili - utilizzo elevato della memoria anon con IO bufferizzato pesante e swap configurato - ed è molto probabile che ciò stia accadendo in natura". Quindi questo potrebbe spiegare alcuni rapporti degli utenti intorno al 2013 o prima.

7. Enormi allocazioni di pagine che bloccano su IO [2011]

Questo era un altro problema:pagine enormi, unità lente e lunghi ritardi (LWN.net, novembre 2011). Questo problema con pagine enormi ora dovrebbe essere risolto.

Inoltre, nonostante ciò che dice l'articolo, penso che la maggior parte degli attuali PC Linux non utilizzi davvero pagine enormi. Questo potrebbe cambiare a partire da Debian 10. Tuttavia, anche se Debian 10 inizia ad allocare pagine enormi ove possibile, mi sembra chiaro che non imporrà alcun ritardo, a meno che tu non modifichi un'altra impostazione chiamata defrag a “sempre”.

8. “Pagine sporche che raggiungono la fine della LRU” [pre-2013]

Non ho esaminato questo, ma l'ho trovato interessante:

mgorman 2011:Questo è un nuovo tipo di stallo relativo all'USB perché è dovuto alla scrittura di compattazione sincrona dove come in passato il grosso problema era sporco
le pagine che raggiungevano la fine della LRU e venivano scritte per reclaim .

mgorman 2013:Il lavoro in quell'area generale ha affrontato
problemi come pagine sporche che raggiungono la fine della LRU (utilizzo eccessivo della CPU
)

Se si tratta di due diversi problemi di "raggiungere la fine della LRU", il primo sembra che potrebbe essere molto grave. Sembra che quando una pagina sporca diventa la pagina utilizzata meno di recente, qualsiasi tentativo di allocare memoria verrebbe ritardato, fino al termine della scrittura di quella pagina sporca.

Qualunque cosa significhi, dice che il problema è stato risolto.

[1] Un'eccezione:per un po', il gestore di pacchetti Debian dpkg utilizzato sync() per migliorare le prestazioni. Questo è stato rimosso, a causa del problema esatto che sync() potrebbe richiedere molto tempo. Sono passati a un approccio usando sync_file_range() su Linux. Vedi il bug di Ubuntu n. 624877, commento 62.

Parte di un precedente tentativo di rispondere a questa domanda, dovrebbe essere per lo più ridondante:

Penso che possiamo spiegare entrambi i rapporti di Artem come coerenti con il codice "No-I/O dirty throttling".

Il codice di limitazione sporca mira a consentire a ciascun dispositivo di supporto una buona quota della "cache di riscrittura totale", "che si riferisce alla sua velocità di riscrittura media attuale rispetto agli altri dispositivi". Questa frase proviene dalla documentazione di /sys/class/bdi/.[2]

Nel caso più semplice, viene scritto solo un dispositivo di supporto. In tal caso, la quota equa del dispositivo è del 100%. le chiamate write() sono limitate per controllare la cache di writeback complessiva e mantenerla su un "setpoint".

Le scritture iniziano a essere limitate a metà strada tra dirty_background_ratio – il punto che avvia la scrittura in background – e dirty_ratio – il limite rigido sulla cache di writeback. Per impostazione predefinita, sono il 10% e il 20% della memoria disponibile.

Ad esempio, puoi ancora riempire fino al 15% scrivendo solo sul tuo disco principale. Potresti avere gigabyte di scritture memorizzate nella cache, in base alla quantità di RAM che hai. A quel punto, le chiamate write() inizieranno a essere limitate per corrispondere alla velocità di writeback, ma non è un problema. Mi aspetto che i problemi di blocco siano per le chiamate read() e fsync(), che rimangono bloccate dietro grandi quantità di IO non correlato. Questo è il problema specifico affrontato dal codice "writeback throttling". Alcuni degli invii di patch WBT includono descrizioni dei problemi, che mostrano gli orribili ritardi che ciò provoca.

Allo stesso modo, potresti riempire interamente il 15% con scritture su una chiavetta USB. Ulteriori scritture sull'USB verranno limitate. Ma il disco principale non utilizzerebbe alcuna parte della sua giusta quota. Se inizi a chiamare write() sul tuo filesystem principale, non verrà limitato, o almeno verrà ritardato molto meno. E penso che le scritture USB () verrebbero ulteriormente limitate, per bilanciare i due writer.

Mi aspetto che la cache di writeback complessiva possa salire temporaneamente al di sopra del setpoint. In alcuni casi più impegnativi, puoi raggiungere il limite massimo della cache di writeback complessiva. Il limite fisso predefinito è il 20% della memoria disponibile; l'opzione di configurazione è dirty_ratio / dirty_bytes . Forse puoi farlo perché un dispositivo può rallentare (forse a causa di uno schema di I/O più casuale) e il throttling sporco non riconosce immediatamente il cambiamento di velocità.

[2] Potresti notare che questo documento suggerisce che puoi manualmente limitare la proporzione di cache di writeback, che può essere utilizzata per una partizione/filesystem specifico. L'impostazione si chiama /sys/class/bdi/*/max_ratio . Tieni presente che "se il dispositivo che desideri limitare è l'unico su cui è attualmente scritto, la limitazione non ha un grande effetto".


Linux
  1. Linux:perché gli utenti Linux non utilizzano una chiamata di sistema per ottenere l'ora corrente?

  2. Perché il seguente comando sta uccidendo un sistema?

  3. Controlla il carico di sistema su Linux

  4. Quali parti di questo codice assembly HelloWorld sono essenziali se dovessi scrivere il programma in assembly?

  5. Linux:'Nome utente' non è nel file sudoers. Questo incidente verrà segnalato

Introduzione al file system Linux

Gestione dello swap nel moderno sistema Linux

Gli effetti dell'aggiunta di utenti a un sistema Linux

Come modificare la shell predefinita nel sistema Linux

Come utilizzare il comando fd sul sistema Linux

Perché l'utilizzo della CPU riportato da top in Linux è superiore al 100%?