diff options
author | Federico Vaga <federico.vaga@vaga.pv.it> | 2023-01-02 21:37:16 +0300 |
---|---|---|
committer | Jonathan Corbet <corbet@lwn.net> | 2023-01-13 19:26:19 +0300 |
commit | 5a37deab42ad1630b39bf9bca13aa55e94310b01 (patch) | |
tree | 61b56baec5f2181afc7d0986986f9de3b4845b9c | |
parent | 15b0f76d266010598a9907383b75598c1c0ad7ca (diff) | |
download | linux-5a37deab42ad1630b39bf9bca13aa55e94310b01.tar.xz |
doc:it_IT: add translation for botching-up-ioctl.rst
This patch adds the translation for the botching up ioctl document.
Signed-off-by: Federico Vaga <federico.vaga@vaga.pv.it>
Link: https://lore.kernel.org/r/20230102183716.9698-1-federico.vaga@vaga.pv.it
Signed-off-by: Jonathan Corbet <corbet@lwn.net>
-rw-r--r-- | Documentation/translations/it_IT/process/botching-up-ioctls.rst | 249 | ||||
-rw-r--r-- | Documentation/translations/it_IT/process/index.rst | 1 |
2 files changed, 250 insertions, 0 deletions
diff --git a/Documentation/translations/it_IT/process/botching-up-ioctls.rst b/Documentation/translations/it_IT/process/botching-up-ioctls.rst new file mode 100644 index 000000000000..91732cdf808a --- /dev/null +++ b/Documentation/translations/it_IT/process/botching-up-ioctls.rst @@ -0,0 +1,249 @@ +.. include:: ../disclaimer-ita.rst + +:Original: Documentation/process/botching-up-ioctls.rst + +========================================== +(Come evitare di) Raffazzonare delle ioctl +========================================== + +Preso da: https://blog.ffwll.ch/2013/11/botching-up-ioctls.html + +Scritto da : Daniel Vetter, Copyright © 2013 Intel Corporation + +Una cosa che gli sviluppatori del sottosistema grafico del kernel Linux hanno +imparato negli ultimi anni è l'inutilità di cercare di creare un'interfaccia +unificata per gestire la memoria e le unità esecutive di diverse GPU. Dunque, +oggigiorno ogni driver ha il suo insieme di ioctl per allocare memoria ed +inviare dei programmi alla GPU. Il che è va bene dato che non c'è più un insano +sistema che finge di essere generico, ma al suo posto ci sono interfacce +dedicate. Ma al tempo stesso è più facile incasinare le cose. + +Per evitare di ripetere gli stessi errori ho preso nota delle lezioni imparate +mentre raffazzonavo il driver drm/i915. La maggior parte di queste lezioni si +focalizzano sui tecnicismi e non sulla visione d'insieme, come le discussioni +riguardo al modo migliore per implementare una ioctl per inviare compiti alla +GPU. Probabilmente, ogni sviluppatore di driver per GPU dovrebbe imparare queste +lezioni in autonomia. + + +Prerequisiti +------------ + +Prima i prerequisiti. Seguite i seguenti suggerimenti se non volete fallire in +partenza e ritrovarvi ad aggiungere un livello di compatibilità a 32-bit. + +* Usate solamente interi a lunghezza fissa. Per evitare i conflitti coi tipi + definiti nello spazio utente, il kernel definisce alcuni tipi speciali, come: + ``__u32``, ``__s64``. Usateli. + +* Allineate tutto alla lunghezza naturale delle piattaforma in uso e riempite + esplicitamente i vuoti. Non necessariamente le piattaforme a 32-bit allineano + i valori a 64-bit rispettandone l'allineamento, ma le piattaforme a 64-bit lo + fanno. Dunque, per farlo correttamente in entrambe i casi dobbiamo sempre + riempire i vuoti. + +* Se una struttura dati contiene valori a 64-bit, allora fate si che la sua + dimensione sia allineata a 64-bit, altrimenti la sua dimensione varierà su + sistemi a 32-bit e 64-bit. Avere una dimensione differente causa problemi + quando si passano vettori di strutture dati al kernel, o quando il kernel + effettua verifiche sulla dimensione (per esempio il sistema drm lo fa). + +* I puntatori sono di tipo ``__u64``, con un *cast* da/a ``uintptr_t`` da lato + spazio utente e da/a ``void __user *`` nello spazio kernel. Sforzatevi il più + possibile per non ritardare la conversione, o peggio maneggiare ``__u64`` nel + vostro codice perché questo riduce le verifiche che strumenti come sparse + possono effettuare. La macro u64_to_user_ptr() può essere usata nel kernel + per evitare avvisi riguardo interi e puntatori di dimensioni differenti. + + +Le Basi +------- + +Con la gioia d'aver evitato un livello di compatibilità, possiamo ora dare uno +sguardo alle basi. Trascurare questi punti renderà difficile la gestione della +compatibilità all'indietro ed in avanti. E dato che sbagliare al primo colpo è +garantito, dovrete rivisitare il codice o estenderlo per ogni interfaccia. + +* Abbiate un modo chiaro per capire dallo spazio utente se una nuova ioctl, o + l'estensione di una esistente, sia supportata dal kernel in esecuzione. Se non + potete fidarvi del fatto che un vecchio kernel possa rifiutare correttamente + un nuovo *flag*, modalità, o ioctl, (probabilmente perché avevate raffazzonato + qualcosa nel passato) allora dovrete implementare nel driver un meccanismo per + notificare quali funzionalità sono supportate, o in alternativa un numero di + versione. + +* Abbiate un piano per estendere le ioctl con nuovi *flag* o campi alla fine di + una struttura dati. Il sistema drm verifica la dimensione di ogni ioctl in + arrivo, ed estende con zeri ogni incongruenza fra kernel e spazio utente. + Questo aiuta, ma non è una soluzione completa dato che uno spazio utente nuovo + su un kernel vecchio non noterebbe che i campi nuovi alla fine della struttura + vengono ignorati. Dunque, anche questo avrà bisogno di essere notificato dal + driver allo spazio utente. + +* Verificate tutti i campi e *flag* inutilizzati ed i riempimenti siano a 0, + altrimenti rifiutare la ioctl. Se non lo fate il vostro bel piano per + estendere le ioctl andrà a rotoli dato che qualcuno userà delle ioctl con + strutture dati con valori casuali dallo stack nei campi inutilizzati. Il che + si traduce nell'avere questi campi nell'ABI, e la cui unica utilità sarà + quella di contenere spazzatura. Per questo dovrete esplicitamente riempire i + vuoti di tutte le vostre strutture dati, anche se non le userete in un + vettore. Il riempimento fatto dal compilatore potrebbe contenere valori + casuali. + +* Abbiate un semplice codice di test per ognuno dei casi sopracitati. + + +Divertirsi coi percorsi d'errore +-------------------------------- + +Oggigiorno non ci sono più scuse rimaste per permettere ai driver drm di essere +sfruttati per diventare root. Questo significa che dobbiamo avere una completa +validazione degli input e gestire in modo robusto i percorsi - tanto le GPU +moriranno comunque nel più strano dei casi particolari: + + * Le ioctl devono verificare l'overflow dei vettori. Inoltre, per i valori + interi si devono verificare *overflow*, *underflow*, e *clamping*. Il + classico esempio è l'inserimento direttamente nell'hardware di valori di + posizionamento di un'immagine *sprite* quando l'hardware supporta giusto 12 + bit, o qualcosa del genere. Tutto funzionerà finché qualche strano *display + server* non decide di preoccuparsi lui stesso del *clamping* e il cursore + farà il giro dello schermo. + + * Avere un test semplice per ogni possibile fallimento della vostra ioctl. + Verificate che il codice di errore rispetti le aspettative. Ed infine, + assicuratevi che verifichiate un solo percorso sbagliato per ogni sotto-test + inviando comunque dati corretti. Senza questo, verifiche precedenti + potrebbero rigettare la ioctl troppo presto, impedendo l'esecuzione del + codice che si voleva effettivamente verificare, rischiando quindi di + mascherare bachi e regressioni. + + * Fate si che tutte le vostre ioctl siano rieseguibili. Prima di tutto X adora + i segnali; secondo questo vi permetterà di verificare il 90% dei percorsi + d'errore interrompendo i vostri test con dei segnali. Grazie all'amore di X + per i segnali, otterrete gratuitamente un eccellente copertura di base per + tutti i vostri percorsi d'errore. Inoltre, siate consistenti sul modo di + gestire la riesecuzione delle ioctl - per esempio, drm ha una piccola + funzione di supporto `drmIoctl` nella sua librerie in spazio utente. Il + driver i915 l'abbozza con l'ioctl `set_tiling`, ed ora siamo inchiodati per + sempre con una semantica arcana sia nel kernel che nello spazio utente. + + + * Se non potete rendere un pezzo di codice rieseguibile, almeno rendete + possibile la sua interruzione. Le GPU moriranno e i vostri utenti non vi + apprezzeranno affatto se tenete in ostaggio il loro scatolotto (mediante un + processo X insopprimibile). Se anche recuperare lo stato è troppo complicato, + allora implementate una scadenza oppure come ultima spiaggia una rete di + sicurezza per rilevare situazioni di stallo quando l'hardware da di matto. + + * Preparate dei test riguardo ai casi particolarmente estremi nel codice di + recupero del sistema - è troppo facile create uno stallo fra il vostro codice + anti-stallo e un processo scrittore. + + +Tempi, attese e mancate scadenze +-------------------------------- + +Le GPU fanno quasi tutto in modo asincrono, dunque dobbiamo regolare le +operazioni ed attendere quelle in sospeso. Questo è davvero difficile; al +momento nessuna delle ioctl supportante dal driver drm/i915 riesce a farlo +perfettamente, il che significa che qui ci sono ancora una valanga di lezioni da +apprendere. + + * Per fare riferimento al tempo usate sempre ``CLOCK_MONOTONIC``. Oggigiorno + questo è quello che viene usato di base da alsa, drm, e v4l. Tuttavia, + lasciate allo spazio utente la possibilità di capire quali *timestamp* + derivano da domini temporali diversi come il vostro orologio di sistema + (fornito dal kernel) oppure un contatore hardware indipendente da qualche + parte. Gli orologi divergeranno, ma con questa informazione gli strumenti di + analisi delle prestazioni possono compensare il problema. Se il vostro spazio + utente può ottenere i valori grezzi degli orologi, allora considerate di + esporre anch'essi. + + * Per descrivere il tempo, usate ``__s64`` per i secondi e ``__u64`` per i + nanosecondi. Non è il modo migliore per specificare il tempo, ma è + praticamente uno standard. + + * Verificate che gli input di valori temporali siano normalizzati, e se non lo + sono scartateli. Fate attenzione perché la struttura dati ``struct ktime`` + del kernel usa interi con segni sia per i secondi che per i nanosecondi. + + * Per le scadenze (*timeout*) usate valori temporali assoluti. Se siete dei + bravi ragazzi e avete reso la vostra ioctl rieseguibile, allora i tempi + relativi tendono ad essere troppo grossolani e a causa degli arrotondamenti + potrebbero estendere in modo indefinito i tempi di attesa ad ogni + riesecuzione. Particolarmente vero se il vostro orologio di riferimento è + qualcosa di molto lento come il contatore di *frame*. Con la giacca da + avvocato delle specifiche diremmo che questo non è un baco perché tutte le + scadenze potrebbero essere estese - ma sicuramente gli utenti vi odieranno + quando le animazioni singhiozzano. + + * Considerate l'idea di eliminare tutte le ioctl sincrone con scadenze, e di + sostituirle con una versione asincrona il cui stato può essere consultato + attraverso il descrittore di file mediante ``poll``. Questo approccio si + sposa meglio in un applicazione guidata dagli eventi. + + * Sviluppate dei test per i casi estremi, specialmente verificate che i valori + di ritorno per gli eventi già completati, le attese terminate con successo, e + le attese scadute abbiano senso e servano ai vostri scopi. + + +Non perdere risorse +------------------- +Nel suo piccolo il driver drm implementa un sistema operativo specializzato per +certe GPU. Questo significa che il driver deve esporre verso lo spazio +utente tonnellate di agganci per accedere ad oggetti e altre risorse. Farlo +correttamente porterà con se alcune insidie: + + * Collegate sempre la vita di una risorsa creata dinamicamente, a quella del + descrittore di file. Considerate una mappatura 1:1 se la vostra risorsa + dev'essere condivisa fra processi - passarsi descrittori di file sul socket + unix semplifica la gestione anche per lo spazio utente. + + * Dev'esserci sempre Il supporto ``O_CLOEXEC``. + + * Assicuratevi di avere abbastanza isolamento fra utenti diversi. Di base + impostate uno spazio dei nomi riservato per ogni descrittore di file, il che + forzerà ogni condivisione ad essere esplicita. Usate uno spazio più globale + per dispositivo solo se gli oggetti sono effettivamente unici per quel + dispositivo. Un controesempio viene dall'interfaccia drm modeset, dove + oggetti specifici di dispositivo, come i connettori, condividono uno spazio + dei nomi con oggetti per il *framebuffer*, ma questi non sono per niente + condivisi. Uno spazio separato, privato di base, per i *framebuffer* sarebbe + stato meglio. + + * Pensate all'identificazione univoca degli agganci verso lo spazio utente. Per + esempio, per la maggior parte dei driver drm, si considera fallace la doppia + sottomissione di un oggetto allo stesso comando ioctl. Ma per evitarlo, se + gli oggetti sono condivisibili, lo spazio utente ha bisogno di sapere se il + driver ha importato un oggetto da un altro processo. Non l'ho ancora provato, + ma considerate l'idea di usare il numero di inode come identificatore per i + descrittori di file condivisi - che poi è come si distinguono i veri file. + Sfortunatamente, questo richiederebbe lo sviluppo di un vero e proprio + filesystem virtuale nel kernel. + + +Ultimo, ma non meno importante +------------------------------ + +Non tutti i problemi si risolvono con una nuova ioctl: + +* Pensateci su due o tre volte prima di implementare un'interfaccia privata per + un driver. Ovviamente è molto più veloce seguire questa via piuttosto che + buttarsi in lunghe discussioni alla ricerca di una soluzione più generica. Ed + a volte un'interfaccia privata è quello che serve per sviluppare un nuovo + concetto. Ma alla fine, una volta che c'è un'interfaccia generica a + disposizione finirete per mantenere due interfacce. Per sempre. + +* Considerate interfacce alternative alle ioctl. Gli attributi sysfs sono molto + meglio per impostazioni che sono specifiche di un dispositivo, o per + sotto-oggetti con una vita piuttosto statica (come le uscite dei connettori in + drm con tutti gli attributi per la sovrascrittura delle rilevazioni). O magari + solo il vostro sistema di test ha bisogno di una certa interfaccia, e allora + debugfs (che non ha un'interfaccia stabile) sarà la soluzione migliore. + +Per concludere. Questo gioco consiste nel fare le cose giuste fin da subito, +dato che se il vostro driver diventa popolare e la piattaforma hardware longeva +finirete per mantenere le vostre ioctl per sempre. Potrete tentare di deprecare +alcune orribili ioctl, ma ci vorranno anni per riuscirci effettivamente. E +ancora, altri anni prima che sparisca l'ultimo utente capace di lamentarsi per +una regressione. diff --git a/Documentation/translations/it_IT/process/index.rst b/Documentation/translations/it_IT/process/index.rst index 8d4e36a07ff4..25602c1a97d1 100644 --- a/Documentation/translations/it_IT/process/index.rst +++ b/Documentation/translations/it_IT/process/index.rst @@ -58,6 +58,7 @@ perché non si è trovato un posto migliore. adding-syscalls magic-number volatile-considered-harmful + botching-up-ioctls clang-format ../riscv/patch-acceptance |