linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
Search results ordered by [date|relevance]  view[summary|nested|Atom feed]
thread overview below | download mbox.gz: |
* [PATCH V4] doc:it_IT: align Italian documentation
@ 2022-12-31 13:08  4% Federico Vaga
  0 siblings, 0 replies; 200+ results
From: Federico Vaga @ 2022-12-31 13:08 UTC (permalink / raw)
  To: Jonathan Corbet; +Cc: Federico Vaga, linux-doc, linux-kernel

Translation for the following patches

commit da4288b95baa ("scripts/check-local-export: avoid 'wait $!' for process substitution")
commit 5372de4e4545 ("docs/doc-guide: Put meta title for kernel-doc HTML page")
commit 4d627ef12b40 ("docs/doc-guide: Mention make variable SPHINXDIRS")
commit 7c43214dddfd ("docs/doc-guide: Add footnote on Inkscape for better images in PDF documents")
commit 615041d42a1a ("docs: kernel-docs: shorten the lengthy doc title")
commit cbf4adfd4d19 ("Documentation: process: Update email client instructions for Thunderbird")
commit e72b3b9810dd ("maintainer-pgp-guide: minor wording tweaks")
commit ea522496afa1 ("Documentation: process: replace outdated LTS table w/ link")
commit 93431e0607e5 ("Replace HTTP links with HTTPS ones: documentation")
commit e648174b53f1 ("Documentation: Fix spelling mistake in hacking.rst")
commit 602684adb42a ("docs: Update version number from 5.x to 6.x in README.rst")
commit 489876063fb1 ("docs: add a man-pages link to the front page")
commit 0c7b4366f1ab ("docs: Rewrite the front page")

Signed-off-by: Federico Vaga <federico.vaga@vaga.pv.it>
---

V1 -> V2 fix typo in footnote link
V2 -> V3 restore latex directive to disable CJK
V3 -> V4 really restore latex directive with its original indentation

 .../translations/it_IT/admin-guide/README.rst |  2 +-
 .../it_IT/doc-guide/kernel-doc.rst            |  2 +
 .../translations/it_IT/doc-guide/sphinx.rst   | 14 ++-
 Documentation/translations/it_IT/index.rst    | 89 +++++++++----------
 .../it_IT/kernel-hacking/hacking.rst          |  2 +-
 .../translations/it_IT/process/2.Process.rst  | 15 +---
 .../it_IT/process/7.AdvancedTopics.rst        |  8 +-
 .../translations/it_IT/process/changes.rst    | 11 +++
 .../it_IT/process/email-clients.rst           | 67 +++++++++-----
 .../it_IT/process/kernel-docs.rst             |  4 +-
 .../it_IT/process/maintainer-pgp-guide.rst    |  4 +-
 11 files changed, 127 insertions(+), 91 deletions(-)

diff --git a/Documentation/translations/it_IT/admin-guide/README.rst b/Documentation/translations/it_IT/admin-guide/README.rst
index b37166817842..c874586a9af9 100644
--- a/Documentation/translations/it_IT/admin-guide/README.rst
+++ b/Documentation/translations/it_IT/admin-guide/README.rst
@@ -4,7 +4,7 @@
 
 .. _it_readme:
 
-Rilascio del kernel Linux  5.x <http://kernel.org/>
+Rilascio del kernel Linux  6.x <http://kernel.org/>
 ===================================================
 
 .. warning::
diff --git a/Documentation/translations/it_IT/doc-guide/kernel-doc.rst b/Documentation/translations/it_IT/doc-guide/kernel-doc.rst
index 78082281acf9..5cece223b46b 100644
--- a/Documentation/translations/it_IT/doc-guide/kernel-doc.rst
+++ b/Documentation/translations/it_IT/doc-guide/kernel-doc.rst
@@ -3,6 +3,8 @@
 .. note:: Per leggere la documentazione originale in inglese:
 	  :ref:`Documentation/doc-guide/index.rst <doc_guide>`
 
+.. title:: Commenti in kernel-doc
+
 .. _it_kernel_doc:
 
 =================================
diff --git a/Documentation/translations/it_IT/doc-guide/sphinx.rst b/Documentation/translations/it_IT/doc-guide/sphinx.rst
index 64528790dc34..1f513bc33618 100644
--- a/Documentation/translations/it_IT/doc-guide/sphinx.rst
+++ b/Documentation/translations/it_IT/doc-guide/sphinx.rst
@@ -151,7 +151,8 @@ Ovviamente, per generare la documentazione, Sphinx (``sphinx-build``)
 dev'essere installato. Se disponibile, il tema *Read the Docs* per Sphinx
 verrà utilizzato per ottenere una documentazione HTML più gradevole.
 Per la documentazione in formato PDF, invece, avrete bisogno di ``XeLaTeX`
-e di ``convert(1)`` disponibile in ImageMagick (https://www.imagemagick.org).
+e di ``convert(1)`` disponibile in ImageMagick
+(https://www.imagemagick.org). \ [#ink]_
 Tipicamente, tutti questi pacchetti sono disponibili e pacchettizzati nelle
 distribuzioni Linux.
 
@@ -162,9 +163,20 @@ la generazione potete usare il seguente comando ``make SPHINXOPTS=-v htmldocs``.
 Potete anche personalizzare l'ouptut html passando un livello aggiuntivo
 DOCS_CSS usando la rispettiva variabile d'ambiente ``DOCS_CSS``.
 
+La variable make ``SPHINXDIRS`` è utile quando si vuole generare solo una parte
+della documentazione. Per esempio, si possono generare solo di documenti in
+``Documentation/doc-guide`` eseguendo ``make SPHINXDIRS=doc-guide htmldocs``. La
+sezione dedicata alla documentazione di ``make help`` vi mostrerà quali sotto
+cartelle potete specificare.
+
 Potete eliminare la documentazione generata tramite il comando
 ``make cleandocs``.
 
+.. [#ink] Avere installato anche ``inkscape(1)`` dal progetto Inkscape ()
+          potrebbe aumentare la qualità delle immagini che verranno integrate
+          nel documento PDF, specialmente per quando si usando rilasci del
+          kernel uguali o superiori a 5.18
+
 Scrivere la documentazione
 ==========================
 
diff --git a/Documentation/translations/it_IT/index.rst b/Documentation/translations/it_IT/index.rst
index e80a3097aa57..fc5f39814e83 100644
--- a/Documentation/translations/it_IT/index.rst
+++ b/Documentation/translations/it_IT/index.rst
@@ -1,3 +1,5 @@
+.. SPDX-License-Identifier: GPL-2.0
+
 .. _it_linux_doc:
 
 ===================
@@ -67,75 +69,68 @@ I miglioramenti alla documentazione sono sempre i benvenuti; per cui,
 se vuoi aiutare, iscriviti alla lista di discussione linux-doc presso
 vger.kernel.org.
 
-Documentazione sulla licenza dei sorgenti
------------------------------------------
-
-I seguenti documenti descrivono la licenza usata nei sorgenti del kernel Linux
-(GPLv2), come licenziare i singoli file; inoltre troverete i riferimenti al
-testo integrale della licenza.
+Lavorare con la comunità di sviluppo
+------------------------------------
 
-* :ref:`it_kernel_licensing`
+Le guide fondamentali per l'interazione con la comunità di sviluppo del kernel e
+su come vedere il proprio lavoro integrato.
 
-Documentazione per gli utenti
------------------------------
-
-I seguenti manuali sono scritti per gli *utenti* del kernel - ovvero,
-coloro che cercano di farlo funzionare in modo ottimale su un dato sistema
-
-.. warning::
+.. toctree::
+   :maxdepth: 1
 
-    TODO ancora da tradurre
+   process/development-process
+   process/submitting-patches
+   Code of conduct <process/code-of-conduct>
+   All development-process docs <process/index>
 
-Documentazione per gli sviluppatori di applicazioni
----------------------------------------------------
 
-Il manuale delle API verso lo spazio utente è una collezione di documenti
-che descrivono le interfacce del kernel viste dagli sviluppatori
-di applicazioni.
+Manuali sull'API interna
+------------------------
 
-.. warning::
+Di seguito una serie di manuali per gli sviluppatori che hanno bisogno di
+interfacciarsi con il resto del kernel.
 
-    TODO ancora da tradurre
+.. toctree::
+   :maxdepth: 1
 
+   core-api/index
 
-Introduzione allo sviluppo del kernel
--------------------------------------
+Strumenti e processi per lo sviluppo
+------------------------------------
 
-Questi manuali contengono informazioni su come contribuire allo sviluppo
-del kernel.
-Attorno al kernel Linux gira una comunità molto grande con migliaia di
-sviluppatori che contribuiscono ogni anno. Come in ogni grande comunità,
-sapere come le cose vengono fatte renderà il processo di integrazione delle
-vostre modifiche molto più semplice
+Di seguito una serie di manuali contenenti informazioni utili a tutti gli
+sviluppatori del kernel.
 
 .. toctree::
-   :maxdepth: 2
+   :maxdepth: 1
 
-   process/index
+   process/license-rules
    doc-guide/index
    kernel-hacking/index
 
-Documentazione della API del kernel
------------------------------------
+Documentazione per gli utenti
+-----------------------------
 
-Questi manuali forniscono dettagli su come funzionano i sottosistemi del
-kernel dal punto di vista degli sviluppatori del kernel. Molte delle
-informazioni contenute in questi manuali sono prese direttamente dai
-file sorgenti, informazioni aggiuntive vengono aggiunte solo se necessarie
-(o almeno ci proviamo — probabilmente *non* tutto quello che è davvero
-necessario).
+Di seguito una serie di manuali per gli *utenti* del kernel - ovvero coloro che
+stanno cercando di farlo funzionare al meglio per un dato sistema, ma anche
+coloro che stanno sviluppando applicazioni che sfruttano l'API verso lo
+spazio-utente.
 
-.. toctree::
-   :maxdepth: 2
+Consultate anche `Linux man pages <https://www.kernel.org/doc/man-pages/>`_, che
+vengono mantenuti separatamente dalla documentazione del kernel Linux
+
+Documentazione relativa ai firmware
+-----------------------------------
+Di seguito informazioni sulle aspettative del kernel circa i firmware.
 
-   core-api/index
 
 Documentazione specifica per architettura
 -----------------------------------------
 
-Questi manuali forniscono dettagli di programmazione per le diverse
-implementazioni d'architettura.
 
-.. warning::
+Documentazione varia
+--------------------
 
-    TODO ancora da tradurre
+Ci sono documenti che sono difficili da inserire nell'attuale organizzazione
+della documentazione; altri hanno bisogno di essere migliorati e/o convertiti
+nel formato *ReStructured Text*; altri sono semplicamente troppo vecchi.
diff --git a/Documentation/translations/it_IT/kernel-hacking/hacking.rst b/Documentation/translations/it_IT/kernel-hacking/hacking.rst
index 560f1d0482d2..dd06bfc1a050 100644
--- a/Documentation/translations/it_IT/kernel-hacking/hacking.rst
+++ b/Documentation/translations/it_IT/kernel-hacking/hacking.rst
@@ -137,7 +137,7 @@ macro :c:func:`in_softirq()` (``include/linux/preempt.h``).
 .. warning::
 
     State attenti che questa macro ritornerà un falso positivo
-    se :ref:`botton half lock <it_local_bh_disable>` è bloccato.
+    se :ref:`bottom half lock <it_local_bh_disable>` è bloccato.
 
 Alcune regole basilari
 ======================
diff --git a/Documentation/translations/it_IT/process/2.Process.rst b/Documentation/translations/it_IT/process/2.Process.rst
index 62826034e0b2..25cd00351c03 100644
--- a/Documentation/translations/it_IT/process/2.Process.rst
+++ b/Documentation/translations/it_IT/process/2.Process.rst
@@ -136,18 +136,11 @@ Quindi, per esempio, la storia del kernel 5.2 appare così (anno 2019):
 La 5.2.21 fu l'aggiornamento finale per la versione 5.2.
 
 Alcuni kernel sono destinati ad essere kernel a "lungo termine"; questi
-riceveranno assistenza per un lungo periodo di tempo.  Al momento in cui
-scriviamo, i manutentori dei kernel stabili a lungo termine sono:
-
-	======  ================================  ==========================================
-	3.16	Ben Hutchings			  (kernel stabile molto più a lungo termine)
-	4.4	Greg Kroah-Hartman e Sasha Levin  (kernel stabile molto più a lungo termine)
-	4.9	Greg Kroah-Hartman e Sasha Levin
-	4.14	Greg Kroah-Hartman e Sasha Levin
-	4.19	Greg Kroah-Hartman e Sasha Levin
-	5.4i	Greg Kroah-Hartman e Sasha Levin
-	======  ================================  ==========================================
+riceveranno assistenza per un lungo periodo di tempo. Consultate il seguente
+collegamento per avere la lista delle versioni attualmente supportate e i
+relativi manutentori:
 
+       https://www.kernel.org/category/releases.html
 
 Questa selezione di kernel di lungo periodo sono puramente dovuti ai loro
 manutentori, alla loro necessità e al tempo per tenere aggiornate proprio
diff --git a/Documentation/translations/it_IT/process/7.AdvancedTopics.rst b/Documentation/translations/it_IT/process/7.AdvancedTopics.rst
index cc1cff5d23ae..dffd813a0910 100644
--- a/Documentation/translations/it_IT/process/7.AdvancedTopics.rst
+++ b/Documentation/translations/it_IT/process/7.AdvancedTopics.rst
@@ -35,9 +35,9 @@ git è parte del processo di sviluppo del kernel.  Gli sviluppatori che
 desiderassero diventare agili con git troveranno più informazioni ai
 seguenti indirizzi:
 
-	http://git-scm.com/
+	https://git-scm.com/
 
-	http://www.kernel.org/pub/software/scm/git/docs/user-manual.html
+	https://www.kernel.org/pub/software/scm/git/docs/user-manual.html
 
 e su varie guide che potrete trovare su internet.
 
@@ -63,7 +63,7 @@ eseguire git-daemon è relativamente semplice .  Altrimenti, iniziano a
 svilupparsi piattaforme che offrono spazi pubblici, e gratuiti (Github,
 per esempio).  Gli sviluppatori permanenti possono ottenere un account
 su kernel.org, ma non è proprio facile da ottenere; per maggiori informazioni
-consultate la pagina web http://kernel.org/faq/.
+consultate la pagina web https://kernel.org/faq/.
 
 In git è normale avere a che fare con tanti rami.  Ogni linea di sviluppo
 può essere separata in "rami per argomenti" e gestiti indipendentemente.
@@ -137,7 +137,7 @@ vostri rami.  Citando Linus
 	facendo, e ho bisogno di fidarmi *senza* dover passare tutte
 	le modifiche manualmente una per una.
 
-(http://lwn.net/Articles/224135/).
+(https://lwn.net/Articles/224135/).
 
 Per evitare queste situazioni, assicuratevi che tutte le patch in un ramo
 siano strettamente correlate al tema delle modifiche; un ramo "driver fixes"
diff --git a/Documentation/translations/it_IT/process/changes.rst b/Documentation/translations/it_IT/process/changes.rst
index 10e0ef9c34b7..473ec2cc558e 100644
--- a/Documentation/translations/it_IT/process/changes.rst
+++ b/Documentation/translations/it_IT/process/changes.rst
@@ -35,6 +35,7 @@ PC Card, per esempio, probabilmente non dovreste preoccuparvi di pcmciautils.
 GNU C                  5.1                gcc --version
 Clang/LLVM (optional)  11.0.0             clang --version
 GNU make               3.81               make --version
+bash                   4.2                bash --version
 binutils               2.23               ld -v
 flex                   2.5.35             flex --version
 bison                  2.0                bison --version
@@ -88,6 +89,11 @@ Make
 
 Per compilare il kernel vi servirà GNU make 3.81 o successivo.
 
+Bash
+----
+Per generare il kernel vengono usati alcuni script per bash.
+Questo richiede bash 4.2 o successivo.
+
 Binutils
 --------
 
@@ -370,6 +376,11 @@ Make
 
 - <ftp://ftp.gnu.org/gnu/make/>
 
+Bash
+----
+
+- <ftp://ftp.gnu.org/gnu/bash/>
+
 Binutils
 --------
 
diff --git a/Documentation/translations/it_IT/process/email-clients.rst b/Documentation/translations/it_IT/process/email-clients.rst
index b792f2f06a74..970671cd91af 100644
--- a/Documentation/translations/it_IT/process/email-clients.rst
+++ b/Documentation/translations/it_IT/process/email-clients.rst
@@ -288,37 +288,62 @@ Thunderbird (GUI)
 Thunderbird è un clone di Outlook a cui piace maciullare il testo, ma esistono
 modi per impedirglielo.
 
+Dopo la configurazione, inclusa l'installazione delle estenzioni, dovrete
+riavviare Thunderbird.
+
 - permettere l'uso di editor esterni:
+
   La cosa più semplice da fare con Thunderbird e le patch è quello di usare
-  l'estensione "external editor" e di usare il vostro ``$EDITOR`` preferito per
-  leggere/includere patch nel vostro messaggio.  Per farlo, scaricate ed
-  installate l'estensione e aggiungete un bottone per chiamarla rapidamente
-  usando :menuselection:`Visualizza-->Barra degli strumenti-->Personalizza...`;
-  una volta fatto potrete richiamarlo premendo sul bottone mentre siete nella
-  finestra :menuselection:`Scrivi`
-
-  Tenete presente che "external editor" richiede che il vostro editor non
-  faccia alcun fork, in altre parole, l'editor non deve ritornare prima di
-  essere stato chiuso.  Potreste dover passare dei parametri aggiuntivi al
-  vostro editor oppure cambiargli la configurazione.  Per esempio, usando
-  gvim dovrete aggiungere l'opzione -f ``/usr/bin/gvim -f`` (Se il binario
-  si trova in ``/usr/bin``) nell'apposito campo nell'interfaccia di
-  configurazione di  :menuselection:`external editor`.  Se usate altri editor
-  consultate il loro  manuale per sapere come configurarli.
+  estensioni che permettano di aprire il vostro editor preferito.
+
+  Di seguito alcune estensioni che possono essere utili al caso.
+
+  - "External Editor Revived"
+
+    https://github.com/Frederick888/external-editor-revived
+
+    https://addons.thunderbird.net/en-GB/thunderbird/addon/external-editor-revived/
+
+    L'estensione richiede l'installazione di "native messaging host". Date
+    un'occhiata alla seguente wiki:
+    https://github.com/Frederick888/external-editor-revived/wiki
+
+  - "External Editor"
+
+    https://github.com/exteditor/exteditor
+
+    Per usarlo, scaricate ed installate l'applicazione. Poi aprite la finestra
+    :menuselection:`Scrivi` e a seguire aggiungete un bottone per eseguirlo
+    `Visualizza-->Barra degli strumenti-->Personalizza...`. Infine, premente
+    questo nuovo bottone tutte le volte che volete usare l'editor esterno.
+
+    Tenete presente che "external editor" richiede che il vostro editor non
+    faccia alcun fork, in altre parole, l'editor non deve ritornare prima di
+    essere stato chiuso.  Potreste dover passare dei parametri aggiuntivi al
+    vostro editor oppure cambiargli la configurazione.  Per esempio, usando
+    gvim dovrete aggiungere l'opzione -f ``/usr/bin/gvim -f`` (Se il binario
+    si trova in ``/usr/bin``) nell'apposito campo nell'interfaccia di
+    configurazione di  :menuselection:`external editor`.  Se usate altri editor
+    consultate il loro  manuale per sapere come configurarli.``)``
 
 Per rendere l'editor interno un po' più sensato, fate così:
 
-- Modificate le impostazioni di Thunderbird per far si che non usi
-  ``format=flowed``. Andate in :menuselection:`Modifica-->Preferenze-->Avanzate-->Editor di configurazione`
+- Modificate le impostazioni di Thunderbird per far si che non usi ``format=flowed``!
+  Andate sulla finestra principale e cercate il bottone per il menu a tendina principale.
+  Poi :menuselection:`Modifica-->Preferenze-->Avanzate-->Editor di configurazione`
   per invocare il registro delle impostazioni.
 
-- impostate ``mailnews.send_plaintext_flowed`` a ``false``
+  - impostate ``mailnews.send_plaintext_flowed`` a ``false``
 
-- impostate ``mailnews.wraplength`` da ``72`` a ``0``
+  - impostate ``mailnews.wraplength`` da ``72`` a ``0``
 
-- :menuselection:`Visualizza-->Corpo del messaggio come-->Testo semplice`
+- Non scrivete messaggi HTML! Andate sulla finestra principale ed aprite la
+  schermata :menuselection:`Menu principale-->Impostazioni account-->nome@unserver.ovunque-->Composizioni e indirizzi`.
+  Qui potrete disabilitare l'opzione "Componi i messaggi in HTML"
 
-- :menuselection:`Visualizza-->Codifica del testo-->Unicode`
+- Aprite i messaggi solo in formato testo! Andate sulla finestra principale e
+  selezionate
+  :menuselection:`Menu principale-->Visualizza-->Copro del messaggio come-->Testo semplice`
 
 
 TkRat (GUI)
diff --git a/Documentation/translations/it_IT/process/kernel-docs.rst b/Documentation/translations/it_IT/process/kernel-docs.rst
index 38e0a955121a..eadcbf50a1b5 100644
--- a/Documentation/translations/it_IT/process/kernel-docs.rst
+++ b/Documentation/translations/it_IT/process/kernel-docs.rst
@@ -6,8 +6,8 @@
 
 .. _it_kernel_docs:
 
-Indice di documenti per le persone interessate a capire e/o scrivere per il kernel Linux
-========================================================================================
+Ulteriore Documentazione Del Kernel Linux
+=========================================
 
 .. note::
    Questo documento contiene riferimenti a documenti in lingua inglese; inoltre
diff --git a/Documentation/translations/it_IT/process/maintainer-pgp-guide.rst b/Documentation/translations/it_IT/process/maintainer-pgp-guide.rst
index a1e98ec9532e..4bd7a8a66904 100644
--- a/Documentation/translations/it_IT/process/maintainer-pgp-guide.rst
+++ b/Documentation/translations/it_IT/process/maintainer-pgp-guide.rst
@@ -286,9 +286,7 @@ magari in una cassetta di sicurezza in banca.
     Probabilmente la vostra stampante non è più quello stupido dispositivo
     connesso alla porta parallela, ma dato che il suo output è comunque
     criptato con la passphrase, eseguire la stampa in un sistema "cloud"
-    moderno dovrebbe essere comunque relativamente sicuro. Un'opzione potrebbe
-    essere quella di cambiare la passphrase della vostra chiave primaria
-    subito dopo aver finito con paperkey.
+    moderno dovrebbe essere comunque relativamente sicuro.
 
 Copia di riserva di tutta la cartella GnuPG
 -------------------------------------------
-- 
2.30.2


^ permalink raw reply related	[relevance 4%]

* [PATCH V3] doc:it_IT: align Italian documentation
@ 2022-12-31 13:01  4% Federico Vaga
  0 siblings, 0 replies; 200+ results
From: Federico Vaga @ 2022-12-31 13:01 UTC (permalink / raw)
  To: Jonathan Corbet; +Cc: Federico Vaga, linux-doc, linux-kernel

Translation for the following patches

commit da4288b95baa ("scripts/check-local-export: avoid 'wait $!' for process substitution")
commit 5372de4e4545 ("docs/doc-guide: Put meta title for kernel-doc HTML page")
commit 4d627ef12b40 ("docs/doc-guide: Mention make variable SPHINXDIRS")
commit 7c43214dddfd ("docs/doc-guide: Add footnote on Inkscape for better images in PDF documents")
commit 615041d42a1a ("docs: kernel-docs: shorten the lengthy doc title")
commit cbf4adfd4d19 ("Documentation: process: Update email client instructions for Thunderbird")
commit e72b3b9810dd ("maintainer-pgp-guide: minor wording tweaks")
commit ea522496afa1 ("Documentation: process: replace outdated LTS table w/ link")
commit 93431e0607e5 ("Replace HTTP links with HTTPS ones: documentation")
commit e648174b53f1 ("Documentation: Fix spelling mistake in hacking.rst")
commit 602684adb42a ("docs: Update version number from 5.x to 6.x in README.rst")
commit 489876063fb1 ("docs: add a man-pages link to the front page")
commit 0c7b4366f1ab ("docs: Rewrite the front page")

Signed-off-by: Federico Vaga <federico.vaga@vaga.pv.it>
---

V1 -> V2 fix typo in footnote link
V2 -> V3 restore latex directive to disable CJK

 .../translations/it_IT/admin-guide/README.rst |  2 +-
 .../it_IT/doc-guide/kernel-doc.rst            |  2 +
 .../translations/it_IT/doc-guide/sphinx.rst   | 14 ++-
 Documentation/translations/it_IT/index.rst    | 91 +++++++++----------
 .../it_IT/kernel-hacking/hacking.rst          |  2 +-
 .../translations/it_IT/process/2.Process.rst  | 15 +--
 .../it_IT/process/7.AdvancedTopics.rst        |  8 +-
 .../translations/it_IT/process/changes.rst    | 11 +++
 .../it_IT/process/email-clients.rst           | 67 +++++++++-----
 .../it_IT/process/kernel-docs.rst             |  4 +-
 .../it_IT/process/maintainer-pgp-guide.rst    |  4 +-
 11 files changed, 128 insertions(+), 92 deletions(-)

diff --git a/Documentation/translations/it_IT/admin-guide/README.rst b/Documentation/translations/it_IT/admin-guide/README.rst
index b37166817842..c874586a9af9 100644
--- a/Documentation/translations/it_IT/admin-guide/README.rst
+++ b/Documentation/translations/it_IT/admin-guide/README.rst
@@ -4,7 +4,7 @@
 
 .. _it_readme:
 
-Rilascio del kernel Linux  5.x <http://kernel.org/>
+Rilascio del kernel Linux  6.x <http://kernel.org/>
 ===================================================
 
 .. warning::
diff --git a/Documentation/translations/it_IT/doc-guide/kernel-doc.rst b/Documentation/translations/it_IT/doc-guide/kernel-doc.rst
index 78082281acf9..5cece223b46b 100644
--- a/Documentation/translations/it_IT/doc-guide/kernel-doc.rst
+++ b/Documentation/translations/it_IT/doc-guide/kernel-doc.rst
@@ -3,6 +3,8 @@
 .. note:: Per leggere la documentazione originale in inglese:
 	  :ref:`Documentation/doc-guide/index.rst <doc_guide>`
 
+.. title:: Commenti in kernel-doc
+
 .. _it_kernel_doc:
 
 =================================
diff --git a/Documentation/translations/it_IT/doc-guide/sphinx.rst b/Documentation/translations/it_IT/doc-guide/sphinx.rst
index 64528790dc34..1f513bc33618 100644
--- a/Documentation/translations/it_IT/doc-guide/sphinx.rst
+++ b/Documentation/translations/it_IT/doc-guide/sphinx.rst
@@ -151,7 +151,8 @@ Ovviamente, per generare la documentazione, Sphinx (``sphinx-build``)
 dev'essere installato. Se disponibile, il tema *Read the Docs* per Sphinx
 verrà utilizzato per ottenere una documentazione HTML più gradevole.
 Per la documentazione in formato PDF, invece, avrete bisogno di ``XeLaTeX`
-e di ``convert(1)`` disponibile in ImageMagick (https://www.imagemagick.org).
+e di ``convert(1)`` disponibile in ImageMagick
+(https://www.imagemagick.org). \ [#ink]_
 Tipicamente, tutti questi pacchetti sono disponibili e pacchettizzati nelle
 distribuzioni Linux.
 
@@ -162,9 +163,20 @@ la generazione potete usare il seguente comando ``make SPHINXOPTS=-v htmldocs``.
 Potete anche personalizzare l'ouptut html passando un livello aggiuntivo
 DOCS_CSS usando la rispettiva variabile d'ambiente ``DOCS_CSS``.
 
+La variable make ``SPHINXDIRS`` è utile quando si vuole generare solo una parte
+della documentazione. Per esempio, si possono generare solo di documenti in
+``Documentation/doc-guide`` eseguendo ``make SPHINXDIRS=doc-guide htmldocs``. La
+sezione dedicata alla documentazione di ``make help`` vi mostrerà quali sotto
+cartelle potete specificare.
+
 Potete eliminare la documentazione generata tramite il comando
 ``make cleandocs``.
 
+.. [#ink] Avere installato anche ``inkscape(1)`` dal progetto Inkscape ()
+          potrebbe aumentare la qualità delle immagini che verranno integrate
+          nel documento PDF, specialmente per quando si usando rilasci del
+          kernel uguali o superiori a 5.18
+
 Scrivere la documentazione
 ==========================
 
diff --git a/Documentation/translations/it_IT/index.rst b/Documentation/translations/it_IT/index.rst
index e80a3097aa57..56c9f63b1042 100644
--- a/Documentation/translations/it_IT/index.rst
+++ b/Documentation/translations/it_IT/index.rst
@@ -1,3 +1,5 @@
+.. SPDX-License-Identifier: GPL-2.0
+
 .. _it_linux_doc:
 
 ===================
@@ -6,7 +8,7 @@ Traduzione italiana
 
 .. raw:: latex
 
-	\kerneldocCJKoff
+     \kerneldocCJKoff
 
 :manutentore: Federico Vaga <federico.vaga@vaga.pv.it>
 
@@ -67,75 +69,68 @@ I miglioramenti alla documentazione sono sempre i benvenuti; per cui,
 se vuoi aiutare, iscriviti alla lista di discussione linux-doc presso
 vger.kernel.org.
 
-Documentazione sulla licenza dei sorgenti
------------------------------------------
-
-I seguenti documenti descrivono la licenza usata nei sorgenti del kernel Linux
-(GPLv2), come licenziare i singoli file; inoltre troverete i riferimenti al
-testo integrale della licenza.
+Lavorare con la comunità di sviluppo
+------------------------------------
 
-* :ref:`it_kernel_licensing`
+Le guide fondamentali per l'interazione con la comunità di sviluppo del kernel e
+su come vedere il proprio lavoro integrato.
 
-Documentazione per gli utenti
------------------------------
-
-I seguenti manuali sono scritti per gli *utenti* del kernel - ovvero,
-coloro che cercano di farlo funzionare in modo ottimale su un dato sistema
-
-.. warning::
+.. toctree::
+   :maxdepth: 1
 
-    TODO ancora da tradurre
+   process/development-process
+   process/submitting-patches
+   Code of conduct <process/code-of-conduct>
+   All development-process docs <process/index>
 
-Documentazione per gli sviluppatori di applicazioni
----------------------------------------------------
 
-Il manuale delle API verso lo spazio utente è una collezione di documenti
-che descrivono le interfacce del kernel viste dagli sviluppatori
-di applicazioni.
+Manuali sull'API interna
+------------------------
 
-.. warning::
+Di seguito una serie di manuali per gli sviluppatori che hanno bisogno di
+interfacciarsi con il resto del kernel.
 
-    TODO ancora da tradurre
+.. toctree::
+   :maxdepth: 1
 
+   core-api/index
 
-Introduzione allo sviluppo del kernel
--------------------------------------
+Strumenti e processi per lo sviluppo
+------------------------------------
 
-Questi manuali contengono informazioni su come contribuire allo sviluppo
-del kernel.
-Attorno al kernel Linux gira una comunità molto grande con migliaia di
-sviluppatori che contribuiscono ogni anno. Come in ogni grande comunità,
-sapere come le cose vengono fatte renderà il processo di integrazione delle
-vostre modifiche molto più semplice
+Di seguito una serie di manuali contenenti informazioni utili a tutti gli
+sviluppatori del kernel.
 
 .. toctree::
-   :maxdepth: 2
+   :maxdepth: 1
 
-   process/index
+   process/license-rules
    doc-guide/index
    kernel-hacking/index
 
-Documentazione della API del kernel
------------------------------------
+Documentazione per gli utenti
+-----------------------------
 
-Questi manuali forniscono dettagli su come funzionano i sottosistemi del
-kernel dal punto di vista degli sviluppatori del kernel. Molte delle
-informazioni contenute in questi manuali sono prese direttamente dai
-file sorgenti, informazioni aggiuntive vengono aggiunte solo se necessarie
-(o almeno ci proviamo — probabilmente *non* tutto quello che è davvero
-necessario).
+Di seguito una serie di manuali per gli *utenti* del kernel - ovvero coloro che
+stanno cercando di farlo funzionare al meglio per un dato sistema, ma anche
+coloro che stanno sviluppando applicazioni che sfruttano l'API verso lo
+spazio-utente.
 
-.. toctree::
-   :maxdepth: 2
+Consultate anche `Linux man pages <https://www.kernel.org/doc/man-pages/>`_, che
+vengono mantenuti separatamente dalla documentazione del kernel Linux
+
+Documentazione relativa ai firmware
+-----------------------------------
+Di seguito informazioni sulle aspettative del kernel circa i firmware.
 
-   core-api/index
 
 Documentazione specifica per architettura
 -----------------------------------------
 
-Questi manuali forniscono dettagli di programmazione per le diverse
-implementazioni d'architettura.
 
-.. warning::
+Documentazione varia
+--------------------
 
-    TODO ancora da tradurre
+Ci sono documenti che sono difficili da inserire nell'attuale organizzazione
+della documentazione; altri hanno bisogno di essere migliorati e/o convertiti
+nel formato *ReStructured Text*; altri sono semplicamente troppo vecchi.
diff --git a/Documentation/translations/it_IT/kernel-hacking/hacking.rst b/Documentation/translations/it_IT/kernel-hacking/hacking.rst
index 560f1d0482d2..dd06bfc1a050 100644
--- a/Documentation/translations/it_IT/kernel-hacking/hacking.rst
+++ b/Documentation/translations/it_IT/kernel-hacking/hacking.rst
@@ -137,7 +137,7 @@ macro :c:func:`in_softirq()` (``include/linux/preempt.h``).
 .. warning::
 
     State attenti che questa macro ritornerà un falso positivo
-    se :ref:`botton half lock <it_local_bh_disable>` è bloccato.
+    se :ref:`bottom half lock <it_local_bh_disable>` è bloccato.
 
 Alcune regole basilari
 ======================
diff --git a/Documentation/translations/it_IT/process/2.Process.rst b/Documentation/translations/it_IT/process/2.Process.rst
index 62826034e0b2..25cd00351c03 100644
--- a/Documentation/translations/it_IT/process/2.Process.rst
+++ b/Documentation/translations/it_IT/process/2.Process.rst
@@ -136,18 +136,11 @@ Quindi, per esempio, la storia del kernel 5.2 appare così (anno 2019):
 La 5.2.21 fu l'aggiornamento finale per la versione 5.2.
 
 Alcuni kernel sono destinati ad essere kernel a "lungo termine"; questi
-riceveranno assistenza per un lungo periodo di tempo.  Al momento in cui
-scriviamo, i manutentori dei kernel stabili a lungo termine sono:
-
-	======  ================================  ==========================================
-	3.16	Ben Hutchings			  (kernel stabile molto più a lungo termine)
-	4.4	Greg Kroah-Hartman e Sasha Levin  (kernel stabile molto più a lungo termine)
-	4.9	Greg Kroah-Hartman e Sasha Levin
-	4.14	Greg Kroah-Hartman e Sasha Levin
-	4.19	Greg Kroah-Hartman e Sasha Levin
-	5.4i	Greg Kroah-Hartman e Sasha Levin
-	======  ================================  ==========================================
+riceveranno assistenza per un lungo periodo di tempo. Consultate il seguente
+collegamento per avere la lista delle versioni attualmente supportate e i
+relativi manutentori:
 
+       https://www.kernel.org/category/releases.html
 
 Questa selezione di kernel di lungo periodo sono puramente dovuti ai loro
 manutentori, alla loro necessità e al tempo per tenere aggiornate proprio
diff --git a/Documentation/translations/it_IT/process/7.AdvancedTopics.rst b/Documentation/translations/it_IT/process/7.AdvancedTopics.rst
index cc1cff5d23ae..dffd813a0910 100644
--- a/Documentation/translations/it_IT/process/7.AdvancedTopics.rst
+++ b/Documentation/translations/it_IT/process/7.AdvancedTopics.rst
@@ -35,9 +35,9 @@ git è parte del processo di sviluppo del kernel.  Gli sviluppatori che
 desiderassero diventare agili con git troveranno più informazioni ai
 seguenti indirizzi:
 
-	http://git-scm.com/
+	https://git-scm.com/
 
-	http://www.kernel.org/pub/software/scm/git/docs/user-manual.html
+	https://www.kernel.org/pub/software/scm/git/docs/user-manual.html
 
 e su varie guide che potrete trovare su internet.
 
@@ -63,7 +63,7 @@ eseguire git-daemon è relativamente semplice .  Altrimenti, iniziano a
 svilupparsi piattaforme che offrono spazi pubblici, e gratuiti (Github,
 per esempio).  Gli sviluppatori permanenti possono ottenere un account
 su kernel.org, ma non è proprio facile da ottenere; per maggiori informazioni
-consultate la pagina web http://kernel.org/faq/.
+consultate la pagina web https://kernel.org/faq/.
 
 In git è normale avere a che fare con tanti rami.  Ogni linea di sviluppo
 può essere separata in "rami per argomenti" e gestiti indipendentemente.
@@ -137,7 +137,7 @@ vostri rami.  Citando Linus
 	facendo, e ho bisogno di fidarmi *senza* dover passare tutte
 	le modifiche manualmente una per una.
 
-(http://lwn.net/Articles/224135/).
+(https://lwn.net/Articles/224135/).
 
 Per evitare queste situazioni, assicuratevi che tutte le patch in un ramo
 siano strettamente correlate al tema delle modifiche; un ramo "driver fixes"
diff --git a/Documentation/translations/it_IT/process/changes.rst b/Documentation/translations/it_IT/process/changes.rst
index 10e0ef9c34b7..473ec2cc558e 100644
--- a/Documentation/translations/it_IT/process/changes.rst
+++ b/Documentation/translations/it_IT/process/changes.rst
@@ -35,6 +35,7 @@ PC Card, per esempio, probabilmente non dovreste preoccuparvi di pcmciautils.
 GNU C                  5.1                gcc --version
 Clang/LLVM (optional)  11.0.0             clang --version
 GNU make               3.81               make --version
+bash                   4.2                bash --version
 binutils               2.23               ld -v
 flex                   2.5.35             flex --version
 bison                  2.0                bison --version
@@ -88,6 +89,11 @@ Make
 
 Per compilare il kernel vi servirà GNU make 3.81 o successivo.
 
+Bash
+----
+Per generare il kernel vengono usati alcuni script per bash.
+Questo richiede bash 4.2 o successivo.
+
 Binutils
 --------
 
@@ -370,6 +376,11 @@ Make
 
 - <ftp://ftp.gnu.org/gnu/make/>
 
+Bash
+----
+
+- <ftp://ftp.gnu.org/gnu/bash/>
+
 Binutils
 --------
 
diff --git a/Documentation/translations/it_IT/process/email-clients.rst b/Documentation/translations/it_IT/process/email-clients.rst
index b792f2f06a74..970671cd91af 100644
--- a/Documentation/translations/it_IT/process/email-clients.rst
+++ b/Documentation/translations/it_IT/process/email-clients.rst
@@ -288,37 +288,62 @@ Thunderbird (GUI)
 Thunderbird è un clone di Outlook a cui piace maciullare il testo, ma esistono
 modi per impedirglielo.
 
+Dopo la configurazione, inclusa l'installazione delle estenzioni, dovrete
+riavviare Thunderbird.
+
 - permettere l'uso di editor esterni:
+
   La cosa più semplice da fare con Thunderbird e le patch è quello di usare
-  l'estensione "external editor" e di usare il vostro ``$EDITOR`` preferito per
-  leggere/includere patch nel vostro messaggio.  Per farlo, scaricate ed
-  installate l'estensione e aggiungete un bottone per chiamarla rapidamente
-  usando :menuselection:`Visualizza-->Barra degli strumenti-->Personalizza...`;
-  una volta fatto potrete richiamarlo premendo sul bottone mentre siete nella
-  finestra :menuselection:`Scrivi`
-
-  Tenete presente che "external editor" richiede che il vostro editor non
-  faccia alcun fork, in altre parole, l'editor non deve ritornare prima di
-  essere stato chiuso.  Potreste dover passare dei parametri aggiuntivi al
-  vostro editor oppure cambiargli la configurazione.  Per esempio, usando
-  gvim dovrete aggiungere l'opzione -f ``/usr/bin/gvim -f`` (Se il binario
-  si trova in ``/usr/bin``) nell'apposito campo nell'interfaccia di
-  configurazione di  :menuselection:`external editor`.  Se usate altri editor
-  consultate il loro  manuale per sapere come configurarli.
+  estensioni che permettano di aprire il vostro editor preferito.
+
+  Di seguito alcune estensioni che possono essere utili al caso.
+
+  - "External Editor Revived"
+
+    https://github.com/Frederick888/external-editor-revived
+
+    https://addons.thunderbird.net/en-GB/thunderbird/addon/external-editor-revived/
+
+    L'estensione richiede l'installazione di "native messaging host". Date
+    un'occhiata alla seguente wiki:
+    https://github.com/Frederick888/external-editor-revived/wiki
+
+  - "External Editor"
+
+    https://github.com/exteditor/exteditor
+
+    Per usarlo, scaricate ed installate l'applicazione. Poi aprite la finestra
+    :menuselection:`Scrivi` e a seguire aggiungete un bottone per eseguirlo
+    `Visualizza-->Barra degli strumenti-->Personalizza...`. Infine, premente
+    questo nuovo bottone tutte le volte che volete usare l'editor esterno.
+
+    Tenete presente che "external editor" richiede che il vostro editor non
+    faccia alcun fork, in altre parole, l'editor non deve ritornare prima di
+    essere stato chiuso.  Potreste dover passare dei parametri aggiuntivi al
+    vostro editor oppure cambiargli la configurazione.  Per esempio, usando
+    gvim dovrete aggiungere l'opzione -f ``/usr/bin/gvim -f`` (Se il binario
+    si trova in ``/usr/bin``) nell'apposito campo nell'interfaccia di
+    configurazione di  :menuselection:`external editor`.  Se usate altri editor
+    consultate il loro  manuale per sapere come configurarli.``)``
 
 Per rendere l'editor interno un po' più sensato, fate così:
 
-- Modificate le impostazioni di Thunderbird per far si che non usi
-  ``format=flowed``. Andate in :menuselection:`Modifica-->Preferenze-->Avanzate-->Editor di configurazione`
+- Modificate le impostazioni di Thunderbird per far si che non usi ``format=flowed``!
+  Andate sulla finestra principale e cercate il bottone per il menu a tendina principale.
+  Poi :menuselection:`Modifica-->Preferenze-->Avanzate-->Editor di configurazione`
   per invocare il registro delle impostazioni.
 
-- impostate ``mailnews.send_plaintext_flowed`` a ``false``
+  - impostate ``mailnews.send_plaintext_flowed`` a ``false``
 
-- impostate ``mailnews.wraplength`` da ``72`` a ``0``
+  - impostate ``mailnews.wraplength`` da ``72`` a ``0``
 
-- :menuselection:`Visualizza-->Corpo del messaggio come-->Testo semplice`
+- Non scrivete messaggi HTML! Andate sulla finestra principale ed aprite la
+  schermata :menuselection:`Menu principale-->Impostazioni account-->nome@unserver.ovunque-->Composizioni e indirizzi`.
+  Qui potrete disabilitare l'opzione "Componi i messaggi in HTML"
 
-- :menuselection:`Visualizza-->Codifica del testo-->Unicode`
+- Aprite i messaggi solo in formato testo! Andate sulla finestra principale e
+  selezionate
+  :menuselection:`Menu principale-->Visualizza-->Copro del messaggio come-->Testo semplice`
 
 
 TkRat (GUI)
diff --git a/Documentation/translations/it_IT/process/kernel-docs.rst b/Documentation/translations/it_IT/process/kernel-docs.rst
index 38e0a955121a..eadcbf50a1b5 100644
--- a/Documentation/translations/it_IT/process/kernel-docs.rst
+++ b/Documentation/translations/it_IT/process/kernel-docs.rst
@@ -6,8 +6,8 @@
 
 .. _it_kernel_docs:
 
-Indice di documenti per le persone interessate a capire e/o scrivere per il kernel Linux
-========================================================================================
+Ulteriore Documentazione Del Kernel Linux
+=========================================
 
 .. note::
    Questo documento contiene riferimenti a documenti in lingua inglese; inoltre
diff --git a/Documentation/translations/it_IT/process/maintainer-pgp-guide.rst b/Documentation/translations/it_IT/process/maintainer-pgp-guide.rst
index a1e98ec9532e..4bd7a8a66904 100644
--- a/Documentation/translations/it_IT/process/maintainer-pgp-guide.rst
+++ b/Documentation/translations/it_IT/process/maintainer-pgp-guide.rst
@@ -286,9 +286,7 @@ magari in una cassetta di sicurezza in banca.
     Probabilmente la vostra stampante non è più quello stupido dispositivo
     connesso alla porta parallela, ma dato che il suo output è comunque
     criptato con la passphrase, eseguire la stampa in un sistema "cloud"
-    moderno dovrebbe essere comunque relativamente sicuro. Un'opzione potrebbe
-    essere quella di cambiare la passphrase della vostra chiave primaria
-    subito dopo aver finito con paperkey.
+    moderno dovrebbe essere comunque relativamente sicuro.
 
 Copia di riserva di tutta la cartella GnuPG
 -------------------------------------------
-- 
2.30.2


^ permalink raw reply related	[relevance 4%]

* [PATCH V2] doc:it_IT: align Italian documentation
@ 2022-12-30 17:31  4% Federico Vaga
  0 siblings, 0 replies; 200+ results
From: Federico Vaga @ 2022-12-30 17:31 UTC (permalink / raw)
  To: Jonathan Corbet; +Cc: Federico Vaga, linux-doc, linux-kernel

Translation for the following patches

commit da4288b95baa ("scripts/check-local-export: avoid 'wait $!' for process substitution")
commit 5372de4e4545 ("docs/doc-guide: Put meta title for kernel-doc HTML page")
commit 4d627ef12b40 ("docs/doc-guide: Mention make variable SPHINXDIRS")
commit 7c43214dddfd ("docs/doc-guide: Add footnote on Inkscape for better images in PDF documents")
commit 615041d42a1a ("docs: kernel-docs: shorten the lengthy doc title")
commit cbf4adfd4d19 ("Documentation: process: Update email client instructions for Thunderbird")
commit e72b3b9810dd ("maintainer-pgp-guide: minor wording tweaks")
commit ea522496afa1 ("Documentation: process: replace outdated LTS table w/ link")
commit 93431e0607e5 ("Replace HTTP links with HTTPS ones: documentation")
commit e648174b53f1 ("Documentation: Fix spelling mistake in hacking.rst")
commit 602684adb42a ("docs: Update version number from 5.x to 6.x in README.rst")
commit 489876063fb1 ("docs: add a man-pages link to the front page")
commit 0c7b4366f1ab ("docs: Rewrite the front page")

Signed-off-by: Federico Vaga <federico.vaga@vaga.pv.it>
---
V1 -> V2 fix typo in footnote link

 .../translations/it_IT/admin-guide/README.rst |  2 +-
 .../it_IT/doc-guide/kernel-doc.rst            |  2 +
 .../translations/it_IT/doc-guide/sphinx.rst   | 14 ++-
 Documentation/translations/it_IT/index.rst    | 93 +++++++++----------
 .../it_IT/kernel-hacking/hacking.rst          |  2 +-
 .../translations/it_IT/process/2.Process.rst  | 15 +--
 .../it_IT/process/7.AdvancedTopics.rst        |  8 +-
 .../translations/it_IT/process/changes.rst    | 11 +++
 .../it_IT/process/email-clients.rst           | 67 ++++++++-----
 .../it_IT/process/kernel-docs.rst             |  4 +-
 .../it_IT/process/maintainer-pgp-guide.rst    |  4 +-
 11 files changed, 127 insertions(+), 95 deletions(-)



diff --git a/Documentation/translations/it_IT/admin-guide/README.rst b/Documentation/translations/it_IT/admin-guide/README.rst
index b37166817842..c874586a9af9 100644
--- a/Documentation/translations/it_IT/admin-guide/README.rst
+++ b/Documentation/translations/it_IT/admin-guide/README.rst
@@ -4,7 +4,7 @@
 
 .. _it_readme:
 
-Rilascio del kernel Linux  5.x <http://kernel.org/>
+Rilascio del kernel Linux  6.x <http://kernel.org/>
 ===================================================
 
 .. warning::
diff --git a/Documentation/translations/it_IT/doc-guide/kernel-doc.rst b/Documentation/translations/it_IT/doc-guide/kernel-doc.rst
index 78082281acf9..5cece223b46b 100644
--- a/Documentation/translations/it_IT/doc-guide/kernel-doc.rst
+++ b/Documentation/translations/it_IT/doc-guide/kernel-doc.rst
@@ -3,6 +3,8 @@
 .. note:: Per leggere la documentazione originale in inglese:
 	  :ref:`Documentation/doc-guide/index.rst <doc_guide>`
 
+.. title:: Commenti in kernel-doc
+
 .. _it_kernel_doc:
 
 =================================
diff --git a/Documentation/translations/it_IT/doc-guide/sphinx.rst b/Documentation/translations/it_IT/doc-guide/sphinx.rst
index 64528790dc34..1f513bc33618 100644
--- a/Documentation/translations/it_IT/doc-guide/sphinx.rst
+++ b/Documentation/translations/it_IT/doc-guide/sphinx.rst
@@ -151,7 +151,8 @@ Ovviamente, per generare la documentazione, Sphinx (``sphinx-build``)
 dev'essere installato. Se disponibile, il tema *Read the Docs* per Sphinx
 verrà utilizzato per ottenere una documentazione HTML più gradevole.
 Per la documentazione in formato PDF, invece, avrete bisogno di ``XeLaTeX`
-e di ``convert(1)`` disponibile in ImageMagick (https://www.imagemagick.org).
+e di ``convert(1)`` disponibile in ImageMagick
+(https://www.imagemagick.org). \ [#ink]_
 Tipicamente, tutti questi pacchetti sono disponibili e pacchettizzati nelle
 distribuzioni Linux.
 
@@ -162,9 +163,20 @@ la generazione potete usare il seguente comando ``make SPHINXOPTS=-v htmldocs``.
 Potete anche personalizzare l'ouptut html passando un livello aggiuntivo
 DOCS_CSS usando la rispettiva variabile d'ambiente ``DOCS_CSS``.
 
+La variable make ``SPHINXDIRS`` è utile quando si vuole generare solo una parte
+della documentazione. Per esempio, si possono generare solo di documenti in
+``Documentation/doc-guide`` eseguendo ``make SPHINXDIRS=doc-guide htmldocs``. La
+sezione dedicata alla documentazione di ``make help`` vi mostrerà quali sotto
+cartelle potete specificare.
+
 Potete eliminare la documentazione generata tramite il comando
 ``make cleandocs``.
 
+.. [#ink] Avere installato anche ``inkscape(1)`` dal progetto Inkscape ()
+          potrebbe aumentare la qualità delle immagini che verranno integrate
+          nel documento PDF, specialmente per quando si usando rilasci del
+          kernel uguali o superiori a 5.18
+
 Scrivere la documentazione
 ==========================
 
diff --git a/Documentation/translations/it_IT/index.rst b/Documentation/translations/it_IT/index.rst
index e80a3097aa57..5dd751349adc 100644
--- a/Documentation/translations/it_IT/index.rst
+++ b/Documentation/translations/it_IT/index.rst
@@ -1,13 +1,11 @@
+.. SPDX-License-Identifier: GPL-2.0
+
 .. _it_linux_doc:
 
 ===================
 Traduzione italiana
 ===================
 
-.. raw:: latex
-
-	\kerneldocCJKoff
-
 :manutentore: Federico Vaga <federico.vaga@vaga.pv.it>
 
 .. _it_disclaimer:
@@ -67,75 +65,68 @@ I miglioramenti alla documentazione sono sempre i benvenuti; per cui,
 se vuoi aiutare, iscriviti alla lista di discussione linux-doc presso
 vger.kernel.org.
 
-Documentazione sulla licenza dei sorgenti
------------------------------------------
-
-I seguenti documenti descrivono la licenza usata nei sorgenti del kernel Linux
-(GPLv2), come licenziare i singoli file; inoltre troverete i riferimenti al
-testo integrale della licenza.
+Lavorare con la comunità di sviluppo
+------------------------------------
 
-* :ref:`it_kernel_licensing`
+Le guide fondamentali per l'interazione con la comunità di sviluppo del kernel e
+su come vedere il proprio lavoro integrato.
 
-Documentazione per gli utenti
------------------------------
-
-I seguenti manuali sono scritti per gli *utenti* del kernel - ovvero,
-coloro che cercano di farlo funzionare in modo ottimale su un dato sistema
-
-.. warning::
+.. toctree::
+   :maxdepth: 1
 
-    TODO ancora da tradurre
+   process/development-process
+   process/submitting-patches
+   Code of conduct <process/code-of-conduct>
+   All development-process docs <process/index>
 
-Documentazione per gli sviluppatori di applicazioni
----------------------------------------------------
 
-Il manuale delle API verso lo spazio utente è una collezione di documenti
-che descrivono le interfacce del kernel viste dagli sviluppatori
-di applicazioni.
+Manuali sull'API interna
+------------------------
 
-.. warning::
+Di seguito una serie di manuali per gli sviluppatori che hanno bisogno di
+interfacciarsi con il resto del kernel.
 
-    TODO ancora da tradurre
+.. toctree::
+   :maxdepth: 1
 
+   core-api/index
 
-Introduzione allo sviluppo del kernel
--------------------------------------
+Strumenti e processi per lo sviluppo
+------------------------------------
 
-Questi manuali contengono informazioni su come contribuire allo sviluppo
-del kernel.
-Attorno al kernel Linux gira una comunità molto grande con migliaia di
-sviluppatori che contribuiscono ogni anno. Come in ogni grande comunità,
-sapere come le cose vengono fatte renderà il processo di integrazione delle
-vostre modifiche molto più semplice
+Di seguito una serie di manuali contenenti informazioni utili a tutti gli
+sviluppatori del kernel.
 
 .. toctree::
-   :maxdepth: 2
+   :maxdepth: 1
 
-   process/index
+   process/license-rules
    doc-guide/index
    kernel-hacking/index
 
-Documentazione della API del kernel
------------------------------------
+Documentazione per gli utenti
+-----------------------------
 
-Questi manuali forniscono dettagli su come funzionano i sottosistemi del
-kernel dal punto di vista degli sviluppatori del kernel. Molte delle
-informazioni contenute in questi manuali sono prese direttamente dai
-file sorgenti, informazioni aggiuntive vengono aggiunte solo se necessarie
-(o almeno ci proviamo — probabilmente *non* tutto quello che è davvero
-necessario).
+Di seguito una serie di manuali per gli *utenti* del kernel - ovvero coloro che
+stanno cercando di farlo funzionare al meglio per un dato sistema, ma anche
+coloro che stanno sviluppando applicazioni che sfruttano l'API verso lo
+spazio-utente.
 
-.. toctree::
-   :maxdepth: 2
+Consultate anche `Linux man pages <https://www.kernel.org/doc/man-pages/>`_, che
+vengono mantenuti separatamente dalla documentazione del kernel Linux
+
+Documentazione relativa ai firmware
+-----------------------------------
+Di seguito informazioni sulle aspettative del kernel circa i firmware.
 
-   core-api/index
 
 Documentazione specifica per architettura
 -----------------------------------------
 
-Questi manuali forniscono dettagli di programmazione per le diverse
-implementazioni d'architettura.
 
-.. warning::
+Documentazione varia
+--------------------
 
-    TODO ancora da tradurre
+Ci sono documenti che sono difficili da inserire nell'attuale organizzazione
+della documentazione; altri hanno bisogno di essere migliorati e/o convertiti
+nel formato *ReStructured Text*; altri sono semplicamente troppo vecchi.
diff --git a/Documentation/translations/it_IT/kernel-hacking/hacking.rst b/Documentation/translations/it_IT/kernel-hacking/hacking.rst
index 560f1d0482d2..dd06bfc1a050 100644
--- a/Documentation/translations/it_IT/kernel-hacking/hacking.rst
+++ b/Documentation/translations/it_IT/kernel-hacking/hacking.rst
@@ -137,7 +137,7 @@ macro :c:func:`in_softirq()` (``include/linux/preempt.h``).
 .. warning::
 
     State attenti che questa macro ritornerà un falso positivo
-    se :ref:`botton half lock <it_local_bh_disable>` è bloccato.
+    se :ref:`bottom half lock <it_local_bh_disable>` è bloccato.
 
 Alcune regole basilari
 ======================
diff --git a/Documentation/translations/it_IT/process/2.Process.rst b/Documentation/translations/it_IT/process/2.Process.rst
index 62826034e0b2..25cd00351c03 100644
--- a/Documentation/translations/it_IT/process/2.Process.rst
+++ b/Documentation/translations/it_IT/process/2.Process.rst
@@ -136,18 +136,11 @@ Quindi, per esempio, la storia del kernel 5.2 appare così (anno 2019):
 La 5.2.21 fu l'aggiornamento finale per la versione 5.2.
 
 Alcuni kernel sono destinati ad essere kernel a "lungo termine"; questi
-riceveranno assistenza per un lungo periodo di tempo.  Al momento in cui
-scriviamo, i manutentori dei kernel stabili a lungo termine sono:
-
-	======  ================================  ==========================================
-	3.16	Ben Hutchings			  (kernel stabile molto più a lungo termine)
-	4.4	Greg Kroah-Hartman e Sasha Levin  (kernel stabile molto più a lungo termine)
-	4.9	Greg Kroah-Hartman e Sasha Levin
-	4.14	Greg Kroah-Hartman e Sasha Levin
-	4.19	Greg Kroah-Hartman e Sasha Levin
-	5.4i	Greg Kroah-Hartman e Sasha Levin
-	======  ================================  ==========================================
+riceveranno assistenza per un lungo periodo di tempo. Consultate il seguente
+collegamento per avere la lista delle versioni attualmente supportate e i
+relativi manutentori:
 
+       https://www.kernel.org/category/releases.html
 
 Questa selezione di kernel di lungo periodo sono puramente dovuti ai loro
 manutentori, alla loro necessità e al tempo per tenere aggiornate proprio
diff --git a/Documentation/translations/it_IT/process/7.AdvancedTopics.rst b/Documentation/translations/it_IT/process/7.AdvancedTopics.rst
index cc1cff5d23ae..dffd813a0910 100644
--- a/Documentation/translations/it_IT/process/7.AdvancedTopics.rst
+++ b/Documentation/translations/it_IT/process/7.AdvancedTopics.rst
@@ -35,9 +35,9 @@ git è parte del processo di sviluppo del kernel.  Gli sviluppatori che
 desiderassero diventare agili con git troveranno più informazioni ai
 seguenti indirizzi:
 
-	http://git-scm.com/
+	https://git-scm.com/
 
-	http://www.kernel.org/pub/software/scm/git/docs/user-manual.html
+	https://www.kernel.org/pub/software/scm/git/docs/user-manual.html
 
 e su varie guide che potrete trovare su internet.
 
@@ -63,7 +63,7 @@ eseguire git-daemon è relativamente semplice .  Altrimenti, iniziano a
 svilupparsi piattaforme che offrono spazi pubblici, e gratuiti (Github,
 per esempio).  Gli sviluppatori permanenti possono ottenere un account
 su kernel.org, ma non è proprio facile da ottenere; per maggiori informazioni
-consultate la pagina web http://kernel.org/faq/.
+consultate la pagina web https://kernel.org/faq/.
 
 In git è normale avere a che fare con tanti rami.  Ogni linea di sviluppo
 può essere separata in "rami per argomenti" e gestiti indipendentemente.
@@ -137,7 +137,7 @@ vostri rami.  Citando Linus
 	facendo, e ho bisogno di fidarmi *senza* dover passare tutte
 	le modifiche manualmente una per una.
 
-(http://lwn.net/Articles/224135/).
+(https://lwn.net/Articles/224135/).
 
 Per evitare queste situazioni, assicuratevi che tutte le patch in un ramo
 siano strettamente correlate al tema delle modifiche; un ramo "driver fixes"
diff --git a/Documentation/translations/it_IT/process/changes.rst b/Documentation/translations/it_IT/process/changes.rst
index 10e0ef9c34b7..473ec2cc558e 100644
--- a/Documentation/translations/it_IT/process/changes.rst
+++ b/Documentation/translations/it_IT/process/changes.rst
@@ -35,6 +35,7 @@ PC Card, per esempio, probabilmente non dovreste preoccuparvi di pcmciautils.
 GNU C                  5.1                gcc --version
 Clang/LLVM (optional)  11.0.0             clang --version
 GNU make               3.81               make --version
+bash                   4.2                bash --version
 binutils               2.23               ld -v
 flex                   2.5.35             flex --version
 bison                  2.0                bison --version
@@ -88,6 +89,11 @@ Make
 
 Per compilare il kernel vi servirà GNU make 3.81 o successivo.
 
+Bash
+----
+Per generare il kernel vengono usati alcuni script per bash.
+Questo richiede bash 4.2 o successivo.
+
 Binutils
 --------
 
@@ -370,6 +376,11 @@ Make
 
 - <ftp://ftp.gnu.org/gnu/make/>
 
+Bash
+----
+
+- <ftp://ftp.gnu.org/gnu/bash/>
+
 Binutils
 --------
 
diff --git a/Documentation/translations/it_IT/process/email-clients.rst b/Documentation/translations/it_IT/process/email-clients.rst
index b792f2f06a74..970671cd91af 100644
--- a/Documentation/translations/it_IT/process/email-clients.rst
+++ b/Documentation/translations/it_IT/process/email-clients.rst
@@ -288,37 +288,62 @@ Thunderbird (GUI)
 Thunderbird è un clone di Outlook a cui piace maciullare il testo, ma esistono
 modi per impedirglielo.
 
+Dopo la configurazione, inclusa l'installazione delle estenzioni, dovrete
+riavviare Thunderbird.
+
 - permettere l'uso di editor esterni:
+
   La cosa più semplice da fare con Thunderbird e le patch è quello di usare
-  l'estensione "external editor" e di usare il vostro ``$EDITOR`` preferito per
-  leggere/includere patch nel vostro messaggio.  Per farlo, scaricate ed
-  installate l'estensione e aggiungete un bottone per chiamarla rapidamente
-  usando :menuselection:`Visualizza-->Barra degli strumenti-->Personalizza...`;
-  una volta fatto potrete richiamarlo premendo sul bottone mentre siete nella
-  finestra :menuselection:`Scrivi`
-
-  Tenete presente che "external editor" richiede che il vostro editor non
-  faccia alcun fork, in altre parole, l'editor non deve ritornare prima di
-  essere stato chiuso.  Potreste dover passare dei parametri aggiuntivi al
-  vostro editor oppure cambiargli la configurazione.  Per esempio, usando
-  gvim dovrete aggiungere l'opzione -f ``/usr/bin/gvim -f`` (Se il binario
-  si trova in ``/usr/bin``) nell'apposito campo nell'interfaccia di
-  configurazione di  :menuselection:`external editor`.  Se usate altri editor
-  consultate il loro  manuale per sapere come configurarli.
+  estensioni che permettano di aprire il vostro editor preferito.
+
+  Di seguito alcune estensioni che possono essere utili al caso.
+
+  - "External Editor Revived"
+
+    https://github.com/Frederick888/external-editor-revived
+
+    https://addons.thunderbird.net/en-GB/thunderbird/addon/external-editor-revived/
+
+    L'estensione richiede l'installazione di "native messaging host". Date
+    un'occhiata alla seguente wiki:
+    https://github.com/Frederick888/external-editor-revived/wiki
+
+  - "External Editor"
+
+    https://github.com/exteditor/exteditor
+
+    Per usarlo, scaricate ed installate l'applicazione. Poi aprite la finestra
+    :menuselection:`Scrivi` e a seguire aggiungete un bottone per eseguirlo
+    `Visualizza-->Barra degli strumenti-->Personalizza...`. Infine, premente
+    questo nuovo bottone tutte le volte che volete usare l'editor esterno.
+
+    Tenete presente che "external editor" richiede che il vostro editor non
+    faccia alcun fork, in altre parole, l'editor non deve ritornare prima di
+    essere stato chiuso.  Potreste dover passare dei parametri aggiuntivi al
+    vostro editor oppure cambiargli la configurazione.  Per esempio, usando
+    gvim dovrete aggiungere l'opzione -f ``/usr/bin/gvim -f`` (Se il binario
+    si trova in ``/usr/bin``) nell'apposito campo nell'interfaccia di
+    configurazione di  :menuselection:`external editor`.  Se usate altri editor
+    consultate il loro  manuale per sapere come configurarli.``)``
 
 Per rendere l'editor interno un po' più sensato, fate così:
 
-- Modificate le impostazioni di Thunderbird per far si che non usi
-  ``format=flowed``. Andate in :menuselection:`Modifica-->Preferenze-->Avanzate-->Editor di configurazione`
+- Modificate le impostazioni di Thunderbird per far si che non usi ``format=flowed``!
+  Andate sulla finestra principale e cercate il bottone per il menu a tendina principale.
+  Poi :menuselection:`Modifica-->Preferenze-->Avanzate-->Editor di configurazione`
   per invocare il registro delle impostazioni.
 
-- impostate ``mailnews.send_plaintext_flowed`` a ``false``
+  - impostate ``mailnews.send_plaintext_flowed`` a ``false``
 
-- impostate ``mailnews.wraplength`` da ``72`` a ``0``
+  - impostate ``mailnews.wraplength`` da ``72`` a ``0``
 
-- :menuselection:`Visualizza-->Corpo del messaggio come-->Testo semplice`
+- Non scrivete messaggi HTML! Andate sulla finestra principale ed aprite la
+  schermata :menuselection:`Menu principale-->Impostazioni account-->nome@unserver.ovunque-->Composizioni e indirizzi`.
+  Qui potrete disabilitare l'opzione "Componi i messaggi in HTML"
 
-- :menuselection:`Visualizza-->Codifica del testo-->Unicode`
+- Aprite i messaggi solo in formato testo! Andate sulla finestra principale e
+  selezionate
+  :menuselection:`Menu principale-->Visualizza-->Copro del messaggio come-->Testo semplice`
 
 
 TkRat (GUI)
diff --git a/Documentation/translations/it_IT/process/kernel-docs.rst b/Documentation/translations/it_IT/process/kernel-docs.rst
index 38e0a955121a..eadcbf50a1b5 100644
--- a/Documentation/translations/it_IT/process/kernel-docs.rst
+++ b/Documentation/translations/it_IT/process/kernel-docs.rst
@@ -6,8 +6,8 @@
 
 .. _it_kernel_docs:
 
-Indice di documenti per le persone interessate a capire e/o scrivere per il kernel Linux
-========================================================================================
+Ulteriore Documentazione Del Kernel Linux
+=========================================
 
 .. note::
    Questo documento contiene riferimenti a documenti in lingua inglese; inoltre
diff --git a/Documentation/translations/it_IT/process/maintainer-pgp-guide.rst b/Documentation/translations/it_IT/process/maintainer-pgp-guide.rst
index a1e98ec9532e..4bd7a8a66904 100644
--- a/Documentation/translations/it_IT/process/maintainer-pgp-guide.rst
+++ b/Documentation/translations/it_IT/process/maintainer-pgp-guide.rst
@@ -286,9 +286,7 @@ magari in una cassetta di sicurezza in banca.
     Probabilmente la vostra stampante non è più quello stupido dispositivo
     connesso alla porta parallela, ma dato che il suo output è comunque
     criptato con la passphrase, eseguire la stampa in un sistema "cloud"
-    moderno dovrebbe essere comunque relativamente sicuro. Un'opzione potrebbe
-    essere quella di cambiare la passphrase della vostra chiave primaria
-    subito dopo aver finito con paperkey.
+    moderno dovrebbe essere comunque relativamente sicuro.
 
 Copia di riserva di tutta la cartella GnuPG
 -------------------------------------------
-- 
2.30.2


^ permalink raw reply related	[relevance 4%]

* [PATCH] doc:it_IT: align Italian documentation
@ 2022-12-30 17:25  4% Federico Vaga
  0 siblings, 0 replies; 200+ results
From: Federico Vaga @ 2022-12-30 17:25 UTC (permalink / raw)
  To: Jonathan Corbet; +Cc: Federico Vaga, linux-doc, linux-kernel

Translation for the following patches

commit da4288b95baa ("scripts/check-local-export: avoid 'wait $!' for process substitution")
commit 5372de4e4545 ("docs/doc-guide: Put meta title for kernel-doc HTML page")
commit 4d627ef12b40 ("docs/doc-guide: Mention make variable SPHINXDIRS")
commit 7c43214dddfd ("docs/doc-guide: Add footnote on Inkscape for better images in PDF documents")
commit 615041d42a1a ("docs: kernel-docs: shorten the lengthy doc title")
commit cbf4adfd4d19 ("Documentation: process: Update email client instructions for Thunderbird")
commit e72b3b9810dd ("maintainer-pgp-guide: minor wording tweaks")
commit ea522496afa1 ("Documentation: process: replace outdated LTS table w/ link")
commit 93431e0607e5 ("Replace HTTP links with HTTPS ones: documentation")
commit e648174b53f1 ("Documentation: Fix spelling mistake in hacking.rst")
commit 602684adb42a ("docs: Update version number from 5.x to 6.x in README.rst")
commit 489876063fb1 ("docs: add a man-pages link to the front page")
commit 0c7b4366f1ab ("docs: Rewrite the front page")

Signed-off-by: Federico Vaga <federico.vaga@vaga.pv.it>
---
 .../translations/it_IT/admin-guide/README.rst |  2 +-
 .../it_IT/doc-guide/kernel-doc.rst            |  2 +
 .../translations/it_IT/doc-guide/sphinx.rst   | 14 ++-
 Documentation/translations/it_IT/index.rst    | 93 +++++++++----------
 .../it_IT/kernel-hacking/hacking.rst          |  2 +-
 .../translations/it_IT/process/2.Process.rst  | 15 +--
 .../it_IT/process/7.AdvancedTopics.rst        |  8 +-
 .../translations/it_IT/process/changes.rst    | 11 +++
 .../it_IT/process/email-clients.rst           | 67 ++++++++-----
 .../it_IT/process/kernel-docs.rst             |  4 +-
 .../it_IT/process/maintainer-pgp-guide.rst    |  4 +-
 11 files changed, 127 insertions(+), 95 deletions(-)

diff --git a/Documentation/translations/it_IT/admin-guide/README.rst b/Documentation/translations/it_IT/admin-guide/README.rst
index b37166817842..c874586a9af9 100644
--- a/Documentation/translations/it_IT/admin-guide/README.rst
+++ b/Documentation/translations/it_IT/admin-guide/README.rst
@@ -4,7 +4,7 @@
 
 .. _it_readme:
 
-Rilascio del kernel Linux  5.x <http://kernel.org/>
+Rilascio del kernel Linux  6.x <http://kernel.org/>
 ===================================================
 
 .. warning::
diff --git a/Documentation/translations/it_IT/doc-guide/kernel-doc.rst b/Documentation/translations/it_IT/doc-guide/kernel-doc.rst
index 78082281acf9..5cece223b46b 100644
--- a/Documentation/translations/it_IT/doc-guide/kernel-doc.rst
+++ b/Documentation/translations/it_IT/doc-guide/kernel-doc.rst
@@ -3,6 +3,8 @@
 .. note:: Per leggere la documentazione originale in inglese:
 	  :ref:`Documentation/doc-guide/index.rst <doc_guide>`
 
+.. title:: Commenti in kernel-doc
+
 .. _it_kernel_doc:
 
 =================================
diff --git a/Documentation/translations/it_IT/doc-guide/sphinx.rst b/Documentation/translations/it_IT/doc-guide/sphinx.rst
index 64528790dc34..3030eedcff88 100644
--- a/Documentation/translations/it_IT/doc-guide/sphinx.rst
+++ b/Documentation/translations/it_IT/doc-guide/sphinx.rst
@@ -151,7 +151,8 @@ Ovviamente, per generare la documentazione, Sphinx (``sphinx-build``)
 dev'essere installato. Se disponibile, il tema *Read the Docs* per Sphinx
 verrà utilizzato per ottenere una documentazione HTML più gradevole.
 Per la documentazione in formato PDF, invece, avrete bisogno di ``XeLaTeX`
-e di ``convert(1)`` disponibile in ImageMagick (https://www.imagemagick.org).
+e di ``convert(1)`` disponibile in ImageMagick
+(https://www.imagemagick.org). \ [#ink]__
 Tipicamente, tutti questi pacchetti sono disponibili e pacchettizzati nelle
 distribuzioni Linux.
 
@@ -162,9 +163,20 @@ la generazione potete usare il seguente comando ``make SPHINXOPTS=-v htmldocs``.
 Potete anche personalizzare l'ouptut html passando un livello aggiuntivo
 DOCS_CSS usando la rispettiva variabile d'ambiente ``DOCS_CSS``.
 
+La variable make ``SPHINXDIRS`` è utile quando si vuole generare solo una parte
+della documentazione. Per esempio, si possono generare solo di documenti in
+``Documentation/doc-guide`` eseguendo ``make SPHINXDIRS=doc-guide htmldocs``. La
+sezione dedicata alla documentazione di ``make help`` vi mostrerà quali sotto
+cartelle potete specificare.
+
 Potete eliminare la documentazione generata tramite il comando
 ``make cleandocs``.
 
+.. [#ink] Avere installato anche ``inkscape(1)`` dal progetto Inkscape ()
+          potrebbe aumentare la qualità delle immagini che verranno integrate
+          nel documento PDF, specialmente per quando si usando rilasci del
+          kernel uguali o superiori a 5.18
+
 Scrivere la documentazione
 ==========================
 
diff --git a/Documentation/translations/it_IT/index.rst b/Documentation/translations/it_IT/index.rst
index e80a3097aa57..5dd751349adc 100644
--- a/Documentation/translations/it_IT/index.rst
+++ b/Documentation/translations/it_IT/index.rst
@@ -1,13 +1,11 @@
+.. SPDX-License-Identifier: GPL-2.0
+
 .. _it_linux_doc:
 
 ===================
 Traduzione italiana
 ===================
 
-.. raw:: latex
-
-	\kerneldocCJKoff
-
 :manutentore: Federico Vaga <federico.vaga@vaga.pv.it>
 
 .. _it_disclaimer:
@@ -67,75 +65,68 @@ I miglioramenti alla documentazione sono sempre i benvenuti; per cui,
 se vuoi aiutare, iscriviti alla lista di discussione linux-doc presso
 vger.kernel.org.
 
-Documentazione sulla licenza dei sorgenti
------------------------------------------
-
-I seguenti documenti descrivono la licenza usata nei sorgenti del kernel Linux
-(GPLv2), come licenziare i singoli file; inoltre troverete i riferimenti al
-testo integrale della licenza.
+Lavorare con la comunità di sviluppo
+------------------------------------
 
-* :ref:`it_kernel_licensing`
+Le guide fondamentali per l'interazione con la comunità di sviluppo del kernel e
+su come vedere il proprio lavoro integrato.
 
-Documentazione per gli utenti
------------------------------
-
-I seguenti manuali sono scritti per gli *utenti* del kernel - ovvero,
-coloro che cercano di farlo funzionare in modo ottimale su un dato sistema
-
-.. warning::
+.. toctree::
+   :maxdepth: 1
 
-    TODO ancora da tradurre
+   process/development-process
+   process/submitting-patches
+   Code of conduct <process/code-of-conduct>
+   All development-process docs <process/index>
 
-Documentazione per gli sviluppatori di applicazioni
----------------------------------------------------
 
-Il manuale delle API verso lo spazio utente è una collezione di documenti
-che descrivono le interfacce del kernel viste dagli sviluppatori
-di applicazioni.
+Manuali sull'API interna
+------------------------
 
-.. warning::
+Di seguito una serie di manuali per gli sviluppatori che hanno bisogno di
+interfacciarsi con il resto del kernel.
 
-    TODO ancora da tradurre
+.. toctree::
+   :maxdepth: 1
 
+   core-api/index
 
-Introduzione allo sviluppo del kernel
--------------------------------------
+Strumenti e processi per lo sviluppo
+------------------------------------
 
-Questi manuali contengono informazioni su come contribuire allo sviluppo
-del kernel.
-Attorno al kernel Linux gira una comunità molto grande con migliaia di
-sviluppatori che contribuiscono ogni anno. Come in ogni grande comunità,
-sapere come le cose vengono fatte renderà il processo di integrazione delle
-vostre modifiche molto più semplice
+Di seguito una serie di manuali contenenti informazioni utili a tutti gli
+sviluppatori del kernel.
 
 .. toctree::
-   :maxdepth: 2
+   :maxdepth: 1
 
-   process/index
+   process/license-rules
    doc-guide/index
    kernel-hacking/index
 
-Documentazione della API del kernel
------------------------------------
+Documentazione per gli utenti
+-----------------------------
 
-Questi manuali forniscono dettagli su come funzionano i sottosistemi del
-kernel dal punto di vista degli sviluppatori del kernel. Molte delle
-informazioni contenute in questi manuali sono prese direttamente dai
-file sorgenti, informazioni aggiuntive vengono aggiunte solo se necessarie
-(o almeno ci proviamo — probabilmente *non* tutto quello che è davvero
-necessario).
+Di seguito una serie di manuali per gli *utenti* del kernel - ovvero coloro che
+stanno cercando di farlo funzionare al meglio per un dato sistema, ma anche
+coloro che stanno sviluppando applicazioni che sfruttano l'API verso lo
+spazio-utente.
 
-.. toctree::
-   :maxdepth: 2
+Consultate anche `Linux man pages <https://www.kernel.org/doc/man-pages/>`_, che
+vengono mantenuti separatamente dalla documentazione del kernel Linux
+
+Documentazione relativa ai firmware
+-----------------------------------
+Di seguito informazioni sulle aspettative del kernel circa i firmware.
 
-   core-api/index
 
 Documentazione specifica per architettura
 -----------------------------------------
 
-Questi manuali forniscono dettagli di programmazione per le diverse
-implementazioni d'architettura.
 
-.. warning::
+Documentazione varia
+--------------------
 
-    TODO ancora da tradurre
+Ci sono documenti che sono difficili da inserire nell'attuale organizzazione
+della documentazione; altri hanno bisogno di essere migliorati e/o convertiti
+nel formato *ReStructured Text*; altri sono semplicamente troppo vecchi.
diff --git a/Documentation/translations/it_IT/kernel-hacking/hacking.rst b/Documentation/translations/it_IT/kernel-hacking/hacking.rst
index 560f1d0482d2..dd06bfc1a050 100644
--- a/Documentation/translations/it_IT/kernel-hacking/hacking.rst
+++ b/Documentation/translations/it_IT/kernel-hacking/hacking.rst
@@ -137,7 +137,7 @@ macro :c:func:`in_softirq()` (``include/linux/preempt.h``).
 .. warning::
 
     State attenti che questa macro ritornerà un falso positivo
-    se :ref:`botton half lock <it_local_bh_disable>` è bloccato.
+    se :ref:`bottom half lock <it_local_bh_disable>` è bloccato.
 
 Alcune regole basilari
 ======================
diff --git a/Documentation/translations/it_IT/process/2.Process.rst b/Documentation/translations/it_IT/process/2.Process.rst
index 62826034e0b2..25cd00351c03 100644
--- a/Documentation/translations/it_IT/process/2.Process.rst
+++ b/Documentation/translations/it_IT/process/2.Process.rst
@@ -136,18 +136,11 @@ Quindi, per esempio, la storia del kernel 5.2 appare così (anno 2019):
 La 5.2.21 fu l'aggiornamento finale per la versione 5.2.
 
 Alcuni kernel sono destinati ad essere kernel a "lungo termine"; questi
-riceveranno assistenza per un lungo periodo di tempo.  Al momento in cui
-scriviamo, i manutentori dei kernel stabili a lungo termine sono:
-
-	======  ================================  ==========================================
-	3.16	Ben Hutchings			  (kernel stabile molto più a lungo termine)
-	4.4	Greg Kroah-Hartman e Sasha Levin  (kernel stabile molto più a lungo termine)
-	4.9	Greg Kroah-Hartman e Sasha Levin
-	4.14	Greg Kroah-Hartman e Sasha Levin
-	4.19	Greg Kroah-Hartman e Sasha Levin
-	5.4i	Greg Kroah-Hartman e Sasha Levin
-	======  ================================  ==========================================
+riceveranno assistenza per un lungo periodo di tempo. Consultate il seguente
+collegamento per avere la lista delle versioni attualmente supportate e i
+relativi manutentori:
 
+       https://www.kernel.org/category/releases.html
 
 Questa selezione di kernel di lungo periodo sono puramente dovuti ai loro
 manutentori, alla loro necessità e al tempo per tenere aggiornate proprio
diff --git a/Documentation/translations/it_IT/process/7.AdvancedTopics.rst b/Documentation/translations/it_IT/process/7.AdvancedTopics.rst
index cc1cff5d23ae..dffd813a0910 100644
--- a/Documentation/translations/it_IT/process/7.AdvancedTopics.rst
+++ b/Documentation/translations/it_IT/process/7.AdvancedTopics.rst
@@ -35,9 +35,9 @@ git è parte del processo di sviluppo del kernel.  Gli sviluppatori che
 desiderassero diventare agili con git troveranno più informazioni ai
 seguenti indirizzi:
 
-	http://git-scm.com/
+	https://git-scm.com/
 
-	http://www.kernel.org/pub/software/scm/git/docs/user-manual.html
+	https://www.kernel.org/pub/software/scm/git/docs/user-manual.html
 
 e su varie guide che potrete trovare su internet.
 
@@ -63,7 +63,7 @@ eseguire git-daemon è relativamente semplice .  Altrimenti, iniziano a
 svilupparsi piattaforme che offrono spazi pubblici, e gratuiti (Github,
 per esempio).  Gli sviluppatori permanenti possono ottenere un account
 su kernel.org, ma non è proprio facile da ottenere; per maggiori informazioni
-consultate la pagina web http://kernel.org/faq/.
+consultate la pagina web https://kernel.org/faq/.
 
 In git è normale avere a che fare con tanti rami.  Ogni linea di sviluppo
 può essere separata in "rami per argomenti" e gestiti indipendentemente.
@@ -137,7 +137,7 @@ vostri rami.  Citando Linus
 	facendo, e ho bisogno di fidarmi *senza* dover passare tutte
 	le modifiche manualmente una per una.
 
-(http://lwn.net/Articles/224135/).
+(https://lwn.net/Articles/224135/).
 
 Per evitare queste situazioni, assicuratevi che tutte le patch in un ramo
 siano strettamente correlate al tema delle modifiche; un ramo "driver fixes"
diff --git a/Documentation/translations/it_IT/process/changes.rst b/Documentation/translations/it_IT/process/changes.rst
index 10e0ef9c34b7..473ec2cc558e 100644
--- a/Documentation/translations/it_IT/process/changes.rst
+++ b/Documentation/translations/it_IT/process/changes.rst
@@ -35,6 +35,7 @@ PC Card, per esempio, probabilmente non dovreste preoccuparvi di pcmciautils.
 GNU C                  5.1                gcc --version
 Clang/LLVM (optional)  11.0.0             clang --version
 GNU make               3.81               make --version
+bash                   4.2                bash --version
 binutils               2.23               ld -v
 flex                   2.5.35             flex --version
 bison                  2.0                bison --version
@@ -88,6 +89,11 @@ Make
 
 Per compilare il kernel vi servirà GNU make 3.81 o successivo.
 
+Bash
+----
+Per generare il kernel vengono usati alcuni script per bash.
+Questo richiede bash 4.2 o successivo.
+
 Binutils
 --------
 
@@ -370,6 +376,11 @@ Make
 
 - <ftp://ftp.gnu.org/gnu/make/>
 
+Bash
+----
+
+- <ftp://ftp.gnu.org/gnu/bash/>
+
 Binutils
 --------
 
diff --git a/Documentation/translations/it_IT/process/email-clients.rst b/Documentation/translations/it_IT/process/email-clients.rst
index b792f2f06a74..970671cd91af 100644
--- a/Documentation/translations/it_IT/process/email-clients.rst
+++ b/Documentation/translations/it_IT/process/email-clients.rst
@@ -288,37 +288,62 @@ Thunderbird (GUI)
 Thunderbird è un clone di Outlook a cui piace maciullare il testo, ma esistono
 modi per impedirglielo.
 
+Dopo la configurazione, inclusa l'installazione delle estenzioni, dovrete
+riavviare Thunderbird.
+
 - permettere l'uso di editor esterni:
+
   La cosa più semplice da fare con Thunderbird e le patch è quello di usare
-  l'estensione "external editor" e di usare il vostro ``$EDITOR`` preferito per
-  leggere/includere patch nel vostro messaggio.  Per farlo, scaricate ed
-  installate l'estensione e aggiungete un bottone per chiamarla rapidamente
-  usando :menuselection:`Visualizza-->Barra degli strumenti-->Personalizza...`;
-  una volta fatto potrete richiamarlo premendo sul bottone mentre siete nella
-  finestra :menuselection:`Scrivi`
-
-  Tenete presente che "external editor" richiede che il vostro editor non
-  faccia alcun fork, in altre parole, l'editor non deve ritornare prima di
-  essere stato chiuso.  Potreste dover passare dei parametri aggiuntivi al
-  vostro editor oppure cambiargli la configurazione.  Per esempio, usando
-  gvim dovrete aggiungere l'opzione -f ``/usr/bin/gvim -f`` (Se il binario
-  si trova in ``/usr/bin``) nell'apposito campo nell'interfaccia di
-  configurazione di  :menuselection:`external editor`.  Se usate altri editor
-  consultate il loro  manuale per sapere come configurarli.
+  estensioni che permettano di aprire il vostro editor preferito.
+
+  Di seguito alcune estensioni che possono essere utili al caso.
+
+  - "External Editor Revived"
+
+    https://github.com/Frederick888/external-editor-revived
+
+    https://addons.thunderbird.net/en-GB/thunderbird/addon/external-editor-revived/
+
+    L'estensione richiede l'installazione di "native messaging host". Date
+    un'occhiata alla seguente wiki:
+    https://github.com/Frederick888/external-editor-revived/wiki
+
+  - "External Editor"
+
+    https://github.com/exteditor/exteditor
+
+    Per usarlo, scaricate ed installate l'applicazione. Poi aprite la finestra
+    :menuselection:`Scrivi` e a seguire aggiungete un bottone per eseguirlo
+    `Visualizza-->Barra degli strumenti-->Personalizza...`. Infine, premente
+    questo nuovo bottone tutte le volte che volete usare l'editor esterno.
+
+    Tenete presente che "external editor" richiede che il vostro editor non
+    faccia alcun fork, in altre parole, l'editor non deve ritornare prima di
+    essere stato chiuso.  Potreste dover passare dei parametri aggiuntivi al
+    vostro editor oppure cambiargli la configurazione.  Per esempio, usando
+    gvim dovrete aggiungere l'opzione -f ``/usr/bin/gvim -f`` (Se il binario
+    si trova in ``/usr/bin``) nell'apposito campo nell'interfaccia di
+    configurazione di  :menuselection:`external editor`.  Se usate altri editor
+    consultate il loro  manuale per sapere come configurarli.``)``
 
 Per rendere l'editor interno un po' più sensato, fate così:
 
-- Modificate le impostazioni di Thunderbird per far si che non usi
-  ``format=flowed``. Andate in :menuselection:`Modifica-->Preferenze-->Avanzate-->Editor di configurazione`
+- Modificate le impostazioni di Thunderbird per far si che non usi ``format=flowed``!
+  Andate sulla finestra principale e cercate il bottone per il menu a tendina principale.
+  Poi :menuselection:`Modifica-->Preferenze-->Avanzate-->Editor di configurazione`
   per invocare il registro delle impostazioni.
 
-- impostate ``mailnews.send_plaintext_flowed`` a ``false``
+  - impostate ``mailnews.send_plaintext_flowed`` a ``false``
 
-- impostate ``mailnews.wraplength`` da ``72`` a ``0``
+  - impostate ``mailnews.wraplength`` da ``72`` a ``0``
 
-- :menuselection:`Visualizza-->Corpo del messaggio come-->Testo semplice`
+- Non scrivete messaggi HTML! Andate sulla finestra principale ed aprite la
+  schermata :menuselection:`Menu principale-->Impostazioni account-->nome@unserver.ovunque-->Composizioni e indirizzi`.
+  Qui potrete disabilitare l'opzione "Componi i messaggi in HTML"
 
-- :menuselection:`Visualizza-->Codifica del testo-->Unicode`
+- Aprite i messaggi solo in formato testo! Andate sulla finestra principale e
+  selezionate
+  :menuselection:`Menu principale-->Visualizza-->Copro del messaggio come-->Testo semplice`
 
 
 TkRat (GUI)
diff --git a/Documentation/translations/it_IT/process/kernel-docs.rst b/Documentation/translations/it_IT/process/kernel-docs.rst
index 38e0a955121a..eadcbf50a1b5 100644
--- a/Documentation/translations/it_IT/process/kernel-docs.rst
+++ b/Documentation/translations/it_IT/process/kernel-docs.rst
@@ -6,8 +6,8 @@
 
 .. _it_kernel_docs:
 
-Indice di documenti per le persone interessate a capire e/o scrivere per il kernel Linux
-========================================================================================
+Ulteriore Documentazione Del Kernel Linux
+=========================================
 
 .. note::
    Questo documento contiene riferimenti a documenti in lingua inglese; inoltre
diff --git a/Documentation/translations/it_IT/process/maintainer-pgp-guide.rst b/Documentation/translations/it_IT/process/maintainer-pgp-guide.rst
index a1e98ec9532e..4bd7a8a66904 100644
--- a/Documentation/translations/it_IT/process/maintainer-pgp-guide.rst
+++ b/Documentation/translations/it_IT/process/maintainer-pgp-guide.rst
@@ -286,9 +286,7 @@ magari in una cassetta di sicurezza in banca.
     Probabilmente la vostra stampante non è più quello stupido dispositivo
     connesso alla porta parallela, ma dato che il suo output è comunque
     criptato con la passphrase, eseguire la stampa in un sistema "cloud"
-    moderno dovrebbe essere comunque relativamente sicuro. Un'opzione potrebbe
-    essere quella di cambiare la passphrase della vostra chiave primaria
-    subito dopo aver finito con paperkey.
+    moderno dovrebbe essere comunque relativamente sicuro.
 
 Copia di riserva di tutta la cartella GnuPG
 -------------------------------------------
-- 
2.30.2


^ permalink raw reply related	[relevance 4%]

* Re: [PATCH v2] Documentation: process: replace outdated LTS table w/ link
  2022-10-15  2:06  0%   ` Bagas Sanjaya
@ 2022-10-18  0:04  0%     ` Nick Desaulniers
  0 siblings, 0 replies; 200+ results
From: Nick Desaulniers @ 2022-10-18  0:04 UTC (permalink / raw)
  To: Bagas Sanjaya
  Cc: Jonathan Corbet, linux-doc, linux-kernel, Greg Kroah-Hartman,
	stable, Ben Hutchings, Sasha Levin, Tyler Hicks

On Fri, Oct 14, 2022 at 7:06 PM Bagas Sanjaya <bagasdotme@gmail.com> wrote:
>
> On 10/15/22 00:10, Nick Desaulniers wrote:
> > The existing table was a bit outdated.
> >
> > 3.16 was EOL in 2020.
> > 4.4 was EOL in 2022.
> >
> > 5.10 is new in 2020.
> > 5.15 is new in 2021.
> >
> > We'll see if 6.1 becomes LTS in 2022.
> >
> > Rather than keep this table updated, it does duplicate information from
> > multiple kernel.org pages. Make one less duplication site that needs to
> > be updated and simply refer to the kernel.org page on releases.
> >
> > Suggested-by: Tyler Hicks <code@tyhicks.com>
> > Suggested-by: Bagas Sanjaya <bagasdotme@gmail.com>
> > Signed-off-by: Nick Desaulniers <ndesaulniers@google.com>
> > Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
>
> Should this patch be backported to all stable releases? I see Cc: stable
> on message header, but not in the patch trailer.

I don't think so; unless people read stable versions of the
documentation rather than HEAD?
Perhaps I didn't need to cc stable, but I think that's ok for
notifying people who are interested in stable, not necessarily
strictly for backports?
Either way, thanks again for the reviews+suggestions.

>
> >  Some kernels are designated "long term" kernels; they will receive support
> > -for a longer period.  As of this writing, the current long term kernels
> > -and their maintainers are:
> > -
> > -     ======  ================================        =======================
> > -     3.16    Ben Hutchings                           (very long-term kernel)
> > -     4.4     Greg Kroah-Hartman & Sasha Levin        (very long-term kernel)
> > -     4.9     Greg Kroah-Hartman & Sasha Levin
> > -     4.14    Greg Kroah-Hartman & Sasha Levin
> > -     4.19    Greg Kroah-Hartman & Sasha Levin
> > -     5.4     Greg Kroah-Hartman & Sasha Levin
> > -     ======  ================================        =======================
> > +for a longer period.  Please refer to the following link for the list of active
> > +long term kernel versions and their maintainers:
> > +
> > +     https://www.kernel.org/category/releases.html
> >
>
> LGTM, thanks.
>
> Reviewed-by: Bagas Sanjaya <bagasdotme@gmail.com>
>
> --
> An old man doll... just what I always wanted! - Clara
>


-- 
Thanks,
~Nick Desaulniers

^ permalink raw reply	[relevance 0%]

* Re: [PATCH v2] Documentation: process: replace outdated LTS table w/ link
  2022-10-14 17:10 13% ` [PATCH v2] Documentation: process: replace outdated LTS table w/ link Nick Desaulniers
  2022-10-14 17:13  0%   ` Tyler Hicks
@ 2022-10-15  2:06  0%   ` Bagas Sanjaya
  2022-10-18  0:04  0%     ` Nick Desaulniers
  1 sibling, 1 reply; 200+ results
From: Bagas Sanjaya @ 2022-10-15  2:06 UTC (permalink / raw)
  To: Nick Desaulniers, Jonathan Corbet
  Cc: linux-doc, linux-kernel, Greg Kroah-Hartman, stable,
	Ben Hutchings, Sasha Levin, Tyler Hicks

On 10/15/22 00:10, Nick Desaulniers wrote:
> The existing table was a bit outdated.
> 
> 3.16 was EOL in 2020.
> 4.4 was EOL in 2022.
> 
> 5.10 is new in 2020.
> 5.15 is new in 2021.
> 
> We'll see if 6.1 becomes LTS in 2022.
> 
> Rather than keep this table updated, it does duplicate information from
> multiple kernel.org pages. Make one less duplication site that needs to
> be updated and simply refer to the kernel.org page on releases.
> 
> Suggested-by: Tyler Hicks <code@tyhicks.com>
> Suggested-by: Bagas Sanjaya <bagasdotme@gmail.com>
> Signed-off-by: Nick Desaulniers <ndesaulniers@google.com>
> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

Should this patch be backported to all stable releases? I see Cc: stable
on message header, but not in the patch trailer.

>  Some kernels are designated "long term" kernels; they will receive support
> -for a longer period.  As of this writing, the current long term kernels
> -and their maintainers are:
> -
> -	======  ================================	=======================
> -	3.16	Ben Hutchings				(very long-term kernel)
> -	4.4	Greg Kroah-Hartman & Sasha Levin	(very long-term kernel)
> -	4.9	Greg Kroah-Hartman & Sasha Levin
> -	4.14	Greg Kroah-Hartman & Sasha Levin
> -	4.19	Greg Kroah-Hartman & Sasha Levin
> -	5.4	Greg Kroah-Hartman & Sasha Levin
> -	======  ================================	=======================
> +for a longer period.  Please refer to the following link for the list of active
> +long term kernel versions and their maintainers:
> +
> +	https://www.kernel.org/category/releases.html
>  

LGTM, thanks.

Reviewed-by: Bagas Sanjaya <bagasdotme@gmail.com>

-- 
An old man doll... just what I always wanted! - Clara


^ permalink raw reply	[relevance 0%]

* Re: [PATCH v2] Documentation: process: replace outdated LTS table w/ link
  2022-10-14 17:10 13% ` [PATCH v2] Documentation: process: replace outdated LTS table w/ link Nick Desaulniers
@ 2022-10-14 17:13  0%   ` Tyler Hicks
  2022-10-15  2:06  0%   ` Bagas Sanjaya
  1 sibling, 0 replies; 200+ results
From: Tyler Hicks @ 2022-10-14 17:13 UTC (permalink / raw)
  To: Nick Desaulniers
  Cc: Jonathan Corbet, linux-doc, linux-kernel, Greg Kroah-Hartman,
	stable, Ben Hutchings, Sasha Levin, Bagas Sanjaya

On 2022-10-14 10:10:40, Nick Desaulniers wrote:
> The existing table was a bit outdated.
> 
> 3.16 was EOL in 2020.
> 4.4 was EOL in 2022.
> 
> 5.10 is new in 2020.
> 5.15 is new in 2021.
> 
> We'll see if 6.1 becomes LTS in 2022.
> 
> Rather than keep this table updated, it does duplicate information from
> multiple kernel.org pages. Make one less duplication site that needs to
> be updated and simply refer to the kernel.org page on releases.
> 
> Suggested-by: Tyler Hicks <code@tyhicks.com>
> Suggested-by: Bagas Sanjaya <bagasdotme@gmail.com>
> Signed-off-by: Nick Desaulniers <ndesaulniers@google.com>
> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> ---
> Changes v1 -> v2:
> * Rather than update table, use a link as per Tyler and Bagas.
> * Carry forward GKH's SB tag.

Thanks! Was just about to send out that same thing. :)

Reviewed-by: Tyler Hicks (Microsoft) <code@tyhicks.com>

Tyler

> 
>  Documentation/process/2.Process.rst | 15 ++++-----------
>  1 file changed, 4 insertions(+), 11 deletions(-)
> 
> diff --git a/Documentation/process/2.Process.rst b/Documentation/process/2.Process.rst
> index e05fb1b8f8b6..6a919cffcbfd 100644
> --- a/Documentation/process/2.Process.rst
> +++ b/Documentation/process/2.Process.rst
> @@ -126,17 +126,10 @@ than one development cycle past their initial release. So, for example, the
>  5.2.21 was the final stable update of the 5.2 release.
>  
>  Some kernels are designated "long term" kernels; they will receive support
> -for a longer period.  As of this writing, the current long term kernels
> -and their maintainers are:
> -
> -	======  ================================	=======================
> -	3.16	Ben Hutchings				(very long-term kernel)
> -	4.4	Greg Kroah-Hartman & Sasha Levin	(very long-term kernel)
> -	4.9	Greg Kroah-Hartman & Sasha Levin
> -	4.14	Greg Kroah-Hartman & Sasha Levin
> -	4.19	Greg Kroah-Hartman & Sasha Levin
> -	5.4	Greg Kroah-Hartman & Sasha Levin
> -	======  ================================	=======================
> +for a longer period.  Please refer to the following link for the list of active
> +long term kernel versions and their maintainers:
> +
> +	https://www.kernel.org/category/releases.html
>  
>  The selection of a kernel for long-term support is purely a matter of a
>  maintainer having the need and the time to maintain that release.  There
> 
> base-commit: 9c9155a3509a2ebdb06d77c7a621e9685c802eac
> -- 
> 2.38.0.413.g74048e4d9e-goog
> 

^ permalink raw reply	[relevance 0%]

* [PATCH v2] Documentation: process: replace outdated LTS table w/ link
  @ 2022-10-14 17:10 13% ` Nick Desaulniers
  2022-10-14 17:13  0%   ` Tyler Hicks
  2022-10-15  2:06  0%   ` Bagas Sanjaya
  0 siblings, 2 replies; 200+ results
From: Nick Desaulniers @ 2022-10-14 17:10 UTC (permalink / raw)
  To: Jonathan Corbet
  Cc: linux-doc, linux-kernel, Greg Kroah-Hartman, stable,
	Ben Hutchings, Sasha Levin, Nick Desaulniers, Tyler Hicks,
	Bagas Sanjaya

The existing table was a bit outdated.

3.16 was EOL in 2020.
4.4 was EOL in 2022.

5.10 is new in 2020.
5.15 is new in 2021.

We'll see if 6.1 becomes LTS in 2022.

Rather than keep this table updated, it does duplicate information from
multiple kernel.org pages. Make one less duplication site that needs to
be updated and simply refer to the kernel.org page on releases.

Suggested-by: Tyler Hicks <code@tyhicks.com>
Suggested-by: Bagas Sanjaya <bagasdotme@gmail.com>
Signed-off-by: Nick Desaulniers <ndesaulniers@google.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
Changes v1 -> v2:
* Rather than update table, use a link as per Tyler and Bagas.
* Carry forward GKH's SB tag.

 Documentation/process/2.Process.rst | 15 ++++-----------
 1 file changed, 4 insertions(+), 11 deletions(-)

diff --git a/Documentation/process/2.Process.rst b/Documentation/process/2.Process.rst
index e05fb1b8f8b6..6a919cffcbfd 100644
--- a/Documentation/process/2.Process.rst
+++ b/Documentation/process/2.Process.rst
@@ -126,17 +126,10 @@ than one development cycle past their initial release. So, for example, the
 5.2.21 was the final stable update of the 5.2 release.
 
 Some kernels are designated "long term" kernels; they will receive support
-for a longer period.  As of this writing, the current long term kernels
-and their maintainers are:
-
-	======  ================================	=======================
-	3.16	Ben Hutchings				(very long-term kernel)
-	4.4	Greg Kroah-Hartman & Sasha Levin	(very long-term kernel)
-	4.9	Greg Kroah-Hartman & Sasha Levin
-	4.14	Greg Kroah-Hartman & Sasha Levin
-	4.19	Greg Kroah-Hartman & Sasha Levin
-	5.4	Greg Kroah-Hartman & Sasha Levin
-	======  ================================	=======================
+for a longer period.  Please refer to the following link for the list of active
+long term kernel versions and their maintainers:
+
+	https://www.kernel.org/category/releases.html
 
 The selection of a kernel for long-term support is purely a matter of a
 maintainer having the need and the time to maintain that release.  There

base-commit: 9c9155a3509a2ebdb06d77c7a621e9685c802eac
-- 
2.38.0.413.g74048e4d9e-goog


^ permalink raw reply related	[relevance 13%]

* Re: [PATCH] Documentation: process: update the list of current LTS
  2022-10-13 18:34 15% [PATCH] Documentation: process: update the list of current LTS Nick Desaulniers
@ 2022-10-14  7:08  0% ` Greg Kroah-Hartman
  0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2022-10-14  7:08 UTC (permalink / raw)
  To: Nick Desaulniers
  Cc: Jonathan Corbet, linux-doc, linux-kernel, stable, Ben Hutchings,
	Sasha Levin

On Thu, Oct 13, 2022 at 11:34:14AM -0700, Nick Desaulniers wrote:
> 3.16 was EOL in 2020.
> 4.4 was EOL in 2022.
> 
> 5.10 is new in 2020.
> 5.15 is new in 2021.
> 
> We'll see if 6.1 becomes LTS in 2022.
> 
> Link: https://lore.kernel.org/stable/514c425e2b4dca71a11b0c669746d3122f7039a5.camel@decadent.org.uk/
> Link: https://lore.kernel.org/stable/1643877137240249@kroah.com/
> Signed-off-by: Nick Desaulniers <ndesaulniers@google.com>
> ---
>  Documentation/process/2.Process.rst | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/Documentation/process/2.Process.rst b/Documentation/process/2.Process.rst
> index e05fb1b8f8b6..9ae64376a8d4 100644
> --- a/Documentation/process/2.Process.rst
> +++ b/Documentation/process/2.Process.rst
> @@ -130,12 +130,12 @@ for a longer period.  As of this writing, the current long term kernels
>  and their maintainers are:
>  
>  	======  ================================	=======================
> -	3.16	Ben Hutchings				(very long-term kernel)
> -	4.4	Greg Kroah-Hartman & Sasha Levin	(very long-term kernel)
>  	4.9	Greg Kroah-Hartman & Sasha Levin
>  	4.14	Greg Kroah-Hartman & Sasha Levin
>  	4.19	Greg Kroah-Hartman & Sasha Levin
>  	5.4	Greg Kroah-Hartman & Sasha Levin
> +	5.10	Greg Kroah-Hartman & Sasha Levin
> +	5.15	Greg Kroah-Hartman & Sasha Levin
>  	======  ================================	=======================
>  
>  The selection of a kernel for long-term support is purely a matter of a


Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

^ permalink raw reply	[relevance 0%]

* [PATCH] Documentation: process: update the list of current LTS
@ 2022-10-13 18:34 15% Nick Desaulniers
  2022-10-14  7:08  0% ` Greg Kroah-Hartman
  0 siblings, 1 reply; 200+ results
From: Nick Desaulniers @ 2022-10-13 18:34 UTC (permalink / raw)
  To: Jonathan Corbet
  Cc: linux-doc, linux-kernel, Greg Kroah-Hartman, stable,
	Ben Hutchings, Sasha Levin, Nick Desaulniers

3.16 was EOL in 2020.
4.4 was EOL in 2022.

5.10 is new in 2020.
5.15 is new in 2021.

We'll see if 6.1 becomes LTS in 2022.

Link: https://lore.kernel.org/stable/514c425e2b4dca71a11b0c669746d3122f7039a5.camel@decadent.org.uk/
Link: https://lore.kernel.org/stable/1643877137240249@kroah.com/
Signed-off-by: Nick Desaulniers <ndesaulniers@google.com>
---
 Documentation/process/2.Process.rst | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Documentation/process/2.Process.rst b/Documentation/process/2.Process.rst
index e05fb1b8f8b6..9ae64376a8d4 100644
--- a/Documentation/process/2.Process.rst
+++ b/Documentation/process/2.Process.rst
@@ -130,12 +130,12 @@ for a longer period.  As of this writing, the current long term kernels
 and their maintainers are:
 
 	======  ================================	=======================
-	3.16	Ben Hutchings				(very long-term kernel)
-	4.4	Greg Kroah-Hartman & Sasha Levin	(very long-term kernel)
 	4.9	Greg Kroah-Hartman & Sasha Levin
 	4.14	Greg Kroah-Hartman & Sasha Levin
 	4.19	Greg Kroah-Hartman & Sasha Levin
 	5.4	Greg Kroah-Hartman & Sasha Levin
+	5.10	Greg Kroah-Hartman & Sasha Levin
+	5.15	Greg Kroah-Hartman & Sasha Levin
 	======  ================================	=======================
 
 The selection of a kernel for long-term support is purely a matter of a
-- 
2.38.0.413.g74048e4d9e-goog


^ permalink raw reply related	[relevance 15%]

* [PATCH v7 2/3] docs/zh_TW: add translations for zh_TW/process
  @ 2021-07-29 15:56  1% ` Hu Haowen
  0 siblings, 0 replies; 200+ results
From: Hu Haowen @ 2021-07-29 15:56 UTC (permalink / raw)
  To: corbet; +Cc: panyunwang849, linux-doc-tw-discuss, linux-doc, linux-kernel

Create new translations for zh_TW/process and link them to index.

Signed-off-by: Hu Haowen <src.res@email.cn>
Reviewed-by: Pan Yunwang <panyunwang849@gmail.com>
---
 Documentation/translations/zh_TW/index.rst    |  10 +-
 .../translations/zh_TW/process/1.Intro.rst    | 199 ++++
 .../translations/zh_TW/process/2.Process.rst  | 369 +++++++
 .../zh_TW/process/3.Early-stage.rst           | 172 ++++
 .../translations/zh_TW/process/4.Coding.rst   | 297 ++++++
 .../translations/zh_TW/process/5.Posting.rst  | 251 +++++
 .../zh_TW/process/6.Followthrough.rst         | 156 +++
 .../zh_TW/process/7.AdvancedTopics.rst        | 137 +++
 .../zh_TW/process/8.Conclusion.rst            |  74 ++
 .../code-of-conduct-interpretation.rst        | 112 ++
 .../zh_TW/process/code-of-conduct.rst         |  76 ++
 .../zh_TW/process/coding-style.rst            | 958 ++++++++++++++++++
 .../zh_TW/process/development-process.rst     |  30 +
 .../zh_TW/process/email-clients.rst           | 252 +++++
 .../process/embargoed-hardware-issues.rst     | 232 +++++
 .../translations/zh_TW/process/howto.rst      | 500 +++++++++
 .../translations/zh_TW/process/index.rst      |  67 ++
 .../zh_TW/process/kernel-driver-statement.rst | 203 ++++
 .../process/kernel-enforcement-statement.rst  | 155 +++
 .../zh_TW/process/license-rules.rst           | 374 +++++++
 .../zh_TW/process/magic-number.rst            | 148 +++
 .../zh_TW/process/management-style.rst        | 211 ++++
 .../zh_TW/process/programming-language.rst    |  76 ++
 .../zh_TW/process/stable-api-nonsense.rst     | 159 +++
 .../zh_TW/process/stable-kernel-rules.rst     |  68 ++
 .../zh_TW/process/submit-checklist.rst        | 109 ++
 .../zh_TW/process/submitting-drivers.rst      | 164 +++
 .../zh_TW/process/submitting-patches.rst      | 686 +++++++++++++
 .../process/volatile-considered-harmful.rst   | 110 ++
 29 files changed, 6351 insertions(+), 4 deletions(-)
 create mode 100644 Documentation/translations/zh_TW/process/1.Intro.rst
 create mode 100644 Documentation/translations/zh_TW/process/2.Process.rst
 create mode 100644 Documentation/translations/zh_TW/process/3.Early-stage.rst
 create mode 100644 Documentation/translations/zh_TW/process/4.Coding.rst
 create mode 100644 Documentation/translations/zh_TW/process/5.Posting.rst
 create mode 100644 Documentation/translations/zh_TW/process/6.Followthrough.rst
 create mode 100644 Documentation/translations/zh_TW/process/7.AdvancedTopics.rst
 create mode 100644 Documentation/translations/zh_TW/process/8.Conclusion.rst
 create mode 100644 Documentation/translations/zh_TW/process/code-of-conduct-interpretation.rst
 create mode 100644 Documentation/translations/zh_TW/process/code-of-conduct.rst
 create mode 100644 Documentation/translations/zh_TW/process/coding-style.rst
 create mode 100644 Documentation/translations/zh_TW/process/development-process.rst
 create mode 100644 Documentation/translations/zh_TW/process/email-clients.rst
 create mode 100644 Documentation/translations/zh_TW/process/embargoed-hardware-issues.rst
 create mode 100644 Documentation/translations/zh_TW/process/howto.rst
 create mode 100644 Documentation/translations/zh_TW/process/index.rst
 create mode 100644 Documentation/translations/zh_TW/process/kernel-driver-statement.rst
 create mode 100644 Documentation/translations/zh_TW/process/kernel-enforcement-statement.rst
 create mode 100644 Documentation/translations/zh_TW/process/license-rules.rst
 create mode 100644 Documentation/translations/zh_TW/process/magic-number.rst
 create mode 100644 Documentation/translations/zh_TW/process/management-style.rst
 create mode 100644 Documentation/translations/zh_TW/process/programming-language.rst
 create mode 100644 Documentation/translations/zh_TW/process/stable-api-nonsense.rst
 create mode 100644 Documentation/translations/zh_TW/process/stable-kernel-rules.rst
 create mode 100644 Documentation/translations/zh_TW/process/submit-checklist.rst
 create mode 100644 Documentation/translations/zh_TW/process/submitting-drivers.rst
 create mode 100644 Documentation/translations/zh_TW/process/submitting-patches.rst
 create mode 100644 Documentation/translations/zh_TW/process/volatile-considered-harmful.rst

diff --git a/Documentation/translations/zh_TW/index.rst b/Documentation/translations/zh_TW/index.rst
index cab58e428825..76981b2111f6 100644
--- a/Documentation/translations/zh_TW/index.rst
+++ b/Documentation/translations/zh_TW/index.rst
@@ -22,9 +22,7 @@
 下面的文檔介紹了Linux內核原始碼的許可證(GPLv2)、如何在原始碼樹中正確標記
 單個文件的許可證、以及指向完整許可證文本的連結。
 
-TODOList:
-
-* Documentation/translations/zh_TW/process/license-rules.rst
+Documentation/translations/zh_TW/process/license-rules.rst
 
 用戶文檔
 --------
@@ -67,9 +65,13 @@ TODOlist:
 開發人員做出貢獻。與任何大型社區一樣,知道如何完成任務將使得更改合併的過程
 變得更加容易。
 
+.. toctree::
+   :maxdepth: 2
+
+   process/index
+
 TODOList:
 
-* process/index
 * dev-tools/index
 * doc-guide/index
 * kernel-hacking/index
diff --git a/Documentation/translations/zh_TW/process/1.Intro.rst b/Documentation/translations/zh_TW/process/1.Intro.rst
new file mode 100644
index 000000000000..ca2b931be6c5
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/1.Intro.rst
@@ -0,0 +1,199 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/1.Intro.rst <development_process_intro>`
+
+:Translator:
+
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+
+:校譯:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+.. _tw_development_process_intro:
+
+引言
+====
+
+內容提要
+--------
+
+本節的其餘部分涵蓋了內核開發的過程,以及開發人員及其僱主在這方面可能遇到的
+各種問題。有很多原因使內核代碼應被合併到正式的(「主線」)內核中,包括對用戶
+的自動可用性、多種形式的社區支持以及影響內核開發方向的能力。提供給Linux內核
+的代碼必須在與GPL兼容的許可證下可用。
+
+:ref:`tw_development_process` 介紹了開發過程、內核發布周期和合併窗口的機制。
+涵蓋了補丁開發、審查和合併周期中的各個階段。還有一些關於工具和郵件列表的討論?
+鼓勵希望開始內核開發的開發人員跟蹤並修復缺陷以作爲初步練習。
+
+
+:ref:`tw_development_early_stage` 包括項目的早期規劃,重點是儘快讓開發社區
+參與進來。
+
+:ref:`tw_development_coding` 是關於編程過程的;介紹了其他開發人員遇到的幾個
+陷阱。也涵蓋了對補丁的一些要求,並且介紹了一些工具,這些工具有助於確保內核
+補丁是正確的。
+
+:ref:`tw_development_posting` 描述發布補丁以供評審的過程。爲了讓開發社區能
+認真對待,補丁必須被正確格式化和描述,並且必須發送到正確的地方。遵循本節中的
+建議有助於確保您的工作能被較好地接納。
+
+:ref:`tw_development_followthrough` 介紹了發布補丁之後發生的事情;工作在這時
+還遠遠沒有完成。與審閱者一起工作是開發過程中的一個重要部分;本節提供了一些
+關於如何在這個重要階段避免問題的提示。當補丁被合併到主線中時,開發人員要注意
+不要假定任務已經完成。
+
+:ref:`tw_development_advancedtopics` 介紹了兩個「高級」主題:使用Git管理補丁
+和查看其他人發布的補丁。
+
+:ref:`tw_development_conclusion` 總結了有關內核開發的更多信息,附帶有相關資源
+連結。
+
+這個文檔是關於什麼的
+--------------------
+
+Linux內核有超過800萬行代碼,每個版本的貢獻者超過1000人,是現存最大、最活躍的
+免費軟體項目之一。從1991年開始,這個內核已經發展成爲一個最好的作業系統組件,
+運行在袖珍數位音樂播放器、桌上型電腦、現存最大的超級計算機以及所有類型的系統上。
+它是一種適用於幾乎任何情況的健壯、高效和可擴展的解決方案。
+
+隨著Linux的發展,希望參與其開發的開發人員(和公司)的數量也在增加。硬體供應商
+希望確保Linux能夠很好地支持他們的產品,使這些產品對Linux用戶具有吸引力。嵌入
+式系統供應商使用Linux作爲集成產品的組件,希望Linux能夠儘可能地勝任手頭的任務。
+分銷商和其他基於Linux的軟體供應商切實關心Linux內核的功能、性能和可靠性。最終
+用戶也常常希望修改Linux,使之能更好地滿足他們的需求。
+
+Linux最引人注目的特性之一是這些開發人員可以訪問它;任何具備必要技能的人都可以
+改進Linux並影響其開發方向。專有產品不能提供這種開放性,這是自由軟體的一個特點。
+如果有什麼不同的話,那就是內核比大多數其他自由軟體項目更開放。一個典型的三個
+月內核開發周期可以涉及1000多個開發人員,他們爲100多個不同的公司(或者根本不
+隸屬公司)工作。
+
+與內核開發社區合作並不是特別困難。但儘管如此,仍有許多潛在的貢獻者在嘗試做
+內核工作時遇到了困難。內核社區已經發展出自己獨特的操作方式,使其能夠在每天
+都要更改數千行代碼的環境中順利運行(並生成高質量的產品)。因此,Linux內核開發
+過程與專有的開發模式有很大的不同也就不足爲奇了。
+
+對於新開發人員來說,內核的開發過程可能會讓人感到奇怪和恐懼,但這背後有充分的
+理由和堅實的經驗。一個不了解內核社區工作方式的開發人員(或者更糟的是,他們
+試圖拋棄或規避之)會得到令人沮喪的體驗。開發社區在幫助那些試圖學習的人的同時,
+沒有時間幫助那些不願意傾聽或不關心開發過程的人。
+
+希望閱讀本文的人能夠避免這種令人沮喪的經歷。這些材料很長,但閱讀它們時所做的
+努力會在短時間內得到回報。開發社區總是需要能讓內核變更好的開發人員;下面的
+文字應該幫助您或爲您工作的人員加入我們的社區。
+
+致謝
+----
+
+本文檔由Jonathan Corbet <corbet@lwn.net> 撰寫。以下人員的建議使之更爲完善:
+Johannes Berg, James Berry, Alex Chiang, Roland Dreier, Randy Dunlap,
+Jake Edge, Jiri Kosina, Matt Mackall, Arthur Marsh, Amanda McPherson,
+Andrew Morton, Andrew Price, Tsugikazu Shibata 和 Jochen Voß 。
+
+這項工作得到了Linux基金會的支持,特別感謝Amanda McPherson,他看到了這項工作
+的價值並將其變成現實。
+
+代碼進入主線的重要性
+--------------------
+
+有些公司和開發人員偶爾會想,爲什麼他們要費心學習如何與內核社區合作,並將代碼
+放入主線內核(「主線」是由Linus Torvalds維護的內核,Linux發行商將其用作基礎)。
+在短期內,貢獻代碼看起來像是一種可以避免的開銷;維護獨立代碼並直接支持用戶
+似乎更容易。事實上,保持代碼獨立(「樹外」)是在經濟上是錯誤的。
+
+爲了說明樹外代碼成本,下面給出內核開發過程的一些相關方面;本文稍後將更詳細地
+討論其中的大部分內容。請考慮:
+
+- 所有Linux用戶都可以使用合併到主線內核中的代碼。它將自動出現在所有啓用它的
+  發行版上。無需驅動程序磁碟、額外下載,也不需要爲多個發行版的多個版本提供
+  支持;這一切將方便所有開發人員和用戶。併入主線解決了大量的分發和支持問題。
+
+- 當內核開發人員努力維護一個穩定的用戶空間接口時,內核內部API處於不斷變化之中。
+  不維持穩定的內部接口是一個慎重的設計決策;它允許在任何時候進行基本的改進,
+  並產出更高質量的代碼。但該策略導致結果是,若要使用新的內核,任何樹外代碼都
+  需要持續的維護。維護樹外代碼會需要大量的工作才能使代碼保持正常運行。
+
+  相反,位於主線中的代碼不需要這樣做,因爲基本規則要求進行API更改的任何開發
+  人員也必須修復由於該更改而破壞的任何代碼。因此,合併到主線中的代碼大大降低
+  了維護成本。
+
+- 除此之外,內核中的代碼通常會被其他開發人員改進。您授權的用戶社區和客戶對您
+  產品的改進可能會令人驚喜。
+
+- 內核代碼在合併到主線之前和之後都要經過審查。無論原始開發人員的技能有多強,
+  這個審查過程總是能找到改進代碼的方法。審查經常發現嚴重的錯誤和安全問題。
+  對於在封閉環境中開發的代碼尤其如此;這種代碼從外部開發人員的審查中獲益匪淺。
+  樹外代碼是低質量代碼。
+
+- 參與開發過程是您影響內核開發方向的方式。旁觀者的抱怨會被聽到,但是活躍的
+  開發人員有更強的聲音——並且能夠實現使內核更好地滿足其需求的更改。
+
+- 當單獨維護代碼時,總是存在第三方爲類似功能提供不同實現的可能性。如果發生
+  這種情況,合併代碼將變得更加困難——甚至成爲不可能。之後,您將面臨以下令人
+  不快的選擇:(1)無限期地維護樹外的非標準特性,或(2)放棄代碼並將用戶遷移
+  到樹內版本。
+
+- 代碼的貢獻是使整個流程工作的根本。通過貢獻代碼,您可以向內核添加新功能,並
+  提供其他內核開發人員使用的功能和示例。如果您已經爲Linux開發了代碼(或者正在
+  考慮這樣做),那麼您顯然對這個平台的持續成功感興趣;貢獻代碼是確保成功的
+  最好方法之一。
+
+上述所有理由都適用於任何樹外內核代碼,包括以專有的、僅二進位形式分發的代碼。
+然而,在考慮任何類型的純二進位內核代碼分布之前,還需要考慮其他因素。包括:
+
+- 圍繞專有內核模塊分發的法律問題其實較爲模糊;相當多的內核版權所有者認爲,
+  大多數僅二進位的模塊是內核的派生產品,因此,它們的分發違反了GNU通用公共
+  許可證(下面將詳細介紹)。本文作者不是律師,本文檔中的任何內容都不可能被
+  視爲法律建議。封閉原始碼模塊的真實法律地位只能由法院決定。但不管怎樣,困擾
+  這些模塊的不確定性仍然存在。
+
+- 二進位模塊大大增加了調試內核問題的難度,以至於大多數內核開發人員甚至都不會
+  嘗試。因此,只分發二進位模塊將使您的用戶更難從社區獲得支持。
+
+- 對於僅二進位的模塊的發行者來說,支持也更加困難,他們必須爲他們希望支持的
+  每個發行版和每個內核版本提供不同版本的模塊。爲了提供較爲全面的覆蓋範圍,
+  可能需要一個模塊的幾十個構建,並且每次升級內核時,您的用戶都必須單獨升級
+  這些模塊。
+
+- 上面提到的關於代碼評審的所有問題都更加存在於封閉原始碼中。由於該代碼根本
+  不可得,因此社區無法對其進行審查,毫無疑問,它將存在嚴重問題。
+
+尤其是嵌入式系統的製造商,可能會傾向於忽視本節中所說的大部分內容;因爲他們
+相信自己正在商用一種使用凍結內核版本的獨立產品,在發布後不需要再進行開發。
+這個論點忽略了廣泛的代碼審查的價值以及允許用戶向產品添加功能的價值。但這些
+產品的商業壽命有限,之後必須發布新版本的產品。在這一點上,代碼在主線上並得到
+良好維護的供應商將能夠更好地占位,以使新產品快速上市。
+
+許可
+----
+
+代碼是根據一些許可證提供給Linux內核的,但是所有代碼都必須與GNU通用公共許可
+證(GPLV2)的版本2兼容,該版本是覆蓋整個內核分發的許可證。在實踐中,這意味
+著所有代碼貢獻都由GPLv2(可選地,語言允許在更高版本的GPL下分發)或3子句BSD
+許可(New BSD License,譯者注)覆蓋。任何不包含在兼容許可證中的貢獻都不會
+被接受到內核中。
+
+貢獻給內核的代碼不需要(或請求)版權分配。合併到主線內核中的所有代碼都保留
+其原始所有權;因此,內核現在擁有數千個所有者。
+
+這種所有權結構也暗示著,任何改變內核許可的嘗試都註定會失敗。很少有實際情況
+可以獲得所有版權所有者的同意(或者從內核中刪除他們的代碼)。因此,尤其是在
+可預見的將來,許可證不大可能遷移到GPL的版本3。
+
+所有貢獻給內核的代碼都必須是合法的免費軟體。因此,不接受匿名(或化名)貢獻
+者的代碼。所有貢獻者都需要在他們的代碼上「sign off(簽發)」,聲明代碼可以
+在GPL下與內核一起分發。無法提供未被其所有者許可爲免費軟體的代碼,或可能爲
+內核造成版權相關問題的代碼(例如,由缺乏適當保護的反向工程工作派生的代碼)
+不能被接受。
+
+有關版權問題的提問在Linux開發郵件列表中很常見。這樣的問題通常會得到不少答案,
+但請記住,回答這些問題的人不是律師,不能提供法律諮詢。如果您有關於Linux原始碼
+的法律問題,沒有什麼可以代替諮詢了解這一領域的律師。依賴從技術郵件列表中獲得
+的答案是一件冒險的事情。
+
+
diff --git a/Documentation/translations/zh_TW/process/2.Process.rst b/Documentation/translations/zh_TW/process/2.Process.rst
new file mode 100644
index 000000000000..b01cdd3a39ae
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/2.Process.rst
@@ -0,0 +1,369 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/2.Process.rst <development_process>`
+
+:Translator:
+
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+
+:校譯:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+.. _tw_development_process:
+
+開發流程如何進行
+================
+
+90年代早期的Linux內核開發是一件相當鬆散的事情,涉及的用戶和開發人員相對較少。
+由於擁有數以百萬計的用戶羣,且每年有大約2000名開發人員參與進來,內核因此必須
+發展出許多既定流程來保證開發的順利進行。要參與到流程中來,需要對此流程的進行
+方式有一個紮實的理解。
+
+總覽
+----
+
+內核開發人員使用一個鬆散的基於時間的發布過程,每兩到三個月發布一次新的主要
+內核版本。最近的發布歷史記錄如下:
+
+	======  =================
+	5.0	2019年3月3日
+	5.1	2019年5月5日
+	5.2	2019年7月7日
+	5.3	2019年9月15日
+	5.4	2019年11月24日
+	5.5	2020年1月6日
+	======  =================
+
+每個5.x版本都是一個主要的內核版本,具有新特性、內部API更改等等。一個典型的5.x
+版本包含大約13000個變更集,變更了幾十萬行代碼。因此,5.x是Linux內核開發的前
+沿;內核使用滾動開發模型,不斷集成重大變化。
+
+對於每個版本的補丁合併,遵循一個相對簡單的規則。在每個開發周期的開頭,「合併
+窗口」被打開。這時,被認爲足夠穩定(並且被開發社區接受)的代碼被合併到主線內
+核中。在這段時間內,新開發周期的大部分變更(以及所有主要變更)將以接近每天
+1000次變更(「補丁」或「變更集」)的速度合併。
+
+(順便說一句,值得注意的是,合併窗口期間集成的更改並不是憑空產生的;它們是經
+提前收集、測試和分級的。稍後將詳細描述該過程的工作方式。)
+
+合併窗口持續大約兩周。在這段時間結束時,LinusTorvalds將聲明窗口已關閉,並
+釋放第一個「rc」內核。例如,對於目標爲5.6的內核,在合併窗口結束時發生的釋放
+將被稱爲5.6-rc1。-rc1 版本是一個信號,表示合併新特性的時間已經過去,穩定下一
+個內核的時間已經到來。
+
+在接下來的6到10周內,只有修復問題的補丁才應該提交給主線。有時會允許更大的
+更改,但這種情況很少發生;試圖在合併窗口外合併新功能的開發人員往往受不到
+友好的接待。一般來說,如果您錯過了給定特性的合併窗口,最好的做法是等待下一
+個開發周期。(偶爾會對未支持硬體的驅動程序進行例外;如果它們不改變已有代碼,
+則不會導致回歸,應該可以隨時被安全地加入)。
+
+隨著修復程序進入主線,補丁速度將隨著時間的推移而變慢。Linus大約每周發布一次
+新的-rc內核;在內核被認爲足夠穩定並最終發布前,一般會達到-rc6到-rc9之間。
+然後,整個過程又重新開始了。
+
+例如,這裡是5.4的開發周期進行情況(2019年):
+
+	==============  ==============================
+	九月 15         5.3 穩定版發布
+	九月 30         5.4-rc1 合併窗口關閉
+	十月 6          5.4-rc2
+	十月 13         5.4-rc3
+	十月 20         5.4-rc4
+	十月 27         5.4-rc5
+	十一月 3        5.4-rc6
+	十一月 10       5.4-rc7
+	十一月 17       5.4-rc8
+	十一月 24       5.4 穩定版發布
+	==============  ==============================
+
+開發人員如何決定何時結束開發周期並創建穩定版本?最重要的指標是以前版本的
+回歸列表。不歡迎出現任何錯誤,但是那些破壞了以前能工作的系統的錯誤被認爲是
+特別嚴重的。因此,導致回歸的補丁是不受歡迎的,很可能在穩定期內刪除。
+
+開發人員的目標是在穩定發布之前修復所有已知的回歸。在現實世界中,這種完美是
+很難實現的;在這種規模的項目中,變數太多了。需要說明的是,延遲最終版本只會
+使問題變得更糟;等待下一個合併窗口的更改將變多,導致下次出現更多的回歸錯誤。
+因此,大多數5.x內核都有一些已知的回歸錯誤,不過,希望沒有一個是嚴重的。
+
+一旦一個穩定的版本發布,它的持續維護工作就被移交給「穩定團隊」,目前由
+Greg Kroah-Hartman領導。穩定團隊將使用5.x.y編號方案不定期地發布穩定版本的
+更新。要合入更新版本,補丁必須(1)修復一個重要的缺陷,且(2)已經合併到
+下一個開發版本主線中。內核通常會在其初始版本後的一個以上的開發周期內收到
+穩定版更新。例如,5.2內核的歷史如下(2019年):
+
+	==============  ===============================
+        七月 7 	        5.2 穩定版發布
+	七月 13	        5.2.1
+	七月 21	        5.2.2
+	七月 26	        5.2.3
+	七月 28	        5.2.4
+	七月 31	        5.2.5
+	...	        ...
+	十月 11         5.2.21
+	==============  ===============================
+
+5.2.21是5.2版本的最終穩定更新。
+
+有些內核被指定爲「長期」內核;它們將得到更長時間的支持。在本文中,當前的長期
+內核及其維護者是:
+
+	======  ================================	================
+	3.16	Ben Hutchings				(長期穩定內核)
+	4.4	Greg Kroah-Hartman & Sasha Levin	(長期穩定內核)
+	4.9	Greg Kroah-Hartman & Sasha Levin
+	4.14	Greg Kroah-Hartman & Sasha Levin
+	4.19	Greg Kroah-Hartman & Sasha Levin
+	5.4	Greg Kroah-Hartman & Sasha Levin
+	======  ================================	================
+
+長期支持內核的選擇純粹是維護人員是否有需求和時間來維護該版本的問題。
+目前還沒有爲即將發布的任何特定版本提供長期支持的已知計劃。
+
+補丁的生命周期
+--------------
+
+補丁不會直接從開發人員的鍵盤進入主線內核。相反,有一個稍微複雜(如果有些非
+正式)的過程,旨在確保對每個補丁進行質量審查,並確保每個補丁實現了一個在主線
+中需要的更改。對於小的修復,這個過程可能會很快完成,,而對於較大或有爭議的
+變更,可能會持續數年。許多開發人員的沮喪來自於對這個過程缺乏理解或者試圖繞過它。
+
+爲了減少這種挫敗,本文將描述補丁如何進入內核。下面的介紹以一種較爲理想化的
+方式描述了這個過程。更詳細的過程將在後面的章節中介紹。
+
+補丁通常要經歷以下階段:
+
+- 設計。這就是補丁的真正需求——以及滿足這些需求的方式——所在。設計工作通常
+  是在不涉及社區的情況下完成的,但是如果可能的話,最好是在公開的情況下完成
+  這項工作;這樣可以節省很多稍後再重新設計的時間。
+
+- 早期評審。補丁被發布到相關的郵件列表中,列表中的開發人員會回復他們可能有
+  的任何評論。如果一切順利的話,這個過程應該會發現補丁的任何主要問題。
+
+- 更廣泛的評審。當補丁接近準備好納入主線時,它應該被相關的子系統維護人員
+  接受——儘管這種接受並不能保證補丁會一直延伸到主線。補丁將出現在維護人員的
+  子系統樹中,並進入 -next 樹(如下所述)。當流程進行時,此步驟將會對補丁
+  進行更廣泛的審查,並發現由於將此補丁與其他人所做的工作合併而導致的任何
+  問題。
+
+- 請注意,大多數維護人員也有日常工作,因此合併補丁可能不是他們的最優先工作。
+  如果您的補丁得到了需要更改的反饋,那麼您應該進行這些更改,或者解釋爲何
+  不應該進行這些更改。如果您的補丁沒有評審意見,也沒有被其相應的子系統或
+  驅動程序維護者接受,那麼您應該堅持不懈地將補丁更新到當前內核使其可被正常
+  應用,並不斷地發送它以供審查和合併。
+
+- 合併到主線。最終,一個成功的補丁將被合併到由LinusTorvalds管理的主線存儲庫
+  中。此時可能會出現更多的評論和/或問題;對開發人員來說應對這些問題並解決
+  出現的任何問題仍很重要。
+
+- 穩定版發布。大量用戶可能受此補丁影響,因此可能再次出現新的問題。
+
+- 長期維護。雖然開發人員在合併代碼後可能會忘記代碼,但這種行爲往往會給開發
+  社區留下不良印象。合併代碼消除了一些維護負擔,因爲其他人將修復由API更改
+  引起的問題。但是,如果代碼要長期保持可用,原始開發人員應該繼續爲代碼負責。
+
+內核開發人員(或他們的僱主)犯的最大錯誤之一是試圖將流程簡化爲一個「合併到
+主線」步驟。這種方法總是會讓所有相關人員感到沮喪。
+
+補丁如何進入內核
+----------------
+
+只有一個人可以將補丁合併到主線內核存儲庫中:LinusTorvalds。但是,在進入
+2.6.38內核的9500多個補丁中,只有112個(大約1.3%)是由Linus自己直接選擇的。
+內核項目已經發展到一個沒有一個開發人員可以在沒有支持的情況下檢查和選擇每個
+補丁的規模。內核開發人員處理這種增長的方式是使用圍繞信任鏈構建的助理系統。
+
+內核代碼庫在邏輯上被分解爲一組子系統:網絡、特定體系結構支持、內存管理、視
+頻設備等。大多數子系統都有一個指定的維護人員,其總體負責該子系統中的代碼。
+這些子系統維護者(鬆散地)是他們所管理的內核部分的「守門員」;他們(通常)
+會接受一個補丁以包含到主線內核中。
+
+子系統維護人員每個人都管理著自己版本的內核原始碼樹,通常(並非總是)使用Git。
+Git等工具(以及Quilt或Mercurial等相關工具)允許維護人員跟蹤補丁列表,包括作者
+信息和其他元數據。在任何給定的時間,維護人員都可以確定他或她的存儲庫中的哪
+些補丁在主線中找不到。
+
+當合併窗口打開時,頂級維護人員將要求Linus從存儲庫中「拉出」他們爲合併選擇
+的補丁。如果Linus同意,補丁流將流向他的存儲庫,成爲主線內核的一部分。
+Linus對拉取中接收到的特定補丁的關注程度各不相同。很明顯,有時他看起來很
+關注。但是一般來說,Linus相信子系統維護人員不會向上游發送壞補丁。
+
+子系統維護人員反過來也可以從其他維護人員那裡獲取補丁。例如,網絡樹是由首先
+在專用於網絡設備驅動程序、無線網絡等的樹中積累的補丁構建的。此存儲鏈可以
+任意長,但很少超過兩個或三個連結。由於鏈中的每個維護者都信任那些管理較低
+級別樹的維護者,所以這個過程稱爲「信任鏈」。
+
+顯然,在這樣的系統中,獲取內核補丁取決於找到正確的維護者。直接向Linus發送
+補丁通常不是正確的方法。
+
+Next 樹
+-------
+
+子系統樹鏈引導補丁流到內核,但它也提出了一個有趣的問題:如果有人想查看爲
+下一個合併窗口準備的所有補丁怎麼辦?開發人員將感興趣的是,還有什麼其他的
+更改有待解決,以了解是否存在需要擔心的衝突;例如,更改核心內核函數原型的
+修補程序將與使用該函數舊形式的任何其他修補程序衝突。審查人員和測試人員希望
+在所有這些變更到達主線內核之前,能夠訪問它們的集成形式的變更。您可以從所有
+相關的子系統樹中提取更改,但這將是一項複雜且容易出錯的工作。
+
+解決方案以-next樹的形式出現,在這裡子系統樹被收集以供測試和審查。這些樹中
+由Andrew Morton維護的較老的一個,被稱爲「-mm」(用於內存管理,創建時爲此)。
+-mm 樹集成了一長串子系統樹中的補丁;它還包含一些旨在幫助調試的補丁。
+
+除此之外,-mm 還包含大量由Andrew直接選擇的補丁。這些補丁可能已經發布在郵件
+列表上,或者它們可能應用於內核中未指定子系統樹的部分。同時,-mm 作爲最後
+手段的子系統樹;如果沒有其他明顯的路徑可以讓補丁進入主線,那麼它很可能最
+終選擇-mm 樹。累積在-mm 中的各種補丁最終將被轉發到適當的子系統樹,或者直接
+發送到Linus。在典型的開發周期中,大約5-10%的補丁通過-mm 進入主線。
+
+當前-mm 補丁可在「mmotm」(-mm of the moment)目錄中找到:
+
+        https://www.ozlabs.org/~akpm/mmotm/
+
+然而,使用MMOTM樹可能會十分令人頭疼;它甚至可能無法編譯。
+
+下一個周期補丁合併的主要樹是linux-next,由Stephen Rothwell 維護。根據設計
+linux-next 是下一個合併窗口關閉後主線的快照。linux-next樹在Linux-kernel 和
+Linux-next 郵件列表中發布,可從以下位置下載:
+
+        https://www.kernel.org/pub/linux/kernel/next/
+
+Linux-next 已經成爲內核開發過程中不可或缺的一部分;在一個給定的合併窗口中合併
+的所有補丁都應該在合併窗口打開之前的一段時間內找到進入Linux-next 的方法。
+
+Staging 樹
+----------
+
+內核原始碼樹包含drivers/staging/目錄,其中有許多驅動程序或文件系統的子目錄
+正在被添加到內核樹中。它們在仍然需要更多的修正的時候可以保留在driver/staging/
+目錄中;一旦完成,就可以將它們移到內核中。這是一種跟蹤不符合Linux內核編碼或
+質量標準的驅動程序的方法,人們可能希望使用它們並跟蹤開發。
+
+Greg Kroah Hartman 目前負責維護staging 樹。仍需要修正的驅動程序將發送給他,
+每個驅動程序在drivers/staging/中都有自己的子目錄。除了驅動程序源文件之外,
+目錄中還應該有一個TODO文件。TODO文件列出了驅動程序需要接受的暫停的工作,
+以及驅動程序的任何補丁都應該抄送的人員列表。當前的規則要求,staging的驅動
+程序必須至少正確編譯。
+
+Staging 是一種讓新的驅動程序進入主線的相對容易的方法,它們會幸運地引起其他
+開發人員的注意,並迅速改進。然而,進入staging並不是故事的結尾;staging中
+沒有看到常規進展的代碼最終將被刪除。經銷商也傾向於相對不願意使用staging驅動
+程序。因此,在成爲一個合適的主線驅動的路上,staging 僅是一個中轉站。
+
+工具
+----
+
+從上面的文本可以看出,內核開發過程在很大程度上依賴於在不同方向上聚集補丁的
+能力。如果沒有適當強大的工具,整個系統將無法在任何地方正常工作。關於如何使用
+這些工具的教程遠遠超出了本文檔的範圍,但還是用一點篇幅介紹一些關鍵點。
+
+到目前爲止,內核社區使用的主要原始碼管理系統是git。Git是在自由軟體社區中開發
+的許多分布式版本控制系統之一。它非常適合內核開發,因爲它在處理大型存儲庫和
+大量補丁時性能非常好。它也以難以學習和使用而著稱,儘管隨著時間的推移它變得
+更好了。對於內核開發人員來說,對Git的某種熟悉幾乎是一種要求;即使他們不將它
+用於自己的工作,他們也需要Git來跟上其他開發人員(以及主線)正在做的事情。
+
+現在幾乎所有的Linux發行版都打包了Git。Git主頁位於:
+
+        https://git-scm.com/
+
+此頁面包含了文檔和教程的連結。
+
+在不使用git的內核開發人員中,最流行的選擇幾乎肯定是Mercurial:
+
+        http://www.seleric.com/mercurial/
+
+Mercurial與Git共享許多特性,但它提供了一個界面,許多人覺得它更易於使用。
+
+另一個值得了解的工具是Quilt:
+
+        https://savannah.nongnu.org/projects/quilt
+
+Quilt 是一個補丁管理系統,而不是原始碼管理系統。它不會隨著時間的推移跟蹤歷史;
+相反,它面向根據不斷發展的代碼庫跟蹤一組特定的更改。一些主要的子系統維護人員
+使用Quilt來管理打算向上游移動的補丁。對於某些樹的管理(例如-mm),quilt 是
+最好的工具。
+
+郵件列表
+--------
+
+大量的Linux內核開發工作是通過郵件列表完成的。如果不加入至少一個某個列表,
+就很難成爲社區中的一個「全功能」成員。但是,Linux郵件列表對開發人員來說也是
+一個潛在的危險,他們可能會被一堆電子郵件淹沒、違反Linux列表上使用的約定,
+或者兩者兼而有之。
+
+大多數內核郵件列表都在vger.kernel.org上運行;主列表位於:
+
+        http://vger.kernel.org/vger-lists.html
+
+不過,也有一些列表託管在別處;其中一些列表位於
+redhat.com/mailman/listinfo。
+
+當然,內核開發的核心郵件列表是linux-kernel。這個列表是一個令人生畏的地方:
+每天的信息量可以達到500條,噪音很高,談話技術性很強,且參與者並不總是表現出
+高度的禮貌。但是,沒有其他地方可以讓內核開發社區作爲一個整體聚集在一起;
+不使用此列表的開發人員將錯過重要信息。
+
+以下一些提示可以幫助在linux-kernel生存:
+
+- 將郵件轉移到單獨的文件夾,而不是主郵箱文件夾。我們必須能夠持續地忽略洪流。
+
+- 不要試圖跟上每一次談話——沒人會這樣。重要的是要篩選感興趣的主題(但請注意
+  長時間的對話可能會偏離原來的主題,儘管未改變電子郵件的主題)和參與的人。
+
+- 不要回復挑事的人。如果有人試圖激起憤怒,請忽略他們。
+
+- 當回復Linux內核電子郵件(或其他列表上的電子郵件)時,請爲所有相關人員保留
+  Cc: 抄送頭。如果沒有確實的理由(如明確的請求),則不應刪除收件人。一定要
+  確保你要回復的人在抄送列表中。這個慣例也使你不必在回覆郵件時明確要求被抄送。
+
+- 在提出問題之前,搜索列表存檔(和整個網絡)。有些開發人員可能會對那些顯然
+  沒有完成家庭作業的人感到不耐煩。
+
+- 避免頂部回復(把你的答案放在你要回復的引文上面的做法)。這會讓你的回答更難
+  理解,印象也很差。
+
+- 在正確的郵件列表發問。linux-kernel 可能是通用的討論場所,但它不是尋找所有
+  子系統開發人員的最佳場所。
+
+最後一點——找到正確的郵件列表——是開發人員常出錯的地方。在linux-kernel上
+提出與網絡相關的問題的人幾乎肯定會收到一個禮貌的建議,轉到netdev列表上提出,
+因爲這是大多數網絡開發人員經常出現的列表。還有其他列表可用於scsi、video4linux、
+ide、filesystem等子系統。查找郵件列表的最佳位置是與內核原始碼一起打包的
+MAINTAINERS文件。
+
+開始內核開發
+------------
+
+關於如何開始內核開發過程的問題很常見——個人和公司皆然。同樣常見的是失誤,這
+使得關係的開始比本應的更困難。
+
+公司通常希望聘請知名的開發人員來啓動開發團隊。實際上,這是一種有效的技術。
+但它也往往是昂貴的,而且對增加有經驗的內核開發人員的數量沒有多大幫助。考
+慮到時間投入,可以讓內部開發人員加快Linux內核的開發速度。利用這段時間可以
+讓僱主擁有一批既了解內核又了解公司的開發人員,還可以幫助培訓其他人。從中期
+來看,這通常是更有利可圖的方法。
+
+可以理解的是,單個開發人員往往對起步感到茫然。從一個大型項目開始可能會很
+嚇人;人們往往想先用一些較小的東西來試試水。由此,一些開發人員開始創建修補
+拼寫錯誤或輕微編碼風格問題的補丁。不幸的是,這樣的補丁會產生一定程度的噪音,
+這會分散整個開發社區的注意力,因此,它們越來越被人不看重。希望向社區介紹
+自己的新開發人員將無法通過這些方式獲得他們期待的反響。
+
+Andrew Morton 爲有抱負的內核開發人員提供了如下建議
+
+::
+
+	所有內核開發者的第一個項目肯定應該是「確保內核在您可以操作的所有
+	機器上始終完美運行」。通常的方法是和其他人一起解決問題(這可能需
+	要堅持!),但就是如此——這是內核開發的一部分。
+
+(http://lwn.net/articles/283982/)
+
+在沒有明顯問題需要解決的情況下,通常建議開發人員查看當前的回歸和開放缺陷
+列表。從來都不缺少需要解決的問題;通過解決這些問題,開發人員將從該過程獲得
+經驗,同時與開發社區的其他成員建立相互尊重。
+
diff --git a/Documentation/translations/zh_TW/process/3.Early-stage.rst b/Documentation/translations/zh_TW/process/3.Early-stage.rst
new file mode 100644
index 000000000000..ab2a45fd65a4
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/3.Early-stage.rst
@@ -0,0 +1,172 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/3.Early-stage.rst <development_early_stage>`
+
+:Translator:
+
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+
+:校譯:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+.. _tw_development_early_stage:
+
+早期規劃
+========
+
+當考慮一個Linux內核開發項目時,很可能會直接跳進去開始編碼。然而,與任何重要
+的項目一樣,許多成功的基礎最好是在第一行代碼編寫之前就打下。在早期計劃和
+溝通中花費一些時間可以在之後節省更多的時間。
+
+搞清問題
+--------
+
+與任何工程項目一樣,成功的內核改善從清晰描述要解決的問題開始。在某些情況
+下,這個步驟很容易:例如當某個特定硬體需要驅動程序時。不過,在其他情況下,
+很容易將實際問題與建議的解決方案混在一起,這可能會導致麻煩。
+
+舉個例子:幾年前,Linux音頻的開發人員尋求一種方法來運行應用程式,而不會因
+系統延遲過大而導致退出或其他問題。他們得到的解決方案是一個連接到Linux安全
+模塊(LSM)框架中的內核模塊;這個模塊可以配置爲允許特定的應用程式訪問實時
+調度程序。這個模塊被實現並發到linux-kernel郵件列表,在那裡它立即遇到了麻煩。
+
+對於音頻開發人員來說,這個安全模塊足以解決他們當前的問題。但是,對於更廣泛的
+內核社區來說,這被視爲對LSM框架的濫用(LSM框架並不打算授予他們原本不具備的
+進程特權),並對系統穩定性造成風險。他們首選的解決方案包括短期的通過rlimit
+機制進行實時調度訪問,以及長期的減少延遲的工作。
+
+然而,音頻社區無法超越他們實施的特定解決方案來看問題;他們不願意接受替代方案。
+由此產生的分歧使這些開發人員對整個內核開發過程感到失望;其中一個開發人員返回
+到audio列表並發布了以下內容:
+
+	有很多非常好的Linux內核開發人員,但他們往往會被一羣傲慢的傻瓜所壓倒。
+	試圖向這些人傳達用戶需求是浪費時間。他們太「聰明」了,根本聽不到少數
+	人的話。
+
+(http://lwn.net/articles/131776/)
+
+實際情況卻是不同的;與特定模塊相比,內核開發人員更關心系統穩定性、長期維護
+以及找到問題的正確解決方案。這個故事的寓意是把重點放在問題上——而不是具體的
+解決方案上——並在開始編寫代碼之前與開發社區討論這個問題。
+
+因此,在考慮一個內核開發項目時,我們應該得到一組簡短問題的答案:
+
+ - 需要解決的問題究竟是什麼?
+
+ - 受此問題影響的用戶有哪些?解決方案應該解決哪些使用案例?
+
+ - 內核現在爲何沒能解決這個問題?
+
+只有這樣,才能開始考慮可能的解決方案。
+
+
+早期討論
+--------
+
+在計劃內核開發項目時,在開始實施之前與社區進行討論是很有意義的。早期溝通可以
+通過多種方式節省時間和麻煩:
+
+ - 很可能問題是由內核以您不理解的方式解決的。Linux內核很大,具有許多不明顯
+   的特性和功能。並不是所有的內核功能都像人們所希望的那樣有文檔記錄,而且很
+   容易遺漏一些東西。某作者發布了一個完整的驅動程序,重複了一個其不
+   知道的現有驅動程序。重新發明現有輪子的代碼不僅浪費,而且不會被接受到主線
+   內核中。
+
+ - 建議的解決方案中可能有一些要素不適合併入主線。在編寫代碼之前,最好先了解
+   這樣的問題。
+
+ - 其他開發人員完全有可能考慮過這個問題;他們可能有更好的解決方案的想法,並且
+   可能願意幫助創建這個解決方案。
+
+在內核開發社區的多年經驗給了我們一個明確的教訓:閉門設計和開發的內核代碼總是
+有一些問題,這些問題只有在代碼發布到社區中時才會被發現。有時這些問題很嚴重,
+需要數月或數年的努力才能使代碼達到內核社區的標準。例如:
+
+ - 設計並實現了單處理器系統的DeviceScape網絡棧。只有使其適合於多處理器系統,
+   才能將其合併到主線中。在代碼中修改鎖等等是一項困難的任務;因此,這段代碼
+   (現在稱爲mac80211)的合併被推遲了一年多。
+
+ - Reiser4文件系統包含許多功能,核心內核開發人員認爲這些功能應該在虛擬文件
+   系統層中實現。它還包括一些特性,這些特性在不將系統暴露於用戶引起的死鎖的
+   情況下是不容易實現的。這些問題過遲發現——以及拒絕處理其中一些問題——已經
+   導致Reiser4置身主線內核之外。
+
+ - Apparmor安全模塊以被認爲不安全和不可靠的方式使用內部虛擬文件系統數據結構。
+   這種擔心(包括其他)使Apparmor多年來無法進入主線。
+
+在這些情況下,與內核開發人員的早期討論,可以避免大量的痛苦和額外的工作。
+
+找誰交流?
+----------
+
+當開發人員決定公開他們的計劃時,下一個問題是:我們從哪裡開始?答案是找到正確
+的郵件列表和正確的維護者。對於郵件列表,最好的方法是在維護者(MAINTAINERS)文件
+中查找要發布的相關位置。如果有一個合適的子系統列表,那麼其上發布通常比在
+linux-kernel上發布更可取;您更有可能接觸到在相關子系統中具有專業知識的開發
+人員,並且環境可能具支持性。
+
+找到維護人員可能會有點困難。同樣,維護者文件是開始的地方。但是,該文件往往不
+是最新的,並且並非所有子系統都在那裡顯示。實際上,維護者文件中列出的人員可能
+不是當前實際擔任該角色的人員。因此,當對聯繫誰有疑問時,一個有用的技巧是使用
+git(尤其是「git-log」)查看感興趣的子系統中當前活動的用戶。看看誰在寫補丁、
+誰會在這些補丁上加上Signed-off-by行簽名(如有)。這些人將是幫助新開發項目的
+最佳人選。
+
+找到合適的維護者有時是非常具有挑戰性的,以至於內核開發人員添加了一個腳本來
+簡化這個過程:
+
+::
+
+	.../scripts/get_maintainer.pl
+
+當給定「-f」選項時,此腳本將返回指定文件或目錄的當前維護者。如果在命令行上
+給出了一個補丁,它將列出可能接收補丁副本的維護人員。有許多選項可以調節
+get_maintainer.pl搜索維護者的嚴格程度;請小心使用更激進的選項,因爲最終結果
+可能會包括對您正在修改的代碼沒有真正興趣的開發人員。
+
+如果所有其他方法都失敗了,那麼與Andrew Morton交流是跟蹤特定代碼段維護人員
+的一種有效方法。
+
+何時郵寄?
+----------
+
+如果可能的話,在早期階段發布你的計劃只會更有幫助。描述正在解決的問題以及已經
+制定的關於如何實施的任何計劃。您可以提供的任何信息都可以幫助開發社區爲項目
+提供有用的輸入。
+
+在這個階段可能發生的一件令人沮喪的事情不是得到反對意見,而是很少或根本沒有
+反饋。令人傷心的事實是:(1)內核開發人員往往很忙;(2)不缺少有宏偉計劃但
+代碼(甚至代碼設想)很少的人去支持他們;(3)沒有人有義務審查或評論別人發表
+的想法。除此之外,高層級的設計常常隱藏著一些問題,這些問題只有在有人真正嘗試
+實現這些設計時才會被發現;因此,內核開發人員寧願看到代碼。
+
+如果發布請求評論(RFC)並沒得到什麼有用的評論,不要以爲這意味著無人對此項目
+有興趣,同時你也不能假設你的想法沒有問題。在這種情況下,最好的做法是繼續進
+行,把你的進展隨時通知社區。
+
+獲得官方認可
+-----------------------
+
+如果您的工作是在公司環境中完成的,就像大多數Linux內核工作一樣;顯然,在您將
+公司的計劃或代碼發布到公共郵件列表之前,必須獲得有適當權利經理的許可。發布
+不確定是否兼容GPL的代碼尤其會帶來問題;公司的管理層和法律人員越早能夠就發布
+內核開發項目達成一致,對參與的每個人都越好。
+
+一些讀者可能會認爲他們的核心工作是爲了支持還沒有正式承認存在的產品。將僱主
+的計劃公布在公共郵件列表上可能不是一個可行的選擇。在這種情況下,有必要考慮
+保密是否真的是必要的;通常不需要把開發計劃關在門內。
+
+的確,有些情況下一家公司在開發過程的早期無法合法地披露其計劃。擁有經驗豐富
+的內核開發人員的公司可能選擇以開環的方式進行開發,前提是他們以後能夠避免
+嚴重的集成問題。對於沒有這種內部專業知識的公司,最好的選擇往往是聘請外部
+開發者根據保密協議審查計劃。Linux基金會運行了一個NDA程序,旨在幫助解決這種
+情況;更多信息參見:
+
+    http://www.linuxfoundation.org/nda/
+
+這種審查通常足以避免以後出現嚴重問題,而無需公開披露項目。
+
diff --git a/Documentation/translations/zh_TW/process/4.Coding.rst b/Documentation/translations/zh_TW/process/4.Coding.rst
new file mode 100644
index 000000000000..ccc3946227a0
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/4.Coding.rst
@@ -0,0 +1,297 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/4.Coding.rst <development_coding>`
+
+:Translator:
+
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+
+:校譯:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+.. _tw_development_coding:
+
+使代碼正確
+======================
+
+雖然一個堅實的、面向社區的設計過程有很多值得說道的,但是任何內核開發項目工作
+的證明都反映在代碼中。它是將由其他開發人員檢查併合並(或不合併)到主線樹中
+的代碼。所以這段代碼的質量決定了項目的最終成功。
+
+本節將檢查編碼過程。我們將從內核開發人員常犯的幾種錯誤開始。然後重點將轉移
+到正確的做法和相關有用的工具上。
+
+陷阱
+----
+
+代碼風格
+********
+
+內核長期以來都有其標準的代碼風格,如
+:ref:`Documentation/translations/zh_TW/process/coding-style.rst <tw_codingstyle>`
+中所述。在多數時候,該文檔中描述的準則至多被認爲是建議性的。因此,內核中存在
+大量不符合代碼風格準則的代碼。這種代碼的存在會給內核開發人員帶來兩方面的危害。
+
+首先,相信內核代碼標準並不重要,也不強制執行。但事實上,如果沒有按照標準
+編寫代碼,那麼新代碼將很難加入到內核中;許多開發人員甚至會在審查代碼之前要求
+對代碼進行重新格式化。一個像內核這麼大的代碼庫需要一些統一格式的代碼,以使
+開發人員能夠快速理解其中的任何部分。所以再也經不起奇怪格式的代碼的折騰了。
+
+內核的代碼風格偶爾會與僱主的強制風格發生衝突。在這種情況下,必須在代碼合併
+之前遵從內核代碼風格。將代碼放入內核意味著以多種方式放棄一定程度的控制權——
+包括控制代碼樣式。
+
+另一個危害是認爲已經在內核中的代碼迫切需要修復代碼樣式。開發者可能會開始編寫
+重新格式化補丁,作爲熟悉開發過程的一種方式,或者作爲將其名字寫入內核變更日誌
+的一種方式,或者兩者兼而有之。但是純代碼風格的修復被開發社區視爲噪音,它們往
+往受到冷遇。因此,最好避免編寫這種類型的補丁。在由於其他原因處理一段代碼的
+同時順帶修復其樣式是很自然的,但是不應該僅爲了更改代碼樣式而更改之。
+
+代碼風格文檔也不應該被視爲絕對不可違反的規則。如果有一個足夠的理由反對這種
+樣式(例如爲了80列限制拆分行會導致可讀性大大降低),那麼就這樣做吧。
+
+注意您還可以使用 ``clang-format`` 工具來幫助您處理這些規則,快速自動重新格式
+化部分代碼,和審閱完整的文件以發現代碼樣式錯誤、拼寫錯誤和可能的改進。它還
+可以方便地排序 ``#includes`` 、對齊變量/宏、重排文本和其他類似任務。有關詳細
+信息,請參閱文檔 :ref:`Documentation/process/clang-format.rst <clangformat>`
+
+抽象層
+******
+
+計算機科學教授教學生以靈活性和信息隱藏的名義廣泛使用抽象層。當然,內核廣泛
+地使用了抽象;任何涉及數百萬行代碼的項目都必須做到這一點以存續下來。但經驗
+表明,過度或過早的抽象可能和過早的優化一樣有害。抽象應用在適當層級,
+不要過度。
+
+簡單點,先考慮一個調用時始終只有一個參數且總爲零的函數。我們可以保留這個參數,
+以在需要使用它時提供的額外靈活性。不過,在那時實現了這個額外參數的代碼很有
+可能以某種從未被注意到的微妙方式被破壞——因爲它從未被使用過。或者當需要額外
+的靈活性時,它並未以符合程式設計師當初期望的方式來實現。內核開發人員通常會提交
+補丁來刪除未使用的參數;一般來說,一開始就不應該添加這些參數。
+
+隱藏硬體訪問的抽象層——通常爲了允許大量的驅動程序兼容多個作業系統——尤其不受
+歡迎。這樣的層使代碼變得模糊,可能會造成性能損失;它們不屬於Linux內核。
+
+另一方面,如果您發現自己從另一個內核子系統複製了大量的代碼,那麼是時候
+了解一下:是否需要將這些代碼中的部分提取到單獨的庫中,或者在更高的層次上
+實現這些功能。在整個內核中複製相同的代碼沒有價值。
+
+#ifdef 和預處理
+***************
+
+C預處理器似乎給一些C程式設計師帶來了強大的誘惑,他們認爲它是一種將大量靈活性加入
+原始碼中的方法。但是預處理器不是C,大量使用它會導致代碼對其他人來說更難閱讀,
+對編譯器來說更難檢查正確性。使用了大量預處理器幾乎總是代碼需要一些
+清理工作的標誌。
+
+使用#ifdef的條件編譯實際上是一個強大的功能,它在內核中使用。但是很少有人希望
+看到代碼被鋪滿#ifdef塊。一般規定,ifdef的使用應儘可能限制在頭文件中。條件
+編譯代碼可以限制函數,如果代碼不存在,這些函數就直接變成空的。然後編譯器將
+悄悄地優化對空函數的調用。使得代碼更加清晰,更容易理解。
+
+C預處理器宏存在許多危險性,包括可能對具有副作用且沒有類型安全的表達式進行多
+重評估。如果您試圖定義宏,請考慮創建一個內聯函數替代。結果相同的代碼,內聯
+函數更容易閱讀,不會多次計算其參數,並且允許編譯器對參數和返回值執行類型檢查。
+
+內聯函數
+********
+
+不過,內聯函數本身也存在風險。程式設計師可以傾心於避免函數調用和用內聯函數填充源
+文件所固有的效率。然而,這些功能實際上會降低性能。因爲它們的代碼在每個調用站
+點都被複製一遍,所以最終會增加編譯內核的大小。此外,這也對處理器的內存緩存
+造成壓力,從而大大降低執行速度。通常內聯函數應該非常小,而且相對較少。畢竟
+函數調用的成本並不高;大量創建內聯函數是過早優化的典型例子。
+
+一般來說,內核程式設計師會自冒風險忽略緩存效果。在數據結構課程開頭中的經典
+時間/空間權衡通常不適用於當代硬體。空間 *就是* 時間,因爲一個大的程序比一個
+更緊湊的程序運行得慢。
+
+較新的編譯器越來越激進地決定一個給定函數是否應該內聯。因此,隨意放置使用
+「inline」關鍵字可能不僅僅是過度的,也可能是無用的。
+
+鎖
+**
+
+2006年5月,「deviceescape」網絡堆棧在前呼後擁下以GPL發布,並被納入主線內核。
+這是一個受歡迎的消息;Linux中對無線網絡的支持充其量被認爲是不合格的,而
+Deviceescape堆棧承諾修復這種情況。然而直到2007年6月(2.6.22),這段代碼才真
+正進入主線。發生了什麼?
+
+這段代碼出現了許多閉門造車的跡象。但一個大麻煩是,它並不是爲多處理器系統而
+設計。在合併這個網絡堆棧(現在稱爲mac80211)之前,需要對其進行一個鎖方案的
+改造。
+
+曾經,Linux內核代碼可以在不考慮多處理器系統所帶來的並發性問題的情況下進行
+開發。然而現在,這個文檔就是在雙核筆記本電腦上寫的。即使在單處理器系統上,
+爲提高響應能力所做的工作也會提高內核內的並發性水平。編寫內核代碼而不考慮鎖
+的日子早已遠去。
+
+可以由多個線程並發訪問的任何資源(數據結構、硬體寄存器等)必須由鎖保護。新
+的代碼應該謹記這一要求;事後修改鎖是一項相當困難的任務。內核開發人員應該花
+時間充分了解可用的鎖原語,以便爲工作選擇正確的工具。對並發性缺乏關注的代碼
+很難進入主線。
+
+回歸
+****
+
+最後一個值得一提的危險是回歸:它可能會引起導致現有用戶的某些東西中斷的改變
+(這也可能會帶來很大的改進)。這種變化被稱爲「回歸」,回歸已經成爲主線內核
+最不受歡迎的問題。除了少數例外情況,如果回歸不能及時修正,會導致回歸的修改
+將被取消。最好首先避免回歸發生。
+
+人們常常爭論,如果回歸帶來的功能遠超過產生的問題,那麼回歸是否爲可接受的。
+如果它破壞了一個系統卻爲十個系統帶來新的功能,爲何不改改態度呢?2007年7月,
+Linus對這個問題給出了最佳答案:
+
+::
+
+	所以我們不會通過引入新問題來修復錯誤。這種方式是靠不住的,沒人知道
+	是否真的有進展。是前進兩步、後退一步,還是前進一步、後退兩步?
+
+(http://lwn.net/articles/243460/)
+
+特別不受歡迎的一種回歸類型是用戶空間ABI的任何變化。一旦接口被導出到用戶空間,
+就必須無限期地支持它。這一事實使得用戶空間接口的創建特別具有挑戰性:因爲它們
+不能以不兼容的方式進行更改,所以必須一次就對。因此,用戶空間接口總是需要大量
+的思考、清晰的文檔和廣泛的審查。
+
+
+代碼檢查工具
+------------
+
+至少目前,編寫無錯誤代碼仍然是我們中很少人能達到的理想狀態。不過,我們希望做
+的是,在代碼進入主線內核之前,儘可能多地捕獲並修復這些錯誤。爲此,內核開發人
+員已經提供了一系列令人印象深刻的工具,可以自動捕獲各種各樣的隱藏問題。計算機
+發現的任何問題都是一個以後不會困擾用戶的問題,因此,只要有可能,就應該使用
+自動化工具。
+
+第一步是注意編譯器產生的警告。當前版本的GCC可以檢測(並警告)大量潛在錯誤。
+通常,這些警告都指向真正的問題。提交以供審閱的代碼一般不會產生任何編譯器警告。
+在消除警告時,注意了解真正的原因,並儘量避免僅「修復」使警告消失而不解決其原因。
+
+請注意,並非所有編譯器警告都默認啓用。使用「make KCFLAGS=-W」構建內核以
+獲得完整集合。
+
+內核提供了幾個配置選項,可以打開調試功能;大多數配置選項位於「kernel hacking」
+子菜單中。對於任何用於開發或測試目的的內核,都應該啓用其中幾個選項。特別是,
+您應該打開:
+
+ - FRAME_WARN 獲取大於給定數量的堆棧幀的警告。
+   這些警告生成的輸出可能比較冗長,但您不必擔心來自內核其他部分的警告。
+
+ - DEBUG_OBJECTS 將添加代碼以跟蹤內核創建的各種對象的生命周期,並在出現問題
+   時發出警告。如果你要添加創建(和導出)關於其自己的複雜對象的子系統,請
+   考慮打開對象調試基礎結構的支持。
+
+ - DEBUG_SLAB 可以發現各種內存分配和使用錯誤;它應該用於大多數開發內核。
+
+ - DEBUG_SPINLOCK, DEBUG_ATOMIC_SLEEP 和 DEBUG_MUTEXES 會發現許多常見的
+   鎖錯誤。
+
+還有很多其他調試選項,其中一些將在下面討論。其中一些有顯著的性能影響,不應
+一直使用。在學習可用選項上花費一些時間,可能會在短期內得到許多回報。
+
+其中一個較重的調試工具是鎖檢查器或「lockdep」。該工具將跟蹤系統中每個鎖
+(spinlock或mutex)的獲取和釋放、獲取鎖的相對順序、當前中斷環境等等。然後,
+它可以確保總是以相同的順序獲取鎖,相同的中斷假設適用於所有情況等等。換句話
+說,lockdep可以找到許多導致系統死鎖的場景。在部署的系統中,這種問題可能會
+很痛苦(對於開發人員和用戶而言);LockDep允許提前以自動方式發現問題。具有
+任何類型的非普通鎖的代碼在提交合併前應在啓用lockdep的情況下運行測試。
+
+作爲一個勤奮的內核程式設計師,毫無疑問,您將檢查任何可能失敗的操作(如內存分配)
+的返回狀態。然而,事實上,最終的故障復現路徑可能完全沒有經過測試。未測試的
+代碼往往會出問題;如果所有這些錯誤處理路徑都被執行了幾次,那麼您可能對代碼
+更有信心。
+
+內核提供了一個可以做到這一點的錯誤注入框架,特別是在涉及內存分配的情況下。
+啓用故障注入後,內存分配的可配置失敗的百分比;這些失敗可以限定在特定的代碼
+範圍內。在啓用了故障注入的情況下運行,程式設計師可以看到當情況惡化時代碼如何響
+應。有關如何使用此工具的詳細信息,請參閱
+Documentation/fault-injection/fault-injection.rst。
+
+「sparse」靜態分析工具可以發現其他類型的錯誤。sparse可以警告程式設計師用戶空間
+和內核空間地址之間的混淆、大端序與小端序的混淆、在需要一組位標誌的地方傳遞
+整數值等等。sparse必須單獨安裝(如果您的分發伺服器沒有將其打包,
+可以在 https://sparse.wiki.kernel.org/index.php/Main_page 找到),
+然後可以通過在make命令中添加「C=1」在代碼上運行它。
+
+「Coccinelle」工具 :ref:`http://coccinelle.lip6.fr/ <devtools_coccinelle>`
+能夠發現各種潛在的編碼問題;它還可以爲這些問題提出修複方案。在
+scripts/coccinelle目錄下已經打包了相當多的內核「語義補丁」;運行
+「make coccicheck」將運行這些語義補丁並報告發現的任何問題。有關詳細信息,請參閱
+:ref:`Documentation/dev-tools/coccinelle.rst <devtools_coccinelle>`
+
+
+其他類型的可移植性錯誤最好通過爲其他體系結構編譯代碼來發現。如果沒有S/390系統
+或Blackfin開發板,您仍然可以執行編譯步驟。可以在以下位置找到一大堆用於x86系統的
+交叉編譯器:
+
+        https://www.kernel.org/pub/tools/crosstool/
+
+花一些時間安裝和使用這些編譯器將有助於避免以後的尷尬。
+
+文檔
+----
+
+文檔通常比內核開發規則更爲例外。即便如此,足夠的文檔將有助於簡化將新代碼合併
+到內核中的過程,使其他開發人員的生活更輕鬆,並對您的用戶有所幫助。在許多情況
+下,添加文檔已基本上是強制性的。
+
+任何補丁的第一個文檔是其關聯的變更日誌。日誌條目應該描述正在解決的問題、解決
+方案的形式、處理補丁的人員、對性能的任何相關影響,以及理解補丁可能需要的任何
+其他內容。確保變更日誌說明了*爲什麼*補丁值得應用;大量開發者未能提供這些信息。
+
+任何添加新用戶空間接口的代碼——包括新的sysfs或/proc文件——都應該包含該接口
+的文檔,該文檔使用戶空間開發人員能夠知道他們在使用什麼。請參閱
+Documentation/ABI/README,了解如何此文檔格式以及需要提供哪些信息。
+
+文檔 :ref:`Documentation/admin-guide/kernel-parameters.rst <kernelparameters>`
+描述了內核的所有引導時間參數。任何添加新參數的補丁都應該向該文檔添加適當的
+條目。
+
+任何新的配置選項都必須附有幫助文本,幫助文本需清楚地解釋這些選項以及用戶可能
+希望何時使用它們。
+
+許多子系統的內部API信息通過專門格式化的注釋進行記錄;這些注釋可以通過
+「kernel-doc」腳本以多種方式提取和格式化。如果您在具有kerneldoc注釋的子系統中
+工作,則應該維護它們,並根據需要爲外部可用的功能添加它們。即使在沒有如此記錄
+的領域中,爲將來添加kerneldoc注釋也沒有壞處;實際上,這對於剛開始開發內核的人
+來說是一個有用的活動。這些注釋的格式以及如何創建kerneldoc模板的一些信息可以在
+:ref:`Documentation/doc-guide/ <doc_guide>` 上找到。
+
+任何閱讀大量現有內核代碼的人都會注意到,注釋的缺失往往是最值得注意的。同時,
+對新代碼的要求比過去更高;合併未注釋的代碼將更加困難。這就是說,人們並不期望
+詳細注釋的代碼。代碼本身應該是自解釋的,注釋闡釋了更微妙的方面。
+
+某些事情應該總是被注釋。使用內存屏障時,應附上一行文字,解釋爲什麼需要設置內存
+屏障。數據結構的鎖規則通常需要在某個地方解釋。一般來說,主要數據結構需要全面
+的文檔。應該指出代碼中分立的位之間不明顯的依賴性。任何可能誘使代碼管理人進行
+錯誤的「清理」的事情都需要一個注釋來說明爲什麼要這樣做。等等。
+
+
+內部API更改
+-----------
+
+內核提供給用戶空間的二進位接口不能被破壞,除非逼不得已。而內核的內部編程接口
+是高度流動的,當需要時可以更改。如果你發現自己不得不處理一個內核API,或者僅
+僅因爲它不滿足你的需求導致無法使用特定的功能,這可能是API需要改變的一個標誌。
+作爲內核開發人員,您有權進行此類更改。
+
+的確可以進行API更改,但更改必須是合理的。因此任何進行內部API更改的補丁都應該
+附帶關於更改內容和必要原因的描述。這種變化也應該拆分成一個單獨的補丁,而不是
+埋在一個更大的補丁中。
+
+另一個要點是,更改內部API的開發人員通常要負責修復內核樹中被更改破壞的任何代碼。
+對於一個廣泛使用的函數,這個責任可以導致成百上千的變化,其中許多變化可能與其他
+開發人員正在做的工作相衝突。不用說,這可能是一項大工程,所以最好確保理由是
+可靠的。請注意,coccinelle工具可以幫助進行廣泛的API更改。
+
+在進行不兼容的API更改時,應儘可能確保編譯器捕獲未更新的代碼。這將幫助您確保找
+到該接口的樹內用處。它還將警告開發人員樹外代碼存在他們需要響應的更改。支持樹外
+代碼不是內核開發人員需要擔心的事情,但是我們也不必使樹外開發人員的生活有不必要
+的困難。
+
diff --git a/Documentation/translations/zh_TW/process/5.Posting.rst b/Documentation/translations/zh_TW/process/5.Posting.rst
new file mode 100644
index 000000000000..5578bca403e6
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/5.Posting.rst
@@ -0,0 +1,251 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/5.Posting.rst <development_posting>`
+
+:Translator:
+
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+
+:校譯:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+.. _tw_development_posting:
+
+發布補丁
+========
+
+您的工作遲早會準備好提交給社區進行審查,並最終包含到主線內核中。毫不稀奇,
+內核開發社區已經發展出一套用於發布補丁的約定和過程;遵循這些約定和過程將使
+參與其中的每個人的生活更加輕鬆。本文檔試圖描述這些約定的部分細節;更多信息
+也可在以下文檔中找到
+:ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`,
+:ref:`Documentation/translations/zh_TW/process/submitting-drivers.rst <tw_submittingdrivers>`
+和 :ref:`Documentation/translations/zh_TW/process/submit-checklist.rst <tw_submitchecklist>`。
+
+何時郵寄
+--------
+
+在補丁完全「準備好」之前,避免發布補丁是一種持續的誘惑。對於簡單的補丁,這
+不是問題。但是如果正在完成的工作很複雜,那麼在工作完成之前從社區獲得反饋就
+可以獲得很多好處。因此,您應該考慮發布正在進行的工作,甚至維護一個可用的Git
+樹,以便感興趣的開發人員可以隨時趕上您的工作。
+
+當發布中有尚未準備好被包含的代碼,最好在發布中說明。還應提及任何有待完成的
+主要工作和任何已知問題。很少有人會願意看那些被認爲是半生不熟的補丁,但是
+那些願意的人會帶著他們的點子來一起幫助你把工作推向正確的方向。
+
+創建補丁之前
+------------
+
+在考慮將補丁發送到開發社區之前,有許多事情應該做。包括:
+
+ - 儘可能地測試代碼。利用內核的調試工具,確保內核使用了所有可能的配置選項組合
+   進行構建,使用交叉編譯器爲不同的體系結構進行構建等。
+
+ - 確保您的代碼符合內核代碼風格指南。
+
+ - 您的更改是否具有性能影響?如果是這樣,您應該運行基準測試來顯示您的變更的
+   影響(或好處);結果的摘要應該包含在補丁中。
+
+ - 確保您有權發布代碼。如果這項工作是爲僱主完成的,僱主對這項工作具有所有權,
+   並且必須同意根據GPL對其進行發布。
+
+一般來說,在發布代碼之前進行一些額外的思考,幾乎總是能在短時間內得到回報。
+
+補丁準備
+--------
+
+準備補丁發布的工作量可能很驚人,但在此嘗試節省時間通常是不明智的,即使在短期
+內亦然。
+
+必須針對內核的特定版本準備補丁。一般來說,補丁應該基於Linus的Git樹中的當前
+主線。當以主線爲基礎時,請從一個衆所周知的發布點開始——如穩定版本或 -rc
+版本發布點——而不是在一個任意的主線分支點。
+
+也可能需要針對-mm、linux-next或子系統樹生成版本,以便於更廣泛的測試和審查。
+根據補丁的區域以及其他地方的情況,針對其他樹建立的補丁可能需要大量的工作來
+解決衝突和處理API更改。
+
+只有最簡單的更改才應格式化爲單個補丁;其他所有更改都應作爲一系列邏輯更改進行。
+分割補丁是一門藝術;一些開發人員花了很長時間來弄清楚如何按照社區期望的方式來
+分割。不過,這些經驗法則也許有幫助:
+
+ - 您發布的補丁系列幾乎肯定不會是開發過程中版本控制系統中的一系列更改。相反,
+   需要對您所做更改的最終形式加以考慮,然後以有意義的方式進行拆分。開發人員對
+   離散的、自包含的更改感興趣,而不是您創造這些更改的原始路徑。
+
+ - 每個邏輯上獨立的變更都應該格式化爲單獨的補丁。這些更改可以是小的(如「向
+   此結構體添加欄位」)或大的(如添加一個重要的新驅動程序),但它們在概念上
+   應該是小的,並且可以在一行內簡述。每個補丁都應該做一個特定的、可以單獨
+   檢查並驗證它所做的事情的更改。
+
+ - 換種方式重申上述準則,也就是說:不要在同一補丁中混合不同類型的更改。如果
+   一個補丁修復了一個關鍵的安全漏洞,又重新排列了一些結構,還重新格式化了代
+   碼,那麼它很有可能會被忽略,從而導致重要的修復丟失。
+
+ - 每個補丁都應該能創建一個可以正確地構建和運行的內核;如果補丁系列在中間被
+   斷開,那麼結果仍應是一個正常工作的內核。部分應用一系列補丁是使用
+   「git bisct」工具查找回歸的一個常見場景;如果結果是一個損壞的內核,那麼將使
+   那些從事追蹤問題的高尚工作的開發人員和用戶的生活更加艱難。
+
+ - 不要過分分割。一位開發人員曾經將一組針對單個文件的編輯分成500個單獨的補丁
+   發布,這並沒有使他成爲內核郵件列表中最受歡迎的人。一個補丁可以相當大,
+   只要它仍然包含一個單一的 *邏輯* 變更。
+
+ - 用一系列補丁添加一個全新的基礎設施,但是該設施在系列中的最後一個補丁啓用
+   整個變更之前不能使用,這看起來很誘人。如果可能的話,應該避免這種誘惑;
+   如果這個系列增加了回歸,那麼二分法將指出最後一個補丁是導致問題的補丁,
+   即使真正的bug在其他地方。只要有可能,添加新代碼的補丁程序應該立即激活該
+   代碼。
+
+創建完美補丁系列的工作可能是一個令人沮喪的過程,在完成「真正的工作」之後需要
+花費大量的時間和思考。但是如果做得好,花費的時間就是值得的。
+
+補丁格式和更改日誌
+------------------
+
+所以現在你有了一系列完美的補丁可以發布,但是這項工作還沒有完成。每個補丁都
+需要被格式化成一條消息,以快速而清晰地將其目的傳達到世界其他地方。爲此,
+每個補丁將由以下部分組成:
+
+ - 可選的「From」行,表明補丁作者。只有當你通過電子郵件發送別人的補丁時,這一行
+   才是必須的,但是爲防止疑問加上它也不會有什麼壞處。
+
+ - 一行描述,說明補丁的作用。對於在沒有其他上下文的情況下看到該消息的讀者來說,
+   該消息應足以確定修補程序的範圍;此行將顯示在「short form(簡短格式)」變更
+   日誌中。此消息通常需要先加上子系統名稱前綴,然後是補丁的目的。例如:
+
+   ::
+
+        gpio: fix build on CONFIG_GPIO_SYSFS=n
+
+ - 一行空白,後接補丁內容的詳細描述。此描述可以是任意需要的長度;它應該說明補丁
+   的作用以及爲什麼它應該應用於內核。
+
+ - 一個或多個標記行,至少有一個由補丁作者的 Signed-off-by 簽名。標記將在下面
+   詳細描述。
+
+上面的項目一起構成補丁的變更日誌。寫一則好的變更日誌是一門至關重要但常常被
+忽視的藝術;值得花一點時間來討論這個問題。當你編寫變更日誌時,你應該記住有
+很多不同的人會讀你的話。其中包括子系統維護人員和審查人員,他們需要決定是否
+應該合併補丁,分銷商和其他維護人員試圖決定是否應該將補丁反向移植到其他內核,
+缺陷搜尋人員想知道補丁是否導致他們正在追查的問題,以及想知道內核如何變化的
+用戶等等。一個好的變更日誌以最直接和最簡潔的方式向所有這些人傳達所需的信息。
+
+在結尾,總結行應該描述變更的影響和動機,以及在一行約束條件下可能發生的變化。
+然後,詳細的描述可以詳述這些主題,並提供任何需要的附加信息。如果補丁修復了
+一個缺陷,請引用引入該缺陷的提交(如果可能,請在引用提交時同時提供其 id 和
+標題)。如果某個問題與特定的日誌或編譯器輸出相關聯,請包含該輸出以幫助其他
+人搜索同一問題的解決方案。如果更改是爲了支持以後補丁中的其他更改,那麼應當
+說明。如果更改了內部API,請詳細說明這些更改以及其他開發人員應該如何響應。
+一般來說,你越把自己放在每個閱讀你變更日誌的人的位置上,變更日誌(和內核
+作爲一個整體)就越好。
+
+不消說,變更日誌是將變更提交到版本控制系統時使用的文本。接下來將是:
+
+ - 補丁本身,採用統一的(「-u」)補丁格式。使用「-p」選項來diff將使函數名與
+   更改相關聯,從而使結果補丁更容易被其他人讀取。
+
+您應該避免在補丁中包括與更改不相關文件(例如,構建過程生成的文件或編輯器
+備份文件)。文檔目錄中的「dontdiff」文件在這方面有幫助;使用「-X」選項將
+其傳遞給diff。
+
+上面提到的標籤(tag)用於描述各種開發人員如何與這個補丁的開發相關聯。
+:ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+文檔中對它們進行了詳細描述;下面是一個簡短的總結。每一行的格式如下:
+
+::
+
+	tag: Full Name <email address>  optional-other-stuff
+
+常用的標籤有:
+
+ - Signed-off-by: 這是一個開發人員的證明,證明他或她有權提交補丁以包含到內核
+   中。這表明同意開發者來源認證協議,其全文見
+   :ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+   如果沒有合適的簽字,則不能合併到主線中。
+
+ - Co-developed-by: 聲明補丁是由多個開發人員共同創建的;當幾個人在一個補丁上
+   工作時,它用於給出共同作者(除了 From: 所給出的作者之外)。由於
+   Co-developed-by: 表示作者身份,所以每個共同開發人,必須緊跟在相關合作作者
+   的Signed-off-by之後。具體內容和示例見以下文件
+   :ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+
+ - Acked-by: 表示另一個開發人員(通常是相關代碼的維護人員)同意補丁適合包含
+   在內核中。
+
+ - Tested-by: 聲明某人已經測試了補丁並確認它可以工作。
+
+ - Reviewed-by: 表示某開發人員已經審查了補丁的正確性;有關詳細信息,請參閱
+   :ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+
+ - Reported-by: 指定報告此補丁修復的問題的用戶;此標記用於表示感謝。
+
+ - Cc:指定某人收到了補丁的副本,並有機會對此發表評論。
+
+在補丁中添加標籤時要小心:只有Cc:才適合在沒有指定人員明確許可的情況下添加。
+
+發送補丁
+--------
+
+在寄出補丁之前,您還需要注意以下幾點:
+
+ - 您確定您的郵件發送程序不會損壞補丁嗎?被郵件客戶端更改空白或修飾了行的補丁
+   無法被另一端接受,並且通常不會進行任何詳細檢查。如果有任何疑問,先把補丁寄
+   給你自己,讓你自己確定它是完好無損的。
+
+   :ref:`Documentation/translations/zh_TW/process/email-clients.rst <tw_email_clients>`
+   提供了一些有用的提示,可以讓特定的郵件客戶端正常發送補丁。
+
+ - 你確定你的補丁沒有荒唐的錯誤嗎?您應該始終通過scripts/checkpatch.pl檢查
+   補丁程序,並解決它提出的問題。請記住,checkpatch.pl,雖然體現了對內核補丁
+   應該是什麼樣的大量思考,但它並不比您聰明。如果修復checkpatch.pl給的問題會
+   使代碼變得更糟,請不要這樣做。
+
+補丁應始終以純文本形式發送。請不要將它們作爲附件發送;這使得審閱者在答覆中更難
+引用補丁的部分。相反,只需將補丁直接放到您的消息中。
+
+寄出補丁時,重要的是將副本發送給任何可能感興趣的人。與其他一些項目不同,內核
+鼓勵人們甚至錯誤地發送過多的副本;不要假定相關人員會看到您在郵件列表中的發布。
+尤其是,副本應發送至:
+
+ - 受影響子系統的維護人員。如前所述,維護人員文件是查找這些人員的首選地方。
+
+ - 其他在同一領域工作的開發人員,尤其是那些現在可能在那裡工作的開發人員。使用
+   git查看還有誰修改了您正在處理的文件,這很有幫助。
+
+ - 如果您對某錯誤報告或功能請求做出響應,也可以抄送原始發送人。
+
+ - 將副本發送到相關郵件列表,或者若無相關列表,則發送到linux-kernel列表。
+
+ - 如果您正在修復一個缺陷,請考慮該修復是否應進入下一個穩定更新。如果是這樣,
+   補丁副本也應發到stable@vger.kernel.org 。另外,在補丁本身的標籤中添加一個
+   「Cc: stable@vger.kernel.org」;這將使穩定版團隊在修復進入主線時收到通知。
+
+當爲一個補丁選擇接收者時,最好清楚你認爲誰最終會接受這個補丁並將其合併。雖然
+可以將補丁直接發給Linus Torvalds並讓他合併,但通常情況下不會這樣做。Linus很
+忙,並且有子系統維護人員負責監視內核的特定部分。通常您會希望維護人員合併您的
+補丁。如果沒有明顯的維護人員,Andrew Morton通常是最後的補丁接收者。
+
+補丁需要好的主題行。補丁主題行的規範格式如下:
+
+::
+
+	[PATCH nn/mm] subsys: one-line description of the patch
+
+其中「nn」是補丁的序號,「mm」是系列中補丁的總數,「subsys」是受影響子系統的
+名稱。當然,一個單獨的補丁可以省略nn/mm。
+
+如果您有一系列重要的補丁,那麼通常發送一個簡介作爲第〇部分。不過,這個約定
+並沒有得到普遍遵循;如果您使用它,請記住簡介中的信息不會進入內核變更日誌。
+因此,請確保補丁本身具有完整的變更日誌信息。
+
+一般來說,多部分補丁的第二部分和後續部分應作爲對第一部分的回覆發送,以便它們
+在接收端都連接在一起。像git和coilt這樣的工具有命令,可以通過適當的線程發送
+一組補丁。但是,如果您有一長串補丁,並正使用git,請不要使用–-chain-reply-to
+選項,以避免創建過深的嵌套。
+
diff --git a/Documentation/translations/zh_TW/process/6.Followthrough.rst b/Documentation/translations/zh_TW/process/6.Followthrough.rst
new file mode 100644
index 000000000000..4af782742db3
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/6.Followthrough.rst
@@ -0,0 +1,156 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/6.Followthrough.rst <development_followthrough>`
+
+:Translator:
+
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+
+:校譯:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+.. _tw_development_followthrough:
+
+跟進
+====
+
+此時,您已經遵循了到目前爲止給出的指導方針,並且,隨著您自己的工程技能的增加,
+已經發布了一系列完美的補丁。即使是經驗豐富的內核開發人員也能犯的最大錯誤之一
+是,認爲他們的工作現在已經完成了。事實上,發布補丁意味著進入流程的下一個階段,
+可能還需要做很多工作。
+
+一個補丁在首次發布時就非常出色、沒有改進的餘地,這是很罕見的。內核開發流程已
+認識到這一事實,因此它非常注重對已發布代碼的改進。作爲代碼的作者,您應該與
+內核社區合作,以確保您的代碼符合內核的質量標準。如果不參與這個過程,很可能會
+無法將補丁合併到主線中。
+
+與審閱者合作
+------------
+
+任何意義上的補丁都會導致其他開發人員在審查代碼時發表大量評論。對於許多開發
+人員來說,與審閱人員合作可能是內核開發過程中最令人生畏的部分。但是如果你
+記住一些事情,生活會變得容易得多:
+
+ - 如果你已經很好地解釋了你的補丁,審閱人員會理解它的價值,以及爲什麼你會
+   費盡心思去寫它。但是這個並不能阻止他們提出一個基本的問題:在五年或十年後
+   維護含有此代碼的內核會怎麼樣?你可能被要求做出的許多改變——從編碼風格的
+   調整到大量的重寫——都來自於對Linux的理解,即從現在起十年後,Linux仍將
+   在開發中。
+
+ - 代碼審查是一項艱苦的工作,這是一項相對吃力不討好的工作;人們記得誰編寫了
+   內核代碼,但對於那些審查它的人來說,幾乎沒有什麼長久的名聲。因此,審閱
+   人員可能會變得暴躁,尤其是當他們看到同樣的錯誤被一遍又一遍地犯下時。如果
+   你得到了一個看起來憤怒、侮辱或完全冒犯你的評論,請抑制以同樣方式回應的衝動。
+   代碼審查是關於代碼的,而不是關於人的,代碼審閱人員不會親自攻擊您。
+
+ - 同樣,代碼審閱人員也不想以犧牲你僱主的利益爲代價來宣傳他們僱主的議程。
+   內核開發人員通常希望今後幾年能在內核上工作,但他們明白他們的僱主可能會改
+   變。他們真的,幾乎毫無例外地,致力於創造他們所能做到的最好的內核;他們並
+   沒有試圖給僱主的競爭對手造成不適。
+
+所有這些歸根結底就是,當審閱者向您發送評論時,您需要注意他們正在進行的技術
+評論。不要讓他們的表達方式或你自己的驕傲阻止此事。當你在一個補丁上得到評論
+時,花點時間去理解評論人想說什麼。如果可能的話,請修覆審閱者要求您修復的內
+容。然後回覆審閱者:謝謝他們,並描述你將如何回答他們的問題。
+
+請注意,您不必同意審閱者建議的每個更改。如果您認爲審閱者誤解了您的代碼,請
+解釋到底發生了什麼。如果您對建議的更改有技術上的異議,請描述它並證明您對該
+問題的解決方案是正確的。如果你的解釋有道理,審閱者會接受的。不過,如果你的
+解釋證明缺乏說服力,尤其是當其他人開始同意審稿人的觀點時,請花些時間重新考慮
+一下。你很容易對自己解決問題的方法視而不見,以至於你沒有意識到某些東西完全
+是錯誤的,或者你甚至沒有解決正確的問題。
+
+Andrew Morton建議,每一個不會導致代碼更改的審閱評論都應該產生一個額外的代碼
+注釋;這可以幫助未來的審閱人員避免第一次出現的問題。
+
+一個致命的錯誤是忽視評論,希望它們會消失。它們不會走的。如果您在沒有對之前
+收到的評論做出響應的情況下重新發布代碼,那麼很可能會發現補丁毫無用處。
+
+說到重新發布代碼:請記住,審閱者不會記住您上次發布的代碼的所有細節。因此,
+提醒審閱人員以前提出的問題以及您如何處理這些問題總是一個好主意;補丁變更
+日誌是提供此類信息的好地方。審閱者不必搜索列表檔案來熟悉上次所說的內容;
+如果您幫助他們直接開始,當他們重新查看您的代碼時,心情會更好。
+
+如果你已經試著做正確的事情,但事情仍然沒有進展呢?大多數技術上的分歧都可以
+通過討論來解決,但有時人們仍需要做出決定。如果你真的認爲這個決定對你不利,
+你可以試著向有更高權力的人上訴。對於本文,更高權力的人是 Andrew Morton 。
+Andrew 在內核開發社區中非常受尊敬;他經常爲似乎被絕望阻塞的事情清障。儘管
+如此,不應輕易就直接找 Andrew ,也不應在所有其他替代方案都被嘗試之前找他。
+當然,記住,他也可能不同意你的意見。
+
+接下來會發生什麼
+----------------
+
+如果一個補丁被認爲適合添加到內核中,並且大多數審查問題得到解決,下一步通常
+是進入子系統維護人員的樹中。工作方式因子系統而異;每個維護人員都有自己的
+工作方式。特別是可能有不止一棵樹——也許一棵樹專門用於計劃下一個合併窗口的
+補丁,另一棵樹用於長期工作。
+
+對於應用到不屬於明顯子系統樹(例如內存管理修補程序)的區域的修補程序,默認樹
+通常上溯到-mm。影響多個子系統的補丁也可以最終進入-mm樹。
+
+包含在子系統樹中可以提高補丁的可見性。現在,使用該樹的其他開發人員將默認獲
+得補丁。子系統樹通常也爲Linux提供支持,使其內容對整個開發社區可見。在這一點
+上,您很可能會從一組新的審閱者那裡得到更多的評論;這些評論需要像上一輪那樣
+得到回應。
+
+在這時也會發生點什麼,這取決於你的補丁的性質,是否與其他人正在做的工作發生
+衝突。在最壞的情況下,嚴重的補丁衝突可能會導致一些工作被擱置,以便剩餘的補丁
+可以成形併合並。另一些時候,衝突解決將涉及到與其他開發人員合作,可能還會
+在樹之間移動一些補丁,以確保所有的應用都是乾淨的。這項工作可能是一件痛苦的
+事情,但也需慶幸現在的幸福:在linux-next樹出現之前,這些衝突通常只在合併窗口
+中出現,必須迅速解決。現在可以在合併窗口打開之前的空閒時間解決這些問題。
+
+有朝一日,如果一切順利,您將登錄並看到您的補丁已經合併到主線內核中。祝賀你!
+然而,一旦慶祝完了(並且您已經將自己添加到維護人員文件中),就一定要記住
+一個重要的小事實:工作仍然沒有完成。併入主線也帶來了它的挑戰。
+
+首先,補丁的可見性再次提高。可能會有以前不知道這個補丁的開發者的新一輪評論。
+忽略它們可能很有誘惑力,因爲您的代碼不再存在任何被合併的問題。但是,要抵制
+這種誘惑,您仍然需要對有問題或建議的開發人員作出響應。
+
+不過,更重要的是:將代碼包含在主線中會將代碼交給更多的一些測試人員。即使您
+爲尚未可用的硬體提供了驅動程序,您也會驚訝於有多少人會將您的代碼構建到內核
+中。當然,如果有測試人員,也可能會有錯誤報告。
+
+最糟糕的錯誤報告是回歸。如果你的補丁導致回歸,你會發現多到讓你不舒服的眼睛盯
+著你;回歸需要儘快修復。如果您不願意或無法修復回歸(其他人都不會爲您修復),
+那麼在穩定期內,您的補丁幾乎肯定會被移除。除了否定您爲使補丁進入主線所做的
+所有工作之外,如果由於未能修復回歸而取消補丁,很可能會使將來的工作更難被合併。
+
+在處理完任何回歸之後,可能還有其他普通缺陷需要處理。穩定期是修復這些錯誤並
+確保代碼在主線內核版本中的首次發布儘可能可靠的最好機會。所以,請回應錯誤
+報告,並儘可能解決問題。這就是穩定期的目的;一旦解決了舊補丁的任何問題,就
+可以開始盡情創建新補丁。
+
+別忘了,還有其他節點也可能會創建缺陷報告:下一個主線穩定版本,當著名的發行
+商選擇包含您補丁的內核版本時等等。繼續響應這些報告是您工作的基本素養。但是
+如果這不能提供足夠的動機,那麼也需要考慮:開發社區會記住那些在合併後對代碼
+失去興趣的開發人員。下一次你發布補丁時,他們會以你以後不會持續維護它爲前提
+來評估它。
+
+其他可能發生的事情
+------------------
+
+某天,當你打開你的郵件客戶端時,看到有人給你寄了一個代碼補丁。畢竟,這是
+讓您的代碼公開存在的好處之一。如果您同意這個補丁,您可以將它轉發給子系統
+維護人員(確保包含一個正確的From:行,這樣屬性是正確的,並添加一個您自己的
+signoff ),或者回復一個 Acked-by: 讓原始發送者向上發送它。
+
+如果您不同意補丁,請禮貌地回復,解釋原因。如果可能的話,告訴作者需要做哪些
+更改才能讓您接受補丁。合併代碼的編寫者和維護者所反對的補丁的確存在著一定的
+阻力,但僅此而已。如果你被認爲不必要的阻礙了好的工作,那麼這些補丁最終會
+繞過你並進入主線。在Linux內核中,沒有人對任何代碼擁有絕對的否決權。可能除
+了Linus。
+
+在非常罕見的情況下,您可能會看到完全不同的東西:另一個開發人員發布了針對您
+的問題的不同解決方案。在這時,兩個補丁之一可能不會被合併,「我的補丁首先
+發布」不被認爲是一個令人信服的技術論據。如果有別人的補丁取代了你的補丁而進
+入了主線,那麼只有一種方法可以回應你:很高興你的問題解決了,請繼續工作吧。
+以這種方式把某人的工作推到一邊可能導致傷心和氣餒,但是社區會記住你的反應,
+即使很久以後他們已經忘記了誰的補丁真正被合併。
+
diff --git a/Documentation/translations/zh_TW/process/7.AdvancedTopics.rst b/Documentation/translations/zh_TW/process/7.AdvancedTopics.rst
new file mode 100644
index 000000000000..3de093d0f170
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/7.AdvancedTopics.rst
@@ -0,0 +1,137 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/7.AdvancedTopics.rst <development_advancedtopics>`
+
+:Translator:
+
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+
+:校譯:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+.. _tw_development_advancedtopics:
+
+高級主題
+========
+
+現在,希望您能夠掌握開發流程的工作方式。然而,還有更多的東西要學!本節將介紹
+一些主題,這些主題對希望成爲Linux內核開發過程常規部分的開發人員有幫助。
+
+使用Git管理補丁
+---------------
+
+內核使用分布式版本控制始於2002年初,當時Linus首次開始使用專有的Bitkeeper應用
+程序。雖然BitKeeper存在爭議,但它所體現的軟體版本管理方法卻肯定不是。分布式
+版本控制可以立即加速內核開發項目。現在有好幾種免費的BitKeeper替代品。
+但無論好壞,內核項目都已經選擇了Git作爲其工具。
+
+使用Git管理補丁可以使開發人員的生活更加輕鬆,尤其是隨著補丁數量的增長。Git也
+有其粗糙的邊角和一定的危險性,它是一個年輕和強大的工具,仍然在其開發人員完善
+中。本文檔不會試圖教會讀者如何使用git;這會是個巨長的文檔。相反,這裡的重點
+將是Git如何特別適合內核開發過程。想要加快用Git速度的開發人員可以在以下網站上
+找到更多信息:
+
+	https://git-scm.com/
+
+	https://www.kernel.org/pub/software/scm/git/docs/user-manual.html
+
+同時網上也能找到各種各樣的教程。
+
+在嘗試使用它生成補丁供他人使用之前,第一要務是閱讀上述網頁,對Git的工作方式
+有一個紮實的了解。使用Git的開發人員應能進行拉取主線存儲庫的副本,查詢修訂
+歷史,提交對樹的更改,使用分支等操作。了解Git用於重寫歷史的工具(如rebase)
+也很有用。Git有自己的術語和概念;Git的新用戶應該了解引用、遠程分支、索引、
+快進合併、推拉、游離頭等。一開始可能有點嚇人,但這些概念不難通過一點學習來
+理解。
+
+使用git生成通過電子郵件提交的補丁是提高速度的一個很好的練習。
+
+當您準備好開始建立Git樹供其他人查看時,無疑需要一個可以從中拉取的伺服器。
+如果您有一個可以訪問網際網路的系統,那麼使用git-daemon設置這樣的伺服器相對
+簡單。同時,免費的公共託管網站(例如github)也開始出現在網絡上。成熟的開發
+人員可以在kernel.org上獲得一個帳戶,但這些帳戶並不容易得到;更多有關信息,
+請參閱 https://kernel.org/faq/ 。
+
+正常的Git工作流程涉及到許多分支的使用。每一條開發線都可以分爲單獨的「主題
+分支」,並獨立維護。Git的分支很容易使用,沒有理由不使用它們。而且,在任何
+情況下,您都不應該在任何您打算讓其他人從中拉取的分支中進行開發。應該小心地
+創建公開可用的分支;當開發分支處於完整狀態並已準備好時(而不是之前)才合併
+開發分支的補丁。
+
+Git提供了一些強大的工具,可以讓您重寫開發歷史。一個不方便的補丁(比如說,
+一個打破二分法的補丁,或者有其他一些明顯的缺陷)可以在適當的位置修復,或者
+完全從歷史中消失。一個補丁系列可以被重寫,就好像它是在今天的主線上寫的一樣,
+即使你已經花了幾個月的時間在寫它。可以透明地將更改從一個分支轉移到另一個
+分支。等等。明智地使用git修改歷史的能力可以幫助創建問題更少的乾淨補丁集。
+
+然而,過度使用這種功能可能會導致其他問題,而不僅僅是對創建完美項目歷史的
+簡單癡迷。重寫歷史將重寫該歷史中包含的更改,將經過測試(希望如此)的內核樹
+變爲未經測試的內核樹。除此之外,如果開發人員沒有共享項目歷史,他們就無法
+輕鬆地協作;如果您重寫了其他開發人員拉入他們存儲庫的歷史,您將使這些開發
+人員的生活更加困難。因此,這裡有一個簡單的經驗法則:被導出到其他地方的歷史
+在此後通常被認爲是不可變的。
+
+因此,一旦將一組更改推送到公開可用的伺服器上,就不應該重寫這些更改。如果您
+嘗試強制進行無法快進合併的更改(即不共享同一歷史記錄的更改),Git將嘗試強制
+執行此規則。這可能覆蓋檢查,有時甚至需要重寫導出的樹。在樹之間移動變更集以
+避免linux-next中的衝突就是一個例子。但這種行爲應該是罕見的。這就是爲什麼
+開發應該在私有分支中進行(必要時可以重寫)並且只有在公共分支處於合理的較新
+狀態時才轉移到公共分支中的原因之一。
+
+當主線(或其他一組變更所基於的樹)前進時,很容易與該樹合併以保持領先地位。
+對於一個私有的分支,rebasing 可能是一個很容易跟上另一棵樹的方法,但是一旦
+一棵樹被導出到外界,rebasing就不可取了。一旦發生這種情況,就必須進行完全
+合併(merge)。合併有時是很有意義的,但是過於頻繁的合併會不必要地擾亂歷史。
+在這種情況下建議的做法是不要頻繁合併,通常只在特定的發布點(如主線-rc發布)
+合併。如果您對特定的更改感到緊張,則可以始終在私有分支中執行測試合併。在
+這種情況下,git「rerere」工具很有用;它能記住合併衝突是如何解決的,這樣您
+就不必重複相同的工作。
+
+關於Git這樣的工具的一個最大的反覆抱怨是:補丁從一個存儲庫到另一個存儲庫的
+大量移動使得很容易陷入錯誤建議的變更中,這些變更避開審查雷達進入主線。當內
+核開發人員看到這種情況發生時,他們往往會感到不高興;在Git樹上放置未審閱或
+主題外的補丁可能會影響您將來讓樹被拉取的能力。引用Linus的話:
+
+::
+
+   你可以給我發補丁,但當我從你那裡拉取一個Git補丁時,我需要知道你清楚
+   自己在做什麼,我需要能夠相信事情而 *無需* 手動檢查每個單獨的更改。
+
+(http://lwn.net/articles/224135/)。
+
+爲了避免這種情況,請確保給定分支中的所有補丁都與相關主題緊密相關;「驅動程序
+修復」分支不應更改核心內存管理代碼。而且,最重要的是,不要使用Git樹來繞過
+審查過程。不時的將樹的摘要發布到相關的列表中,在合適時候請求linux-next中
+包含該樹。
+
+如果其他人開始發送補丁以包含到您的樹中,不要忘記審閱它們。還要確保您維護正確
+的作者信息; git 「am」工具在這方面做得最好,但是如果補丁通過第三方轉發給您,
+您可能需要在補丁中添加「From:」行。
+
+請求拉取時,請務必提供所有相關信息:樹的位置、要拉取的分支以及拉取將導致的
+更改。在這方面 git request-pull 命令非常有用;它將按照其他開發人員所期望的
+格式化請求,並檢查以確保您已記得將這些更改推送到公共伺服器。
+
+審閱補丁
+--------
+
+一些讀者顯然會反對將本節與「高級主題」放在一起,因爲即使是剛開始的內核開發人員
+也應該審閱補丁。當然,沒有比查看其他人發布的代碼更好的方法來學習如何在內核環境
+中編程了。此外,審閱者永遠供不應求;通過審閱代碼,您可以對整個流程做出重大貢獻。
+
+審查代碼可能是一副令人生畏的圖景,特別是對一個新的內核開發人員來說,他們
+可能會對公開詢問代碼感到緊張,而這些代碼是由那些有更多經驗的人發布的。不過,
+即使是最有經驗的開發人員編寫的代碼也可以得到改進。也許對(所有)審閱者最好
+的建議是:把審閱評論當成問題而不是批評。詢問「在這條路徑中如何釋放鎖?」
+總是比說「這裡的鎖是錯誤的」更好。
+
+不同的開發人員將從不同的角度審查代碼。部分人會主要關注代碼風格以及代碼行是
+否有尾隨空格。其他人會主要關注補丁作爲一個整體實現的變更是否對內核有好處。
+同時也有人會檢查是否存在鎖問題、堆棧使用過度、可能的安全問題、在其他地方
+發現的代碼重複、足夠的文檔、對性能的不利影響、用戶空間ABI更改等。所有類型
+的檢查,只要它們能引導更好的代碼進入內核,都是受歡迎和值得的。
+
diff --git a/Documentation/translations/zh_TW/process/8.Conclusion.rst b/Documentation/translations/zh_TW/process/8.Conclusion.rst
new file mode 100644
index 000000000000..7572b17667d9
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/8.Conclusion.rst
@@ -0,0 +1,74 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/8.Conclusion.rst <development_conclusion>`
+:Translator:
+
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+
+:校譯:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+.. _tw_development_conclusion:
+
+更多信息
+========
+
+關於Linux內核開發和相關主題的信息來源很多。首先是在內核原始碼分發中找到的
+文檔目錄。頂級
+:ref:`Documentation/translations/zh_TW/process/howto.rst <tw_process_howto>`
+文件是一個重要的起點;
+:ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+和 :ref:`Documentation/translations/zh_TW/process/submitting-drivers.rst <tw_submittingdrivers>`
+也是所有內核開發人員都應該閱讀的內容。許多內部內核API都是使用kerneldoc機制
+記錄的;「make htmldocs」或「make pdfdocs」可用於以HTML或PDF格式生成這些文檔
+(儘管某些發行版提供的tex版本會遇到內部限制,無法正確處理文檔)。
+
+不同的網站在各個細節層次上討論內核開發。本文作者想謙虛地建議用 https://lwn.net/
+作爲來源;有關許多特定內核主題的信息可以通過以下網址的 LWN 內核索引找到:
+
+  http://lwn.net/kernel/index/
+
+除此之外,內核開發人員的一個寶貴資源是:
+
+  https://kernelnewbies.org/
+
+當然,也不應該忘記 https://kernel.org/ ,這是內核發布信息的最終位置。
+
+關於內核開發有很多書:
+
+  《Linux設備驅動程序》第三版(Jonathan Corbet、Alessandro Rubini和Greg Kroah Hartman)
+  線上版本在 http://lwn.net/kernel/ldd3/
+
+  《Linux內核設計與實現》(Robert Love)
+
+  《深入理解Linux內核》(Daniel Bovet和Marco Cesati)
+
+然而,所有這些書都有一個共同的缺點:它們上架時就往往有些過時,而且已經上架
+一段時間了。不過,在那裡還是可以找到相當多的好信息。
+
+有關git的文檔,請訪問:
+
+  https://www.kernel.org/pub/software/scm/git/docs/
+
+  https://www.kernel.org/pub/software/scm/git/docs/user-manual.html
+
+結論
+====
+
+祝賀所有通過這篇冗長的文檔的人。希望它能夠幫助您理解Linux內核是如何開發的,
+以及您如何參與這個過程。
+
+最後,重要的是參與。任何開源軟體項目都不會超過其貢獻者投入其中的總和。Linux
+內核的發展速度和以前一樣快,因爲它得到了大量開發人員的幫助,他們都在努力使它
+變得更好。內核是一個最成功的例子,說明了當成千上萬的人爲了一個共同的目標一起
+工作時,可以做出什麼。
+
+不過,內核總是可以從更大的開發人員基礎中獲益。總有更多的工作要做。但是同樣
+重要的是,Linux生態系統中的大多數其他參與者可以通過爲內核做出貢獻而受益。使
+代碼進入主線是提高代碼質量、降低維護和分發成本、提高對內核開發方向的影響程度
+等的關鍵。這是一種共贏的局面。啓動你的編輯器,來加入我們吧;你會非常受歡迎的。
+
diff --git a/Documentation/translations/zh_TW/process/code-of-conduct-interpretation.rst b/Documentation/translations/zh_TW/process/code-of-conduct-interpretation.rst
new file mode 100644
index 000000000000..949d831aaf6c
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/code-of-conduct-interpretation.rst
@@ -0,0 +1,112 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/code-of-conduct-interpretation.rst <code_of_conduct_interpretation>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+.. _tw_code_of_conduct_interpretation:
+
+Linux內核貢獻者契約行為準則解釋
+===============================
+
+:ref:`tw_code_of_conduct` 準則是一個通用文檔,旨在爲幾乎所有開源社區提供一套規則。
+每個開源社區都是獨一無二的,Linux內核也不例外。因此,本文描述了Linux內核社區中
+如何解釋它。我們也不希望這種解釋隨著時間的推移是靜態的,並將根據需要進行調整。
+
+與開發軟體的「傳統」方法相比,Linux內核開發工作是一個非常個人化的過程。你的貢獻
+和背後的想法將被仔細審查,往往導致批判和批評。審查將幾乎總是需要改進,材料才
+能包括在內核中。要知道這是因爲所有相關人員都希望看到Linux整體成功的最佳解決方
+案。這個開發過程已經被證明可以創建有史以來最健壯的作業系統內核,我們不想做任何
+事情來導致提交質量和最終結果的下降。
+
+維護者
+------
+
+行為準則多次使用「維護者」一詞。在內核社區中,「維護者」是負責子系統、驅動程序或
+文件的任何人,並在內核原始碼樹的維護者文件中列出。
+
+責任
+----
+
+《行為準則》提到了維護人員的權利和責任,這需要進一步澄清。
+
+首先,最重要的是,有一個合理的期望是由維護人員通過實例來領導。
+
+也就是說,我們的社區是廣闊的,對維護者沒有新的要求,他們單方面處理其他人在
+他們活躍的社區的行爲。這一責任由我們所有人承擔,最終《行為準則》記錄了最終的
+上訴路徑,以防有關行爲問題的問題懸而未決。
+
+維護人員應該願意在出現問題時提供幫助,並在需要時與社區中的其他人合作。如果您
+不確定如何處理出現的情況,請不要害怕聯繫技術諮詢委員會(TAB)或其他維護人員。
+除非您願意,否則不會將其視爲違規報告。如果您不確定是否該聯繫TAB 或任何其他維
+護人員,請聯繫我們的衝突調解人 Mishi Choudhary <mishi@linux.com>。
+
+最後,「善待對方」才是每個人的最終目標。我們知道每個人都是人,有時我們都會失敗,
+但我們所有人的首要目標應該是努力友好地解決問題。執行行為準則將是最後的選擇。
+
+我們的目標是創建一個強大的、技術先進的作業系統,以及所涉及的技術複雜性,這自
+然需要專業知識和決策。
+
+所需的專業知識因貢獻領域而異。它主要由上下文和技術複雜性決定,其次由貢獻者和
+維護者的期望決定。
+
+專家的期望和決策都要經過討論,但在最後,爲了取得進展,必須能夠做出決策。這一
+特權掌握在維護人員和項目領導的手中,預計將善意使用。
+
+因此,設定專業知識期望、作出決定和拒絕不適當的貢獻不被視爲違反行為準則。
+
+雖然維護人員一般都歡迎新來者,但他們幫助(新)貢獻者克服障礙的能力有限,因此
+他們必須確定優先事項。這也不應被視爲違反了行為準則。內核社區意識到這一點,並
+以各種形式提供入門級節目,如 kernelnewbies.org 。
+
+範圍
+----
+
+Linux內核社區主要在一組公共電子郵件列表上進行交互,這些列表分布在由多個不同
+公司或個人控制的多個不同伺服器上。所有這些列表都在內核原始碼樹中的
+MAINTAINERS 文件中定義。發送到這些郵件列表的任何電子郵件都被視爲包含在行爲
+準則中。
+
+使用 kernel.org bugzilla和其他子系統bugzilla 或bug跟蹤工具的開發人員應該遵循
+行為準則的指導原則。Linux內核社區沒有「官方」項目電子郵件地址或「官方」社交媒體
+地址。使用kernel.org電子郵件帳戶執行的任何活動必須遵循爲kernel.org發布的行爲
+準則,就像任何使用公司電子郵件帳戶的個人必須遵循該公司的特定規則一樣。
+
+行為準則並不禁止在郵件列表消息、內核更改日誌消息或代碼注釋中繼續包含名稱、
+電子郵件地址和相關注釋。
+
+其他論壇中的互動包括在適用於上述論壇的任何規則中,通常不包括在行為準則中。
+除了在極端情況下可考慮的例外情況。
+
+提交給內核的貢獻應該使用適當的語言。在行為準則之前已經存在的內容現在不會被
+視爲違反。然而,不適當的語言可以被視爲一個bug;如果任何相關方提交補丁,
+這樣的bug將被更快地修復。當前屬於用戶/內核API的一部分的表達式,或者反映已
+發布標準或規範中使用的術語的表達式,不被視爲bug。
+
+執行
+----
+
+行為準則中列出的地址屬於行為準則委員會。https://kernel.org/code-of-conduct.html
+列出了在任何給定時間接收這些電子郵件的確切成員。成員不能訪問在加入委員會之前
+或離開委員會之後所做的報告。
+
+最初的行為準則委員會由TAB的志願者以及作爲中立第三方的專業調解人組成。委員會
+的首要任務是建立文件化的流程,並將其公開。
+
+如果報告人不希望將整個委員會納入投訴或關切,可直接聯繫委員會的任何成員,包括
+調解人。
+
+行為準則委員會根據流程審查案例(見上文),並根據需要和適當與TAB協商,例如請求
+和接收有關內核社區的信息。
+
+委員會做出的任何決定都將提交到表中,以便在必要時與相關維護人員一起執行。行爲
+準則委員會的決定可以通過三分之二的投票推翻。
+
+每季度,行為準則委員會和標籤將提供一份報告,概述行為準則委員會收到的匿名報告
+及其狀態,以及任何否決決定的細節,包括完整和可識別的投票細節。
+
+我們希望在啓動期之後爲行為準則委員會人員配備建立一個不同的流程。發生此情況時,
+將使用該信息更新此文檔。
+
diff --git a/Documentation/translations/zh_TW/process/code-of-conduct.rst b/Documentation/translations/zh_TW/process/code-of-conduct.rst
new file mode 100644
index 000000000000..716e5843b6e9
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/code-of-conduct.rst
@@ -0,0 +1,76 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/code-of-conduct.rst <code_of_conduct>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+.. _tw_code_of_conduct:
+
+貢獻者契約行為準則
+++++++++++++++++++
+
+我們的誓言
+==========
+
+爲了營造一個開放、友好的環境,我們作爲貢獻者和維護人承諾,讓我們的社區和參
+與者,擁有一個無騷擾的體驗,無論年齡、體型、殘疾、種族、性別特徵、性別認同
+和表達、經驗水平、教育程度、社會狀況,經濟地位、國籍、個人外貌、種族、宗教
+或性身份和取向。
+
+我們的標準
+==========
+
+有助於創造積極環境的行爲包括:
+
+* 使用歡迎和包容的語言
+* 尊重不同的觀點和經驗
+* 優雅地接受建設性的批評
+* 關注什麼對社區最有利
+* 對其他社區成員表示同情
+
+參與者的不可接受行爲包括:
+
+* 使用性意味的語言或意象以及不受歡迎的性注意或者更過分的行爲
+* 煽動、侮辱/貶損評論以及個人或政治攻擊
+* 公開或私下騷擾
+* 未經明確許可,發布他人的私人信息,如物理或電子地址。
+* 在專業場合被合理認爲不適當的其他行爲
+
+我們的責任
+==========
+
+維護人員負責澄清可接受行爲的標準,並應針對任何不可接受行爲採取適當和公平的
+糾正措施。
+
+維護人員有權和責任刪除、編輯或拒絕與本行為準則不一致的評論、承諾、代碼、
+wiki編輯、問題和其他貢獻,或暫時或永久禁止任何貢獻者從事他們認爲不適當、
+威脅、冒犯或有害的其他行爲。
+
+範圍
+====
+
+當個人代表項目或其社區時,本行為準則既適用於項目空間,也適用於公共空間。
+代表一個項目或社區的例子包括使用一個正式的項目電子郵件地址,通過一個正式
+的社交媒體帳戶發布,或者在在線或離線事件中擔任指定的代表。項目維護人員可以
+進一步定義和澄清項目的表示。
+
+執行
+====
+
+如有濫用、騷擾或其他不可接受的行爲,可聯繫行為準則委員會<conduct@kernel.org>。
+所有投訴都將接受審查和調查,並將得到必要和適當的答覆。行為準則委員會有義務
+對事件報告人保密。具體執行政策的進一步細節可單獨公布。
+
+歸屬
+====
+
+本行為準則改編自《貢獻者契約》,版本1.4,可從
+https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 獲取。
+
+解釋
+====
+
+有關Linux內核社區如何解釋此文檔,請參閱 :ref:`tw_code_of_conduct_interpretation`
+
diff --git a/Documentation/translations/zh_TW/process/coding-style.rst b/Documentation/translations/zh_TW/process/coding-style.rst
new file mode 100644
index 000000000000..61e614aad6a7
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/coding-style.rst
@@ -0,0 +1,958 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/coding-style.rst <codingstyle>`
+
+.. _tw_codingstyle:
+
+譯者::
+
+  中文版維護者: 張樂 Zhang Le <r0bertz@gentoo.org>
+  中文版翻譯者: 張樂 Zhang Le <r0bertz@gentoo.org>
+  中文版校譯者: 王聰 Wang Cong <xiyou.wangcong@gmail.com>
+                 wheelz <kernel.zeng@gmail.com>
+                 管旭東 Xudong Guan <xudong.guan@gmail.com>
+                 Li Zefan <lizf@cn.fujitsu.com>
+                 Wang Chen <wangchen@cn.fujitsu.com>
+                 Hu Haowen <src.res@email.cn>
+
+Linux 內核代碼風格
+=========================
+
+這是一個簡短的文檔,描述了 linux 內核的首選代碼風格。代碼風格是因人而異的,
+而且我不願意把自己的觀點強加給任何人,但這就像我去做任何事情都必須遵循的原則
+那樣,我也希望在絕大多數事上保持這種的態度。請 (在寫代碼時) 至少考慮一下這裡
+的代碼風格。
+
+首先,我建議你列印一份 GNU 代碼規範,然後不要讀。燒了它,這是一個具有重大象徵
+性意義的動作。
+
+不管怎樣,現在我們開始:
+
+
+1) 縮進
+--------------
+
+制表符是 8 個字符,所以縮進也是 8 個字符。有些異端運動試圖將縮進變爲 4 (甚至
+2!) 字符深,這幾乎相當於嘗試將圓周率的值定義爲 3。
+
+理由:縮進的全部意義就在於清楚的定義一個控制塊起止於何處。尤其是當你盯著你的
+屏幕連續看了 20 小時之後,你將會發現大一點的縮進會使你更容易分辨縮進。
+
+現在,有些人會抱怨 8 個字符的縮進會使代碼向右邊移動的太遠,在 80 個字符的終端
+屏幕上就很難讀這樣的代碼。這個問題的答案是,如果你需要 3 級以上的縮進,不管用
+何種方式你的代碼已經有問題了,應該修正你的程序。
+
+簡而言之,8 個字符的縮進可以讓代碼更容易閱讀,還有一個好處是當你的函數嵌套太
+深的時候可以給你警告。留心這個警告。
+
+在 switch 語句中消除多級縮進的首選的方式是讓 ``switch`` 和從屬於它的 ``case``
+標籤對齊於同一列,而不要 ``兩次縮進`` ``case`` 標籤。比如:
+
+.. code-block:: c
+
+	switch (suffix) {
+	case 'G':
+	case 'g':
+		mem <<= 30;
+		break;
+	case 'M':
+	case 'm':
+		mem <<= 20;
+		break;
+	case 'K':
+	case 'k':
+		mem <<= 10;
+		fallthrough;
+	default:
+		break;
+	}
+
+不要把多個語句放在一行里,除非你有什麼東西要隱藏:
+
+.. code-block:: c
+
+	if (condition) do_this;
+	  do_something_everytime;
+
+也不要在一行里放多個賦值語句。內核代碼風格超級簡單。就是避免可能導致別人誤讀
+的表達式。
+
+除了注釋、文檔和 Kconfig 之外,不要使用空格來縮進,前面的例子是例外,是有意爲
+之。
+
+選用一個好的編輯器,不要在行尾留空格。
+
+
+2) 把長的行和字符串打散
+------------------------------
+
+代碼風格的意義就在於使用平常使用的工具來維持代碼的可讀性和可維護性。
+
+每一行的長度的限制是 80 列,我們強烈建議您遵守這個慣例。
+
+長於 80 列的語句要打散成有意義的片段。除非超過 80 列能顯著增加可讀性,並且不
+會隱藏信息。子片段要明顯短於母片段,並明顯靠右。這同樣適用於有著很長參數列表
+的函數頭。然而,絕對不要打散對用戶可見的字符串,例如 printk 信息,因爲這樣就
+很難對它們 grep。
+
+
+3) 大括號和空格的放置
+------------------------------
+
+C 語言風格中另外一個常見問題是大括號的放置。和縮進大小不同,選擇或棄用某种放
+置策略並沒有多少技術上的原因,不過首選的方式,就像 Kernighan 和 Ritchie 展示
+給我們的,是把起始大括號放在行尾,而把結束大括號放在行首,所以:
+
+.. code-block:: c
+
+	if (x is true) {
+		we do y
+	}
+
+這適用於所有的非函數語句塊 (if, switch, for, while, do)。比如:
+
+.. code-block:: c
+
+	switch (action) {
+	case KOBJ_ADD:
+		return "add";
+	case KOBJ_REMOVE:
+		return "remove";
+	case KOBJ_CHANGE:
+		return "change";
+	default:
+		return NULL;
+	}
+
+不過,有一個例外,那就是函數:函數的起始大括號放置於下一行的開頭,所以:
+
+.. code-block:: c
+
+	int function(int x)
+	{
+		body of function
+	}
+
+全世界的異端可能會抱怨這個不一致性是... 呃... 不一致的,不過所有思維健全的人
+都知道 (a) K&R 是 **正確的** 並且 (b) K&R 是正確的。此外,不管怎樣函數都是特
+殊的 (C 函數是不能嵌套的)。
+
+注意結束大括號獨自占據一行,除非它後面跟著同一個語句的剩餘部分,也就是 do 語
+句中的 "while" 或者 if 語句中的 "else",像這樣:
+
+.. code-block:: c
+
+	do {
+		body of do-loop
+	} while (condition);
+
+和
+
+.. code-block:: c
+
+	if (x == y) {
+		..
+	} else if (x > y) {
+		...
+	} else {
+		....
+	}
+
+理由:K&R。
+
+也請注意這種大括號的放置方式也能使空 (或者差不多空的) 行的數量最小化,同時不
+失可讀性。因此,由於你的屏幕上的新行是不可再生資源 (想想 25 行的終端屏幕),你
+將會有更多的空行來放置注釋。
+
+當只有一個單獨的語句的時候,不用加不必要的大括號。
+
+.. code-block:: c
+
+	if (condition)
+		action();
+
+和
+
+.. code-block:: c
+
+	if (condition)
+		do_this();
+	else
+		do_that();
+
+這並不適用於只有一個條件分支是單語句的情況;這時所有分支都要使用大括號:
+
+.. code-block:: c
+
+	if (condition) {
+		do_this();
+		do_that();
+	} else {
+		otherwise();
+	}
+
+3.1) 空格
+********************
+
+Linux 內核的空格使用方式 (主要) 取決於它是用於函數還是關鍵字。(大多數) 關鍵字
+後要加一個空格。值得注意的例外是 sizeof, typeof, alignof 和 __attribute__,這
+些關鍵字某些程度上看起來更像函數 (它們在 Linux 里也常常伴隨小括號而使用,儘管
+在 C 里這樣的小括號不是必需的,就像 ``struct fileinfo info;`` 聲明過後的
+``sizeof info``)。
+
+所以在這些關鍵字之後放一個空格::
+
+	if, switch, case, for, do, while
+
+但是不要在 sizeof, typeof, alignof 或者 __attribute__ 這些關鍵字之後放空格。
+例如,
+
+.. code-block:: c
+
+	s = sizeof(struct file);
+
+不要在小括號里的表達式兩側加空格。這是一個 **反例** :
+
+.. code-block:: c
+
+	s = sizeof( struct file );
+
+當聲明指針類型或者返回指針類型的函數時, ``*`` 的首選使用方式是使之靠近變量名
+或者函數名,而不是靠近類型名。例子:
+
+.. code-block:: c
+
+	char *linux_banner;
+	unsigned long long memparse(char *ptr, char **retptr);
+	char *match_strdup(substring_t *s);
+
+在大多數二元和三元操作符兩側使用一個空格,例如下面所有這些操作符::
+
+	=  +  -  <  >  *  /  %  |  &  ^  <=  >=  ==  !=  ?  :
+
+但是一元操作符後不要加空格::
+
+	&  *  +  -  ~  !  sizeof  typeof  alignof  __attribute__  defined
+
+後綴自加和自減一元操作符前不加空格::
+
+	++  --
+
+前綴自加和自減一元操作符後不加空格::
+
+	++  --
+
+``.`` 和 ``->`` 結構體成員操作符前後不加空格。
+
+不要在行尾留空白。有些可以自動縮進的編輯器會在新行的行首加入適量的空白,然後
+你就可以直接在那一行輸入代碼。不過假如你最後沒有在那一行輸入代碼,有些編輯器
+就不會移除已經加入的空白,就像你故意留下一個只有空白的行。包含行尾空白的行就
+這樣產生了。
+
+當 git 發現補丁包含了行尾空白的時候會警告你,並且可以應你的要求去掉行尾空白;
+不過如果你是正在打一系列補丁,這樣做會導致後面的補丁失敗,因爲你改變了補丁的
+上下文。
+
+
+4) 命名
+------------------------------
+
+C 是一個簡樸的語言,你的命名也應該這樣。和 Modula-2 和 Pascal 程式設計師不同,
+C 程式設計師不使用類似 ThisVariableIsATemporaryCounter 這樣華麗的名字。C 程式設計師會
+稱那個變量爲 ``tmp`` ,這樣寫起來會更容易,而且至少不會令其難於理解。
+
+不過,雖然混用大小寫的名字是不提倡使用的,但是全局變量還是需要一個具描述性的
+名字。稱一個全局函數爲 ``foo`` 是一個難以饒恕的錯誤。
+
+全局變量 (只有當你 **真正** 需要它們的時候再用它) 需要有一個具描述性的名字,就
+像全局函數。如果你有一個可以計算活動用戶數量的函數,你應該叫它
+``count_active_users()`` 或者類似的名字,你不應該叫它 ``cntuser()`` 。
+
+在函數名中包含函數類型 (所謂的匈牙利命名法) 是腦子出了問題——編譯器知道那些類
+型而且能夠檢查那些類型,這樣做只能把程式設計師弄糊塗了。難怪微軟總是製造出有問題
+的程序。
+
+本地變量名應該簡短,而且能夠表達相關的含義。如果你有一些隨機的整數型的循環計
+數器,它應該被稱爲 ``i`` 。叫它 ``loop_counter`` 並無益處,如果它沒有被誤解的
+可能的話。類似的, ``tmp`` 可以用來稱呼任意類型的臨時變量。
+
+如果你怕混淆了你的本地變量名,你就遇到另一個問題了,叫做函數增長荷爾蒙失衡綜
+合症。請看第六章 (函數)。
+
+
+5) Typedef
+-----------
+
+不要使用類似 ``vps_t`` 之類的東西。
+
+對結構體和指針使用 typedef 是一個 **錯誤** 。當你在代碼里看到:
+
+.. code-block:: c
+
+	vps_t a;
+
+這代表什麼意思呢?
+
+相反,如果是這樣
+
+.. code-block:: c
+
+	struct virtual_container *a;
+
+你就知道 ``a`` 是什麼了。
+
+很多人認爲 typedef ``能提高可讀性`` 。實際不是這樣的。它們只在下列情況下有用:
+
+ (a) 完全不透明的對象 (這種情況下要主動使用 typedef 來 **隱藏** 這個對象實際上
+     是什麼)。
+
+     例如: ``pte_t`` 等不透明對象,你只能用合適的訪問函數來訪問它們。
+
+     .. note::
+
+       不透明性和 "訪問函數" 本身是不好的。我們使用 pte_t 等類型的原因在於真
+       的是完全沒有任何共用的可訪問信息。
+
+ (b) 清楚的整數類型,如此,這層抽象就可以 **幫助** 消除到底是 ``int`` 還是
+     ``long`` 的混淆。
+
+     u8/u16/u32 是完全沒有問題的 typedef,不過它們更符合類別 (d) 而不是這裡。
+
+     .. note::
+
+       要這樣做,必須事出有因。如果某個變量是 ``unsigned long`` ,那麼沒有必要
+
+	typedef unsigned long myflags_t;
+
+     不過如果有一個明確的原因,比如它在某種情況下可能會是一個 ``unsigned int``
+     而在其他情況下可能爲 ``unsigned long`` ,那麼就不要猶豫,請務必使用
+     typedef。
+
+ (c) 當你使用 sparse 按字面的創建一個 **新** 類型來做類型檢查的時候。
+
+ (d) 和標準 C99 類型相同的類型,在某些例外的情況下。
+
+     雖然讓眼睛和腦筋來適應新的標準類型比如 ``uint32_t`` 不需要花很多時間,可
+     是有些人仍然拒絕使用它們。
+
+     因此,Linux 特有的等同於標準類型的 ``u8/u16/u32/u64`` 類型和它們的有符號
+     類型是被允許的——儘管在你自己的新代碼中,它們不是強制要求要使用的。
+
+     當編輯已經使用了某個類型集的已有代碼時,你應該遵循那些代碼中已經做出的選
+     擇。
+
+ (e) 可以在用戶空間安全使用的類型。
+
+     在某些用戶空間可見的結構體裡,我們不能要求 C99 類型而且不能用上面提到的
+     ``u32`` 類型。因此,我們在與用戶空間共享的所有結構體中使用 __u32 和類似
+     的類型。
+
+可能還有其他的情況,不過基本的規則是 **永遠不要** 使用 typedef,除非你可以明
+確的應用上述某個規則中的一個。
+
+總的來說,如果一個指針或者一個結構體裡的元素可以合理的被直接訪問到,那麼它們
+就不應該是一個 typedef。
+
+
+6) 函數
+------------------------------
+
+函數應該簡短而漂亮,並且只完成一件事情。函數應該可以一屏或者兩屏顯示完 (我們
+都知道 ISO/ANSI 屏幕大小是 80x24),只做一件事情,而且把它做好。
+
+一個函數的最大長度是和該函數的複雜度和縮進級數成反比的。所以,如果你有一個理
+論上很簡單的只有一個很長 (但是簡單) 的 case 語句的函數,而且你需要在每個 case
+里做很多很小的事情,這樣的函數儘管很長,但也是可以的。
+
+不過,如果你有一個複雜的函數,而且你懷疑一個天分不是很高的高中一年級學生可能
+甚至搞不清楚這個函數的目的,你應該嚴格遵守前面提到的長度限制。使用輔助函數,
+並爲之取個具描述性的名字 (如果你覺得它們的性能很重要的話,可以讓編譯器內聯它
+們,這樣的效果往往會比你寫一個複雜函數的效果要好。)
+
+函數的另外一個衡量標準是本地變量的數量。此數量不應超過 5-10 個,否則你的函數
+就有問題了。重新考慮一下你的函數,把它分拆成更小的函數。人的大腦一般可以輕鬆
+的同時跟蹤 7 個不同的事物,如果再增多的話,就會糊塗了。即便你聰穎過人,你也可
+能會記不清你 2 個星期前做過的事情。
+
+在源文件里,使用空行隔開不同的函數。如果該函數需要被導出,它的 **EXPORT** 宏
+應該緊貼在它的結束大括號之下。比如:
+
+.. code-block:: c
+
+	int system_is_up(void)
+	{
+		return system_state == SYSTEM_RUNNING;
+	}
+	EXPORT_SYMBOL(system_is_up);
+
+在函數原型中,包含函數名和它們的數據類型。雖然 C 語言裡沒有這樣的要求,在
+Linux 里這是提倡的做法,因爲這樣可以很簡單的給讀者提供更多的有價值的信息。
+
+
+7) 集中的函數退出途徑
+------------------------------
+
+雖然被某些人聲稱已經過時,但是 goto 語句的等價物還是經常被編譯器所使用,具體
+形式是無條件跳轉指令。
+
+當一個函數從多個位置退出,並且需要做一些類似清理的常見操作時,goto 語句就很方
+便了。如果並不需要清理操作,那麼直接 return 即可。
+
+選擇一個能夠說明 goto 行爲或它爲何存在的標籤名。如果 goto 要釋放 ``buffer``,
+一個不錯的名字可以是 ``out_free_buffer:`` 。別去使用像 ``err1:`` 和 ``err2:``
+這樣的GW_BASIC 名稱,因爲一旦你添加或刪除了 (函數的) 退出路徑,你就必須對它們
+重新編號,這樣會難以去檢驗正確性。
+
+使用 goto 的理由是:
+
+- 無條件語句容易理解和跟蹤
+- 嵌套程度減小
+- 可以避免由於修改時忘記更新個別的退出點而導致錯誤
+- 讓編譯器省去刪除冗餘代碼的工作 ;)
+
+.. code-block:: c
+
+	int fun(int a)
+	{
+		int result = 0;
+		char *buffer;
+
+		buffer = kmalloc(SIZE, GFP_KERNEL);
+		if (!buffer)
+			return -ENOMEM;
+
+		if (condition1) {
+			while (loop1) {
+				...
+			}
+			result = 1;
+			goto out_free_buffer;
+		}
+		...
+	out_free_buffer:
+		kfree(buffer);
+		return result;
+	}
+
+一個需要注意的常見錯誤是 ``一個 err 錯誤`` ,就像這樣:
+
+.. code-block:: c
+
+	err:
+		kfree(foo->bar);
+		kfree(foo);
+		return ret;
+
+這段代碼的錯誤是,在某些退出路徑上 ``foo`` 是 NULL。通常情況下,通過把它分離
+成兩個錯誤標籤 ``err_free_bar:`` 和 ``err_free_foo:`` 來修復這個錯誤:
+
+.. code-block:: c
+
+	 err_free_bar:
+		kfree(foo->bar);
+	 err_free_foo:
+		kfree(foo);
+		return ret;
+
+理想情況下,你應該模擬錯誤來測試所有退出路徑。
+
+
+8) 注釋
+------------------------------
+
+注釋是好的,不過有過度注釋的危險。永遠不要在注釋里解釋你的代碼是如何運作的:
+更好的做法是讓別人一看你的代碼就可以明白,解釋寫的很差的代碼是浪費時間。
+
+一般的,你想要你的注釋告訴別人你的代碼做了什麼,而不是怎麼做的。也請你不要把
+注釋放在一個函數體內部:如果函數複雜到你需要獨立的注釋其中的一部分,你很可能
+需要回到第六章看一看。你可以做一些小注釋來註明或警告某些很聰明 (或者槽糕) 的
+做法,但不要加太多。你應該做的,是把注釋放在函數的頭部,告訴人們它做了什麼,
+也可以加上它做這些事情的原因。
+
+當注釋內核 API 函數時,請使用 kernel-doc 格式。請看
+Documentation/doc-guide/ 和 scripts/kernel-doc 以獲得詳細信息。
+
+長 (多行) 注釋的首選風格是:
+
+.. code-block:: c
+
+	/*
+	 * This is the preferred style for multi-line
+	 * comments in the Linux kernel source code.
+	 * Please use it consistently.
+	 *
+	 * Description:  A column of asterisks on the left side,
+	 * with beginning and ending almost-blank lines.
+	 */
+
+對於在 net/ 和 drivers/net/ 的文件,首選的長 (多行) 注釋風格有些不同。
+
+.. code-block:: c
+
+	/* The preferred comment style for files in net/ and drivers/net
+	 * looks like this.
+	 *
+	 * It is nearly the same as the generally preferred comment style,
+	 * but there is no initial almost-blank line.
+	 */
+
+注釋數據也是很重要的,不管是基本類型還是衍生類型。爲了方便實現這一點,每一行
+應只聲明一個數據 (不要使用逗號來一次聲明多個數據)。這樣你就有空間來爲每個數據
+寫一段小注釋來解釋它們的用途了。
+
+
+9) 你已經把事情弄糟了
+------------------------------
+
+這沒什麼,我們都是這樣。可能你的使用了很長時間 Unix 的朋友已經告訴你
+``GNU emacs`` 能自動幫你格式化 C 原始碼,而且你也注意到了,確實是這樣,不過它
+所使用的默認值和我們想要的相去甚遠 (實際上,甚至比隨機打的還要差——無數個猴子
+在 GNU emacs 里打字永遠不會創造出一個好程序) (譯註:Infinite Monkey Theorem)
+
+所以你要麼放棄 GNU emacs,要麼改變它讓它使用更合理的設定。要採用後一個方案,
+你可以把下面這段粘貼到你的 .emacs 文件里。
+
+.. code-block:: none
+
+  (defun c-lineup-arglist-tabs-only (ignored)
+    "Line up argument lists by tabs, not spaces"
+    (let* ((anchor (c-langelem-pos c-syntactic-element))
+           (column (c-langelem-2nd-pos c-syntactic-element))
+           (offset (- (1+ column) anchor))
+           (steps (floor offset c-basic-offset)))
+      (* (max steps 1)
+         c-basic-offset)))
+
+  (dir-locals-set-class-variables
+   'linux-kernel
+   '((c-mode . (
+          (c-basic-offset . 8)
+          (c-label-minimum-indentation . 0)
+          (c-offsets-alist . (
+                  (arglist-close         . c-lineup-arglist-tabs-only)
+                  (arglist-cont-nonempty .
+		      (c-lineup-gcc-asm-reg c-lineup-arglist-tabs-only))
+                  (arglist-intro         . +)
+                  (brace-list-intro      . +)
+                  (c                     . c-lineup-C-comments)
+                  (case-label            . 0)
+                  (comment-intro         . c-lineup-comment)
+                  (cpp-define-intro      . +)
+                  (cpp-macro             . -1000)
+                  (cpp-macro-cont        . +)
+                  (defun-block-intro     . +)
+                  (else-clause           . 0)
+                  (func-decl-cont        . +)
+                  (inclass               . +)
+                  (inher-cont            . c-lineup-multi-inher)
+                  (knr-argdecl-intro     . 0)
+                  (label                 . -1000)
+                  (statement             . 0)
+                  (statement-block-intro . +)
+                  (statement-case-intro  . +)
+                  (statement-cont        . +)
+                  (substatement          . +)
+                  ))
+          (indent-tabs-mode . t)
+          (show-trailing-whitespace . t)
+          ))))
+
+  (dir-locals-set-directory-class
+   (expand-file-name "~/src/linux-trees")
+   'linux-kernel)
+
+這會讓 emacs 在 ``~/src/linux-trees`` 下的 C 源文件獲得更好的內核代碼風格。
+
+不過就算你嘗試讓 emacs 正確的格式化代碼失敗了,也並不意味著你失去了一切:還可
+以用 ``indent`` 。
+
+不過,GNU indent 也有和 GNU emacs 一樣有問題的設定,所以你需要給它一些命令選
+項。不過,這還不算太糟糕,因爲就算是 GNU indent 的作者也認同 K&R 的權威性
+(GNU 的人並不是壞人,他們只是在這個問題上被嚴重的誤導了),所以你只要給 indent
+指定選項 ``-kr -i8`` (代表 ``K&R,8 字符縮進``),或使用 ``scripts/Lindent``
+這樣就可以以最時髦的方式縮進原始碼。
+
+``indent`` 有很多選項,特別是重新格式化注釋的時候,你可能需要看一下它的手冊。
+不過記住: ``indent`` 不能修正壞的編程習慣。
+
+
+10) Kconfig 配置文件
+------------------------------
+
+對於遍布源碼樹的所有 Kconfig* 配置文件來說,它們縮進方式有所不同。緊挨著
+``config`` 定義的行,用一個制表符縮進,然而 help 信息的縮進則額外增加 2 個空
+格。舉個例子::
+
+  config AUDIT
+	bool "Auditing support"
+	depends on NET
+	help
+	  Enable auditing infrastructure that can be used with another
+	  kernel subsystem, such as SELinux (which requires this for
+	  logging of avc messages output).  Does not do system-call
+	  auditing without CONFIG_AUDITSYSCALL.
+
+而那些危險的功能 (比如某些文件系統的寫支持) 應該在它們的提示字符串里顯著的聲
+明這一點::
+
+  config ADFS_FS_RW
+	bool "ADFS write support (DANGEROUS)"
+	depends on ADFS_FS
+	...
+
+要查看配置文件的完整文檔,請看 Documentation/kbuild/kconfig-language.rst。
+
+
+11) 數據結構
+------------------------------
+
+如果一個數據結構,在創建和銷毀它的單線執行環境之外可見,那麼它必須要有一個引
+用計數器。內核里沒有垃圾收集 (並且內核之外的垃圾收集慢且效率低下),這意味著你
+絕對需要記錄你對這種數據結構的使用情況。
+
+引用計數意味著你能夠避免上鎖,並且允許多個用戶並行訪問這個數據結構——而不需要
+擔心這個數據結構僅僅因爲暫時不被使用就消失了,那些用戶可能不過是沉睡了一陣或
+者做了一些其他事情而已。
+
+注意上鎖 **不能** 取代引用計數。上鎖是爲了保持數據結構的一致性,而引用計數是一
+個內存管理技巧。通常二者都需要,不要把兩個搞混了。
+
+很多數據結構實際上有 2 級引用計數,它們通常有不同 ``類`` 的用戶。子類計數器統
+計子類用戶的數量,每當子類計數器減至零時,全局計數器減一。
+
+這種 ``多級引用計數`` 的例子可以在內存管理 (``struct mm_struct``: mm_users 和
+mm_count),和文件系統 (``struct super_block``: s_count 和 s_active) 中找到。
+
+記住:如果另一個執行線索可以找到你的數據結構,但這個數據結構沒有引用計數器,
+這裡幾乎肯定是一個 bug。
+
+
+12) 宏,枚舉和RTL
+------------------------------
+
+用於定義常量的宏的名字及枚舉里的標籤需要大寫。
+
+.. code-block:: c
+
+	#define CONSTANT 0x12345
+
+在定義幾個相關的常量時,最好用枚舉。
+
+宏的名字請用大寫字母,不過形如函數的宏的名字可以用小寫字母。
+
+一般的,如果能寫成內聯函數就不要寫成像函數的宏。
+
+含有多個語句的宏應該被包含在一個 do-while 代碼塊里:
+
+.. code-block:: c
+
+	#define macrofun(a, b, c)			\
+		do {					\
+			if (a == 5)			\
+				do_this(b, c);		\
+		} while (0)
+
+使用宏的時候應避免的事情:
+
+1) 影響控制流程的宏:
+
+.. code-block:: c
+
+	#define FOO(x)					\
+		do {					\
+			if (blah(x) < 0)		\
+				return -EBUGGERED;	\
+		} while (0)
+
+**非常** 不好。它看起來像一個函數,不過卻能導致 ``調用`` 它的函數退出;不要打
+亂讀者大腦里的語法分析器。
+
+2) 依賴於一個固定名字的本地變量的宏:
+
+.. code-block:: c
+
+	#define FOO(val) bar(index, val)
+
+可能看起來像是個不錯的東西,不過它非常容易把讀代碼的人搞糊塗,而且容易導致看起
+來不相關的改動帶來錯誤。
+
+3) 作爲左值的帶參數的宏: FOO(x) = y;如果有人把 FOO 變成一個內聯函數的話,這
+   種用法就會出錯了。
+
+4) 忘記了優先級:使用表達式定義常量的宏必須將表達式置於一對小括號之內。帶參數
+   的宏也要注意此類問題。
+
+.. code-block:: c
+
+	#define CONSTANT 0x4000
+	#define CONSTEXP (CONSTANT | 3)
+
+5) 在宏里定義類似函數的本地變量時命名衝突:
+
+.. code-block:: c
+
+	#define FOO(x)				\
+	({					\
+		typeof(x) ret;			\
+		ret = calc_ret(x);		\
+		(ret);				\
+	})
+
+ret 是本地變量的通用名字 - __foo_ret 更不容易與一個已存在的變量衝突。
+
+cpp 手冊對宏的講解很詳細。gcc internals 手冊也詳細講解了 RTL,內核里的彙編語
+言經常用到它。
+
+
+13) 列印內核消息
+------------------------------
+
+內核開發者應該是受過良好教育的。請一定注意內核信息的拼寫,以給人以好的印象。
+不要用不規範的單詞比如 ``dont``,而要用 ``do not`` 或者 ``don't`` 。保證這些信
+息簡單明了,無歧義。
+
+內核信息不必以英文句號結束。
+
+在小括號里列印數字 (%d) 沒有任何價值,應該避免這樣做。
+
+<linux/device.h> 里有一些驅動模型診斷宏,你應該使用它們,以確保信息對應於正確
+的設備和驅動,並且被標記了正確的消息級別。這些宏有:dev_err(), dev_warn(),
+dev_info() 等等。對於那些不和某個特定設備相關連的信息,<linux/printk.h> 定義
+了 pr_notice(), pr_info(), pr_warn(), pr_err() 和其他。
+
+寫出好的調試信息可以是一個很大的挑戰;一旦你寫出後,這些信息在遠程除錯時能提
+供極大的幫助。然而列印調試信息的處理方式同列印非調試信息不同。其他 pr_XXX()
+函數能無條件地列印,pr_debug() 卻不;默認情況下它不會被編譯,除非定義了 DEBUG
+或設定了 CONFIG_DYNAMIC_DEBUG。實際這同樣是爲了 dev_dbg(),一個相關約定是在一
+個已經開啓了 DEBUG 時,使用 VERBOSE_DEBUG 來添加 dev_vdbg()。
+
+許多子系統擁有 Kconfig 調試選項來開啓 -DDEBUG 在對應的 Makefile 裡面;在其他
+情況下,特殊文件使用 #define DEBUG。當一條調試信息需要被無條件列印時,例如,
+如果已經包含一個調試相關的 #ifdef 條件,printk(KERN_DEBUG ...) 就可被使用。
+
+
+14) 分配內存
+------------------------------
+
+內核提供了下面的一般用途的內存分配函數:
+kmalloc(), kzalloc(), kmalloc_array(), kcalloc(), vmalloc() 和 vzalloc()。
+請參考 API 文檔以獲取有關它們的詳細信息。
+
+傳遞結構體大小的首選形式是這樣的:
+
+.. code-block:: c
+
+	p = kmalloc(sizeof(*p), ...);
+
+另外一種傳遞方式中,sizeof 的操作數是結構體的名字,這樣會降低可讀性,並且可能
+會引入 bug。有可能指針變量類型被改變時,而對應的傳遞給內存分配函數的 sizeof
+的結果不變。
+
+強制轉換一個 void 指針返回值是多餘的。C 語言本身保證了從 void 指針到其他任何
+指針類型的轉換是沒有問題的。
+
+分配一個數組的首選形式是這樣的:
+
+.. code-block:: c
+
+	p = kmalloc_array(n, sizeof(...), ...);
+
+分配一個零長數組的首選形式是這樣的:
+
+.. code-block:: c
+
+	p = kcalloc(n, sizeof(...), ...);
+
+兩種形式檢查分配大小 n * sizeof(...) 的溢出,如果溢出返回 NULL。
+
+
+15) 內聯弊病
+------------------------------
+
+有一個常見的誤解是 ``內聯`` 是 gcc 提供的可以讓代碼運行更快的一個選項。雖然使
+用內聯函數有時候是恰當的 (比如作爲一種替代宏的方式,請看第十二章),不過很多情
+況下不是這樣。inline 的過度使用會使內核變大,從而使整個系統運行速度變慢。
+因爲體積大內核會占用更多的指令高速緩存,而且會導致 pagecache 的可用內存減少。
+想像一下,一次 pagecache 未命中就會導致一次磁碟尋址,將耗時 5 毫秒。5 毫秒的
+時間內 CPU 能執行很多很多指令。
+
+一個基本的原則是如果一個函數有 3 行以上,就不要把它變成內聯函數。這個原則的一
+個例外是,如果你知道某個參數是一個編譯時常量,而且因爲這個常量你確定編譯器在
+編譯時能優化掉你的函數的大部分代碼,那仍然可以給它加上 inline 關鍵字。
+kmalloc() 內聯函數就是一個很好的例子。
+
+人們經常主張給 static 的而且只用了一次的函數加上 inline,如此不會有任何損失,
+因爲沒有什麼好權衡的。雖然從技術上說這是正確的,但是實際上這種情況下即使不加
+inline gcc 也可以自動使其內聯。而且其他用戶可能會要求移除 inline,由此而來的
+爭論會抵消 inline 自身的潛在價值,得不償失。
+
+
+16) 函數返回值及命名
+------------------------------
+
+函數可以返回多種不同類型的值,最常見的一種是表明函數執行成功或者失敗的值。這樣
+的一個值可以表示爲一個錯誤代碼整數 (-Exxx=失敗,0=成功) 或者一個 ``成功``
+布爾值 (0=失敗,非0=成功)。
+
+混合使用這兩種表達方式是難於發現的 bug 的來源。如果 C 語言本身嚴格區分整形和
+布爾型變量,那麼編譯器就能夠幫我們發現這些錯誤... 不過 C 語言不區分。爲了避免
+產生這種 bug,請遵循下面的慣例::
+
+	如果函數的名字是一個動作或者強制性的命令,那麼這個函數應該返回錯誤代
+	碼整數。如果是一個判斷,那麼函數應該返回一個 "成功" 布爾值。
+
+比如, ``add work`` 是一個命令,所以 add_work() 在成功時返回 0,在失敗時返回
+-EBUSY。類似的,因爲 ``PCI device present`` 是一個判斷,所以 pci_dev_present()
+在成功找到一個匹配的設備時應該返回 1,如果找不到時應該返回 0。
+
+所有 EXPORTed 函數都必須遵守這個慣例,所有的公共函數也都應該如此。私有
+(static) 函數不需要如此,但是我們也推薦這樣做。
+
+返回值是實際計算結果而不是計算是否成功的標誌的函數不受此慣例的限制。一般的,
+他們通過返回一些正常值範圍之外的結果來表示出錯。典型的例子是返回指針的函數,
+他們使用 NULL 或者 ERR_PTR 機制來報告錯誤。
+
+
+17) 不要重新發明內核宏
+------------------------------
+
+頭文件 include/linux/kernel.h 包含了一些宏,你應該使用它們,而不要自己寫一些
+它們的變種。比如,如果你需要計算一個數組的長度,使用這個宏
+
+.. code-block:: c
+
+	#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+類似的,如果你要計算某結構體成員的大小,使用
+
+.. code-block:: c
+
+	#define sizeof_field(t, f) (sizeof(((t*)0)->f))
+
+還有可以做嚴格的類型檢查的 min() 和 max() 宏,如果你需要可以使用它們。你可以
+自己看看那個頭文件里還定義了什麼你可以拿來用的東西,如果有定義的話,你就不應
+在你的代碼里自己重新定義。
+
+
+18) 編輯器模式行和其他需要羅嗦的事情
+--------------------------------------------------
+
+有一些編輯器可以解釋嵌入在源文件里的由一些特殊標記標明的配置信息。比如,emacs
+能夠解釋被標記成這樣的行:
+
+.. code-block:: c
+
+	-*- mode: c -*-
+
+或者這樣的:
+
+.. code-block:: c
+
+	/*
+	Local Variables:
+	compile-command: "gcc -DMAGIC_DEBUG_FLAG foo.c"
+	End:
+	*/
+
+Vim 能夠解釋這樣的標記:
+
+.. code-block:: c
+
+	/* vim:set sw=8 noet */
+
+不要在原始碼中包含任何這樣的內容。每個人都有他自己的編輯器配置,你的源文件不
+應該覆蓋別人的配置。這包括有關縮進和模式配置的標記。人們可以使用他們自己定製
+的模式,或者使用其他可以產生正確的縮進的巧妙方法。
+
+
+19) 內聯彙編
+------------------------------
+
+在特定架構的代碼中,你可能需要內聯彙編與 CPU 和平台相關功能連接。需要這麼做時
+就不要猶豫。然而,當 C 可以完成工作時,不要平白無故地使用內聯彙編。在可能的情
+況下,你可以並且應該用 C 和硬體溝通。
+
+請考慮去寫捆綁通用位元 (wrap common bits) 的內聯彙編的簡單輔助函數,別去重複
+地寫下只有細微差異內聯彙編。記住內聯彙編可以使用 C 參數。
+
+大型,有一定複雜度的彙編函數應該放在 .S 文件內,用相應的 C 原型定義在 C 頭文
+件中。彙編函數的 C 原型應該使用 ``asmlinkage`` 。
+
+你可能需要把彙編語句標記爲 volatile,用來阻止 GCC 在沒發現任何副作用後就把它
+移除了。你不必總是這樣做,儘管,這不必要的舉動會限制優化。
+
+在寫一個包含多條指令的單個內聯彙編語句時,把每條指令用引號分割而且各占一行,
+除了最後一條指令外,在每個指令結尾加上 \n\t,讓彙編輸出時可以正確地縮進下一條
+指令:
+
+.. code-block:: c
+
+	asm ("magic %reg1, #42\n\t"
+	     "more_magic %reg2, %reg3"
+	     : /* outputs */ : /* inputs */ : /* clobbers */);
+
+
+20) 條件編譯
+------------------------------
+
+只要可能,就不要在 .c 文件裡面使用預處理條件 (#if, #ifdef);這樣做讓代碼更難
+閱讀並且更難去跟蹤邏輯。替代方案是,在頭文件中用預處理條件提供給那些 .c 文件
+使用,再給 #else 提供一個空樁 (no-op stub) 版本,然後在 .c 文件內無條件地調用
+那些 (定義在頭文件內的) 函數。這樣做,編譯器會避免爲樁函數 (stub) 的調用生成
+任何代碼,產生的結果是相同的,但邏輯將更加清晰。
+
+最好傾向於編譯整個函數,而不是函數的一部分或表達式的一部分。與其放一個 ifdef
+在表達式內,不如分解出部分或全部表達式,放進一個單獨的輔助函數,並應用預處理
+條件到這個輔助函數內。
+
+如果你有一個在特定配置中,可能變成未使用的函數或變量,編譯器會警告它定義了但
+未使用,把它標記爲 __maybe_unused 而不是將它包含在一個預處理條件中。(然而,如
+果一個函數或變量總是未使用,就直接刪除它。)
+
+在代碼中,儘可能地使用 IS_ENABLED 宏來轉化某個 Kconfig 標記爲 C 的布爾
+表達式,並在一般的 C 條件中使用它:
+
+.. code-block:: c
+
+	if (IS_ENABLED(CONFIG_SOMETHING)) {
+		...
+	}
+
+編譯器會做常量摺疊,然後就像使用 #ifdef 那樣去包含或排除代碼塊,所以這不會帶
+來任何運行時開銷。然而,這種方法依舊允許 C 編譯器查看塊內的代碼,並檢查它的正
+確性 (語法,類型,符號引用,等等)。因此,如果條件不滿足,代碼塊內的引用符號就
+不存在時,你還是必須去用 #ifdef。
+
+在任何有意義的 #if 或 #ifdef 塊的末尾 (超過幾行的),在 #endif 同一行的後面寫下
+註解,注釋這個條件表達式。例如:
+
+.. code-block:: c
+
+	#ifdef CONFIG_SOMETHING
+	...
+	#endif /* CONFIG_SOMETHING */
+
+
+附錄 I) 參考
+-------------------
+
+The C Programming Language, 第二版
+作者:Brian W. Kernighan 和 Denni M. Ritchie.
+Prentice Hall, Inc., 1988.
+ISBN 0-13-110362-8 (軟皮), 0-13-110370-9 (硬皮).
+
+The Practice of Programming
+作者:Brian W. Kernighan 和 Rob Pike.
+Addison-Wesley, Inc., 1999.
+ISBN 0-201-61586-X.
+
+GNU 手冊 - 遵循 K&R 標準和此文本 - cpp, gcc, gcc internals and indent,
+都可以從 https://www.gnu.org/manual/ 找到
+
+WG14 是 C 語言的國際標準化工作組,URL: http://www.open-std.org/JTC1/SC22/WG14/
+
+Kernel process/coding-style.rst,作者 greg@kroah.com 發表於 OLS 2002:
+http://www.kroah.com/linux/talks/ols_2002_kernel_codingstyle_talk/html/
+
diff --git a/Documentation/translations/zh_TW/process/development-process.rst b/Documentation/translations/zh_TW/process/development-process.rst
new file mode 100644
index 000000000000..45e6385647cd
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/development-process.rst
@@ -0,0 +1,30 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/development-process.rst <development_process_main>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+.. _tw_development_process_main:
+
+內核開發過程指南
+================
+
+內容:
+
+.. toctree::
+   :numbered:
+   :maxdepth: 2
+
+   1.Intro
+   2.Process
+   3.Early-stage
+   4.Coding
+   5.Posting
+   6.Followthrough
+   7.AdvancedTopics
+   8.Conclusion
+
+本文檔的目的是幫助開發人員(及其經理)以最小的挫折感與開發社區合作。它試圖記錄這個社區如何以一種不熟悉Linux內核開發(或者實際上是自由軟體開發)的人可以訪問的方式工作。雖然這裡有一些技術資料,但這是一個面向過程的討論,不需要深入了解內核編程就可以理解。
+
diff --git a/Documentation/translations/zh_TW/process/email-clients.rst b/Documentation/translations/zh_TW/process/email-clients.rst
new file mode 100644
index 000000000000..4ba543d06f3b
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/email-clients.rst
@@ -0,0 +1,252 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _tw_email_clients:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/email-clients.rst <email_clients>`
+
+譯者::
+
+        中文版維護者: 賈威威  Harry Wei <harryxiyou@gmail.com>
+        中文版翻譯者: 賈威威  Harry Wei <harryxiyou@gmail.com>
+                       時奎亮  Alex Shi <alex.shi@linux.alibaba.com>
+        中文版校譯者: Yinglin Luan <synmyth@gmail.com>
+        	       Xiaochen Wang <wangxiaochen0@gmail.com>
+                       yaxinsn <yaxinsn@163.com>
+                      Hu Haowen <src.res@email.cn>
+
+Linux郵件客戶端配置信息
+=======================
+
+Git
+---
+
+現在大多數開發人員使用 ``git send-email`` 而不是常規的電子郵件客戶端。這方面
+的手冊非常好。在接收端,維護人員使用 ``git am`` 加載補丁。
+
+如果你是 ``git`` 新手,那麼把你的第一個補丁發送給你自己。將其保存爲包含所有
+標題的原始文本。運行 ``git am raw_email.txt`` ,然後使用 ``git log`` 查看更
+改日誌。如果工作正常,再將補丁發送到相應的郵件列表。
+
+
+普通配置
+--------
+Linux內核補丁是通過郵件被提交的,最好把補丁作爲郵件體的內嵌文本。有些維護者
+接收附件,但是附件的內容格式應該是"text/plain"。然而,附件一般是不贊成的,
+因爲這會使補丁的引用部分在評論過程中變的很困難。
+
+用來發送Linux內核補丁的郵件客戶端在發送補丁時應該處於文本的原始狀態。例如,
+他們不能改變或者刪除制表符或者空格,甚至是在每一行的開頭或者結尾。
+
+不要通過"format=flowed"模式發送補丁。這樣會引起不可預期以及有害的斷行。
+
+不要讓你的郵件客戶端進行自動換行。這樣也會破壞你的補丁。
+
+郵件客戶端不能改變文本的字符集編碼方式。要發送的補丁只能是ASCII或者UTF-8編碼方式,
+如果你使用UTF-8編碼方式發送郵件,那麼你將會避免一些可能發生的字符集問題。
+
+郵件客戶端應該形成並且保持 References: 或者 In-Reply-To: 標題,那麼
+郵件話題就不會中斷。
+
+複製粘帖(或者剪貼粘帖)通常不能用於補丁,因爲制表符會轉換爲空格。使用xclipboard, xclip
+或者xcutsel也許可以,但是最好測試一下或者避免使用複製粘帖。
+
+不要在使用PGP/GPG署名的郵件中包含補丁。這樣會使得很多腳本不能讀取和適用於你的補丁。
+(這個問題應該是可以修復的)
+
+在給內核郵件列表發送補丁之前,給自己發送一個補丁是個不錯的主意,保存接收到的
+郵件,將補丁用'patch'命令打上,如果成功了,再給內核郵件列表發送。
+
+
+一些郵件客戶端提示
+------------------
+這裡給出一些詳細的MUA配置提示,可以用於給Linux內核發送補丁。這些並不意味是
+所有的軟體包配置總結。
+
+說明:
+TUI = 以文本爲基礎的用戶接口
+GUI = 圖形界面用戶接口
+
+Alpine (TUI)
+~~~~~~~~~~~~
+
+配置選項:
+在"Sending Preferences"部分:
+
+- "Do Not Send Flowed Text"必須開啓
+- "Strip Whitespace Before Sending"必須關閉
+
+當寫郵件時,光標應該放在補丁會出現的地方,然後按下CTRL-R組合鍵,使指定的
+補丁文件嵌入到郵件中。
+
+Evolution (GUI)
+~~~~~~~~~~~~~~~
+
+一些開發者成功的使用它發送補丁
+
+當選擇郵件選項:Preformat
+  從Format->Heading->Preformatted (Ctrl-7)或者工具欄
+
+然後使用:
+  Insert->Text File... (Alt-n x)插入補丁文件。
+
+你還可以"diff -Nru old.c new.c | xclip",選擇Preformat,然後使用中間鍵進行粘帖。
+
+Kmail (GUI)
+~~~~~~~~~~~
+
+一些開發者成功的使用它發送補丁。
+
+默認設置不爲HTML格式是合適的;不要啓用它。
+
+當書寫一封郵件的時候,在選項下面不要選擇自動換行。唯一的缺點就是你在郵件中輸入的任何文本
+都不會被自動換行,因此你必須在發送補丁之前手動換行。最簡單的方法就是啓用自動換行來書寫郵件,
+然後把它保存爲草稿。一旦你在草稿中再次打開它,它已經全部自動換行了,那麼你的郵件雖然沒有
+選擇自動換行,但是還不會失去已有的自動換行。
+
+在郵件的底部,插入補丁之前,放上常用的補丁定界符:三個連字號(---)。
+
+然後在"Message"菜單條目,選擇插入文件,接著選取你的補丁文件。還有一個額外的選項,你可以
+通過它配置你的郵件建立工具欄菜單,還可以帶上"insert file"圖標。
+
+你可以安全地通過GPG標記附件,但是內嵌補丁最好不要使用GPG標記它們。作爲內嵌文本的簽發補丁,
+當從GPG中提取7位編碼時會使他們變的更加複雜。
+
+如果你非要以附件的形式發送補丁,那麼就右鍵點擊附件,然後選中屬性,突出"Suggest automatic
+display",這樣內嵌附件更容易讓讀者看到。
+
+當你要保存將要發送的內嵌文本補丁,你可以從消息列表窗格選擇包含補丁的郵件,然後右擊選擇
+"save as"。你可以使用一個沒有更改的包含補丁的郵件,如果它是以正確的形式組成。當你正真在它
+自己的窗口之下察看,那時沒有選項可以保存郵件--已經有一個這樣的bug被匯報到了kmail的bugzilla
+並且希望這將會被處理。郵件是以只針對某個用戶可讀寫的權限被保存的,所以如果你想把郵件複製到其他地方,
+你不得不把他們的權限改爲組或者整體可讀。
+
+Lotus Notes (GUI)
+~~~~~~~~~~~~~~~~~
+
+不要使用它。
+
+Mutt (TUI)
+~~~~~~~~~~
+
+很多Linux開發人員使用mutt客戶端,所以證明它肯定工作的非常漂亮。
+
+Mutt不自帶編輯器,所以不管你使用什麼編輯器都不應該帶有自動斷行。大多數編輯器都帶有
+一個"insert file"選項,它可以通過不改變文件內容的方式插入文件。
+
+'vim'作爲mutt的編輯器:
+  set editor="vi"
+
+  如果使用xclip,敲入以下命令
+  :set paste
+  按中鍵之前或者shift-insert或者使用
+  :r filename
+
+如果想要把補丁作爲內嵌文本。
+(a)ttach工作的很好,不帶有"set paste"。
+
+你可以通過 ``git format-patch`` 生成補丁,然後用 Mutt發送它們::
+
+        $ mutt -H 0001-some-bug-fix.patch
+
+配置選項:
+它應該以默認設置的形式工作。
+然而,把"send_charset"設置爲"us-ascii::utf-8"也是一個不錯的主意。
+
+Mutt 是高度可配置的。 這裡是個使用mutt通過 Gmail 發送的補丁的最小配置::
+
+  # .muttrc
+  # ================  IMAP ====================
+  set imap_user = 'yourusername@gmail.com'
+  set imap_pass = 'yourpassword'
+  set spoolfile = imaps://imap.gmail.com/INBOX
+  set folder = imaps://imap.gmail.com/
+  set record="imaps://imap.gmail.com/[Gmail]/Sent Mail"
+  set postponed="imaps://imap.gmail.com/[Gmail]/Drafts"
+  set mbox="imaps://imap.gmail.com/[Gmail]/All Mail"
+
+  # ================  SMTP  ====================
+  set smtp_url = "smtp://username@smtp.gmail.com:587/"
+  set smtp_pass = $imap_pass
+  set ssl_force_tls = yes # Require encrypted connection
+
+  # ================  Composition  ====================
+  set editor = `echo \$EDITOR`
+  set edit_headers = yes  # See the headers when editing
+  set charset = UTF-8     # value of $LANG; also fallback for send_charset
+  # Sender, email address, and sign-off line must match
+  unset use_domain        # because joe@localhost is just embarrassing
+  set realname = "YOUR NAME"
+  set from = "username@gmail.com"
+  set use_from = yes
+
+Mutt文檔含有更多信息:
+
+    http://dev.mutt.org/trac/wiki/UseCases/Gmail
+
+    http://dev.mutt.org/doc/manual.html
+
+Pine (TUI)
+~~~~~~~~~~
+
+Pine過去有一些空格刪減問題,但是這些現在應該都被修復了。
+
+如果可以,請使用alpine(pine的繼承者)
+
+配置選項:
+- 最近的版本需要消除流程文本
+- "no-strip-whitespace-before-send"選項也是需要的。
+
+
+Sylpheed (GUI)
+~~~~~~~~~~~~~~
+
+- 內嵌文本可以很好的工作(或者使用附件)。
+- 允許使用外部的編輯器。
+- 對於目錄較多時非常慢。
+- 如果通過non-SSL連接,無法使用TLS SMTP授權。
+- 在組成窗口中有一個很有用的ruler bar。
+- 給地址本中添加地址就不會正確的了解顯示名。
+
+Thunderbird (GUI)
+~~~~~~~~~~~~~~~~~
+
+默認情況下,thunderbird很容易損壞文本,但是還有一些方法可以強制它變得更好。
+
+- 在用戶帳號設置里,組成和尋址,不要選擇"Compose messages in HTML format"。
+
+- 編輯你的Thunderbird配置設置來使它不要拆行使用:user_pref("mailnews.wraplength", 0);
+
+- 編輯你的Thunderbird配置設置,使它不要使用"format=flowed"格式:user_pref("mailnews.
+  send_plaintext_flowed", false);
+
+- 你需要使Thunderbird變爲預先格式方式:
+  如果默認情況下你書寫的是HTML格式,那不是很難。僅僅從標題欄的下拉框中選擇"Preformat"格式。
+  如果默認情況下你書寫的是文本格式,你不得把它改爲HTML格式(僅僅作爲一次性的)來書寫新的消息,
+  然後強制使它回到文本格式,否則它就會拆行。要實現它,在寫信的圖標上使用shift鍵來使它變爲HTML
+  格式,然後標題欄的下拉框中選擇"Preformat"格式。
+
+- 允許使用外部的編輯器:
+  針對Thunderbird打補丁最簡單的方法就是使用一個"external editor"擴展,然後使用你最喜歡的
+  $EDITOR來讀取或者合併補丁到文本中。要實現它,可以下載並且安裝這個擴展,然後添加一個使用它的
+  按鍵View->Toolbars->Customize...最後當你書寫信息的時候僅僅點擊它就可以了。
+
+TkRat (GUI)
+~~~~~~~~~~~
+
+可以使用它。使用"Insert file..."或者外部的編輯器。
+
+Gmail (Web GUI)
+~~~~~~~~~~~~~~~
+
+不要使用它發送補丁。
+
+Gmail網頁客戶端自動地把制表符轉換爲空格。
+
+雖然制表符轉換爲空格問題可以被外部編輯器解決,同時它還會使用回車換行把每行拆分爲78個字符。
+
+另一個問題是Gmail還會把任何不是ASCII的字符的信息改爲base64編碼。它把東西變的像歐洲人的名字。
+
+                                ###
+
diff --git a/Documentation/translations/zh_TW/process/embargoed-hardware-issues.rst b/Documentation/translations/zh_TW/process/embargoed-hardware-issues.rst
new file mode 100644
index 000000000000..6c76fc96131a
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/embargoed-hardware-issues.rst
@@ -0,0 +1,232 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/embargoed-hardware-issues.rst <embargoed_hardware_issues>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+被限制的硬體問題
+================
+
+範圍
+----
+
+導致安全問題的硬體問題與只影響Linux內核的純軟體錯誤是不同的安全錯誤類別。
+
+必須區別對待諸如熔毀(Meltdown)、Spectre、L1TF等硬體問題,因爲它們通常會影響
+所有作業系統(「OS」),因此需要在不同的OS供應商、發行版、硬體供應商和其他各方
+之間進行協調。對於某些問題,軟體緩解可能依賴於微碼或固件更新,這需要進一步的
+協調。
+
+.. _tw_Contact:
+
+接觸
+----
+
+Linux內核硬體安全小組獨立於普通的Linux內核安全小組。
+
+該小組只負責協調被限制的硬體安全問題。Linux內核中純軟體安全漏洞的報告不由該
+小組處理,報告者將被引導至常規Linux內核安全小組(:ref:`Documentation/admin-guide/
+<securitybugs>`)聯繫。
+
+可以通過電子郵件 <hardware-security@kernel.org> 與小組聯繫。這是一份私密的安全
+官名單,他們將幫助您根據我們的文檔化流程協調問題。
+
+郵件列表是加密的,發送到列表的電子郵件可以通過PGP或S/MIME加密,並且必須使用報告
+者的PGP密鑰或S/MIME證書籤名。該列表的PGP密鑰和S/MIME證書可從
+https://www.kernel.org/.... 獲得。
+
+雖然硬體安全問題通常由受影響的硬體供應商處理,但我們歡迎發現潛在硬體缺陷的研究
+人員或個人與我們聯繫。
+
+硬體安全官
+^^^^^^^^^^
+
+目前的硬體安全官小組:
+
+  - Linus Torvalds(Linux基金會院士)
+  - Greg Kroah Hartman(Linux基金會院士)
+  - Thomas Gleixner(Linux基金會院士)
+
+郵件列表的操作
+^^^^^^^^^^^^^^
+
+處理流程中使用的加密郵件列表託管在Linux Foundation的IT基礎設施上。通過提供這項
+服務,Linux基金會的IT基礎設施安全總監在技術上有能力訪問被限制的信息,但根據他
+的僱傭合同,他必須保密。Linux基金會的IT基礎設施安全總監還負責 kernel.org 基礎
+設施。
+
+Linux基金會目前的IT基礎設施安全總監是 Konstantin Ryabitsev。
+
+保密協議
+--------
+
+Linux內核硬體安全小組不是正式的機構,因此無法簽訂任何保密協議。核心社區意識到
+這些問題的敏感性,並提供了一份諒解備忘錄。
+
+諒解備忘錄
+----------
+
+Linux內核社區深刻理解在不同作業系統供應商、發行商、硬體供應商和其他各方之間
+進行協調時,保持硬體安全問題處於限制狀態的要求。
+
+Linux內核社區在過去已經成功地處理了硬體安全問題,並且有必要的機制允許在限制
+限制下進行符合社區的開發。
+
+Linux內核社區有一個專門的硬體安全小組負責初始聯繫,並監督在限制規則下處理
+此類問題的過程。
+
+硬體安全小組確定開發人員(領域專家),他們將組成特定問題的初始響應小組。最初
+的響應小組可以引入更多的開發人員(領域專家)以最佳的技術方式解決這個問題。
+
+所有相關開發商承諾遵守限制規定,並對收到的信息保密。違反承諾將導致立即從當前
+問題中排除,並從所有相關郵件列表中刪除。此外,硬體安全小組還將把違反者排除在
+未來的問題之外。這一後果的影響在我們社區是一種非常有效的威懾。如果發生違規
+情況,硬體安全小組將立即通知相關方。如果您或任何人發現潛在的違規行爲,請立即
+向硬體安全人員報告。
+
+流程
+^^^^
+
+由於Linux內核開發的全球分布式特性,面對面的會議幾乎不可能解決硬體安全問題。
+由於時區和其他因素,電話會議很難協調,只能在絕對必要時使用。加密電子郵件已被
+證明是解決此類問題的最有效和最安全的通信方法。
+
+開始披露
+""""""""
+
+披露內容首先通過電子郵件聯繫Linux內核硬體安全小組。此初始聯繫人應包含問題的
+描述和任何已知受影響硬體的列表。如果您的組織製造或分發受影響的硬體,我們建議
+您也考慮哪些其他硬體可能會受到影響。
+
+硬體安全小組將提供一個特定於事件的加密郵件列表,用於與報告者進行初步討論、
+進一步披露和協調。
+
+硬體安全小組將向披露方提供一份開發人員(領域專家)名單,在與開發人員確認他們
+將遵守本諒解備忘錄和文件化流程後,應首先告知開發人員有關該問題的信息。這些開發
+人員組成初始響應小組,並在初始接觸後負責處理問題。硬體安全小組支持響應小組,
+但不一定參與緩解開發過程。
+
+雖然個別開發人員可能通過其僱主受到保密協議的保護,但他們不能以Linux內核開發
+人員的身份簽訂個別保密協議。但是,他們將同意遵守這一書面程序和諒解備忘錄。
+
+披露方應提供已經或應該被告知該問題的所有其他實體的聯繫人名單。這有幾個目的:
+
+  - 披露的實體列表允許跨行業通信,例如其他作業系統供應商、硬體供應商等。
+
+  - 可聯繫已披露的實體,指定應參與緩解措施開發的專家。
+
+  - 如果需要處理某一問題的專家受僱於某一上市實體或某一上市實體的成員,則響應
+    小組可要求該實體披露該專家。這確保專家也是實體反應小組的一部分。
+
+披露
+""""
+
+披露方通過特定的加密郵件列表向初始響應小組提供詳細信息。
+
+根據我們的經驗,這些問題的技術文檔通常是一個足夠的起點,最好通過電子郵件進行
+進一步的技術澄清。
+
+緩解開發
+""""""""
+
+初始響應小組設置加密郵件列表,或在適當的情況下重新修改現有郵件列表。
+
+使用郵件列表接近於正常的Linux開發過程,並且在過去已經成功地用於爲各種硬體安全
+問題開發緩解措施。
+
+郵件列表的操作方式與正常的Linux開發相同。發布、討論和審查修補程序,如果同意,
+則應用於非公共git存儲庫,參與開發人員只能通過安全連接訪問該存儲庫。存儲庫包含
+針對主線內核的主開發分支,並根據需要爲穩定的內核版本提供向後移植分支。
+
+最初的響應小組將根據需要從Linux內核開發人員社區中確定更多的專家。引進專家可以
+在開發過程中的任何時候發生,需要及時處理。
+
+如果專家受僱於披露方提供的披露清單上的實體或其成員,則相關實體將要求其參與。
+
+否則,披露方將被告知專家參與的情況。諒解備忘錄涵蓋了專家,要求披露方確認參與。
+如果披露方有令人信服的理由提出異議,則必須在五個工作日內提出異議,並立即與事件
+小組解決。如果披露方在五個工作日內未作出回應,則視爲默許。
+
+在確認或解決異議後,專家由事件小組披露,並進入開發過程。
+
+協調發布
+""""""""
+
+有關各方將協商限制結束的日期和時間。此時,準備好的緩解措施集成到相關的內核樹中
+並發布。
+
+雖然我們理解硬體安全問題需要協調限制時間,但限制時間應限制在所有有關各方制定、
+測試和準備緩解措施所需的最短時間內。人爲地延長限制時間以滿足會議討論日期或其他
+非技術原因,會給相關的開發人員和響應小組帶來了更多的工作和負擔,因爲補丁需要
+保持最新,以便跟蹤正在進行的上游內核開發,這可能會造成衝突的更改。
+
+CVE分配
+"""""""
+
+硬體安全小組和初始響應小組都不分配CVE,開發過程也不需要CVE。如果CVE是由披露方
+提供的,則可用於文檔中。
+
+流程專使
+--------
+
+爲了協助這一進程,我們在各組織設立了專使,他們可以回答有關報告流程和進一步處理
+的問題或提供指導。專使不參與特定問題的披露,除非響應小組或相關披露方提出要求。
+現任專使名單:
+
+  ============= ========================================================
+  ARM
+  AMD		Tom Lendacky <tom.lendacky@amd.com>
+  IBM
+  Intel		Tony Luck <tony.luck@intel.com>
+  Qualcomm	Trilok Soni <tsoni@codeaurora.org>
+
+  Microsoft	Sasha Levin <sashal@kernel.org>
+  VMware
+  Xen		Andrew Cooper <andrew.cooper3@citrix.com>
+
+  Canonical	John Johansen <john.johansen@canonical.com>
+  Debian	Ben Hutchings <ben@decadent.org.uk>
+  Oracle	Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
+  Red Hat	Josh Poimboeuf <jpoimboe@redhat.com>
+  SUSE		Jiri Kosina <jkosina@suse.cz>
+
+  Amazon
+  Google	Kees Cook <keescook@chromium.org>
+  ============= ========================================================
+
+如果要將您的組織添加到專使名單中,請與硬體安全小組聯繫。被提名的專使必須完全
+理解和支持我們的過程,並且在Linux內核社區中很容易聯繫。
+
+加密郵件列表
+------------
+
+我們使用加密郵件列表進行通信。這些列表的工作原理是,發送到列表的電子郵件使用
+列表的PGP密鑰或列表的/MIME證書進行加密。郵件列表軟體對電子郵件進行解密,並
+使用訂閱者的PGP密鑰或S/MIME證書爲每個訂閱者分別對其進行重新加密。有關郵件列表
+軟體和用於確保列表安全和數據保護的設置的詳細信息,請訪問:
+https://www.kernel.org/....
+
+關鍵點
+^^^^^^
+
+初次接觸見 :ref:`tw_Contact`. 對於特定於事件的郵件列表,密鑰和S/MIME證書通過
+特定列表發送的電子郵件傳遞給訂閱者。
+
+訂閱事件特定列表
+^^^^^^^^^^^^^^^^
+
+訂閱由響應小組處理。希望參與通信的披露方將潛在訂戶的列表發送給響應組,以便
+響應組可以驗證訂閱請求。
+
+每個訂戶都需要通過電子郵件向響應小組發送訂閱請求。電子郵件必須使用訂閱伺服器
+的PGP密鑰或S/MIME證書籤名。如果使用PGP密鑰,則必須從公鑰伺服器獲得該密鑰,
+並且理想情況下該密鑰連接到Linux內核的PGP信任網。另請參見:
+https://www.kernel.org/signature.html.
+
+響應小組驗證訂閱者,並將訂閱者添加到列表中。訂閱後,訂閱者將收到來自郵件列表
+的電子郵件,該郵件列表使用列表的PGP密鑰或列表的/MIME證書籤名。訂閱者的電子郵件
+客戶端可以從簽名中提取PGP密鑰或S/MIME證書,以便訂閱者可以向列表發送加密電子
+郵件。
+
diff --git a/Documentation/translations/zh_TW/process/howto.rst b/Documentation/translations/zh_TW/process/howto.rst
new file mode 100644
index 000000000000..2043691b92e3
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/howto.rst
@@ -0,0 +1,500 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _tw_process_howto:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/howto.rst <process_howto>`
+
+譯者::
+
+    英文版維護者: Greg Kroah-Hartman <greg@kroah.com>
+    中文版維護者: 李陽  Li Yang <leoyang.li@nxp.com>
+    中文版翻譯者: 李陽  Li Yang <leoyang.li@nxp.com>
+                   時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+    中文版校譯者:
+                   鍾宇  TripleX Chung <xxx.phy@gmail.com>
+                   陳琦  Maggie Chen <chenqi@beyondsoft.com>
+                   王聰  Wang Cong <xiyou.wangcong@gmail.com>
+                   胡皓文 Hu Haowen <src.res@email.cn>
+
+如何參與Linux內核開發
+=====================
+
+這是一篇將如何參與Linux內核開發的相關問題一網打盡的終極祕笈。它將指導你
+成爲一名Linux內核開發者,並且學會如何同Linux內核開發社區合作。它儘可能不
+包括任何關於內核編程的技術細節,但會給你指引一條獲得這些知識的正確途徑。
+
+如果這篇文章中的任何內容不再適用,請給文末列出的文件維護者發送補丁。
+
+
+入門
+----
+
+你想了解如何成爲一名Linux內核開發者?或者老闆吩咐你「給這個設備寫個Linux
+驅動程序」?這篇文章的目的就是教會你達成這些目標的全部訣竅,它將描述你需
+要經過的流程以及給出如何同內核社區合作的一些提示。它還將試圖解釋內核社區
+爲何這樣運作。
+
+Linux內核大部分是由C語言寫成的,一些體系結構相關的代碼用到了彙編語言。要
+參與內核開發,你必須精通C語言。除非你想爲某個架構開發底層代碼,否則你並
+不需要了解(任何體系結構的)彙編語言。下面列舉的書籍雖然不能替代紮實的C
+語言教育和多年的開發經驗,但如果需要的話,做爲參考還是不錯的:
+
+ - "The C Programming Language" by Kernighan and Ritchie [Prentice Hall]
+   《C程序設計語言(第2版·新版)》(徐寶文 李志 譯)[機械工業出版社]
+ - "Practical C Programming" by Steve Oualline [O'Reilly]
+   《實用C語言編程(第三版)》(郭大海 譯)[中國電力出版社]
+ - "C:  A Reference Manual" by Harbison and Steele [Prentice Hall]
+   《C語言參考手冊(原書第5版)》(邱仲潘 等譯)[機械工業出版社]
+
+Linux內核使用GNU C和GNU工具鏈開發。雖然它遵循ISO C89標準,但也用到了一些
+標準中沒有定義的擴展。內核是自給自足的C環境,不依賴於標準C庫的支持,所以
+並不支持C標準中的部分定義。比如long long類型的大數除法和浮點運算就不允許
+使用。有時候確實很難弄清楚內核對工具鏈的要求和它所使用的擴展,不幸的是目
+前還沒有明確的參考資料可以解釋它們。請查閱gcc信息頁(使用「info gcc」命令
+顯示)獲得一些這方面信息。
+
+請記住你是在學習怎麼和已經存在的開發社區打交道。它由一羣形形色色的人組成,
+他們對代碼、風格和過程有著很高的標準。這些標準是在長期實踐中總結出來的,
+適應於地理上分散的大型開發團隊。它們已經被很好得整理成檔,建議你在開發
+之前儘可能多的學習這些標準,而不要期望別人來適應你或者你公司的行爲方式。
+
+
+法律問題
+--------
+
+Linux內核原始碼都是在GPL(通用公共許可證)的保護下發布的。要了解這種許可
+的細節請查看原始碼主目錄下的COPYING文件。Linux內核許可準則和如何使用
+`SPDX <https://spdx.org/>` 標誌符說明在這個文件中
+:ref:`Documentation/translations/zh_TW/process/license-rules.rst <tw_kernel_licensing>`
+如果你對它還有更深入問題請聯繫律師,而不要在Linux內核郵件組上提問。因爲
+郵件組裡的人並不是律師,不要期望他們的話有法律效力。
+
+對於GPL的常見問題和解答,請訪問以下連結:
+	https://www.gnu.org/licenses/gpl-faq.html
+
+
+文檔
+----
+
+Linux內核代碼中包含有大量的文檔。這些文檔對於學習如何與內核社區互動有著
+不可估量的價值。當一個新的功能被加入內核,最好把解釋如何使用這個功能的文
+檔也放進內核。當內核的改動導致面向用戶空間的接口發生變化時,最好將相關信
+息或手冊頁(manpages)的補丁發到mtk.manpages@gmail.com,以向手冊頁(manpages)
+的維護者解釋這些變化。
+
+以下是內核代碼中需要閱讀的文檔:
+  :ref:`Documentation/admin-guide/README.rst <readme>`
+    文件簡要介紹了Linux內核的背景,並且描述了如何配置和編譯內核。內核的
+    新用戶應該從這裡開始。
+
+
+  :ref:`Documentation/process/changes.rst <changes>`
+    文件給出了用來編譯和使用內核所需要的最小軟體包列表。
+
+  :ref:`Documentation/translations/zh_TW/process/coding-style.rst <tw_codingstyle>`
+    描述Linux內核的代碼風格和理由。所有新代碼需要遵守這篇文檔中定義的規
+    范。大多數維護者只會接收符合規定的補丁,很多人也只會幫忙檢查符合風格
+    的代碼。
+
+  :ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+  :ref:`Documentation/process/submitting-drivers.rst <submittingdrivers>`
+
+    這兩份文檔明確描述如何創建和發送補丁,其中包括(但不僅限於):
+       - 郵件內容
+       - 郵件格式
+       - 選擇收件人
+
+    遵守這些規定並不能保證提交成功(因爲所有補丁需要通過嚴格的內容和風格
+    審查),但是忽視他們幾乎就意味著失敗。
+
+    其他關於如何正確地生成補丁的優秀文檔包括:
+    "The Perfect Patch"
+
+        https://www.ozlabs.org/~akpm/stuff/tpp.txt
+
+    "Linux kernel patch submission format"
+
+        https://web.archive.org/web/20180829112450/http://linux.yyz.us/patch-format.html
+
+  :ref:`Documentation/translations/zh_TW/process/stable-api-nonsense.rst <tw_stable_api_nonsense>`
+    論證內核爲什麼特意不包括穩定的內核內部API,也就是說不包括像這樣的特
+    性:
+
+       - 子系統中間層(爲了兼容性?)
+       - 在不同作業系統間易於移植的驅動程序
+       - 減緩(甚至阻止)內核代碼的快速變化
+
+    這篇文檔對於理解Linux的開發哲學至關重要。對於將開發平台從其他操作系
+    統轉移到Linux的人來說也很重要。
+
+  :ref:`Documentation/admin-guide/security-bugs.rst <securitybugs>`
+    如果你認爲自己發現了Linux內核的安全性問題,請根據這篇文檔中的步驟來
+    提醒其他內核開發者並幫助解決這個問題。
+
+  :ref:`Documentation/translations/zh_TW/process/management-style.rst <tw_managementstyle>`
+
+    描述內核維護者的工作方法及其共有特點。這對於剛剛接觸內核開發(或者對
+    它感到好奇)的人來說很重要,因爲它解釋了很多對於內核維護者獨特行爲的
+    普遍誤解與迷惑。
+
+  :ref:`Documentation/process/stable-kernel-rules.rst <stable_kernel_rules>`
+    解釋了穩定版內核發布的規則,以及如何將改動放入這些版本的步驟。
+
+  :ref:`Documentation/process/kernel-docs.rst <kernel_docs>`
+    有助於內核開發的外部文檔列表。如果你在內核自帶的文檔中沒有找到你想找
+    的內容,可以查看這些文檔。
+
+  :ref:`Documentation/process/applying-patches.rst <applying_patches>`
+    關於補丁是什麼以及如何將它打在不同內核開發分支上的好介紹
+
+內核還擁有大量從代碼自動生成或者從 ReStructuredText(ReST) 標記生成的文檔,
+比如這個文檔,它包含內核內部API的全面介紹以及如何妥善處理加鎖的規則。所有
+這些文檔都可以通過運行以下命令從內核代碼中生成爲PDF或HTML文檔::
+
+    make pdfdocs
+    make htmldocs
+
+ReST格式的文檔會生成在 Documentation/output. 目錄中。
+它們也可以用下列命令生成 LaTeX 和 ePub 格式文檔::
+
+    make latexdocs
+    make epubdocs
+
+如何成爲內核開發者
+------------------
+如果你對Linux內核開發一無所知,你應該訪問「Linux內核新手」計劃:
+
+	https://kernelnewbies.org
+
+它擁有一個可以問各種最基本的內核開發問題的郵件列表(在提問之前一定要記得
+查找已往的郵件,確認是否有人已經回答過相同的問題)。它還擁有一個可以獲得
+實時反饋的IRC聊天頻道,以及大量對於學習Linux內核開發相當有幫助的文檔。
+
+網站簡要介紹了原始碼組織結構、子系統劃分以及目前正在進行的項目(包括內核
+中的和單獨維護的)。它還提供了一些基本的幫助信息,比如如何編譯內核和打補
+丁。
+
+如果你想加入內核開發社區並協助完成一些任務,卻找不到從哪裡開始,可以訪問
+「Linux內核房管員」計劃:
+
+	https://kernelnewbies.org/KernelJanitors
+
+這是極佳的起點。它提供一個相對簡單的任務列表,列出內核代碼中需要被重新
+整理或者改正的地方。通過和負責這個計劃的開發者們一同工作,你會學到將補丁
+集成進內核的基本原理。如果還沒有決定下一步要做什麼的話,你還可能會得到方
+向性的指點。
+
+在真正動手修改內核代碼之前,理解要修改的代碼如何運作是必需的。要達到這個
+目的,沒什麼辦法比直接讀代碼更有效了(大多數花招都會有相應的注釋),而且
+一些特製的工具還可以提供幫助。例如,「Linux代碼交叉引用」項目就是一個值得
+特別推薦的幫助工具,它將原始碼顯示在有編目和索引的網頁上。其中一個更新及
+時的內核源碼庫,可以通過以下地址訪問:
+
+        https://elixir.bootlin.com/
+
+
+開發流程
+--------
+
+目前Linux內核開發流程包括幾個「主內核分支」和很多子系統相關的內核分支。這
+些分支包括:
+
+  - Linus 的內核源碼樹
+  - 多個主要版本的穩定版內核樹
+  - 子系統相關的內核樹
+  - linux-next 集成測試樹
+
+
+主線樹
+------
+主線樹是由Linus Torvalds 維護的。你可以在https://kernel.org 網站或者代碼
+庫中下找到它。它的開發遵循以下步驟:
+
+  - 每當一個新版本的內核被發布,爲期兩周的集成窗口將被打開。在這段時間裡
+    維護者可以向Linus提交大段的修改,通常這些修改已經被放到-mm內核中幾個
+    星期了。提交大量修改的首選方式是使用git工具(內核的代碼版本管理工具
+    ,更多的信息可以在 https://git-scm.com/ 獲取),不過使用普通補丁也是
+    可以的。
+  - 兩個星期以後-rc1版本內核發布。之後只有不包含可能影響整個內核穩定性的
+    新功能的補丁才可能被接受。請注意一個全新的驅動程序(或者文件系統)有
+    可能在-rc1後被接受是因爲這樣的修改完全獨立,不會影響其他的代碼,所以
+    沒有造成內核退步的風險。在-rc1以後也可以用git向Linus提交補丁,不過所
+    有的補丁需要同時被發送到相應的公衆郵件列表以徵詢意見。
+  - 當Linus認爲當前的git源碼樹已經達到一個合理健全的狀態足以發布供人測試
+    時,一個新的-rc版本就會被發布。計劃是每周都發布新的-rc版本。
+  - 這個過程一直持續下去直到內核被認爲達到足夠穩定的狀態,持續時間大概是
+    6個星期。
+
+關於內核發布,值得一提的是Andrew Morton在linux-kernel郵件列表中如是說:
+	「沒有人知道新內核何時會被發布,因爲發布是根據已知bug的情況來決定
+	的,而不是根據一個事先制定好的時間表。」
+
+子系統特定樹
+------------
+
+各種內核子系統的維護者——以及許多內核子系統開發人員——在原始碼庫中公開了他們
+當前的開發狀態。這樣,其他人就可以看到內核的不同區域發生了什麼。在開發速度
+很快的領域,可能會要求開發人員將提交的內容建立在這樣的子系統內核樹上,這樣
+就避免了提交與其他已經進行的工作之間的衝突。
+
+這些存儲庫中的大多數都是Git樹,但是也有其他的scm在使用,或者補丁隊列被發布
+爲Quilt系列。這些子系統存儲庫的地址列在MAINTAINERS文件中。其中許多可以在
+https://git.kernel.org/上瀏覽。
+
+在將一個建議的補丁提交到這樣的子系統樹之前,需要對它進行審查,審查主要發生
+在郵件列表上(請參見下面相應的部分)。對於幾個內核子系統,這個審查過程是通
+過工具補丁跟蹤的。Patchwork提供了一個Web界面,顯示補丁發布、對補丁的任何評
+論或修訂,維護人員可以將補丁標記爲正在審查、接受或拒絕。大多數補丁網站都列
+在 https://patchwork.kernel.org/
+
+Linux-next 集成測試樹
+---------------------
+
+在將子系統樹的更新合併到主線樹之前,需要對它們進行集成測試。爲此,存在一個
+特殊的測試存儲庫,其中幾乎每天都會提取所有子系統樹:
+
+        https://git.kernel.org/?p=linux/kernel/git/next/linux-next.git
+
+通過這種方式,Linux-next 對下一個合併階段將進入主線內核的內容給出了一個概要
+展望。非常歡冒險的測試者運行測試Linux-next。
+
+多個主要版本的穩定版內核樹
+-----------------------------------
+由3個數字組成的內核版本號說明此內核是-stable版本。它們包含內核的相對較小且
+至關重要的修補,這些修補針對安全性問題或者嚴重的內核退步。
+
+這種版本的內核適用於那些期望獲得最新的穩定版內核並且不想參與測試開發版或
+者實驗版的用戶。
+
+穩定版內核樹版本由「穩定版」小組(郵件地址<stable@vger.kernel.org>)維護,一般
+隔周發布新版本。
+
+內核源碼中的 :ref:`Documentation/process/stable-kernel-rules.rst <stable_kernel_rules>`
+文件具體描述了可被穩定版內核接受的修改類型以及發布的流程。
+
+
+報告bug
+-------
+
+bugzilla.kernel.org是Linux內核開發者們用來跟蹤內核Bug的網站。我們鼓勵用
+戶在這個工具中報告找到的所有bug。如何使用內核bugzilla的細節請訪問:
+
+	http://test.kernel.org/bugzilla/faq.html
+
+內核源碼主目錄中的:ref:`admin-guide/reporting-bugs.rst <reportingbugs>`
+文件里有一個很好的模板。它指導用戶如何報告可能的內核bug以及需要提供哪些信息
+來幫助內核開發者們找到問題的根源。
+
+
+利用bug報告
+-----------
+
+練習內核開發技能的最好辦法就是修改其他人報告的bug。你不光可以幫助內核變
+得更加穩定,還可以學會如何解決實際問題從而提高自己的技能,並且讓其他開發
+者感受到你的存在。修改bug是贏得其他開發者讚譽的最好辦法,因爲並不是很多
+人都喜歡浪費時間去修改別人報告的bug。
+
+要嘗試修改已知的bug,請訪問 http://bugzilla.kernel.org 網址。
+
+
+郵件列表
+--------
+
+正如上面的文檔所描述,大多數的骨幹內核開發者都加入了Linux Kernel郵件列
+表。如何訂閱和退訂列表的細節可以在這裡找到:
+
+	http://vger.kernel.org/vger-lists.html#linux-kernel
+
+網上很多地方都有這個郵件列表的存檔(archive)。可以使用搜尋引擎來找到這些
+存檔。比如:
+
+	http://dir.gmane.org/gmane.linux.kernel
+
+在發信之前,我們強烈建議你先在存檔中搜索你想要討論的問題。很多已經被詳細
+討論過的問題只在郵件列表的存檔中可以找到。
+
+大多數內核子系統也有自己獨立的郵件列表來協調各自的開發工作。從
+MAINTAINERS文件中可以找到不同話題對應的郵件列表。
+
+很多郵件列表架設在kernel.org伺服器上。這些列表的信息可以在這裡找到:
+
+	http://vger.kernel.org/vger-lists.html
+
+在使用這些郵件列表時,請記住保持良好的行爲習慣。下面的連結提供了與這些列
+表(或任何其它郵件列表)交流的一些簡單規則,雖然內容有點濫竽充數。
+
+	http://www.albion.com/netiquette/
+
+當有很多人回覆你的郵件時,郵件的抄送列表會變得很長。請不要將任何人從抄送
+列表中刪除,除非你有足夠的理由這麼做。也不要只回復到郵件列表。請習慣於同
+一封郵件接收兩次(一封來自發送者一封來自郵件列表),而不要試圖通過添加一
+些奇特的郵件頭來解決這個問題,人們不會喜歡的。
+
+記住保留你所回復內容的上下文和源頭。在你回覆郵件的頂部保留「某某某說到……」
+這幾行。將你的評論加在被引用的段落之間而不要放在郵件的頂部。
+
+如果你在郵件中附帶補丁,請確認它們是可以直接閱讀的純文本(如
+:ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+文檔中所述)。內核開發者們不希望遇到附件或者被壓縮了的補丁。只有這樣才能
+保證他們可以直接評論你的每行代碼。請確保你使用的郵件發送程序不會修改空格
+和制表符。一個防範性的測試方法是先將郵件發送給自己,然後自己嘗試是否可以
+順利地打上收到的補丁。如果測試不成功,請調整或者更換你的郵件發送程序直到
+它正確工作爲止。
+
+總而言之,請尊重其他的郵件列表訂閱者。
+
+
+同內核社區合作
+----------------
+
+內核社區的目標就是提供盡善盡美的內核。所以當你提交補丁期望被接受進內核的
+時候,它的技術價值以及其他方面都將被評審。那麼你可能會得到什麼呢?
+
+  - 批評
+  - 評論
+  - 要求修改
+  - 要求證明修改的必要性
+  - 沉默
+
+要記住,這些是把補丁放進內核的正常情況。你必須學會聽取對補丁的批評和評論,
+從技術層面評估它們,然後要麼重寫你的補丁要麼簡明扼要地論證修改是不必要
+的。如果你發的郵件沒有得到任何回應,請過幾天後再試一次,因爲有時信件會湮
+沒在茫茫信海中。
+
+你不應該做的事情:
+
+  - 期望自己的補丁不受任何質疑就直接被接受
+  - 翻臉
+  - 忽略別人的評論
+  - 沒有按照別人的要求做任何修改就重新提交
+
+在一個努力追尋最好技術方案的社區里,對於一個補丁有多少好處總會有不同的見
+解。你必須要抱著合作的態度,願意改變自己的觀點來適應內核的風格。或者至少
+願意去證明你的想法是有價值的。記住,犯錯誤是允許的,只要你願意朝著正確的
+方案去努力。
+
+如果你的第一個補丁換來的是一堆修改建議,這是很正常的。這並不代表你的補丁
+不會被接受,也不意味著有人和你作對。你只需要改正所有提出的問題然後重新發
+送你的補丁。
+
+內核社區和公司文化的差異
+------------------------
+
+內核社區的工作模式同大多數傳統公司開發隊伍的工作模式並不相同。下面這些例
+子,可以幫助你避免某些可能發生問題:
+用這些話介紹你的修改提案會有好處:
+
+    - 它同時解決了多個問題
+    - 它刪除了2000行代碼
+    - 這是補丁,它已經解釋了我想要說明的
+    - 我在5種不同的體系結構上測試過它……
+    - 這是一系列小補丁用來……
+    - 這個修改提高了普通機器的性能……
+
+應該避免如下的說法:
+
+    - 我們在AIX/ptx/Solaris就是這麼做的,所以這麼做肯定是好的……
+    - 我做這行已經20年了,所以……
+    - 爲了我們公司賺錢考慮必須這麼做
+    - 這是我們的企業產品線所需要的
+    - 這裡是描述我觀點的1000頁設計文檔
+    - 這是一個5000行的補丁用來……
+    - 我重寫了現在亂七八糟的代碼,這就是……
+    - 我被規定了最後期限,所以這個補丁需要立刻被接受
+
+另外一個內核社區與大部分傳統公司的軟體開發隊伍不同的地方是無法面對面地交
+流。使用電子郵件和IRC聊天工具做爲主要溝通工具的一個好處是性別和種族歧視
+將會更少。Linux內核的工作環境更能接受婦女和少數族羣,因爲每個人在別人眼
+里只是一個郵件地址。國際化也幫助了公平的實現,因爲你無法通過姓名來判斷人
+的性別。男人有可能叫李麗,女人也有可能叫王剛。大多數在Linux內核上工作過
+並表達過看法的女性對在linux上工作的經歷都給出了正面的評價。
+
+對於一些不習慣使用英語的人來說,語言可能是一個引起問題的障礙。在郵件列表
+中要正確地表達想法必需良好地掌握語言,所以建議你在發送郵件之前最好檢查一
+下英文寫得是否正確。
+
+
+拆分修改
+--------
+
+Linux內核社區並不喜歡一下接收大段的代碼。修改需要被恰當地介紹、討論並且
+拆分成獨立的小段。這幾乎完全和公司中的習慣背道而馳。你的想法應該在開發最
+開始的階段就讓大家知道,這樣你就可以及時獲得對你正在進行的開發的反饋。這
+樣也會讓社區覺得你是在和他們協作,而不是僅僅把他們當作傾銷新功能的對象。
+無論如何,你不要一次性地向郵件列表發送50封信,你的補丁序列應該永遠用不到
+這麼多。
+
+將補丁拆開的原因如下:
+
+1) 小的補丁更有可能被接受,因爲它們不需要太多的時間和精力去驗證其正確性。
+   一個5行的補丁,可能在維護者看了一眼以後就會被接受。而500行的補丁則
+   需要數個小時來審查其正確性(所需時間隨補丁大小增加大約呈指數級增長)。
+
+   當出了問題的時候,小的補丁也會讓調試變得非常容易。一個一個補丁地回溯
+   將會比仔細剖析一個被打上的大補丁(這個補丁破壞了其他東西)容易得多。
+
+2)不光發送小的補丁很重要,在提交之前重新編排、化簡(或者僅僅重新排列)
+   補丁也是很重要的。
+
+這裡有內核開發者Al Viro打的一個比方:
+	「想像一個老師正在給學生批改數學作業。老師並不希望看到學生爲了得
+	到正確解法所進行的嘗試和產生的錯誤。他希望看到的是最乾淨最優雅的
+	解答。好學生了解這點,絕不會把最終解決之前的中間方案提交上去。」
+
+	內核開發也是這樣。維護者和評審者不希望看到一個人在解決問題時的思
+	考過程。他們只希望看到簡單和優雅的解決方案。
+
+直接給出一流的解決方案,和社區一起協作討論尚未完成的工作,這兩者之間似乎
+很難找到一個平衡點。所以最好儘早開始收集有利於你進行改進的反饋;同時也要
+保證修改分成很多小塊,這樣在整個項目都準備好被包含進內核之前,其中的一部
+分可能會先被接收。
+
+必須了解這樣做是不可接受的:試圖將未完成的工作提交進內核,然後再找時間修
+復。
+
+
+證明修改的必要性
+----------------
+除了將補丁拆成小塊,很重要的一點是讓Linux社區了解他們爲什麼需要這樣修改。
+你必須證明新功能是有人需要的並且是有用的。
+
+
+記錄修改
+--------
+
+當你發送補丁的時候,需要特別留意郵件正文的內容。因爲這裡的信息將會做爲補
+丁的修改記錄(ChangeLog),會被一直保留以備大家查閱。它需要完全地描述補丁,
+包括:
+
+  - 爲什麼需要這個修改
+  - 補丁的總體設計
+  - 實現細節
+  - 測試結果
+
+想了解它具體應該看起來像什麼,請查閱以下文檔中的「ChangeLog」章節:
+  「The Perfect Patch」
+  	 https://www.ozlabs.org/~akpm/stuff/tpp.txt
+
+
+這些事情有時候做起來很難。要在任何方面都做到完美可能需要好幾年時間。這是
+一個持續提高的過程,它需要大量的耐心和決心。只要不放棄,你一定可以做到。
+很多人已經做到了,而他們都曾經和現在的你站在同樣的起點上。
+
+
+感謝
+----
+感謝Paolo Ciarrocchi允許「開發流程」部分基於他所寫的文章
+(http://www.kerneltravel.net/newbie/2.6-development_process),感謝Randy
+Dunlap和Gerrit Huizenga完善了應該說和不該說的列表。感謝Pat Mochel, Hanna
+Linder, Randy Dunlap, Kay Sievers, Vojtech Pavlik, Jan Kara, Josh Boyer,
+Kees Cook, Andrew Morton, Andi Kleen, Vadim Lobanov, Jesper Juhl, Adrian
+Bunk, Keri Harris, Frans Pop, David A. Wheeler, Junio Hamano, Michael
+Kerrisk和Alex Shepard的評審、建議和貢獻。沒有他們的幫助,這篇文檔是不可
+能完成的。
+
+
+
+英文版維護者: Greg Kroah-Hartman <greg@kroah.com>
+
diff --git a/Documentation/translations/zh_TW/process/index.rst b/Documentation/translations/zh_TW/process/index.rst
new file mode 100644
index 000000000000..ec7ad14bfd13
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/index.rst
@@ -0,0 +1,67 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. raw:: latex
+
+	\renewcommand\thesection*
+	\renewcommand\thesubsection*
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/index.rst <process_index>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+.. _tw_process_index:
+
+與Linux 內核社區一起工作
+========================
+
+你想成爲Linux內核開發人員嗎?歡迎之至!在學習許多關於內核的技術知識的同時,
+了解我們社區的工作方式也很重要。閱讀這些文檔可以讓您以更輕鬆的、麻煩更少的
+方式將更改合併到內核。
+
+以下是每位開發人員都應閱讀的基本指南:
+
+.. toctree::
+   :maxdepth: 1
+
+   howto
+   code-of-conduct
+   code-of-conduct-interpretation
+   submitting-patches
+   programming-language
+   coding-style
+   development-process
+   email-clients
+   license-rules
+   kernel-enforcement-statement
+   kernel-driver-statement
+
+其它大多數開發人員感興趣的社區指南:
+
+
+.. toctree::
+   :maxdepth: 1
+
+   submitting-drivers
+   submit-checklist
+   stable-api-nonsense
+   stable-kernel-rules
+   management-style
+   embargoed-hardware-issues
+
+這些是一些總體性技術指南,由於不大好分類而放在這裡:
+
+.. toctree::
+   :maxdepth: 1
+
+   magic-number
+   volatile-considered-harmful
+
+.. only::  subproject and html
+
+   目錄
+   ====
+
+   * :ref:`genindex`
+
diff --git a/Documentation/translations/zh_TW/process/kernel-driver-statement.rst b/Documentation/translations/zh_TW/process/kernel-driver-statement.rst
new file mode 100644
index 000000000000..8f225379b12c
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/kernel-driver-statement.rst
@@ -0,0 +1,203 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _zh_process_statement_driver:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/kernel-driver-statement.rst <process_statement_driver>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+內核驅動聲明
+------------
+
+關於Linux內核模塊的立場聲明
+===========================
+
+我們,以下署名的Linux內核開發人員,認爲任何封閉源Linux內核模塊或驅動程序都是
+有害的和不可取的。我們已經一再發現它們對Linux用戶,企業和更大的Linux生態系統
+有害。這樣的模塊否定了Linux開發模型的開放性,穩定性,靈活性和可維護性,並使
+他們的用戶無法使用Linux社區的專業知識。提供閉源內核模塊的供應商迫使其客戶
+放棄Linux的主要優勢或選擇新的供應商。因此,爲了充分利用開源所提供的成本節省和
+共享支持優勢,我們敦促供應商採取措施,以開源內核代碼在Linux上爲其客戶提供支持。
+
+我們只爲自己說話,而不是我們今天可能會爲之工作,過去或將來會爲之工作的任何公司。
+
+ - Dave Airlie
+ - Nick Andrew
+ - Jens Axboe
+ - Ralf Baechle
+ - Felipe Balbi
+ - Ohad Ben-Cohen
+ - Muli Ben-Yehuda
+ - Jiri Benc
+ - Arnd Bergmann
+ - Thomas Bogendoerfer
+ - Vitaly Bordug
+ - James Bottomley
+ - Josh Boyer
+ - Neil Brown
+ - Mark Brown
+ - David Brownell
+ - Michael Buesch
+ - Franck Bui-Huu
+ - Adrian Bunk
+ - François Cami
+ - Ralph Campbell
+ - Luiz Fernando N. Capitulino
+ - Mauro Carvalho Chehab
+ - Denis Cheng
+ - Jonathan Corbet
+ - Glauber Costa
+ - Alan Cox
+ - Magnus Damm
+ - Ahmed S. Darwish
+ - Robert P. J. Day
+ - Hans de Goede
+ - Arnaldo Carvalho de Melo
+ - Helge Deller
+ - Jean Delvare
+ - Mathieu Desnoyers
+ - Sven-Thorsten Dietrich
+ - Alexey Dobriyan
+ - Daniel Drake
+ - Alex Dubov
+ - Randy Dunlap
+ - Michael Ellerman
+ - Pekka Enberg
+ - Jan Engelhardt
+ - Mark Fasheh
+ - J. Bruce Fields
+ - Larry Finger
+ - Jeremy Fitzhardinge
+ - Mike Frysinger
+ - Kumar Gala
+ - Robin Getz
+ - Liam Girdwood
+ - Jan-Benedict Glaw
+ - Thomas Gleixner
+ - Brice Goglin
+ - Cyrill Gorcunov
+ - Andy Gospodarek
+ - Thomas Graf
+ - Krzysztof Halasa
+ - Harvey Harrison
+ - Stephen Hemminger
+ - Michael Hennerich
+ - Tejun Heo
+ - Benjamin Herrenschmidt
+ - Kristian Høgsberg
+ - Henrique de Moraes Holschuh
+ - Marcel Holtmann
+ - Mike Isely
+ - Takashi Iwai
+ - Olof Johansson
+ - Dave Jones
+ - Jesper Juhl
+ - Matthias Kaehlcke
+ - Kenji Kaneshige
+ - Jan Kara
+ - Jeremy Kerr
+ - Russell King
+ - Olaf Kirch
+ - Roel Kluin
+ - Hans-Jürgen Koch
+ - Auke Kok
+ - Peter Korsgaard
+ - Jiri Kosina
+ - Aaro Koskinen
+ - Mariusz Kozlowski
+ - Greg Kroah-Hartman
+ - Michael Krufky
+ - Aneesh Kumar
+ - Clemens Ladisch
+ - Christoph Lameter
+ - Gunnar Larisch
+ - Anders Larsen
+ - Grant Likely
+ - John W. Linville
+ - Yinghai Lu
+ - Tony Luck
+ - Pavel Machek
+ - Matt Mackall
+ - Paul Mackerras
+ - Roland McGrath
+ - Patrick McHardy
+ - Kyle McMartin
+ - Paul Menage
+ - Thierry Merle
+ - Eric Miao
+ - Akinobu Mita
+ - Ingo Molnar
+ - James Morris
+ - Andrew Morton
+ - Paul Mundt
+ - Oleg Nesterov
+ - Luca Olivetti
+ - S.Çağlar Onur
+ - Pierre Ossman
+ - Keith Owens
+ - Venkatesh Pallipadi
+ - Nick Piggin
+ - Nicolas Pitre
+ - Evgeniy Polyakov
+ - Richard Purdie
+ - Mike Rapoport
+ - Sam Ravnborg
+ - Gerrit Renker
+ - Stefan Richter
+ - David Rientjes
+ - Luis R. Rodriguez
+ - Stefan Roese
+ - Francois Romieu
+ - Rami Rosen
+ - Stephen Rothwell
+ - Maciej W. Rozycki
+ - Mark Salyzyn
+ - Yoshinori Sato
+ - Deepak Saxena
+ - Holger Schurig
+ - Amit Shah
+ - Yoshihiro Shimoda
+ - Sergei Shtylyov
+ - Kay Sievers
+ - Sebastian Siewior
+ - Rik Snel
+ - Jes Sorensen
+ - Alexey Starikovskiy
+ - Alan Stern
+ - Timur Tabi
+ - Hirokazu Takata
+ - Eliezer Tamir
+ - Eugene Teo
+ - Doug Thompson
+ - FUJITA Tomonori
+ - Dmitry Torokhov
+ - Marcelo Tosatti
+ - Steven Toth
+ - Theodore Tso
+ - Matthias Urlichs
+ - Geert Uytterhoeven
+ - Arjan van de Ven
+ - Ivo van Doorn
+ - Rik van Riel
+ - Wim Van Sebroeck
+ - Hans Verkuil
+ - Horst H. von Brand
+ - Dmitri Vorobiev
+ - Anton Vorontsov
+ - Daniel Walker
+ - Johannes Weiner
+ - Harald Welte
+ - Matthew Wilcox
+ - Dan J. Williams
+ - Darrick J. Wong
+ - David Woodhouse
+ - Chris Wright
+ - Bryan Wu
+ - Rafael J. Wysocki
+ - Herbert Xu
+ - Vlad Yasevich
+ - Peter Zijlstra
+ - Bartlomiej Zolnierkiewicz
+
diff --git a/Documentation/translations/zh_TW/process/kernel-enforcement-statement.rst b/Documentation/translations/zh_TW/process/kernel-enforcement-statement.rst
new file mode 100644
index 000000000000..99e21d22800d
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/kernel-enforcement-statement.rst
@@ -0,0 +1,155 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _tw_process_statement_kernel:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/kernel-enforcement-statement.rst <process_statement_kernel>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+Linux 內核執行聲明
+------------------
+
+作爲Linux內核的開發人員,我們對如何使用我們的軟體以及如何實施軟體許可證有著
+濃厚的興趣。遵守GPL-2.0的互惠共享義務對我們軟體和社區的長期可持續性至關重要。
+
+雖然有權強制執行對我們社區的貢獻中的單獨版權權益,但我們有共同的利益,即確保
+個人強制執行行動的方式有利於我們的社區,不會對我們軟體生態系統的健康和增長
+產生意外的負面影響。爲了阻止無益的執法行動,我們同意代表我們自己和我們版權
+利益的任何繼承人對Linux內核用戶作出以下符合我們開發社區最大利益的承諾:
+
+    儘管有GPL-2.0的終止條款,我們同意,採用以下GPL-3.0條款作爲我們許可證下的
+    附加許可,作爲任何對許可證下權利的非防禦性主張,這符合我們開發社區的最佳
+    利益。
+
+        但是,如果您停止所有違反本許可證的行爲,則您從特定版權持有人處獲得的
+        許可證將被恢復:(a)暫時恢復,除非版權持有人明確並最終終止您的許可證;
+        以及(b)永久恢復, 如果版權持有人未能在你終止違反後60天內以合理方式
+        通知您違反本許可證的行爲,則永久恢復您的許可證。
+
+        此外,如果版權所有者以某種合理的方式通知您違反了本許可,這是您第一次
+        從該版權所有者處收到違反本許可的通知(對於任何作品),並且您在收到通知
+        後的30天內糾正違規行爲。則您從特定版權所有者處獲得的許可將永久恢復.
+
+我們提供這些保證的目的是鼓勵更多地使用該軟體。我們希望公司和個人使用、修改和
+分發此軟體。我們希望以公開和透明的方式與用戶合作,以消除我們對法規遵從性或強制
+執行的任何不確定性,這些不確定性可能會限制我們軟體的採用。我們將法律行動視爲
+最後手段,只有在其他社區努力未能解決這一問題時才採取行動。
+
+最後,一旦一個不合規問題得到解決,我們希望用戶會感到歡迎,加入我們爲之努力的
+這個項目。共同努力,我們會更強大。
+
+除了下面提到的以外,我們只爲自己說話,而不是爲今天、過去或將來可能爲之工作的
+任何公司說話。
+
+  - Laura Abbott
+  - Bjorn Andersson (Linaro)
+  - Andrea Arcangeli
+  - Neil Armstrong
+  - Jens Axboe
+  - Pablo Neira Ayuso
+  - Khalid Aziz
+  - Ralf Baechle
+  - Felipe Balbi
+  - Arnd Bergmann
+  - Ard Biesheuvel
+  - Tim Bird
+  - Paolo Bonzini
+  - Christian Borntraeger
+  - Mark Brown (Linaro)
+  - Paul Burton
+  - Javier Martinez Canillas
+  - Rob Clark
+  - Kees Cook (Google)
+  - Jonathan Corbet
+  - Dennis Dalessandro
+  - Vivien Didelot (Savoir-faire Linux)
+  - Hans de Goede
+  - Mel Gorman (SUSE)
+  - Sven Eckelmann
+  - Alex Elder (Linaro)
+  - Fabio Estevam
+  - Larry Finger
+  - Bhumika Goyal
+  - Andy Gross
+  - Juergen Gross
+  - Shawn Guo
+  - Ulf Hansson
+  - Stephen Hemminger (Microsoft)
+  - Tejun Heo
+  - Rob Herring
+  - Masami Hiramatsu
+  - Michal Hocko
+  - Simon Horman
+  - Johan Hovold (Hovold Consulting AB)
+  - Christophe JAILLET
+  - Olof Johansson
+  - Lee Jones (Linaro)
+  - Heiner Kallweit
+  - Srinivas Kandagatla
+  - Jan Kara
+  - Shuah Khan (Samsung)
+  - David Kershner
+  - Jaegeuk Kim
+  - Namhyung Kim
+  - Colin Ian King
+  - Jeff Kirsher
+  - Greg Kroah-Hartman (Linux Foundation)
+  - Christian König
+  - Vinod Koul
+  - Krzysztof Kozlowski
+  - Viresh Kumar
+  - Aneesh Kumar K.V
+  - Julia Lawall
+  - Doug Ledford
+  - Chuck Lever (Oracle)
+  - Daniel Lezcano
+  - Shaohua Li
+  - Xin Long
+  - Tony Luck
+  - Catalin Marinas (Arm Ltd)
+  - Mike Marshall
+  - Chris Mason
+  - Paul E. McKenney
+  - Arnaldo Carvalho de Melo
+  - David S. Miller
+  - Ingo Molnar
+  - Kuninori Morimoto
+  - Trond Myklebust
+  - Martin K. Petersen (Oracle)
+  - Borislav Petkov
+  - Jiri Pirko
+  - Josh Poimboeuf
+  - Sebastian Reichel (Collabora)
+  - Guenter Roeck
+  - Joerg Roedel
+  - Leon Romanovsky
+  - Steven Rostedt (VMware)
+  - Frank Rowand
+  - Ivan Safonov
+  - Anna Schumaker
+  - Jes Sorensen
+  - K.Y. Srinivasan
+  - David Sterba (SUSE)
+  - Heiko Stuebner
+  - Jiri Kosina (SUSE)
+  - Willy Tarreau
+  - Dmitry Torokhov
+  - Linus Torvalds
+  - Thierry Reding
+  - Rik van Riel
+  - Luis R. Rodriguez
+  - Geert Uytterhoeven (Glider bvba)
+  - Eduardo Valentin (Amazon.com)
+  - Daniel Vetter
+  - Linus Walleij
+  - Richard Weinberger
+  - Dan Williams
+  - Rafael J. Wysocki
+  - Arvind Yadav
+  - Masahiro Yamada
+  - Wei Yongjun
+  - Lv Zheng
+  - Marc Zyngier (Arm Ltd)
+
diff --git a/Documentation/translations/zh_TW/process/license-rules.rst b/Documentation/translations/zh_TW/process/license-rules.rst
new file mode 100644
index 000000000000..ad2b80f97123
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/license-rules.rst
@@ -0,0 +1,374 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/license-rules.rst <kernel_licensing>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+.. _tw_kernel_licensing:
+
+Linux內核許可規則
+=================
+
+Linux內核根據LICENSES/preferred/GPL-2.0中提供的GNU通用公共許可證版本2
+(GPL-2.0)的條款提供,並在LICENSES/exceptions/Linux-syscall-note中顯式
+描述了例外的系統調用,如COPYING文件中所述。
+
+此文檔文件提供了如何對每個源文件進行注釋以使其許可證清晰明確的說明。
+它不會取代內核的許可證。
+
+內核原始碼作爲一個整體適用於COPYING文件中描述的許可證,但是單個源文件可以
+具有不同的與GPL-20兼容的許可證::
+
+    GPL-1.0+ : GNU通用公共許可證v1.0或更高版本
+    GPL-2.0+ : GNU通用公共許可證v2.0或更高版本
+    LGPL-2.0 : 僅限GNU庫通用公共許可證v2
+    LGPL-2.0+: GNU 庫通用公共許可證v2或更高版本
+    LGPL-2.1 : 僅限GNU寬通用公共許可證v2.1
+    LGPL-2.1+: GNU寬通用公共許可證v2.1或更高版本
+
+除此之外,個人文件可以在雙重許可下提供,例如一個兼容的GPL變體,或者BSD,
+MIT等許可。
+
+用戶空間API(UAPI)頭文件描述了用戶空間程序與內核的接口,這是一種特殊情況。
+根據內核COPYING文件中的注釋,syscall接口是一個明確的邊界,它不會將GPL要求
+擴展到任何使用它與內核通信的軟體。由於UAPI頭文件必須包含在創建在Linux內核
+上運行的可執行文件的任何源文件中,因此此例外必須記錄在特別的許可證表述中。
+
+表達源文件許可證的常用方法是將匹配的樣板文本添加到文件的頂部注釋中。由於
+格式,拼寫錯誤等,這些「樣板」很難通過那些在上下文中使用的驗證許可證合規性
+的工具。
+
+樣板文本的替代方法是在每個源文件中使用軟體包數據交換(SPDX)許可證標識符。
+SPDX許可證標識符是機器可解析的,並且是用於提供文件內容的許可證的精確縮寫。
+SPDX許可證標識符由Linux 基金會的SPDX 工作組管理,並得到了整個行業,工具
+供應商和法律團隊的合作夥伴的一致同意。有關詳細信息,請參閱
+https://spdx.org/
+
+Linux內核需要所有源文件中的精確SPDX標識符。內核中使用的有效標識符在
+`許可標識符`_ 一節中進行了解釋,並且已可以在
+https://spdx.org/licenses/ 上的官方SPDX許可證列表中檢索,並附帶許可證
+文本。
+
+許可標識符語法
+--------------
+
+1.安置:
+
+   內核文件中的SPDX許可證標識符應添加到可包含注釋的文件中的第一行。對於大多
+   數文件,這是第一行,除了那些在第一行中需要'#!PATH_TO_INTERPRETER'的腳本。
+   對於這些腳本,SPDX標識符進入第二行。
+
+|
+
+2. 風格:
+
+   SPDX許可證標識符以注釋的形式添加。注釋樣式取決於文件類型::
+
+      C source:	// SPDX-License-Identifier: <SPDX License Expression>
+      C header:	/* SPDX-License-Identifier: <SPDX License Expression> */
+      ASM:	/* SPDX-License-Identifier: <SPDX License Expression> */
+      scripts:	# SPDX-License-Identifier: <SPDX License Expression>
+      .rst:	.. SPDX-License-Identifier: <SPDX License Expression>
+      .dts{i}:	// SPDX-License-Identifier: <SPDX License Expression>
+
+   如果特定工具無法處理標準注釋樣式,則應使用工具接受的相應注釋機制。這是在
+   C 頭文件中使用「/\*\*/」樣式注釋的原因。過去在使用生成的.lds文件中觀察到
+   構建被破壞,其中'ld'無法解析C++注釋。現在已經解決了這個問題,但仍然有較
+   舊的彙編程序工具無法處理C++樣式的注釋。
+
+|
+
+3. 句法:
+
+   <SPDX許可證表達式>是SPDX許可證列表中的SPDX短格式許可證標識符,或者在許可
+   證例外適用時由「WITH」分隔的兩個SPDX短格式許可證標識符的組合。當應用多個許
+   可證時,表達式由分隔子表達式的關鍵字「AND」,「OR」組成,並由「(」,「)」包圍。
+
+   帶有「或更高」選項的[L]GPL等許可證的許可證標識符通過使用「+」來表示「或更高」
+   選項來構建。::
+
+      // SPDX-License-Identifier: GPL-2.0+
+      // SPDX-License-Identifier: LGPL-2.1+
+
+   當需要修正的許可證時,應使用WITH。 例如,linux內核UAPI文件使用表達式::
+
+      // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
+      // SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note
+
+   其它在內核中使用WITH例外的事例如下::
+
+      // SPDX-License-Identifier: GPL-2.0 WITH mif-exception
+      // SPDX-License-Identifier: GPL-2.0+ WITH GCC-exception-2.0
+
+   例外只能與特定的許可證標識符一起使用。有效的許可證標識符列在異常文本文件
+   的標記中。有關詳細信息,請參閱 `許可標識符`_ 一章中的 `例外`_ 。
+
+   如果文件是雙重許可且只選擇一個許可證,則應使用OR。例如,一些dtsi文件在雙
+   許可下可用::
+
+      // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+
+   內核中雙許可文件中許可表達式的示例::
+
+      // SPDX-License-Identifier: GPL-2.0 OR MIT
+      // SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+      // SPDX-License-Identifier: GPL-2.0 OR Apache-2.0
+      // SPDX-License-Identifier: GPL-2.0 OR MPL-1.1
+      // SPDX-License-Identifier: (GPL-2.0 WITH Linux-syscall-note) OR MIT
+      // SPDX-License-Identifier: GPL-1.0+ OR BSD-3-Clause OR OpenSSL
+
+   如果文件具有多個許可證,其條款全部適用於使用該文件,則應使用AND。例如,
+   如果代碼是從另一個項目繼承的,並且已經授予了將其放入內核的權限,但原始
+   許可條款需要保持有效::
+
+      // SPDX-License-Identifier: (GPL-2.0 WITH Linux-syscall-note) AND MIT
+
+   另一個需要遵守兩套許可條款的例子是::
+
+      // SPDX-License-Identifier: GPL-1.0+ AND LGPL-2.1+
+
+許可標識符
+----------
+
+當前使用的許可證以及添加到內核的代碼許可證可以分解爲:
+
+1. _`優先許可`:
+
+   應儘可能使用這些許可證,因爲它們已知完全兼容並廣泛使用。這些許可證在內核
+   目錄::
+
+      LICENSES/preferred/
+
+   此目錄中的文件包含完整的許可證文本和 `元標記`_ 。文件名與SPDX許可證標識
+   符相同,後者應用於源文件中的許可證。
+
+   例如::
+
+      LICENSES/preferred/GPL-2.0
+
+   包含GPLv2許可證文本和所需的元標籤::
+
+      LICENSES/preferred/MIT
+
+   包含MIT許可證文本和所需的元標記
+
+   _`元標記`:
+
+   許可證文件中必須包含以下元標記:
+
+   - Valid-License-Identifier:
+
+     一行或多行, 聲明那些許可標識符在項目內有效, 以引用此特定許可的文本。通
+     常這是一個有效的標識符,但是例如對於帶有'或更高'選項的許可證,兩個標識
+     符都有效。
+
+   - SPDX-URL:
+
+     SPDX頁面的URL,其中包含與許可證相關的其他信息.
+
+   - Usage-Guidance:
+
+     使用建議的自由格式文本。該文本必須包含SPDX許可證標識符的正確示例,因爲
+     它們應根據 `許可標識符語法`_ 指南放入源文件中。
+
+   - License-Text:
+
+     此標記之後的所有文本都被視爲原始許可文本
+
+   文件格式示例::
+
+      Valid-License-Identifier: GPL-2.0
+      Valid-License-Identifier: GPL-2.0+
+      SPDX-URL: https://spdx.org/licenses/GPL-2.0.html
+      Usage-Guide:
+        To use this license in source code, put one of the following SPDX
+	tag/value pairs into a comment according to the placement
+	guidelines in the licensing rules documentation.
+	For 'GNU General Public License (GPL) version 2 only' use:
+	  SPDX-License-Identifier: GPL-2.0
+	For 'GNU General Public License (GPL) version 2 or any later version' use:
+	  SPDX-License-Identifier: GPL-2.0+
+      License-Text:
+        Full license text
+
+   ::
+
+      SPDX-License-Identifier: MIT
+      SPDX-URL: https://spdx.org/licenses/MIT.html
+      Usage-Guide:
+	To use this license in source code, put the following SPDX
+	tag/value pair into a comment according to the placement
+	guidelines in the licensing rules documentation.
+	  SPDX-License-Identifier: MIT
+      License-Text:
+        Full license text
+
+|
+
+2. 不推薦的許可證:
+
+   這些許可證只應用於現有代碼或從其他項目導入代碼。這些許可證在內核目錄::
+
+      LICENSES/other/
+
+   此目錄中的文件包含完整的許可證文本和 `元標記`_ 。文件名與SPDX許可證標識
+   符相同,後者應用於源文件中的許可證。
+
+   例如::
+
+      LICENSES/other/ISC
+
+   包含國際系統聯合許可文本和所需的元標籤::
+
+      LICENSES/other/ZLib
+
+   包含ZLIB許可文本和所需的元標籤.
+
+   元標籤:
+
+   「其他」許可證的元標籤要求與 `優先許可`_ 的要求相同。
+
+   文件格式示例::
+
+      Valid-License-Identifier: ISC
+      SPDX-URL: https://spdx.org/licenses/ISC.html
+      Usage-Guide:
+        Usage of this license in the kernel for new code is discouraged
+	and it should solely be used for importing code from an already
+	existing project.
+        To use this license in source code, put the following SPDX
+	tag/value pair into a comment according to the placement
+	guidelines in the licensing rules documentation.
+	  SPDX-License-Identifier: ISC
+      License-Text:
+        Full license text
+
+|
+
+3. _`例外`:
+
+   某些許可證可以修改,並允許原始許可證不具有的某些例外權利。這些例外在
+   內核目錄::
+
+      LICENSES/exceptions/
+
+   此目錄中的文件包含完整的例外文本和所需的 `例外元標記`_ 。
+
+   例如::
+
+      LICENSES/exceptions/Linux-syscall-note
+
+   包含Linux內核的COPYING文件中記錄的Linux系統調用例外,該文件用於UAPI
+   頭文件。例如::
+
+      LICENSES/exceptions/GCC-exception-2.0
+
+   包含GCC'連結例外',它允許獨立於其許可證的任何二進位文件與標記有此例外的
+   文件的編譯版本連結。這是從GPL不兼容原始碼創建可運行的可執行文件所必需的。
+
+   _`例外元標記`:
+
+   以下元標記必須在例外文件中可用:
+
+   - SPDX-Exception-Identifier:
+
+     一個可與SPDX許可證標識符一起使用的例外標識符。
+
+   - SPDX-URL:
+
+     SPDX頁面的URL,其中包含與例外相關的其他信息。
+
+   - SPDX-Licenses:
+
+     以逗號分隔的例外可用的SPDX許可證標識符列表。
+
+   - Usage-Guidance:
+
+     使用建議的自由格式文本。必須在文本後面加上SPDX許可證標識符的正確示例,
+     因爲它們應根據 `許可標識符語法`_ 指南放入源文件中。
+
+   - Exception-Text:
+
+     此標記之後的所有文本都被視爲原始異常文本
+
+   文件格式示例::
+
+      SPDX-Exception-Identifier: Linux-syscall-note
+      SPDX-URL: https://spdx.org/licenses/Linux-syscall-note.html
+      SPDX-Licenses: GPL-2.0, GPL-2.0+, GPL-1.0+, LGPL-2.0, LGPL-2.0+, LGPL-2.1, LGPL-2.1+
+      Usage-Guidance:
+        This exception is used together with one of the above SPDX-Licenses
+	to mark user-space API (uapi) header files so they can be included
+	into non GPL compliant user-space application code.
+        To use this exception add it with the keyword WITH to one of the
+	identifiers in the SPDX-Licenses tag:
+	  SPDX-License-Identifier: <SPDX-License> WITH Linux-syscall-note
+      Exception-Text:
+        Full exception text
+
+   ::
+
+      SPDX-Exception-Identifier: GCC-exception-2.0
+      SPDX-URL: https://spdx.org/licenses/GCC-exception-2.0.html
+      SPDX-Licenses: GPL-2.0, GPL-2.0+
+      Usage-Guidance:
+        The "GCC Runtime Library exception 2.0" is used together with one
+	of the above SPDX-Licenses for code imported from the GCC runtime
+	library.
+        To use this exception add it with the keyword WITH to one of the
+	identifiers in the SPDX-Licenses tag:
+	  SPDX-License-Identifier: <SPDX-License> WITH GCC-exception-2.0
+      Exception-Text:
+        Full exception text
+
+
+所有SPDX許可證標識符和例外都必須在LICENSES子目錄中具有相應的文件。這是允許
+工具驗證(例如checkpatch.pl)以及準備好從源讀取和提取許可證所必需的, 這是
+各種FOSS組織推薦的,例如 `FSFE REUSE initiative <https://reuse.software/>`_.
+
+_`模塊許可`
+-----------------
+
+   可加載內核模塊還需要MODULE_LICENSE()標記。此標記既不替代正確的原始碼
+   許可證信息(SPDX-License-Identifier),也不以任何方式表示或確定提供模塊
+   原始碼的確切許可證。
+
+   此標記的唯一目的是提供足夠的信息,該模塊是否是自由軟體或者是內核模塊加
+   載器和用戶空間工具的專有模塊。
+
+   MODULE_LICENSE()的有效許可證字符串是:
+
+    ============================= =============================================
+    "GPL"			  模塊是根據GPL版本2許可的。這並不表示僅限於
+                                  GPL-2.0或GPL-2.0或更高版本之間的任何區別。
+                                  最正確許可證信息只能通過相應源文件中的許可證
+                                  信息來確定
+
+    "GPL v2"			  和"GPL"相同,它的存在是因爲歷史原因。
+
+    "GPL and additional rights"   表示模塊源在GPL v2變體和MIT許可下雙重許可的
+                                  歷史變體。請不要在新代碼中使用。
+
+    "Dual MIT/GPL"		  表達該模塊在GPL v2變體或MIT許可證選擇下雙重
+                                  許可的正確方式。
+
+    "Dual BSD/GPL"		  該模塊根據GPL v2變體或BSD許可證選擇進行雙重
+                                  許可。 BSD許可證的確切變體只能通過相應源文件
+                                  中的許可證信息來確定。
+
+    "Dual MPL/GPL"		  該模塊根據GPL v2變體或Mozilla Public License
+                                  (MPL)選項進行雙重許可。 MPL許可證的確切變體
+                                  只能通過相應的源文件中的許可證信息來確定。
+
+    "Proprietary"		  該模塊屬於專有許可。此字符串僅用於專有的第三
+                                  方模塊,不能用於在內核樹中具有原始碼的模塊。
+                                  以這種方式標記的模塊在加載時會使用'P'標記汙
+                                  染內核,並且內核模塊加載器拒絕將這些模塊連結
+                                  到使用EXPORT_SYMBOL_GPL()導出的符號。
+    ============================= =============================================
+
+
diff --git a/Documentation/translations/zh_TW/process/magic-number.rst b/Documentation/translations/zh_TW/process/magic-number.rst
new file mode 100644
index 000000000000..ae321a9aaece
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/magic-number.rst
@@ -0,0 +1,148 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _tw_magicnumbers:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/magic-number.rst <magicnumbers>`
+
+如果想評論或更新本文的內容,請直接發信到LKML。如果你使用英文交流有困難的話,也可
+以向中文版維護者求助。如果本翻譯更新不及時或者翻譯存在問題,請聯繫中文版維護者::
+
+        中文版維護者: 賈威威 Jia Wei Wei <harryxiyou@gmail.com>
+        中文版翻譯者: 賈威威 Jia Wei Wei <harryxiyou@gmail.com>
+        中文版校譯者: 賈威威 Jia Wei Wei <harryxiyou@gmail.com>
+                      胡皓文 Hu Haowen <src.res@email.cn>
+
+Linux 魔術數
+============
+
+這個文件是有關當前使用的魔術值註冊表。當你給一個結構添加了一個魔術值,你也應該把這個魔術值添加到這個文件,因爲我們最好把用於各種結構的魔術值統一起來。
+
+使用魔術值來保護內核數據結構是一個非常好的主意。這就允許你在運行期檢查(a)一個結構是否已經被攻擊,或者(b)你已經給一個例行程序通過了一個錯誤的結構。後一種情況特別地有用---特別是當你通過一個空指針指向結構體的時候。tty源碼,例如,經常通過特定驅動使用這種方法並且反覆地排列特定方面的結構。
+
+使用魔術值的方法是在結構的開始處聲明的,如下::
+
+        struct tty_ldisc {
+	        int	magic;
+        	...
+        };
+
+當你以後給內核添加增強功能的時候,請遵守這條規則!這樣就會節省數不清的調試時間,特別是一些古怪的情況,例如,數組超出範圍並且重新寫了超出部分。遵守這個規則,‪這些情況可以被快速地,安全地避免。
+
+		Theodore Ts'o
+		  31 Mar 94
+
+給當前的Linux 2.1.55添加魔術表。
+
+		Michael Chastain
+		<mailto:mec@shout.net>
+		22 Sep 1997
+
+現在應該最新的Linux 2.1.112.因爲在特性凍結期間,不能在2.2.x前改變任何東西。這些條目被數域所排序。
+
+		Krzysztof G.Baranowski
+	        <mailto: kgb@knm.org.pl>
+		29 Jul 1998
+
+更新魔術表到Linux 2.5.45。剛好越過特性凍結,但是有可能還會有一些新的魔術值在2.6.x之前融入到內核中。
+
+		Petr Baudis
+		<pasky@ucw.cz>
+		03 Nov 2002
+
+更新魔術表到Linux 2.5.74。
+
+		Fabian Frederick
+                <ffrederick@users.sourceforge.net>
+		09 Jul 2003
+
+===================== ================ ======================== ==========================================
+魔術數名              數字             結構                     文件
+===================== ================ ======================== ==========================================
+PG_MAGIC              'P'              pg_{read,write}_hdr      ``include/linux/pg.h``
+CMAGIC                0x0111           user                     ``include/linux/a.out.h``
+MKISS_DRIVER_MAGIC    0x04bf           mkiss_channel            ``drivers/net/mkiss.h``
+HDLC_MAGIC            0x239e           n_hdlc                   ``drivers/char/n_hdlc.c``
+APM_BIOS_MAGIC        0x4101           apm_user                 ``arch/x86/kernel/apm_32.c``
+DB_MAGIC              0x4442           fc_info                  ``drivers/net/iph5526_novram.c``
+DL_MAGIC              0x444d           fc_info                  ``drivers/net/iph5526_novram.c``
+FASYNC_MAGIC          0x4601           fasync_struct            ``include/linux/fs.h``
+FF_MAGIC              0x4646           fc_info                  ``drivers/net/iph5526_novram.c``
+PTY_MAGIC             0x5001                                    ``drivers/char/pty.c``
+PPP_MAGIC             0x5002           ppp                      ``include/linux/if_pppvar.h``
+SSTATE_MAGIC          0x5302           serial_state             ``include/linux/serial.h``
+SLIP_MAGIC            0x5302           slip                     ``drivers/net/slip.h``
+STRIP_MAGIC           0x5303           strip                    ``drivers/net/strip.c``
+SIXPACK_MAGIC         0x5304           sixpack                  ``drivers/net/hamradio/6pack.h``
+AX25_MAGIC            0x5316           ax_disp                  ``drivers/net/mkiss.h``
+TTY_MAGIC             0x5401           tty_struct               ``include/linux/tty.h``
+MGSL_MAGIC            0x5401           mgsl_info                ``drivers/char/synclink.c``
+TTY_DRIVER_MAGIC      0x5402           tty_driver               ``include/linux/tty_driver.h``
+MGSLPC_MAGIC          0x5402           mgslpc_info              ``drivers/char/pcmcia/synclink_cs.c``
+USB_SERIAL_MAGIC      0x6702           usb_serial               ``drivers/usb/serial/usb-serial.h``
+FULL_DUPLEX_MAGIC     0x6969                                    ``drivers/net/ethernet/dec/tulip/de2104x.c``
+USB_BLUETOOTH_MAGIC   0x6d02           usb_bluetooth            ``drivers/usb/class/bluetty.c``
+RFCOMM_TTY_MAGIC      0x6d02                                    ``net/bluetooth/rfcomm/tty.c``
+USB_SERIAL_PORT_MAGIC 0x7301           usb_serial_port          ``drivers/usb/serial/usb-serial.h``
+CG_MAGIC              0x00090255       ufs_cylinder_group       ``include/linux/ufs_fs.h``
+LSEMAGIC              0x05091998       lse                      ``drivers/fc4/fc.c``
+GDTIOCTL_MAGIC        0x06030f07       gdth_iowr_str            ``drivers/scsi/gdth_ioctl.h``
+RIEBL_MAGIC           0x09051990                                ``drivers/net/atarilance.c``
+NBD_REQUEST_MAGIC     0x12560953       nbd_request              ``include/linux/nbd.h``
+RED_MAGIC2            0x170fc2a5       (any)                    ``mm/slab.c``
+BAYCOM_MAGIC          0x19730510       baycom_state             ``drivers/net/baycom_epp.c``
+ISDN_X25IFACE_MAGIC   0x1e75a2b9       isdn_x25iface_proto_data ``drivers/isdn/isdn_x25iface.h``
+ECP_MAGIC             0x21504345       cdkecpsig                ``include/linux/cdk.h``
+LSOMAGIC              0x27091997       lso                      ``drivers/fc4/fc.c``
+LSMAGIC               0x2a3b4d2a       ls                       ``drivers/fc4/fc.c``
+WANPIPE_MAGIC         0x414C4453       sdla_{dump,exec}         ``include/linux/wanpipe.h``
+CS_CARD_MAGIC         0x43525553       cs_card                  ``sound/oss/cs46xx.c``
+LABELCL_MAGIC         0x4857434c       labelcl_info_s           ``include/asm/ia64/sn/labelcl.h``
+ISDN_ASYNC_MAGIC      0x49344C01       modem_info               ``include/linux/isdn.h``
+CTC_ASYNC_MAGIC       0x49344C01       ctc_tty_info             ``drivers/s390/net/ctctty.c``
+ISDN_NET_MAGIC        0x49344C02       isdn_net_local_s         ``drivers/isdn/i4l/isdn_net_lib.h``
+SAVEKMSG_MAGIC2       0x4B4D5347       savekmsg                 ``arch/*/amiga/config.c``
+CS_STATE_MAGIC        0x4c4f4749       cs_state                 ``sound/oss/cs46xx.c``
+SLAB_C_MAGIC          0x4f17a36d       kmem_cache               ``mm/slab.c``
+COW_MAGIC             0x4f4f4f4d       cow_header_v1            ``arch/um/drivers/ubd_user.c``
+I810_CARD_MAGIC       0x5072696E       i810_card                ``sound/oss/i810_audio.c``
+TRIDENT_CARD_MAGIC    0x5072696E       trident_card             ``sound/oss/trident.c``
+ROUTER_MAGIC          0x524d4157       wan_device               [in ``wanrouter.h`` pre 3.9]
+SAVEKMSG_MAGIC1       0x53415645       savekmsg                 ``arch/*/amiga/config.c``
+GDA_MAGIC             0x58464552       gda                      ``arch/mips/include/asm/sn/gda.h``
+RED_MAGIC1            0x5a2cf071       (any)                    ``mm/slab.c``
+EEPROM_MAGIC_VALUE    0x5ab478d2       lanai_dev                ``drivers/atm/lanai.c``
+HDLCDRV_MAGIC         0x5ac6e778       hdlcdrv_state            ``include/linux/hdlcdrv.h``
+PCXX_MAGIC            0x5c6df104       channel                  ``drivers/char/pcxx.h``
+KV_MAGIC              0x5f4b565f       kernel_vars_s            ``arch/mips/include/asm/sn/klkernvars.h``
+I810_STATE_MAGIC      0x63657373       i810_state               ``sound/oss/i810_audio.c``
+TRIDENT_STATE_MAGIC   0x63657373       trient_state             ``sound/oss/trident.c``
+M3_CARD_MAGIC         0x646e6f50       m3_card                  ``sound/oss/maestro3.c``
+FW_HEADER_MAGIC       0x65726F66       fw_header                ``drivers/atm/fore200e.h``
+SLOT_MAGIC            0x67267321       slot                     ``drivers/hotplug/cpqphp.h``
+SLOT_MAGIC            0x67267322       slot                     ``drivers/hotplug/acpiphp.h``
+LO_MAGIC              0x68797548       nbd_device               ``include/linux/nbd.h``
+M3_STATE_MAGIC        0x734d724d       m3_state                 ``sound/oss/maestro3.c``
+VMALLOC_MAGIC         0x87654320       snd_alloc_track          ``sound/core/memory.c``
+KMALLOC_MAGIC         0x87654321       snd_alloc_track          ``sound/core/memory.c``
+PWC_MAGIC             0x89DC10AB       pwc_device               ``drivers/usb/media/pwc.h``
+NBD_REPLY_MAGIC       0x96744668       nbd_reply                ``include/linux/nbd.h``
+ENI155_MAGIC          0xa54b872d       midway_eprom	        ``drivers/atm/eni.h``
+CODA_MAGIC            0xC0DAC0DA       coda_file_info           ``fs/coda/coda_fs_i.h``
+DPMEM_MAGIC           0xc0ffee11       gdt_pci_sram             ``drivers/scsi/gdth.h``
+YAM_MAGIC             0xF10A7654       yam_port                 ``drivers/net/hamradio/yam.c``
+CCB_MAGIC             0xf2691ad2       ccb                      ``drivers/scsi/ncr53c8xx.c``
+QUEUE_MAGIC_FREE      0xf7e1c9a3       queue_entry              ``drivers/scsi/arm/queue.c``
+QUEUE_MAGIC_USED      0xf7e1cc33       queue_entry              ``drivers/scsi/arm/queue.c``
+HTB_CMAGIC            0xFEFAFEF1       htb_class                ``net/sched/sch_htb.c``
+NMI_MAGIC             0x48414d4d455201 nmi_s                    ``arch/mips/include/asm/sn/nmi.h``
+===================== ================ ======================== ==========================================
+
+
+請注意,在聲音記憶管理中仍然有一些特殊的爲每個驅動定義的魔術值。查看include/sound/sndmagic.h來獲取他們完整的列表信息。很多OSS聲音驅動擁有自己從音效卡PCI ID構建的魔術值-他們也沒有被列在這裡。
+
+IrDA子系統也使用了大量的自己的魔術值,查看include/net/irda/irda.h來獲取他們完整的信息。
+
+HFS是另外一個比較大的使用魔術值的文件系統-你可以在fs/hfs/hfs.h中找到他們。
+
diff --git a/Documentation/translations/zh_TW/process/management-style.rst b/Documentation/translations/zh_TW/process/management-style.rst
new file mode 100644
index 000000000000..dce248470063
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/management-style.rst
@@ -0,0 +1,211 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/management-style.rst <managementstyle>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+.. _tw_managementstyle:
+
+Linux內核管理風格
+=================
+
+這是一個簡短的文檔,描述了Linux內核首選的(或胡編的,取決於您問誰)管理風格。
+它的目的是在某種程度上參照 :ref:`process/coding-style.rst <codingstyle>`
+主要是爲了避免反覆回答 [#cnf1]_ 相同(或類似)的問題。
+
+管理風格是非常個人化的,比簡單的編碼風格規則更難以量化,因此本文檔可能與實
+際情況有關,也可能與實際情況無關。起初它是一個玩笑,但這並不意味著它可能不
+是真的。你得自己決定。
+
+順便說一句,在談到「核心管理者」時,主要是技術負責人,而不是在公司內部進行傳
+統管理的人。如果你簽署了採購訂單或者對你的團隊的預算有任何了解,你幾乎肯定
+不是一個核心管理者。這些建議可能適用於您,也可能不適用於您。
+
+首先,我建議你購買「高效人的七個習慣」,而不是閱讀它。燒了它,這是一個偉大的
+象徵性姿態。
+
+.. [#cnf1] 本文件並不是通過回答問題,而是通過讓提問者痛苦地明白,我們不知道
+   答案是什麼。
+
+不管怎樣,這裡是:
+
+.. _tw_decisions:
+
+1)決策
+-------
+
+每個人都認爲管理者做決定,而且決策很重要。決定越大越痛苦,管理者就必須越高級。
+這很明顯,但事實並非如此。
+
+遊戲的名字是 **避免** 做出決定。尤其是,如果有人告訴你「選擇(a)或(b),
+我們真的需要你來做決定」,你就是陷入麻煩的管理者。你管理的人比你更了解細節,
+所以如果他們來找你做技術決策,你完蛋了。你顯然沒有能力爲他們做這個決定。
+
+(推論:如果你管理的人不比你更了解細節,你也會被搞砸,儘管原因完全不同。
+也就是說,你的工作是錯的,他們應該管理你的才智)
+
+所以遊戲的名字是 **避免** 做出決定,至少是那些大而痛苦的決定。做一些小的
+和非結果性的決定是很好的,並且使您看起來好像知道自己在做什麼,所以內核管理者
+需要做的是將那些大的和痛苦的決定變成那些沒有人真正關心的小事情。
+
+這有助於認識到一個大的決定和一個小的決定之間的關鍵區別是你是否可以在事後修正
+你的決定。任何決定都可以通過始終確保如果你錯了(而且你一定會錯),你以後總是
+可以通過回溯來彌補損失。突然間,你就要做兩個無關緊要的決定,一個是錯誤的,另
+一個是正確的。
+
+人們甚至會認爲這是真正的領導能力(咳,胡說,咳)。
+
+因此,避免重大決策的關鍵在於避免做那些無法挽回的事情。不要被引導到一個你無法
+逃離的角落。走投無路的老鼠可能很危險——走投無路的管理者真可憐。
+
+事實證明,由於沒有人會愚蠢到讓內核管理者承擔巨大的財政責任,所以通常很容易
+回溯。既然你不可能浪費掉你無法償還的巨額資金,你唯一可以回溯的就是技術決策,
+而回溯很容易:只要告訴大家你是個不稱職的傻瓜,說對不起,然後撤銷你去年讓別
+人所做的毫無價值的工作。突然間,你一年前做的決定不在是一個重大的決定,因爲
+它很容易被推翻。
+
+事實證明,有些人對接受這種方法有困難,原因有兩個:
+
+ - 承認你是個白癡比看起來更難。我們都喜歡保持形象,在公共場合說你錯了有時
+   確實很難。
+ - 如果有人告訴你,你去年所做的工作終究是不值得的,那麼對那些可憐的低級工
+   程師來說也是很困難的,雖然實際的 **工作** 很容易刪除,但你可能已經不可
+   挽回地失去了工程師的信任。記住:「不可撤銷」是我們一開始就試圖避免的,
+   而你的決定終究是一個重大的決定。
+
+令人欣慰的是,這兩個原因都可以通過預先承認你沒有任何線索,提前告訴人們你的
+決定完全是初步的,而且可能是錯誤的事情來有效地緩解。你應該始終保留改變主意
+的權利,並讓人們 **意識** 到這一點。當你 **還沒有** 做過真正愚蠢的事情的時
+候,承認自己是愚蠢的要容易得多。
+
+然後,當它真的被證明是愚蠢的時候,人們就轉動他們的眼珠說「哎呀,下次不要了」。
+
+這種對不稱職的先發制人的承認,也可能使真正做這項工作的人也會三思是否值得做。
+畢竟,如果他們不確定這是否是一個好主意,你肯定不應該通過向他們保證他們所做
+的工作將會進入(內核)鼓勵他們。在他們開始一項巨大的努力之前,至少讓他們三
+思而後行。
+
+記住:他們最好比你更了解細節,而且他們通常認爲他們對每件事都有答案。作爲一
+個管理者,你能做的最好的事情不是灌輸自信,而是對他們所做的事情進行健康的批
+判性思考。
+
+順便說一句,另一種避免做出決定的方法是看起來很可憐的抱怨 「我們不能兩者兼
+得嗎?」 相信我,它是有效的。如果不清楚哪種方法更好,他們最終會弄清楚的。
+最終的答案可能是兩個團隊都會因爲這種情況而感到沮喪,以至於他們放棄了。
+
+這聽起來像是一個失敗,但這通常是一個跡象,表明兩個項目都有問題,而參與其中
+的人不能做決定的原因是他們都是錯誤的。你最終會聞到玫瑰的味道,你避免了另一
+個你本可以搞砸的決定。
+
+2)人
+-----
+
+大多數人都是白癡,做一名管理者意味著你必須處理好這件事,也許更重要的是,
+**他們** 必須處理好你。
+
+事實證明,雖然很容易糾正技術錯誤,但不容易糾正人格障礙。你只能和他們的和
+你的(人格障礙)共處。
+
+但是,爲了做好作爲內核管理者的準備,最好記住不要燒掉任何橋樑,不要轟炸任何
+無辜的村民,也不要疏遠太多的內核開發人員。事實證明,疏遠人是相當容易的,而
+親近一個疏遠的人是很難的。因此,「疏遠」立即屬於「不可逆」的範疇,並根據
+:ref:`tw_decisions` 成爲絕不可以做的事情。
+
+這裡只有幾個簡單的規則:
+
+ (1) 不要叫人笨蛋(至少不要在公共場合)
+ (2) 學習如何在忘記規則(1)時道歉
+
+問題在於 #1 很容易去做,因爲你可以用數百萬種不同的方式說「你是一個笨蛋」 [#cnf2]_
+有時甚至沒有意識到,而且幾乎總是帶著一種白熱化的信念,認爲你是對的。
+
+你越確信自己是對的(讓我們面對現實吧,你可以把幾乎所有人都稱爲壞人,而且你
+經常是對的),事後道歉就越難。
+
+要解決此問題,您實際上只有兩個選項:
+
+ - 非常擅長道歉
+ - 把「愛」均勻地散開,沒有人會真正感覺到自己被不公平地瞄準了。讓它有足夠的
+   創造性,他們甚至可能會覺得好笑。
+
+選擇永遠保持禮貌是不存在的。沒有人會相信一個如此明顯地隱藏了他們真實性格的人。
+
+.. [#cnf2] 保羅·西蒙演唱了「離開愛人的50種方法」,因爲坦率地說,「告訴開發者
+   他們是D*CKHEAD" 的100萬種方法都無法確認。但我確信他已經這麼想了。
+
+3)人2 - 好人
+-------------
+
+雖然大多數人都是白癡,但不幸的是,據此推論你也是白癡,儘管我們都自我感覺良
+好,我們比普通人更好(讓我們面對現實吧,沒有人相信他們是普通人或低於普通人),
+我們也應該承認我們不是最鋒利的刀,而且會有其他人比你更不像白癡。
+
+有些人對聰明人反應不好。其他人利用它們。
+
+作爲內核維護人員,確保您在第二組中。接受他們,因爲他們會讓你的工作更容易。
+特別是,他們能夠爲你做決定,這就是遊戲的全部內容。
+
+所以當你發現一個比你聰明的人時,就順其自然吧。你的管理職責在很大程度上變成
+了「聽起來像是個好主意——去嘗試吧」,或者「聽起來不錯,但是XXX呢?」「。第二個版
+本尤其是一個很好的方法,要麼學習一些關於「XXX」的新東西,要麼通過指出一些聰明
+人沒有想到的東西來顯得更具管理性。無論哪種情況,你都會贏。
+
+要注意的一件事是認識到一個領域的偉大不一定會轉化爲其他領域。所以你可能會向
+特定的方向刺激人們,但讓我們面對現實吧,他們可能擅長他們所做的事情,而且對
+其他事情都很差勁。好消息是,人們往往會自然而然地重拾他們擅長的東西,所以當
+你向某個方向刺激他們時,你並不是在做不可逆轉的事情,只是不要用力推。
+
+4)責備
+-------
+
+事情會出問題的,人們希望去責備人。貼標籤,你就是受責備的人。
+
+事實上,接受責備並不難,尤其是當人們意識到這不 **全是** 你的過錯時。這讓我
+們找到了承擔責任的最佳方式:爲別人承擔這件事。你會感覺很好,他們會感覺很好,
+沒有受到指責. 那誰,失去了他們的全部36GB色情收藏的人,因爲你的無能將勉強承
+認,你至少沒有試圖逃避責任。
+
+然後讓真正搞砸了的開發人員(如果你能找到他們)私下知道他們搞砸了。不僅是爲
+了將來可以避免,而且爲了讓他們知道他們欠你一個人情。而且,也許更重要的是,
+他們也可能是能夠解決問題的人。因爲,讓我們面對現實吧,肯定不是你。
+
+承擔責任也是你首先成爲管理者的原因。這是讓人們信任你,讓你獲得潛在的榮耀的
+一部分,因爲你就是那個會說「我搞砸了」的人。如果你已經遵循了以前的規則,你現
+在已經很擅長說了。
+
+5)應避免的事情
+---------------
+
+有一件事人們甚至比被稱爲「笨蛋」更討厭,那就是在一個神聖的聲音中被稱爲「笨蛋」。
+第一個你可以道歉,第二個你不會真正得到機會。即使你做得很好,他們也可能不再
+傾聽。
+
+我們都認爲自己比別人強,這意味著當別人裝腔作勢時,這會讓我們很惱火。你也許
+在道德和智力上比你周圍的每個人都優越,但不要試圖太明顯,除非你真的打算激怒
+某人 [#cnf3]_
+
+同樣,不要對事情太客氣或太微妙。禮貌很容易落得落花流水,把問題隱藏起來,
+正如他們所說,「在網際網路上,沒人能聽到你的含蓄。」用一個鈍器把這一點錘進去,
+因爲你不能真的依靠別人來獲得你的觀點。
+
+一些幽默可以幫助緩和直率和道德化。過度到荒謬的地步,可以灌輸一個觀點,而不
+會讓接受者感到痛苦,他們只是認爲你是愚蠢的。因此,它可以幫助我們擺脫對批評
+的個人心理障礙。
+
+.. [#cnf3] 提示:與你的工作沒有直接關係的網絡新聞組是消除你對他人不滿的好
+   方法。偶爾寫些侮辱性的帖子,打個噴嚏,讓你的情緒得到淨化。別把牢騷帶回家
+
+6)爲什麼是我?
+---------------
+
+既然你的主要責任似乎是爲別人的錯誤承擔責任,並且讓別人痛苦地明白你是不稱職
+的,那麼顯而易見的問題之一就變成了爲什麼首先要這樣做。
+
+首先,雖然你可能會或可能不會聽到十幾歲女孩(或男孩,讓我們不要在這裡評判或
+性別歧視)敲你的更衣室門,你會得到一個巨大的個人成就感爲「負責」。別介意你真
+的在領導別人,你要跟上別人,儘可能快地追趕他們。每個人都會認爲你是負責人。
+
+如果你可以做到這個, 這是個偉大的工作!
+
diff --git a/Documentation/translations/zh_TW/process/programming-language.rst b/Documentation/translations/zh_TW/process/programming-language.rst
new file mode 100644
index 000000000000..54e3699eadf8
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/programming-language.rst
@@ -0,0 +1,76 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/programming-language.rst <programming_language>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+.. _tw_programming_language:
+
+程序設計語言
+============
+
+內核是用C語言 :ref:`c-language <tw_c-language>` 編寫的。更準確地說,內核通常是用 :ref:`gcc <tw_gcc>`
+在 ``-std=gnu89`` :ref:`gcc-c-dialect-options <tw_gcc-c-dialect-options>` 下編譯的:ISO C90的 GNU 方言(
+包括一些C99特性)
+
+這種方言包含對語言 :ref:`gnu-extensions <tw_gnu-extensions>` 的許多擴展,當然,它們許多都在內核中使用。
+
+對於一些體系結構,有一些使用 :ref:`clang <tw_clang>` 和 :ref:`icc <tw_icc>` 編譯內核
+的支持,儘管在編寫此文檔時還沒有完成,仍需要第三方補丁。
+
+屬性
+----
+
+在整個內核中使用的一個常見擴展是屬性(attributes) :ref:`gcc-attribute-syntax <tw_gcc-attribute-syntax>`
+屬性允許將實現定義的語義引入語言實體(如變量、函數或類型),而無需對語言進行
+重大的語法更改(例如添加新關鍵字) :ref:`n2049 <tw_n2049>`
+
+在某些情況下,屬性是可選的(即不支持這些屬性的編譯器仍然應該生成正確的代碼,
+即使其速度較慢或執行的編譯時檢查/診斷次數不夠)
+
+內核定義了僞關鍵字(例如, ``pure`` ),而不是直接使用GNU屬性語法(例如,
+``__attribute__((__pure__))`` ),以檢測可以使用哪些關鍵字和/或縮短代碼, 具體
+請參閱 ``include/linux/compiler_attributes.h``
+
+.. _tw_c-language:
+
+c-language
+   http://www.open-std.org/jtc1/sc22/wg14/www/standards
+
+.. _tw_gcc:
+
+gcc
+   https://gcc.gnu.org
+
+.. _tw_clang:
+
+clang
+   https://clang.llvm.org
+
+.. _tw_icc:
+
+icc
+   https://software.intel.com/en-us/c-compilers
+
+.. _tw_gcc-c-dialect-options:
+
+c-dialect-options
+   https://gcc.gnu.org/onlinedocs/gcc/C-Dialect-Options.html
+
+.. _tw_gnu-extensions:
+
+gnu-extensions
+   https://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html
+
+.. _tw_gcc-attribute-syntax:
+
+gcc-attribute-syntax
+   https://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html
+
+.. _tw_n2049:
+
+n2049
+   http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2049.pdf
+
diff --git a/Documentation/translations/zh_TW/process/stable-api-nonsense.rst b/Documentation/translations/zh_TW/process/stable-api-nonsense.rst
new file mode 100644
index 000000000000..22caa5b8d422
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/stable-api-nonsense.rst
@@ -0,0 +1,159 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _tw_stable_api_nonsense:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/stable-api-nonsense.rst
+           <stable_api_nonsense>`
+
+譯者::
+
+        中文版維護者: 鍾宇  TripleX Chung <xxx.phy@gmail.com>
+        中文版翻譯者: 鍾宇  TripleX Chung <xxx.phy@gmail.com>
+        中文版校譯者: 李陽  Li Yang <leoyang.li@nxp.com>
+                      胡皓文 Hu Haowen <src.res@email.cn>
+
+Linux 內核驅動接口
+==================
+
+寫作本文檔的目的,是爲了解釋爲什麼Linux既沒有二進位內核接口,也沒有穩定
+的內核接口。這裡所說的內核接口,是指內核里的接口,而不是內核和用戶空間
+的接口。內核到用戶空間的接口,是提供給應用程式使用的系統調用,系統調用
+在歷史上幾乎沒有過變化,將來也不會有變化。我有一些老應用程式是在0.9版本
+或者更早版本的內核上編譯的,在使用2.6版本內核的Linux發布上依然用得很好
+。用戶和應用程式作者可以將這個接口看成是穩定的。
+
+
+執行綱要
+--------
+
+你也許以爲自己想要穩定的內核接口,但是你不清楚你要的實際上不是它。你需
+要的其實是穩定的驅動程序,而你只有將驅動程序放到公版內核的原始碼樹里,
+才有可能達到這個目的。而且這樣做還有很多其它好處,正是因爲這些好處使得
+Linux能成爲強壯,穩定,成熟的作業系統,這也是你最開始選擇Linux的原因。
+
+
+入門
+-----
+
+只有那些寫驅動程序的「怪人」才會擔心內核接口的改變,對廣大用戶來說,既
+看不到內核接口,也不需要去關心它。
+
+首先,我不打算討論關於任何非GPL許可的內核驅動的法律問題,這些非GPL許可
+的驅動程序包括不公開原始碼,隱藏原始碼,二進位或者是用原始碼包裝,或者
+是其它任何形式的不能以GPL許可公開原始碼的驅動程序。如果有法律問題,請咨
+詢律師,我只是一個程式設計師,所以我只打算探討技術問題(不是小看法律問題,
+法律問題很實際,並且需要一直關注)。
+
+既然只談技術問題,我們就有了下面兩個主題:二進位內核接口和穩定的內核源
+代碼接口。這兩個問題是互相關聯的,讓我們先解決掉二進位接口的問題。
+
+
+二進位內核接口
+--------------
+假如我們有一個穩定的內核原始碼接口,那麼自然而然的,我們就擁有了穩定的
+二進位接口,是這樣的嗎?錯。讓我們看看關於Linux內核的幾點事實:
+
+    - 取決於所用的C編譯器的版本,不同的內核數據結構里的結構體的對齊方
+      式會有差別,代碼中不同函數的表現形式也不一樣(函數是不是被inline
+      編譯取決於編譯器行爲)。不同的函數的表現形式並不重要,但是數據
+      結構內部的對齊方式很關鍵。
+
+    - 取決於內核的配置選項,不同的選項會讓內核的很多東西發生改變:
+
+      - 同一個結構體可能包含不同的成員變量
+      - 有的函數可能根本不會被實現(比如編譯的時候沒有選擇SMP支持
+        一些鎖函數就會被定義成空函數)。
+      - 內核使用的內存會以不同的方式對齊,這取決於不同的內核配置選
+        項。
+
+    - Linux可以在很多的不同體系結構的處理器上運行。在某個體系結構上編
+      譯好的二進位驅動程序,不可能在另外一個體系結構上正確的運行。
+
+對於一個特定的內核,滿足這些條件並不難,使用同一個C編譯器和同樣的內核配
+置選項來編譯驅動程序模塊就可以了。這對於給一個特定Linux發布的特定版本提
+供驅動程序,是完全可以滿足需求的。但是如果你要給不同發布的不同版本都發
+布一個驅動程序,就需要在每個發布上用不同的內核設置參數都編譯一次內核,
+這簡直跟噩夢一樣。而且還要注意到,每個Linux發布還提供不同的Linux內核,
+這些內核都針對不同的硬體類型進行了優化(有很多種不同的處理器,還有不同
+的內核設置選項)。所以每發布一次驅動程序,都需要提供很多不同版本的內核
+模塊。
+
+相信我,如果你真的要採取這種發布方式,一定會慢慢瘋掉,我很久以前就有過
+深刻的教訓...
+
+
+穩定的內核原始碼接口
+--------------------
+
+如果有人不將他的內核驅動程序,放入公版內核的原始碼樹,而又想讓驅動程序
+一直保持在最新的內核中可用,那麼這個話題將會變得沒完沒了。
+內核開發是持續而且快節奏的,從來都不會慢下來。內核開發人員在當前接口中
+找到bug,或者找到更好的實現方式。一旦發現這些,他們就很快會去修改當前的
+接口。修改接口意味著,函數名可能會改變,結構體可能被擴充或者刪減,函數
+的參數也可能發生改變。一旦接口被修改,內核中使用這些接口的地方需要同時
+修正,這樣才能保證所有的東西繼續工作。
+
+舉一個例子,內核的USB驅動程序接口在USB子系統的整個生命周期中,至少經歷
+了三次重寫。這些重寫解決以下問題:
+
+    - 把數據流從同步模式改成非同步模式,這個改動減少了一些驅動程序的
+      複雜度,提高了所有USB驅動程序的吞吐率,這樣幾乎所有的USB設備都
+      能以最大速率工作了。
+    - 修改了USB核心代碼中爲USB驅動分配數據包內存的方式,所有的驅動都
+      需要提供更多的參數給USB核心,以修正了很多已經被記錄在案的死鎖。
+
+這和一些封閉原始碼的作業系統形成鮮明的對比,在那些作業系統上,不得不額
+外的維護舊的USB接口。這導致了一個可能性,新的開發者依然會不小心使用舊的
+接口,以不恰當的方式編寫代碼,進而影響到作業系統的穩定性。
+在上面的例子中,所有的開發者都同意這些重要的改動,在這樣的情況下修改代
+價很低。如果Linux保持一個穩定的內核原始碼接口,那麼就得創建一個新的接口
+;舊的,有問題的接口必須一直維護,給Linux USB開發者帶來額外的工作。既然
+所有的Linux USB驅動的作者都是利用自己的時間工作,那麼要求他們去做毫無意
+義的免費額外工作,是不可能的。
+安全問題對Linux來說十分重要。一個安全問題被發現,就會在短時間內得到修
+正。在很多情況下,這將導致Linux內核中的一些接口被重寫,以從根本上避免安
+全問題。一旦接口被重寫,所有使用這些接口的驅動程序,必須同時得到修正,
+以確定安全問題已經得到修復並且不可能在未來還有同樣的安全問題。如果內核
+內部接口不允許改變,那麼就不可能修復這樣的安全問題,也不可能確認這樣的
+安全問題以後不會發生。
+開發者一直在清理內核接口。如果一個接口沒有人在使用了,它就會被刪除。這
+樣可以確保內核儘可能的小,而且所有潛在的接口都會得到儘可能完整的測試
+(沒有人使用的接口是不可能得到良好的測試的)。
+
+
+要做什麼
+--------
+
+如果你寫了一個Linux內核驅動,但是它還不在Linux原始碼樹里,作爲一個開發
+者,你應該怎麼做?爲每個發布的每個版本提供一個二進位驅動,那簡直是一個
+噩夢,要跟上永遠處於變化之中的內核接口,也是一件辛苦活。
+很簡單,讓你的驅動進入內核原始碼樹(要記得我們在談論的是以GPL許可發行
+的驅動,如果你的代碼不符合GPL,那麼祝你好運,你只能自己解決這個問題了,
+你這個吸血鬼<把Andrew和Linus對吸血鬼的定義連結到這裡>)。當你的代碼加入
+公版內核原始碼樹之後,如果一個內核接口改變,你的驅動會直接被修改接口的
+那個人修改。保證你的驅動永遠都可以編譯通過,並且一直工作,你幾乎不需要
+做什麼事情。
+
+把驅動放到內核原始碼樹里會有很多的好處:
+
+    - 驅動的質量會提升,而維護成本(對原始作者來說)會下降。
+    - 其他人會給驅動添加新特性。
+    - 其他人會找到驅動中的bug並修復。
+    - 其他人會在驅動中找到性能優化的機會。
+    - 當外部的接口的改變需要修改驅動程序的時候,其他人會修改驅動程序
+    - 不需要聯繫任何發行商,這個驅動會自動的隨著所有的Linux發布一起發
+      布。
+
+和別的作業系統相比,Linux爲更多不同的設備提供現成的驅動,而且能在更多不
+同體系結構的處理器上支持這些設備。這個經過考驗的開發模式,必然是錯不了
+的 :)
+
+感謝
+----
+感謝 Randy Dunlap, Andrew Morton, David Brownell, Hanna Linder,
+Robert Love, and Nishanth Aravamudan 對於本文檔早期版本的評審和建議。
+
+英文版維護者: Greg Kroah-Hartman <greg@kroah.com>
+
diff --git a/Documentation/translations/zh_TW/process/stable-kernel-rules.rst b/Documentation/translations/zh_TW/process/stable-kernel-rules.rst
new file mode 100644
index 000000000000..9bb0d9b4f3ac
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/stable-kernel-rules.rst
@@ -0,0 +1,68 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _tw_stable_kernel_rules:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/stable-kernel-rules.rst <stable_kernel_rules>`
+
+如果想評論或更新本文的內容,請直接聯繫原文檔的維護者。如果你使用英文
+交流有困難的話,也可以向中文版維護者求助。如果本翻譯更新不及時或者翻
+譯存在問題,請聯繫中文版維護者::
+
+        中文版維護者: 鍾宇  TripleX Chung <xxx.phy@gmail.com>
+        中文版翻譯者: 鍾宇  TripleX Chung <xxx.phy@gmail.com>
+        中文版校譯者:
+            - 李陽  Li Yang <leoyang.li@nxp.com>
+            - Kangkai Yin <e12051@motorola.com>
+            - 胡皓文 Hu Haowen <src.res@email.cn>
+
+所有你想知道的事情 - 關於linux穩定版發布
+========================================
+
+關於Linux 2.6穩定版發布,所有你想知道的事情。
+
+關於哪些類型的補丁可以被接收進入穩定版代碼樹,哪些不可以的規則:
+----------------------------------------------------------------
+
+  - 必須是顯而易見的正確,並且經過測試的。
+  - 連同上下文,不能大於100行。
+  - 必須只修正一件事情。
+  - 必須修正了一個給大家帶來麻煩的真正的bug(不是「這也許是一個問題...」
+    那樣的東西)。
+  - 必須修正帶來如下後果的問題:編譯錯誤(對被標記爲CONFIG_BROKEN的例外),
+    內核崩潰,掛起,數據損壞,真正的安全問題,或者一些類似「哦,這不
+    好」的問題。簡短的說,就是一些致命的問題。
+  - 沒有「理論上的競爭條件」,除非能給出競爭條件如何被利用的解釋。
+  - 不能存在任何的「瑣碎的」修正(拼寫修正,去掉多餘空格之類的)。
+  - 必須被相關子系統的維護者接受。
+  - 必須遵循Documentation/translations/zh_TW/process/submitting-patches.rst里的規則。
+
+向穩定版代碼樹提交補丁的過程:
+------------------------------
+
+  - 在確認了補丁符合以上的規則後,將補丁發送到stable@vger.kernel.org。
+  - 如果補丁被接受到隊列里,發送者會收到一個ACK回復,如果沒有被接受,收
+    到的是NAK回復。回復需要幾天的時間,這取決於開發者的時間安排。
+  - 被接受的補丁會被加到穩定版本隊列里,等待其他開發者的審查。
+  - 安全方面的補丁不要發到這個列表,應該發送到security@kernel.org。
+
+審查周期:
+----------
+
+  - 當穩定版的維護者決定開始一個審查周期,補丁將被發送到審查委員會,以
+    及被補丁影響的領域的維護者(除非提交者就是該領域的維護者)並且抄送
+    到linux-kernel郵件列表。
+  - 審查委員會有48小時的時間,用來決定給該補丁回復ACK還是NAK。
+  - 如果委員會中有成員拒絕這個補丁,或者linux-kernel列表上有人反對這個
+    補丁,並提出維護者和審查委員會之前沒有意識到的問題,補丁會從隊列中
+    丟棄。
+  - 在審查周期結束的時候,那些得到ACK回應的補丁將會被加入到最新的穩定版
+    發布中,一個新的穩定版發布就此產生。
+  - 安全性補丁將從內核安全小組那裡直接接收到穩定版代碼樹中,而不是通過
+    通常的審查周期。請聯繫內核安全小組以獲得關於這個過程的更多細節。
+
+審查委員會:
+------------
+  - 由一些自願承擔這項任務的內核開發者,和幾個非志願的組成。
+
diff --git a/Documentation/translations/zh_TW/process/submit-checklist.rst b/Documentation/translations/zh_TW/process/submit-checklist.rst
new file mode 100644
index 000000000000..ff2f89cba83f
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/submit-checklist.rst
@@ -0,0 +1,109 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/submit-checklist.rst <submitchecklist>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+.. _tw_submitchecklist:
+
+Linux內核補丁提交清單
+~~~~~~~~~~~~~~~~~~~~~
+
+如果開發人員希望看到他們的內核補丁提交更快地被接受,那麼他們應該做一些基本
+的事情。
+
+這些都是在
+:ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+和其他有關提交Linux內核補丁的文檔中提供的。
+
+1) 如果使用工具,則包括定義/聲明該工具的文件。不要依賴於其他頭文件拉入您使用
+   的頭文件。
+
+2) 乾淨的編譯:
+
+   a) 使用適用或修改的 ``CONFIG`` 選項 ``=y``、``=m`` 和 ``=n`` 。沒有GCC
+      警告/錯誤,沒有連結器警告/錯誤。
+
+   b) 通過allnoconfig、allmodconfig
+
+   c) 使用 ``O=builddir`` 時可以成功編譯
+
+3) 通過使用本地交叉編譯工具或其他一些構建場在多個CPU體系結構上構建。
+
+4) PPC64是一種很好的交叉編譯檢查體系結構,因爲它傾向於對64位的數使用無符號
+   長整型。
+
+5) 如下所述 :ref:`Documentation/translations/zh_TW/process/coding-style.rst <tw_codingstyle>`.
+   檢查您的補丁是否爲常規樣式。在提交( ``scripts/check patch.pl`` )之前,
+   使用補丁樣式檢查器檢查是否有輕微的衝突。您應該能夠處理您的補丁中存在的所有
+   違規行爲。
+
+6) 任何新的或修改過的 ``CONFIG`` 選項都不會弄髒配置菜單,並默認爲關閉,除非
+   它們符合 ``Documentation/kbuild/kconfig-language.rst`` 中記錄的異常條件,
+   菜單屬性:默認值.
+
+7) 所有新的 ``kconfig`` 選項都有幫助文本。
+
+8) 已仔細審查了相關的 ``Kconfig`` 組合。這很難用測試來糾正——腦力在這裡是有
+   回報的。
+
+9) 用 sparse 檢查乾淨。
+
+10) 使用 ``make checkstack`` 和 ``make namespacecheck`` 並修復他們發現的任何
+    問題。
+
+    .. note::
+
+        ``checkstack`` 並沒有明確指出問題,但是任何一個在堆棧上使用超過512
+        字節的函數都可以進行更改。
+
+11) 包括 :ref:`kernel-doc <kernel_doc>` 內核文檔以記錄全局內核API。(靜態函數
+    不需要,但也可以。)使用 ``make htmldocs`` 或 ``make pdfdocs`` 檢查
+    :ref:`kernel-doc <kernel_doc>` 並修復任何問題。
+
+12) 通過以下選項同時啓用的測試 ``CONFIG_PREEMPT``, ``CONFIG_DEBUG_PREEMPT``,
+    ``CONFIG_DEBUG_SLAB``, ``CONFIG_DEBUG_PAGEALLOC``, ``CONFIG_DEBUG_MUTEXES``,
+    ``CONFIG_DEBUG_SPINLOCK``, ``CONFIG_DEBUG_ATOMIC_SLEEP``,
+    ``CONFIG_PROVE_RCU`` and ``CONFIG_DEBUG_OBJECTS_RCU_HEAD``
+
+13) 已經過構建和運行時測試,包括有或沒有 ``CONFIG_SMP``, ``CONFIG_PREEMPT``.
+
+14) 如果補丁程序影響IO/磁碟等:使用或不使用 ``CONFIG_LBDAF`` 進行測試。
+
+15) 所有代碼路徑都已在啓用所有lockdep功能的情況下運行。
+
+16) 所有新的/proc條目都記錄在 ``Documentation/``
+
+17) 所有新的內核引導參數都記錄在
+    Documentation/admin-guide/kernel-parameters.rst 中。
+
+18) 所有新的模塊參數都記錄在 ``MODULE_PARM_DESC()``
+
+19) 所有新的用戶空間接口都記錄在 ``Documentation/ABI/`` 中。有關詳細信息,
+    請參閱 ``Documentation/ABI/README`` 。更改用戶空間接口的補丁應該抄送
+    linux-api@vger.kernel.org。
+
+20) 已通過至少注入slab和page分配失敗進行檢查。請參閱 ``Documentation/fault-injection/``
+    如果新代碼是實質性的,那麼添加子系統特定的故障注入可能是合適的。
+
+21) 新添加的代碼已經用 ``gcc -W`` 編譯(使用 ``make EXTRA-CFLAGS=-W`` )。這
+    將產生大量噪聲,但對於查找諸如「警告:有符號和無符號之間的比較」之類的錯誤
+    很有用。
+
+22) 在它被合併到-mm補丁集中之後進行測試,以確保它仍然與所有其他排隊的補丁以
+    及VM、VFS和其他子系統中的各種更改一起工作。
+
+23) 所有內存屏障例如 ``barrier()``, ``rmb()``, ``wmb()`` 都需要原始碼中的注
+    釋來解釋它們正在執行的操作及其原因的邏輯。
+
+24) 如果補丁添加了任何ioctl,那麼也要更新 ``Documentation/userspace-api/ioctl/ioctl-number.rst``
+
+25) 如果修改後的原始碼依賴或使用與以下 ``Kconfig`` 符號相關的任何內核API或
+    功能,則在禁用相關 ``Kconfig`` 符號和/或 ``=m`` (如果該選項可用)的情況
+    下測試以下多個構建[並非所有這些都同時存在,只是它們的各種/隨機組合]:
+
+    ``CONFIG_SMP``, ``CONFIG_SYSFS``, ``CONFIG_PROC_FS``, ``CONFIG_INPUT``, ``CONFIG_PCI``, ``CONFIG_BLOCK``, ``CONFIG_PM``, ``CONFIG_MAGIC_SYSRQ``,
+    ``CONFIG_NET``, ``CONFIG_INET=n`` (但是後者伴隨 ``CONFIG_NET=y``).
+
diff --git a/Documentation/translations/zh_TW/process/submitting-drivers.rst b/Documentation/translations/zh_TW/process/submitting-drivers.rst
new file mode 100644
index 000000000000..2fdd742318ba
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/submitting-drivers.rst
@@ -0,0 +1,164 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _tw_submittingdrivers:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/submitting-drivers.rst
+           <submittingdrivers>`
+
+如果想評論或更新本文的內容,請直接聯繫原文檔的維護者。如果你使用英文
+交流有困難的話,也可以向中文版維護者求助。如果本翻譯更新不及時或者翻
+譯存在問題,請聯繫中文版維護者::
+
+        中文版維護者: 李陽  Li Yang <leoyang.li@nxp.com>
+        中文版翻譯者: 李陽  Li Yang <leoyang.li@nxp.com>
+        中文版校譯者: 陳琦 Maggie Chen <chenqi@beyondsoft.com>
+                       王聰 Wang Cong <xiyou.wangcong@gmail.com>
+                       張巍 Zhang Wei <wezhang@outlook.com>
+                       胡皓文 Hu Haowen <src.res@email.cn>
+
+如何向 Linux 內核提交驅動程序
+=============================
+
+這篇文檔將會解釋如何向不同的內核源碼樹提交設備驅動程序。請注意,如果你感
+興趣的是顯卡驅動程序,你也許應該訪問 XFree86 項目(https://www.xfree86.org/)
+和/或 X.org 項目 (https://x.org)。
+
+另請參閱 Documentation/translations/zh_TW/process/submitting-patches.rst 文檔。
+
+
+分配設備號
+----------
+
+塊設備和字符設備的主設備號與從設備號是由 Linux 命名編號分配權威 LANANA(
+現在是 Torben Mathiasen)負責分配。申請的網址是 https://www.lanana.org/。
+即使不準備提交到主流內核的設備驅動也需要在這裡分配設備號。有關詳細信息,
+請參閱 Documentation/admin-guide/devices.rst。
+
+如果你使用的不是已經分配的設備號,那麼當你提交設備驅動的時候,它將會被強
+制分配一個新的設備號,即便這個設備號和你之前發給客戶的截然不同。
+
+設備驅動的提交對象
+------------------
+
+Linux 2.0:
+	此內核源碼樹不接受新的驅動程序。
+
+Linux 2.2:
+	此內核源碼樹不接受新的驅動程序。
+
+Linux 2.4:
+	如果所屬的代碼領域在內核的 MAINTAINERS 文件中列有一個總維護者,
+	那麼請將驅動程序提交給他。如果此維護者沒有回應或者你找不到恰當的
+	維護者,那麼請聯繫 Willy Tarreau <w@1wt.eu>。
+
+Linux 2.6:
+	除了遵循和 2.4 版內核同樣的規則外,你還需要在 linux-kernel 郵件
+	列表上跟蹤最新的 API 變化。向 Linux 2.6 內核提交驅動的頂級聯繫人
+	是 Andrew Morton <akpm@linux-foundation.org>。
+
+決定設備驅動能否被接受的條件
+----------------------------
+
+許可:		代碼必須使用 GNU 通用公開許可證 (GPL) 提交給 Linux,但是
+		我們並不要求 GPL 是唯一的許可。你或許會希望同時使用多種
+		許可證發布,如果希望驅動程序可以被其他開源社區(比如BSD)
+		使用。請參考 include/linux/module.h 文件中所列出的可被
+		接受共存的許可。
+
+版權:		版權所有者必須同意使用 GPL 許可。最好提交者和版權所有者
+		是相同個人或實體。否則,必需列出授權使用 GPL 的版權所有
+		人或實體,以備驗證之需。
+
+接口:		如果你的驅動程序使用現成的接口並且和其他同類的驅動程序行
+		爲相似,而不是去發明無謂的新接口,那麼它將會更容易被接受。
+		如果你需要一個 Linux 和 NT 的通用驅動接口,那麼請在用
+		戶空間實現它。
+
+代碼:		請使用 Documentation/process/coding-style.rst 中所描述的 Linux 代碼風
+		格。如果你的某些代碼段(例如那些與 Windows 驅動程序包共
+		享的代碼段)需要使用其他格式,而你卻只希望維護一份代碼,
+		那麼請將它們很好地區分出來,並且註明原因。
+
+可移植性:	請注意,指針並不永遠是 32 位的,不是所有的計算機都使用小
+		尾模式 (little endian) 存儲數據,不是所有的人都擁有浮點
+		單元,不要隨便在你的驅動程序里嵌入 x86 彙編指令。只能在
+		x86 上運行的驅動程序一般是不受歡迎的。雖然你可能只有 x86
+		硬體,很難測試驅動程序在其他平台上是否可用,但是確保代碼
+		可以被輕鬆地移植卻是很簡單的。
+
+清晰度:	做到所有人都能修補這個驅動程序將會很有好處,因爲這樣你將
+		會直接收到修復的補丁而不是 bug 報告。如果你提交一個試圖
+		隱藏硬體工作機理的驅動程序,那麼它將會被扔進廢紙簍。
+
+電源管理:	因爲 Linux 正在被很多行動裝置和桌面系統使用,所以你的驅
+		動程序也很有可能被使用在這些設備上。它應該支持最基本的電
+		源管理,即在需要的情況下實現系統級休眠和喚醒要用到的
+		.suspend 和 .resume 函數。你應該檢查你的驅動程序是否能正
+		確地處理休眠與喚醒,如果實在無法確認,請至少把 .suspend
+		函數定義成返回 -ENOSYS(功能未實現)錯誤。你還應該嘗試確
+		保你的驅動在什麼都不乾的情況下將耗電降到最低。要獲得驅動
+		程序測試的指導,請參閱
+		Documentation/power/drivers-testing.rst。有關驅動程序電
+		源管理問題相對全面的概述,請參閱
+		Documentation/driver-api/pm/devices.rst。
+
+管理:		如果一個驅動程序的作者還在進行有效的維護,那麼通常除了那
+		些明顯正確且不需要任何檢查的補丁以外,其他所有的補丁都會
+		被轉發給作者。如果你希望成爲驅動程序的聯繫人和更新者,最
+		好在代碼注釋中寫明並且在 MAINTAINERS 文件中加入這個驅動
+		程序的條目。
+
+不影響設備驅動能否被接受的條件
+------------------------------
+
+供應商:	由硬體供應商來維護驅動程序通常是一件好事。不過,如果源碼
+		樹里已經有其他人提供了可穩定工作的驅動程序,那麼請不要期
+		望「我是供應商」會成爲內核改用你的驅動程序的理由。理想的情
+		況是:供應商與現有驅動程序的作者合作,構建一個統一完美的
+		驅動程序。
+
+作者:		驅動程序是由大的 Linux 公司研發還是由你個人編寫,並不影
+		響其是否能被內核接受。沒有人對內核源碼樹享有特權。只要你
+		充分了解內核社區,你就會發現這一點。
+
+
+資源列表
+--------
+
+Linux 內核主源碼樹:
+	ftp.??.kernel.org:/pub/linux/kernel/...
+	?? == 你的國家代碼,例如 "cn"、"us"、"uk"、"fr" 等等
+
+Linux 內核郵件列表:
+	linux-kernel@vger.kernel.org
+	[可通過向majordomo@vger.kernel.org發郵件來訂閱]
+
+Linux 設備驅動程序,第三版(探討 2.6.10 版內核):
+	https://lwn.net/Kernel/LDD3/ (免費版)
+
+LWN.net:
+	每周內核開發活動摘要 - https://lwn.net/
+
+	2.6 版中 API 的變更:
+
+		https://lwn.net/Articles/2.6-kernel-api/
+
+	將舊版內核的驅動程序移植到 2.6 版:
+
+		https://lwn.net/Articles/driver-porting/
+
+內核新手(KernelNewbies):
+	爲新的內核開發者提供文檔和幫助
+	https://kernelnewbies.org/
+
+Linux USB項目:
+	http://www.linux-usb.org/
+
+寫內核驅動的「不要」(Arjan van de Ven著):
+	http://www.fenrus.org/how-to-not-write-a-device-driver-paper.pdf
+
+內核清潔工 (Kernel Janitor):
+	https://kernelnewbies.org/KernelJanitors
+
diff --git a/Documentation/translations/zh_TW/process/submitting-patches.rst b/Documentation/translations/zh_TW/process/submitting-patches.rst
new file mode 100644
index 000000000000..cdf0b52e4a98
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/submitting-patches.rst
@@ -0,0 +1,686 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _tw_submittingpatches:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/submitting-patches.rst <submittingpatches>`
+
+譯者::
+
+        中文版維護者: 鍾宇 TripleX Chung <xxx.phy@gmail.com>
+        中文版翻譯者: 鍾宇 TripleX Chung <xxx.phy@gmail.com>
+                       時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+        中文版校譯者: 李陽 Li Yang <leoyang.li@nxp.com>
+                       王聰 Wang Cong <xiyou.wangcong@gmail.com>
+                       胡皓文 Hu Haowen <src.res@email.cn>
+
+
+如何讓你的改動進入內核
+======================
+
+對於想要將改動提交到 Linux 內核的個人或者公司來說,如果不熟悉「規矩」,
+提交的流程會讓人畏懼。本文檔收集了一系列建議,這些建議可以大大的提高你
+的改動被接受的機會.
+
+以下文檔含有大量簡潔的建議, 具體請見:
+:ref:`Documentation/process <development_process_main>`
+同樣,:ref:`Documentation/translations/zh_TW/process/submit-checklist.rst <tw_submitchecklist>`
+給出在提交代碼前需要檢查的項目的列表。如果你在提交一個驅動程序,那麼
+同時閱讀一下:
+:ref:`Documentation/process/submitting-drivers.rst <submittingdrivers>`
+
+其中許多步驟描述了Git版本控制系統的默認行爲;如果您使用Git來準備補丁,
+您將發現它爲您完成的大部分機械工作,儘管您仍然需要準備和記錄一組合理的
+補丁。一般來說,使用git將使您作爲內核開發人員的生活更輕鬆。
+
+
+0) 獲取當前源碼樹
+-----------------
+
+如果您沒有一個可以使用當前內核原始碼的存儲庫,請使用git獲取一個。您將要
+從主線存儲庫開始,它可以通過以下方式獲取::
+
+        git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
+
+但是,請注意,您可能不希望直接針對主線樹進行開發。大多數子系統維護人員運
+行自己的樹,並希望看到針對這些樹準備的補丁。請參見MAINTAINERS文件中子系
+統的 **T:** 項以查找該樹,或者簡單地詢問維護者該樹是否未在其中列出。
+
+仍然可以通過tarballs下載內核版本(如下一節所述),但這是進行內核開發的
+一種困難的方式。
+
+1) "diff -up"
+-------------
+
+使用 "diff -up" 或者 "diff -uprN" 來創建補丁。
+
+所有內核的改動,都是以補丁的形式呈現的,補丁由 diff(1) 生成。創建補丁的
+時候,要確認它是以 "unified diff" 格式創建的,這種格式由 diff(1) 的 '-u'
+參數生成。而且,請使用 '-p' 參數,那樣會顯示每個改動所在的C函數,使得
+產生的補丁容易讀得多。補丁應該基於內核原始碼樹的根目錄,而不是裡邊的任
+何子目錄。
+
+爲一個單獨的文件創建補丁,一般來說這樣做就夠了::
+
+        SRCTREE=linux
+        MYFILE=drivers/net/mydriver.c
+
+        cd $SRCTREE
+        cp $MYFILE $MYFILE.orig
+        vi $MYFILE      # make your change
+        cd ..
+        diff -up $SRCTREE/$MYFILE{.orig,} > /tmp/patch
+
+爲多個文件創建補丁,你可以解開一個沒有修改過的內核原始碼樹,然後和你自
+己的代碼樹之間做 diff 。例如::
+
+        MYSRC=/devel/linux
+
+        tar xvfz linux-3.19.tar.gz
+        mv linux-3.19 linux-3.19-vanilla
+        diff -uprN -X linux-3.19-vanilla/Documentation/dontdiff \
+                linux-3.19-vanilla $MYSRC > /tmp/patch
+
+"dontdiff" 是內核在編譯的時候產生的文件的列表,列表中的文件在 diff(1)
+產生的補丁里會被跳過。
+
+確定你的補丁里沒有包含任何不屬於這次補丁提交的額外文件。記得在用diff(1)
+生成補丁之後,審閱一次補丁,以確保準確。
+
+如果你的改動很散亂,你應該研究一下如何將補丁分割成獨立的部分,將改動分
+割成一系列合乎邏輯的步驟。這樣更容易讓其他內核開發者審核,如果你想你的
+補丁被接受,這是很重要的。請參閱:
+:ref:`tw_split_changes`
+
+如果你用 ``git`` , ``git rebase -i`` 可以幫助你這一點。如果你不用 ``git``,
+``quilt`` <https://savannah.nongnu.org/projects/quilt> 另外一個流行的選擇。
+
+.. _tw_describe_changes:
+
+2) 描述你的改動
+---------------
+
+描述你的問題。無論您的補丁是一行錯誤修復還是5000行新功能,都必須有一個潛在
+的問題激勵您完成這項工作。讓審稿人相信有一個問題值得解決,讓他們讀完第一段
+是有意義的。
+
+描述用戶可見的影響。直接崩潰和鎖定是相當有說服力的,但並不是所有的錯誤都那麼
+明目張胆。即使在代碼審查期間發現了這個問題,也要描述一下您認爲它可能對用戶產
+生的影響。請記住,大多數Linux安裝運行的內核來自二級穩定樹或特定於供應商/產品
+的樹,只從上游精選特定的補丁,因此請包含任何可以幫助您將更改定位到下游的內容:
+觸發的場景、DMESG的摘錄、崩潰描述、性能回歸、延遲尖峯、鎖定等。
+
+量化優化和權衡。如果您聲稱在性能、內存消耗、堆棧占用空間或二進位大小方面有所
+改進,請包括支持它們的數字。但也要描述不明顯的成本。優化通常不是免費的,而是
+在CPU、內存和可讀性之間進行權衡;或者,探索性的工作,在不同的工作負載之間進
+行權衡。請描述優化的預期缺點,以便審閱者可以權衡成本和收益。
+
+一旦問題建立起來,就要詳細地描述一下您實際在做什麼。對於審閱者來說,用簡單的
+英語描述代碼的變化是很重要的,以驗證代碼的行爲是否符合您的意願。
+
+如果您將補丁描述寫在一個表單中,這個表單可以很容易地作爲「提交日誌」放入Linux
+的原始碼管理系統git中,那麼維護人員將非常感謝您。見 :ref:`tw_explicit_in_reply_to`.
+
+每個補丁只解決一個問題。如果你的描述開始變長,這就表明你可能需要拆分你的補丁。
+請見 :ref:`tw_split_changes`
+
+提交或重新提交修補程序或修補程序系列時,請包括完整的修補程序說明和理由。不要
+只說這是補丁(系列)的第幾版。不要期望子系統維護人員引用更早的補丁版本或引用
+URL來查找補丁描述並將其放入補丁中。也就是說,補丁(系列)及其描述應該是獨立的。
+這對維護人員和審查人員都有好處。一些評審者可能甚至沒有收到補丁的早期版本。
+
+描述你在命令語氣中的變化,例如「make xyzzy do frotz」而不是「[這個補丁]make
+xyzzy do frotz」或「[我]changed xyzzy to do frotz」,就好像你在命令代碼庫改變
+它的行爲一樣。
+
+如果修補程序修復了一個記錄的bug條目,請按編號和URL引用該bug條目。如果補丁來
+自郵件列表討論,請給出郵件列表存檔的URL;使用帶有 ``Message-ID`` 的
+https://lkml.kernel.org/ 重定向,以確保連結不會過時。
+
+但是,在沒有外部資源的情況下,儘量讓你的解釋可理解。除了提供郵件列表存檔或
+bug的URL之外,還要總結需要提交補丁的相關討論要點。
+
+如果您想要引用一個特定的提交,不要只引用提交的 SHA-1 ID。還請包括提交的一行
+摘要,以便於審閱者了解它是關於什麼的。例如::
+
+        Commit e21d2170f36602ae2708 ("video: remove unnecessary
+        platform_set_drvdata()") removed the unnecessary
+        platform_set_drvdata(), but left the variable "dev" unused,
+        delete it.
+
+您還應該確保至少使用前12位 SHA-1 ID. 內核存儲庫包含*許多*對象,使與較短的ID
+發生衝突的可能性很大。記住,即使現在不會與您的六個字符ID發生衝突,這種情況
+可能五年後改變。
+
+如果修補程序修復了特定提交中的錯誤,例如,使用 ``git bisct`` ,請使用帶有前
+12個字符SHA-1 ID 的"Fixes:"標記和單行摘要。爲了簡化不要將標記拆分爲多個,
+行、標記不受分析腳本「75列換行」規則的限制。例如::
+
+        Fixes: 54a4f0239f2e ("KVM: MMU: make kvm_mmu_zap_page() return the number of pages it actually freed")
+
+下列 ``git config`` 設置可以添加讓 ``git log``, ``git show`` 漂亮的顯示格式::
+
+	[core]
+		abbrev = 12
+	[pretty]
+		fixes = Fixes: %h (\"%s\")
+
+.. _tw_split_changes:
+
+3) 拆分你的改動
+---------------
+
+將每個邏輯更改分隔成一個單獨的補丁。
+
+例如,如果你的改動里同時有bug修正和性能優化,那麼把這些改動拆分到兩個或
+者更多的補丁文件中。如果你的改動包含對API的修改,並且修改了驅動程序來適
+應這些新的API,那麼把這些修改分成兩個補丁。
+
+另一方面,如果你將一個單獨的改動做成多個補丁文件,那麼將它們合併成一個
+單獨的補丁文件。這樣一個邏輯上單獨的改動只被包含在一個補丁文件里。
+
+如果有一個補丁依賴另外一個補丁來完成它的改動,那沒問題。簡單的在你的補
+丁描述里指出「這個補丁依賴某補丁」就好了。
+
+在將您的更改劃分爲一系列補丁時,要特別注意確保內核在系列中的每個補丁之後
+都能正常構建和運行。使用 ``git bisect`` 來追蹤問題的開發者可能會在任何時
+候分割你的補丁系列;如果你在中間引入錯誤,他們不會感謝你。
+
+如果你不能將補丁濃縮成更少的文件,那麼每次大約發送出15個,然後等待審查
+和集成。
+
+4) 檢查你的更改風格
+-------------------
+
+檢查您的補丁是否存在基本樣式衝突,詳細信息可在
+:ref:`Documentation/translations/zh_TW/process/coding-style.rst <tw_codingstyle>`
+中找到。如果不這樣做,只會浪費審稿人的時間,並且會導致你的補丁被拒絕,甚至
+可能沒有被閱讀。
+
+一個重要的例外是在將代碼從一個文件移動到另一個文件時——在這種情況下,您不應
+該在移動代碼的同一個補丁中修改移動的代碼。這清楚地描述了移動代碼和您的更改
+的行爲。這大大有助於審查實際差異,並允許工具更好地跟蹤代碼本身的歷史。
+
+在提交之前,使用補丁樣式檢查程序檢查補丁(scripts/check patch.pl)。不過,
+請注意,樣式檢查程序應該被視爲一個指南,而不是作爲人類判斷的替代品。如果您
+的代碼看起來更好,但有違規行爲,那麼最好不要使用它。
+
+檢查者報告三個級別:
+
+ - ERROR:很可能出錯的事情
+ - WARNING:需要仔細審查的事項
+ - CHECK:需要思考的事情
+
+您應該能夠判斷您的補丁中存在的所有違規行爲。
+
+5) 選擇補丁收件人
+-----------------
+
+您應該總是在任何補丁上複製相應的子系統維護人員,以獲得他們維護的代碼;查看
+維護人員文件和原始碼修訂歷史記錄,以了解這些維護人員是誰。腳本
+scripts/get_Maintainer.pl在這個步驟中非常有用。如果您找不到正在工作的子系統
+的維護人員,那麼Andrew Morton(akpm@linux-foundation.org)將充當最後的維護
+人員。
+
+您通常還應該選擇至少一個郵件列表來接收補丁集的。linux-kernel@vger.kernel.org
+作爲最後一個解決辦法的列表,但是這個列表上的體積已經引起了許多開發人員的拒絕。
+在MAINTAINERS文件中查找子系統特定的列表;您的補丁可能會在那裡得到更多的關注。
+不過,請不要發送垃圾郵件到無關的列表。
+
+許多與內核相關的列表託管在vger.kernel.org上;您可以在
+http://vger.kernel.org/vger-lists.html 上找到它們的列表。不過,也有與內核相關
+的列表託管在其他地方。
+
+不要一次發送超過15個補丁到vger郵件列表!!!!
+
+Linus Torvalds 是決定改動能否進入 Linux 內核的最終裁決者。他的 e-mail
+地址是 <torvalds@linux-foundation.org> 。他收到的 e-mail 很多,所以一般
+的說,最好別給他發 e-mail。
+
+如果您有修復可利用安全漏洞的補丁,請將該補丁發送到 security@kernel.org。對於
+嚴重的bug,可以考慮短期暫停以允許分銷商向用戶發布補丁;在這種情況下,顯然不應
+將補丁發送到任何公共列表。
+
+修復已發布內核中嚴重錯誤的補丁程序應該指向穩定版維護人員,方法是放這樣的一行::
+
+        Cc: stable@vger.kernel.org
+
+進入補丁的簽准區(注意,不是電子郵件收件人)。除了這個文件之外,您還應該閱讀
+:ref:`Documentation/process/stable-kernel-rules.rst <stable_kernel_rules>`
+
+但是,請注意,一些子系統維護人員希望得出他們自己的結論,即哪些補丁應該被放到
+穩定的樹上。尤其是網絡維護人員,不希望看到單個開發人員在補丁中添加像上面這樣
+的行。
+
+如果更改影響到用戶和內核接口,請向手冊頁維護人員(如維護人員文件中所列)發送
+手冊頁補丁,或至少發送更改通知,以便一些信息進入手冊頁。還應將用戶空間API
+更改複製到 linux-api@vger.kernel.org。
+
+對於小的補丁,你也許會CC到搜集瑣碎補丁的郵件列表(Trivial Patch Monkey)
+trivial@kernel.org,那裡專門收集瑣碎的補丁。下面這樣的補丁會被看作「瑣碎的」
+補丁:
+
+ - 文檔的拼寫修正。
+ - 修正會影響到 grep(1) 的拼寫。
+ - 警告信息修正(頻繁的列印無用的警告是不好的。)
+ - 編譯錯誤修正(代碼邏輯的確是對的,只是編譯有問題。)
+ - 運行時修正(只要真的修正了錯誤。)
+ - 移除使用了被廢棄的函數/宏的代碼(例如 check_region。)
+ - 聯繫方式和文檔修正。
+ - 用可移植的代碼替換不可移植的代碼(即使在體系結構相關的代碼中,既然有
+ - 人拷貝,只要它是瑣碎的)
+ - 任何文件的作者/維護者對該文件的改動(例如 patch monkey 在重傳模式下)
+
+(譯註,關於「瑣碎補丁」的一些說明:因爲原文的這一部分寫得比較簡單,所以不得不
+違例寫一下譯註。"trivial"這個英文單詞的本意是「瑣碎的,不重要的。」但是在這裡
+有稍微有一些變化,例如對一些明顯的NULL指針的修正,屬於運行時修正,會被歸類
+到瑣碎補丁里。雖然NULL指針的修正很重要,但是這樣的修正往往很小而且很容易得到
+檢驗,所以也被歸入瑣碎補丁。瑣碎補丁更精確的歸類應該是
+「simple, localized & easy to verify」,也就是說簡單的,局部的和易於檢驗的。
+trivial@kernel.org郵件列表的目的是針對這樣的補丁,爲提交者提供一個中心,來
+降低提交的門檻。)
+
+6) 沒有 MIME 編碼,沒有連結,沒有壓縮,沒有附件,只有純文本
+-----------------------------------------------------------
+
+Linus 和其他的內核開發者需要閱讀和評論你提交的改動。對於內核開發者來說
+,可以「引用」你的改動很重要,使用一般的 e-mail 工具,他們就可以在你的
+代碼的任何位置添加評論。
+
+因爲這個原因,所有的提交的補丁都是 e-mail 中「內嵌」的。
+
+.. warning::
+   如果你使用剪切-粘貼你的補丁,小心你的編輯器的自動換行功能破壞你的補丁
+
+不要將補丁作爲 MIME 編碼的附件,不管是否壓縮。很多流行的 e-mail 軟體不
+是任何時候都將 MIME 編碼的附件當作純文本發送的,這會使得別人無法在你的
+代碼中加評論。另外,MIME 編碼的附件會讓 Linus 多花一點時間來處理,這就
+降低了你的改動被接受的可能性。
+
+例外:如果你的郵遞員弄壞了補丁,那麼有人可能會要求你使用mime重新發送補丁
+
+請參閱 :ref:`Documentation/translations/zh_TW/process/email-clients.rst <tw_email_clients>`
+以獲取有關配置電子郵件客戶端以使其不受影響地發送修補程序的提示。
+
+7) e-mail 的大小
+----------------
+
+大的改動對郵件列表不合適,對某些維護者也不合適。如果你的補丁,在不壓縮
+的情況下,超過了300kB,那麼你最好將補丁放在一個能通過 internet 訪問的服
+務器上,然後用指向你的補丁的 URL 替代。但是請注意,如果您的補丁超過了
+300kb,那麼它幾乎肯定需要被破壞。
+
+8)回複評審意見
+---------------
+
+你的補丁幾乎肯定會得到評審者對補丁改進方法的評論。您必須對這些評論作出
+回應;讓補丁被忽略的一個好辦法就是忽略審閱者的意見。不會導致代碼更改的
+意見或問題幾乎肯定會帶來注釋或變更日誌的改變,以便下一個評審者更好地了解
+正在發生的事情。
+
+一定要告訴審稿人你在做什麼改變,並感謝他們的時間。代碼審查是一個累人且
+耗時的過程,審查人員有時會變得暴躁。即使在這種情況下,也要禮貌地回應並
+解決他們指出的問題。
+
+9)不要洩氣或不耐煩
+-------------------
+
+提交更改後,請耐心等待。審閱者是忙碌的人,可能無法立即訪問您的修補程序。
+
+曾幾何時,補丁曾在沒有評論的情況下消失在空白中,但開發過程比現在更加順利。
+您應該在一周左右的時間內收到評論;如果沒有收到評論,請確保您已將補丁發送
+到正確的位置。在重新提交或聯繫審閱者之前至少等待一周-在諸如合併窗口之類的
+繁忙時間可能更長。
+
+10)主題中包含 PATCH
+--------------------
+
+由於到linus和linux內核的電子郵件流量很高,通常會在主題行前面加上[PATCH]
+前綴. 這使Linus和其他內核開發人員更容易將補丁與其他電子郵件討論區分開。
+
+11)簽署你的作品-開發者原始認證
+-------------------------------
+
+爲了加強對誰做了何事的追蹤,尤其是對那些透過好幾層的維護者的補丁,我們
+建議在發送出去的補丁上加一個 「sign-off」 的過程。
+
+"sign-off" 是在補丁的注釋的最後的簡單的一行文字,認證你編寫了它或者其他
+人有權力將它作爲開放原始碼的補丁傳遞。規則很簡單:如果你能認證如下信息:
+
+開發者來源證書 1.1
+^^^^^^^^^^^^^^^^^^
+
+對於本項目的貢獻,我認證如下信息:
+
+      (a)這些貢獻是完全或者部分的由我創建,我有權利以文件中指出
+           的開放原始碼許可證提交它;或者
+      (b)這些貢獻基於以前的工作,據我所知,這些以前的工作受恰當的開放
+           原始碼許可證保護,而且,根據許可證,我有權提交修改後的貢獻,
+           無論是完全還是部分由我創造,這些貢獻都使用同一個開放原始碼許可證
+           (除非我被允許用其它的許可證),正如文件中指出的;或者
+      (c)這些貢獻由認證(a),(b)或者(c)的人直接提供給我,而
+           且我沒有修改它。
+      (d)我理解並同意這個項目和貢獻是公開的,貢獻的記錄(包括我
+           一起提交的個人記錄,包括 sign-off )被永久維護並且可以和這個項目
+           或者開放原始碼的許可證同步地再發行。
+
+那麼加入這樣一行::
+
+       Signed-off-by: Random J Developer <random@developer.example.org>
+
+使用你的真名(抱歉,不能使用假名或者匿名。)
+
+有人在最後加上標籤。現在這些東西會被忽略,但是你可以這樣做,來標記公司
+內部的過程,或者只是指出關於 sign-off 的一些特殊細節。
+
+如果您是子系統或分支維護人員,有時需要稍微修改收到的補丁,以便合併它們,
+因爲樹和提交者中的代碼不完全相同。如果你嚴格遵守規則(c),你應該要求提交者
+重新發布,但這完全是在浪費時間和精力。規則(b)允許您調整代碼,但是更改一個
+提交者的代碼並讓他認可您的錯誤是非常不禮貌的。要解決此問題,建議在最後一個
+由簽名行和您的行之間添加一行,指示更改的性質。雖然這並不是強制性的,但似乎
+在描述前加上您的郵件和/或姓名(全部用方括號括起來),這足以讓人注意到您對最
+後一分鐘的更改負有責任。例如::
+
+	Signed-off-by: Random J Developer <random@developer.example.org>
+	[lucky@maintainer.example.org: struct foo moved from foo.c to foo.h]
+	Signed-off-by: Lucky K Maintainer <lucky@maintainer.example.org>
+
+如果您維護一個穩定的分支機構,同時希望對作者進行致謝、跟蹤更改、合併修復並
+保護提交者不受投訴,那麼這種做法尤其有用。請注意,在任何情況下都不能更改作者
+的ID(From 頭),因爲它是出現在更改日誌中的標識。
+
+對回合(back-porters)的特別說明:在提交消息的頂部(主題行之後)插入一個補丁
+的起源指示似乎是一種常見且有用的實踐,以便於跟蹤。例如,下面是我們在3.x穩定
+版本中看到的內容::
+
+  Date:   Tue Oct 7 07:26:38 2014 -0400
+
+    libata: Un-break ATA blacklist
+
+    commit 1c40279960bcd7d52dbdf1d466b20d24b99176c8 upstream.
+
+還有, 這裡是一個舊版內核中的一個回合補丁::
+
+    Date:   Tue May 13 22:12:27 2008 +0200
+
+        wireless, airo: waitbusy() won't delay
+
+        [backport of 2.6 commit b7acbdfbd1f277c1eb23f344f899cfa4cd0bf36a]
+
+12)何時使用Acked-by:,CC:,和Co-Developed by:
+----------------------------------------------
+
+Singed-off-by: 標記表示簽名者參與了補丁的開發,或者他/她在補丁的傳遞路徑中。
+
+如果一個人沒有直接參與補丁的準備或處理,但希望表示並記錄他們對補丁的批准,
+那麼他們可以要求在補丁的變更日誌中添加一個 Acked-by:
+
+Acked-by:通常由受影響代碼的維護者使用,當該維護者既沒有貢獻也沒有轉發補丁時。
+
+Acked-by: 不像簽字人那樣正式。這是一個記錄,確認人至少審查了補丁,並表示接受。
+因此,補丁合併有時會手動將Acker的「Yep,looks good to me」轉換爲 Acked-By:(但
+請注意,通常最好要求一個明確的Ack)。
+
+Acked-by:不一定表示對整個補丁的確認。例如,如果一個補丁影響多個子系統,並且
+有一個:來自一個子系統維護者,那麼這通常表示只確認影響維護者代碼的部分。這裡
+應該仔細判斷。如有疑問,應參考郵件列表檔案中的原始討論。
+
+如果某人有機會對補丁進行評論,但沒有提供此類評論,您可以選擇在補丁中添加 ``Cc:``
+這是唯一一個標籤,它可以在沒有被它命名的人顯式操作的情況下添加,但它應該表明
+這個人是在補丁上抄送的。討論中包含了潛在利益相關方。
+
+Co-developed-by: 聲明補丁是由多個開發人員共同創建的;當幾個人在一個補丁上工
+作時,它用於將屬性賦予共同作者(除了 From: 所賦予的作者之外)。因爲
+Co-developed-by: 表示作者身份,所以每個共同開發人:必須緊跟在相關合作作者的
+簽名之後。標準的簽核程序要求:標記的簽核順序應儘可能反映補丁的時間歷史,而不
+管作者是通過 From :還是由 Co-developed-by: 共同開發的。值得注意的是,最後一
+個簽字人:必須始終是提交補丁的開發人員。
+
+注意,當作者也是電子郵件標題「發件人:」行中列出的人時,「From: 」 標記是可選的。
+
+作者提交的補丁程序示例::
+
+	<changelog>
+
+	Co-developed-by: First Co-Author <first@coauthor.example.org>
+	Signed-off-by: First Co-Author <first@coauthor.example.org>
+	Co-developed-by: Second Co-Author <second@coauthor.example.org>
+	Signed-off-by: Second Co-Author <second@coauthor.example.org>
+	Signed-off-by: From Author <from@author.example.org>
+
+合作開發者提交的補丁示例::
+
+	From: From Author <from@author.example.org>
+
+	<changelog>
+
+	Co-developed-by: Random Co-Author <random@coauthor.example.org>
+	Signed-off-by: Random Co-Author <random@coauthor.example.org>
+	Signed-off-by: From Author <from@author.example.org>
+	Co-developed-by: Submitting Co-Author <sub@coauthor.example.org>
+	Signed-off-by: Submitting Co-Author <sub@coauthor.example.org>
+
+
+13)使用報告人:、測試人:、審核人:、建議人:、修復人:
+--------------------------------------------------------
+
+Reported-by: 給那些發現錯誤並報告錯誤的人致謝,它希望激勵他們在將來再次幫助
+我們。請注意,如果bug是以私有方式報告的,那麼在使用Reported-by標記之前,請
+先請求權限。
+
+Tested-by: 標記表示補丁已由指定的人(在某些環境中)成功測試。這個標籤通知
+維護人員已經執行了一些測試,爲將來的補丁提供了一種定位測試人員的方法,並確
+保測試人員的信譽。
+
+Reviewed-by:相反,根據審查人的聲明,表明該補丁已被審查並被認爲是可接受的:
+
+
+審查人的監督聲明
+^^^^^^^^^^^^^^^^
+
+通過提供我的 Reviewed-by,我聲明:
+
+        (a) 我已經對這個補丁進行了一次技術審查,以評估它是否適合被包含到
+            主線內核中。
+
+        (b) 與補丁相關的任何問題、顧慮或問題都已反饋給提交者。我對提交者對
+            我的評論的回應感到滿意。
+
+        (c) 雖然這一提交可能會改進一些東西,但我相信,此時,(1)對內核
+            進行了有價值的修改,(2)沒有包含爭論中涉及的已知問題。
+
+        (d) 雖然我已經審查了補丁並認爲它是健全的,但我不會(除非另有明確
+            說明)作出任何保證或保證它將在任何給定情況下實現其規定的目的
+            或正常運行。
+
+Reviewed-by 是一種觀點聲明,即補丁是對內核的適當修改,沒有任何遺留的嚴重技術
+問題。任何感興趣的審閱者(完成工作的人)都可以爲一個補丁提供一個 Review-by
+標籤。此標籤用於向審閱者提供致謝,並通知維護者已在修補程序上完成的審閱程度。
+Reviewed-by: 當由已知了解主題區域並執行徹底檢查的審閱者提供時,通常會增加
+補丁進入內核的可能性。
+
+Suggested-by: 表示補丁的想法是由指定的人提出的,並確保將此想法歸功於指定的
+人。請注意,未經許可,不得添加此標籤,特別是如果該想法未在公共論壇上發布。
+這就是說,如果我們勤快地致謝我們的創意者,他們很有希望在未來得到鼓舞,再次
+幫助我們。
+
+Fixes: 指示補丁在以前的提交中修復了一個問題。它可以很容易地確定錯誤的來源,
+這有助於檢查錯誤修復。這個標記還幫助穩定內核團隊確定應該接收修復的穩定內核
+版本。這是指示補丁修復的錯誤的首選方法。請參閱 :ref:`tw_describe_changes`
+描述您的更改以了解更多詳細信息。
+
+.. _tw_the_canonical_patch_format:
+
+12)標準補丁格式
+----------------
+
+本節描述如何格式化補丁本身。請注意,如果您的補丁存儲在 ``Git`` 存儲庫中,則
+可以使用 ``git format-patch`` 進行正確的補丁格式設置。但是,這些工具無法創建
+必要的文本,因此請務必閱讀下面的說明。
+
+標準的補丁,標題行是::
+
+    Subject: [PATCH 001/123] 子系統:一句話概述
+
+標準補丁的信體存在如下部分:
+
+  - 一個 "from" 行指出補丁作者。後跟空行(僅當發送修補程序的人不是作者時才需要)。
+
+  - 解釋的正文,行以75列包裝,這將被複製到永久變更日誌來描述這個補丁。
+
+  - 一個空行
+
+  - 上面描述的「Signed-off-by」 行,也將出現在更改日誌中。
+
+  - 只包含 ``---`` 的標記線。
+
+  - 任何其他不適合放在變更日誌的注釋。
+
+  - 實際補丁( ``diff`` 輸出)。
+
+標題行的格式,使得對標題行按字母序排序非常的容易 - 很多 e-mail 客戶端都
+可以支持 - 因爲序列號是用零填充的,所以按數字排序和按字母排序是一樣的。
+
+e-mail 標題中的「子系統」標識哪個內核子系統將被打補丁。
+
+e-mail 標題中的「一句話概述」扼要的描述 e-mail 中的補丁。「一句話概述」
+不應該是一個文件名。對於一個補丁系列(「補丁系列」指一系列的多個相關補
+丁),不要對每個補丁都使用同樣的「一句話概述」。
+
+記住 e-mail 的「一句話概述」會成爲該補丁的全局唯一標識。它會蔓延到 git
+的改動記錄里。然後「一句話概述」會被用在開發者的討論里,用來指代這個補
+丁。用戶將希望通過 google 來搜索"一句話概述"來找到那些討論這個補丁的文
+章。當人們在兩三個月後使用諸如 ``gitk`` 或 ``git log --oneline`` 之類
+的工具查看數千個補丁時,也會很快看到它。
+
+出於這些原因,概述必須不超過70-75個字符,並且必須描述補丁的更改以及爲
+什麼需要補丁。既要簡潔又要描述性很有挑戰性,但寫得好的概述應該這樣做。
+
+概述的前綴可以用方括號括起來:「Subject: [PATCH <tag>...] <概述>」。標記
+不被視爲概述的一部分,而是描述應該如何處理補丁。如果補丁的多個版本已發
+送出來以響應評審(即「v1,v2,v3」)或「rfc」,以指示評審請求,那麼通用標記
+可能包括版本描述符。如果一個補丁系列中有四個補丁,那麼各個補丁可以這樣
+編號:1/4、2/4、3/4、4/4。這可以確保開發人員了解補丁應用的順序,並且他們
+已經查看或應用了補丁系列中的所有補丁。
+
+一些標題的例子::
+
+    Subject: [patch 2/5] ext2: improve scalability of bitmap searching
+    Subject: [PATCHv2 001/207] x86: fix eflags tracking
+
+"From" 行是信體裡的最上面一行,具有如下格式:
+        From: Patch Author <author@example.com>
+
+"From" 行指明在永久改動日誌里,誰會被確認爲作者。如果沒有 "From" 行,那
+麼郵件頭裡的 "From: " 行會被用來決定改動日誌中的作者。
+
+說明的主題將會被提交到永久的原始碼改動日誌里,因此對那些早已經不記得和
+這個補丁相關的討論細節的有能力的讀者來說,是有意義的。包括補丁程序定位
+錯誤的(內核日誌消息、OOPS消息等)症狀,對於搜索提交日誌以尋找適用補丁的人
+尤其有用。如果一個補丁修復了一個編譯失敗,那麼可能不需要包含所有編譯失敗;
+只要足夠讓搜索補丁的人能夠找到它就行了。與概述一樣,既要簡潔又要描述性。
+
+"---" 標記行對於補丁處理工具要找到哪裡是改動日誌信息的結束,是不可缺少
+的。
+
+對於 "---" 標記之後的額外註解,一個好的用途就是用來寫 diffstat,用來顯
+示修改了什麼文件和每個文件都增加和刪除了多少行。diffstat 對於比較大的補
+丁特別有用。其餘那些只是和時刻或者開發者相關的註解,不合適放到永久的改
+動日誌里的,也應該放這裡。
+使用 diffstat的選項 "-p 1 -w 70" 這樣文件名就會從內核原始碼樹的目錄開始
+,不會占用太寬的空間(很容易適合80列的寬度,也許會有一些縮進。)
+
+在後面的參考資料中能看到適當的補丁格式的更多細節。
+
+.. _tw_explicit_in_reply_to:
+
+15) 明確回覆郵件頭(In-Reply-To)
+-------------------------------
+
+手動添加回復補丁的的標題頭(In-Reply_To:) 是有幫助的(例如,使用 ``git send-email`` )
+將補丁與以前的相關討論關聯起來,例如,將bug修復程序連結到電子郵件和bug報告。
+但是,對於多補丁系列,最好避免在回復時使用連結到該系列的舊版本。這樣,
+補丁的多個版本就不會成爲電子郵件客戶端中無法管理的引用序列。如果連結有用,
+可以使用 https://lkml.kernel.org/ 重定向器(例如,在封面電子郵件文本中)
+連結到補丁系列的早期版本。
+
+16) 發送git pull請求
+--------------------
+
+如果您有一系列補丁,那麼讓維護人員通過git pull操作將它們直接拉入子系統存儲
+庫可能是最方便的。但是,請注意,從開發人員那裡獲取補丁比從郵件列表中獲取補
+丁需要更高的信任度。因此,許多子系統維護人員不願意接受請求,特別是來自新的
+未知開發人員的請求。如果有疑問,您可以在封面郵件中使用pull 請求作爲補丁系列
+正常發布的一個選項,讓維護人員可以選擇使用其中之一。
+
+pull 請求的主題行中應該有[Git Pull]。請求本身應該在一行中包含存儲庫名稱和
+感興趣的分支;它應該看起來像::
+
+  Please pull from
+
+      git://jdelvare.pck.nerim.net/jdelvare-2.6 i2c-for-linus
+
+  to get these changes:
+
+
+pull 請求還應該包含一條整體消息,說明請求中將包含什麼,一個補丁本身的 ``Git shortlog``
+以及一個顯示補丁系列整體效果的 ``diffstat`` 。當然,將所有這些信息收集在一起
+的最簡單方法是讓 ``git`` 使用 ``git request-pull`` 命令爲您完成這些工作。
+
+一些維護人員(包括Linus)希望看到來自已簽名提交的請求;這增加了他們對你的
+請求信心。特別是,在沒有簽名標籤的情況下,Linus 不會從像 Github 這樣的公共
+託管站點拉請求。
+
+創建此類簽名的第一步是生成一個 GNRPG 密鑰,並由一個或多個核心內核開發人員對
+其進行簽名。這一步對新開發人員來說可能很困難,但沒有辦法繞過它。參加會議是
+找到可以簽署您的密鑰的開發人員的好方法。
+
+一旦您在Git 中準備了一個您希望有人拉的補丁系列,就用 ``git tag -s`` 創建一
+個簽名標記。這將創建一個新標記,標識該系列中的最後一次提交,並包含用您的私
+鑰創建的簽名。您還可以將changelog樣式的消息添加到標記中;這是一個描述拉請求
+整體效果的理想位置。
+
+如果維護人員將要從中提取的樹不是您正在使用的存儲庫,請不要忘記將已簽名的標記
+顯式推送到公共樹。
+
+生成拉請求時,請使用已簽名的標記作爲目標。這樣的命令可以實現::
+
+  git request-pull master git://my.public.tree/linux.git my-signed-tag
+
+參考文獻
+--------
+
+Andrew Morton, "The perfect patch" (tpp).
+  <https://www.ozlabs.org/~akpm/stuff/tpp.txt>
+
+Jeff Garzik, "Linux kernel patch submission format".
+  <https://web.archive.org/web/20180829112450/http://linux.yyz.us/patch-format.html>
+
+Greg Kroah-Hartman, "How to piss off a kernel subsystem maintainer".
+  <http://www.kroah.com/log/linux/maintainer.html>
+
+  <http://www.kroah.com/log/linux/maintainer-02.html>
+
+  <http://www.kroah.com/log/linux/maintainer-03.html>
+
+  <http://www.kroah.com/log/linux/maintainer-04.html>
+
+  <http://www.kroah.com/log/linux/maintainer-05.html>
+
+  <http://www.kroah.com/log/linux/maintainer-06.html>
+
+NO!!!! No more huge patch bombs to linux-kernel@vger.kernel.org people!
+  <https://lore.kernel.org/r/20050711.125305.08322243.davem@davemloft.net>
+
+Kernel Documentation/process/coding-style.rst:
+  :ref:`Documentation/translations/zh_TW/process/coding-style.rst <tw_codingstyle>`
+
+Linus Torvalds's mail on the canonical patch format:
+  <https://lore.kernel.org/r/Pine.LNX.4.58.0504071023190.28951@ppc970.osdl.org>
+
+Andi Kleen, "On submitting kernel patches"
+  Some strategies to get difficult or controversial changes in.
+
+  http://halobates.de/on-submitting-patches.pdf
+
diff --git a/Documentation/translations/zh_TW/process/volatile-considered-harmful.rst b/Documentation/translations/zh_TW/process/volatile-considered-harmful.rst
new file mode 100644
index 000000000000..097fe80352cb
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/volatile-considered-harmful.rst
@@ -0,0 +1,110 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _tw_volatile_considered_harmful:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/volatile-considered-harmful.rst
+           <volatile_considered_harmful>`
+
+如果想評論或更新本文的內容,請直接聯繫原文檔的維護者。如果你使用英文
+交流有困難的話,也可以向中文版維護者求助。如果本翻譯更新不及時或者翻
+譯存在問題,請聯繫中文版維護者::
+
+        英文版維護者: Jonathan Corbet <corbet@lwn.net>
+        中文版維護者: 伍鵬  Bryan Wu <bryan.wu@analog.com>
+        中文版翻譯者: 伍鵬  Bryan Wu <bryan.wu@analog.com>
+        中文版校譯者: 張漢輝  Eugene Teo <eugeneteo@kernel.sg>
+                       楊瑞  Dave Young <hidave.darkstar@gmail.com>
+                       時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+                       胡皓文 Hu Haowen <src.res@email.cn>
+
+爲什麼不應該使用「volatile」類型
+================================
+
+C程式設計師通常認爲volatile表示某個變量可以在當前執行的線程之外被改變;因此,在內核
+中用到共享數據結構時,常常會有C程式設計師喜歡使用volatile這類變量。換句話說,他們經
+常會把volatile類型看成某種簡易的原子變量,當然它們不是。在內核中使用volatile幾
+乎總是錯誤的;本文檔將解釋爲什麼這樣。
+
+理解volatile的關鍵是知道它的目的是用來消除優化,實際上很少有人真正需要這樣的應
+用。在內核中,程式設計師必須防止意外的並發訪問破壞共享的數據結構,這其實是一個完全
+不同的任務。用來防止意外並發訪問的保護措施,可以更加高效的避免大多數優化相關的
+問題。
+
+像volatile一樣,內核提供了很多原語來保證並發訪問時的數據安全(自旋鎖, 互斥量,內
+存屏障等等),同樣可以防止意外的優化。如果可以正確使用這些內核原語,那麼就沒有
+必要再使用volatile。如果仍然必須使用volatile,那麼幾乎可以肯定在代碼的某處有一
+個bug。在正確設計的內核代碼中,volatile能帶來的僅僅是使事情變慢。
+
+思考一下這段典型的內核代碼::
+
+    spin_lock(&the_lock);
+    do_something_on(&shared_data);
+    do_something_else_with(&shared_data);
+    spin_unlock(&the_lock);
+
+如果所有的代碼都遵循加鎖規則,當持有the_lock的時候,不可能意外的改變shared_data的
+值。任何可能訪問該數據的其他代碼都會在這個鎖上等待。自旋鎖原語跟內存屏障一樣—— 它
+們顯式的用來書寫成這樣 —— 意味著數據訪問不會跨越它們而被優化。所以本來編譯器認爲
+它知道在shared_data裡面將有什麼,但是因爲spin_lock()調用跟內存屏障一樣,會強制編
+譯器忘記它所知道的一切。那麼在訪問這些數據時不會有優化的問題。
+
+如果shared_data被聲名爲volatile,鎖操作將仍然是必須的。就算我們知道沒有其他人正在
+使用它,編譯器也將被阻止優化對臨界區內shared_data的訪問。在鎖有效的同時,
+shared_data不是volatile的。在處理共享數據的時候,適當的鎖操作可以不再需要
+volatile —— 並且是有潛在危害的。
+
+volatile的存儲類型最初是爲那些內存映射的I/O寄存器而定義。在內核里,寄存器訪問也應
+該被鎖保護,但是人們也不希望編譯器「優化」臨界區內的寄存器訪問。內核里I/O的內存訪問
+是通過訪問函數完成的;不贊成通過指針對I/O內存的直接訪問,並且不是在所有體系架構上
+都能工作。那些訪問函數正是爲了防止意外優化而寫的,因此,再說一次,volatile類型不
+是必需的。
+
+另一種引起用戶可能使用volatile的情況是當處理器正忙著等待一個變量的值。正確執行一
+個忙等待的方法是::
+
+    while (my_variable != what_i_want)
+        cpu_relax();
+
+cpu_relax()調用會降低CPU的能量消耗或者讓位於超線程雙處理器;它也作爲內存屏障一樣出
+現,所以,再一次,volatile不是必需的。當然,忙等待一開始就是一種反常規的做法。
+
+在內核中,一些稀少的情況下volatile仍然是有意義的:
+
+  - 在一些體系架構的系統上,允許直接的I/0內存訪問,那麼前面提到的訪問函數可以使用
+    volatile。基本上,每一個訪問函數調用它自己都是一個小的臨界區域並且保證了按照
+    程式設計師期望的那樣發生訪問操作。
+
+  - 某些會改變內存的內聯彙編代碼雖然沒有什麼其他明顯的附作用,但是有被GCC刪除的可
+    能性。在彙編聲明中加上volatile關鍵字可以防止這種刪除操作。
+
+  - Jiffies變量是一種特殊情況,雖然每次引用它的時候都可以有不同的值,但讀jiffies
+    變量時不需要任何特殊的加鎖保護。所以jiffies變量可以使用volatile,但是不贊成
+    其他跟jiffies相同類型變量使用volatile。Jiffies被認爲是一種「愚蠢的遺留物"
+    (Linus的話)因爲解決這個問題比保持現狀要麻煩的多。
+
+  - 由於某些I/0設備可能會修改連續一致的內存,所以有時,指向連續一致內存的數據結構
+    的指針需要正確的使用volatile。網絡適配器使用的環狀緩存區正是這類情形的一個例
+    子,其中適配器用改變指針來表示哪些描述符已經處理過了。
+
+對於大多代碼,上述幾種可以使用volatile的情況都不適用。所以,使用volatile是一種
+bug並且需要對這樣的代碼額外仔細檢查。那些試圖使用volatile的開發人員需要退一步想想
+他們真正想實現的是什麼。
+
+非常歡迎刪除volatile變量的補丁 - 只要證明這些補丁完整的考慮了並發問題。
+
+注釋
+----
+
+[1] https://lwn.net/Articles/233481/
+[2] https://lwn.net/Articles/233482/
+
+致謝
+----
+
+最初由Randy Dunlap推動並作初步研究
+由Jonathan Corbet撰寫
+參考Satyam Sharma,Johannes Stezenbach,Jesper Juhl,Heikki Orsila,
+H. Peter Anvin,Philipp Hahn和Stefan Richter的意見改善了本檔。
+
-- 
2.25.1


^ permalink raw reply related	[relevance 1%]

* [PATCH v6 2/3] docs/zh_TW: add translations for zh_TW/process
  @ 2021-07-27 16:15  1% ` Hu Haowen
  0 siblings, 0 replies; 200+ results
From: Hu Haowen @ 2021-07-27 16:15 UTC (permalink / raw)
  To: corbet; +Cc: panyunwang849, linux-doc-tw, linux-doc, linux-kernel

Create new translations for zh_TW/process and link them to index.

Signed-off-by: Hu Haowen <src.res@email.cn>
---
 Documentation/translations/zh_TW/index.rst    |  10 +-
 .../translations/zh_TW/process/1.Intro.rst    | 199 ++++
 .../translations/zh_TW/process/2.Process.rst  | 369 +++++++
 .../zh_TW/process/3.Early-stage.rst           | 172 ++++
 .../translations/zh_TW/process/4.Coding.rst   | 297 ++++++
 .../translations/zh_TW/process/5.Posting.rst  | 251 +++++
 .../zh_TW/process/6.Followthrough.rst         | 156 +++
 .../zh_TW/process/7.AdvancedTopics.rst        | 137 +++
 .../zh_TW/process/8.Conclusion.rst            |  74 ++
 .../code-of-conduct-interpretation.rst        | 112 ++
 .../zh_TW/process/code-of-conduct.rst         |  76 ++
 .../zh_TW/process/coding-style.rst            | 958 ++++++++++++++++++
 .../zh_TW/process/development-process.rst     |  30 +
 .../zh_TW/process/email-clients.rst           | 252 +++++
 .../process/embargoed-hardware-issues.rst     | 232 +++++
 .../translations/zh_TW/process/howto.rst      | 500 +++++++++
 .../translations/zh_TW/process/index.rst      |  67 ++
 .../zh_TW/process/kernel-driver-statement.rst | 203 ++++
 .../process/kernel-enforcement-statement.rst  | 155 +++
 .../zh_TW/process/license-rules.rst           | 374 +++++++
 .../zh_TW/process/magic-number.rst            | 148 +++
 .../zh_TW/process/management-style.rst        | 211 ++++
 .../zh_TW/process/programming-language.rst    |  76 ++
 .../zh_TW/process/stable-api-nonsense.rst     | 159 +++
 .../zh_TW/process/stable-kernel-rules.rst     |  68 ++
 .../zh_TW/process/submit-checklist.rst        | 109 ++
 .../zh_TW/process/submitting-drivers.rst      | 164 +++
 .../zh_TW/process/submitting-patches.rst      | 686 +++++++++++++
 .../process/volatile-considered-harmful.rst   | 110 ++
 29 files changed, 6351 insertions(+), 4 deletions(-)
 create mode 100644 Documentation/translations/zh_TW/process/1.Intro.rst
 create mode 100644 Documentation/translations/zh_TW/process/2.Process.rst
 create mode 100644 Documentation/translations/zh_TW/process/3.Early-stage.rst
 create mode 100644 Documentation/translations/zh_TW/process/4.Coding.rst
 create mode 100644 Documentation/translations/zh_TW/process/5.Posting.rst
 create mode 100644 Documentation/translations/zh_TW/process/6.Followthrough.rst
 create mode 100644 Documentation/translations/zh_TW/process/7.AdvancedTopics.rst
 create mode 100644 Documentation/translations/zh_TW/process/8.Conclusion.rst
 create mode 100644 Documentation/translations/zh_TW/process/code-of-conduct-interpretation.rst
 create mode 100644 Documentation/translations/zh_TW/process/code-of-conduct.rst
 create mode 100644 Documentation/translations/zh_TW/process/coding-style.rst
 create mode 100644 Documentation/translations/zh_TW/process/development-process.rst
 create mode 100644 Documentation/translations/zh_TW/process/email-clients.rst
 create mode 100644 Documentation/translations/zh_TW/process/embargoed-hardware-issues.rst
 create mode 100644 Documentation/translations/zh_TW/process/howto.rst
 create mode 100644 Documentation/translations/zh_TW/process/index.rst
 create mode 100644 Documentation/translations/zh_TW/process/kernel-driver-statement.rst
 create mode 100644 Documentation/translations/zh_TW/process/kernel-enforcement-statement.rst
 create mode 100644 Documentation/translations/zh_TW/process/license-rules.rst
 create mode 100644 Documentation/translations/zh_TW/process/magic-number.rst
 create mode 100644 Documentation/translations/zh_TW/process/management-style.rst
 create mode 100644 Documentation/translations/zh_TW/process/programming-language.rst
 create mode 100644 Documentation/translations/zh_TW/process/stable-api-nonsense.rst
 create mode 100644 Documentation/translations/zh_TW/process/stable-kernel-rules.rst
 create mode 100644 Documentation/translations/zh_TW/process/submit-checklist.rst
 create mode 100644 Documentation/translations/zh_TW/process/submitting-drivers.rst
 create mode 100644 Documentation/translations/zh_TW/process/submitting-patches.rst
 create mode 100644 Documentation/translations/zh_TW/process/volatile-considered-harmful.rst

diff --git a/Documentation/translations/zh_TW/index.rst b/Documentation/translations/zh_TW/index.rst
index cab58e428825..76981b2111f6 100644
--- a/Documentation/translations/zh_TW/index.rst
+++ b/Documentation/translations/zh_TW/index.rst
@@ -22,9 +22,7 @@
 下面的文檔介紹了Linux內核原始碼的許可證(GPLv2)、如何在原始碼樹中正確標記
 單個文件的許可證、以及指向完整許可證文本的連結。
 
-TODOList:
-
-* Documentation/translations/zh_TW/process/license-rules.rst
+Documentation/translations/zh_TW/process/license-rules.rst
 
 用戶文檔
 --------
@@ -67,9 +65,13 @@ TODOlist:
 開發人員做出貢獻。與任何大型社區一樣,知道如何完成任務將使得更改合併的過程
 變得更加容易。
 
+.. toctree::
+   :maxdepth: 2
+
+   process/index
+
 TODOList:
 
-* process/index
 * dev-tools/index
 * doc-guide/index
 * kernel-hacking/index
diff --git a/Documentation/translations/zh_TW/process/1.Intro.rst b/Documentation/translations/zh_TW/process/1.Intro.rst
new file mode 100644
index 000000000000..ca2b931be6c5
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/1.Intro.rst
@@ -0,0 +1,199 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/1.Intro.rst <development_process_intro>`
+
+:Translator:
+
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+
+:校譯:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+.. _tw_development_process_intro:
+
+引言
+====
+
+內容提要
+--------
+
+本節的其餘部分涵蓋了內核開發的過程,以及開發人員及其僱主在這方面可能遇到的
+各種問題。有很多原因使內核代碼應被合併到正式的(「主線」)內核中,包括對用戶
+的自動可用性、多種形式的社區支持以及影響內核開發方向的能力。提供給Linux內核
+的代碼必須在與GPL兼容的許可證下可用。
+
+:ref:`tw_development_process` 介紹了開發過程、內核發布周期和合併窗口的機制。
+涵蓋了補丁開發、審查和合併周期中的各個階段。還有一些關於工具和郵件列表的討論?
+鼓勵希望開始內核開發的開發人員跟蹤並修復缺陷以作爲初步練習。
+
+
+:ref:`tw_development_early_stage` 包括項目的早期規劃,重點是儘快讓開發社區
+參與進來。
+
+:ref:`tw_development_coding` 是關於編程過程的;介紹了其他開發人員遇到的幾個
+陷阱。也涵蓋了對補丁的一些要求,並且介紹了一些工具,這些工具有助於確保內核
+補丁是正確的。
+
+:ref:`tw_development_posting` 描述發布補丁以供評審的過程。爲了讓開發社區能
+認真對待,補丁必須被正確格式化和描述,並且必須發送到正確的地方。遵循本節中的
+建議有助於確保您的工作能被較好地接納。
+
+:ref:`tw_development_followthrough` 介紹了發布補丁之後發生的事情;工作在這時
+還遠遠沒有完成。與審閱者一起工作是開發過程中的一個重要部分;本節提供了一些
+關於如何在這個重要階段避免問題的提示。當補丁被合併到主線中時,開發人員要注意
+不要假定任務已經完成。
+
+:ref:`tw_development_advancedtopics` 介紹了兩個「高級」主題:使用Git管理補丁
+和查看其他人發布的補丁。
+
+:ref:`tw_development_conclusion` 總結了有關內核開發的更多信息,附帶有相關資源
+連結。
+
+這個文檔是關於什麼的
+--------------------
+
+Linux內核有超過800萬行代碼,每個版本的貢獻者超過1000人,是現存最大、最活躍的
+免費軟體項目之一。從1991年開始,這個內核已經發展成爲一個最好的作業系統組件,
+運行在袖珍數位音樂播放器、桌上型電腦、現存最大的超級計算機以及所有類型的系統上。
+它是一種適用於幾乎任何情況的健壯、高效和可擴展的解決方案。
+
+隨著Linux的發展,希望參與其開發的開發人員(和公司)的數量也在增加。硬體供應商
+希望確保Linux能夠很好地支持他們的產品,使這些產品對Linux用戶具有吸引力。嵌入
+式系統供應商使用Linux作爲集成產品的組件,希望Linux能夠儘可能地勝任手頭的任務。
+分銷商和其他基於Linux的軟體供應商切實關心Linux內核的功能、性能和可靠性。最終
+用戶也常常希望修改Linux,使之能更好地滿足他們的需求。
+
+Linux最引人注目的特性之一是這些開發人員可以訪問它;任何具備必要技能的人都可以
+改進Linux並影響其開發方向。專有產品不能提供這種開放性,這是自由軟體的一個特點。
+如果有什麼不同的話,那就是內核比大多數其他自由軟體項目更開放。一個典型的三個
+月內核開發周期可以涉及1000多個開發人員,他們爲100多個不同的公司(或者根本不
+隸屬公司)工作。
+
+與內核開發社區合作並不是特別困難。但儘管如此,仍有許多潛在的貢獻者在嘗試做
+內核工作時遇到了困難。內核社區已經發展出自己獨特的操作方式,使其能夠在每天
+都要更改數千行代碼的環境中順利運行(並生成高質量的產品)。因此,Linux內核開發
+過程與專有的開發模式有很大的不同也就不足爲奇了。
+
+對於新開發人員來說,內核的開發過程可能會讓人感到奇怪和恐懼,但這背後有充分的
+理由和堅實的經驗。一個不了解內核社區工作方式的開發人員(或者更糟的是,他們
+試圖拋棄或規避之)會得到令人沮喪的體驗。開發社區在幫助那些試圖學習的人的同時,
+沒有時間幫助那些不願意傾聽或不關心開發過程的人。
+
+希望閱讀本文的人能夠避免這種令人沮喪的經歷。這些材料很長,但閱讀它們時所做的
+努力會在短時間內得到回報。開發社區總是需要能讓內核變更好的開發人員;下面的
+文字應該幫助您或爲您工作的人員加入我們的社區。
+
+致謝
+----
+
+本文檔由Jonathan Corbet <corbet@lwn.net> 撰寫。以下人員的建議使之更爲完善:
+Johannes Berg, James Berry, Alex Chiang, Roland Dreier, Randy Dunlap,
+Jake Edge, Jiri Kosina, Matt Mackall, Arthur Marsh, Amanda McPherson,
+Andrew Morton, Andrew Price, Tsugikazu Shibata 和 Jochen Voß 。
+
+這項工作得到了Linux基金會的支持,特別感謝Amanda McPherson,他看到了這項工作
+的價值並將其變成現實。
+
+代碼進入主線的重要性
+--------------------
+
+有些公司和開發人員偶爾會想,爲什麼他們要費心學習如何與內核社區合作,並將代碼
+放入主線內核(「主線」是由Linus Torvalds維護的內核,Linux發行商將其用作基礎)。
+在短期內,貢獻代碼看起來像是一種可以避免的開銷;維護獨立代碼並直接支持用戶
+似乎更容易。事實上,保持代碼獨立(「樹外」)是在經濟上是錯誤的。
+
+爲了說明樹外代碼成本,下面給出內核開發過程的一些相關方面;本文稍後將更詳細地
+討論其中的大部分內容。請考慮:
+
+- 所有Linux用戶都可以使用合併到主線內核中的代碼。它將自動出現在所有啓用它的
+  發行版上。無需驅動程序磁碟、額外下載,也不需要爲多個發行版的多個版本提供
+  支持;這一切將方便所有開發人員和用戶。併入主線解決了大量的分發和支持問題。
+
+- 當內核開發人員努力維護一個穩定的用戶空間接口時,內核內部API處於不斷變化之中。
+  不維持穩定的內部接口是一個慎重的設計決策;它允許在任何時候進行基本的改進,
+  並產出更高質量的代碼。但該策略導致結果是,若要使用新的內核,任何樹外代碼都
+  需要持續的維護。維護樹外代碼會需要大量的工作才能使代碼保持正常運行。
+
+  相反,位於主線中的代碼不需要這樣做,因爲基本規則要求進行API更改的任何開發
+  人員也必須修復由於該更改而破壞的任何代碼。因此,合併到主線中的代碼大大降低
+  了維護成本。
+
+- 除此之外,內核中的代碼通常會被其他開發人員改進。您授權的用戶社區和客戶對您
+  產品的改進可能會令人驚喜。
+
+- 內核代碼在合併到主線之前和之後都要經過審查。無論原始開發人員的技能有多強,
+  這個審查過程總是能找到改進代碼的方法。審查經常發現嚴重的錯誤和安全問題。
+  對於在封閉環境中開發的代碼尤其如此;這種代碼從外部開發人員的審查中獲益匪淺。
+  樹外代碼是低質量代碼。
+
+- 參與開發過程是您影響內核開發方向的方式。旁觀者的抱怨會被聽到,但是活躍的
+  開發人員有更強的聲音——並且能夠實現使內核更好地滿足其需求的更改。
+
+- 當單獨維護代碼時,總是存在第三方爲類似功能提供不同實現的可能性。如果發生
+  這種情況,合併代碼將變得更加困難——甚至成爲不可能。之後,您將面臨以下令人
+  不快的選擇:(1)無限期地維護樹外的非標準特性,或(2)放棄代碼並將用戶遷移
+  到樹內版本。
+
+- 代碼的貢獻是使整個流程工作的根本。通過貢獻代碼,您可以向內核添加新功能,並
+  提供其他內核開發人員使用的功能和示例。如果您已經爲Linux開發了代碼(或者正在
+  考慮這樣做),那麼您顯然對這個平台的持續成功感興趣;貢獻代碼是確保成功的
+  最好方法之一。
+
+上述所有理由都適用於任何樹外內核代碼,包括以專有的、僅二進位形式分發的代碼。
+然而,在考慮任何類型的純二進位內核代碼分布之前,還需要考慮其他因素。包括:
+
+- 圍繞專有內核模塊分發的法律問題其實較爲模糊;相當多的內核版權所有者認爲,
+  大多數僅二進位的模塊是內核的派生產品,因此,它們的分發違反了GNU通用公共
+  許可證(下面將詳細介紹)。本文作者不是律師,本文檔中的任何內容都不可能被
+  視爲法律建議。封閉原始碼模塊的真實法律地位只能由法院決定。但不管怎樣,困擾
+  這些模塊的不確定性仍然存在。
+
+- 二進位模塊大大增加了調試內核問題的難度,以至於大多數內核開發人員甚至都不會
+  嘗試。因此,只分發二進位模塊將使您的用戶更難從社區獲得支持。
+
+- 對於僅二進位的模塊的發行者來說,支持也更加困難,他們必須爲他們希望支持的
+  每個發行版和每個內核版本提供不同版本的模塊。爲了提供較爲全面的覆蓋範圍,
+  可能需要一個模塊的幾十個構建,並且每次升級內核時,您的用戶都必須單獨升級
+  這些模塊。
+
+- 上面提到的關於代碼評審的所有問題都更加存在於封閉原始碼中。由於該代碼根本
+  不可得,因此社區無法對其進行審查,毫無疑問,它將存在嚴重問題。
+
+尤其是嵌入式系統的製造商,可能會傾向於忽視本節中所說的大部分內容;因爲他們
+相信自己正在商用一種使用凍結內核版本的獨立產品,在發布後不需要再進行開發。
+這個論點忽略了廣泛的代碼審查的價值以及允許用戶向產品添加功能的價值。但這些
+產品的商業壽命有限,之後必須發布新版本的產品。在這一點上,代碼在主線上並得到
+良好維護的供應商將能夠更好地占位,以使新產品快速上市。
+
+許可
+----
+
+代碼是根據一些許可證提供給Linux內核的,但是所有代碼都必須與GNU通用公共許可
+證(GPLV2)的版本2兼容,該版本是覆蓋整個內核分發的許可證。在實踐中,這意味
+著所有代碼貢獻都由GPLv2(可選地,語言允許在更高版本的GPL下分發)或3子句BSD
+許可(New BSD License,譯者注)覆蓋。任何不包含在兼容許可證中的貢獻都不會
+被接受到內核中。
+
+貢獻給內核的代碼不需要(或請求)版權分配。合併到主線內核中的所有代碼都保留
+其原始所有權;因此,內核現在擁有數千個所有者。
+
+這種所有權結構也暗示著,任何改變內核許可的嘗試都註定會失敗。很少有實際情況
+可以獲得所有版權所有者的同意(或者從內核中刪除他們的代碼)。因此,尤其是在
+可預見的將來,許可證不大可能遷移到GPL的版本3。
+
+所有貢獻給內核的代碼都必須是合法的免費軟體。因此,不接受匿名(或化名)貢獻
+者的代碼。所有貢獻者都需要在他們的代碼上「sign off(簽發)」,聲明代碼可以
+在GPL下與內核一起分發。無法提供未被其所有者許可爲免費軟體的代碼,或可能爲
+內核造成版權相關問題的代碼(例如,由缺乏適當保護的反向工程工作派生的代碼)
+不能被接受。
+
+有關版權問題的提問在Linux開發郵件列表中很常見。這樣的問題通常會得到不少答案,
+但請記住,回答這些問題的人不是律師,不能提供法律諮詢。如果您有關於Linux原始碼
+的法律問題,沒有什麼可以代替諮詢了解這一領域的律師。依賴從技術郵件列表中獲得
+的答案是一件冒險的事情。
+
+
diff --git a/Documentation/translations/zh_TW/process/2.Process.rst b/Documentation/translations/zh_TW/process/2.Process.rst
new file mode 100644
index 000000000000..b01cdd3a39ae
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/2.Process.rst
@@ -0,0 +1,369 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/2.Process.rst <development_process>`
+
+:Translator:
+
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+
+:校譯:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+.. _tw_development_process:
+
+開發流程如何進行
+================
+
+90年代早期的Linux內核開發是一件相當鬆散的事情,涉及的用戶和開發人員相對較少。
+由於擁有數以百萬計的用戶羣,且每年有大約2000名開發人員參與進來,內核因此必須
+發展出許多既定流程來保證開發的順利進行。要參與到流程中來,需要對此流程的進行
+方式有一個紮實的理解。
+
+總覽
+----
+
+內核開發人員使用一個鬆散的基於時間的發布過程,每兩到三個月發布一次新的主要
+內核版本。最近的發布歷史記錄如下:
+
+	======  =================
+	5.0	2019年3月3日
+	5.1	2019年5月5日
+	5.2	2019年7月7日
+	5.3	2019年9月15日
+	5.4	2019年11月24日
+	5.5	2020年1月6日
+	======  =================
+
+每個5.x版本都是一個主要的內核版本,具有新特性、內部API更改等等。一個典型的5.x
+版本包含大約13000個變更集,變更了幾十萬行代碼。因此,5.x是Linux內核開發的前
+沿;內核使用滾動開發模型,不斷集成重大變化。
+
+對於每個版本的補丁合併,遵循一個相對簡單的規則。在每個開發周期的開頭,「合併
+窗口」被打開。這時,被認爲足夠穩定(並且被開發社區接受)的代碼被合併到主線內
+核中。在這段時間內,新開發周期的大部分變更(以及所有主要變更)將以接近每天
+1000次變更(「補丁」或「變更集」)的速度合併。
+
+(順便說一句,值得注意的是,合併窗口期間集成的更改並不是憑空產生的;它們是經
+提前收集、測試和分級的。稍後將詳細描述該過程的工作方式。)
+
+合併窗口持續大約兩周。在這段時間結束時,LinusTorvalds將聲明窗口已關閉,並
+釋放第一個「rc」內核。例如,對於目標爲5.6的內核,在合併窗口結束時發生的釋放
+將被稱爲5.6-rc1。-rc1 版本是一個信號,表示合併新特性的時間已經過去,穩定下一
+個內核的時間已經到來。
+
+在接下來的6到10周內,只有修復問題的補丁才應該提交給主線。有時會允許更大的
+更改,但這種情況很少發生;試圖在合併窗口外合併新功能的開發人員往往受不到
+友好的接待。一般來說,如果您錯過了給定特性的合併窗口,最好的做法是等待下一
+個開發周期。(偶爾會對未支持硬體的驅動程序進行例外;如果它們不改變已有代碼,
+則不會導致回歸,應該可以隨時被安全地加入)。
+
+隨著修復程序進入主線,補丁速度將隨著時間的推移而變慢。Linus大約每周發布一次
+新的-rc內核;在內核被認爲足夠穩定並最終發布前,一般會達到-rc6到-rc9之間。
+然後,整個過程又重新開始了。
+
+例如,這裡是5.4的開發周期進行情況(2019年):
+
+	==============  ==============================
+	九月 15         5.3 穩定版發布
+	九月 30         5.4-rc1 合併窗口關閉
+	十月 6          5.4-rc2
+	十月 13         5.4-rc3
+	十月 20         5.4-rc4
+	十月 27         5.4-rc5
+	十一月 3        5.4-rc6
+	十一月 10       5.4-rc7
+	十一月 17       5.4-rc8
+	十一月 24       5.4 穩定版發布
+	==============  ==============================
+
+開發人員如何決定何時結束開發周期並創建穩定版本?最重要的指標是以前版本的
+回歸列表。不歡迎出現任何錯誤,但是那些破壞了以前能工作的系統的錯誤被認爲是
+特別嚴重的。因此,導致回歸的補丁是不受歡迎的,很可能在穩定期內刪除。
+
+開發人員的目標是在穩定發布之前修復所有已知的回歸。在現實世界中,這種完美是
+很難實現的;在這種規模的項目中,變數太多了。需要說明的是,延遲最終版本只會
+使問題變得更糟;等待下一個合併窗口的更改將變多,導致下次出現更多的回歸錯誤。
+因此,大多數5.x內核都有一些已知的回歸錯誤,不過,希望沒有一個是嚴重的。
+
+一旦一個穩定的版本發布,它的持續維護工作就被移交給「穩定團隊」,目前由
+Greg Kroah-Hartman領導。穩定團隊將使用5.x.y編號方案不定期地發布穩定版本的
+更新。要合入更新版本,補丁必須(1)修復一個重要的缺陷,且(2)已經合併到
+下一個開發版本主線中。內核通常會在其初始版本後的一個以上的開發周期內收到
+穩定版更新。例如,5.2內核的歷史如下(2019年):
+
+	==============  ===============================
+        七月 7 	        5.2 穩定版發布
+	七月 13	        5.2.1
+	七月 21	        5.2.2
+	七月 26	        5.2.3
+	七月 28	        5.2.4
+	七月 31	        5.2.5
+	...	        ...
+	十月 11         5.2.21
+	==============  ===============================
+
+5.2.21是5.2版本的最終穩定更新。
+
+有些內核被指定爲「長期」內核;它們將得到更長時間的支持。在本文中,當前的長期
+內核及其維護者是:
+
+	======  ================================	================
+	3.16	Ben Hutchings				(長期穩定內核)
+	4.4	Greg Kroah-Hartman & Sasha Levin	(長期穩定內核)
+	4.9	Greg Kroah-Hartman & Sasha Levin
+	4.14	Greg Kroah-Hartman & Sasha Levin
+	4.19	Greg Kroah-Hartman & Sasha Levin
+	5.4	Greg Kroah-Hartman & Sasha Levin
+	======  ================================	================
+
+長期支持內核的選擇純粹是維護人員是否有需求和時間來維護該版本的問題。
+目前還沒有爲即將發布的任何特定版本提供長期支持的已知計劃。
+
+補丁的生命周期
+--------------
+
+補丁不會直接從開發人員的鍵盤進入主線內核。相反,有一個稍微複雜(如果有些非
+正式)的過程,旨在確保對每個補丁進行質量審查,並確保每個補丁實現了一個在主線
+中需要的更改。對於小的修復,這個過程可能會很快完成,,而對於較大或有爭議的
+變更,可能會持續數年。許多開發人員的沮喪來自於對這個過程缺乏理解或者試圖繞過它。
+
+爲了減少這種挫敗,本文將描述補丁如何進入內核。下面的介紹以一種較爲理想化的
+方式描述了這個過程。更詳細的過程將在後面的章節中介紹。
+
+補丁通常要經歷以下階段:
+
+- 設計。這就是補丁的真正需求——以及滿足這些需求的方式——所在。設計工作通常
+  是在不涉及社區的情況下完成的,但是如果可能的話,最好是在公開的情況下完成
+  這項工作;這樣可以節省很多稍後再重新設計的時間。
+
+- 早期評審。補丁被發布到相關的郵件列表中,列表中的開發人員會回復他們可能有
+  的任何評論。如果一切順利的話,這個過程應該會發現補丁的任何主要問題。
+
+- 更廣泛的評審。當補丁接近準備好納入主線時,它應該被相關的子系統維護人員
+  接受——儘管這種接受並不能保證補丁會一直延伸到主線。補丁將出現在維護人員的
+  子系統樹中,並進入 -next 樹(如下所述)。當流程進行時,此步驟將會對補丁
+  進行更廣泛的審查,並發現由於將此補丁與其他人所做的工作合併而導致的任何
+  問題。
+
+- 請注意,大多數維護人員也有日常工作,因此合併補丁可能不是他們的最優先工作。
+  如果您的補丁得到了需要更改的反饋,那麼您應該進行這些更改,或者解釋爲何
+  不應該進行這些更改。如果您的補丁沒有評審意見,也沒有被其相應的子系統或
+  驅動程序維護者接受,那麼您應該堅持不懈地將補丁更新到當前內核使其可被正常
+  應用,並不斷地發送它以供審查和合併。
+
+- 合併到主線。最終,一個成功的補丁將被合併到由LinusTorvalds管理的主線存儲庫
+  中。此時可能會出現更多的評論和/或問題;對開發人員來說應對這些問題並解決
+  出現的任何問題仍很重要。
+
+- 穩定版發布。大量用戶可能受此補丁影響,因此可能再次出現新的問題。
+
+- 長期維護。雖然開發人員在合併代碼後可能會忘記代碼,但這種行爲往往會給開發
+  社區留下不良印象。合併代碼消除了一些維護負擔,因爲其他人將修復由API更改
+  引起的問題。但是,如果代碼要長期保持可用,原始開發人員應該繼續爲代碼負責。
+
+內核開發人員(或他們的僱主)犯的最大錯誤之一是試圖將流程簡化爲一個「合併到
+主線」步驟。這種方法總是會讓所有相關人員感到沮喪。
+
+補丁如何進入內核
+----------------
+
+只有一個人可以將補丁合併到主線內核存儲庫中:LinusTorvalds。但是,在進入
+2.6.38內核的9500多個補丁中,只有112個(大約1.3%)是由Linus自己直接選擇的。
+內核項目已經發展到一個沒有一個開發人員可以在沒有支持的情況下檢查和選擇每個
+補丁的規模。內核開發人員處理這種增長的方式是使用圍繞信任鏈構建的助理系統。
+
+內核代碼庫在邏輯上被分解爲一組子系統:網絡、特定體系結構支持、內存管理、視
+頻設備等。大多數子系統都有一個指定的維護人員,其總體負責該子系統中的代碼。
+這些子系統維護者(鬆散地)是他們所管理的內核部分的「守門員」;他們(通常)
+會接受一個補丁以包含到主線內核中。
+
+子系統維護人員每個人都管理著自己版本的內核原始碼樹,通常(並非總是)使用Git。
+Git等工具(以及Quilt或Mercurial等相關工具)允許維護人員跟蹤補丁列表,包括作者
+信息和其他元數據。在任何給定的時間,維護人員都可以確定他或她的存儲庫中的哪
+些補丁在主線中找不到。
+
+當合併窗口打開時,頂級維護人員將要求Linus從存儲庫中「拉出」他們爲合併選擇
+的補丁。如果Linus同意,補丁流將流向他的存儲庫,成爲主線內核的一部分。
+Linus對拉取中接收到的特定補丁的關注程度各不相同。很明顯,有時他看起來很
+關注。但是一般來說,Linus相信子系統維護人員不會向上游發送壞補丁。
+
+子系統維護人員反過來也可以從其他維護人員那裡獲取補丁。例如,網絡樹是由首先
+在專用於網絡設備驅動程序、無線網絡等的樹中積累的補丁構建的。此存儲鏈可以
+任意長,但很少超過兩個或三個連結。由於鏈中的每個維護者都信任那些管理較低
+級別樹的維護者,所以這個過程稱爲「信任鏈」。
+
+顯然,在這樣的系統中,獲取內核補丁取決於找到正確的維護者。直接向Linus發送
+補丁通常不是正確的方法。
+
+Next 樹
+-------
+
+子系統樹鏈引導補丁流到內核,但它也提出了一個有趣的問題:如果有人想查看爲
+下一個合併窗口準備的所有補丁怎麼辦?開發人員將感興趣的是,還有什麼其他的
+更改有待解決,以了解是否存在需要擔心的衝突;例如,更改核心內核函數原型的
+修補程序將與使用該函數舊形式的任何其他修補程序衝突。審查人員和測試人員希望
+在所有這些變更到達主線內核之前,能夠訪問它們的集成形式的變更。您可以從所有
+相關的子系統樹中提取更改,但這將是一項複雜且容易出錯的工作。
+
+解決方案以-next樹的形式出現,在這裡子系統樹被收集以供測試和審查。這些樹中
+由Andrew Morton維護的較老的一個,被稱爲「-mm」(用於內存管理,創建時爲此)。
+-mm 樹集成了一長串子系統樹中的補丁;它還包含一些旨在幫助調試的補丁。
+
+除此之外,-mm 還包含大量由Andrew直接選擇的補丁。這些補丁可能已經發布在郵件
+列表上,或者它們可能應用於內核中未指定子系統樹的部分。同時,-mm 作爲最後
+手段的子系統樹;如果沒有其他明顯的路徑可以讓補丁進入主線,那麼它很可能最
+終選擇-mm 樹。累積在-mm 中的各種補丁最終將被轉發到適當的子系統樹,或者直接
+發送到Linus。在典型的開發周期中,大約5-10%的補丁通過-mm 進入主線。
+
+當前-mm 補丁可在「mmotm」(-mm of the moment)目錄中找到:
+
+        https://www.ozlabs.org/~akpm/mmotm/
+
+然而,使用MMOTM樹可能會十分令人頭疼;它甚至可能無法編譯。
+
+下一個周期補丁合併的主要樹是linux-next,由Stephen Rothwell 維護。根據設計
+linux-next 是下一個合併窗口關閉後主線的快照。linux-next樹在Linux-kernel 和
+Linux-next 郵件列表中發布,可從以下位置下載:
+
+        https://www.kernel.org/pub/linux/kernel/next/
+
+Linux-next 已經成爲內核開發過程中不可或缺的一部分;在一個給定的合併窗口中合併
+的所有補丁都應該在合併窗口打開之前的一段時間內找到進入Linux-next 的方法。
+
+Staging 樹
+----------
+
+內核原始碼樹包含drivers/staging/目錄,其中有許多驅動程序或文件系統的子目錄
+正在被添加到內核樹中。它們在仍然需要更多的修正的時候可以保留在driver/staging/
+目錄中;一旦完成,就可以將它們移到內核中。這是一種跟蹤不符合Linux內核編碼或
+質量標準的驅動程序的方法,人們可能希望使用它們並跟蹤開發。
+
+Greg Kroah Hartman 目前負責維護staging 樹。仍需要修正的驅動程序將發送給他,
+每個驅動程序在drivers/staging/中都有自己的子目錄。除了驅動程序源文件之外,
+目錄中還應該有一個TODO文件。TODO文件列出了驅動程序需要接受的暫停的工作,
+以及驅動程序的任何補丁都應該抄送的人員列表。當前的規則要求,staging的驅動
+程序必須至少正確編譯。
+
+Staging 是一種讓新的驅動程序進入主線的相對容易的方法,它們會幸運地引起其他
+開發人員的注意,並迅速改進。然而,進入staging並不是故事的結尾;staging中
+沒有看到常規進展的代碼最終將被刪除。經銷商也傾向於相對不願意使用staging驅動
+程序。因此,在成爲一個合適的主線驅動的路上,staging 僅是一個中轉站。
+
+工具
+----
+
+從上面的文本可以看出,內核開發過程在很大程度上依賴於在不同方向上聚集補丁的
+能力。如果沒有適當強大的工具,整個系統將無法在任何地方正常工作。關於如何使用
+這些工具的教程遠遠超出了本文檔的範圍,但還是用一點篇幅介紹一些關鍵點。
+
+到目前爲止,內核社區使用的主要原始碼管理系統是git。Git是在自由軟體社區中開發
+的許多分布式版本控制系統之一。它非常適合內核開發,因爲它在處理大型存儲庫和
+大量補丁時性能非常好。它也以難以學習和使用而著稱,儘管隨著時間的推移它變得
+更好了。對於內核開發人員來說,對Git的某種熟悉幾乎是一種要求;即使他們不將它
+用於自己的工作,他們也需要Git來跟上其他開發人員(以及主線)正在做的事情。
+
+現在幾乎所有的Linux發行版都打包了Git。Git主頁位於:
+
+        https://git-scm.com/
+
+此頁面包含了文檔和教程的連結。
+
+在不使用git的內核開發人員中,最流行的選擇幾乎肯定是Mercurial:
+
+        http://www.seleric.com/mercurial/
+
+Mercurial與Git共享許多特性,但它提供了一個界面,許多人覺得它更易於使用。
+
+另一個值得了解的工具是Quilt:
+
+        https://savannah.nongnu.org/projects/quilt
+
+Quilt 是一個補丁管理系統,而不是原始碼管理系統。它不會隨著時間的推移跟蹤歷史;
+相反,它面向根據不斷發展的代碼庫跟蹤一組特定的更改。一些主要的子系統維護人員
+使用Quilt來管理打算向上游移動的補丁。對於某些樹的管理(例如-mm),quilt 是
+最好的工具。
+
+郵件列表
+--------
+
+大量的Linux內核開發工作是通過郵件列表完成的。如果不加入至少一個某個列表,
+就很難成爲社區中的一個「全功能」成員。但是,Linux郵件列表對開發人員來說也是
+一個潛在的危險,他們可能會被一堆電子郵件淹沒、違反Linux列表上使用的約定,
+或者兩者兼而有之。
+
+大多數內核郵件列表都在vger.kernel.org上運行;主列表位於:
+
+        http://vger.kernel.org/vger-lists.html
+
+不過,也有一些列表託管在別處;其中一些列表位於
+redhat.com/mailman/listinfo。
+
+當然,內核開發的核心郵件列表是linux-kernel。這個列表是一個令人生畏的地方:
+每天的信息量可以達到500條,噪音很高,談話技術性很強,且參與者並不總是表現出
+高度的禮貌。但是,沒有其他地方可以讓內核開發社區作爲一個整體聚集在一起;
+不使用此列表的開發人員將錯過重要信息。
+
+以下一些提示可以幫助在linux-kernel生存:
+
+- 將郵件轉移到單獨的文件夾,而不是主郵箱文件夾。我們必須能夠持續地忽略洪流。
+
+- 不要試圖跟上每一次談話——沒人會這樣。重要的是要篩選感興趣的主題(但請注意
+  長時間的對話可能會偏離原來的主題,儘管未改變電子郵件的主題)和參與的人。
+
+- 不要回復挑事的人。如果有人試圖激起憤怒,請忽略他們。
+
+- 當回復Linux內核電子郵件(或其他列表上的電子郵件)時,請爲所有相關人員保留
+  Cc: 抄送頭。如果沒有確實的理由(如明確的請求),則不應刪除收件人。一定要
+  確保你要回復的人在抄送列表中。這個慣例也使你不必在回覆郵件時明確要求被抄送。
+
+- 在提出問題之前,搜索列表存檔(和整個網絡)。有些開發人員可能會對那些顯然
+  沒有完成家庭作業的人感到不耐煩。
+
+- 避免頂部回復(把你的答案放在你要回復的引文上面的做法)。這會讓你的回答更難
+  理解,印象也很差。
+
+- 在正確的郵件列表發問。linux-kernel 可能是通用的討論場所,但它不是尋找所有
+  子系統開發人員的最佳場所。
+
+最後一點——找到正確的郵件列表——是開發人員常出錯的地方。在linux-kernel上
+提出與網絡相關的問題的人幾乎肯定會收到一個禮貌的建議,轉到netdev列表上提出,
+因爲這是大多數網絡開發人員經常出現的列表。還有其他列表可用於scsi、video4linux、
+ide、filesystem等子系統。查找郵件列表的最佳位置是與內核原始碼一起打包的
+MAINTAINERS文件。
+
+開始內核開發
+------------
+
+關於如何開始內核開發過程的問題很常見——個人和公司皆然。同樣常見的是失誤,這
+使得關係的開始比本應的更困難。
+
+公司通常希望聘請知名的開發人員來啓動開發團隊。實際上,這是一種有效的技術。
+但它也往往是昂貴的,而且對增加有經驗的內核開發人員的數量沒有多大幫助。考
+慮到時間投入,可以讓內部開發人員加快Linux內核的開發速度。利用這段時間可以
+讓僱主擁有一批既了解內核又了解公司的開發人員,還可以幫助培訓其他人。從中期
+來看,這通常是更有利可圖的方法。
+
+可以理解的是,單個開發人員往往對起步感到茫然。從一個大型項目開始可能會很
+嚇人;人們往往想先用一些較小的東西來試試水。由此,一些開發人員開始創建修補
+拼寫錯誤或輕微編碼風格問題的補丁。不幸的是,這樣的補丁會產生一定程度的噪音,
+這會分散整個開發社區的注意力,因此,它們越來越被人不看重。希望向社區介紹
+自己的新開發人員將無法通過這些方式獲得他們期待的反響。
+
+Andrew Morton 爲有抱負的內核開發人員提供了如下建議
+
+::
+
+	所有內核開發者的第一個項目肯定應該是「確保內核在您可以操作的所有
+	機器上始終完美運行」。通常的方法是和其他人一起解決問題(這可能需
+	要堅持!),但就是如此——這是內核開發的一部分。
+
+(http://lwn.net/articles/283982/)
+
+在沒有明顯問題需要解決的情況下,通常建議開發人員查看當前的回歸和開放缺陷
+列表。從來都不缺少需要解決的問題;通過解決這些問題,開發人員將從該過程獲得
+經驗,同時與開發社區的其他成員建立相互尊重。
+
diff --git a/Documentation/translations/zh_TW/process/3.Early-stage.rst b/Documentation/translations/zh_TW/process/3.Early-stage.rst
new file mode 100644
index 000000000000..ab2a45fd65a4
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/3.Early-stage.rst
@@ -0,0 +1,172 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/3.Early-stage.rst <development_early_stage>`
+
+:Translator:
+
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+
+:校譯:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+.. _tw_development_early_stage:
+
+早期規劃
+========
+
+當考慮一個Linux內核開發項目時,很可能會直接跳進去開始編碼。然而,與任何重要
+的項目一樣,許多成功的基礎最好是在第一行代碼編寫之前就打下。在早期計劃和
+溝通中花費一些時間可以在之後節省更多的時間。
+
+搞清問題
+--------
+
+與任何工程項目一樣,成功的內核改善從清晰描述要解決的問題開始。在某些情況
+下,這個步驟很容易:例如當某個特定硬體需要驅動程序時。不過,在其他情況下,
+很容易將實際問題與建議的解決方案混在一起,這可能會導致麻煩。
+
+舉個例子:幾年前,Linux音頻的開發人員尋求一種方法來運行應用程式,而不會因
+系統延遲過大而導致退出或其他問題。他們得到的解決方案是一個連接到Linux安全
+模塊(LSM)框架中的內核模塊;這個模塊可以配置爲允許特定的應用程式訪問實時
+調度程序。這個模塊被實現並發到linux-kernel郵件列表,在那裡它立即遇到了麻煩。
+
+對於音頻開發人員來說,這個安全模塊足以解決他們當前的問題。但是,對於更廣泛的
+內核社區來說,這被視爲對LSM框架的濫用(LSM框架並不打算授予他們原本不具備的
+進程特權),並對系統穩定性造成風險。他們首選的解決方案包括短期的通過rlimit
+機制進行實時調度訪問,以及長期的減少延遲的工作。
+
+然而,音頻社區無法超越他們實施的特定解決方案來看問題;他們不願意接受替代方案。
+由此產生的分歧使這些開發人員對整個內核開發過程感到失望;其中一個開發人員返回
+到audio列表並發布了以下內容:
+
+	有很多非常好的Linux內核開發人員,但他們往往會被一羣傲慢的傻瓜所壓倒。
+	試圖向這些人傳達用戶需求是浪費時間。他們太「聰明」了,根本聽不到少數
+	人的話。
+
+(http://lwn.net/articles/131776/)
+
+實際情況卻是不同的;與特定模塊相比,內核開發人員更關心系統穩定性、長期維護
+以及找到問題的正確解決方案。這個故事的寓意是把重點放在問題上——而不是具體的
+解決方案上——並在開始編寫代碼之前與開發社區討論這個問題。
+
+因此,在考慮一個內核開發項目時,我們應該得到一組簡短問題的答案:
+
+ - 需要解決的問題究竟是什麼?
+
+ - 受此問題影響的用戶有哪些?解決方案應該解決哪些使用案例?
+
+ - 內核現在爲何沒能解決這個問題?
+
+只有這樣,才能開始考慮可能的解決方案。
+
+
+早期討論
+--------
+
+在計劃內核開發項目時,在開始實施之前與社區進行討論是很有意義的。早期溝通可以
+通過多種方式節省時間和麻煩:
+
+ - 很可能問題是由內核以您不理解的方式解決的。Linux內核很大,具有許多不明顯
+   的特性和功能。並不是所有的內核功能都像人們所希望的那樣有文檔記錄,而且很
+   容易遺漏一些東西。某作者發布了一個完整的驅動程序,重複了一個其不
+   知道的現有驅動程序。重新發明現有輪子的代碼不僅浪費,而且不會被接受到主線
+   內核中。
+
+ - 建議的解決方案中可能有一些要素不適合併入主線。在編寫代碼之前,最好先了解
+   這樣的問題。
+
+ - 其他開發人員完全有可能考慮過這個問題;他們可能有更好的解決方案的想法,並且
+   可能願意幫助創建這個解決方案。
+
+在內核開發社區的多年經驗給了我們一個明確的教訓:閉門設計和開發的內核代碼總是
+有一些問題,這些問題只有在代碼發布到社區中時才會被發現。有時這些問題很嚴重,
+需要數月或數年的努力才能使代碼達到內核社區的標準。例如:
+
+ - 設計並實現了單處理器系統的DeviceScape網絡棧。只有使其適合於多處理器系統,
+   才能將其合併到主線中。在代碼中修改鎖等等是一項困難的任務;因此,這段代碼
+   (現在稱爲mac80211)的合併被推遲了一年多。
+
+ - Reiser4文件系統包含許多功能,核心內核開發人員認爲這些功能應該在虛擬文件
+   系統層中實現。它還包括一些特性,這些特性在不將系統暴露於用戶引起的死鎖的
+   情況下是不容易實現的。這些問題過遲發現——以及拒絕處理其中一些問題——已經
+   導致Reiser4置身主線內核之外。
+
+ - Apparmor安全模塊以被認爲不安全和不可靠的方式使用內部虛擬文件系統數據結構。
+   這種擔心(包括其他)使Apparmor多年來無法進入主線。
+
+在這些情況下,與內核開發人員的早期討論,可以避免大量的痛苦和額外的工作。
+
+找誰交流?
+----------
+
+當開發人員決定公開他們的計劃時,下一個問題是:我們從哪裡開始?答案是找到正確
+的郵件列表和正確的維護者。對於郵件列表,最好的方法是在維護者(MAINTAINERS)文件
+中查找要發布的相關位置。如果有一個合適的子系統列表,那麼其上發布通常比在
+linux-kernel上發布更可取;您更有可能接觸到在相關子系統中具有專業知識的開發
+人員,並且環境可能具支持性。
+
+找到維護人員可能會有點困難。同樣,維護者文件是開始的地方。但是,該文件往往不
+是最新的,並且並非所有子系統都在那裡顯示。實際上,維護者文件中列出的人員可能
+不是當前實際擔任該角色的人員。因此,當對聯繫誰有疑問時,一個有用的技巧是使用
+git(尤其是「git-log」)查看感興趣的子系統中當前活動的用戶。看看誰在寫補丁、
+誰會在這些補丁上加上Signed-off-by行簽名(如有)。這些人將是幫助新開發項目的
+最佳人選。
+
+找到合適的維護者有時是非常具有挑戰性的,以至於內核開發人員添加了一個腳本來
+簡化這個過程:
+
+::
+
+	.../scripts/get_maintainer.pl
+
+當給定「-f」選項時,此腳本將返回指定文件或目錄的當前維護者。如果在命令行上
+給出了一個補丁,它將列出可能接收補丁副本的維護人員。有許多選項可以調節
+get_maintainer.pl搜索維護者的嚴格程度;請小心使用更激進的選項,因爲最終結果
+可能會包括對您正在修改的代碼沒有真正興趣的開發人員。
+
+如果所有其他方法都失敗了,那麼與Andrew Morton交流是跟蹤特定代碼段維護人員
+的一種有效方法。
+
+何時郵寄?
+----------
+
+如果可能的話,在早期階段發布你的計劃只會更有幫助。描述正在解決的問題以及已經
+制定的關於如何實施的任何計劃。您可以提供的任何信息都可以幫助開發社區爲項目
+提供有用的輸入。
+
+在這個階段可能發生的一件令人沮喪的事情不是得到反對意見,而是很少或根本沒有
+反饋。令人傷心的事實是:(1)內核開發人員往往很忙;(2)不缺少有宏偉計劃但
+代碼(甚至代碼設想)很少的人去支持他們;(3)沒有人有義務審查或評論別人發表
+的想法。除此之外,高層級的設計常常隱藏著一些問題,這些問題只有在有人真正嘗試
+實現這些設計時才會被發現;因此,內核開發人員寧願看到代碼。
+
+如果發布請求評論(RFC)並沒得到什麼有用的評論,不要以爲這意味著無人對此項目
+有興趣,同時你也不能假設你的想法沒有問題。在這種情況下,最好的做法是繼續進
+行,把你的進展隨時通知社區。
+
+獲得官方認可
+-----------------------
+
+如果您的工作是在公司環境中完成的,就像大多數Linux內核工作一樣;顯然,在您將
+公司的計劃或代碼發布到公共郵件列表之前,必須獲得有適當權利經理的許可。發布
+不確定是否兼容GPL的代碼尤其會帶來問題;公司的管理層和法律人員越早能夠就發布
+內核開發項目達成一致,對參與的每個人都越好。
+
+一些讀者可能會認爲他們的核心工作是爲了支持還沒有正式承認存在的產品。將僱主
+的計劃公布在公共郵件列表上可能不是一個可行的選擇。在這種情況下,有必要考慮
+保密是否真的是必要的;通常不需要把開發計劃關在門內。
+
+的確,有些情況下一家公司在開發過程的早期無法合法地披露其計劃。擁有經驗豐富
+的內核開發人員的公司可能選擇以開環的方式進行開發,前提是他們以後能夠避免
+嚴重的集成問題。對於沒有這種內部專業知識的公司,最好的選擇往往是聘請外部
+開發者根據保密協議審查計劃。Linux基金會運行了一個NDA程序,旨在幫助解決這種
+情況;更多信息參見:
+
+    http://www.linuxfoundation.org/nda/
+
+這種審查通常足以避免以後出現嚴重問題,而無需公開披露項目。
+
diff --git a/Documentation/translations/zh_TW/process/4.Coding.rst b/Documentation/translations/zh_TW/process/4.Coding.rst
new file mode 100644
index 000000000000..ccc3946227a0
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/4.Coding.rst
@@ -0,0 +1,297 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/4.Coding.rst <development_coding>`
+
+:Translator:
+
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+
+:校譯:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+.. _tw_development_coding:
+
+使代碼正確
+======================
+
+雖然一個堅實的、面向社區的設計過程有很多值得說道的,但是任何內核開發項目工作
+的證明都反映在代碼中。它是將由其他開發人員檢查併合並(或不合併)到主線樹中
+的代碼。所以這段代碼的質量決定了項目的最終成功。
+
+本節將檢查編碼過程。我們將從內核開發人員常犯的幾種錯誤開始。然後重點將轉移
+到正確的做法和相關有用的工具上。
+
+陷阱
+----
+
+代碼風格
+********
+
+內核長期以來都有其標準的代碼風格,如
+:ref:`Documentation/translations/zh_TW/process/coding-style.rst <tw_codingstyle>`
+中所述。在多數時候,該文檔中描述的準則至多被認爲是建議性的。因此,內核中存在
+大量不符合代碼風格準則的代碼。這種代碼的存在會給內核開發人員帶來兩方面的危害。
+
+首先,相信內核代碼標準並不重要,也不強制執行。但事實上,如果沒有按照標準
+編寫代碼,那麼新代碼將很難加入到內核中;許多開發人員甚至會在審查代碼之前要求
+對代碼進行重新格式化。一個像內核這麼大的代碼庫需要一些統一格式的代碼,以使
+開發人員能夠快速理解其中的任何部分。所以再也經不起奇怪格式的代碼的折騰了。
+
+內核的代碼風格偶爾會與僱主的強制風格發生衝突。在這種情況下,必須在代碼合併
+之前遵從內核代碼風格。將代碼放入內核意味著以多種方式放棄一定程度的控制權——
+包括控制代碼樣式。
+
+另一個危害是認爲已經在內核中的代碼迫切需要修復代碼樣式。開發者可能會開始編寫
+重新格式化補丁,作爲熟悉開發過程的一種方式,或者作爲將其名字寫入內核變更日誌
+的一種方式,或者兩者兼而有之。但是純代碼風格的修復被開發社區視爲噪音,它們往
+往受到冷遇。因此,最好避免編寫這種類型的補丁。在由於其他原因處理一段代碼的
+同時順帶修復其樣式是很自然的,但是不應該僅爲了更改代碼樣式而更改之。
+
+代碼風格文檔也不應該被視爲絕對不可違反的規則。如果有一個足夠的理由反對這種
+樣式(例如爲了80列限制拆分行會導致可讀性大大降低),那麼就這樣做吧。
+
+注意您還可以使用 ``clang-format`` 工具來幫助您處理這些規則,快速自動重新格式
+化部分代碼,和審閱完整的文件以發現代碼樣式錯誤、拼寫錯誤和可能的改進。它還
+可以方便地排序 ``#includes`` 、對齊變量/宏、重排文本和其他類似任務。有關詳細
+信息,請參閱文檔 :ref:`Documentation/process/clang-format.rst <clangformat>`
+
+抽象層
+******
+
+計算機科學教授教學生以靈活性和信息隱藏的名義廣泛使用抽象層。當然,內核廣泛
+地使用了抽象;任何涉及數百萬行代碼的項目都必須做到這一點以存續下來。但經驗
+表明,過度或過早的抽象可能和過早的優化一樣有害。抽象應用在適當層級,
+不要過度。
+
+簡單點,先考慮一個調用時始終只有一個參數且總爲零的函數。我們可以保留這個參數,
+以在需要使用它時提供的額外靈活性。不過,在那時實現了這個額外參數的代碼很有
+可能以某種從未被注意到的微妙方式被破壞——因爲它從未被使用過。或者當需要額外
+的靈活性時,它並未以符合程式設計師當初期望的方式來實現。內核開發人員通常會提交
+補丁來刪除未使用的參數;一般來說,一開始就不應該添加這些參數。
+
+隱藏硬體訪問的抽象層——通常爲了允許大量的驅動程序兼容多個作業系統——尤其不受
+歡迎。這樣的層使代碼變得模糊,可能會造成性能損失;它們不屬於Linux內核。
+
+另一方面,如果您發現自己從另一個內核子系統複製了大量的代碼,那麼是時候
+了解一下:是否需要將這些代碼中的部分提取到單獨的庫中,或者在更高的層次上
+實現這些功能。在整個內核中複製相同的代碼沒有價值。
+
+#ifdef 和預處理
+***************
+
+C預處理器似乎給一些C程式設計師帶來了強大的誘惑,他們認爲它是一種將大量靈活性加入
+原始碼中的方法。但是預處理器不是C,大量使用它會導致代碼對其他人來說更難閱讀,
+對編譯器來說更難檢查正確性。使用了大量預處理器幾乎總是代碼需要一些
+清理工作的標誌。
+
+使用#ifdef的條件編譯實際上是一個強大的功能,它在內核中使用。但是很少有人希望
+看到代碼被鋪滿#ifdef塊。一般規定,ifdef的使用應儘可能限制在頭文件中。條件
+編譯代碼可以限制函數,如果代碼不存在,這些函數就直接變成空的。然後編譯器將
+悄悄地優化對空函數的調用。使得代碼更加清晰,更容易理解。
+
+C預處理器宏存在許多危險性,包括可能對具有副作用且沒有類型安全的表達式進行多
+重評估。如果您試圖定義宏,請考慮創建一個內聯函數替代。結果相同的代碼,內聯
+函數更容易閱讀,不會多次計算其參數,並且允許編譯器對參數和返回值執行類型檢查。
+
+內聯函數
+********
+
+不過,內聯函數本身也存在風險。程式設計師可以傾心於避免函數調用和用內聯函數填充源
+文件所固有的效率。然而,這些功能實際上會降低性能。因爲它們的代碼在每個調用站
+點都被複製一遍,所以最終會增加編譯內核的大小。此外,這也對處理器的內存緩存
+造成壓力,從而大大降低執行速度。通常內聯函數應該非常小,而且相對較少。畢竟
+函數調用的成本並不高;大量創建內聯函數是過早優化的典型例子。
+
+一般來說,內核程式設計師會自冒風險忽略緩存效果。在數據結構課程開頭中的經典
+時間/空間權衡通常不適用於當代硬體。空間 *就是* 時間,因爲一個大的程序比一個
+更緊湊的程序運行得慢。
+
+較新的編譯器越來越激進地決定一個給定函數是否應該內聯。因此,隨意放置使用
+「inline」關鍵字可能不僅僅是過度的,也可能是無用的。
+
+鎖
+**
+
+2006年5月,「deviceescape」網絡堆棧在前呼後擁下以GPL發布,並被納入主線內核。
+這是一個受歡迎的消息;Linux中對無線網絡的支持充其量被認爲是不合格的,而
+Deviceescape堆棧承諾修復這種情況。然而直到2007年6月(2.6.22),這段代碼才真
+正進入主線。發生了什麼?
+
+這段代碼出現了許多閉門造車的跡象。但一個大麻煩是,它並不是爲多處理器系統而
+設計。在合併這個網絡堆棧(現在稱爲mac80211)之前,需要對其進行一個鎖方案的
+改造。
+
+曾經,Linux內核代碼可以在不考慮多處理器系統所帶來的並發性問題的情況下進行
+開發。然而現在,這個文檔就是在雙核筆記本電腦上寫的。即使在單處理器系統上,
+爲提高響應能力所做的工作也會提高內核內的並發性水平。編寫內核代碼而不考慮鎖
+的日子早已遠去。
+
+可以由多個線程並發訪問的任何資源(數據結構、硬體寄存器等)必須由鎖保護。新
+的代碼應該謹記這一要求;事後修改鎖是一項相當困難的任務。內核開發人員應該花
+時間充分了解可用的鎖原語,以便爲工作選擇正確的工具。對並發性缺乏關注的代碼
+很難進入主線。
+
+回歸
+****
+
+最後一個值得一提的危險是回歸:它可能會引起導致現有用戶的某些東西中斷的改變
+(這也可能會帶來很大的改進)。這種變化被稱爲「回歸」,回歸已經成爲主線內核
+最不受歡迎的問題。除了少數例外情況,如果回歸不能及時修正,會導致回歸的修改
+將被取消。最好首先避免回歸發生。
+
+人們常常爭論,如果回歸帶來的功能遠超過產生的問題,那麼回歸是否爲可接受的。
+如果它破壞了一個系統卻爲十個系統帶來新的功能,爲何不改改態度呢?2007年7月,
+Linus對這個問題給出了最佳答案:
+
+::
+
+	所以我們不會通過引入新問題來修復錯誤。這種方式是靠不住的,沒人知道
+	是否真的有進展。是前進兩步、後退一步,還是前進一步、後退兩步?
+
+(http://lwn.net/articles/243460/)
+
+特別不受歡迎的一種回歸類型是用戶空間ABI的任何變化。一旦接口被導出到用戶空間,
+就必須無限期地支持它。這一事實使得用戶空間接口的創建特別具有挑戰性:因爲它們
+不能以不兼容的方式進行更改,所以必須一次就對。因此,用戶空間接口總是需要大量
+的思考、清晰的文檔和廣泛的審查。
+
+
+代碼檢查工具
+------------
+
+至少目前,編寫無錯誤代碼仍然是我們中很少人能達到的理想狀態。不過,我們希望做
+的是,在代碼進入主線內核之前,儘可能多地捕獲並修復這些錯誤。爲此,內核開發人
+員已經提供了一系列令人印象深刻的工具,可以自動捕獲各種各樣的隱藏問題。計算機
+發現的任何問題都是一個以後不會困擾用戶的問題,因此,只要有可能,就應該使用
+自動化工具。
+
+第一步是注意編譯器產生的警告。當前版本的GCC可以檢測(並警告)大量潛在錯誤。
+通常,這些警告都指向真正的問題。提交以供審閱的代碼一般不會產生任何編譯器警告。
+在消除警告時,注意了解真正的原因,並儘量避免僅「修復」使警告消失而不解決其原因。
+
+請注意,並非所有編譯器警告都默認啓用。使用「make KCFLAGS=-W」構建內核以
+獲得完整集合。
+
+內核提供了幾個配置選項,可以打開調試功能;大多數配置選項位於「kernel hacking」
+子菜單中。對於任何用於開發或測試目的的內核,都應該啓用其中幾個選項。特別是,
+您應該打開:
+
+ - FRAME_WARN 獲取大於給定數量的堆棧幀的警告。
+   這些警告生成的輸出可能比較冗長,但您不必擔心來自內核其他部分的警告。
+
+ - DEBUG_OBJECTS 將添加代碼以跟蹤內核創建的各種對象的生命周期,並在出現問題
+   時發出警告。如果你要添加創建(和導出)關於其自己的複雜對象的子系統,請
+   考慮打開對象調試基礎結構的支持。
+
+ - DEBUG_SLAB 可以發現各種內存分配和使用錯誤;它應該用於大多數開發內核。
+
+ - DEBUG_SPINLOCK, DEBUG_ATOMIC_SLEEP 和 DEBUG_MUTEXES 會發現許多常見的
+   鎖錯誤。
+
+還有很多其他調試選項,其中一些將在下面討論。其中一些有顯著的性能影響,不應
+一直使用。在學習可用選項上花費一些時間,可能會在短期內得到許多回報。
+
+其中一個較重的調試工具是鎖檢查器或「lockdep」。該工具將跟蹤系統中每個鎖
+(spinlock或mutex)的獲取和釋放、獲取鎖的相對順序、當前中斷環境等等。然後,
+它可以確保總是以相同的順序獲取鎖,相同的中斷假設適用於所有情況等等。換句話
+說,lockdep可以找到許多導致系統死鎖的場景。在部署的系統中,這種問題可能會
+很痛苦(對於開發人員和用戶而言);LockDep允許提前以自動方式發現問題。具有
+任何類型的非普通鎖的代碼在提交合併前應在啓用lockdep的情況下運行測試。
+
+作爲一個勤奮的內核程式設計師,毫無疑問,您將檢查任何可能失敗的操作(如內存分配)
+的返回狀態。然而,事實上,最終的故障復現路徑可能完全沒有經過測試。未測試的
+代碼往往會出問題;如果所有這些錯誤處理路徑都被執行了幾次,那麼您可能對代碼
+更有信心。
+
+內核提供了一個可以做到這一點的錯誤注入框架,特別是在涉及內存分配的情況下。
+啓用故障注入後,內存分配的可配置失敗的百分比;這些失敗可以限定在特定的代碼
+範圍內。在啓用了故障注入的情況下運行,程式設計師可以看到當情況惡化時代碼如何響
+應。有關如何使用此工具的詳細信息,請參閱
+Documentation/fault-injection/fault-injection.rst。
+
+「sparse」靜態分析工具可以發現其他類型的錯誤。sparse可以警告程式設計師用戶空間
+和內核空間地址之間的混淆、大端序與小端序的混淆、在需要一組位標誌的地方傳遞
+整數值等等。sparse必須單獨安裝(如果您的分發伺服器沒有將其打包,
+可以在 https://sparse.wiki.kernel.org/index.php/Main_page 找到),
+然後可以通過在make命令中添加「C=1」在代碼上運行它。
+
+「Coccinelle」工具 :ref:`http://coccinelle.lip6.fr/ <devtools_coccinelle>`
+能夠發現各種潛在的編碼問題;它還可以爲這些問題提出修複方案。在
+scripts/coccinelle目錄下已經打包了相當多的內核「語義補丁」;運行
+「make coccicheck」將運行這些語義補丁並報告發現的任何問題。有關詳細信息,請參閱
+:ref:`Documentation/dev-tools/coccinelle.rst <devtools_coccinelle>`
+
+
+其他類型的可移植性錯誤最好通過爲其他體系結構編譯代碼來發現。如果沒有S/390系統
+或Blackfin開發板,您仍然可以執行編譯步驟。可以在以下位置找到一大堆用於x86系統的
+交叉編譯器:
+
+        https://www.kernel.org/pub/tools/crosstool/
+
+花一些時間安裝和使用這些編譯器將有助於避免以後的尷尬。
+
+文檔
+----
+
+文檔通常比內核開發規則更爲例外。即便如此,足夠的文檔將有助於簡化將新代碼合併
+到內核中的過程,使其他開發人員的生活更輕鬆,並對您的用戶有所幫助。在許多情況
+下,添加文檔已基本上是強制性的。
+
+任何補丁的第一個文檔是其關聯的變更日誌。日誌條目應該描述正在解決的問題、解決
+方案的形式、處理補丁的人員、對性能的任何相關影響,以及理解補丁可能需要的任何
+其他內容。確保變更日誌說明了*爲什麼*補丁值得應用;大量開發者未能提供這些信息。
+
+任何添加新用戶空間接口的代碼——包括新的sysfs或/proc文件——都應該包含該接口
+的文檔,該文檔使用戶空間開發人員能夠知道他們在使用什麼。請參閱
+Documentation/ABI/README,了解如何此文檔格式以及需要提供哪些信息。
+
+文檔 :ref:`Documentation/admin-guide/kernel-parameters.rst <kernelparameters>`
+描述了內核的所有引導時間參數。任何添加新參數的補丁都應該向該文檔添加適當的
+條目。
+
+任何新的配置選項都必須附有幫助文本,幫助文本需清楚地解釋這些選項以及用戶可能
+希望何時使用它們。
+
+許多子系統的內部API信息通過專門格式化的注釋進行記錄;這些注釋可以通過
+「kernel-doc」腳本以多種方式提取和格式化。如果您在具有kerneldoc注釋的子系統中
+工作,則應該維護它們,並根據需要爲外部可用的功能添加它們。即使在沒有如此記錄
+的領域中,爲將來添加kerneldoc注釋也沒有壞處;實際上,這對於剛開始開發內核的人
+來說是一個有用的活動。這些注釋的格式以及如何創建kerneldoc模板的一些信息可以在
+:ref:`Documentation/doc-guide/ <doc_guide>` 上找到。
+
+任何閱讀大量現有內核代碼的人都會注意到,注釋的缺失往往是最值得注意的。同時,
+對新代碼的要求比過去更高;合併未注釋的代碼將更加困難。這就是說,人們並不期望
+詳細注釋的代碼。代碼本身應該是自解釋的,注釋闡釋了更微妙的方面。
+
+某些事情應該總是被注釋。使用內存屏障時,應附上一行文字,解釋爲什麼需要設置內存
+屏障。數據結構的鎖規則通常需要在某個地方解釋。一般來說,主要數據結構需要全面
+的文檔。應該指出代碼中分立的位之間不明顯的依賴性。任何可能誘使代碼管理人進行
+錯誤的「清理」的事情都需要一個注釋來說明爲什麼要這樣做。等等。
+
+
+內部API更改
+-----------
+
+內核提供給用戶空間的二進位接口不能被破壞,除非逼不得已。而內核的內部編程接口
+是高度流動的,當需要時可以更改。如果你發現自己不得不處理一個內核API,或者僅
+僅因爲它不滿足你的需求導致無法使用特定的功能,這可能是API需要改變的一個標誌。
+作爲內核開發人員,您有權進行此類更改。
+
+的確可以進行API更改,但更改必須是合理的。因此任何進行內部API更改的補丁都應該
+附帶關於更改內容和必要原因的描述。這種變化也應該拆分成一個單獨的補丁,而不是
+埋在一個更大的補丁中。
+
+另一個要點是,更改內部API的開發人員通常要負責修復內核樹中被更改破壞的任何代碼。
+對於一個廣泛使用的函數,這個責任可以導致成百上千的變化,其中許多變化可能與其他
+開發人員正在做的工作相衝突。不用說,這可能是一項大工程,所以最好確保理由是
+可靠的。請注意,coccinelle工具可以幫助進行廣泛的API更改。
+
+在進行不兼容的API更改時,應儘可能確保編譯器捕獲未更新的代碼。這將幫助您確保找
+到該接口的樹內用處。它還將警告開發人員樹外代碼存在他們需要響應的更改。支持樹外
+代碼不是內核開發人員需要擔心的事情,但是我們也不必使樹外開發人員的生活有不必要
+的困難。
+
diff --git a/Documentation/translations/zh_TW/process/5.Posting.rst b/Documentation/translations/zh_TW/process/5.Posting.rst
new file mode 100644
index 000000000000..5578bca403e6
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/5.Posting.rst
@@ -0,0 +1,251 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/5.Posting.rst <development_posting>`
+
+:Translator:
+
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+
+:校譯:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+.. _tw_development_posting:
+
+發布補丁
+========
+
+您的工作遲早會準備好提交給社區進行審查,並最終包含到主線內核中。毫不稀奇,
+內核開發社區已經發展出一套用於發布補丁的約定和過程;遵循這些約定和過程將使
+參與其中的每個人的生活更加輕鬆。本文檔試圖描述這些約定的部分細節;更多信息
+也可在以下文檔中找到
+:ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`,
+:ref:`Documentation/translations/zh_TW/process/submitting-drivers.rst <tw_submittingdrivers>`
+和 :ref:`Documentation/translations/zh_TW/process/submit-checklist.rst <tw_submitchecklist>`。
+
+何時郵寄
+--------
+
+在補丁完全「準備好」之前,避免發布補丁是一種持續的誘惑。對於簡單的補丁,這
+不是問題。但是如果正在完成的工作很複雜,那麼在工作完成之前從社區獲得反饋就
+可以獲得很多好處。因此,您應該考慮發布正在進行的工作,甚至維護一個可用的Git
+樹,以便感興趣的開發人員可以隨時趕上您的工作。
+
+當發布中有尚未準備好被包含的代碼,最好在發布中說明。還應提及任何有待完成的
+主要工作和任何已知問題。很少有人會願意看那些被認爲是半生不熟的補丁,但是
+那些願意的人會帶著他們的點子來一起幫助你把工作推向正確的方向。
+
+創建補丁之前
+------------
+
+在考慮將補丁發送到開發社區之前,有許多事情應該做。包括:
+
+ - 儘可能地測試代碼。利用內核的調試工具,確保內核使用了所有可能的配置選項組合
+   進行構建,使用交叉編譯器爲不同的體系結構進行構建等。
+
+ - 確保您的代碼符合內核代碼風格指南。
+
+ - 您的更改是否具有性能影響?如果是這樣,您應該運行基準測試來顯示您的變更的
+   影響(或好處);結果的摘要應該包含在補丁中。
+
+ - 確保您有權發布代碼。如果這項工作是爲僱主完成的,僱主對這項工作具有所有權,
+   並且必須同意根據GPL對其進行發布。
+
+一般來說,在發布代碼之前進行一些額外的思考,幾乎總是能在短時間內得到回報。
+
+補丁準備
+--------
+
+準備補丁發布的工作量可能很驚人,但在此嘗試節省時間通常是不明智的,即使在短期
+內亦然。
+
+必須針對內核的特定版本準備補丁。一般來說,補丁應該基於Linus的Git樹中的當前
+主線。當以主線爲基礎時,請從一個衆所周知的發布點開始——如穩定版本或 -rc
+版本發布點——而不是在一個任意的主線分支點。
+
+也可能需要針對-mm、linux-next或子系統樹生成版本,以便於更廣泛的測試和審查。
+根據補丁的區域以及其他地方的情況,針對其他樹建立的補丁可能需要大量的工作來
+解決衝突和處理API更改。
+
+只有最簡單的更改才應格式化爲單個補丁;其他所有更改都應作爲一系列邏輯更改進行。
+分割補丁是一門藝術;一些開發人員花了很長時間來弄清楚如何按照社區期望的方式來
+分割。不過,這些經驗法則也許有幫助:
+
+ - 您發布的補丁系列幾乎肯定不會是開發過程中版本控制系統中的一系列更改。相反,
+   需要對您所做更改的最終形式加以考慮,然後以有意義的方式進行拆分。開發人員對
+   離散的、自包含的更改感興趣,而不是您創造這些更改的原始路徑。
+
+ - 每個邏輯上獨立的變更都應該格式化爲單獨的補丁。這些更改可以是小的(如「向
+   此結構體添加欄位」)或大的(如添加一個重要的新驅動程序),但它們在概念上
+   應該是小的,並且可以在一行內簡述。每個補丁都應該做一個特定的、可以單獨
+   檢查並驗證它所做的事情的更改。
+
+ - 換種方式重申上述準則,也就是說:不要在同一補丁中混合不同類型的更改。如果
+   一個補丁修復了一個關鍵的安全漏洞,又重新排列了一些結構,還重新格式化了代
+   碼,那麼它很有可能會被忽略,從而導致重要的修復丟失。
+
+ - 每個補丁都應該能創建一個可以正確地構建和運行的內核;如果補丁系列在中間被
+   斷開,那麼結果仍應是一個正常工作的內核。部分應用一系列補丁是使用
+   「git bisct」工具查找回歸的一個常見場景;如果結果是一個損壞的內核,那麼將使
+   那些從事追蹤問題的高尚工作的開發人員和用戶的生活更加艱難。
+
+ - 不要過分分割。一位開發人員曾經將一組針對單個文件的編輯分成500個單獨的補丁
+   發布,這並沒有使他成爲內核郵件列表中最受歡迎的人。一個補丁可以相當大,
+   只要它仍然包含一個單一的 *邏輯* 變更。
+
+ - 用一系列補丁添加一個全新的基礎設施,但是該設施在系列中的最後一個補丁啓用
+   整個變更之前不能使用,這看起來很誘人。如果可能的話,應該避免這種誘惑;
+   如果這個系列增加了回歸,那麼二分法將指出最後一個補丁是導致問題的補丁,
+   即使真正的bug在其他地方。只要有可能,添加新代碼的補丁程序應該立即激活該
+   代碼。
+
+創建完美補丁系列的工作可能是一個令人沮喪的過程,在完成「真正的工作」之後需要
+花費大量的時間和思考。但是如果做得好,花費的時間就是值得的。
+
+補丁格式和更改日誌
+------------------
+
+所以現在你有了一系列完美的補丁可以發布,但是這項工作還沒有完成。每個補丁都
+需要被格式化成一條消息,以快速而清晰地將其目的傳達到世界其他地方。爲此,
+每個補丁將由以下部分組成:
+
+ - 可選的「From」行,表明補丁作者。只有當你通過電子郵件發送別人的補丁時,這一行
+   才是必須的,但是爲防止疑問加上它也不會有什麼壞處。
+
+ - 一行描述,說明補丁的作用。對於在沒有其他上下文的情況下看到該消息的讀者來說,
+   該消息應足以確定修補程序的範圍;此行將顯示在「short form(簡短格式)」變更
+   日誌中。此消息通常需要先加上子系統名稱前綴,然後是補丁的目的。例如:
+
+   ::
+
+        gpio: fix build on CONFIG_GPIO_SYSFS=n
+
+ - 一行空白,後接補丁內容的詳細描述。此描述可以是任意需要的長度;它應該說明補丁
+   的作用以及爲什麼它應該應用於內核。
+
+ - 一個或多個標記行,至少有一個由補丁作者的 Signed-off-by 簽名。標記將在下面
+   詳細描述。
+
+上面的項目一起構成補丁的變更日誌。寫一則好的變更日誌是一門至關重要但常常被
+忽視的藝術;值得花一點時間來討論這個問題。當你編寫變更日誌時,你應該記住有
+很多不同的人會讀你的話。其中包括子系統維護人員和審查人員,他們需要決定是否
+應該合併補丁,分銷商和其他維護人員試圖決定是否應該將補丁反向移植到其他內核,
+缺陷搜尋人員想知道補丁是否導致他們正在追查的問題,以及想知道內核如何變化的
+用戶等等。一個好的變更日誌以最直接和最簡潔的方式向所有這些人傳達所需的信息。
+
+在結尾,總結行應該描述變更的影響和動機,以及在一行約束條件下可能發生的變化。
+然後,詳細的描述可以詳述這些主題,並提供任何需要的附加信息。如果補丁修復了
+一個缺陷,請引用引入該缺陷的提交(如果可能,請在引用提交時同時提供其 id 和
+標題)。如果某個問題與特定的日誌或編譯器輸出相關聯,請包含該輸出以幫助其他
+人搜索同一問題的解決方案。如果更改是爲了支持以後補丁中的其他更改,那麼應當
+說明。如果更改了內部API,請詳細說明這些更改以及其他開發人員應該如何響應。
+一般來說,你越把自己放在每個閱讀你變更日誌的人的位置上,變更日誌(和內核
+作爲一個整體)就越好。
+
+不消說,變更日誌是將變更提交到版本控制系統時使用的文本。接下來將是:
+
+ - 補丁本身,採用統一的(「-u」)補丁格式。使用「-p」選項來diff將使函數名與
+   更改相關聯,從而使結果補丁更容易被其他人讀取。
+
+您應該避免在補丁中包括與更改不相關文件(例如,構建過程生成的文件或編輯器
+備份文件)。文檔目錄中的「dontdiff」文件在這方面有幫助;使用「-X」選項將
+其傳遞給diff。
+
+上面提到的標籤(tag)用於描述各種開發人員如何與這個補丁的開發相關聯。
+:ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+文檔中對它們進行了詳細描述;下面是一個簡短的總結。每一行的格式如下:
+
+::
+
+	tag: Full Name <email address>  optional-other-stuff
+
+常用的標籤有:
+
+ - Signed-off-by: 這是一個開發人員的證明,證明他或她有權提交補丁以包含到內核
+   中。這表明同意開發者來源認證協議,其全文見
+   :ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+   如果沒有合適的簽字,則不能合併到主線中。
+
+ - Co-developed-by: 聲明補丁是由多個開發人員共同創建的;當幾個人在一個補丁上
+   工作時,它用於給出共同作者(除了 From: 所給出的作者之外)。由於
+   Co-developed-by: 表示作者身份,所以每個共同開發人,必須緊跟在相關合作作者
+   的Signed-off-by之後。具體內容和示例見以下文件
+   :ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+
+ - Acked-by: 表示另一個開發人員(通常是相關代碼的維護人員)同意補丁適合包含
+   在內核中。
+
+ - Tested-by: 聲明某人已經測試了補丁並確認它可以工作。
+
+ - Reviewed-by: 表示某開發人員已經審查了補丁的正確性;有關詳細信息,請參閱
+   :ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+
+ - Reported-by: 指定報告此補丁修復的問題的用戶;此標記用於表示感謝。
+
+ - Cc:指定某人收到了補丁的副本,並有機會對此發表評論。
+
+在補丁中添加標籤時要小心:只有Cc:才適合在沒有指定人員明確許可的情況下添加。
+
+發送補丁
+--------
+
+在寄出補丁之前,您還需要注意以下幾點:
+
+ - 您確定您的郵件發送程序不會損壞補丁嗎?被郵件客戶端更改空白或修飾了行的補丁
+   無法被另一端接受,並且通常不會進行任何詳細檢查。如果有任何疑問,先把補丁寄
+   給你自己,讓你自己確定它是完好無損的。
+
+   :ref:`Documentation/translations/zh_TW/process/email-clients.rst <tw_email_clients>`
+   提供了一些有用的提示,可以讓特定的郵件客戶端正常發送補丁。
+
+ - 你確定你的補丁沒有荒唐的錯誤嗎?您應該始終通過scripts/checkpatch.pl檢查
+   補丁程序,並解決它提出的問題。請記住,checkpatch.pl,雖然體現了對內核補丁
+   應該是什麼樣的大量思考,但它並不比您聰明。如果修復checkpatch.pl給的問題會
+   使代碼變得更糟,請不要這樣做。
+
+補丁應始終以純文本形式發送。請不要將它們作爲附件發送;這使得審閱者在答覆中更難
+引用補丁的部分。相反,只需將補丁直接放到您的消息中。
+
+寄出補丁時,重要的是將副本發送給任何可能感興趣的人。與其他一些項目不同,內核
+鼓勵人們甚至錯誤地發送過多的副本;不要假定相關人員會看到您在郵件列表中的發布。
+尤其是,副本應發送至:
+
+ - 受影響子系統的維護人員。如前所述,維護人員文件是查找這些人員的首選地方。
+
+ - 其他在同一領域工作的開發人員,尤其是那些現在可能在那裡工作的開發人員。使用
+   git查看還有誰修改了您正在處理的文件,這很有幫助。
+
+ - 如果您對某錯誤報告或功能請求做出響應,也可以抄送原始發送人。
+
+ - 將副本發送到相關郵件列表,或者若無相關列表,則發送到linux-kernel列表。
+
+ - 如果您正在修復一個缺陷,請考慮該修復是否應進入下一個穩定更新。如果是這樣,
+   補丁副本也應發到stable@vger.kernel.org 。另外,在補丁本身的標籤中添加一個
+   「Cc: stable@vger.kernel.org」;這將使穩定版團隊在修復進入主線時收到通知。
+
+當爲一個補丁選擇接收者時,最好清楚你認爲誰最終會接受這個補丁並將其合併。雖然
+可以將補丁直接發給Linus Torvalds並讓他合併,但通常情況下不會這樣做。Linus很
+忙,並且有子系統維護人員負責監視內核的特定部分。通常您會希望維護人員合併您的
+補丁。如果沒有明顯的維護人員,Andrew Morton通常是最後的補丁接收者。
+
+補丁需要好的主題行。補丁主題行的規範格式如下:
+
+::
+
+	[PATCH nn/mm] subsys: one-line description of the patch
+
+其中「nn」是補丁的序號,「mm」是系列中補丁的總數,「subsys」是受影響子系統的
+名稱。當然,一個單獨的補丁可以省略nn/mm。
+
+如果您有一系列重要的補丁,那麼通常發送一個簡介作爲第〇部分。不過,這個約定
+並沒有得到普遍遵循;如果您使用它,請記住簡介中的信息不會進入內核變更日誌。
+因此,請確保補丁本身具有完整的變更日誌信息。
+
+一般來說,多部分補丁的第二部分和後續部分應作爲對第一部分的回覆發送,以便它們
+在接收端都連接在一起。像git和coilt這樣的工具有命令,可以通過適當的線程發送
+一組補丁。但是,如果您有一長串補丁,並正使用git,請不要使用–-chain-reply-to
+選項,以避免創建過深的嵌套。
+
diff --git a/Documentation/translations/zh_TW/process/6.Followthrough.rst b/Documentation/translations/zh_TW/process/6.Followthrough.rst
new file mode 100644
index 000000000000..4af782742db3
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/6.Followthrough.rst
@@ -0,0 +1,156 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/6.Followthrough.rst <development_followthrough>`
+
+:Translator:
+
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+
+:校譯:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+.. _tw_development_followthrough:
+
+跟進
+====
+
+此時,您已經遵循了到目前爲止給出的指導方針,並且,隨著您自己的工程技能的增加,
+已經發布了一系列完美的補丁。即使是經驗豐富的內核開發人員也能犯的最大錯誤之一
+是,認爲他們的工作現在已經完成了。事實上,發布補丁意味著進入流程的下一個階段,
+可能還需要做很多工作。
+
+一個補丁在首次發布時就非常出色、沒有改進的餘地,這是很罕見的。內核開發流程已
+認識到這一事實,因此它非常注重對已發布代碼的改進。作爲代碼的作者,您應該與
+內核社區合作,以確保您的代碼符合內核的質量標準。如果不參與這個過程,很可能會
+無法將補丁合併到主線中。
+
+與審閱者合作
+------------
+
+任何意義上的補丁都會導致其他開發人員在審查代碼時發表大量評論。對於許多開發
+人員來說,與審閱人員合作可能是內核開發過程中最令人生畏的部分。但是如果你
+記住一些事情,生活會變得容易得多:
+
+ - 如果你已經很好地解釋了你的補丁,審閱人員會理解它的價值,以及爲什麼你會
+   費盡心思去寫它。但是這個並不能阻止他們提出一個基本的問題:在五年或十年後
+   維護含有此代碼的內核會怎麼樣?你可能被要求做出的許多改變——從編碼風格的
+   調整到大量的重寫——都來自於對Linux的理解,即從現在起十年後,Linux仍將
+   在開發中。
+
+ - 代碼審查是一項艱苦的工作,這是一項相對吃力不討好的工作;人們記得誰編寫了
+   內核代碼,但對於那些審查它的人來說,幾乎沒有什麼長久的名聲。因此,審閱
+   人員可能會變得暴躁,尤其是當他們看到同樣的錯誤被一遍又一遍地犯下時。如果
+   你得到了一個看起來憤怒、侮辱或完全冒犯你的評論,請抑制以同樣方式回應的衝動。
+   代碼審查是關於代碼的,而不是關於人的,代碼審閱人員不會親自攻擊您。
+
+ - 同樣,代碼審閱人員也不想以犧牲你僱主的利益爲代價來宣傳他們僱主的議程。
+   內核開發人員通常希望今後幾年能在內核上工作,但他們明白他們的僱主可能會改
+   變。他們真的,幾乎毫無例外地,致力於創造他們所能做到的最好的內核;他們並
+   沒有試圖給僱主的競爭對手造成不適。
+
+所有這些歸根結底就是,當審閱者向您發送評論時,您需要注意他們正在進行的技術
+評論。不要讓他們的表達方式或你自己的驕傲阻止此事。當你在一個補丁上得到評論
+時,花點時間去理解評論人想說什麼。如果可能的話,請修覆審閱者要求您修復的內
+容。然後回覆審閱者:謝謝他們,並描述你將如何回答他們的問題。
+
+請注意,您不必同意審閱者建議的每個更改。如果您認爲審閱者誤解了您的代碼,請
+解釋到底發生了什麼。如果您對建議的更改有技術上的異議,請描述它並證明您對該
+問題的解決方案是正確的。如果你的解釋有道理,審閱者會接受的。不過,如果你的
+解釋證明缺乏說服力,尤其是當其他人開始同意審稿人的觀點時,請花些時間重新考慮
+一下。你很容易對自己解決問題的方法視而不見,以至於你沒有意識到某些東西完全
+是錯誤的,或者你甚至沒有解決正確的問題。
+
+Andrew Morton建議,每一個不會導致代碼更改的審閱評論都應該產生一個額外的代碼
+注釋;這可以幫助未來的審閱人員避免第一次出現的問題。
+
+一個致命的錯誤是忽視評論,希望它們會消失。它們不會走的。如果您在沒有對之前
+收到的評論做出響應的情況下重新發布代碼,那麼很可能會發現補丁毫無用處。
+
+說到重新發布代碼:請記住,審閱者不會記住您上次發布的代碼的所有細節。因此,
+提醒審閱人員以前提出的問題以及您如何處理這些問題總是一個好主意;補丁變更
+日誌是提供此類信息的好地方。審閱者不必搜索列表檔案來熟悉上次所說的內容;
+如果您幫助他們直接開始,當他們重新查看您的代碼時,心情會更好。
+
+如果你已經試著做正確的事情,但事情仍然沒有進展呢?大多數技術上的分歧都可以
+通過討論來解決,但有時人們仍需要做出決定。如果你真的認爲這個決定對你不利,
+你可以試著向有更高權力的人上訴。對於本文,更高權力的人是 Andrew Morton 。
+Andrew 在內核開發社區中非常受尊敬;他經常爲似乎被絕望阻塞的事情清障。儘管
+如此,不應輕易就直接找 Andrew ,也不應在所有其他替代方案都被嘗試之前找他。
+當然,記住,他也可能不同意你的意見。
+
+接下來會發生什麼
+----------------
+
+如果一個補丁被認爲適合添加到內核中,並且大多數審查問題得到解決,下一步通常
+是進入子系統維護人員的樹中。工作方式因子系統而異;每個維護人員都有自己的
+工作方式。特別是可能有不止一棵樹——也許一棵樹專門用於計劃下一個合併窗口的
+補丁,另一棵樹用於長期工作。
+
+對於應用到不屬於明顯子系統樹(例如內存管理修補程序)的區域的修補程序,默認樹
+通常上溯到-mm。影響多個子系統的補丁也可以最終進入-mm樹。
+
+包含在子系統樹中可以提高補丁的可見性。現在,使用該樹的其他開發人員將默認獲
+得補丁。子系統樹通常也爲Linux提供支持,使其內容對整個開發社區可見。在這一點
+上,您很可能會從一組新的審閱者那裡得到更多的評論;這些評論需要像上一輪那樣
+得到回應。
+
+在這時也會發生點什麼,這取決於你的補丁的性質,是否與其他人正在做的工作發生
+衝突。在最壞的情況下,嚴重的補丁衝突可能會導致一些工作被擱置,以便剩餘的補丁
+可以成形併合並。另一些時候,衝突解決將涉及到與其他開發人員合作,可能還會
+在樹之間移動一些補丁,以確保所有的應用都是乾淨的。這項工作可能是一件痛苦的
+事情,但也需慶幸現在的幸福:在linux-next樹出現之前,這些衝突通常只在合併窗口
+中出現,必須迅速解決。現在可以在合併窗口打開之前的空閒時間解決這些問題。
+
+有朝一日,如果一切順利,您將登錄並看到您的補丁已經合併到主線內核中。祝賀你!
+然而,一旦慶祝完了(並且您已經將自己添加到維護人員文件中),就一定要記住
+一個重要的小事實:工作仍然沒有完成。併入主線也帶來了它的挑戰。
+
+首先,補丁的可見性再次提高。可能會有以前不知道這個補丁的開發者的新一輪評論。
+忽略它們可能很有誘惑力,因爲您的代碼不再存在任何被合併的問題。但是,要抵制
+這種誘惑,您仍然需要對有問題或建議的開發人員作出響應。
+
+不過,更重要的是:將代碼包含在主線中會將代碼交給更多的一些測試人員。即使您
+爲尚未可用的硬體提供了驅動程序,您也會驚訝於有多少人會將您的代碼構建到內核
+中。當然,如果有測試人員,也可能會有錯誤報告。
+
+最糟糕的錯誤報告是回歸。如果你的補丁導致回歸,你會發現多到讓你不舒服的眼睛盯
+著你;回歸需要儘快修復。如果您不願意或無法修復回歸(其他人都不會爲您修復),
+那麼在穩定期內,您的補丁幾乎肯定會被移除。除了否定您爲使補丁進入主線所做的
+所有工作之外,如果由於未能修復回歸而取消補丁,很可能會使將來的工作更難被合併。
+
+在處理完任何回歸之後,可能還有其他普通缺陷需要處理。穩定期是修復這些錯誤並
+確保代碼在主線內核版本中的首次發布儘可能可靠的最好機會。所以,請回應錯誤
+報告,並儘可能解決問題。這就是穩定期的目的;一旦解決了舊補丁的任何問題,就
+可以開始盡情創建新補丁。
+
+別忘了,還有其他節點也可能會創建缺陷報告:下一個主線穩定版本,當著名的發行
+商選擇包含您補丁的內核版本時等等。繼續響應這些報告是您工作的基本素養。但是
+如果這不能提供足夠的動機,那麼也需要考慮:開發社區會記住那些在合併後對代碼
+失去興趣的開發人員。下一次你發布補丁時,他們會以你以後不會持續維護它爲前提
+來評估它。
+
+其他可能發生的事情
+------------------
+
+某天,當你打開你的郵件客戶端時,看到有人給你寄了一個代碼補丁。畢竟,這是
+讓您的代碼公開存在的好處之一。如果您同意這個補丁,您可以將它轉發給子系統
+維護人員(確保包含一個正確的From:行,這樣屬性是正確的,並添加一個您自己的
+signoff ),或者回復一個 Acked-by: 讓原始發送者向上發送它。
+
+如果您不同意補丁,請禮貌地回復,解釋原因。如果可能的話,告訴作者需要做哪些
+更改才能讓您接受補丁。合併代碼的編寫者和維護者所反對的補丁的確存在著一定的
+阻力,但僅此而已。如果你被認爲不必要的阻礙了好的工作,那麼這些補丁最終會
+繞過你並進入主線。在Linux內核中,沒有人對任何代碼擁有絕對的否決權。可能除
+了Linus。
+
+在非常罕見的情況下,您可能會看到完全不同的東西:另一個開發人員發布了針對您
+的問題的不同解決方案。在這時,兩個補丁之一可能不會被合併,「我的補丁首先
+發布」不被認爲是一個令人信服的技術論據。如果有別人的補丁取代了你的補丁而進
+入了主線,那麼只有一種方法可以回應你:很高興你的問題解決了,請繼續工作吧。
+以這種方式把某人的工作推到一邊可能導致傷心和氣餒,但是社區會記住你的反應,
+即使很久以後他們已經忘記了誰的補丁真正被合併。
+
diff --git a/Documentation/translations/zh_TW/process/7.AdvancedTopics.rst b/Documentation/translations/zh_TW/process/7.AdvancedTopics.rst
new file mode 100644
index 000000000000..3de093d0f170
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/7.AdvancedTopics.rst
@@ -0,0 +1,137 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/7.AdvancedTopics.rst <development_advancedtopics>`
+
+:Translator:
+
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+
+:校譯:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+.. _tw_development_advancedtopics:
+
+高級主題
+========
+
+現在,希望您能夠掌握開發流程的工作方式。然而,還有更多的東西要學!本節將介紹
+一些主題,這些主題對希望成爲Linux內核開發過程常規部分的開發人員有幫助。
+
+使用Git管理補丁
+---------------
+
+內核使用分布式版本控制始於2002年初,當時Linus首次開始使用專有的Bitkeeper應用
+程序。雖然BitKeeper存在爭議,但它所體現的軟體版本管理方法卻肯定不是。分布式
+版本控制可以立即加速內核開發項目。現在有好幾種免費的BitKeeper替代品。
+但無論好壞,內核項目都已經選擇了Git作爲其工具。
+
+使用Git管理補丁可以使開發人員的生活更加輕鬆,尤其是隨著補丁數量的增長。Git也
+有其粗糙的邊角和一定的危險性,它是一個年輕和強大的工具,仍然在其開發人員完善
+中。本文檔不會試圖教會讀者如何使用git;這會是個巨長的文檔。相反,這裡的重點
+將是Git如何特別適合內核開發過程。想要加快用Git速度的開發人員可以在以下網站上
+找到更多信息:
+
+	https://git-scm.com/
+
+	https://www.kernel.org/pub/software/scm/git/docs/user-manual.html
+
+同時網上也能找到各種各樣的教程。
+
+在嘗試使用它生成補丁供他人使用之前,第一要務是閱讀上述網頁,對Git的工作方式
+有一個紮實的了解。使用Git的開發人員應能進行拉取主線存儲庫的副本,查詢修訂
+歷史,提交對樹的更改,使用分支等操作。了解Git用於重寫歷史的工具(如rebase)
+也很有用。Git有自己的術語和概念;Git的新用戶應該了解引用、遠程分支、索引、
+快進合併、推拉、游離頭等。一開始可能有點嚇人,但這些概念不難通過一點學習來
+理解。
+
+使用git生成通過電子郵件提交的補丁是提高速度的一個很好的練習。
+
+當您準備好開始建立Git樹供其他人查看時,無疑需要一個可以從中拉取的伺服器。
+如果您有一個可以訪問網際網路的系統,那麼使用git-daemon設置這樣的伺服器相對
+簡單。同時,免費的公共託管網站(例如github)也開始出現在網絡上。成熟的開發
+人員可以在kernel.org上獲得一個帳戶,但這些帳戶並不容易得到;更多有關信息,
+請參閱 https://kernel.org/faq/ 。
+
+正常的Git工作流程涉及到許多分支的使用。每一條開發線都可以分爲單獨的「主題
+分支」,並獨立維護。Git的分支很容易使用,沒有理由不使用它們。而且,在任何
+情況下,您都不應該在任何您打算讓其他人從中拉取的分支中進行開發。應該小心地
+創建公開可用的分支;當開發分支處於完整狀態並已準備好時(而不是之前)才合併
+開發分支的補丁。
+
+Git提供了一些強大的工具,可以讓您重寫開發歷史。一個不方便的補丁(比如說,
+一個打破二分法的補丁,或者有其他一些明顯的缺陷)可以在適當的位置修復,或者
+完全從歷史中消失。一個補丁系列可以被重寫,就好像它是在今天的主線上寫的一樣,
+即使你已經花了幾個月的時間在寫它。可以透明地將更改從一個分支轉移到另一個
+分支。等等。明智地使用git修改歷史的能力可以幫助創建問題更少的乾淨補丁集。
+
+然而,過度使用這種功能可能會導致其他問題,而不僅僅是對創建完美項目歷史的
+簡單癡迷。重寫歷史將重寫該歷史中包含的更改,將經過測試(希望如此)的內核樹
+變爲未經測試的內核樹。除此之外,如果開發人員沒有共享項目歷史,他們就無法
+輕鬆地協作;如果您重寫了其他開發人員拉入他們存儲庫的歷史,您將使這些開發
+人員的生活更加困難。因此,這裡有一個簡單的經驗法則:被導出到其他地方的歷史
+在此後通常被認爲是不可變的。
+
+因此,一旦將一組更改推送到公開可用的伺服器上,就不應該重寫這些更改。如果您
+嘗試強制進行無法快進合併的更改(即不共享同一歷史記錄的更改),Git將嘗試強制
+執行此規則。這可能覆蓋檢查,有時甚至需要重寫導出的樹。在樹之間移動變更集以
+避免linux-next中的衝突就是一個例子。但這種行爲應該是罕見的。這就是爲什麼
+開發應該在私有分支中進行(必要時可以重寫)並且只有在公共分支處於合理的較新
+狀態時才轉移到公共分支中的原因之一。
+
+當主線(或其他一組變更所基於的樹)前進時,很容易與該樹合併以保持領先地位。
+對於一個私有的分支,rebasing 可能是一個很容易跟上另一棵樹的方法,但是一旦
+一棵樹被導出到外界,rebasing就不可取了。一旦發生這種情況,就必須進行完全
+合併(merge)。合併有時是很有意義的,但是過於頻繁的合併會不必要地擾亂歷史。
+在這種情況下建議的做法是不要頻繁合併,通常只在特定的發布點(如主線-rc發布)
+合併。如果您對特定的更改感到緊張,則可以始終在私有分支中執行測試合併。在
+這種情況下,git「rerere」工具很有用;它能記住合併衝突是如何解決的,這樣您
+就不必重複相同的工作。
+
+關於Git這樣的工具的一個最大的反覆抱怨是:補丁從一個存儲庫到另一個存儲庫的
+大量移動使得很容易陷入錯誤建議的變更中,這些變更避開審查雷達進入主線。當內
+核開發人員看到這種情況發生時,他們往往會感到不高興;在Git樹上放置未審閱或
+主題外的補丁可能會影響您將來讓樹被拉取的能力。引用Linus的話:
+
+::
+
+   你可以給我發補丁,但當我從你那裡拉取一個Git補丁時,我需要知道你清楚
+   自己在做什麼,我需要能夠相信事情而 *無需* 手動檢查每個單獨的更改。
+
+(http://lwn.net/articles/224135/)。
+
+爲了避免這種情況,請確保給定分支中的所有補丁都與相關主題緊密相關;「驅動程序
+修復」分支不應更改核心內存管理代碼。而且,最重要的是,不要使用Git樹來繞過
+審查過程。不時的將樹的摘要發布到相關的列表中,在合適時候請求linux-next中
+包含該樹。
+
+如果其他人開始發送補丁以包含到您的樹中,不要忘記審閱它們。還要確保您維護正確
+的作者信息; git 「am」工具在這方面做得最好,但是如果補丁通過第三方轉發給您,
+您可能需要在補丁中添加「From:」行。
+
+請求拉取時,請務必提供所有相關信息:樹的位置、要拉取的分支以及拉取將導致的
+更改。在這方面 git request-pull 命令非常有用;它將按照其他開發人員所期望的
+格式化請求,並檢查以確保您已記得將這些更改推送到公共伺服器。
+
+審閱補丁
+--------
+
+一些讀者顯然會反對將本節與「高級主題」放在一起,因爲即使是剛開始的內核開發人員
+也應該審閱補丁。當然,沒有比查看其他人發布的代碼更好的方法來學習如何在內核環境
+中編程了。此外,審閱者永遠供不應求;通過審閱代碼,您可以對整個流程做出重大貢獻。
+
+審查代碼可能是一副令人生畏的圖景,特別是對一個新的內核開發人員來說,他們
+可能會對公開詢問代碼感到緊張,而這些代碼是由那些有更多經驗的人發布的。不過,
+即使是最有經驗的開發人員編寫的代碼也可以得到改進。也許對(所有)審閱者最好
+的建議是:把審閱評論當成問題而不是批評。詢問「在這條路徑中如何釋放鎖?」
+總是比說「這裡的鎖是錯誤的」更好。
+
+不同的開發人員將從不同的角度審查代碼。部分人會主要關注代碼風格以及代碼行是
+否有尾隨空格。其他人會主要關注補丁作爲一個整體實現的變更是否對內核有好處。
+同時也有人會檢查是否存在鎖問題、堆棧使用過度、可能的安全問題、在其他地方
+發現的代碼重複、足夠的文檔、對性能的不利影響、用戶空間ABI更改等。所有類型
+的檢查,只要它們能引導更好的代碼進入內核,都是受歡迎和值得的。
+
diff --git a/Documentation/translations/zh_TW/process/8.Conclusion.rst b/Documentation/translations/zh_TW/process/8.Conclusion.rst
new file mode 100644
index 000000000000..7572b17667d9
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/8.Conclusion.rst
@@ -0,0 +1,74 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/8.Conclusion.rst <development_conclusion>`
+:Translator:
+
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+
+:校譯:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+.. _tw_development_conclusion:
+
+更多信息
+========
+
+關於Linux內核開發和相關主題的信息來源很多。首先是在內核原始碼分發中找到的
+文檔目錄。頂級
+:ref:`Documentation/translations/zh_TW/process/howto.rst <tw_process_howto>`
+文件是一個重要的起點;
+:ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+和 :ref:`Documentation/translations/zh_TW/process/submitting-drivers.rst <tw_submittingdrivers>`
+也是所有內核開發人員都應該閱讀的內容。許多內部內核API都是使用kerneldoc機制
+記錄的;「make htmldocs」或「make pdfdocs」可用於以HTML或PDF格式生成這些文檔
+(儘管某些發行版提供的tex版本會遇到內部限制,無法正確處理文檔)。
+
+不同的網站在各個細節層次上討論內核開發。本文作者想謙虛地建議用 https://lwn.net/
+作爲來源;有關許多特定內核主題的信息可以通過以下網址的 LWN 內核索引找到:
+
+  http://lwn.net/kernel/index/
+
+除此之外,內核開發人員的一個寶貴資源是:
+
+  https://kernelnewbies.org/
+
+當然,也不應該忘記 https://kernel.org/ ,這是內核發布信息的最終位置。
+
+關於內核開發有很多書:
+
+  《Linux設備驅動程序》第三版(Jonathan Corbet、Alessandro Rubini和Greg Kroah Hartman)
+  線上版本在 http://lwn.net/kernel/ldd3/
+
+  《Linux內核設計與實現》(Robert Love)
+
+  《深入理解Linux內核》(Daniel Bovet和Marco Cesati)
+
+然而,所有這些書都有一個共同的缺點:它們上架時就往往有些過時,而且已經上架
+一段時間了。不過,在那裡還是可以找到相當多的好信息。
+
+有關git的文檔,請訪問:
+
+  https://www.kernel.org/pub/software/scm/git/docs/
+
+  https://www.kernel.org/pub/software/scm/git/docs/user-manual.html
+
+結論
+====
+
+祝賀所有通過這篇冗長的文檔的人。希望它能夠幫助您理解Linux內核是如何開發的,
+以及您如何參與這個過程。
+
+最後,重要的是參與。任何開源軟體項目都不會超過其貢獻者投入其中的總和。Linux
+內核的發展速度和以前一樣快,因爲它得到了大量開發人員的幫助,他們都在努力使它
+變得更好。內核是一個最成功的例子,說明了當成千上萬的人爲了一個共同的目標一起
+工作時,可以做出什麼。
+
+不過,內核總是可以從更大的開發人員基礎中獲益。總有更多的工作要做。但是同樣
+重要的是,Linux生態系統中的大多數其他參與者可以通過爲內核做出貢獻而受益。使
+代碼進入主線是提高代碼質量、降低維護和分發成本、提高對內核開發方向的影響程度
+等的關鍵。這是一種共贏的局面。啓動你的編輯器,來加入我們吧;你會非常受歡迎的。
+
diff --git a/Documentation/translations/zh_TW/process/code-of-conduct-interpretation.rst b/Documentation/translations/zh_TW/process/code-of-conduct-interpretation.rst
new file mode 100644
index 000000000000..949d831aaf6c
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/code-of-conduct-interpretation.rst
@@ -0,0 +1,112 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/code-of-conduct-interpretation.rst <code_of_conduct_interpretation>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+.. _tw_code_of_conduct_interpretation:
+
+Linux內核貢獻者契約行為準則解釋
+===============================
+
+:ref:`tw_code_of_conduct` 準則是一個通用文檔,旨在爲幾乎所有開源社區提供一套規則。
+每個開源社區都是獨一無二的,Linux內核也不例外。因此,本文描述了Linux內核社區中
+如何解釋它。我們也不希望這種解釋隨著時間的推移是靜態的,並將根據需要進行調整。
+
+與開發軟體的「傳統」方法相比,Linux內核開發工作是一個非常個人化的過程。你的貢獻
+和背後的想法將被仔細審查,往往導致批判和批評。審查將幾乎總是需要改進,材料才
+能包括在內核中。要知道這是因爲所有相關人員都希望看到Linux整體成功的最佳解決方
+案。這個開發過程已經被證明可以創建有史以來最健壯的作業系統內核,我們不想做任何
+事情來導致提交質量和最終結果的下降。
+
+維護者
+------
+
+行為準則多次使用「維護者」一詞。在內核社區中,「維護者」是負責子系統、驅動程序或
+文件的任何人,並在內核原始碼樹的維護者文件中列出。
+
+責任
+----
+
+《行為準則》提到了維護人員的權利和責任,這需要進一步澄清。
+
+首先,最重要的是,有一個合理的期望是由維護人員通過實例來領導。
+
+也就是說,我們的社區是廣闊的,對維護者沒有新的要求,他們單方面處理其他人在
+他們活躍的社區的行爲。這一責任由我們所有人承擔,最終《行為準則》記錄了最終的
+上訴路徑,以防有關行爲問題的問題懸而未決。
+
+維護人員應該願意在出現問題時提供幫助,並在需要時與社區中的其他人合作。如果您
+不確定如何處理出現的情況,請不要害怕聯繫技術諮詢委員會(TAB)或其他維護人員。
+除非您願意,否則不會將其視爲違規報告。如果您不確定是否該聯繫TAB 或任何其他維
+護人員,請聯繫我們的衝突調解人 Mishi Choudhary <mishi@linux.com>。
+
+最後,「善待對方」才是每個人的最終目標。我們知道每個人都是人,有時我們都會失敗,
+但我們所有人的首要目標應該是努力友好地解決問題。執行行為準則將是最後的選擇。
+
+我們的目標是創建一個強大的、技術先進的作業系統,以及所涉及的技術複雜性,這自
+然需要專業知識和決策。
+
+所需的專業知識因貢獻領域而異。它主要由上下文和技術複雜性決定,其次由貢獻者和
+維護者的期望決定。
+
+專家的期望和決策都要經過討論,但在最後,爲了取得進展,必須能夠做出決策。這一
+特權掌握在維護人員和項目領導的手中,預計將善意使用。
+
+因此,設定專業知識期望、作出決定和拒絕不適當的貢獻不被視爲違反行為準則。
+
+雖然維護人員一般都歡迎新來者,但他們幫助(新)貢獻者克服障礙的能力有限,因此
+他們必須確定優先事項。這也不應被視爲違反了行為準則。內核社區意識到這一點,並
+以各種形式提供入門級節目,如 kernelnewbies.org 。
+
+範圍
+----
+
+Linux內核社區主要在一組公共電子郵件列表上進行交互,這些列表分布在由多個不同
+公司或個人控制的多個不同伺服器上。所有這些列表都在內核原始碼樹中的
+MAINTAINERS 文件中定義。發送到這些郵件列表的任何電子郵件都被視爲包含在行爲
+準則中。
+
+使用 kernel.org bugzilla和其他子系統bugzilla 或bug跟蹤工具的開發人員應該遵循
+行為準則的指導原則。Linux內核社區沒有「官方」項目電子郵件地址或「官方」社交媒體
+地址。使用kernel.org電子郵件帳戶執行的任何活動必須遵循爲kernel.org發布的行爲
+準則,就像任何使用公司電子郵件帳戶的個人必須遵循該公司的特定規則一樣。
+
+行為準則並不禁止在郵件列表消息、內核更改日誌消息或代碼注釋中繼續包含名稱、
+電子郵件地址和相關注釋。
+
+其他論壇中的互動包括在適用於上述論壇的任何規則中,通常不包括在行為準則中。
+除了在極端情況下可考慮的例外情況。
+
+提交給內核的貢獻應該使用適當的語言。在行為準則之前已經存在的內容現在不會被
+視爲違反。然而,不適當的語言可以被視爲一個bug;如果任何相關方提交補丁,
+這樣的bug將被更快地修復。當前屬於用戶/內核API的一部分的表達式,或者反映已
+發布標準或規範中使用的術語的表達式,不被視爲bug。
+
+執行
+----
+
+行為準則中列出的地址屬於行為準則委員會。https://kernel.org/code-of-conduct.html
+列出了在任何給定時間接收這些電子郵件的確切成員。成員不能訪問在加入委員會之前
+或離開委員會之後所做的報告。
+
+最初的行為準則委員會由TAB的志願者以及作爲中立第三方的專業調解人組成。委員會
+的首要任務是建立文件化的流程,並將其公開。
+
+如果報告人不希望將整個委員會納入投訴或關切,可直接聯繫委員會的任何成員,包括
+調解人。
+
+行為準則委員會根據流程審查案例(見上文),並根據需要和適當與TAB協商,例如請求
+和接收有關內核社區的信息。
+
+委員會做出的任何決定都將提交到表中,以便在必要時與相關維護人員一起執行。行爲
+準則委員會的決定可以通過三分之二的投票推翻。
+
+每季度,行為準則委員會和標籤將提供一份報告,概述行為準則委員會收到的匿名報告
+及其狀態,以及任何否決決定的細節,包括完整和可識別的投票細節。
+
+我們希望在啓動期之後爲行為準則委員會人員配備建立一個不同的流程。發生此情況時,
+將使用該信息更新此文檔。
+
diff --git a/Documentation/translations/zh_TW/process/code-of-conduct.rst b/Documentation/translations/zh_TW/process/code-of-conduct.rst
new file mode 100644
index 000000000000..716e5843b6e9
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/code-of-conduct.rst
@@ -0,0 +1,76 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/code-of-conduct.rst <code_of_conduct>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+.. _tw_code_of_conduct:
+
+貢獻者契約行為準則
+++++++++++++++++++
+
+我們的誓言
+==========
+
+爲了營造一個開放、友好的環境,我們作爲貢獻者和維護人承諾,讓我們的社區和參
+與者,擁有一個無騷擾的體驗,無論年齡、體型、殘疾、種族、性別特徵、性別認同
+和表達、經驗水平、教育程度、社會狀況,經濟地位、國籍、個人外貌、種族、宗教
+或性身份和取向。
+
+我們的標準
+==========
+
+有助於創造積極環境的行爲包括:
+
+* 使用歡迎和包容的語言
+* 尊重不同的觀點和經驗
+* 優雅地接受建設性的批評
+* 關注什麼對社區最有利
+* 對其他社區成員表示同情
+
+參與者的不可接受行爲包括:
+
+* 使用性意味的語言或意象以及不受歡迎的性注意或者更過分的行爲
+* 煽動、侮辱/貶損評論以及個人或政治攻擊
+* 公開或私下騷擾
+* 未經明確許可,發布他人的私人信息,如物理或電子地址。
+* 在專業場合被合理認爲不適當的其他行爲
+
+我們的責任
+==========
+
+維護人員負責澄清可接受行爲的標準,並應針對任何不可接受行爲採取適當和公平的
+糾正措施。
+
+維護人員有權和責任刪除、編輯或拒絕與本行為準則不一致的評論、承諾、代碼、
+wiki編輯、問題和其他貢獻,或暫時或永久禁止任何貢獻者從事他們認爲不適當、
+威脅、冒犯或有害的其他行爲。
+
+範圍
+====
+
+當個人代表項目或其社區時,本行為準則既適用於項目空間,也適用於公共空間。
+代表一個項目或社區的例子包括使用一個正式的項目電子郵件地址,通過一個正式
+的社交媒體帳戶發布,或者在在線或離線事件中擔任指定的代表。項目維護人員可以
+進一步定義和澄清項目的表示。
+
+執行
+====
+
+如有濫用、騷擾或其他不可接受的行爲,可聯繫行為準則委員會<conduct@kernel.org>。
+所有投訴都將接受審查和調查,並將得到必要和適當的答覆。行為準則委員會有義務
+對事件報告人保密。具體執行政策的進一步細節可單獨公布。
+
+歸屬
+====
+
+本行為準則改編自《貢獻者契約》,版本1.4,可從
+https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 獲取。
+
+解釋
+====
+
+有關Linux內核社區如何解釋此文檔,請參閱 :ref:`tw_code_of_conduct_interpretation`
+
diff --git a/Documentation/translations/zh_TW/process/coding-style.rst b/Documentation/translations/zh_TW/process/coding-style.rst
new file mode 100644
index 000000000000..61e614aad6a7
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/coding-style.rst
@@ -0,0 +1,958 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/coding-style.rst <codingstyle>`
+
+.. _tw_codingstyle:
+
+譯者::
+
+  中文版維護者: 張樂 Zhang Le <r0bertz@gentoo.org>
+  中文版翻譯者: 張樂 Zhang Le <r0bertz@gentoo.org>
+  中文版校譯者: 王聰 Wang Cong <xiyou.wangcong@gmail.com>
+                 wheelz <kernel.zeng@gmail.com>
+                 管旭東 Xudong Guan <xudong.guan@gmail.com>
+                 Li Zefan <lizf@cn.fujitsu.com>
+                 Wang Chen <wangchen@cn.fujitsu.com>
+                 Hu Haowen <src.res@email.cn>
+
+Linux 內核代碼風格
+=========================
+
+這是一個簡短的文檔,描述了 linux 內核的首選代碼風格。代碼風格是因人而異的,
+而且我不願意把自己的觀點強加給任何人,但這就像我去做任何事情都必須遵循的原則
+那樣,我也希望在絕大多數事上保持這種的態度。請 (在寫代碼時) 至少考慮一下這裡
+的代碼風格。
+
+首先,我建議你列印一份 GNU 代碼規範,然後不要讀。燒了它,這是一個具有重大象徵
+性意義的動作。
+
+不管怎樣,現在我們開始:
+
+
+1) 縮進
+--------------
+
+制表符是 8 個字符,所以縮進也是 8 個字符。有些異端運動試圖將縮進變爲 4 (甚至
+2!) 字符深,這幾乎相當於嘗試將圓周率的值定義爲 3。
+
+理由:縮進的全部意義就在於清楚的定義一個控制塊起止於何處。尤其是當你盯著你的
+屏幕連續看了 20 小時之後,你將會發現大一點的縮進會使你更容易分辨縮進。
+
+現在,有些人會抱怨 8 個字符的縮進會使代碼向右邊移動的太遠,在 80 個字符的終端
+屏幕上就很難讀這樣的代碼。這個問題的答案是,如果你需要 3 級以上的縮進,不管用
+何種方式你的代碼已經有問題了,應該修正你的程序。
+
+簡而言之,8 個字符的縮進可以讓代碼更容易閱讀,還有一個好處是當你的函數嵌套太
+深的時候可以給你警告。留心這個警告。
+
+在 switch 語句中消除多級縮進的首選的方式是讓 ``switch`` 和從屬於它的 ``case``
+標籤對齊於同一列,而不要 ``兩次縮進`` ``case`` 標籤。比如:
+
+.. code-block:: c
+
+	switch (suffix) {
+	case 'G':
+	case 'g':
+		mem <<= 30;
+		break;
+	case 'M':
+	case 'm':
+		mem <<= 20;
+		break;
+	case 'K':
+	case 'k':
+		mem <<= 10;
+		fallthrough;
+	default:
+		break;
+	}
+
+不要把多個語句放在一行里,除非你有什麼東西要隱藏:
+
+.. code-block:: c
+
+	if (condition) do_this;
+	  do_something_everytime;
+
+也不要在一行里放多個賦值語句。內核代碼風格超級簡單。就是避免可能導致別人誤讀
+的表達式。
+
+除了注釋、文檔和 Kconfig 之外,不要使用空格來縮進,前面的例子是例外,是有意爲
+之。
+
+選用一個好的編輯器,不要在行尾留空格。
+
+
+2) 把長的行和字符串打散
+------------------------------
+
+代碼風格的意義就在於使用平常使用的工具來維持代碼的可讀性和可維護性。
+
+每一行的長度的限制是 80 列,我們強烈建議您遵守這個慣例。
+
+長於 80 列的語句要打散成有意義的片段。除非超過 80 列能顯著增加可讀性,並且不
+會隱藏信息。子片段要明顯短於母片段,並明顯靠右。這同樣適用於有著很長參數列表
+的函數頭。然而,絕對不要打散對用戶可見的字符串,例如 printk 信息,因爲這樣就
+很難對它們 grep。
+
+
+3) 大括號和空格的放置
+------------------------------
+
+C 語言風格中另外一個常見問題是大括號的放置。和縮進大小不同,選擇或棄用某种放
+置策略並沒有多少技術上的原因,不過首選的方式,就像 Kernighan 和 Ritchie 展示
+給我們的,是把起始大括號放在行尾,而把結束大括號放在行首,所以:
+
+.. code-block:: c
+
+	if (x is true) {
+		we do y
+	}
+
+這適用於所有的非函數語句塊 (if, switch, for, while, do)。比如:
+
+.. code-block:: c
+
+	switch (action) {
+	case KOBJ_ADD:
+		return "add";
+	case KOBJ_REMOVE:
+		return "remove";
+	case KOBJ_CHANGE:
+		return "change";
+	default:
+		return NULL;
+	}
+
+不過,有一個例外,那就是函數:函數的起始大括號放置於下一行的開頭,所以:
+
+.. code-block:: c
+
+	int function(int x)
+	{
+		body of function
+	}
+
+全世界的異端可能會抱怨這個不一致性是... 呃... 不一致的,不過所有思維健全的人
+都知道 (a) K&R 是 **正確的** 並且 (b) K&R 是正確的。此外,不管怎樣函數都是特
+殊的 (C 函數是不能嵌套的)。
+
+注意結束大括號獨自占據一行,除非它後面跟著同一個語句的剩餘部分,也就是 do 語
+句中的 "while" 或者 if 語句中的 "else",像這樣:
+
+.. code-block:: c
+
+	do {
+		body of do-loop
+	} while (condition);
+
+和
+
+.. code-block:: c
+
+	if (x == y) {
+		..
+	} else if (x > y) {
+		...
+	} else {
+		....
+	}
+
+理由:K&R。
+
+也請注意這種大括號的放置方式也能使空 (或者差不多空的) 行的數量最小化,同時不
+失可讀性。因此,由於你的屏幕上的新行是不可再生資源 (想想 25 行的終端屏幕),你
+將會有更多的空行來放置注釋。
+
+當只有一個單獨的語句的時候,不用加不必要的大括號。
+
+.. code-block:: c
+
+	if (condition)
+		action();
+
+和
+
+.. code-block:: c
+
+	if (condition)
+		do_this();
+	else
+		do_that();
+
+這並不適用於只有一個條件分支是單語句的情況;這時所有分支都要使用大括號:
+
+.. code-block:: c
+
+	if (condition) {
+		do_this();
+		do_that();
+	} else {
+		otherwise();
+	}
+
+3.1) 空格
+********************
+
+Linux 內核的空格使用方式 (主要) 取決於它是用於函數還是關鍵字。(大多數) 關鍵字
+後要加一個空格。值得注意的例外是 sizeof, typeof, alignof 和 __attribute__,這
+些關鍵字某些程度上看起來更像函數 (它們在 Linux 里也常常伴隨小括號而使用,儘管
+在 C 里這樣的小括號不是必需的,就像 ``struct fileinfo info;`` 聲明過後的
+``sizeof info``)。
+
+所以在這些關鍵字之後放一個空格::
+
+	if, switch, case, for, do, while
+
+但是不要在 sizeof, typeof, alignof 或者 __attribute__ 這些關鍵字之後放空格。
+例如,
+
+.. code-block:: c
+
+	s = sizeof(struct file);
+
+不要在小括號里的表達式兩側加空格。這是一個 **反例** :
+
+.. code-block:: c
+
+	s = sizeof( struct file );
+
+當聲明指針類型或者返回指針類型的函數時, ``*`` 的首選使用方式是使之靠近變量名
+或者函數名,而不是靠近類型名。例子:
+
+.. code-block:: c
+
+	char *linux_banner;
+	unsigned long long memparse(char *ptr, char **retptr);
+	char *match_strdup(substring_t *s);
+
+在大多數二元和三元操作符兩側使用一個空格,例如下面所有這些操作符::
+
+	=  +  -  <  >  *  /  %  |  &  ^  <=  >=  ==  !=  ?  :
+
+但是一元操作符後不要加空格::
+
+	&  *  +  -  ~  !  sizeof  typeof  alignof  __attribute__  defined
+
+後綴自加和自減一元操作符前不加空格::
+
+	++  --
+
+前綴自加和自減一元操作符後不加空格::
+
+	++  --
+
+``.`` 和 ``->`` 結構體成員操作符前後不加空格。
+
+不要在行尾留空白。有些可以自動縮進的編輯器會在新行的行首加入適量的空白,然後
+你就可以直接在那一行輸入代碼。不過假如你最後沒有在那一行輸入代碼,有些編輯器
+就不會移除已經加入的空白,就像你故意留下一個只有空白的行。包含行尾空白的行就
+這樣產生了。
+
+當 git 發現補丁包含了行尾空白的時候會警告你,並且可以應你的要求去掉行尾空白;
+不過如果你是正在打一系列補丁,這樣做會導致後面的補丁失敗,因爲你改變了補丁的
+上下文。
+
+
+4) 命名
+------------------------------
+
+C 是一個簡樸的語言,你的命名也應該這樣。和 Modula-2 和 Pascal 程式設計師不同,
+C 程式設計師不使用類似 ThisVariableIsATemporaryCounter 這樣華麗的名字。C 程式設計師會
+稱那個變量爲 ``tmp`` ,這樣寫起來會更容易,而且至少不會令其難於理解。
+
+不過,雖然混用大小寫的名字是不提倡使用的,但是全局變量還是需要一個具描述性的
+名字。稱一個全局函數爲 ``foo`` 是一個難以饒恕的錯誤。
+
+全局變量 (只有當你 **真正** 需要它們的時候再用它) 需要有一個具描述性的名字,就
+像全局函數。如果你有一個可以計算活動用戶數量的函數,你應該叫它
+``count_active_users()`` 或者類似的名字,你不應該叫它 ``cntuser()`` 。
+
+在函數名中包含函數類型 (所謂的匈牙利命名法) 是腦子出了問題——編譯器知道那些類
+型而且能夠檢查那些類型,這樣做只能把程式設計師弄糊塗了。難怪微軟總是製造出有問題
+的程序。
+
+本地變量名應該簡短,而且能夠表達相關的含義。如果你有一些隨機的整數型的循環計
+數器,它應該被稱爲 ``i`` 。叫它 ``loop_counter`` 並無益處,如果它沒有被誤解的
+可能的話。類似的, ``tmp`` 可以用來稱呼任意類型的臨時變量。
+
+如果你怕混淆了你的本地變量名,你就遇到另一個問題了,叫做函數增長荷爾蒙失衡綜
+合症。請看第六章 (函數)。
+
+
+5) Typedef
+-----------
+
+不要使用類似 ``vps_t`` 之類的東西。
+
+對結構體和指針使用 typedef 是一個 **錯誤** 。當你在代碼里看到:
+
+.. code-block:: c
+
+	vps_t a;
+
+這代表什麼意思呢?
+
+相反,如果是這樣
+
+.. code-block:: c
+
+	struct virtual_container *a;
+
+你就知道 ``a`` 是什麼了。
+
+很多人認爲 typedef ``能提高可讀性`` 。實際不是這樣的。它們只在下列情況下有用:
+
+ (a) 完全不透明的對象 (這種情況下要主動使用 typedef 來 **隱藏** 這個對象實際上
+     是什麼)。
+
+     例如: ``pte_t`` 等不透明對象,你只能用合適的訪問函數來訪問它們。
+
+     .. note::
+
+       不透明性和 "訪問函數" 本身是不好的。我們使用 pte_t 等類型的原因在於真
+       的是完全沒有任何共用的可訪問信息。
+
+ (b) 清楚的整數類型,如此,這層抽象就可以 **幫助** 消除到底是 ``int`` 還是
+     ``long`` 的混淆。
+
+     u8/u16/u32 是完全沒有問題的 typedef,不過它們更符合類別 (d) 而不是這裡。
+
+     .. note::
+
+       要這樣做,必須事出有因。如果某個變量是 ``unsigned long`` ,那麼沒有必要
+
+	typedef unsigned long myflags_t;
+
+     不過如果有一個明確的原因,比如它在某種情況下可能會是一個 ``unsigned int``
+     而在其他情況下可能爲 ``unsigned long`` ,那麼就不要猶豫,請務必使用
+     typedef。
+
+ (c) 當你使用 sparse 按字面的創建一個 **新** 類型來做類型檢查的時候。
+
+ (d) 和標準 C99 類型相同的類型,在某些例外的情況下。
+
+     雖然讓眼睛和腦筋來適應新的標準類型比如 ``uint32_t`` 不需要花很多時間,可
+     是有些人仍然拒絕使用它們。
+
+     因此,Linux 特有的等同於標準類型的 ``u8/u16/u32/u64`` 類型和它們的有符號
+     類型是被允許的——儘管在你自己的新代碼中,它們不是強制要求要使用的。
+
+     當編輯已經使用了某個類型集的已有代碼時,你應該遵循那些代碼中已經做出的選
+     擇。
+
+ (e) 可以在用戶空間安全使用的類型。
+
+     在某些用戶空間可見的結構體裡,我們不能要求 C99 類型而且不能用上面提到的
+     ``u32`` 類型。因此,我們在與用戶空間共享的所有結構體中使用 __u32 和類似
+     的類型。
+
+可能還有其他的情況,不過基本的規則是 **永遠不要** 使用 typedef,除非你可以明
+確的應用上述某個規則中的一個。
+
+總的來說,如果一個指針或者一個結構體裡的元素可以合理的被直接訪問到,那麼它們
+就不應該是一個 typedef。
+
+
+6) 函數
+------------------------------
+
+函數應該簡短而漂亮,並且只完成一件事情。函數應該可以一屏或者兩屏顯示完 (我們
+都知道 ISO/ANSI 屏幕大小是 80x24),只做一件事情,而且把它做好。
+
+一個函數的最大長度是和該函數的複雜度和縮進級數成反比的。所以,如果你有一個理
+論上很簡單的只有一個很長 (但是簡單) 的 case 語句的函數,而且你需要在每個 case
+里做很多很小的事情,這樣的函數儘管很長,但也是可以的。
+
+不過,如果你有一個複雜的函數,而且你懷疑一個天分不是很高的高中一年級學生可能
+甚至搞不清楚這個函數的目的,你應該嚴格遵守前面提到的長度限制。使用輔助函數,
+並爲之取個具描述性的名字 (如果你覺得它們的性能很重要的話,可以讓編譯器內聯它
+們,這樣的效果往往會比你寫一個複雜函數的效果要好。)
+
+函數的另外一個衡量標準是本地變量的數量。此數量不應超過 5-10 個,否則你的函數
+就有問題了。重新考慮一下你的函數,把它分拆成更小的函數。人的大腦一般可以輕鬆
+的同時跟蹤 7 個不同的事物,如果再增多的話,就會糊塗了。即便你聰穎過人,你也可
+能會記不清你 2 個星期前做過的事情。
+
+在源文件里,使用空行隔開不同的函數。如果該函數需要被導出,它的 **EXPORT** 宏
+應該緊貼在它的結束大括號之下。比如:
+
+.. code-block:: c
+
+	int system_is_up(void)
+	{
+		return system_state == SYSTEM_RUNNING;
+	}
+	EXPORT_SYMBOL(system_is_up);
+
+在函數原型中,包含函數名和它們的數據類型。雖然 C 語言裡沒有這樣的要求,在
+Linux 里這是提倡的做法,因爲這樣可以很簡單的給讀者提供更多的有價值的信息。
+
+
+7) 集中的函數退出途徑
+------------------------------
+
+雖然被某些人聲稱已經過時,但是 goto 語句的等價物還是經常被編譯器所使用,具體
+形式是無條件跳轉指令。
+
+當一個函數從多個位置退出,並且需要做一些類似清理的常見操作時,goto 語句就很方
+便了。如果並不需要清理操作,那麼直接 return 即可。
+
+選擇一個能夠說明 goto 行爲或它爲何存在的標籤名。如果 goto 要釋放 ``buffer``,
+一個不錯的名字可以是 ``out_free_buffer:`` 。別去使用像 ``err1:`` 和 ``err2:``
+這樣的GW_BASIC 名稱,因爲一旦你添加或刪除了 (函數的) 退出路徑,你就必須對它們
+重新編號,這樣會難以去檢驗正確性。
+
+使用 goto 的理由是:
+
+- 無條件語句容易理解和跟蹤
+- 嵌套程度減小
+- 可以避免由於修改時忘記更新個別的退出點而導致錯誤
+- 讓編譯器省去刪除冗餘代碼的工作 ;)
+
+.. code-block:: c
+
+	int fun(int a)
+	{
+		int result = 0;
+		char *buffer;
+
+		buffer = kmalloc(SIZE, GFP_KERNEL);
+		if (!buffer)
+			return -ENOMEM;
+
+		if (condition1) {
+			while (loop1) {
+				...
+			}
+			result = 1;
+			goto out_free_buffer;
+		}
+		...
+	out_free_buffer:
+		kfree(buffer);
+		return result;
+	}
+
+一個需要注意的常見錯誤是 ``一個 err 錯誤`` ,就像這樣:
+
+.. code-block:: c
+
+	err:
+		kfree(foo->bar);
+		kfree(foo);
+		return ret;
+
+這段代碼的錯誤是,在某些退出路徑上 ``foo`` 是 NULL。通常情況下,通過把它分離
+成兩個錯誤標籤 ``err_free_bar:`` 和 ``err_free_foo:`` 來修復這個錯誤:
+
+.. code-block:: c
+
+	 err_free_bar:
+		kfree(foo->bar);
+	 err_free_foo:
+		kfree(foo);
+		return ret;
+
+理想情況下,你應該模擬錯誤來測試所有退出路徑。
+
+
+8) 注釋
+------------------------------
+
+注釋是好的,不過有過度注釋的危險。永遠不要在注釋里解釋你的代碼是如何運作的:
+更好的做法是讓別人一看你的代碼就可以明白,解釋寫的很差的代碼是浪費時間。
+
+一般的,你想要你的注釋告訴別人你的代碼做了什麼,而不是怎麼做的。也請你不要把
+注釋放在一個函數體內部:如果函數複雜到你需要獨立的注釋其中的一部分,你很可能
+需要回到第六章看一看。你可以做一些小注釋來註明或警告某些很聰明 (或者槽糕) 的
+做法,但不要加太多。你應該做的,是把注釋放在函數的頭部,告訴人們它做了什麼,
+也可以加上它做這些事情的原因。
+
+當注釋內核 API 函數時,請使用 kernel-doc 格式。請看
+Documentation/doc-guide/ 和 scripts/kernel-doc 以獲得詳細信息。
+
+長 (多行) 注釋的首選風格是:
+
+.. code-block:: c
+
+	/*
+	 * This is the preferred style for multi-line
+	 * comments in the Linux kernel source code.
+	 * Please use it consistently.
+	 *
+	 * Description:  A column of asterisks on the left side,
+	 * with beginning and ending almost-blank lines.
+	 */
+
+對於在 net/ 和 drivers/net/ 的文件,首選的長 (多行) 注釋風格有些不同。
+
+.. code-block:: c
+
+	/* The preferred comment style for files in net/ and drivers/net
+	 * looks like this.
+	 *
+	 * It is nearly the same as the generally preferred comment style,
+	 * but there is no initial almost-blank line.
+	 */
+
+注釋數據也是很重要的,不管是基本類型還是衍生類型。爲了方便實現這一點,每一行
+應只聲明一個數據 (不要使用逗號來一次聲明多個數據)。這樣你就有空間來爲每個數據
+寫一段小注釋來解釋它們的用途了。
+
+
+9) 你已經把事情弄糟了
+------------------------------
+
+這沒什麼,我們都是這樣。可能你的使用了很長時間 Unix 的朋友已經告訴你
+``GNU emacs`` 能自動幫你格式化 C 原始碼,而且你也注意到了,確實是這樣,不過它
+所使用的默認值和我們想要的相去甚遠 (實際上,甚至比隨機打的還要差——無數個猴子
+在 GNU emacs 里打字永遠不會創造出一個好程序) (譯註:Infinite Monkey Theorem)
+
+所以你要麼放棄 GNU emacs,要麼改變它讓它使用更合理的設定。要採用後一個方案,
+你可以把下面這段粘貼到你的 .emacs 文件里。
+
+.. code-block:: none
+
+  (defun c-lineup-arglist-tabs-only (ignored)
+    "Line up argument lists by tabs, not spaces"
+    (let* ((anchor (c-langelem-pos c-syntactic-element))
+           (column (c-langelem-2nd-pos c-syntactic-element))
+           (offset (- (1+ column) anchor))
+           (steps (floor offset c-basic-offset)))
+      (* (max steps 1)
+         c-basic-offset)))
+
+  (dir-locals-set-class-variables
+   'linux-kernel
+   '((c-mode . (
+          (c-basic-offset . 8)
+          (c-label-minimum-indentation . 0)
+          (c-offsets-alist . (
+                  (arglist-close         . c-lineup-arglist-tabs-only)
+                  (arglist-cont-nonempty .
+		      (c-lineup-gcc-asm-reg c-lineup-arglist-tabs-only))
+                  (arglist-intro         . +)
+                  (brace-list-intro      . +)
+                  (c                     . c-lineup-C-comments)
+                  (case-label            . 0)
+                  (comment-intro         . c-lineup-comment)
+                  (cpp-define-intro      . +)
+                  (cpp-macro             . -1000)
+                  (cpp-macro-cont        . +)
+                  (defun-block-intro     . +)
+                  (else-clause           . 0)
+                  (func-decl-cont        . +)
+                  (inclass               . +)
+                  (inher-cont            . c-lineup-multi-inher)
+                  (knr-argdecl-intro     . 0)
+                  (label                 . -1000)
+                  (statement             . 0)
+                  (statement-block-intro . +)
+                  (statement-case-intro  . +)
+                  (statement-cont        . +)
+                  (substatement          . +)
+                  ))
+          (indent-tabs-mode . t)
+          (show-trailing-whitespace . t)
+          ))))
+
+  (dir-locals-set-directory-class
+   (expand-file-name "~/src/linux-trees")
+   'linux-kernel)
+
+這會讓 emacs 在 ``~/src/linux-trees`` 下的 C 源文件獲得更好的內核代碼風格。
+
+不過就算你嘗試讓 emacs 正確的格式化代碼失敗了,也並不意味著你失去了一切:還可
+以用 ``indent`` 。
+
+不過,GNU indent 也有和 GNU emacs 一樣有問題的設定,所以你需要給它一些命令選
+項。不過,這還不算太糟糕,因爲就算是 GNU indent 的作者也認同 K&R 的權威性
+(GNU 的人並不是壞人,他們只是在這個問題上被嚴重的誤導了),所以你只要給 indent
+指定選項 ``-kr -i8`` (代表 ``K&R,8 字符縮進``),或使用 ``scripts/Lindent``
+這樣就可以以最時髦的方式縮進原始碼。
+
+``indent`` 有很多選項,特別是重新格式化注釋的時候,你可能需要看一下它的手冊。
+不過記住: ``indent`` 不能修正壞的編程習慣。
+
+
+10) Kconfig 配置文件
+------------------------------
+
+對於遍布源碼樹的所有 Kconfig* 配置文件來說,它們縮進方式有所不同。緊挨著
+``config`` 定義的行,用一個制表符縮進,然而 help 信息的縮進則額外增加 2 個空
+格。舉個例子::
+
+  config AUDIT
+	bool "Auditing support"
+	depends on NET
+	help
+	  Enable auditing infrastructure that can be used with another
+	  kernel subsystem, such as SELinux (which requires this for
+	  logging of avc messages output).  Does not do system-call
+	  auditing without CONFIG_AUDITSYSCALL.
+
+而那些危險的功能 (比如某些文件系統的寫支持) 應該在它們的提示字符串里顯著的聲
+明這一點::
+
+  config ADFS_FS_RW
+	bool "ADFS write support (DANGEROUS)"
+	depends on ADFS_FS
+	...
+
+要查看配置文件的完整文檔,請看 Documentation/kbuild/kconfig-language.rst。
+
+
+11) 數據結構
+------------------------------
+
+如果一個數據結構,在創建和銷毀它的單線執行環境之外可見,那麼它必須要有一個引
+用計數器。內核里沒有垃圾收集 (並且內核之外的垃圾收集慢且效率低下),這意味著你
+絕對需要記錄你對這種數據結構的使用情況。
+
+引用計數意味著你能夠避免上鎖,並且允許多個用戶並行訪問這個數據結構——而不需要
+擔心這個數據結構僅僅因爲暫時不被使用就消失了,那些用戶可能不過是沉睡了一陣或
+者做了一些其他事情而已。
+
+注意上鎖 **不能** 取代引用計數。上鎖是爲了保持數據結構的一致性,而引用計數是一
+個內存管理技巧。通常二者都需要,不要把兩個搞混了。
+
+很多數據結構實際上有 2 級引用計數,它們通常有不同 ``類`` 的用戶。子類計數器統
+計子類用戶的數量,每當子類計數器減至零時,全局計數器減一。
+
+這種 ``多級引用計數`` 的例子可以在內存管理 (``struct mm_struct``: mm_users 和
+mm_count),和文件系統 (``struct super_block``: s_count 和 s_active) 中找到。
+
+記住:如果另一個執行線索可以找到你的數據結構,但這個數據結構沒有引用計數器,
+這裡幾乎肯定是一個 bug。
+
+
+12) 宏,枚舉和RTL
+------------------------------
+
+用於定義常量的宏的名字及枚舉里的標籤需要大寫。
+
+.. code-block:: c
+
+	#define CONSTANT 0x12345
+
+在定義幾個相關的常量時,最好用枚舉。
+
+宏的名字請用大寫字母,不過形如函數的宏的名字可以用小寫字母。
+
+一般的,如果能寫成內聯函數就不要寫成像函數的宏。
+
+含有多個語句的宏應該被包含在一個 do-while 代碼塊里:
+
+.. code-block:: c
+
+	#define macrofun(a, b, c)			\
+		do {					\
+			if (a == 5)			\
+				do_this(b, c);		\
+		} while (0)
+
+使用宏的時候應避免的事情:
+
+1) 影響控制流程的宏:
+
+.. code-block:: c
+
+	#define FOO(x)					\
+		do {					\
+			if (blah(x) < 0)		\
+				return -EBUGGERED;	\
+		} while (0)
+
+**非常** 不好。它看起來像一個函數,不過卻能導致 ``調用`` 它的函數退出;不要打
+亂讀者大腦里的語法分析器。
+
+2) 依賴於一個固定名字的本地變量的宏:
+
+.. code-block:: c
+
+	#define FOO(val) bar(index, val)
+
+可能看起來像是個不錯的東西,不過它非常容易把讀代碼的人搞糊塗,而且容易導致看起
+來不相關的改動帶來錯誤。
+
+3) 作爲左值的帶參數的宏: FOO(x) = y;如果有人把 FOO 變成一個內聯函數的話,這
+   種用法就會出錯了。
+
+4) 忘記了優先級:使用表達式定義常量的宏必須將表達式置於一對小括號之內。帶參數
+   的宏也要注意此類問題。
+
+.. code-block:: c
+
+	#define CONSTANT 0x4000
+	#define CONSTEXP (CONSTANT | 3)
+
+5) 在宏里定義類似函數的本地變量時命名衝突:
+
+.. code-block:: c
+
+	#define FOO(x)				\
+	({					\
+		typeof(x) ret;			\
+		ret = calc_ret(x);		\
+		(ret);				\
+	})
+
+ret 是本地變量的通用名字 - __foo_ret 更不容易與一個已存在的變量衝突。
+
+cpp 手冊對宏的講解很詳細。gcc internals 手冊也詳細講解了 RTL,內核里的彙編語
+言經常用到它。
+
+
+13) 列印內核消息
+------------------------------
+
+內核開發者應該是受過良好教育的。請一定注意內核信息的拼寫,以給人以好的印象。
+不要用不規範的單詞比如 ``dont``,而要用 ``do not`` 或者 ``don't`` 。保證這些信
+息簡單明了,無歧義。
+
+內核信息不必以英文句號結束。
+
+在小括號里列印數字 (%d) 沒有任何價值,應該避免這樣做。
+
+<linux/device.h> 里有一些驅動模型診斷宏,你應該使用它們,以確保信息對應於正確
+的設備和驅動,並且被標記了正確的消息級別。這些宏有:dev_err(), dev_warn(),
+dev_info() 等等。對於那些不和某個特定設備相關連的信息,<linux/printk.h> 定義
+了 pr_notice(), pr_info(), pr_warn(), pr_err() 和其他。
+
+寫出好的調試信息可以是一個很大的挑戰;一旦你寫出後,這些信息在遠程除錯時能提
+供極大的幫助。然而列印調試信息的處理方式同列印非調試信息不同。其他 pr_XXX()
+函數能無條件地列印,pr_debug() 卻不;默認情況下它不會被編譯,除非定義了 DEBUG
+或設定了 CONFIG_DYNAMIC_DEBUG。實際這同樣是爲了 dev_dbg(),一個相關約定是在一
+個已經開啓了 DEBUG 時,使用 VERBOSE_DEBUG 來添加 dev_vdbg()。
+
+許多子系統擁有 Kconfig 調試選項來開啓 -DDEBUG 在對應的 Makefile 裡面;在其他
+情況下,特殊文件使用 #define DEBUG。當一條調試信息需要被無條件列印時,例如,
+如果已經包含一個調試相關的 #ifdef 條件,printk(KERN_DEBUG ...) 就可被使用。
+
+
+14) 分配內存
+------------------------------
+
+內核提供了下面的一般用途的內存分配函數:
+kmalloc(), kzalloc(), kmalloc_array(), kcalloc(), vmalloc() 和 vzalloc()。
+請參考 API 文檔以獲取有關它們的詳細信息。
+
+傳遞結構體大小的首選形式是這樣的:
+
+.. code-block:: c
+
+	p = kmalloc(sizeof(*p), ...);
+
+另外一種傳遞方式中,sizeof 的操作數是結構體的名字,這樣會降低可讀性,並且可能
+會引入 bug。有可能指針變量類型被改變時,而對應的傳遞給內存分配函數的 sizeof
+的結果不變。
+
+強制轉換一個 void 指針返回值是多餘的。C 語言本身保證了從 void 指針到其他任何
+指針類型的轉換是沒有問題的。
+
+分配一個數組的首選形式是這樣的:
+
+.. code-block:: c
+
+	p = kmalloc_array(n, sizeof(...), ...);
+
+分配一個零長數組的首選形式是這樣的:
+
+.. code-block:: c
+
+	p = kcalloc(n, sizeof(...), ...);
+
+兩種形式檢查分配大小 n * sizeof(...) 的溢出,如果溢出返回 NULL。
+
+
+15) 內聯弊病
+------------------------------
+
+有一個常見的誤解是 ``內聯`` 是 gcc 提供的可以讓代碼運行更快的一個選項。雖然使
+用內聯函數有時候是恰當的 (比如作爲一種替代宏的方式,請看第十二章),不過很多情
+況下不是這樣。inline 的過度使用會使內核變大,從而使整個系統運行速度變慢。
+因爲體積大內核會占用更多的指令高速緩存,而且會導致 pagecache 的可用內存減少。
+想像一下,一次 pagecache 未命中就會導致一次磁碟尋址,將耗時 5 毫秒。5 毫秒的
+時間內 CPU 能執行很多很多指令。
+
+一個基本的原則是如果一個函數有 3 行以上,就不要把它變成內聯函數。這個原則的一
+個例外是,如果你知道某個參數是一個編譯時常量,而且因爲這個常量你確定編譯器在
+編譯時能優化掉你的函數的大部分代碼,那仍然可以給它加上 inline 關鍵字。
+kmalloc() 內聯函數就是一個很好的例子。
+
+人們經常主張給 static 的而且只用了一次的函數加上 inline,如此不會有任何損失,
+因爲沒有什麼好權衡的。雖然從技術上說這是正確的,但是實際上這種情況下即使不加
+inline gcc 也可以自動使其內聯。而且其他用戶可能會要求移除 inline,由此而來的
+爭論會抵消 inline 自身的潛在價值,得不償失。
+
+
+16) 函數返回值及命名
+------------------------------
+
+函數可以返回多種不同類型的值,最常見的一種是表明函數執行成功或者失敗的值。這樣
+的一個值可以表示爲一個錯誤代碼整數 (-Exxx=失敗,0=成功) 或者一個 ``成功``
+布爾值 (0=失敗,非0=成功)。
+
+混合使用這兩種表達方式是難於發現的 bug 的來源。如果 C 語言本身嚴格區分整形和
+布爾型變量,那麼編譯器就能夠幫我們發現這些錯誤... 不過 C 語言不區分。爲了避免
+產生這種 bug,請遵循下面的慣例::
+
+	如果函數的名字是一個動作或者強制性的命令,那麼這個函數應該返回錯誤代
+	碼整數。如果是一個判斷,那麼函數應該返回一個 "成功" 布爾值。
+
+比如, ``add work`` 是一個命令,所以 add_work() 在成功時返回 0,在失敗時返回
+-EBUSY。類似的,因爲 ``PCI device present`` 是一個判斷,所以 pci_dev_present()
+在成功找到一個匹配的設備時應該返回 1,如果找不到時應該返回 0。
+
+所有 EXPORTed 函數都必須遵守這個慣例,所有的公共函數也都應該如此。私有
+(static) 函數不需要如此,但是我們也推薦這樣做。
+
+返回值是實際計算結果而不是計算是否成功的標誌的函數不受此慣例的限制。一般的,
+他們通過返回一些正常值範圍之外的結果來表示出錯。典型的例子是返回指針的函數,
+他們使用 NULL 或者 ERR_PTR 機制來報告錯誤。
+
+
+17) 不要重新發明內核宏
+------------------------------
+
+頭文件 include/linux/kernel.h 包含了一些宏,你應該使用它們,而不要自己寫一些
+它們的變種。比如,如果你需要計算一個數組的長度,使用這個宏
+
+.. code-block:: c
+
+	#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+類似的,如果你要計算某結構體成員的大小,使用
+
+.. code-block:: c
+
+	#define sizeof_field(t, f) (sizeof(((t*)0)->f))
+
+還有可以做嚴格的類型檢查的 min() 和 max() 宏,如果你需要可以使用它們。你可以
+自己看看那個頭文件里還定義了什麼你可以拿來用的東西,如果有定義的話,你就不應
+在你的代碼里自己重新定義。
+
+
+18) 編輯器模式行和其他需要羅嗦的事情
+--------------------------------------------------
+
+有一些編輯器可以解釋嵌入在源文件里的由一些特殊標記標明的配置信息。比如,emacs
+能夠解釋被標記成這樣的行:
+
+.. code-block:: c
+
+	-*- mode: c -*-
+
+或者這樣的:
+
+.. code-block:: c
+
+	/*
+	Local Variables:
+	compile-command: "gcc -DMAGIC_DEBUG_FLAG foo.c"
+	End:
+	*/
+
+Vim 能夠解釋這樣的標記:
+
+.. code-block:: c
+
+	/* vim:set sw=8 noet */
+
+不要在原始碼中包含任何這樣的內容。每個人都有他自己的編輯器配置,你的源文件不
+應該覆蓋別人的配置。這包括有關縮進和模式配置的標記。人們可以使用他們自己定製
+的模式,或者使用其他可以產生正確的縮進的巧妙方法。
+
+
+19) 內聯彙編
+------------------------------
+
+在特定架構的代碼中,你可能需要內聯彙編與 CPU 和平台相關功能連接。需要這麼做時
+就不要猶豫。然而,當 C 可以完成工作時,不要平白無故地使用內聯彙編。在可能的情
+況下,你可以並且應該用 C 和硬體溝通。
+
+請考慮去寫捆綁通用位元 (wrap common bits) 的內聯彙編的簡單輔助函數,別去重複
+地寫下只有細微差異內聯彙編。記住內聯彙編可以使用 C 參數。
+
+大型,有一定複雜度的彙編函數應該放在 .S 文件內,用相應的 C 原型定義在 C 頭文
+件中。彙編函數的 C 原型應該使用 ``asmlinkage`` 。
+
+你可能需要把彙編語句標記爲 volatile,用來阻止 GCC 在沒發現任何副作用後就把它
+移除了。你不必總是這樣做,儘管,這不必要的舉動會限制優化。
+
+在寫一個包含多條指令的單個內聯彙編語句時,把每條指令用引號分割而且各占一行,
+除了最後一條指令外,在每個指令結尾加上 \n\t,讓彙編輸出時可以正確地縮進下一條
+指令:
+
+.. code-block:: c
+
+	asm ("magic %reg1, #42\n\t"
+	     "more_magic %reg2, %reg3"
+	     : /* outputs */ : /* inputs */ : /* clobbers */);
+
+
+20) 條件編譯
+------------------------------
+
+只要可能,就不要在 .c 文件裡面使用預處理條件 (#if, #ifdef);這樣做讓代碼更難
+閱讀並且更難去跟蹤邏輯。替代方案是,在頭文件中用預處理條件提供給那些 .c 文件
+使用,再給 #else 提供一個空樁 (no-op stub) 版本,然後在 .c 文件內無條件地調用
+那些 (定義在頭文件內的) 函數。這樣做,編譯器會避免爲樁函數 (stub) 的調用生成
+任何代碼,產生的結果是相同的,但邏輯將更加清晰。
+
+最好傾向於編譯整個函數,而不是函數的一部分或表達式的一部分。與其放一個 ifdef
+在表達式內,不如分解出部分或全部表達式,放進一個單獨的輔助函數,並應用預處理
+條件到這個輔助函數內。
+
+如果你有一個在特定配置中,可能變成未使用的函數或變量,編譯器會警告它定義了但
+未使用,把它標記爲 __maybe_unused 而不是將它包含在一個預處理條件中。(然而,如
+果一個函數或變量總是未使用,就直接刪除它。)
+
+在代碼中,儘可能地使用 IS_ENABLED 宏來轉化某個 Kconfig 標記爲 C 的布爾
+表達式,並在一般的 C 條件中使用它:
+
+.. code-block:: c
+
+	if (IS_ENABLED(CONFIG_SOMETHING)) {
+		...
+	}
+
+編譯器會做常量摺疊,然後就像使用 #ifdef 那樣去包含或排除代碼塊,所以這不會帶
+來任何運行時開銷。然而,這種方法依舊允許 C 編譯器查看塊內的代碼,並檢查它的正
+確性 (語法,類型,符號引用,等等)。因此,如果條件不滿足,代碼塊內的引用符號就
+不存在時,你還是必須去用 #ifdef。
+
+在任何有意義的 #if 或 #ifdef 塊的末尾 (超過幾行的),在 #endif 同一行的後面寫下
+註解,注釋這個條件表達式。例如:
+
+.. code-block:: c
+
+	#ifdef CONFIG_SOMETHING
+	...
+	#endif /* CONFIG_SOMETHING */
+
+
+附錄 I) 參考
+-------------------
+
+The C Programming Language, 第二版
+作者:Brian W. Kernighan 和 Denni M. Ritchie.
+Prentice Hall, Inc., 1988.
+ISBN 0-13-110362-8 (軟皮), 0-13-110370-9 (硬皮).
+
+The Practice of Programming
+作者:Brian W. Kernighan 和 Rob Pike.
+Addison-Wesley, Inc., 1999.
+ISBN 0-201-61586-X.
+
+GNU 手冊 - 遵循 K&R 標準和此文本 - cpp, gcc, gcc internals and indent,
+都可以從 https://www.gnu.org/manual/ 找到
+
+WG14 是 C 語言的國際標準化工作組,URL: http://www.open-std.org/JTC1/SC22/WG14/
+
+Kernel process/coding-style.rst,作者 greg@kroah.com 發表於 OLS 2002:
+http://www.kroah.com/linux/talks/ols_2002_kernel_codingstyle_talk/html/
+
diff --git a/Documentation/translations/zh_TW/process/development-process.rst b/Documentation/translations/zh_TW/process/development-process.rst
new file mode 100644
index 000000000000..45e6385647cd
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/development-process.rst
@@ -0,0 +1,30 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/development-process.rst <development_process_main>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+.. _tw_development_process_main:
+
+內核開發過程指南
+================
+
+內容:
+
+.. toctree::
+   :numbered:
+   :maxdepth: 2
+
+   1.Intro
+   2.Process
+   3.Early-stage
+   4.Coding
+   5.Posting
+   6.Followthrough
+   7.AdvancedTopics
+   8.Conclusion
+
+本文檔的目的是幫助開發人員(及其經理)以最小的挫折感與開發社區合作。它試圖記錄這個社區如何以一種不熟悉Linux內核開發(或者實際上是自由軟體開發)的人可以訪問的方式工作。雖然這裡有一些技術資料,但這是一個面向過程的討論,不需要深入了解內核編程就可以理解。
+
diff --git a/Documentation/translations/zh_TW/process/email-clients.rst b/Documentation/translations/zh_TW/process/email-clients.rst
new file mode 100644
index 000000000000..4ba543d06f3b
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/email-clients.rst
@@ -0,0 +1,252 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _tw_email_clients:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/email-clients.rst <email_clients>`
+
+譯者::
+
+        中文版維護者: 賈威威  Harry Wei <harryxiyou@gmail.com>
+        中文版翻譯者: 賈威威  Harry Wei <harryxiyou@gmail.com>
+                       時奎亮  Alex Shi <alex.shi@linux.alibaba.com>
+        中文版校譯者: Yinglin Luan <synmyth@gmail.com>
+        	       Xiaochen Wang <wangxiaochen0@gmail.com>
+                       yaxinsn <yaxinsn@163.com>
+                      Hu Haowen <src.res@email.cn>
+
+Linux郵件客戶端配置信息
+=======================
+
+Git
+---
+
+現在大多數開發人員使用 ``git send-email`` 而不是常規的電子郵件客戶端。這方面
+的手冊非常好。在接收端,維護人員使用 ``git am`` 加載補丁。
+
+如果你是 ``git`` 新手,那麼把你的第一個補丁發送給你自己。將其保存爲包含所有
+標題的原始文本。運行 ``git am raw_email.txt`` ,然後使用 ``git log`` 查看更
+改日誌。如果工作正常,再將補丁發送到相應的郵件列表。
+
+
+普通配置
+--------
+Linux內核補丁是通過郵件被提交的,最好把補丁作爲郵件體的內嵌文本。有些維護者
+接收附件,但是附件的內容格式應該是"text/plain"。然而,附件一般是不贊成的,
+因爲這會使補丁的引用部分在評論過程中變的很困難。
+
+用來發送Linux內核補丁的郵件客戶端在發送補丁時應該處於文本的原始狀態。例如,
+他們不能改變或者刪除制表符或者空格,甚至是在每一行的開頭或者結尾。
+
+不要通過"format=flowed"模式發送補丁。這樣會引起不可預期以及有害的斷行。
+
+不要讓你的郵件客戶端進行自動換行。這樣也會破壞你的補丁。
+
+郵件客戶端不能改變文本的字符集編碼方式。要發送的補丁只能是ASCII或者UTF-8編碼方式,
+如果你使用UTF-8編碼方式發送郵件,那麼你將會避免一些可能發生的字符集問題。
+
+郵件客戶端應該形成並且保持 References: 或者 In-Reply-To: 標題,那麼
+郵件話題就不會中斷。
+
+複製粘帖(或者剪貼粘帖)通常不能用於補丁,因爲制表符會轉換爲空格。使用xclipboard, xclip
+或者xcutsel也許可以,但是最好測試一下或者避免使用複製粘帖。
+
+不要在使用PGP/GPG署名的郵件中包含補丁。這樣會使得很多腳本不能讀取和適用於你的補丁。
+(這個問題應該是可以修復的)
+
+在給內核郵件列表發送補丁之前,給自己發送一個補丁是個不錯的主意,保存接收到的
+郵件,將補丁用'patch'命令打上,如果成功了,再給內核郵件列表發送。
+
+
+一些郵件客戶端提示
+------------------
+這裡給出一些詳細的MUA配置提示,可以用於給Linux內核發送補丁。這些並不意味是
+所有的軟體包配置總結。
+
+說明:
+TUI = 以文本爲基礎的用戶接口
+GUI = 圖形界面用戶接口
+
+Alpine (TUI)
+~~~~~~~~~~~~
+
+配置選項:
+在"Sending Preferences"部分:
+
+- "Do Not Send Flowed Text"必須開啓
+- "Strip Whitespace Before Sending"必須關閉
+
+當寫郵件時,光標應該放在補丁會出現的地方,然後按下CTRL-R組合鍵,使指定的
+補丁文件嵌入到郵件中。
+
+Evolution (GUI)
+~~~~~~~~~~~~~~~
+
+一些開發者成功的使用它發送補丁
+
+當選擇郵件選項:Preformat
+  從Format->Heading->Preformatted (Ctrl-7)或者工具欄
+
+然後使用:
+  Insert->Text File... (Alt-n x)插入補丁文件。
+
+你還可以"diff -Nru old.c new.c | xclip",選擇Preformat,然後使用中間鍵進行粘帖。
+
+Kmail (GUI)
+~~~~~~~~~~~
+
+一些開發者成功的使用它發送補丁。
+
+默認設置不爲HTML格式是合適的;不要啓用它。
+
+當書寫一封郵件的時候,在選項下面不要選擇自動換行。唯一的缺點就是你在郵件中輸入的任何文本
+都不會被自動換行,因此你必須在發送補丁之前手動換行。最簡單的方法就是啓用自動換行來書寫郵件,
+然後把它保存爲草稿。一旦你在草稿中再次打開它,它已經全部自動換行了,那麼你的郵件雖然沒有
+選擇自動換行,但是還不會失去已有的自動換行。
+
+在郵件的底部,插入補丁之前,放上常用的補丁定界符:三個連字號(---)。
+
+然後在"Message"菜單條目,選擇插入文件,接著選取你的補丁文件。還有一個額外的選項,你可以
+通過它配置你的郵件建立工具欄菜單,還可以帶上"insert file"圖標。
+
+你可以安全地通過GPG標記附件,但是內嵌補丁最好不要使用GPG標記它們。作爲內嵌文本的簽發補丁,
+當從GPG中提取7位編碼時會使他們變的更加複雜。
+
+如果你非要以附件的形式發送補丁,那麼就右鍵點擊附件,然後選中屬性,突出"Suggest automatic
+display",這樣內嵌附件更容易讓讀者看到。
+
+當你要保存將要發送的內嵌文本補丁,你可以從消息列表窗格選擇包含補丁的郵件,然後右擊選擇
+"save as"。你可以使用一個沒有更改的包含補丁的郵件,如果它是以正確的形式組成。當你正真在它
+自己的窗口之下察看,那時沒有選項可以保存郵件--已經有一個這樣的bug被匯報到了kmail的bugzilla
+並且希望這將會被處理。郵件是以只針對某個用戶可讀寫的權限被保存的,所以如果你想把郵件複製到其他地方,
+你不得不把他們的權限改爲組或者整體可讀。
+
+Lotus Notes (GUI)
+~~~~~~~~~~~~~~~~~
+
+不要使用它。
+
+Mutt (TUI)
+~~~~~~~~~~
+
+很多Linux開發人員使用mutt客戶端,所以證明它肯定工作的非常漂亮。
+
+Mutt不自帶編輯器,所以不管你使用什麼編輯器都不應該帶有自動斷行。大多數編輯器都帶有
+一個"insert file"選項,它可以通過不改變文件內容的方式插入文件。
+
+'vim'作爲mutt的編輯器:
+  set editor="vi"
+
+  如果使用xclip,敲入以下命令
+  :set paste
+  按中鍵之前或者shift-insert或者使用
+  :r filename
+
+如果想要把補丁作爲內嵌文本。
+(a)ttach工作的很好,不帶有"set paste"。
+
+你可以通過 ``git format-patch`` 生成補丁,然後用 Mutt發送它們::
+
+        $ mutt -H 0001-some-bug-fix.patch
+
+配置選項:
+它應該以默認設置的形式工作。
+然而,把"send_charset"設置爲"us-ascii::utf-8"也是一個不錯的主意。
+
+Mutt 是高度可配置的。 這裡是個使用mutt通過 Gmail 發送的補丁的最小配置::
+
+  # .muttrc
+  # ================  IMAP ====================
+  set imap_user = 'yourusername@gmail.com'
+  set imap_pass = 'yourpassword'
+  set spoolfile = imaps://imap.gmail.com/INBOX
+  set folder = imaps://imap.gmail.com/
+  set record="imaps://imap.gmail.com/[Gmail]/Sent Mail"
+  set postponed="imaps://imap.gmail.com/[Gmail]/Drafts"
+  set mbox="imaps://imap.gmail.com/[Gmail]/All Mail"
+
+  # ================  SMTP  ====================
+  set smtp_url = "smtp://username@smtp.gmail.com:587/"
+  set smtp_pass = $imap_pass
+  set ssl_force_tls = yes # Require encrypted connection
+
+  # ================  Composition  ====================
+  set editor = `echo \$EDITOR`
+  set edit_headers = yes  # See the headers when editing
+  set charset = UTF-8     # value of $LANG; also fallback for send_charset
+  # Sender, email address, and sign-off line must match
+  unset use_domain        # because joe@localhost is just embarrassing
+  set realname = "YOUR NAME"
+  set from = "username@gmail.com"
+  set use_from = yes
+
+Mutt文檔含有更多信息:
+
+    http://dev.mutt.org/trac/wiki/UseCases/Gmail
+
+    http://dev.mutt.org/doc/manual.html
+
+Pine (TUI)
+~~~~~~~~~~
+
+Pine過去有一些空格刪減問題,但是這些現在應該都被修復了。
+
+如果可以,請使用alpine(pine的繼承者)
+
+配置選項:
+- 最近的版本需要消除流程文本
+- "no-strip-whitespace-before-send"選項也是需要的。
+
+
+Sylpheed (GUI)
+~~~~~~~~~~~~~~
+
+- 內嵌文本可以很好的工作(或者使用附件)。
+- 允許使用外部的編輯器。
+- 對於目錄較多時非常慢。
+- 如果通過non-SSL連接,無法使用TLS SMTP授權。
+- 在組成窗口中有一個很有用的ruler bar。
+- 給地址本中添加地址就不會正確的了解顯示名。
+
+Thunderbird (GUI)
+~~~~~~~~~~~~~~~~~
+
+默認情況下,thunderbird很容易損壞文本,但是還有一些方法可以強制它變得更好。
+
+- 在用戶帳號設置里,組成和尋址,不要選擇"Compose messages in HTML format"。
+
+- 編輯你的Thunderbird配置設置來使它不要拆行使用:user_pref("mailnews.wraplength", 0);
+
+- 編輯你的Thunderbird配置設置,使它不要使用"format=flowed"格式:user_pref("mailnews.
+  send_plaintext_flowed", false);
+
+- 你需要使Thunderbird變爲預先格式方式:
+  如果默認情況下你書寫的是HTML格式,那不是很難。僅僅從標題欄的下拉框中選擇"Preformat"格式。
+  如果默認情況下你書寫的是文本格式,你不得把它改爲HTML格式(僅僅作爲一次性的)來書寫新的消息,
+  然後強制使它回到文本格式,否則它就會拆行。要實現它,在寫信的圖標上使用shift鍵來使它變爲HTML
+  格式,然後標題欄的下拉框中選擇"Preformat"格式。
+
+- 允許使用外部的編輯器:
+  針對Thunderbird打補丁最簡單的方法就是使用一個"external editor"擴展,然後使用你最喜歡的
+  $EDITOR來讀取或者合併補丁到文本中。要實現它,可以下載並且安裝這個擴展,然後添加一個使用它的
+  按鍵View->Toolbars->Customize...最後當你書寫信息的時候僅僅點擊它就可以了。
+
+TkRat (GUI)
+~~~~~~~~~~~
+
+可以使用它。使用"Insert file..."或者外部的編輯器。
+
+Gmail (Web GUI)
+~~~~~~~~~~~~~~~
+
+不要使用它發送補丁。
+
+Gmail網頁客戶端自動地把制表符轉換爲空格。
+
+雖然制表符轉換爲空格問題可以被外部編輯器解決,同時它還會使用回車換行把每行拆分爲78個字符。
+
+另一個問題是Gmail還會把任何不是ASCII的字符的信息改爲base64編碼。它把東西變的像歐洲人的名字。
+
+                                ###
+
diff --git a/Documentation/translations/zh_TW/process/embargoed-hardware-issues.rst b/Documentation/translations/zh_TW/process/embargoed-hardware-issues.rst
new file mode 100644
index 000000000000..6c76fc96131a
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/embargoed-hardware-issues.rst
@@ -0,0 +1,232 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/embargoed-hardware-issues.rst <embargoed_hardware_issues>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+被限制的硬體問題
+================
+
+範圍
+----
+
+導致安全問題的硬體問題與只影響Linux內核的純軟體錯誤是不同的安全錯誤類別。
+
+必須區別對待諸如熔毀(Meltdown)、Spectre、L1TF等硬體問題,因爲它們通常會影響
+所有作業系統(「OS」),因此需要在不同的OS供應商、發行版、硬體供應商和其他各方
+之間進行協調。對於某些問題,軟體緩解可能依賴於微碼或固件更新,這需要進一步的
+協調。
+
+.. _tw_Contact:
+
+接觸
+----
+
+Linux內核硬體安全小組獨立於普通的Linux內核安全小組。
+
+該小組只負責協調被限制的硬體安全問題。Linux內核中純軟體安全漏洞的報告不由該
+小組處理,報告者將被引導至常規Linux內核安全小組(:ref:`Documentation/admin-guide/
+<securitybugs>`)聯繫。
+
+可以通過電子郵件 <hardware-security@kernel.org> 與小組聯繫。這是一份私密的安全
+官名單,他們將幫助您根據我們的文檔化流程協調問題。
+
+郵件列表是加密的,發送到列表的電子郵件可以通過PGP或S/MIME加密,並且必須使用報告
+者的PGP密鑰或S/MIME證書籤名。該列表的PGP密鑰和S/MIME證書可從
+https://www.kernel.org/.... 獲得。
+
+雖然硬體安全問題通常由受影響的硬體供應商處理,但我們歡迎發現潛在硬體缺陷的研究
+人員或個人與我們聯繫。
+
+硬體安全官
+^^^^^^^^^^
+
+目前的硬體安全官小組:
+
+  - Linus Torvalds(Linux基金會院士)
+  - Greg Kroah Hartman(Linux基金會院士)
+  - Thomas Gleixner(Linux基金會院士)
+
+郵件列表的操作
+^^^^^^^^^^^^^^
+
+處理流程中使用的加密郵件列表託管在Linux Foundation的IT基礎設施上。通過提供這項
+服務,Linux基金會的IT基礎設施安全總監在技術上有能力訪問被限制的信息,但根據他
+的僱傭合同,他必須保密。Linux基金會的IT基礎設施安全總監還負責 kernel.org 基礎
+設施。
+
+Linux基金會目前的IT基礎設施安全總監是 Konstantin Ryabitsev。
+
+保密協議
+--------
+
+Linux內核硬體安全小組不是正式的機構,因此無法簽訂任何保密協議。核心社區意識到
+這些問題的敏感性,並提供了一份諒解備忘錄。
+
+諒解備忘錄
+----------
+
+Linux內核社區深刻理解在不同作業系統供應商、發行商、硬體供應商和其他各方之間
+進行協調時,保持硬體安全問題處於限制狀態的要求。
+
+Linux內核社區在過去已經成功地處理了硬體安全問題,並且有必要的機制允許在限制
+限制下進行符合社區的開發。
+
+Linux內核社區有一個專門的硬體安全小組負責初始聯繫,並監督在限制規則下處理
+此類問題的過程。
+
+硬體安全小組確定開發人員(領域專家),他們將組成特定問題的初始響應小組。最初
+的響應小組可以引入更多的開發人員(領域專家)以最佳的技術方式解決這個問題。
+
+所有相關開發商承諾遵守限制規定,並對收到的信息保密。違反承諾將導致立即從當前
+問題中排除,並從所有相關郵件列表中刪除。此外,硬體安全小組還將把違反者排除在
+未來的問題之外。這一後果的影響在我們社區是一種非常有效的威懾。如果發生違規
+情況,硬體安全小組將立即通知相關方。如果您或任何人發現潛在的違規行爲,請立即
+向硬體安全人員報告。
+
+流程
+^^^^
+
+由於Linux內核開發的全球分布式特性,面對面的會議幾乎不可能解決硬體安全問題。
+由於時區和其他因素,電話會議很難協調,只能在絕對必要時使用。加密電子郵件已被
+證明是解決此類問題的最有效和最安全的通信方法。
+
+開始披露
+""""""""
+
+披露內容首先通過電子郵件聯繫Linux內核硬體安全小組。此初始聯繫人應包含問題的
+描述和任何已知受影響硬體的列表。如果您的組織製造或分發受影響的硬體,我們建議
+您也考慮哪些其他硬體可能會受到影響。
+
+硬體安全小組將提供一個特定於事件的加密郵件列表,用於與報告者進行初步討論、
+進一步披露和協調。
+
+硬體安全小組將向披露方提供一份開發人員(領域專家)名單,在與開發人員確認他們
+將遵守本諒解備忘錄和文件化流程後,應首先告知開發人員有關該問題的信息。這些開發
+人員組成初始響應小組,並在初始接觸後負責處理問題。硬體安全小組支持響應小組,
+但不一定參與緩解開發過程。
+
+雖然個別開發人員可能通過其僱主受到保密協議的保護,但他們不能以Linux內核開發
+人員的身份簽訂個別保密協議。但是,他們將同意遵守這一書面程序和諒解備忘錄。
+
+披露方應提供已經或應該被告知該問題的所有其他實體的聯繫人名單。這有幾個目的:
+
+  - 披露的實體列表允許跨行業通信,例如其他作業系統供應商、硬體供應商等。
+
+  - 可聯繫已披露的實體,指定應參與緩解措施開發的專家。
+
+  - 如果需要處理某一問題的專家受僱於某一上市實體或某一上市實體的成員,則響應
+    小組可要求該實體披露該專家。這確保專家也是實體反應小組的一部分。
+
+披露
+""""
+
+披露方通過特定的加密郵件列表向初始響應小組提供詳細信息。
+
+根據我們的經驗,這些問題的技術文檔通常是一個足夠的起點,最好通過電子郵件進行
+進一步的技術澄清。
+
+緩解開發
+""""""""
+
+初始響應小組設置加密郵件列表,或在適當的情況下重新修改現有郵件列表。
+
+使用郵件列表接近於正常的Linux開發過程,並且在過去已經成功地用於爲各種硬體安全
+問題開發緩解措施。
+
+郵件列表的操作方式與正常的Linux開發相同。發布、討論和審查修補程序,如果同意,
+則應用於非公共git存儲庫,參與開發人員只能通過安全連接訪問該存儲庫。存儲庫包含
+針對主線內核的主開發分支,並根據需要爲穩定的內核版本提供向後移植分支。
+
+最初的響應小組將根據需要從Linux內核開發人員社區中確定更多的專家。引進專家可以
+在開發過程中的任何時候發生,需要及時處理。
+
+如果專家受僱於披露方提供的披露清單上的實體或其成員,則相關實體將要求其參與。
+
+否則,披露方將被告知專家參與的情況。諒解備忘錄涵蓋了專家,要求披露方確認參與。
+如果披露方有令人信服的理由提出異議,則必須在五個工作日內提出異議,並立即與事件
+小組解決。如果披露方在五個工作日內未作出回應,則視爲默許。
+
+在確認或解決異議後,專家由事件小組披露,並進入開發過程。
+
+協調發布
+""""""""
+
+有關各方將協商限制結束的日期和時間。此時,準備好的緩解措施集成到相關的內核樹中
+並發布。
+
+雖然我們理解硬體安全問題需要協調限制時間,但限制時間應限制在所有有關各方制定、
+測試和準備緩解措施所需的最短時間內。人爲地延長限制時間以滿足會議討論日期或其他
+非技術原因,會給相關的開發人員和響應小組帶來了更多的工作和負擔,因爲補丁需要
+保持最新,以便跟蹤正在進行的上游內核開發,這可能會造成衝突的更改。
+
+CVE分配
+"""""""
+
+硬體安全小組和初始響應小組都不分配CVE,開發過程也不需要CVE。如果CVE是由披露方
+提供的,則可用於文檔中。
+
+流程專使
+--------
+
+爲了協助這一進程,我們在各組織設立了專使,他們可以回答有關報告流程和進一步處理
+的問題或提供指導。專使不參與特定問題的披露,除非響應小組或相關披露方提出要求。
+現任專使名單:
+
+  ============= ========================================================
+  ARM
+  AMD		Tom Lendacky <tom.lendacky@amd.com>
+  IBM
+  Intel		Tony Luck <tony.luck@intel.com>
+  Qualcomm	Trilok Soni <tsoni@codeaurora.org>
+
+  Microsoft	Sasha Levin <sashal@kernel.org>
+  VMware
+  Xen		Andrew Cooper <andrew.cooper3@citrix.com>
+
+  Canonical	John Johansen <john.johansen@canonical.com>
+  Debian	Ben Hutchings <ben@decadent.org.uk>
+  Oracle	Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
+  Red Hat	Josh Poimboeuf <jpoimboe@redhat.com>
+  SUSE		Jiri Kosina <jkosina@suse.cz>
+
+  Amazon
+  Google	Kees Cook <keescook@chromium.org>
+  ============= ========================================================
+
+如果要將您的組織添加到專使名單中,請與硬體安全小組聯繫。被提名的專使必須完全
+理解和支持我們的過程,並且在Linux內核社區中很容易聯繫。
+
+加密郵件列表
+------------
+
+我們使用加密郵件列表進行通信。這些列表的工作原理是,發送到列表的電子郵件使用
+列表的PGP密鑰或列表的/MIME證書進行加密。郵件列表軟體對電子郵件進行解密,並
+使用訂閱者的PGP密鑰或S/MIME證書爲每個訂閱者分別對其進行重新加密。有關郵件列表
+軟體和用於確保列表安全和數據保護的設置的詳細信息,請訪問:
+https://www.kernel.org/....
+
+關鍵點
+^^^^^^
+
+初次接觸見 :ref:`tw_Contact`. 對於特定於事件的郵件列表,密鑰和S/MIME證書通過
+特定列表發送的電子郵件傳遞給訂閱者。
+
+訂閱事件特定列表
+^^^^^^^^^^^^^^^^
+
+訂閱由響應小組處理。希望參與通信的披露方將潛在訂戶的列表發送給響應組,以便
+響應組可以驗證訂閱請求。
+
+每個訂戶都需要通過電子郵件向響應小組發送訂閱請求。電子郵件必須使用訂閱伺服器
+的PGP密鑰或S/MIME證書籤名。如果使用PGP密鑰,則必須從公鑰伺服器獲得該密鑰,
+並且理想情況下該密鑰連接到Linux內核的PGP信任網。另請參見:
+https://www.kernel.org/signature.html.
+
+響應小組驗證訂閱者,並將訂閱者添加到列表中。訂閱後,訂閱者將收到來自郵件列表
+的電子郵件,該郵件列表使用列表的PGP密鑰或列表的/MIME證書籤名。訂閱者的電子郵件
+客戶端可以從簽名中提取PGP密鑰或S/MIME證書,以便訂閱者可以向列表發送加密電子
+郵件。
+
diff --git a/Documentation/translations/zh_TW/process/howto.rst b/Documentation/translations/zh_TW/process/howto.rst
new file mode 100644
index 000000000000..2043691b92e3
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/howto.rst
@@ -0,0 +1,500 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _tw_process_howto:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/howto.rst <process_howto>`
+
+譯者::
+
+    英文版維護者: Greg Kroah-Hartman <greg@kroah.com>
+    中文版維護者: 李陽  Li Yang <leoyang.li@nxp.com>
+    中文版翻譯者: 李陽  Li Yang <leoyang.li@nxp.com>
+                   時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+    中文版校譯者:
+                   鍾宇  TripleX Chung <xxx.phy@gmail.com>
+                   陳琦  Maggie Chen <chenqi@beyondsoft.com>
+                   王聰  Wang Cong <xiyou.wangcong@gmail.com>
+                   胡皓文 Hu Haowen <src.res@email.cn>
+
+如何參與Linux內核開發
+=====================
+
+這是一篇將如何參與Linux內核開發的相關問題一網打盡的終極祕笈。它將指導你
+成爲一名Linux內核開發者,並且學會如何同Linux內核開發社區合作。它儘可能不
+包括任何關於內核編程的技術細節,但會給你指引一條獲得這些知識的正確途徑。
+
+如果這篇文章中的任何內容不再適用,請給文末列出的文件維護者發送補丁。
+
+
+入門
+----
+
+你想了解如何成爲一名Linux內核開發者?或者老闆吩咐你「給這個設備寫個Linux
+驅動程序」?這篇文章的目的就是教會你達成這些目標的全部訣竅,它將描述你需
+要經過的流程以及給出如何同內核社區合作的一些提示。它還將試圖解釋內核社區
+爲何這樣運作。
+
+Linux內核大部分是由C語言寫成的,一些體系結構相關的代碼用到了彙編語言。要
+參與內核開發,你必須精通C語言。除非你想爲某個架構開發底層代碼,否則你並
+不需要了解(任何體系結構的)彙編語言。下面列舉的書籍雖然不能替代紮實的C
+語言教育和多年的開發經驗,但如果需要的話,做爲參考還是不錯的:
+
+ - "The C Programming Language" by Kernighan and Ritchie [Prentice Hall]
+   《C程序設計語言(第2版·新版)》(徐寶文 李志 譯)[機械工業出版社]
+ - "Practical C Programming" by Steve Oualline [O'Reilly]
+   《實用C語言編程(第三版)》(郭大海 譯)[中國電力出版社]
+ - "C:  A Reference Manual" by Harbison and Steele [Prentice Hall]
+   《C語言參考手冊(原書第5版)》(邱仲潘 等譯)[機械工業出版社]
+
+Linux內核使用GNU C和GNU工具鏈開發。雖然它遵循ISO C89標準,但也用到了一些
+標準中沒有定義的擴展。內核是自給自足的C環境,不依賴於標準C庫的支持,所以
+並不支持C標準中的部分定義。比如long long類型的大數除法和浮點運算就不允許
+使用。有時候確實很難弄清楚內核對工具鏈的要求和它所使用的擴展,不幸的是目
+前還沒有明確的參考資料可以解釋它們。請查閱gcc信息頁(使用「info gcc」命令
+顯示)獲得一些這方面信息。
+
+請記住你是在學習怎麼和已經存在的開發社區打交道。它由一羣形形色色的人組成,
+他們對代碼、風格和過程有著很高的標準。這些標準是在長期實踐中總結出來的,
+適應於地理上分散的大型開發團隊。它們已經被很好得整理成檔,建議你在開發
+之前儘可能多的學習這些標準,而不要期望別人來適應你或者你公司的行爲方式。
+
+
+法律問題
+--------
+
+Linux內核原始碼都是在GPL(通用公共許可證)的保護下發布的。要了解這種許可
+的細節請查看原始碼主目錄下的COPYING文件。Linux內核許可準則和如何使用
+`SPDX <https://spdx.org/>` 標誌符說明在這個文件中
+:ref:`Documentation/translations/zh_TW/process/license-rules.rst <tw_kernel_licensing>`
+如果你對它還有更深入問題請聯繫律師,而不要在Linux內核郵件組上提問。因爲
+郵件組裡的人並不是律師,不要期望他們的話有法律效力。
+
+對於GPL的常見問題和解答,請訪問以下連結:
+	https://www.gnu.org/licenses/gpl-faq.html
+
+
+文檔
+----
+
+Linux內核代碼中包含有大量的文檔。這些文檔對於學習如何與內核社區互動有著
+不可估量的價值。當一個新的功能被加入內核,最好把解釋如何使用這個功能的文
+檔也放進內核。當內核的改動導致面向用戶空間的接口發生變化時,最好將相關信
+息或手冊頁(manpages)的補丁發到mtk.manpages@gmail.com,以向手冊頁(manpages)
+的維護者解釋這些變化。
+
+以下是內核代碼中需要閱讀的文檔:
+  :ref:`Documentation/admin-guide/README.rst <readme>`
+    文件簡要介紹了Linux內核的背景,並且描述了如何配置和編譯內核。內核的
+    新用戶應該從這裡開始。
+
+
+  :ref:`Documentation/process/changes.rst <changes>`
+    文件給出了用來編譯和使用內核所需要的最小軟體包列表。
+
+  :ref:`Documentation/translations/zh_TW/process/coding-style.rst <tw_codingstyle>`
+    描述Linux內核的代碼風格和理由。所有新代碼需要遵守這篇文檔中定義的規
+    范。大多數維護者只會接收符合規定的補丁,很多人也只會幫忙檢查符合風格
+    的代碼。
+
+  :ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+  :ref:`Documentation/process/submitting-drivers.rst <submittingdrivers>`
+
+    這兩份文檔明確描述如何創建和發送補丁,其中包括(但不僅限於):
+       - 郵件內容
+       - 郵件格式
+       - 選擇收件人
+
+    遵守這些規定並不能保證提交成功(因爲所有補丁需要通過嚴格的內容和風格
+    審查),但是忽視他們幾乎就意味著失敗。
+
+    其他關於如何正確地生成補丁的優秀文檔包括:
+    "The Perfect Patch"
+
+        https://www.ozlabs.org/~akpm/stuff/tpp.txt
+
+    "Linux kernel patch submission format"
+
+        https://web.archive.org/web/20180829112450/http://linux.yyz.us/patch-format.html
+
+  :ref:`Documentation/translations/zh_TW/process/stable-api-nonsense.rst <tw_stable_api_nonsense>`
+    論證內核爲什麼特意不包括穩定的內核內部API,也就是說不包括像這樣的特
+    性:
+
+       - 子系統中間層(爲了兼容性?)
+       - 在不同作業系統間易於移植的驅動程序
+       - 減緩(甚至阻止)內核代碼的快速變化
+
+    這篇文檔對於理解Linux的開發哲學至關重要。對於將開發平台從其他操作系
+    統轉移到Linux的人來說也很重要。
+
+  :ref:`Documentation/admin-guide/security-bugs.rst <securitybugs>`
+    如果你認爲自己發現了Linux內核的安全性問題,請根據這篇文檔中的步驟來
+    提醒其他內核開發者並幫助解決這個問題。
+
+  :ref:`Documentation/translations/zh_TW/process/management-style.rst <tw_managementstyle>`
+
+    描述內核維護者的工作方法及其共有特點。這對於剛剛接觸內核開發(或者對
+    它感到好奇)的人來說很重要,因爲它解釋了很多對於內核維護者獨特行爲的
+    普遍誤解與迷惑。
+
+  :ref:`Documentation/process/stable-kernel-rules.rst <stable_kernel_rules>`
+    解釋了穩定版內核發布的規則,以及如何將改動放入這些版本的步驟。
+
+  :ref:`Documentation/process/kernel-docs.rst <kernel_docs>`
+    有助於內核開發的外部文檔列表。如果你在內核自帶的文檔中沒有找到你想找
+    的內容,可以查看這些文檔。
+
+  :ref:`Documentation/process/applying-patches.rst <applying_patches>`
+    關於補丁是什麼以及如何將它打在不同內核開發分支上的好介紹
+
+內核還擁有大量從代碼自動生成或者從 ReStructuredText(ReST) 標記生成的文檔,
+比如這個文檔,它包含內核內部API的全面介紹以及如何妥善處理加鎖的規則。所有
+這些文檔都可以通過運行以下命令從內核代碼中生成爲PDF或HTML文檔::
+
+    make pdfdocs
+    make htmldocs
+
+ReST格式的文檔會生成在 Documentation/output. 目錄中。
+它們也可以用下列命令生成 LaTeX 和 ePub 格式文檔::
+
+    make latexdocs
+    make epubdocs
+
+如何成爲內核開發者
+------------------
+如果你對Linux內核開發一無所知,你應該訪問「Linux內核新手」計劃:
+
+	https://kernelnewbies.org
+
+它擁有一個可以問各種最基本的內核開發問題的郵件列表(在提問之前一定要記得
+查找已往的郵件,確認是否有人已經回答過相同的問題)。它還擁有一個可以獲得
+實時反饋的IRC聊天頻道,以及大量對於學習Linux內核開發相當有幫助的文檔。
+
+網站簡要介紹了原始碼組織結構、子系統劃分以及目前正在進行的項目(包括內核
+中的和單獨維護的)。它還提供了一些基本的幫助信息,比如如何編譯內核和打補
+丁。
+
+如果你想加入內核開發社區並協助完成一些任務,卻找不到從哪裡開始,可以訪問
+「Linux內核房管員」計劃:
+
+	https://kernelnewbies.org/KernelJanitors
+
+這是極佳的起點。它提供一個相對簡單的任務列表,列出內核代碼中需要被重新
+整理或者改正的地方。通過和負責這個計劃的開發者們一同工作,你會學到將補丁
+集成進內核的基本原理。如果還沒有決定下一步要做什麼的話,你還可能會得到方
+向性的指點。
+
+在真正動手修改內核代碼之前,理解要修改的代碼如何運作是必需的。要達到這個
+目的,沒什麼辦法比直接讀代碼更有效了(大多數花招都會有相應的注釋),而且
+一些特製的工具還可以提供幫助。例如,「Linux代碼交叉引用」項目就是一個值得
+特別推薦的幫助工具,它將原始碼顯示在有編目和索引的網頁上。其中一個更新及
+時的內核源碼庫,可以通過以下地址訪問:
+
+        https://elixir.bootlin.com/
+
+
+開發流程
+--------
+
+目前Linux內核開發流程包括幾個「主內核分支」和很多子系統相關的內核分支。這
+些分支包括:
+
+  - Linus 的內核源碼樹
+  - 多個主要版本的穩定版內核樹
+  - 子系統相關的內核樹
+  - linux-next 集成測試樹
+
+
+主線樹
+------
+主線樹是由Linus Torvalds 維護的。你可以在https://kernel.org 網站或者代碼
+庫中下找到它。它的開發遵循以下步驟:
+
+  - 每當一個新版本的內核被發布,爲期兩周的集成窗口將被打開。在這段時間裡
+    維護者可以向Linus提交大段的修改,通常這些修改已經被放到-mm內核中幾個
+    星期了。提交大量修改的首選方式是使用git工具(內核的代碼版本管理工具
+    ,更多的信息可以在 https://git-scm.com/ 獲取),不過使用普通補丁也是
+    可以的。
+  - 兩個星期以後-rc1版本內核發布。之後只有不包含可能影響整個內核穩定性的
+    新功能的補丁才可能被接受。請注意一個全新的驅動程序(或者文件系統)有
+    可能在-rc1後被接受是因爲這樣的修改完全獨立,不會影響其他的代碼,所以
+    沒有造成內核退步的風險。在-rc1以後也可以用git向Linus提交補丁,不過所
+    有的補丁需要同時被發送到相應的公衆郵件列表以徵詢意見。
+  - 當Linus認爲當前的git源碼樹已經達到一個合理健全的狀態足以發布供人測試
+    時,一個新的-rc版本就會被發布。計劃是每周都發布新的-rc版本。
+  - 這個過程一直持續下去直到內核被認爲達到足夠穩定的狀態,持續時間大概是
+    6個星期。
+
+關於內核發布,值得一提的是Andrew Morton在linux-kernel郵件列表中如是說:
+	「沒有人知道新內核何時會被發布,因爲發布是根據已知bug的情況來決定
+	的,而不是根據一個事先制定好的時間表。」
+
+子系統特定樹
+------------
+
+各種內核子系統的維護者——以及許多內核子系統開發人員——在原始碼庫中公開了他們
+當前的開發狀態。這樣,其他人就可以看到內核的不同區域發生了什麼。在開發速度
+很快的領域,可能會要求開發人員將提交的內容建立在這樣的子系統內核樹上,這樣
+就避免了提交與其他已經進行的工作之間的衝突。
+
+這些存儲庫中的大多數都是Git樹,但是也有其他的scm在使用,或者補丁隊列被發布
+爲Quilt系列。這些子系統存儲庫的地址列在MAINTAINERS文件中。其中許多可以在
+https://git.kernel.org/上瀏覽。
+
+在將一個建議的補丁提交到這樣的子系統樹之前,需要對它進行審查,審查主要發生
+在郵件列表上(請參見下面相應的部分)。對於幾個內核子系統,這個審查過程是通
+過工具補丁跟蹤的。Patchwork提供了一個Web界面,顯示補丁發布、對補丁的任何評
+論或修訂,維護人員可以將補丁標記爲正在審查、接受或拒絕。大多數補丁網站都列
+在 https://patchwork.kernel.org/
+
+Linux-next 集成測試樹
+---------------------
+
+在將子系統樹的更新合併到主線樹之前,需要對它們進行集成測試。爲此,存在一個
+特殊的測試存儲庫,其中幾乎每天都會提取所有子系統樹:
+
+        https://git.kernel.org/?p=linux/kernel/git/next/linux-next.git
+
+通過這種方式,Linux-next 對下一個合併階段將進入主線內核的內容給出了一個概要
+展望。非常歡冒險的測試者運行測試Linux-next。
+
+多個主要版本的穩定版內核樹
+-----------------------------------
+由3個數字組成的內核版本號說明此內核是-stable版本。它們包含內核的相對較小且
+至關重要的修補,這些修補針對安全性問題或者嚴重的內核退步。
+
+這種版本的內核適用於那些期望獲得最新的穩定版內核並且不想參與測試開發版或
+者實驗版的用戶。
+
+穩定版內核樹版本由「穩定版」小組(郵件地址<stable@vger.kernel.org>)維護,一般
+隔周發布新版本。
+
+內核源碼中的 :ref:`Documentation/process/stable-kernel-rules.rst <stable_kernel_rules>`
+文件具體描述了可被穩定版內核接受的修改類型以及發布的流程。
+
+
+報告bug
+-------
+
+bugzilla.kernel.org是Linux內核開發者們用來跟蹤內核Bug的網站。我們鼓勵用
+戶在這個工具中報告找到的所有bug。如何使用內核bugzilla的細節請訪問:
+
+	http://test.kernel.org/bugzilla/faq.html
+
+內核源碼主目錄中的:ref:`admin-guide/reporting-bugs.rst <reportingbugs>`
+文件里有一個很好的模板。它指導用戶如何報告可能的內核bug以及需要提供哪些信息
+來幫助內核開發者們找到問題的根源。
+
+
+利用bug報告
+-----------
+
+練習內核開發技能的最好辦法就是修改其他人報告的bug。你不光可以幫助內核變
+得更加穩定,還可以學會如何解決實際問題從而提高自己的技能,並且讓其他開發
+者感受到你的存在。修改bug是贏得其他開發者讚譽的最好辦法,因爲並不是很多
+人都喜歡浪費時間去修改別人報告的bug。
+
+要嘗試修改已知的bug,請訪問 http://bugzilla.kernel.org 網址。
+
+
+郵件列表
+--------
+
+正如上面的文檔所描述,大多數的骨幹內核開發者都加入了Linux Kernel郵件列
+表。如何訂閱和退訂列表的細節可以在這裡找到:
+
+	http://vger.kernel.org/vger-lists.html#linux-kernel
+
+網上很多地方都有這個郵件列表的存檔(archive)。可以使用搜尋引擎來找到這些
+存檔。比如:
+
+	http://dir.gmane.org/gmane.linux.kernel
+
+在發信之前,我們強烈建議你先在存檔中搜索你想要討論的問題。很多已經被詳細
+討論過的問題只在郵件列表的存檔中可以找到。
+
+大多數內核子系統也有自己獨立的郵件列表來協調各自的開發工作。從
+MAINTAINERS文件中可以找到不同話題對應的郵件列表。
+
+很多郵件列表架設在kernel.org伺服器上。這些列表的信息可以在這裡找到:
+
+	http://vger.kernel.org/vger-lists.html
+
+在使用這些郵件列表時,請記住保持良好的行爲習慣。下面的連結提供了與這些列
+表(或任何其它郵件列表)交流的一些簡單規則,雖然內容有點濫竽充數。
+
+	http://www.albion.com/netiquette/
+
+當有很多人回覆你的郵件時,郵件的抄送列表會變得很長。請不要將任何人從抄送
+列表中刪除,除非你有足夠的理由這麼做。也不要只回復到郵件列表。請習慣於同
+一封郵件接收兩次(一封來自發送者一封來自郵件列表),而不要試圖通過添加一
+些奇特的郵件頭來解決這個問題,人們不會喜歡的。
+
+記住保留你所回復內容的上下文和源頭。在你回覆郵件的頂部保留「某某某說到……」
+這幾行。將你的評論加在被引用的段落之間而不要放在郵件的頂部。
+
+如果你在郵件中附帶補丁,請確認它們是可以直接閱讀的純文本(如
+:ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+文檔中所述)。內核開發者們不希望遇到附件或者被壓縮了的補丁。只有這樣才能
+保證他們可以直接評論你的每行代碼。請確保你使用的郵件發送程序不會修改空格
+和制表符。一個防範性的測試方法是先將郵件發送給自己,然後自己嘗試是否可以
+順利地打上收到的補丁。如果測試不成功,請調整或者更換你的郵件發送程序直到
+它正確工作爲止。
+
+總而言之,請尊重其他的郵件列表訂閱者。
+
+
+同內核社區合作
+----------------
+
+內核社區的目標就是提供盡善盡美的內核。所以當你提交補丁期望被接受進內核的
+時候,它的技術價值以及其他方面都將被評審。那麼你可能會得到什麼呢?
+
+  - 批評
+  - 評論
+  - 要求修改
+  - 要求證明修改的必要性
+  - 沉默
+
+要記住,這些是把補丁放進內核的正常情況。你必須學會聽取對補丁的批評和評論,
+從技術層面評估它們,然後要麼重寫你的補丁要麼簡明扼要地論證修改是不必要
+的。如果你發的郵件沒有得到任何回應,請過幾天後再試一次,因爲有時信件會湮
+沒在茫茫信海中。
+
+你不應該做的事情:
+
+  - 期望自己的補丁不受任何質疑就直接被接受
+  - 翻臉
+  - 忽略別人的評論
+  - 沒有按照別人的要求做任何修改就重新提交
+
+在一個努力追尋最好技術方案的社區里,對於一個補丁有多少好處總會有不同的見
+解。你必須要抱著合作的態度,願意改變自己的觀點來適應內核的風格。或者至少
+願意去證明你的想法是有價值的。記住,犯錯誤是允許的,只要你願意朝著正確的
+方案去努力。
+
+如果你的第一個補丁換來的是一堆修改建議,這是很正常的。這並不代表你的補丁
+不會被接受,也不意味著有人和你作對。你只需要改正所有提出的問題然後重新發
+送你的補丁。
+
+內核社區和公司文化的差異
+------------------------
+
+內核社區的工作模式同大多數傳統公司開發隊伍的工作模式並不相同。下面這些例
+子,可以幫助你避免某些可能發生問題:
+用這些話介紹你的修改提案會有好處:
+
+    - 它同時解決了多個問題
+    - 它刪除了2000行代碼
+    - 這是補丁,它已經解釋了我想要說明的
+    - 我在5種不同的體系結構上測試過它……
+    - 這是一系列小補丁用來……
+    - 這個修改提高了普通機器的性能……
+
+應該避免如下的說法:
+
+    - 我們在AIX/ptx/Solaris就是這麼做的,所以這麼做肯定是好的……
+    - 我做這行已經20年了,所以……
+    - 爲了我們公司賺錢考慮必須這麼做
+    - 這是我們的企業產品線所需要的
+    - 這裡是描述我觀點的1000頁設計文檔
+    - 這是一個5000行的補丁用來……
+    - 我重寫了現在亂七八糟的代碼,這就是……
+    - 我被規定了最後期限,所以這個補丁需要立刻被接受
+
+另外一個內核社區與大部分傳統公司的軟體開發隊伍不同的地方是無法面對面地交
+流。使用電子郵件和IRC聊天工具做爲主要溝通工具的一個好處是性別和種族歧視
+將會更少。Linux內核的工作環境更能接受婦女和少數族羣,因爲每個人在別人眼
+里只是一個郵件地址。國際化也幫助了公平的實現,因爲你無法通過姓名來判斷人
+的性別。男人有可能叫李麗,女人也有可能叫王剛。大多數在Linux內核上工作過
+並表達過看法的女性對在linux上工作的經歷都給出了正面的評價。
+
+對於一些不習慣使用英語的人來說,語言可能是一個引起問題的障礙。在郵件列表
+中要正確地表達想法必需良好地掌握語言,所以建議你在發送郵件之前最好檢查一
+下英文寫得是否正確。
+
+
+拆分修改
+--------
+
+Linux內核社區並不喜歡一下接收大段的代碼。修改需要被恰當地介紹、討論並且
+拆分成獨立的小段。這幾乎完全和公司中的習慣背道而馳。你的想法應該在開發最
+開始的階段就讓大家知道,這樣你就可以及時獲得對你正在進行的開發的反饋。這
+樣也會讓社區覺得你是在和他們協作,而不是僅僅把他們當作傾銷新功能的對象。
+無論如何,你不要一次性地向郵件列表發送50封信,你的補丁序列應該永遠用不到
+這麼多。
+
+將補丁拆開的原因如下:
+
+1) 小的補丁更有可能被接受,因爲它們不需要太多的時間和精力去驗證其正確性。
+   一個5行的補丁,可能在維護者看了一眼以後就會被接受。而500行的補丁則
+   需要數個小時來審查其正確性(所需時間隨補丁大小增加大約呈指數級增長)。
+
+   當出了問題的時候,小的補丁也會讓調試變得非常容易。一個一個補丁地回溯
+   將會比仔細剖析一個被打上的大補丁(這個補丁破壞了其他東西)容易得多。
+
+2)不光發送小的補丁很重要,在提交之前重新編排、化簡(或者僅僅重新排列)
+   補丁也是很重要的。
+
+這裡有內核開發者Al Viro打的一個比方:
+	「想像一個老師正在給學生批改數學作業。老師並不希望看到學生爲了得
+	到正確解法所進行的嘗試和產生的錯誤。他希望看到的是最乾淨最優雅的
+	解答。好學生了解這點,絕不會把最終解決之前的中間方案提交上去。」
+
+	內核開發也是這樣。維護者和評審者不希望看到一個人在解決問題時的思
+	考過程。他們只希望看到簡單和優雅的解決方案。
+
+直接給出一流的解決方案,和社區一起協作討論尚未完成的工作,這兩者之間似乎
+很難找到一個平衡點。所以最好儘早開始收集有利於你進行改進的反饋;同時也要
+保證修改分成很多小塊,這樣在整個項目都準備好被包含進內核之前,其中的一部
+分可能會先被接收。
+
+必須了解這樣做是不可接受的:試圖將未完成的工作提交進內核,然後再找時間修
+復。
+
+
+證明修改的必要性
+----------------
+除了將補丁拆成小塊,很重要的一點是讓Linux社區了解他們爲什麼需要這樣修改。
+你必須證明新功能是有人需要的並且是有用的。
+
+
+記錄修改
+--------
+
+當你發送補丁的時候,需要特別留意郵件正文的內容。因爲這裡的信息將會做爲補
+丁的修改記錄(ChangeLog),會被一直保留以備大家查閱。它需要完全地描述補丁,
+包括:
+
+  - 爲什麼需要這個修改
+  - 補丁的總體設計
+  - 實現細節
+  - 測試結果
+
+想了解它具體應該看起來像什麼,請查閱以下文檔中的「ChangeLog」章節:
+  「The Perfect Patch」
+  	 https://www.ozlabs.org/~akpm/stuff/tpp.txt
+
+
+這些事情有時候做起來很難。要在任何方面都做到完美可能需要好幾年時間。這是
+一個持續提高的過程,它需要大量的耐心和決心。只要不放棄,你一定可以做到。
+很多人已經做到了,而他們都曾經和現在的你站在同樣的起點上。
+
+
+感謝
+----
+感謝Paolo Ciarrocchi允許「開發流程」部分基於他所寫的文章
+(http://www.kerneltravel.net/newbie/2.6-development_process),感謝Randy
+Dunlap和Gerrit Huizenga完善了應該說和不該說的列表。感謝Pat Mochel, Hanna
+Linder, Randy Dunlap, Kay Sievers, Vojtech Pavlik, Jan Kara, Josh Boyer,
+Kees Cook, Andrew Morton, Andi Kleen, Vadim Lobanov, Jesper Juhl, Adrian
+Bunk, Keri Harris, Frans Pop, David A. Wheeler, Junio Hamano, Michael
+Kerrisk和Alex Shepard的評審、建議和貢獻。沒有他們的幫助,這篇文檔是不可
+能完成的。
+
+
+
+英文版維護者: Greg Kroah-Hartman <greg@kroah.com>
+
diff --git a/Documentation/translations/zh_TW/process/index.rst b/Documentation/translations/zh_TW/process/index.rst
new file mode 100644
index 000000000000..ec7ad14bfd13
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/index.rst
@@ -0,0 +1,67 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. raw:: latex
+
+	\renewcommand\thesection*
+	\renewcommand\thesubsection*
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/index.rst <process_index>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+.. _tw_process_index:
+
+與Linux 內核社區一起工作
+========================
+
+你想成爲Linux內核開發人員嗎?歡迎之至!在學習許多關於內核的技術知識的同時,
+了解我們社區的工作方式也很重要。閱讀這些文檔可以讓您以更輕鬆的、麻煩更少的
+方式將更改合併到內核。
+
+以下是每位開發人員都應閱讀的基本指南:
+
+.. toctree::
+   :maxdepth: 1
+
+   howto
+   code-of-conduct
+   code-of-conduct-interpretation
+   submitting-patches
+   programming-language
+   coding-style
+   development-process
+   email-clients
+   license-rules
+   kernel-enforcement-statement
+   kernel-driver-statement
+
+其它大多數開發人員感興趣的社區指南:
+
+
+.. toctree::
+   :maxdepth: 1
+
+   submitting-drivers
+   submit-checklist
+   stable-api-nonsense
+   stable-kernel-rules
+   management-style
+   embargoed-hardware-issues
+
+這些是一些總體性技術指南,由於不大好分類而放在這裡:
+
+.. toctree::
+   :maxdepth: 1
+
+   magic-number
+   volatile-considered-harmful
+
+.. only::  subproject and html
+
+   目錄
+   ====
+
+   * :ref:`genindex`
+
diff --git a/Documentation/translations/zh_TW/process/kernel-driver-statement.rst b/Documentation/translations/zh_TW/process/kernel-driver-statement.rst
new file mode 100644
index 000000000000..8f225379b12c
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/kernel-driver-statement.rst
@@ -0,0 +1,203 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _zh_process_statement_driver:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/kernel-driver-statement.rst <process_statement_driver>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+內核驅動聲明
+------------
+
+關於Linux內核模塊的立場聲明
+===========================
+
+我們,以下署名的Linux內核開發人員,認爲任何封閉源Linux內核模塊或驅動程序都是
+有害的和不可取的。我們已經一再發現它們對Linux用戶,企業和更大的Linux生態系統
+有害。這樣的模塊否定了Linux開發模型的開放性,穩定性,靈活性和可維護性,並使
+他們的用戶無法使用Linux社區的專業知識。提供閉源內核模塊的供應商迫使其客戶
+放棄Linux的主要優勢或選擇新的供應商。因此,爲了充分利用開源所提供的成本節省和
+共享支持優勢,我們敦促供應商採取措施,以開源內核代碼在Linux上爲其客戶提供支持。
+
+我們只爲自己說話,而不是我們今天可能會爲之工作,過去或將來會爲之工作的任何公司。
+
+ - Dave Airlie
+ - Nick Andrew
+ - Jens Axboe
+ - Ralf Baechle
+ - Felipe Balbi
+ - Ohad Ben-Cohen
+ - Muli Ben-Yehuda
+ - Jiri Benc
+ - Arnd Bergmann
+ - Thomas Bogendoerfer
+ - Vitaly Bordug
+ - James Bottomley
+ - Josh Boyer
+ - Neil Brown
+ - Mark Brown
+ - David Brownell
+ - Michael Buesch
+ - Franck Bui-Huu
+ - Adrian Bunk
+ - François Cami
+ - Ralph Campbell
+ - Luiz Fernando N. Capitulino
+ - Mauro Carvalho Chehab
+ - Denis Cheng
+ - Jonathan Corbet
+ - Glauber Costa
+ - Alan Cox
+ - Magnus Damm
+ - Ahmed S. Darwish
+ - Robert P. J. Day
+ - Hans de Goede
+ - Arnaldo Carvalho de Melo
+ - Helge Deller
+ - Jean Delvare
+ - Mathieu Desnoyers
+ - Sven-Thorsten Dietrich
+ - Alexey Dobriyan
+ - Daniel Drake
+ - Alex Dubov
+ - Randy Dunlap
+ - Michael Ellerman
+ - Pekka Enberg
+ - Jan Engelhardt
+ - Mark Fasheh
+ - J. Bruce Fields
+ - Larry Finger
+ - Jeremy Fitzhardinge
+ - Mike Frysinger
+ - Kumar Gala
+ - Robin Getz
+ - Liam Girdwood
+ - Jan-Benedict Glaw
+ - Thomas Gleixner
+ - Brice Goglin
+ - Cyrill Gorcunov
+ - Andy Gospodarek
+ - Thomas Graf
+ - Krzysztof Halasa
+ - Harvey Harrison
+ - Stephen Hemminger
+ - Michael Hennerich
+ - Tejun Heo
+ - Benjamin Herrenschmidt
+ - Kristian Høgsberg
+ - Henrique de Moraes Holschuh
+ - Marcel Holtmann
+ - Mike Isely
+ - Takashi Iwai
+ - Olof Johansson
+ - Dave Jones
+ - Jesper Juhl
+ - Matthias Kaehlcke
+ - Kenji Kaneshige
+ - Jan Kara
+ - Jeremy Kerr
+ - Russell King
+ - Olaf Kirch
+ - Roel Kluin
+ - Hans-Jürgen Koch
+ - Auke Kok
+ - Peter Korsgaard
+ - Jiri Kosina
+ - Aaro Koskinen
+ - Mariusz Kozlowski
+ - Greg Kroah-Hartman
+ - Michael Krufky
+ - Aneesh Kumar
+ - Clemens Ladisch
+ - Christoph Lameter
+ - Gunnar Larisch
+ - Anders Larsen
+ - Grant Likely
+ - John W. Linville
+ - Yinghai Lu
+ - Tony Luck
+ - Pavel Machek
+ - Matt Mackall
+ - Paul Mackerras
+ - Roland McGrath
+ - Patrick McHardy
+ - Kyle McMartin
+ - Paul Menage
+ - Thierry Merle
+ - Eric Miao
+ - Akinobu Mita
+ - Ingo Molnar
+ - James Morris
+ - Andrew Morton
+ - Paul Mundt
+ - Oleg Nesterov
+ - Luca Olivetti
+ - S.Çağlar Onur
+ - Pierre Ossman
+ - Keith Owens
+ - Venkatesh Pallipadi
+ - Nick Piggin
+ - Nicolas Pitre
+ - Evgeniy Polyakov
+ - Richard Purdie
+ - Mike Rapoport
+ - Sam Ravnborg
+ - Gerrit Renker
+ - Stefan Richter
+ - David Rientjes
+ - Luis R. Rodriguez
+ - Stefan Roese
+ - Francois Romieu
+ - Rami Rosen
+ - Stephen Rothwell
+ - Maciej W. Rozycki
+ - Mark Salyzyn
+ - Yoshinori Sato
+ - Deepak Saxena
+ - Holger Schurig
+ - Amit Shah
+ - Yoshihiro Shimoda
+ - Sergei Shtylyov
+ - Kay Sievers
+ - Sebastian Siewior
+ - Rik Snel
+ - Jes Sorensen
+ - Alexey Starikovskiy
+ - Alan Stern
+ - Timur Tabi
+ - Hirokazu Takata
+ - Eliezer Tamir
+ - Eugene Teo
+ - Doug Thompson
+ - FUJITA Tomonori
+ - Dmitry Torokhov
+ - Marcelo Tosatti
+ - Steven Toth
+ - Theodore Tso
+ - Matthias Urlichs
+ - Geert Uytterhoeven
+ - Arjan van de Ven
+ - Ivo van Doorn
+ - Rik van Riel
+ - Wim Van Sebroeck
+ - Hans Verkuil
+ - Horst H. von Brand
+ - Dmitri Vorobiev
+ - Anton Vorontsov
+ - Daniel Walker
+ - Johannes Weiner
+ - Harald Welte
+ - Matthew Wilcox
+ - Dan J. Williams
+ - Darrick J. Wong
+ - David Woodhouse
+ - Chris Wright
+ - Bryan Wu
+ - Rafael J. Wysocki
+ - Herbert Xu
+ - Vlad Yasevich
+ - Peter Zijlstra
+ - Bartlomiej Zolnierkiewicz
+
diff --git a/Documentation/translations/zh_TW/process/kernel-enforcement-statement.rst b/Documentation/translations/zh_TW/process/kernel-enforcement-statement.rst
new file mode 100644
index 000000000000..99e21d22800d
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/kernel-enforcement-statement.rst
@@ -0,0 +1,155 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _tw_process_statement_kernel:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/kernel-enforcement-statement.rst <process_statement_kernel>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+Linux 內核執行聲明
+------------------
+
+作爲Linux內核的開發人員,我們對如何使用我們的軟體以及如何實施軟體許可證有著
+濃厚的興趣。遵守GPL-2.0的互惠共享義務對我們軟體和社區的長期可持續性至關重要。
+
+雖然有權強制執行對我們社區的貢獻中的單獨版權權益,但我們有共同的利益,即確保
+個人強制執行行動的方式有利於我們的社區,不會對我們軟體生態系統的健康和增長
+產生意外的負面影響。爲了阻止無益的執法行動,我們同意代表我們自己和我們版權
+利益的任何繼承人對Linux內核用戶作出以下符合我們開發社區最大利益的承諾:
+
+    儘管有GPL-2.0的終止條款,我們同意,採用以下GPL-3.0條款作爲我們許可證下的
+    附加許可,作爲任何對許可證下權利的非防禦性主張,這符合我們開發社區的最佳
+    利益。
+
+        但是,如果您停止所有違反本許可證的行爲,則您從特定版權持有人處獲得的
+        許可證將被恢復:(a)暫時恢復,除非版權持有人明確並最終終止您的許可證;
+        以及(b)永久恢復, 如果版權持有人未能在你終止違反後60天內以合理方式
+        通知您違反本許可證的行爲,則永久恢復您的許可證。
+
+        此外,如果版權所有者以某種合理的方式通知您違反了本許可,這是您第一次
+        從該版權所有者處收到違反本許可的通知(對於任何作品),並且您在收到通知
+        後的30天內糾正違規行爲。則您從特定版權所有者處獲得的許可將永久恢復.
+
+我們提供這些保證的目的是鼓勵更多地使用該軟體。我們希望公司和個人使用、修改和
+分發此軟體。我們希望以公開和透明的方式與用戶合作,以消除我們對法規遵從性或強制
+執行的任何不確定性,這些不確定性可能會限制我們軟體的採用。我們將法律行動視爲
+最後手段,只有在其他社區努力未能解決這一問題時才採取行動。
+
+最後,一旦一個不合規問題得到解決,我們希望用戶會感到歡迎,加入我們爲之努力的
+這個項目。共同努力,我們會更強大。
+
+除了下面提到的以外,我們只爲自己說話,而不是爲今天、過去或將來可能爲之工作的
+任何公司說話。
+
+  - Laura Abbott
+  - Bjorn Andersson (Linaro)
+  - Andrea Arcangeli
+  - Neil Armstrong
+  - Jens Axboe
+  - Pablo Neira Ayuso
+  - Khalid Aziz
+  - Ralf Baechle
+  - Felipe Balbi
+  - Arnd Bergmann
+  - Ard Biesheuvel
+  - Tim Bird
+  - Paolo Bonzini
+  - Christian Borntraeger
+  - Mark Brown (Linaro)
+  - Paul Burton
+  - Javier Martinez Canillas
+  - Rob Clark
+  - Kees Cook (Google)
+  - Jonathan Corbet
+  - Dennis Dalessandro
+  - Vivien Didelot (Savoir-faire Linux)
+  - Hans de Goede
+  - Mel Gorman (SUSE)
+  - Sven Eckelmann
+  - Alex Elder (Linaro)
+  - Fabio Estevam
+  - Larry Finger
+  - Bhumika Goyal
+  - Andy Gross
+  - Juergen Gross
+  - Shawn Guo
+  - Ulf Hansson
+  - Stephen Hemminger (Microsoft)
+  - Tejun Heo
+  - Rob Herring
+  - Masami Hiramatsu
+  - Michal Hocko
+  - Simon Horman
+  - Johan Hovold (Hovold Consulting AB)
+  - Christophe JAILLET
+  - Olof Johansson
+  - Lee Jones (Linaro)
+  - Heiner Kallweit
+  - Srinivas Kandagatla
+  - Jan Kara
+  - Shuah Khan (Samsung)
+  - David Kershner
+  - Jaegeuk Kim
+  - Namhyung Kim
+  - Colin Ian King
+  - Jeff Kirsher
+  - Greg Kroah-Hartman (Linux Foundation)
+  - Christian König
+  - Vinod Koul
+  - Krzysztof Kozlowski
+  - Viresh Kumar
+  - Aneesh Kumar K.V
+  - Julia Lawall
+  - Doug Ledford
+  - Chuck Lever (Oracle)
+  - Daniel Lezcano
+  - Shaohua Li
+  - Xin Long
+  - Tony Luck
+  - Catalin Marinas (Arm Ltd)
+  - Mike Marshall
+  - Chris Mason
+  - Paul E. McKenney
+  - Arnaldo Carvalho de Melo
+  - David S. Miller
+  - Ingo Molnar
+  - Kuninori Morimoto
+  - Trond Myklebust
+  - Martin K. Petersen (Oracle)
+  - Borislav Petkov
+  - Jiri Pirko
+  - Josh Poimboeuf
+  - Sebastian Reichel (Collabora)
+  - Guenter Roeck
+  - Joerg Roedel
+  - Leon Romanovsky
+  - Steven Rostedt (VMware)
+  - Frank Rowand
+  - Ivan Safonov
+  - Anna Schumaker
+  - Jes Sorensen
+  - K.Y. Srinivasan
+  - David Sterba (SUSE)
+  - Heiko Stuebner
+  - Jiri Kosina (SUSE)
+  - Willy Tarreau
+  - Dmitry Torokhov
+  - Linus Torvalds
+  - Thierry Reding
+  - Rik van Riel
+  - Luis R. Rodriguez
+  - Geert Uytterhoeven (Glider bvba)
+  - Eduardo Valentin (Amazon.com)
+  - Daniel Vetter
+  - Linus Walleij
+  - Richard Weinberger
+  - Dan Williams
+  - Rafael J. Wysocki
+  - Arvind Yadav
+  - Masahiro Yamada
+  - Wei Yongjun
+  - Lv Zheng
+  - Marc Zyngier (Arm Ltd)
+
diff --git a/Documentation/translations/zh_TW/process/license-rules.rst b/Documentation/translations/zh_TW/process/license-rules.rst
new file mode 100644
index 000000000000..ad2b80f97123
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/license-rules.rst
@@ -0,0 +1,374 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/license-rules.rst <kernel_licensing>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+.. _tw_kernel_licensing:
+
+Linux內核許可規則
+=================
+
+Linux內核根據LICENSES/preferred/GPL-2.0中提供的GNU通用公共許可證版本2
+(GPL-2.0)的條款提供,並在LICENSES/exceptions/Linux-syscall-note中顯式
+描述了例外的系統調用,如COPYING文件中所述。
+
+此文檔文件提供了如何對每個源文件進行注釋以使其許可證清晰明確的說明。
+它不會取代內核的許可證。
+
+內核原始碼作爲一個整體適用於COPYING文件中描述的許可證,但是單個源文件可以
+具有不同的與GPL-20兼容的許可證::
+
+    GPL-1.0+ : GNU通用公共許可證v1.0或更高版本
+    GPL-2.0+ : GNU通用公共許可證v2.0或更高版本
+    LGPL-2.0 : 僅限GNU庫通用公共許可證v2
+    LGPL-2.0+: GNU 庫通用公共許可證v2或更高版本
+    LGPL-2.1 : 僅限GNU寬通用公共許可證v2.1
+    LGPL-2.1+: GNU寬通用公共許可證v2.1或更高版本
+
+除此之外,個人文件可以在雙重許可下提供,例如一個兼容的GPL變體,或者BSD,
+MIT等許可。
+
+用戶空間API(UAPI)頭文件描述了用戶空間程序與內核的接口,這是一種特殊情況。
+根據內核COPYING文件中的注釋,syscall接口是一個明確的邊界,它不會將GPL要求
+擴展到任何使用它與內核通信的軟體。由於UAPI頭文件必須包含在創建在Linux內核
+上運行的可執行文件的任何源文件中,因此此例外必須記錄在特別的許可證表述中。
+
+表達源文件許可證的常用方法是將匹配的樣板文本添加到文件的頂部注釋中。由於
+格式,拼寫錯誤等,這些「樣板」很難通過那些在上下文中使用的驗證許可證合規性
+的工具。
+
+樣板文本的替代方法是在每個源文件中使用軟體包數據交換(SPDX)許可證標識符。
+SPDX許可證標識符是機器可解析的,並且是用於提供文件內容的許可證的精確縮寫。
+SPDX許可證標識符由Linux 基金會的SPDX 工作組管理,並得到了整個行業,工具
+供應商和法律團隊的合作夥伴的一致同意。有關詳細信息,請參閱
+https://spdx.org/
+
+Linux內核需要所有源文件中的精確SPDX標識符。內核中使用的有效標識符在
+`許可標識符`_ 一節中進行了解釋,並且已可以在
+https://spdx.org/licenses/ 上的官方SPDX許可證列表中檢索,並附帶許可證
+文本。
+
+許可標識符語法
+--------------
+
+1.安置:
+
+   內核文件中的SPDX許可證標識符應添加到可包含注釋的文件中的第一行。對於大多
+   數文件,這是第一行,除了那些在第一行中需要'#!PATH_TO_INTERPRETER'的腳本。
+   對於這些腳本,SPDX標識符進入第二行。
+
+|
+
+2. 風格:
+
+   SPDX許可證標識符以注釋的形式添加。注釋樣式取決於文件類型::
+
+      C source:	// SPDX-License-Identifier: <SPDX License Expression>
+      C header:	/* SPDX-License-Identifier: <SPDX License Expression> */
+      ASM:	/* SPDX-License-Identifier: <SPDX License Expression> */
+      scripts:	# SPDX-License-Identifier: <SPDX License Expression>
+      .rst:	.. SPDX-License-Identifier: <SPDX License Expression>
+      .dts{i}:	// SPDX-License-Identifier: <SPDX License Expression>
+
+   如果特定工具無法處理標準注釋樣式,則應使用工具接受的相應注釋機制。這是在
+   C 頭文件中使用「/\*\*/」樣式注釋的原因。過去在使用生成的.lds文件中觀察到
+   構建被破壞,其中'ld'無法解析C++注釋。現在已經解決了這個問題,但仍然有較
+   舊的彙編程序工具無法處理C++樣式的注釋。
+
+|
+
+3. 句法:
+
+   <SPDX許可證表達式>是SPDX許可證列表中的SPDX短格式許可證標識符,或者在許可
+   證例外適用時由「WITH」分隔的兩個SPDX短格式許可證標識符的組合。當應用多個許
+   可證時,表達式由分隔子表達式的關鍵字「AND」,「OR」組成,並由「(」,「)」包圍。
+
+   帶有「或更高」選項的[L]GPL等許可證的許可證標識符通過使用「+」來表示「或更高」
+   選項來構建。::
+
+      // SPDX-License-Identifier: GPL-2.0+
+      // SPDX-License-Identifier: LGPL-2.1+
+
+   當需要修正的許可證時,應使用WITH。 例如,linux內核UAPI文件使用表達式::
+
+      // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
+      // SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note
+
+   其它在內核中使用WITH例外的事例如下::
+
+      // SPDX-License-Identifier: GPL-2.0 WITH mif-exception
+      // SPDX-License-Identifier: GPL-2.0+ WITH GCC-exception-2.0
+
+   例外只能與特定的許可證標識符一起使用。有效的許可證標識符列在異常文本文件
+   的標記中。有關詳細信息,請參閱 `許可標識符`_ 一章中的 `例外`_ 。
+
+   如果文件是雙重許可且只選擇一個許可證,則應使用OR。例如,一些dtsi文件在雙
+   許可下可用::
+
+      // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+
+   內核中雙許可文件中許可表達式的示例::
+
+      // SPDX-License-Identifier: GPL-2.0 OR MIT
+      // SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+      // SPDX-License-Identifier: GPL-2.0 OR Apache-2.0
+      // SPDX-License-Identifier: GPL-2.0 OR MPL-1.1
+      // SPDX-License-Identifier: (GPL-2.0 WITH Linux-syscall-note) OR MIT
+      // SPDX-License-Identifier: GPL-1.0+ OR BSD-3-Clause OR OpenSSL
+
+   如果文件具有多個許可證,其條款全部適用於使用該文件,則應使用AND。例如,
+   如果代碼是從另一個項目繼承的,並且已經授予了將其放入內核的權限,但原始
+   許可條款需要保持有效::
+
+      // SPDX-License-Identifier: (GPL-2.0 WITH Linux-syscall-note) AND MIT
+
+   另一個需要遵守兩套許可條款的例子是::
+
+      // SPDX-License-Identifier: GPL-1.0+ AND LGPL-2.1+
+
+許可標識符
+----------
+
+當前使用的許可證以及添加到內核的代碼許可證可以分解爲:
+
+1. _`優先許可`:
+
+   應儘可能使用這些許可證,因爲它們已知完全兼容並廣泛使用。這些許可證在內核
+   目錄::
+
+      LICENSES/preferred/
+
+   此目錄中的文件包含完整的許可證文本和 `元標記`_ 。文件名與SPDX許可證標識
+   符相同,後者應用於源文件中的許可證。
+
+   例如::
+
+      LICENSES/preferred/GPL-2.0
+
+   包含GPLv2許可證文本和所需的元標籤::
+
+      LICENSES/preferred/MIT
+
+   包含MIT許可證文本和所需的元標記
+
+   _`元標記`:
+
+   許可證文件中必須包含以下元標記:
+
+   - Valid-License-Identifier:
+
+     一行或多行, 聲明那些許可標識符在項目內有效, 以引用此特定許可的文本。通
+     常這是一個有效的標識符,但是例如對於帶有'或更高'選項的許可證,兩個標識
+     符都有效。
+
+   - SPDX-URL:
+
+     SPDX頁面的URL,其中包含與許可證相關的其他信息.
+
+   - Usage-Guidance:
+
+     使用建議的自由格式文本。該文本必須包含SPDX許可證標識符的正確示例,因爲
+     它們應根據 `許可標識符語法`_ 指南放入源文件中。
+
+   - License-Text:
+
+     此標記之後的所有文本都被視爲原始許可文本
+
+   文件格式示例::
+
+      Valid-License-Identifier: GPL-2.0
+      Valid-License-Identifier: GPL-2.0+
+      SPDX-URL: https://spdx.org/licenses/GPL-2.0.html
+      Usage-Guide:
+        To use this license in source code, put one of the following SPDX
+	tag/value pairs into a comment according to the placement
+	guidelines in the licensing rules documentation.
+	For 'GNU General Public License (GPL) version 2 only' use:
+	  SPDX-License-Identifier: GPL-2.0
+	For 'GNU General Public License (GPL) version 2 or any later version' use:
+	  SPDX-License-Identifier: GPL-2.0+
+      License-Text:
+        Full license text
+
+   ::
+
+      SPDX-License-Identifier: MIT
+      SPDX-URL: https://spdx.org/licenses/MIT.html
+      Usage-Guide:
+	To use this license in source code, put the following SPDX
+	tag/value pair into a comment according to the placement
+	guidelines in the licensing rules documentation.
+	  SPDX-License-Identifier: MIT
+      License-Text:
+        Full license text
+
+|
+
+2. 不推薦的許可證:
+
+   這些許可證只應用於現有代碼或從其他項目導入代碼。這些許可證在內核目錄::
+
+      LICENSES/other/
+
+   此目錄中的文件包含完整的許可證文本和 `元標記`_ 。文件名與SPDX許可證標識
+   符相同,後者應用於源文件中的許可證。
+
+   例如::
+
+      LICENSES/other/ISC
+
+   包含國際系統聯合許可文本和所需的元標籤::
+
+      LICENSES/other/ZLib
+
+   包含ZLIB許可文本和所需的元標籤.
+
+   元標籤:
+
+   「其他」許可證的元標籤要求與 `優先許可`_ 的要求相同。
+
+   文件格式示例::
+
+      Valid-License-Identifier: ISC
+      SPDX-URL: https://spdx.org/licenses/ISC.html
+      Usage-Guide:
+        Usage of this license in the kernel for new code is discouraged
+	and it should solely be used for importing code from an already
+	existing project.
+        To use this license in source code, put the following SPDX
+	tag/value pair into a comment according to the placement
+	guidelines in the licensing rules documentation.
+	  SPDX-License-Identifier: ISC
+      License-Text:
+        Full license text
+
+|
+
+3. _`例外`:
+
+   某些許可證可以修改,並允許原始許可證不具有的某些例外權利。這些例外在
+   內核目錄::
+
+      LICENSES/exceptions/
+
+   此目錄中的文件包含完整的例外文本和所需的 `例外元標記`_ 。
+
+   例如::
+
+      LICENSES/exceptions/Linux-syscall-note
+
+   包含Linux內核的COPYING文件中記錄的Linux系統調用例外,該文件用於UAPI
+   頭文件。例如::
+
+      LICENSES/exceptions/GCC-exception-2.0
+
+   包含GCC'連結例外',它允許獨立於其許可證的任何二進位文件與標記有此例外的
+   文件的編譯版本連結。這是從GPL不兼容原始碼創建可運行的可執行文件所必需的。
+
+   _`例外元標記`:
+
+   以下元標記必須在例外文件中可用:
+
+   - SPDX-Exception-Identifier:
+
+     一個可與SPDX許可證標識符一起使用的例外標識符。
+
+   - SPDX-URL:
+
+     SPDX頁面的URL,其中包含與例外相關的其他信息。
+
+   - SPDX-Licenses:
+
+     以逗號分隔的例外可用的SPDX許可證標識符列表。
+
+   - Usage-Guidance:
+
+     使用建議的自由格式文本。必須在文本後面加上SPDX許可證標識符的正確示例,
+     因爲它們應根據 `許可標識符語法`_ 指南放入源文件中。
+
+   - Exception-Text:
+
+     此標記之後的所有文本都被視爲原始異常文本
+
+   文件格式示例::
+
+      SPDX-Exception-Identifier: Linux-syscall-note
+      SPDX-URL: https://spdx.org/licenses/Linux-syscall-note.html
+      SPDX-Licenses: GPL-2.0, GPL-2.0+, GPL-1.0+, LGPL-2.0, LGPL-2.0+, LGPL-2.1, LGPL-2.1+
+      Usage-Guidance:
+        This exception is used together with one of the above SPDX-Licenses
+	to mark user-space API (uapi) header files so they can be included
+	into non GPL compliant user-space application code.
+        To use this exception add it with the keyword WITH to one of the
+	identifiers in the SPDX-Licenses tag:
+	  SPDX-License-Identifier: <SPDX-License> WITH Linux-syscall-note
+      Exception-Text:
+        Full exception text
+
+   ::
+
+      SPDX-Exception-Identifier: GCC-exception-2.0
+      SPDX-URL: https://spdx.org/licenses/GCC-exception-2.0.html
+      SPDX-Licenses: GPL-2.0, GPL-2.0+
+      Usage-Guidance:
+        The "GCC Runtime Library exception 2.0" is used together with one
+	of the above SPDX-Licenses for code imported from the GCC runtime
+	library.
+        To use this exception add it with the keyword WITH to one of the
+	identifiers in the SPDX-Licenses tag:
+	  SPDX-License-Identifier: <SPDX-License> WITH GCC-exception-2.0
+      Exception-Text:
+        Full exception text
+
+
+所有SPDX許可證標識符和例外都必須在LICENSES子目錄中具有相應的文件。這是允許
+工具驗證(例如checkpatch.pl)以及準備好從源讀取和提取許可證所必需的, 這是
+各種FOSS組織推薦的,例如 `FSFE REUSE initiative <https://reuse.software/>`_.
+
+_`模塊許可`
+-----------------
+
+   可加載內核模塊還需要MODULE_LICENSE()標記。此標記既不替代正確的原始碼
+   許可證信息(SPDX-License-Identifier),也不以任何方式表示或確定提供模塊
+   原始碼的確切許可證。
+
+   此標記的唯一目的是提供足夠的信息,該模塊是否是自由軟體或者是內核模塊加
+   載器和用戶空間工具的專有模塊。
+
+   MODULE_LICENSE()的有效許可證字符串是:
+
+    ============================= =============================================
+    "GPL"			  模塊是根據GPL版本2許可的。這並不表示僅限於
+                                  GPL-2.0或GPL-2.0或更高版本之間的任何區別。
+                                  最正確許可證信息只能通過相應源文件中的許可證
+                                  信息來確定
+
+    "GPL v2"			  和"GPL"相同,它的存在是因爲歷史原因。
+
+    "GPL and additional rights"   表示模塊源在GPL v2變體和MIT許可下雙重許可的
+                                  歷史變體。請不要在新代碼中使用。
+
+    "Dual MIT/GPL"		  表達該模塊在GPL v2變體或MIT許可證選擇下雙重
+                                  許可的正確方式。
+
+    "Dual BSD/GPL"		  該模塊根據GPL v2變體或BSD許可證選擇進行雙重
+                                  許可。 BSD許可證的確切變體只能通過相應源文件
+                                  中的許可證信息來確定。
+
+    "Dual MPL/GPL"		  該模塊根據GPL v2變體或Mozilla Public License
+                                  (MPL)選項進行雙重許可。 MPL許可證的確切變體
+                                  只能通過相應的源文件中的許可證信息來確定。
+
+    "Proprietary"		  該模塊屬於專有許可。此字符串僅用於專有的第三
+                                  方模塊,不能用於在內核樹中具有原始碼的模塊。
+                                  以這種方式標記的模塊在加載時會使用'P'標記汙
+                                  染內核,並且內核模塊加載器拒絕將這些模塊連結
+                                  到使用EXPORT_SYMBOL_GPL()導出的符號。
+    ============================= =============================================
+
+
diff --git a/Documentation/translations/zh_TW/process/magic-number.rst b/Documentation/translations/zh_TW/process/magic-number.rst
new file mode 100644
index 000000000000..ae321a9aaece
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/magic-number.rst
@@ -0,0 +1,148 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _tw_magicnumbers:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/magic-number.rst <magicnumbers>`
+
+如果想評論或更新本文的內容,請直接發信到LKML。如果你使用英文交流有困難的話,也可
+以向中文版維護者求助。如果本翻譯更新不及時或者翻譯存在問題,請聯繫中文版維護者::
+
+        中文版維護者: 賈威威 Jia Wei Wei <harryxiyou@gmail.com>
+        中文版翻譯者: 賈威威 Jia Wei Wei <harryxiyou@gmail.com>
+        中文版校譯者: 賈威威 Jia Wei Wei <harryxiyou@gmail.com>
+                      胡皓文 Hu Haowen <src.res@email.cn>
+
+Linux 魔術數
+============
+
+這個文件是有關當前使用的魔術值註冊表。當你給一個結構添加了一個魔術值,你也應該把這個魔術值添加到這個文件,因爲我們最好把用於各種結構的魔術值統一起來。
+
+使用魔術值來保護內核數據結構是一個非常好的主意。這就允許你在運行期檢查(a)一個結構是否已經被攻擊,或者(b)你已經給一個例行程序通過了一個錯誤的結構。後一種情況特別地有用---特別是當你通過一個空指針指向結構體的時候。tty源碼,例如,經常通過特定驅動使用這種方法並且反覆地排列特定方面的結構。
+
+使用魔術值的方法是在結構的開始處聲明的,如下::
+
+        struct tty_ldisc {
+	        int	magic;
+        	...
+        };
+
+當你以後給內核添加增強功能的時候,請遵守這條規則!這樣就會節省數不清的調試時間,特別是一些古怪的情況,例如,數組超出範圍並且重新寫了超出部分。遵守這個規則,‪這些情況可以被快速地,安全地避免。
+
+		Theodore Ts'o
+		  31 Mar 94
+
+給當前的Linux 2.1.55添加魔術表。
+
+		Michael Chastain
+		<mailto:mec@shout.net>
+		22 Sep 1997
+
+現在應該最新的Linux 2.1.112.因爲在特性凍結期間,不能在2.2.x前改變任何東西。這些條目被數域所排序。
+
+		Krzysztof G.Baranowski
+	        <mailto: kgb@knm.org.pl>
+		29 Jul 1998
+
+更新魔術表到Linux 2.5.45。剛好越過特性凍結,但是有可能還會有一些新的魔術值在2.6.x之前融入到內核中。
+
+		Petr Baudis
+		<pasky@ucw.cz>
+		03 Nov 2002
+
+更新魔術表到Linux 2.5.74。
+
+		Fabian Frederick
+                <ffrederick@users.sourceforge.net>
+		09 Jul 2003
+
+===================== ================ ======================== ==========================================
+魔術數名              數字             結構                     文件
+===================== ================ ======================== ==========================================
+PG_MAGIC              'P'              pg_{read,write}_hdr      ``include/linux/pg.h``
+CMAGIC                0x0111           user                     ``include/linux/a.out.h``
+MKISS_DRIVER_MAGIC    0x04bf           mkiss_channel            ``drivers/net/mkiss.h``
+HDLC_MAGIC            0x239e           n_hdlc                   ``drivers/char/n_hdlc.c``
+APM_BIOS_MAGIC        0x4101           apm_user                 ``arch/x86/kernel/apm_32.c``
+DB_MAGIC              0x4442           fc_info                  ``drivers/net/iph5526_novram.c``
+DL_MAGIC              0x444d           fc_info                  ``drivers/net/iph5526_novram.c``
+FASYNC_MAGIC          0x4601           fasync_struct            ``include/linux/fs.h``
+FF_MAGIC              0x4646           fc_info                  ``drivers/net/iph5526_novram.c``
+PTY_MAGIC             0x5001                                    ``drivers/char/pty.c``
+PPP_MAGIC             0x5002           ppp                      ``include/linux/if_pppvar.h``
+SSTATE_MAGIC          0x5302           serial_state             ``include/linux/serial.h``
+SLIP_MAGIC            0x5302           slip                     ``drivers/net/slip.h``
+STRIP_MAGIC           0x5303           strip                    ``drivers/net/strip.c``
+SIXPACK_MAGIC         0x5304           sixpack                  ``drivers/net/hamradio/6pack.h``
+AX25_MAGIC            0x5316           ax_disp                  ``drivers/net/mkiss.h``
+TTY_MAGIC             0x5401           tty_struct               ``include/linux/tty.h``
+MGSL_MAGIC            0x5401           mgsl_info                ``drivers/char/synclink.c``
+TTY_DRIVER_MAGIC      0x5402           tty_driver               ``include/linux/tty_driver.h``
+MGSLPC_MAGIC          0x5402           mgslpc_info              ``drivers/char/pcmcia/synclink_cs.c``
+USB_SERIAL_MAGIC      0x6702           usb_serial               ``drivers/usb/serial/usb-serial.h``
+FULL_DUPLEX_MAGIC     0x6969                                    ``drivers/net/ethernet/dec/tulip/de2104x.c``
+USB_BLUETOOTH_MAGIC   0x6d02           usb_bluetooth            ``drivers/usb/class/bluetty.c``
+RFCOMM_TTY_MAGIC      0x6d02                                    ``net/bluetooth/rfcomm/tty.c``
+USB_SERIAL_PORT_MAGIC 0x7301           usb_serial_port          ``drivers/usb/serial/usb-serial.h``
+CG_MAGIC              0x00090255       ufs_cylinder_group       ``include/linux/ufs_fs.h``
+LSEMAGIC              0x05091998       lse                      ``drivers/fc4/fc.c``
+GDTIOCTL_MAGIC        0x06030f07       gdth_iowr_str            ``drivers/scsi/gdth_ioctl.h``
+RIEBL_MAGIC           0x09051990                                ``drivers/net/atarilance.c``
+NBD_REQUEST_MAGIC     0x12560953       nbd_request              ``include/linux/nbd.h``
+RED_MAGIC2            0x170fc2a5       (any)                    ``mm/slab.c``
+BAYCOM_MAGIC          0x19730510       baycom_state             ``drivers/net/baycom_epp.c``
+ISDN_X25IFACE_MAGIC   0x1e75a2b9       isdn_x25iface_proto_data ``drivers/isdn/isdn_x25iface.h``
+ECP_MAGIC             0x21504345       cdkecpsig                ``include/linux/cdk.h``
+LSOMAGIC              0x27091997       lso                      ``drivers/fc4/fc.c``
+LSMAGIC               0x2a3b4d2a       ls                       ``drivers/fc4/fc.c``
+WANPIPE_MAGIC         0x414C4453       sdla_{dump,exec}         ``include/linux/wanpipe.h``
+CS_CARD_MAGIC         0x43525553       cs_card                  ``sound/oss/cs46xx.c``
+LABELCL_MAGIC         0x4857434c       labelcl_info_s           ``include/asm/ia64/sn/labelcl.h``
+ISDN_ASYNC_MAGIC      0x49344C01       modem_info               ``include/linux/isdn.h``
+CTC_ASYNC_MAGIC       0x49344C01       ctc_tty_info             ``drivers/s390/net/ctctty.c``
+ISDN_NET_MAGIC        0x49344C02       isdn_net_local_s         ``drivers/isdn/i4l/isdn_net_lib.h``
+SAVEKMSG_MAGIC2       0x4B4D5347       savekmsg                 ``arch/*/amiga/config.c``
+CS_STATE_MAGIC        0x4c4f4749       cs_state                 ``sound/oss/cs46xx.c``
+SLAB_C_MAGIC          0x4f17a36d       kmem_cache               ``mm/slab.c``
+COW_MAGIC             0x4f4f4f4d       cow_header_v1            ``arch/um/drivers/ubd_user.c``
+I810_CARD_MAGIC       0x5072696E       i810_card                ``sound/oss/i810_audio.c``
+TRIDENT_CARD_MAGIC    0x5072696E       trident_card             ``sound/oss/trident.c``
+ROUTER_MAGIC          0x524d4157       wan_device               [in ``wanrouter.h`` pre 3.9]
+SAVEKMSG_MAGIC1       0x53415645       savekmsg                 ``arch/*/amiga/config.c``
+GDA_MAGIC             0x58464552       gda                      ``arch/mips/include/asm/sn/gda.h``
+RED_MAGIC1            0x5a2cf071       (any)                    ``mm/slab.c``
+EEPROM_MAGIC_VALUE    0x5ab478d2       lanai_dev                ``drivers/atm/lanai.c``
+HDLCDRV_MAGIC         0x5ac6e778       hdlcdrv_state            ``include/linux/hdlcdrv.h``
+PCXX_MAGIC            0x5c6df104       channel                  ``drivers/char/pcxx.h``
+KV_MAGIC              0x5f4b565f       kernel_vars_s            ``arch/mips/include/asm/sn/klkernvars.h``
+I810_STATE_MAGIC      0x63657373       i810_state               ``sound/oss/i810_audio.c``
+TRIDENT_STATE_MAGIC   0x63657373       trient_state             ``sound/oss/trident.c``
+M3_CARD_MAGIC         0x646e6f50       m3_card                  ``sound/oss/maestro3.c``
+FW_HEADER_MAGIC       0x65726F66       fw_header                ``drivers/atm/fore200e.h``
+SLOT_MAGIC            0x67267321       slot                     ``drivers/hotplug/cpqphp.h``
+SLOT_MAGIC            0x67267322       slot                     ``drivers/hotplug/acpiphp.h``
+LO_MAGIC              0x68797548       nbd_device               ``include/linux/nbd.h``
+M3_STATE_MAGIC        0x734d724d       m3_state                 ``sound/oss/maestro3.c``
+VMALLOC_MAGIC         0x87654320       snd_alloc_track          ``sound/core/memory.c``
+KMALLOC_MAGIC         0x87654321       snd_alloc_track          ``sound/core/memory.c``
+PWC_MAGIC             0x89DC10AB       pwc_device               ``drivers/usb/media/pwc.h``
+NBD_REPLY_MAGIC       0x96744668       nbd_reply                ``include/linux/nbd.h``
+ENI155_MAGIC          0xa54b872d       midway_eprom	        ``drivers/atm/eni.h``
+CODA_MAGIC            0xC0DAC0DA       coda_file_info           ``fs/coda/coda_fs_i.h``
+DPMEM_MAGIC           0xc0ffee11       gdt_pci_sram             ``drivers/scsi/gdth.h``
+YAM_MAGIC             0xF10A7654       yam_port                 ``drivers/net/hamradio/yam.c``
+CCB_MAGIC             0xf2691ad2       ccb                      ``drivers/scsi/ncr53c8xx.c``
+QUEUE_MAGIC_FREE      0xf7e1c9a3       queue_entry              ``drivers/scsi/arm/queue.c``
+QUEUE_MAGIC_USED      0xf7e1cc33       queue_entry              ``drivers/scsi/arm/queue.c``
+HTB_CMAGIC            0xFEFAFEF1       htb_class                ``net/sched/sch_htb.c``
+NMI_MAGIC             0x48414d4d455201 nmi_s                    ``arch/mips/include/asm/sn/nmi.h``
+===================== ================ ======================== ==========================================
+
+
+請注意,在聲音記憶管理中仍然有一些特殊的爲每個驅動定義的魔術值。查看include/sound/sndmagic.h來獲取他們完整的列表信息。很多OSS聲音驅動擁有自己從音效卡PCI ID構建的魔術值-他們也沒有被列在這裡。
+
+IrDA子系統也使用了大量的自己的魔術值,查看include/net/irda/irda.h來獲取他們完整的信息。
+
+HFS是另外一個比較大的使用魔術值的文件系統-你可以在fs/hfs/hfs.h中找到他們。
+
diff --git a/Documentation/translations/zh_TW/process/management-style.rst b/Documentation/translations/zh_TW/process/management-style.rst
new file mode 100644
index 000000000000..dce248470063
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/management-style.rst
@@ -0,0 +1,211 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/management-style.rst <managementstyle>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+.. _tw_managementstyle:
+
+Linux內核管理風格
+=================
+
+這是一個簡短的文檔,描述了Linux內核首選的(或胡編的,取決於您問誰)管理風格。
+它的目的是在某種程度上參照 :ref:`process/coding-style.rst <codingstyle>`
+主要是爲了避免反覆回答 [#cnf1]_ 相同(或類似)的問題。
+
+管理風格是非常個人化的,比簡單的編碼風格規則更難以量化,因此本文檔可能與實
+際情況有關,也可能與實際情況無關。起初它是一個玩笑,但這並不意味著它可能不
+是真的。你得自己決定。
+
+順便說一句,在談到「核心管理者」時,主要是技術負責人,而不是在公司內部進行傳
+統管理的人。如果你簽署了採購訂單或者對你的團隊的預算有任何了解,你幾乎肯定
+不是一個核心管理者。這些建議可能適用於您,也可能不適用於您。
+
+首先,我建議你購買「高效人的七個習慣」,而不是閱讀它。燒了它,這是一個偉大的
+象徵性姿態。
+
+.. [#cnf1] 本文件並不是通過回答問題,而是通過讓提問者痛苦地明白,我們不知道
+   答案是什麼。
+
+不管怎樣,這裡是:
+
+.. _tw_decisions:
+
+1)決策
+-------
+
+每個人都認爲管理者做決定,而且決策很重要。決定越大越痛苦,管理者就必須越高級。
+這很明顯,但事實並非如此。
+
+遊戲的名字是 **避免** 做出決定。尤其是,如果有人告訴你「選擇(a)或(b),
+我們真的需要你來做決定」,你就是陷入麻煩的管理者。你管理的人比你更了解細節,
+所以如果他們來找你做技術決策,你完蛋了。你顯然沒有能力爲他們做這個決定。
+
+(推論:如果你管理的人不比你更了解細節,你也會被搞砸,儘管原因完全不同。
+也就是說,你的工作是錯的,他們應該管理你的才智)
+
+所以遊戲的名字是 **避免** 做出決定,至少是那些大而痛苦的決定。做一些小的
+和非結果性的決定是很好的,並且使您看起來好像知道自己在做什麼,所以內核管理者
+需要做的是將那些大的和痛苦的決定變成那些沒有人真正關心的小事情。
+
+這有助於認識到一個大的決定和一個小的決定之間的關鍵區別是你是否可以在事後修正
+你的決定。任何決定都可以通過始終確保如果你錯了(而且你一定會錯),你以後總是
+可以通過回溯來彌補損失。突然間,你就要做兩個無關緊要的決定,一個是錯誤的,另
+一個是正確的。
+
+人們甚至會認爲這是真正的領導能力(咳,胡說,咳)。
+
+因此,避免重大決策的關鍵在於避免做那些無法挽回的事情。不要被引導到一個你無法
+逃離的角落。走投無路的老鼠可能很危險——走投無路的管理者真可憐。
+
+事實證明,由於沒有人會愚蠢到讓內核管理者承擔巨大的財政責任,所以通常很容易
+回溯。既然你不可能浪費掉你無法償還的巨額資金,你唯一可以回溯的就是技術決策,
+而回溯很容易:只要告訴大家你是個不稱職的傻瓜,說對不起,然後撤銷你去年讓別
+人所做的毫無價值的工作。突然間,你一年前做的決定不在是一個重大的決定,因爲
+它很容易被推翻。
+
+事實證明,有些人對接受這種方法有困難,原因有兩個:
+
+ - 承認你是個白癡比看起來更難。我們都喜歡保持形象,在公共場合說你錯了有時
+   確實很難。
+ - 如果有人告訴你,你去年所做的工作終究是不值得的,那麼對那些可憐的低級工
+   程師來說也是很困難的,雖然實際的 **工作** 很容易刪除,但你可能已經不可
+   挽回地失去了工程師的信任。記住:「不可撤銷」是我們一開始就試圖避免的,
+   而你的決定終究是一個重大的決定。
+
+令人欣慰的是,這兩個原因都可以通過預先承認你沒有任何線索,提前告訴人們你的
+決定完全是初步的,而且可能是錯誤的事情來有效地緩解。你應該始終保留改變主意
+的權利,並讓人們 **意識** 到這一點。當你 **還沒有** 做過真正愚蠢的事情的時
+候,承認自己是愚蠢的要容易得多。
+
+然後,當它真的被證明是愚蠢的時候,人們就轉動他們的眼珠說「哎呀,下次不要了」。
+
+這種對不稱職的先發制人的承認,也可能使真正做這項工作的人也會三思是否值得做。
+畢竟,如果他們不確定這是否是一個好主意,你肯定不應該通過向他們保證他們所做
+的工作將會進入(內核)鼓勵他們。在他們開始一項巨大的努力之前,至少讓他們三
+思而後行。
+
+記住:他們最好比你更了解細節,而且他們通常認爲他們對每件事都有答案。作爲一
+個管理者,你能做的最好的事情不是灌輸自信,而是對他們所做的事情進行健康的批
+判性思考。
+
+順便說一句,另一種避免做出決定的方法是看起來很可憐的抱怨 「我們不能兩者兼
+得嗎?」 相信我,它是有效的。如果不清楚哪種方法更好,他們最終會弄清楚的。
+最終的答案可能是兩個團隊都會因爲這種情況而感到沮喪,以至於他們放棄了。
+
+這聽起來像是一個失敗,但這通常是一個跡象,表明兩個項目都有問題,而參與其中
+的人不能做決定的原因是他們都是錯誤的。你最終會聞到玫瑰的味道,你避免了另一
+個你本可以搞砸的決定。
+
+2)人
+-----
+
+大多數人都是白癡,做一名管理者意味著你必須處理好這件事,也許更重要的是,
+**他們** 必須處理好你。
+
+事實證明,雖然很容易糾正技術錯誤,但不容易糾正人格障礙。你只能和他們的和
+你的(人格障礙)共處。
+
+但是,爲了做好作爲內核管理者的準備,最好記住不要燒掉任何橋樑,不要轟炸任何
+無辜的村民,也不要疏遠太多的內核開發人員。事實證明,疏遠人是相當容易的,而
+親近一個疏遠的人是很難的。因此,「疏遠」立即屬於「不可逆」的範疇,並根據
+:ref:`tw_decisions` 成爲絕不可以做的事情。
+
+這裡只有幾個簡單的規則:
+
+ (1) 不要叫人笨蛋(至少不要在公共場合)
+ (2) 學習如何在忘記規則(1)時道歉
+
+問題在於 #1 很容易去做,因爲你可以用數百萬種不同的方式說「你是一個笨蛋」 [#cnf2]_
+有時甚至沒有意識到,而且幾乎總是帶著一種白熱化的信念,認爲你是對的。
+
+你越確信自己是對的(讓我們面對現實吧,你可以把幾乎所有人都稱爲壞人,而且你
+經常是對的),事後道歉就越難。
+
+要解決此問題,您實際上只有兩個選項:
+
+ - 非常擅長道歉
+ - 把「愛」均勻地散開,沒有人會真正感覺到自己被不公平地瞄準了。讓它有足夠的
+   創造性,他們甚至可能會覺得好笑。
+
+選擇永遠保持禮貌是不存在的。沒有人會相信一個如此明顯地隱藏了他們真實性格的人。
+
+.. [#cnf2] 保羅·西蒙演唱了「離開愛人的50種方法」,因爲坦率地說,「告訴開發者
+   他們是D*CKHEAD" 的100萬種方法都無法確認。但我確信他已經這麼想了。
+
+3)人2 - 好人
+-------------
+
+雖然大多數人都是白癡,但不幸的是,據此推論你也是白癡,儘管我們都自我感覺良
+好,我們比普通人更好(讓我們面對現實吧,沒有人相信他們是普通人或低於普通人),
+我們也應該承認我們不是最鋒利的刀,而且會有其他人比你更不像白癡。
+
+有些人對聰明人反應不好。其他人利用它們。
+
+作爲內核維護人員,確保您在第二組中。接受他們,因爲他們會讓你的工作更容易。
+特別是,他們能夠爲你做決定,這就是遊戲的全部內容。
+
+所以當你發現一個比你聰明的人時,就順其自然吧。你的管理職責在很大程度上變成
+了「聽起來像是個好主意——去嘗試吧」,或者「聽起來不錯,但是XXX呢?」「。第二個版
+本尤其是一個很好的方法,要麼學習一些關於「XXX」的新東西,要麼通過指出一些聰明
+人沒有想到的東西來顯得更具管理性。無論哪種情況,你都會贏。
+
+要注意的一件事是認識到一個領域的偉大不一定會轉化爲其他領域。所以你可能會向
+特定的方向刺激人們,但讓我們面對現實吧,他們可能擅長他們所做的事情,而且對
+其他事情都很差勁。好消息是,人們往往會自然而然地重拾他們擅長的東西,所以當
+你向某個方向刺激他們時,你並不是在做不可逆轉的事情,只是不要用力推。
+
+4)責備
+-------
+
+事情會出問題的,人們希望去責備人。貼標籤,你就是受責備的人。
+
+事實上,接受責備並不難,尤其是當人們意識到這不 **全是** 你的過錯時。這讓我
+們找到了承擔責任的最佳方式:爲別人承擔這件事。你會感覺很好,他們會感覺很好,
+沒有受到指責. 那誰,失去了他們的全部36GB色情收藏的人,因爲你的無能將勉強承
+認,你至少沒有試圖逃避責任。
+
+然後讓真正搞砸了的開發人員(如果你能找到他們)私下知道他們搞砸了。不僅是爲
+了將來可以避免,而且爲了讓他們知道他們欠你一個人情。而且,也許更重要的是,
+他們也可能是能夠解決問題的人。因爲,讓我們面對現實吧,肯定不是你。
+
+承擔責任也是你首先成爲管理者的原因。這是讓人們信任你,讓你獲得潛在的榮耀的
+一部分,因爲你就是那個會說「我搞砸了」的人。如果你已經遵循了以前的規則,你現
+在已經很擅長說了。
+
+5)應避免的事情
+---------------
+
+有一件事人們甚至比被稱爲「笨蛋」更討厭,那就是在一個神聖的聲音中被稱爲「笨蛋」。
+第一個你可以道歉,第二個你不會真正得到機會。即使你做得很好,他們也可能不再
+傾聽。
+
+我們都認爲自己比別人強,這意味著當別人裝腔作勢時,這會讓我們很惱火。你也許
+在道德和智力上比你周圍的每個人都優越,但不要試圖太明顯,除非你真的打算激怒
+某人 [#cnf3]_
+
+同樣,不要對事情太客氣或太微妙。禮貌很容易落得落花流水,把問題隱藏起來,
+正如他們所說,「在網際網路上,沒人能聽到你的含蓄。」用一個鈍器把這一點錘進去,
+因爲你不能真的依靠別人來獲得你的觀點。
+
+一些幽默可以幫助緩和直率和道德化。過度到荒謬的地步,可以灌輸一個觀點,而不
+會讓接受者感到痛苦,他們只是認爲你是愚蠢的。因此,它可以幫助我們擺脫對批評
+的個人心理障礙。
+
+.. [#cnf3] 提示:與你的工作沒有直接關係的網絡新聞組是消除你對他人不滿的好
+   方法。偶爾寫些侮辱性的帖子,打個噴嚏,讓你的情緒得到淨化。別把牢騷帶回家
+
+6)爲什麼是我?
+---------------
+
+既然你的主要責任似乎是爲別人的錯誤承擔責任,並且讓別人痛苦地明白你是不稱職
+的,那麼顯而易見的問題之一就變成了爲什麼首先要這樣做。
+
+首先,雖然你可能會或可能不會聽到十幾歲女孩(或男孩,讓我們不要在這裡評判或
+性別歧視)敲你的更衣室門,你會得到一個巨大的個人成就感爲「負責」。別介意你真
+的在領導別人,你要跟上別人,儘可能快地追趕他們。每個人都會認爲你是負責人。
+
+如果你可以做到這個, 這是個偉大的工作!
+
diff --git a/Documentation/translations/zh_TW/process/programming-language.rst b/Documentation/translations/zh_TW/process/programming-language.rst
new file mode 100644
index 000000000000..54e3699eadf8
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/programming-language.rst
@@ -0,0 +1,76 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/programming-language.rst <programming_language>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+.. _tw_programming_language:
+
+程序設計語言
+============
+
+內核是用C語言 :ref:`c-language <tw_c-language>` 編寫的。更準確地說,內核通常是用 :ref:`gcc <tw_gcc>`
+在 ``-std=gnu89`` :ref:`gcc-c-dialect-options <tw_gcc-c-dialect-options>` 下編譯的:ISO C90的 GNU 方言(
+包括一些C99特性)
+
+這種方言包含對語言 :ref:`gnu-extensions <tw_gnu-extensions>` 的許多擴展,當然,它們許多都在內核中使用。
+
+對於一些體系結構,有一些使用 :ref:`clang <tw_clang>` 和 :ref:`icc <tw_icc>` 編譯內核
+的支持,儘管在編寫此文檔時還沒有完成,仍需要第三方補丁。
+
+屬性
+----
+
+在整個內核中使用的一個常見擴展是屬性(attributes) :ref:`gcc-attribute-syntax <tw_gcc-attribute-syntax>`
+屬性允許將實現定義的語義引入語言實體(如變量、函數或類型),而無需對語言進行
+重大的語法更改(例如添加新關鍵字) :ref:`n2049 <tw_n2049>`
+
+在某些情況下,屬性是可選的(即不支持這些屬性的編譯器仍然應該生成正確的代碼,
+即使其速度較慢或執行的編譯時檢查/診斷次數不夠)
+
+內核定義了僞關鍵字(例如, ``pure`` ),而不是直接使用GNU屬性語法(例如,
+``__attribute__((__pure__))`` ),以檢測可以使用哪些關鍵字和/或縮短代碼, 具體
+請參閱 ``include/linux/compiler_attributes.h``
+
+.. _tw_c-language:
+
+c-language
+   http://www.open-std.org/jtc1/sc22/wg14/www/standards
+
+.. _tw_gcc:
+
+gcc
+   https://gcc.gnu.org
+
+.. _tw_clang:
+
+clang
+   https://clang.llvm.org
+
+.. _tw_icc:
+
+icc
+   https://software.intel.com/en-us/c-compilers
+
+.. _tw_gcc-c-dialect-options:
+
+c-dialect-options
+   https://gcc.gnu.org/onlinedocs/gcc/C-Dialect-Options.html
+
+.. _tw_gnu-extensions:
+
+gnu-extensions
+   https://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html
+
+.. _tw_gcc-attribute-syntax:
+
+gcc-attribute-syntax
+   https://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html
+
+.. _tw_n2049:
+
+n2049
+   http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2049.pdf
+
diff --git a/Documentation/translations/zh_TW/process/stable-api-nonsense.rst b/Documentation/translations/zh_TW/process/stable-api-nonsense.rst
new file mode 100644
index 000000000000..22caa5b8d422
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/stable-api-nonsense.rst
@@ -0,0 +1,159 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _tw_stable_api_nonsense:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/stable-api-nonsense.rst
+           <stable_api_nonsense>`
+
+譯者::
+
+        中文版維護者: 鍾宇  TripleX Chung <xxx.phy@gmail.com>
+        中文版翻譯者: 鍾宇  TripleX Chung <xxx.phy@gmail.com>
+        中文版校譯者: 李陽  Li Yang <leoyang.li@nxp.com>
+                      胡皓文 Hu Haowen <src.res@email.cn>
+
+Linux 內核驅動接口
+==================
+
+寫作本文檔的目的,是爲了解釋爲什麼Linux既沒有二進位內核接口,也沒有穩定
+的內核接口。這裡所說的內核接口,是指內核里的接口,而不是內核和用戶空間
+的接口。內核到用戶空間的接口,是提供給應用程式使用的系統調用,系統調用
+在歷史上幾乎沒有過變化,將來也不會有變化。我有一些老應用程式是在0.9版本
+或者更早版本的內核上編譯的,在使用2.6版本內核的Linux發布上依然用得很好
+。用戶和應用程式作者可以將這個接口看成是穩定的。
+
+
+執行綱要
+--------
+
+你也許以爲自己想要穩定的內核接口,但是你不清楚你要的實際上不是它。你需
+要的其實是穩定的驅動程序,而你只有將驅動程序放到公版內核的原始碼樹里,
+才有可能達到這個目的。而且這樣做還有很多其它好處,正是因爲這些好處使得
+Linux能成爲強壯,穩定,成熟的作業系統,這也是你最開始選擇Linux的原因。
+
+
+入門
+-----
+
+只有那些寫驅動程序的「怪人」才會擔心內核接口的改變,對廣大用戶來說,既
+看不到內核接口,也不需要去關心它。
+
+首先,我不打算討論關於任何非GPL許可的內核驅動的法律問題,這些非GPL許可
+的驅動程序包括不公開原始碼,隱藏原始碼,二進位或者是用原始碼包裝,或者
+是其它任何形式的不能以GPL許可公開原始碼的驅動程序。如果有法律問題,請咨
+詢律師,我只是一個程式設計師,所以我只打算探討技術問題(不是小看法律問題,
+法律問題很實際,並且需要一直關注)。
+
+既然只談技術問題,我們就有了下面兩個主題:二進位內核接口和穩定的內核源
+代碼接口。這兩個問題是互相關聯的,讓我們先解決掉二進位接口的問題。
+
+
+二進位內核接口
+--------------
+假如我們有一個穩定的內核原始碼接口,那麼自然而然的,我們就擁有了穩定的
+二進位接口,是這樣的嗎?錯。讓我們看看關於Linux內核的幾點事實:
+
+    - 取決於所用的C編譯器的版本,不同的內核數據結構里的結構體的對齊方
+      式會有差別,代碼中不同函數的表現形式也不一樣(函數是不是被inline
+      編譯取決於編譯器行爲)。不同的函數的表現形式並不重要,但是數據
+      結構內部的對齊方式很關鍵。
+
+    - 取決於內核的配置選項,不同的選項會讓內核的很多東西發生改變:
+
+      - 同一個結構體可能包含不同的成員變量
+      - 有的函數可能根本不會被實現(比如編譯的時候沒有選擇SMP支持
+        一些鎖函數就會被定義成空函數)。
+      - 內核使用的內存會以不同的方式對齊,這取決於不同的內核配置選
+        項。
+
+    - Linux可以在很多的不同體系結構的處理器上運行。在某個體系結構上編
+      譯好的二進位驅動程序,不可能在另外一個體系結構上正確的運行。
+
+對於一個特定的內核,滿足這些條件並不難,使用同一個C編譯器和同樣的內核配
+置選項來編譯驅動程序模塊就可以了。這對於給一個特定Linux發布的特定版本提
+供驅動程序,是完全可以滿足需求的。但是如果你要給不同發布的不同版本都發
+布一個驅動程序,就需要在每個發布上用不同的內核設置參數都編譯一次內核,
+這簡直跟噩夢一樣。而且還要注意到,每個Linux發布還提供不同的Linux內核,
+這些內核都針對不同的硬體類型進行了優化(有很多種不同的處理器,還有不同
+的內核設置選項)。所以每發布一次驅動程序,都需要提供很多不同版本的內核
+模塊。
+
+相信我,如果你真的要採取這種發布方式,一定會慢慢瘋掉,我很久以前就有過
+深刻的教訓...
+
+
+穩定的內核原始碼接口
+--------------------
+
+如果有人不將他的內核驅動程序,放入公版內核的原始碼樹,而又想讓驅動程序
+一直保持在最新的內核中可用,那麼這個話題將會變得沒完沒了。
+內核開發是持續而且快節奏的,從來都不會慢下來。內核開發人員在當前接口中
+找到bug,或者找到更好的實現方式。一旦發現這些,他們就很快會去修改當前的
+接口。修改接口意味著,函數名可能會改變,結構體可能被擴充或者刪減,函數
+的參數也可能發生改變。一旦接口被修改,內核中使用這些接口的地方需要同時
+修正,這樣才能保證所有的東西繼續工作。
+
+舉一個例子,內核的USB驅動程序接口在USB子系統的整個生命周期中,至少經歷
+了三次重寫。這些重寫解決以下問題:
+
+    - 把數據流從同步模式改成非同步模式,這個改動減少了一些驅動程序的
+      複雜度,提高了所有USB驅動程序的吞吐率,這樣幾乎所有的USB設備都
+      能以最大速率工作了。
+    - 修改了USB核心代碼中爲USB驅動分配數據包內存的方式,所有的驅動都
+      需要提供更多的參數給USB核心,以修正了很多已經被記錄在案的死鎖。
+
+這和一些封閉原始碼的作業系統形成鮮明的對比,在那些作業系統上,不得不額
+外的維護舊的USB接口。這導致了一個可能性,新的開發者依然會不小心使用舊的
+接口,以不恰當的方式編寫代碼,進而影響到作業系統的穩定性。
+在上面的例子中,所有的開發者都同意這些重要的改動,在這樣的情況下修改代
+價很低。如果Linux保持一個穩定的內核原始碼接口,那麼就得創建一個新的接口
+;舊的,有問題的接口必須一直維護,給Linux USB開發者帶來額外的工作。既然
+所有的Linux USB驅動的作者都是利用自己的時間工作,那麼要求他們去做毫無意
+義的免費額外工作,是不可能的。
+安全問題對Linux來說十分重要。一個安全問題被發現,就會在短時間內得到修
+正。在很多情況下,這將導致Linux內核中的一些接口被重寫,以從根本上避免安
+全問題。一旦接口被重寫,所有使用這些接口的驅動程序,必須同時得到修正,
+以確定安全問題已經得到修復並且不可能在未來還有同樣的安全問題。如果內核
+內部接口不允許改變,那麼就不可能修復這樣的安全問題,也不可能確認這樣的
+安全問題以後不會發生。
+開發者一直在清理內核接口。如果一個接口沒有人在使用了,它就會被刪除。這
+樣可以確保內核儘可能的小,而且所有潛在的接口都會得到儘可能完整的測試
+(沒有人使用的接口是不可能得到良好的測試的)。
+
+
+要做什麼
+--------
+
+如果你寫了一個Linux內核驅動,但是它還不在Linux原始碼樹里,作爲一個開發
+者,你應該怎麼做?爲每個發布的每個版本提供一個二進位驅動,那簡直是一個
+噩夢,要跟上永遠處於變化之中的內核接口,也是一件辛苦活。
+很簡單,讓你的驅動進入內核原始碼樹(要記得我們在談論的是以GPL許可發行
+的驅動,如果你的代碼不符合GPL,那麼祝你好運,你只能自己解決這個問題了,
+你這個吸血鬼<把Andrew和Linus對吸血鬼的定義連結到這裡>)。當你的代碼加入
+公版內核原始碼樹之後,如果一個內核接口改變,你的驅動會直接被修改接口的
+那個人修改。保證你的驅動永遠都可以編譯通過,並且一直工作,你幾乎不需要
+做什麼事情。
+
+把驅動放到內核原始碼樹里會有很多的好處:
+
+    - 驅動的質量會提升,而維護成本(對原始作者來說)會下降。
+    - 其他人會給驅動添加新特性。
+    - 其他人會找到驅動中的bug並修復。
+    - 其他人會在驅動中找到性能優化的機會。
+    - 當外部的接口的改變需要修改驅動程序的時候,其他人會修改驅動程序
+    - 不需要聯繫任何發行商,這個驅動會自動的隨著所有的Linux發布一起發
+      布。
+
+和別的作業系統相比,Linux爲更多不同的設備提供現成的驅動,而且能在更多不
+同體系結構的處理器上支持這些設備。這個經過考驗的開發模式,必然是錯不了
+的 :)
+
+感謝
+----
+感謝 Randy Dunlap, Andrew Morton, David Brownell, Hanna Linder,
+Robert Love, and Nishanth Aravamudan 對於本文檔早期版本的評審和建議。
+
+英文版維護者: Greg Kroah-Hartman <greg@kroah.com>
+
diff --git a/Documentation/translations/zh_TW/process/stable-kernel-rules.rst b/Documentation/translations/zh_TW/process/stable-kernel-rules.rst
new file mode 100644
index 000000000000..9bb0d9b4f3ac
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/stable-kernel-rules.rst
@@ -0,0 +1,68 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _tw_stable_kernel_rules:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/stable-kernel-rules.rst <stable_kernel_rules>`
+
+如果想評論或更新本文的內容,請直接聯繫原文檔的維護者。如果你使用英文
+交流有困難的話,也可以向中文版維護者求助。如果本翻譯更新不及時或者翻
+譯存在問題,請聯繫中文版維護者::
+
+        中文版維護者: 鍾宇  TripleX Chung <xxx.phy@gmail.com>
+        中文版翻譯者: 鍾宇  TripleX Chung <xxx.phy@gmail.com>
+        中文版校譯者:
+            - 李陽  Li Yang <leoyang.li@nxp.com>
+            - Kangkai Yin <e12051@motorola.com>
+            - 胡皓文 Hu Haowen <src.res@email.cn>
+
+所有你想知道的事情 - 關於linux穩定版發布
+========================================
+
+關於Linux 2.6穩定版發布,所有你想知道的事情。
+
+關於哪些類型的補丁可以被接收進入穩定版代碼樹,哪些不可以的規則:
+----------------------------------------------------------------
+
+  - 必須是顯而易見的正確,並且經過測試的。
+  - 連同上下文,不能大於100行。
+  - 必須只修正一件事情。
+  - 必須修正了一個給大家帶來麻煩的真正的bug(不是「這也許是一個問題...」
+    那樣的東西)。
+  - 必須修正帶來如下後果的問題:編譯錯誤(對被標記爲CONFIG_BROKEN的例外),
+    內核崩潰,掛起,數據損壞,真正的安全問題,或者一些類似「哦,這不
+    好」的問題。簡短的說,就是一些致命的問題。
+  - 沒有「理論上的競爭條件」,除非能給出競爭條件如何被利用的解釋。
+  - 不能存在任何的「瑣碎的」修正(拼寫修正,去掉多餘空格之類的)。
+  - 必須被相關子系統的維護者接受。
+  - 必須遵循Documentation/translations/zh_TW/process/submitting-patches.rst里的規則。
+
+向穩定版代碼樹提交補丁的過程:
+------------------------------
+
+  - 在確認了補丁符合以上的規則後,將補丁發送到stable@vger.kernel.org。
+  - 如果補丁被接受到隊列里,發送者會收到一個ACK回復,如果沒有被接受,收
+    到的是NAK回復。回復需要幾天的時間,這取決於開發者的時間安排。
+  - 被接受的補丁會被加到穩定版本隊列里,等待其他開發者的審查。
+  - 安全方面的補丁不要發到這個列表,應該發送到security@kernel.org。
+
+審查周期:
+----------
+
+  - 當穩定版的維護者決定開始一個審查周期,補丁將被發送到審查委員會,以
+    及被補丁影響的領域的維護者(除非提交者就是該領域的維護者)並且抄送
+    到linux-kernel郵件列表。
+  - 審查委員會有48小時的時間,用來決定給該補丁回復ACK還是NAK。
+  - 如果委員會中有成員拒絕這個補丁,或者linux-kernel列表上有人反對這個
+    補丁,並提出維護者和審查委員會之前沒有意識到的問題,補丁會從隊列中
+    丟棄。
+  - 在審查周期結束的時候,那些得到ACK回應的補丁將會被加入到最新的穩定版
+    發布中,一個新的穩定版發布就此產生。
+  - 安全性補丁將從內核安全小組那裡直接接收到穩定版代碼樹中,而不是通過
+    通常的審查周期。請聯繫內核安全小組以獲得關於這個過程的更多細節。
+
+審查委員會:
+------------
+  - 由一些自願承擔這項任務的內核開發者,和幾個非志願的組成。
+
diff --git a/Documentation/translations/zh_TW/process/submit-checklist.rst b/Documentation/translations/zh_TW/process/submit-checklist.rst
new file mode 100644
index 000000000000..ff2f89cba83f
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/submit-checklist.rst
@@ -0,0 +1,109 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/submit-checklist.rst <submitchecklist>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+.. _tw_submitchecklist:
+
+Linux內核補丁提交清單
+~~~~~~~~~~~~~~~~~~~~~
+
+如果開發人員希望看到他們的內核補丁提交更快地被接受,那麼他們應該做一些基本
+的事情。
+
+這些都是在
+:ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+和其他有關提交Linux內核補丁的文檔中提供的。
+
+1) 如果使用工具,則包括定義/聲明該工具的文件。不要依賴於其他頭文件拉入您使用
+   的頭文件。
+
+2) 乾淨的編譯:
+
+   a) 使用適用或修改的 ``CONFIG`` 選項 ``=y``、``=m`` 和 ``=n`` 。沒有GCC
+      警告/錯誤,沒有連結器警告/錯誤。
+
+   b) 通過allnoconfig、allmodconfig
+
+   c) 使用 ``O=builddir`` 時可以成功編譯
+
+3) 通過使用本地交叉編譯工具或其他一些構建場在多個CPU體系結構上構建。
+
+4) PPC64是一種很好的交叉編譯檢查體系結構,因爲它傾向於對64位的數使用無符號
+   長整型。
+
+5) 如下所述 :ref:`Documentation/translations/zh_TW/process/coding-style.rst <tw_codingstyle>`.
+   檢查您的補丁是否爲常規樣式。在提交( ``scripts/check patch.pl`` )之前,
+   使用補丁樣式檢查器檢查是否有輕微的衝突。您應該能夠處理您的補丁中存在的所有
+   違規行爲。
+
+6) 任何新的或修改過的 ``CONFIG`` 選項都不會弄髒配置菜單,並默認爲關閉,除非
+   它們符合 ``Documentation/kbuild/kconfig-language.rst`` 中記錄的異常條件,
+   菜單屬性:默認值.
+
+7) 所有新的 ``kconfig`` 選項都有幫助文本。
+
+8) 已仔細審查了相關的 ``Kconfig`` 組合。這很難用測試來糾正——腦力在這裡是有
+   回報的。
+
+9) 用 sparse 檢查乾淨。
+
+10) 使用 ``make checkstack`` 和 ``make namespacecheck`` 並修復他們發現的任何
+    問題。
+
+    .. note::
+
+        ``checkstack`` 並沒有明確指出問題,但是任何一個在堆棧上使用超過512
+        字節的函數都可以進行更改。
+
+11) 包括 :ref:`kernel-doc <kernel_doc>` 內核文檔以記錄全局內核API。(靜態函數
+    不需要,但也可以。)使用 ``make htmldocs`` 或 ``make pdfdocs`` 檢查
+    :ref:`kernel-doc <kernel_doc>` 並修復任何問題。
+
+12) 通過以下選項同時啓用的測試 ``CONFIG_PREEMPT``, ``CONFIG_DEBUG_PREEMPT``,
+    ``CONFIG_DEBUG_SLAB``, ``CONFIG_DEBUG_PAGEALLOC``, ``CONFIG_DEBUG_MUTEXES``,
+    ``CONFIG_DEBUG_SPINLOCK``, ``CONFIG_DEBUG_ATOMIC_SLEEP``,
+    ``CONFIG_PROVE_RCU`` and ``CONFIG_DEBUG_OBJECTS_RCU_HEAD``
+
+13) 已經過構建和運行時測試,包括有或沒有 ``CONFIG_SMP``, ``CONFIG_PREEMPT``.
+
+14) 如果補丁程序影響IO/磁碟等:使用或不使用 ``CONFIG_LBDAF`` 進行測試。
+
+15) 所有代碼路徑都已在啓用所有lockdep功能的情況下運行。
+
+16) 所有新的/proc條目都記錄在 ``Documentation/``
+
+17) 所有新的內核引導參數都記錄在
+    Documentation/admin-guide/kernel-parameters.rst 中。
+
+18) 所有新的模塊參數都記錄在 ``MODULE_PARM_DESC()``
+
+19) 所有新的用戶空間接口都記錄在 ``Documentation/ABI/`` 中。有關詳細信息,
+    請參閱 ``Documentation/ABI/README`` 。更改用戶空間接口的補丁應該抄送
+    linux-api@vger.kernel.org。
+
+20) 已通過至少注入slab和page分配失敗進行檢查。請參閱 ``Documentation/fault-injection/``
+    如果新代碼是實質性的,那麼添加子系統特定的故障注入可能是合適的。
+
+21) 新添加的代碼已經用 ``gcc -W`` 編譯(使用 ``make EXTRA-CFLAGS=-W`` )。這
+    將產生大量噪聲,但對於查找諸如「警告:有符號和無符號之間的比較」之類的錯誤
+    很有用。
+
+22) 在它被合併到-mm補丁集中之後進行測試,以確保它仍然與所有其他排隊的補丁以
+    及VM、VFS和其他子系統中的各種更改一起工作。
+
+23) 所有內存屏障例如 ``barrier()``, ``rmb()``, ``wmb()`` 都需要原始碼中的注
+    釋來解釋它們正在執行的操作及其原因的邏輯。
+
+24) 如果補丁添加了任何ioctl,那麼也要更新 ``Documentation/userspace-api/ioctl/ioctl-number.rst``
+
+25) 如果修改後的原始碼依賴或使用與以下 ``Kconfig`` 符號相關的任何內核API或
+    功能,則在禁用相關 ``Kconfig`` 符號和/或 ``=m`` (如果該選項可用)的情況
+    下測試以下多個構建[並非所有這些都同時存在,只是它們的各種/隨機組合]:
+
+    ``CONFIG_SMP``, ``CONFIG_SYSFS``, ``CONFIG_PROC_FS``, ``CONFIG_INPUT``, ``CONFIG_PCI``, ``CONFIG_BLOCK``, ``CONFIG_PM``, ``CONFIG_MAGIC_SYSRQ``,
+    ``CONFIG_NET``, ``CONFIG_INET=n`` (但是後者伴隨 ``CONFIG_NET=y``).
+
diff --git a/Documentation/translations/zh_TW/process/submitting-drivers.rst b/Documentation/translations/zh_TW/process/submitting-drivers.rst
new file mode 100644
index 000000000000..2fdd742318ba
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/submitting-drivers.rst
@@ -0,0 +1,164 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _tw_submittingdrivers:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/submitting-drivers.rst
+           <submittingdrivers>`
+
+如果想評論或更新本文的內容,請直接聯繫原文檔的維護者。如果你使用英文
+交流有困難的話,也可以向中文版維護者求助。如果本翻譯更新不及時或者翻
+譯存在問題,請聯繫中文版維護者::
+
+        中文版維護者: 李陽  Li Yang <leoyang.li@nxp.com>
+        中文版翻譯者: 李陽  Li Yang <leoyang.li@nxp.com>
+        中文版校譯者: 陳琦 Maggie Chen <chenqi@beyondsoft.com>
+                       王聰 Wang Cong <xiyou.wangcong@gmail.com>
+                       張巍 Zhang Wei <wezhang@outlook.com>
+                       胡皓文 Hu Haowen <src.res@email.cn>
+
+如何向 Linux 內核提交驅動程序
+=============================
+
+這篇文檔將會解釋如何向不同的內核源碼樹提交設備驅動程序。請注意,如果你感
+興趣的是顯卡驅動程序,你也許應該訪問 XFree86 項目(https://www.xfree86.org/)
+和/或 X.org 項目 (https://x.org)。
+
+另請參閱 Documentation/translations/zh_TW/process/submitting-patches.rst 文檔。
+
+
+分配設備號
+----------
+
+塊設備和字符設備的主設備號與從設備號是由 Linux 命名編號分配權威 LANANA(
+現在是 Torben Mathiasen)負責分配。申請的網址是 https://www.lanana.org/。
+即使不準備提交到主流內核的設備驅動也需要在這裡分配設備號。有關詳細信息,
+請參閱 Documentation/admin-guide/devices.rst。
+
+如果你使用的不是已經分配的設備號,那麼當你提交設備驅動的時候,它將會被強
+制分配一個新的設備號,即便這個設備號和你之前發給客戶的截然不同。
+
+設備驅動的提交對象
+------------------
+
+Linux 2.0:
+	此內核源碼樹不接受新的驅動程序。
+
+Linux 2.2:
+	此內核源碼樹不接受新的驅動程序。
+
+Linux 2.4:
+	如果所屬的代碼領域在內核的 MAINTAINERS 文件中列有一個總維護者,
+	那麼請將驅動程序提交給他。如果此維護者沒有回應或者你找不到恰當的
+	維護者,那麼請聯繫 Willy Tarreau <w@1wt.eu>。
+
+Linux 2.6:
+	除了遵循和 2.4 版內核同樣的規則外,你還需要在 linux-kernel 郵件
+	列表上跟蹤最新的 API 變化。向 Linux 2.6 內核提交驅動的頂級聯繫人
+	是 Andrew Morton <akpm@linux-foundation.org>。
+
+決定設備驅動能否被接受的條件
+----------------------------
+
+許可:		代碼必須使用 GNU 通用公開許可證 (GPL) 提交給 Linux,但是
+		我們並不要求 GPL 是唯一的許可。你或許會希望同時使用多種
+		許可證發布,如果希望驅動程序可以被其他開源社區(比如BSD)
+		使用。請參考 include/linux/module.h 文件中所列出的可被
+		接受共存的許可。
+
+版權:		版權所有者必須同意使用 GPL 許可。最好提交者和版權所有者
+		是相同個人或實體。否則,必需列出授權使用 GPL 的版權所有
+		人或實體,以備驗證之需。
+
+接口:		如果你的驅動程序使用現成的接口並且和其他同類的驅動程序行
+		爲相似,而不是去發明無謂的新接口,那麼它將會更容易被接受。
+		如果你需要一個 Linux 和 NT 的通用驅動接口,那麼請在用
+		戶空間實現它。
+
+代碼:		請使用 Documentation/process/coding-style.rst 中所描述的 Linux 代碼風
+		格。如果你的某些代碼段(例如那些與 Windows 驅動程序包共
+		享的代碼段)需要使用其他格式,而你卻只希望維護一份代碼,
+		那麼請將它們很好地區分出來,並且註明原因。
+
+可移植性:	請注意,指針並不永遠是 32 位的,不是所有的計算機都使用小
+		尾模式 (little endian) 存儲數據,不是所有的人都擁有浮點
+		單元,不要隨便在你的驅動程序里嵌入 x86 彙編指令。只能在
+		x86 上運行的驅動程序一般是不受歡迎的。雖然你可能只有 x86
+		硬體,很難測試驅動程序在其他平台上是否可用,但是確保代碼
+		可以被輕鬆地移植卻是很簡單的。
+
+清晰度:	做到所有人都能修補這個驅動程序將會很有好處,因爲這樣你將
+		會直接收到修復的補丁而不是 bug 報告。如果你提交一個試圖
+		隱藏硬體工作機理的驅動程序,那麼它將會被扔進廢紙簍。
+
+電源管理:	因爲 Linux 正在被很多行動裝置和桌面系統使用,所以你的驅
+		動程序也很有可能被使用在這些設備上。它應該支持最基本的電
+		源管理,即在需要的情況下實現系統級休眠和喚醒要用到的
+		.suspend 和 .resume 函數。你應該檢查你的驅動程序是否能正
+		確地處理休眠與喚醒,如果實在無法確認,請至少把 .suspend
+		函數定義成返回 -ENOSYS(功能未實現)錯誤。你還應該嘗試確
+		保你的驅動在什麼都不乾的情況下將耗電降到最低。要獲得驅動
+		程序測試的指導,請參閱
+		Documentation/power/drivers-testing.rst。有關驅動程序電
+		源管理問題相對全面的概述,請參閱
+		Documentation/driver-api/pm/devices.rst。
+
+管理:		如果一個驅動程序的作者還在進行有效的維護,那麼通常除了那
+		些明顯正確且不需要任何檢查的補丁以外,其他所有的補丁都會
+		被轉發給作者。如果你希望成爲驅動程序的聯繫人和更新者,最
+		好在代碼注釋中寫明並且在 MAINTAINERS 文件中加入這個驅動
+		程序的條目。
+
+不影響設備驅動能否被接受的條件
+------------------------------
+
+供應商:	由硬體供應商來維護驅動程序通常是一件好事。不過,如果源碼
+		樹里已經有其他人提供了可穩定工作的驅動程序,那麼請不要期
+		望「我是供應商」會成爲內核改用你的驅動程序的理由。理想的情
+		況是:供應商與現有驅動程序的作者合作,構建一個統一完美的
+		驅動程序。
+
+作者:		驅動程序是由大的 Linux 公司研發還是由你個人編寫,並不影
+		響其是否能被內核接受。沒有人對內核源碼樹享有特權。只要你
+		充分了解內核社區,你就會發現這一點。
+
+
+資源列表
+--------
+
+Linux 內核主源碼樹:
+	ftp.??.kernel.org:/pub/linux/kernel/...
+	?? == 你的國家代碼,例如 "cn"、"us"、"uk"、"fr" 等等
+
+Linux 內核郵件列表:
+	linux-kernel@vger.kernel.org
+	[可通過向majordomo@vger.kernel.org發郵件來訂閱]
+
+Linux 設備驅動程序,第三版(探討 2.6.10 版內核):
+	https://lwn.net/Kernel/LDD3/ (免費版)
+
+LWN.net:
+	每周內核開發活動摘要 - https://lwn.net/
+
+	2.6 版中 API 的變更:
+
+		https://lwn.net/Articles/2.6-kernel-api/
+
+	將舊版內核的驅動程序移植到 2.6 版:
+
+		https://lwn.net/Articles/driver-porting/
+
+內核新手(KernelNewbies):
+	爲新的內核開發者提供文檔和幫助
+	https://kernelnewbies.org/
+
+Linux USB項目:
+	http://www.linux-usb.org/
+
+寫內核驅動的「不要」(Arjan van de Ven著):
+	http://www.fenrus.org/how-to-not-write-a-device-driver-paper.pdf
+
+內核清潔工 (Kernel Janitor):
+	https://kernelnewbies.org/KernelJanitors
+
diff --git a/Documentation/translations/zh_TW/process/submitting-patches.rst b/Documentation/translations/zh_TW/process/submitting-patches.rst
new file mode 100644
index 000000000000..cdf0b52e4a98
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/submitting-patches.rst
@@ -0,0 +1,686 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _tw_submittingpatches:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/submitting-patches.rst <submittingpatches>`
+
+譯者::
+
+        中文版維護者: 鍾宇 TripleX Chung <xxx.phy@gmail.com>
+        中文版翻譯者: 鍾宇 TripleX Chung <xxx.phy@gmail.com>
+                       時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+        中文版校譯者: 李陽 Li Yang <leoyang.li@nxp.com>
+                       王聰 Wang Cong <xiyou.wangcong@gmail.com>
+                       胡皓文 Hu Haowen <src.res@email.cn>
+
+
+如何讓你的改動進入內核
+======================
+
+對於想要將改動提交到 Linux 內核的個人或者公司來說,如果不熟悉「規矩」,
+提交的流程會讓人畏懼。本文檔收集了一系列建議,這些建議可以大大的提高你
+的改動被接受的機會.
+
+以下文檔含有大量簡潔的建議, 具體請見:
+:ref:`Documentation/process <development_process_main>`
+同樣,:ref:`Documentation/translations/zh_TW/process/submit-checklist.rst <tw_submitchecklist>`
+給出在提交代碼前需要檢查的項目的列表。如果你在提交一個驅動程序,那麼
+同時閱讀一下:
+:ref:`Documentation/process/submitting-drivers.rst <submittingdrivers>`
+
+其中許多步驟描述了Git版本控制系統的默認行爲;如果您使用Git來準備補丁,
+您將發現它爲您完成的大部分機械工作,儘管您仍然需要準備和記錄一組合理的
+補丁。一般來說,使用git將使您作爲內核開發人員的生活更輕鬆。
+
+
+0) 獲取當前源碼樹
+-----------------
+
+如果您沒有一個可以使用當前內核原始碼的存儲庫,請使用git獲取一個。您將要
+從主線存儲庫開始,它可以通過以下方式獲取::
+
+        git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
+
+但是,請注意,您可能不希望直接針對主線樹進行開發。大多數子系統維護人員運
+行自己的樹,並希望看到針對這些樹準備的補丁。請參見MAINTAINERS文件中子系
+統的 **T:** 項以查找該樹,或者簡單地詢問維護者該樹是否未在其中列出。
+
+仍然可以通過tarballs下載內核版本(如下一節所述),但這是進行內核開發的
+一種困難的方式。
+
+1) "diff -up"
+-------------
+
+使用 "diff -up" 或者 "diff -uprN" 來創建補丁。
+
+所有內核的改動,都是以補丁的形式呈現的,補丁由 diff(1) 生成。創建補丁的
+時候,要確認它是以 "unified diff" 格式創建的,這種格式由 diff(1) 的 '-u'
+參數生成。而且,請使用 '-p' 參數,那樣會顯示每個改動所在的C函數,使得
+產生的補丁容易讀得多。補丁應該基於內核原始碼樹的根目錄,而不是裡邊的任
+何子目錄。
+
+爲一個單獨的文件創建補丁,一般來說這樣做就夠了::
+
+        SRCTREE=linux
+        MYFILE=drivers/net/mydriver.c
+
+        cd $SRCTREE
+        cp $MYFILE $MYFILE.orig
+        vi $MYFILE      # make your change
+        cd ..
+        diff -up $SRCTREE/$MYFILE{.orig,} > /tmp/patch
+
+爲多個文件創建補丁,你可以解開一個沒有修改過的內核原始碼樹,然後和你自
+己的代碼樹之間做 diff 。例如::
+
+        MYSRC=/devel/linux
+
+        tar xvfz linux-3.19.tar.gz
+        mv linux-3.19 linux-3.19-vanilla
+        diff -uprN -X linux-3.19-vanilla/Documentation/dontdiff \
+                linux-3.19-vanilla $MYSRC > /tmp/patch
+
+"dontdiff" 是內核在編譯的時候產生的文件的列表,列表中的文件在 diff(1)
+產生的補丁里會被跳過。
+
+確定你的補丁里沒有包含任何不屬於這次補丁提交的額外文件。記得在用diff(1)
+生成補丁之後,審閱一次補丁,以確保準確。
+
+如果你的改動很散亂,你應該研究一下如何將補丁分割成獨立的部分,將改動分
+割成一系列合乎邏輯的步驟。這樣更容易讓其他內核開發者審核,如果你想你的
+補丁被接受,這是很重要的。請參閱:
+:ref:`tw_split_changes`
+
+如果你用 ``git`` , ``git rebase -i`` 可以幫助你這一點。如果你不用 ``git``,
+``quilt`` <https://savannah.nongnu.org/projects/quilt> 另外一個流行的選擇。
+
+.. _tw_describe_changes:
+
+2) 描述你的改動
+---------------
+
+描述你的問題。無論您的補丁是一行錯誤修復還是5000行新功能,都必須有一個潛在
+的問題激勵您完成這項工作。讓審稿人相信有一個問題值得解決,讓他們讀完第一段
+是有意義的。
+
+描述用戶可見的影響。直接崩潰和鎖定是相當有說服力的,但並不是所有的錯誤都那麼
+明目張胆。即使在代碼審查期間發現了這個問題,也要描述一下您認爲它可能對用戶產
+生的影響。請記住,大多數Linux安裝運行的內核來自二級穩定樹或特定於供應商/產品
+的樹,只從上游精選特定的補丁,因此請包含任何可以幫助您將更改定位到下游的內容:
+觸發的場景、DMESG的摘錄、崩潰描述、性能回歸、延遲尖峯、鎖定等。
+
+量化優化和權衡。如果您聲稱在性能、內存消耗、堆棧占用空間或二進位大小方面有所
+改進,請包括支持它們的數字。但也要描述不明顯的成本。優化通常不是免費的,而是
+在CPU、內存和可讀性之間進行權衡;或者,探索性的工作,在不同的工作負載之間進
+行權衡。請描述優化的預期缺點,以便審閱者可以權衡成本和收益。
+
+一旦問題建立起來,就要詳細地描述一下您實際在做什麼。對於審閱者來說,用簡單的
+英語描述代碼的變化是很重要的,以驗證代碼的行爲是否符合您的意願。
+
+如果您將補丁描述寫在一個表單中,這個表單可以很容易地作爲「提交日誌」放入Linux
+的原始碼管理系統git中,那麼維護人員將非常感謝您。見 :ref:`tw_explicit_in_reply_to`.
+
+每個補丁只解決一個問題。如果你的描述開始變長,這就表明你可能需要拆分你的補丁。
+請見 :ref:`tw_split_changes`
+
+提交或重新提交修補程序或修補程序系列時,請包括完整的修補程序說明和理由。不要
+只說這是補丁(系列)的第幾版。不要期望子系統維護人員引用更早的補丁版本或引用
+URL來查找補丁描述並將其放入補丁中。也就是說,補丁(系列)及其描述應該是獨立的。
+這對維護人員和審查人員都有好處。一些評審者可能甚至沒有收到補丁的早期版本。
+
+描述你在命令語氣中的變化,例如「make xyzzy do frotz」而不是「[這個補丁]make
+xyzzy do frotz」或「[我]changed xyzzy to do frotz」,就好像你在命令代碼庫改變
+它的行爲一樣。
+
+如果修補程序修復了一個記錄的bug條目,請按編號和URL引用該bug條目。如果補丁來
+自郵件列表討論,請給出郵件列表存檔的URL;使用帶有 ``Message-ID`` 的
+https://lkml.kernel.org/ 重定向,以確保連結不會過時。
+
+但是,在沒有外部資源的情況下,儘量讓你的解釋可理解。除了提供郵件列表存檔或
+bug的URL之外,還要總結需要提交補丁的相關討論要點。
+
+如果您想要引用一個特定的提交,不要只引用提交的 SHA-1 ID。還請包括提交的一行
+摘要,以便於審閱者了解它是關於什麼的。例如::
+
+        Commit e21d2170f36602ae2708 ("video: remove unnecessary
+        platform_set_drvdata()") removed the unnecessary
+        platform_set_drvdata(), but left the variable "dev" unused,
+        delete it.
+
+您還應該確保至少使用前12位 SHA-1 ID. 內核存儲庫包含*許多*對象,使與較短的ID
+發生衝突的可能性很大。記住,即使現在不會與您的六個字符ID發生衝突,這種情況
+可能五年後改變。
+
+如果修補程序修復了特定提交中的錯誤,例如,使用 ``git bisct`` ,請使用帶有前
+12個字符SHA-1 ID 的"Fixes:"標記和單行摘要。爲了簡化不要將標記拆分爲多個,
+行、標記不受分析腳本「75列換行」規則的限制。例如::
+
+        Fixes: 54a4f0239f2e ("KVM: MMU: make kvm_mmu_zap_page() return the number of pages it actually freed")
+
+下列 ``git config`` 設置可以添加讓 ``git log``, ``git show`` 漂亮的顯示格式::
+
+	[core]
+		abbrev = 12
+	[pretty]
+		fixes = Fixes: %h (\"%s\")
+
+.. _tw_split_changes:
+
+3) 拆分你的改動
+---------------
+
+將每個邏輯更改分隔成一個單獨的補丁。
+
+例如,如果你的改動里同時有bug修正和性能優化,那麼把這些改動拆分到兩個或
+者更多的補丁文件中。如果你的改動包含對API的修改,並且修改了驅動程序來適
+應這些新的API,那麼把這些修改分成兩個補丁。
+
+另一方面,如果你將一個單獨的改動做成多個補丁文件,那麼將它們合併成一個
+單獨的補丁文件。這樣一個邏輯上單獨的改動只被包含在一個補丁文件里。
+
+如果有一個補丁依賴另外一個補丁來完成它的改動,那沒問題。簡單的在你的補
+丁描述里指出「這個補丁依賴某補丁」就好了。
+
+在將您的更改劃分爲一系列補丁時,要特別注意確保內核在系列中的每個補丁之後
+都能正常構建和運行。使用 ``git bisect`` 來追蹤問題的開發者可能會在任何時
+候分割你的補丁系列;如果你在中間引入錯誤,他們不會感謝你。
+
+如果你不能將補丁濃縮成更少的文件,那麼每次大約發送出15個,然後等待審查
+和集成。
+
+4) 檢查你的更改風格
+-------------------
+
+檢查您的補丁是否存在基本樣式衝突,詳細信息可在
+:ref:`Documentation/translations/zh_TW/process/coding-style.rst <tw_codingstyle>`
+中找到。如果不這樣做,只會浪費審稿人的時間,並且會導致你的補丁被拒絕,甚至
+可能沒有被閱讀。
+
+一個重要的例外是在將代碼從一個文件移動到另一個文件時——在這種情況下,您不應
+該在移動代碼的同一個補丁中修改移動的代碼。這清楚地描述了移動代碼和您的更改
+的行爲。這大大有助於審查實際差異,並允許工具更好地跟蹤代碼本身的歷史。
+
+在提交之前,使用補丁樣式檢查程序檢查補丁(scripts/check patch.pl)。不過,
+請注意,樣式檢查程序應該被視爲一個指南,而不是作爲人類判斷的替代品。如果您
+的代碼看起來更好,但有違規行爲,那麼最好不要使用它。
+
+檢查者報告三個級別:
+
+ - ERROR:很可能出錯的事情
+ - WARNING:需要仔細審查的事項
+ - CHECK:需要思考的事情
+
+您應該能夠判斷您的補丁中存在的所有違規行爲。
+
+5) 選擇補丁收件人
+-----------------
+
+您應該總是在任何補丁上複製相應的子系統維護人員,以獲得他們維護的代碼;查看
+維護人員文件和原始碼修訂歷史記錄,以了解這些維護人員是誰。腳本
+scripts/get_Maintainer.pl在這個步驟中非常有用。如果您找不到正在工作的子系統
+的維護人員,那麼Andrew Morton(akpm@linux-foundation.org)將充當最後的維護
+人員。
+
+您通常還應該選擇至少一個郵件列表來接收補丁集的。linux-kernel@vger.kernel.org
+作爲最後一個解決辦法的列表,但是這個列表上的體積已經引起了許多開發人員的拒絕。
+在MAINTAINERS文件中查找子系統特定的列表;您的補丁可能會在那裡得到更多的關注。
+不過,請不要發送垃圾郵件到無關的列表。
+
+許多與內核相關的列表託管在vger.kernel.org上;您可以在
+http://vger.kernel.org/vger-lists.html 上找到它們的列表。不過,也有與內核相關
+的列表託管在其他地方。
+
+不要一次發送超過15個補丁到vger郵件列表!!!!
+
+Linus Torvalds 是決定改動能否進入 Linux 內核的最終裁決者。他的 e-mail
+地址是 <torvalds@linux-foundation.org> 。他收到的 e-mail 很多,所以一般
+的說,最好別給他發 e-mail。
+
+如果您有修復可利用安全漏洞的補丁,請將該補丁發送到 security@kernel.org。對於
+嚴重的bug,可以考慮短期暫停以允許分銷商向用戶發布補丁;在這種情況下,顯然不應
+將補丁發送到任何公共列表。
+
+修復已發布內核中嚴重錯誤的補丁程序應該指向穩定版維護人員,方法是放這樣的一行::
+
+        Cc: stable@vger.kernel.org
+
+進入補丁的簽准區(注意,不是電子郵件收件人)。除了這個文件之外,您還應該閱讀
+:ref:`Documentation/process/stable-kernel-rules.rst <stable_kernel_rules>`
+
+但是,請注意,一些子系統維護人員希望得出他們自己的結論,即哪些補丁應該被放到
+穩定的樹上。尤其是網絡維護人員,不希望看到單個開發人員在補丁中添加像上面這樣
+的行。
+
+如果更改影響到用戶和內核接口,請向手冊頁維護人員(如維護人員文件中所列)發送
+手冊頁補丁,或至少發送更改通知,以便一些信息進入手冊頁。還應將用戶空間API
+更改複製到 linux-api@vger.kernel.org。
+
+對於小的補丁,你也許會CC到搜集瑣碎補丁的郵件列表(Trivial Patch Monkey)
+trivial@kernel.org,那裡專門收集瑣碎的補丁。下面這樣的補丁會被看作「瑣碎的」
+補丁:
+
+ - 文檔的拼寫修正。
+ - 修正會影響到 grep(1) 的拼寫。
+ - 警告信息修正(頻繁的列印無用的警告是不好的。)
+ - 編譯錯誤修正(代碼邏輯的確是對的,只是編譯有問題。)
+ - 運行時修正(只要真的修正了錯誤。)
+ - 移除使用了被廢棄的函數/宏的代碼(例如 check_region。)
+ - 聯繫方式和文檔修正。
+ - 用可移植的代碼替換不可移植的代碼(即使在體系結構相關的代碼中,既然有
+ - 人拷貝,只要它是瑣碎的)
+ - 任何文件的作者/維護者對該文件的改動(例如 patch monkey 在重傳模式下)
+
+(譯註,關於「瑣碎補丁」的一些說明:因爲原文的這一部分寫得比較簡單,所以不得不
+違例寫一下譯註。"trivial"這個英文單詞的本意是「瑣碎的,不重要的。」但是在這裡
+有稍微有一些變化,例如對一些明顯的NULL指針的修正,屬於運行時修正,會被歸類
+到瑣碎補丁里。雖然NULL指針的修正很重要,但是這樣的修正往往很小而且很容易得到
+檢驗,所以也被歸入瑣碎補丁。瑣碎補丁更精確的歸類應該是
+「simple, localized & easy to verify」,也就是說簡單的,局部的和易於檢驗的。
+trivial@kernel.org郵件列表的目的是針對這樣的補丁,爲提交者提供一個中心,來
+降低提交的門檻。)
+
+6) 沒有 MIME 編碼,沒有連結,沒有壓縮,沒有附件,只有純文本
+-----------------------------------------------------------
+
+Linus 和其他的內核開發者需要閱讀和評論你提交的改動。對於內核開發者來說
+,可以「引用」你的改動很重要,使用一般的 e-mail 工具,他們就可以在你的
+代碼的任何位置添加評論。
+
+因爲這個原因,所有的提交的補丁都是 e-mail 中「內嵌」的。
+
+.. warning::
+   如果你使用剪切-粘貼你的補丁,小心你的編輯器的自動換行功能破壞你的補丁
+
+不要將補丁作爲 MIME 編碼的附件,不管是否壓縮。很多流行的 e-mail 軟體不
+是任何時候都將 MIME 編碼的附件當作純文本發送的,這會使得別人無法在你的
+代碼中加評論。另外,MIME 編碼的附件會讓 Linus 多花一點時間來處理,這就
+降低了你的改動被接受的可能性。
+
+例外:如果你的郵遞員弄壞了補丁,那麼有人可能會要求你使用mime重新發送補丁
+
+請參閱 :ref:`Documentation/translations/zh_TW/process/email-clients.rst <tw_email_clients>`
+以獲取有關配置電子郵件客戶端以使其不受影響地發送修補程序的提示。
+
+7) e-mail 的大小
+----------------
+
+大的改動對郵件列表不合適,對某些維護者也不合適。如果你的補丁,在不壓縮
+的情況下,超過了300kB,那麼你最好將補丁放在一個能通過 internet 訪問的服
+務器上,然後用指向你的補丁的 URL 替代。但是請注意,如果您的補丁超過了
+300kb,那麼它幾乎肯定需要被破壞。
+
+8)回複評審意見
+---------------
+
+你的補丁幾乎肯定會得到評審者對補丁改進方法的評論。您必須對這些評論作出
+回應;讓補丁被忽略的一個好辦法就是忽略審閱者的意見。不會導致代碼更改的
+意見或問題幾乎肯定會帶來注釋或變更日誌的改變,以便下一個評審者更好地了解
+正在發生的事情。
+
+一定要告訴審稿人你在做什麼改變,並感謝他們的時間。代碼審查是一個累人且
+耗時的過程,審查人員有時會變得暴躁。即使在這種情況下,也要禮貌地回應並
+解決他們指出的問題。
+
+9)不要洩氣或不耐煩
+-------------------
+
+提交更改後,請耐心等待。審閱者是忙碌的人,可能無法立即訪問您的修補程序。
+
+曾幾何時,補丁曾在沒有評論的情況下消失在空白中,但開發過程比現在更加順利。
+您應該在一周左右的時間內收到評論;如果沒有收到評論,請確保您已將補丁發送
+到正確的位置。在重新提交或聯繫審閱者之前至少等待一周-在諸如合併窗口之類的
+繁忙時間可能更長。
+
+10)主題中包含 PATCH
+--------------------
+
+由於到linus和linux內核的電子郵件流量很高,通常會在主題行前面加上[PATCH]
+前綴. 這使Linus和其他內核開發人員更容易將補丁與其他電子郵件討論區分開。
+
+11)簽署你的作品-開發者原始認證
+-------------------------------
+
+爲了加強對誰做了何事的追蹤,尤其是對那些透過好幾層的維護者的補丁,我們
+建議在發送出去的補丁上加一個 「sign-off」 的過程。
+
+"sign-off" 是在補丁的注釋的最後的簡單的一行文字,認證你編寫了它或者其他
+人有權力將它作爲開放原始碼的補丁傳遞。規則很簡單:如果你能認證如下信息:
+
+開發者來源證書 1.1
+^^^^^^^^^^^^^^^^^^
+
+對於本項目的貢獻,我認證如下信息:
+
+      (a)這些貢獻是完全或者部分的由我創建,我有權利以文件中指出
+           的開放原始碼許可證提交它;或者
+      (b)這些貢獻基於以前的工作,據我所知,這些以前的工作受恰當的開放
+           原始碼許可證保護,而且,根據許可證,我有權提交修改後的貢獻,
+           無論是完全還是部分由我創造,這些貢獻都使用同一個開放原始碼許可證
+           (除非我被允許用其它的許可證),正如文件中指出的;或者
+      (c)這些貢獻由認證(a),(b)或者(c)的人直接提供給我,而
+           且我沒有修改它。
+      (d)我理解並同意這個項目和貢獻是公開的,貢獻的記錄(包括我
+           一起提交的個人記錄,包括 sign-off )被永久維護並且可以和這個項目
+           或者開放原始碼的許可證同步地再發行。
+
+那麼加入這樣一行::
+
+       Signed-off-by: Random J Developer <random@developer.example.org>
+
+使用你的真名(抱歉,不能使用假名或者匿名。)
+
+有人在最後加上標籤。現在這些東西會被忽略,但是你可以這樣做,來標記公司
+內部的過程,或者只是指出關於 sign-off 的一些特殊細節。
+
+如果您是子系統或分支維護人員,有時需要稍微修改收到的補丁,以便合併它們,
+因爲樹和提交者中的代碼不完全相同。如果你嚴格遵守規則(c),你應該要求提交者
+重新發布,但這完全是在浪費時間和精力。規則(b)允許您調整代碼,但是更改一個
+提交者的代碼並讓他認可您的錯誤是非常不禮貌的。要解決此問題,建議在最後一個
+由簽名行和您的行之間添加一行,指示更改的性質。雖然這並不是強制性的,但似乎
+在描述前加上您的郵件和/或姓名(全部用方括號括起來),這足以讓人注意到您對最
+後一分鐘的更改負有責任。例如::
+
+	Signed-off-by: Random J Developer <random@developer.example.org>
+	[lucky@maintainer.example.org: struct foo moved from foo.c to foo.h]
+	Signed-off-by: Lucky K Maintainer <lucky@maintainer.example.org>
+
+如果您維護一個穩定的分支機構,同時希望對作者進行致謝、跟蹤更改、合併修復並
+保護提交者不受投訴,那麼這種做法尤其有用。請注意,在任何情況下都不能更改作者
+的ID(From 頭),因爲它是出現在更改日誌中的標識。
+
+對回合(back-porters)的特別說明:在提交消息的頂部(主題行之後)插入一個補丁
+的起源指示似乎是一種常見且有用的實踐,以便於跟蹤。例如,下面是我們在3.x穩定
+版本中看到的內容::
+
+  Date:   Tue Oct 7 07:26:38 2014 -0400
+
+    libata: Un-break ATA blacklist
+
+    commit 1c40279960bcd7d52dbdf1d466b20d24b99176c8 upstream.
+
+還有, 這裡是一個舊版內核中的一個回合補丁::
+
+    Date:   Tue May 13 22:12:27 2008 +0200
+
+        wireless, airo: waitbusy() won't delay
+
+        [backport of 2.6 commit b7acbdfbd1f277c1eb23f344f899cfa4cd0bf36a]
+
+12)何時使用Acked-by:,CC:,和Co-Developed by:
+----------------------------------------------
+
+Singed-off-by: 標記表示簽名者參與了補丁的開發,或者他/她在補丁的傳遞路徑中。
+
+如果一個人沒有直接參與補丁的準備或處理,但希望表示並記錄他們對補丁的批准,
+那麼他們可以要求在補丁的變更日誌中添加一個 Acked-by:
+
+Acked-by:通常由受影響代碼的維護者使用,當該維護者既沒有貢獻也沒有轉發補丁時。
+
+Acked-by: 不像簽字人那樣正式。這是一個記錄,確認人至少審查了補丁,並表示接受。
+因此,補丁合併有時會手動將Acker的「Yep,looks good to me」轉換爲 Acked-By:(但
+請注意,通常最好要求一個明確的Ack)。
+
+Acked-by:不一定表示對整個補丁的確認。例如,如果一個補丁影響多個子系統,並且
+有一個:來自一個子系統維護者,那麼這通常表示只確認影響維護者代碼的部分。這裡
+應該仔細判斷。如有疑問,應參考郵件列表檔案中的原始討論。
+
+如果某人有機會對補丁進行評論,但沒有提供此類評論,您可以選擇在補丁中添加 ``Cc:``
+這是唯一一個標籤,它可以在沒有被它命名的人顯式操作的情況下添加,但它應該表明
+這個人是在補丁上抄送的。討論中包含了潛在利益相關方。
+
+Co-developed-by: 聲明補丁是由多個開發人員共同創建的;當幾個人在一個補丁上工
+作時,它用於將屬性賦予共同作者(除了 From: 所賦予的作者之外)。因爲
+Co-developed-by: 表示作者身份,所以每個共同開發人:必須緊跟在相關合作作者的
+簽名之後。標準的簽核程序要求:標記的簽核順序應儘可能反映補丁的時間歷史,而不
+管作者是通過 From :還是由 Co-developed-by: 共同開發的。值得注意的是,最後一
+個簽字人:必須始終是提交補丁的開發人員。
+
+注意,當作者也是電子郵件標題「發件人:」行中列出的人時,「From: 」 標記是可選的。
+
+作者提交的補丁程序示例::
+
+	<changelog>
+
+	Co-developed-by: First Co-Author <first@coauthor.example.org>
+	Signed-off-by: First Co-Author <first@coauthor.example.org>
+	Co-developed-by: Second Co-Author <second@coauthor.example.org>
+	Signed-off-by: Second Co-Author <second@coauthor.example.org>
+	Signed-off-by: From Author <from@author.example.org>
+
+合作開發者提交的補丁示例::
+
+	From: From Author <from@author.example.org>
+
+	<changelog>
+
+	Co-developed-by: Random Co-Author <random@coauthor.example.org>
+	Signed-off-by: Random Co-Author <random@coauthor.example.org>
+	Signed-off-by: From Author <from@author.example.org>
+	Co-developed-by: Submitting Co-Author <sub@coauthor.example.org>
+	Signed-off-by: Submitting Co-Author <sub@coauthor.example.org>
+
+
+13)使用報告人:、測試人:、審核人:、建議人:、修復人:
+--------------------------------------------------------
+
+Reported-by: 給那些發現錯誤並報告錯誤的人致謝,它希望激勵他們在將來再次幫助
+我們。請注意,如果bug是以私有方式報告的,那麼在使用Reported-by標記之前,請
+先請求權限。
+
+Tested-by: 標記表示補丁已由指定的人(在某些環境中)成功測試。這個標籤通知
+維護人員已經執行了一些測試,爲將來的補丁提供了一種定位測試人員的方法,並確
+保測試人員的信譽。
+
+Reviewed-by:相反,根據審查人的聲明,表明該補丁已被審查並被認爲是可接受的:
+
+
+審查人的監督聲明
+^^^^^^^^^^^^^^^^
+
+通過提供我的 Reviewed-by,我聲明:
+
+        (a) 我已經對這個補丁進行了一次技術審查,以評估它是否適合被包含到
+            主線內核中。
+
+        (b) 與補丁相關的任何問題、顧慮或問題都已反饋給提交者。我對提交者對
+            我的評論的回應感到滿意。
+
+        (c) 雖然這一提交可能會改進一些東西,但我相信,此時,(1)對內核
+            進行了有價值的修改,(2)沒有包含爭論中涉及的已知問題。
+
+        (d) 雖然我已經審查了補丁並認爲它是健全的,但我不會(除非另有明確
+            說明)作出任何保證或保證它將在任何給定情況下實現其規定的目的
+            或正常運行。
+
+Reviewed-by 是一種觀點聲明,即補丁是對內核的適當修改,沒有任何遺留的嚴重技術
+問題。任何感興趣的審閱者(完成工作的人)都可以爲一個補丁提供一個 Review-by
+標籤。此標籤用於向審閱者提供致謝,並通知維護者已在修補程序上完成的審閱程度。
+Reviewed-by: 當由已知了解主題區域並執行徹底檢查的審閱者提供時,通常會增加
+補丁進入內核的可能性。
+
+Suggested-by: 表示補丁的想法是由指定的人提出的,並確保將此想法歸功於指定的
+人。請注意,未經許可,不得添加此標籤,特別是如果該想法未在公共論壇上發布。
+這就是說,如果我們勤快地致謝我們的創意者,他們很有希望在未來得到鼓舞,再次
+幫助我們。
+
+Fixes: 指示補丁在以前的提交中修復了一個問題。它可以很容易地確定錯誤的來源,
+這有助於檢查錯誤修復。這個標記還幫助穩定內核團隊確定應該接收修復的穩定內核
+版本。這是指示補丁修復的錯誤的首選方法。請參閱 :ref:`tw_describe_changes`
+描述您的更改以了解更多詳細信息。
+
+.. _tw_the_canonical_patch_format:
+
+12)標準補丁格式
+----------------
+
+本節描述如何格式化補丁本身。請注意,如果您的補丁存儲在 ``Git`` 存儲庫中,則
+可以使用 ``git format-patch`` 進行正確的補丁格式設置。但是,這些工具無法創建
+必要的文本,因此請務必閱讀下面的說明。
+
+標準的補丁,標題行是::
+
+    Subject: [PATCH 001/123] 子系統:一句話概述
+
+標準補丁的信體存在如下部分:
+
+  - 一個 "from" 行指出補丁作者。後跟空行(僅當發送修補程序的人不是作者時才需要)。
+
+  - 解釋的正文,行以75列包裝,這將被複製到永久變更日誌來描述這個補丁。
+
+  - 一個空行
+
+  - 上面描述的「Signed-off-by」 行,也將出現在更改日誌中。
+
+  - 只包含 ``---`` 的標記線。
+
+  - 任何其他不適合放在變更日誌的注釋。
+
+  - 實際補丁( ``diff`` 輸出)。
+
+標題行的格式,使得對標題行按字母序排序非常的容易 - 很多 e-mail 客戶端都
+可以支持 - 因爲序列號是用零填充的,所以按數字排序和按字母排序是一樣的。
+
+e-mail 標題中的「子系統」標識哪個內核子系統將被打補丁。
+
+e-mail 標題中的「一句話概述」扼要的描述 e-mail 中的補丁。「一句話概述」
+不應該是一個文件名。對於一個補丁系列(「補丁系列」指一系列的多個相關補
+丁),不要對每個補丁都使用同樣的「一句話概述」。
+
+記住 e-mail 的「一句話概述」會成爲該補丁的全局唯一標識。它會蔓延到 git
+的改動記錄里。然後「一句話概述」會被用在開發者的討論里,用來指代這個補
+丁。用戶將希望通過 google 來搜索"一句話概述"來找到那些討論這個補丁的文
+章。當人們在兩三個月後使用諸如 ``gitk`` 或 ``git log --oneline`` 之類
+的工具查看數千個補丁時,也會很快看到它。
+
+出於這些原因,概述必須不超過70-75個字符,並且必須描述補丁的更改以及爲
+什麼需要補丁。既要簡潔又要描述性很有挑戰性,但寫得好的概述應該這樣做。
+
+概述的前綴可以用方括號括起來:「Subject: [PATCH <tag>...] <概述>」。標記
+不被視爲概述的一部分,而是描述應該如何處理補丁。如果補丁的多個版本已發
+送出來以響應評審(即「v1,v2,v3」)或「rfc」,以指示評審請求,那麼通用標記
+可能包括版本描述符。如果一個補丁系列中有四個補丁,那麼各個補丁可以這樣
+編號:1/4、2/4、3/4、4/4。這可以確保開發人員了解補丁應用的順序,並且他們
+已經查看或應用了補丁系列中的所有補丁。
+
+一些標題的例子::
+
+    Subject: [patch 2/5] ext2: improve scalability of bitmap searching
+    Subject: [PATCHv2 001/207] x86: fix eflags tracking
+
+"From" 行是信體裡的最上面一行,具有如下格式:
+        From: Patch Author <author@example.com>
+
+"From" 行指明在永久改動日誌里,誰會被確認爲作者。如果沒有 "From" 行,那
+麼郵件頭裡的 "From: " 行會被用來決定改動日誌中的作者。
+
+說明的主題將會被提交到永久的原始碼改動日誌里,因此對那些早已經不記得和
+這個補丁相關的討論細節的有能力的讀者來說,是有意義的。包括補丁程序定位
+錯誤的(內核日誌消息、OOPS消息等)症狀,對於搜索提交日誌以尋找適用補丁的人
+尤其有用。如果一個補丁修復了一個編譯失敗,那麼可能不需要包含所有編譯失敗;
+只要足夠讓搜索補丁的人能夠找到它就行了。與概述一樣,既要簡潔又要描述性。
+
+"---" 標記行對於補丁處理工具要找到哪裡是改動日誌信息的結束,是不可缺少
+的。
+
+對於 "---" 標記之後的額外註解,一個好的用途就是用來寫 diffstat,用來顯
+示修改了什麼文件和每個文件都增加和刪除了多少行。diffstat 對於比較大的補
+丁特別有用。其餘那些只是和時刻或者開發者相關的註解,不合適放到永久的改
+動日誌里的,也應該放這裡。
+使用 diffstat的選項 "-p 1 -w 70" 這樣文件名就會從內核原始碼樹的目錄開始
+,不會占用太寬的空間(很容易適合80列的寬度,也許會有一些縮進。)
+
+在後面的參考資料中能看到適當的補丁格式的更多細節。
+
+.. _tw_explicit_in_reply_to:
+
+15) 明確回覆郵件頭(In-Reply-To)
+-------------------------------
+
+手動添加回復補丁的的標題頭(In-Reply_To:) 是有幫助的(例如,使用 ``git send-email`` )
+將補丁與以前的相關討論關聯起來,例如,將bug修復程序連結到電子郵件和bug報告。
+但是,對於多補丁系列,最好避免在回復時使用連結到該系列的舊版本。這樣,
+補丁的多個版本就不會成爲電子郵件客戶端中無法管理的引用序列。如果連結有用,
+可以使用 https://lkml.kernel.org/ 重定向器(例如,在封面電子郵件文本中)
+連結到補丁系列的早期版本。
+
+16) 發送git pull請求
+--------------------
+
+如果您有一系列補丁,那麼讓維護人員通過git pull操作將它們直接拉入子系統存儲
+庫可能是最方便的。但是,請注意,從開發人員那裡獲取補丁比從郵件列表中獲取補
+丁需要更高的信任度。因此,許多子系統維護人員不願意接受請求,特別是來自新的
+未知開發人員的請求。如果有疑問,您可以在封面郵件中使用pull 請求作爲補丁系列
+正常發布的一個選項,讓維護人員可以選擇使用其中之一。
+
+pull 請求的主題行中應該有[Git Pull]。請求本身應該在一行中包含存儲庫名稱和
+感興趣的分支;它應該看起來像::
+
+  Please pull from
+
+      git://jdelvare.pck.nerim.net/jdelvare-2.6 i2c-for-linus
+
+  to get these changes:
+
+
+pull 請求還應該包含一條整體消息,說明請求中將包含什麼,一個補丁本身的 ``Git shortlog``
+以及一個顯示補丁系列整體效果的 ``diffstat`` 。當然,將所有這些信息收集在一起
+的最簡單方法是讓 ``git`` 使用 ``git request-pull`` 命令爲您完成這些工作。
+
+一些維護人員(包括Linus)希望看到來自已簽名提交的請求;這增加了他們對你的
+請求信心。特別是,在沒有簽名標籤的情況下,Linus 不會從像 Github 這樣的公共
+託管站點拉請求。
+
+創建此類簽名的第一步是生成一個 GNRPG 密鑰,並由一個或多個核心內核開發人員對
+其進行簽名。這一步對新開發人員來說可能很困難,但沒有辦法繞過它。參加會議是
+找到可以簽署您的密鑰的開發人員的好方法。
+
+一旦您在Git 中準備了一個您希望有人拉的補丁系列,就用 ``git tag -s`` 創建一
+個簽名標記。這將創建一個新標記,標識該系列中的最後一次提交,並包含用您的私
+鑰創建的簽名。您還可以將changelog樣式的消息添加到標記中;這是一個描述拉請求
+整體效果的理想位置。
+
+如果維護人員將要從中提取的樹不是您正在使用的存儲庫,請不要忘記將已簽名的標記
+顯式推送到公共樹。
+
+生成拉請求時,請使用已簽名的標記作爲目標。這樣的命令可以實現::
+
+  git request-pull master git://my.public.tree/linux.git my-signed-tag
+
+參考文獻
+--------
+
+Andrew Morton, "The perfect patch" (tpp).
+  <https://www.ozlabs.org/~akpm/stuff/tpp.txt>
+
+Jeff Garzik, "Linux kernel patch submission format".
+  <https://web.archive.org/web/20180829112450/http://linux.yyz.us/patch-format.html>
+
+Greg Kroah-Hartman, "How to piss off a kernel subsystem maintainer".
+  <http://www.kroah.com/log/linux/maintainer.html>
+
+  <http://www.kroah.com/log/linux/maintainer-02.html>
+
+  <http://www.kroah.com/log/linux/maintainer-03.html>
+
+  <http://www.kroah.com/log/linux/maintainer-04.html>
+
+  <http://www.kroah.com/log/linux/maintainer-05.html>
+
+  <http://www.kroah.com/log/linux/maintainer-06.html>
+
+NO!!!! No more huge patch bombs to linux-kernel@vger.kernel.org people!
+  <https://lore.kernel.org/r/20050711.125305.08322243.davem@davemloft.net>
+
+Kernel Documentation/process/coding-style.rst:
+  :ref:`Documentation/translations/zh_TW/process/coding-style.rst <tw_codingstyle>`
+
+Linus Torvalds's mail on the canonical patch format:
+  <https://lore.kernel.org/r/Pine.LNX.4.58.0504071023190.28951@ppc970.osdl.org>
+
+Andi Kleen, "On submitting kernel patches"
+  Some strategies to get difficult or controversial changes in.
+
+  http://halobates.de/on-submitting-patches.pdf
+
diff --git a/Documentation/translations/zh_TW/process/volatile-considered-harmful.rst b/Documentation/translations/zh_TW/process/volatile-considered-harmful.rst
new file mode 100644
index 000000000000..097fe80352cb
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/volatile-considered-harmful.rst
@@ -0,0 +1,110 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _tw_volatile_considered_harmful:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/volatile-considered-harmful.rst
+           <volatile_considered_harmful>`
+
+如果想評論或更新本文的內容,請直接聯繫原文檔的維護者。如果你使用英文
+交流有困難的話,也可以向中文版維護者求助。如果本翻譯更新不及時或者翻
+譯存在問題,請聯繫中文版維護者::
+
+        英文版維護者: Jonathan Corbet <corbet@lwn.net>
+        中文版維護者: 伍鵬  Bryan Wu <bryan.wu@analog.com>
+        中文版翻譯者: 伍鵬  Bryan Wu <bryan.wu@analog.com>
+        中文版校譯者: 張漢輝  Eugene Teo <eugeneteo@kernel.sg>
+                       楊瑞  Dave Young <hidave.darkstar@gmail.com>
+                       時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+                       胡皓文 Hu Haowen <src.res@email.cn>
+
+爲什麼不應該使用「volatile」類型
+================================
+
+C程式設計師通常認爲volatile表示某個變量可以在當前執行的線程之外被改變;因此,在內核
+中用到共享數據結構時,常常會有C程式設計師喜歡使用volatile這類變量。換句話說,他們經
+常會把volatile類型看成某種簡易的原子變量,當然它們不是。在內核中使用volatile幾
+乎總是錯誤的;本文檔將解釋爲什麼這樣。
+
+理解volatile的關鍵是知道它的目的是用來消除優化,實際上很少有人真正需要這樣的應
+用。在內核中,程式設計師必須防止意外的並發訪問破壞共享的數據結構,這其實是一個完全
+不同的任務。用來防止意外並發訪問的保護措施,可以更加高效的避免大多數優化相關的
+問題。
+
+像volatile一樣,內核提供了很多原語來保證並發訪問時的數據安全(自旋鎖, 互斥量,內
+存屏障等等),同樣可以防止意外的優化。如果可以正確使用這些內核原語,那麼就沒有
+必要再使用volatile。如果仍然必須使用volatile,那麼幾乎可以肯定在代碼的某處有一
+個bug。在正確設計的內核代碼中,volatile能帶來的僅僅是使事情變慢。
+
+思考一下這段典型的內核代碼::
+
+    spin_lock(&the_lock);
+    do_something_on(&shared_data);
+    do_something_else_with(&shared_data);
+    spin_unlock(&the_lock);
+
+如果所有的代碼都遵循加鎖規則,當持有the_lock的時候,不可能意外的改變shared_data的
+值。任何可能訪問該數據的其他代碼都會在這個鎖上等待。自旋鎖原語跟內存屏障一樣—— 它
+們顯式的用來書寫成這樣 —— 意味著數據訪問不會跨越它們而被優化。所以本來編譯器認爲
+它知道在shared_data裡面將有什麼,但是因爲spin_lock()調用跟內存屏障一樣,會強制編
+譯器忘記它所知道的一切。那麼在訪問這些數據時不會有優化的問題。
+
+如果shared_data被聲名爲volatile,鎖操作將仍然是必須的。就算我們知道沒有其他人正在
+使用它,編譯器也將被阻止優化對臨界區內shared_data的訪問。在鎖有效的同時,
+shared_data不是volatile的。在處理共享數據的時候,適當的鎖操作可以不再需要
+volatile —— 並且是有潛在危害的。
+
+volatile的存儲類型最初是爲那些內存映射的I/O寄存器而定義。在內核里,寄存器訪問也應
+該被鎖保護,但是人們也不希望編譯器「優化」臨界區內的寄存器訪問。內核里I/O的內存訪問
+是通過訪問函數完成的;不贊成通過指針對I/O內存的直接訪問,並且不是在所有體系架構上
+都能工作。那些訪問函數正是爲了防止意外優化而寫的,因此,再說一次,volatile類型不
+是必需的。
+
+另一種引起用戶可能使用volatile的情況是當處理器正忙著等待一個變量的值。正確執行一
+個忙等待的方法是::
+
+    while (my_variable != what_i_want)
+        cpu_relax();
+
+cpu_relax()調用會降低CPU的能量消耗或者讓位於超線程雙處理器;它也作爲內存屏障一樣出
+現,所以,再一次,volatile不是必需的。當然,忙等待一開始就是一種反常規的做法。
+
+在內核中,一些稀少的情況下volatile仍然是有意義的:
+
+  - 在一些體系架構的系統上,允許直接的I/0內存訪問,那麼前面提到的訪問函數可以使用
+    volatile。基本上,每一個訪問函數調用它自己都是一個小的臨界區域並且保證了按照
+    程式設計師期望的那樣發生訪問操作。
+
+  - 某些會改變內存的內聯彙編代碼雖然沒有什麼其他明顯的附作用,但是有被GCC刪除的可
+    能性。在彙編聲明中加上volatile關鍵字可以防止這種刪除操作。
+
+  - Jiffies變量是一種特殊情況,雖然每次引用它的時候都可以有不同的值,但讀jiffies
+    變量時不需要任何特殊的加鎖保護。所以jiffies變量可以使用volatile,但是不贊成
+    其他跟jiffies相同類型變量使用volatile。Jiffies被認爲是一種「愚蠢的遺留物"
+    (Linus的話)因爲解決這個問題比保持現狀要麻煩的多。
+
+  - 由於某些I/0設備可能會修改連續一致的內存,所以有時,指向連續一致內存的數據結構
+    的指針需要正確的使用volatile。網絡適配器使用的環狀緩存區正是這類情形的一個例
+    子,其中適配器用改變指針來表示哪些描述符已經處理過了。
+
+對於大多代碼,上述幾種可以使用volatile的情況都不適用。所以,使用volatile是一種
+bug並且需要對這樣的代碼額外仔細檢查。那些試圖使用volatile的開發人員需要退一步想想
+他們真正想實現的是什麼。
+
+非常歡迎刪除volatile變量的補丁 - 只要證明這些補丁完整的考慮了並發問題。
+
+注釋
+----
+
+[1] https://lwn.net/Articles/233481/
+[2] https://lwn.net/Articles/233482/
+
+致謝
+----
+
+最初由Randy Dunlap推動並作初步研究
+由Jonathan Corbet撰寫
+參考Satyam Sharma,Johannes Stezenbach,Jesper Juhl,Heikki Orsila,
+H. Peter Anvin,Philipp Hahn和Stefan Richter的意見改善了本檔。
+
-- 
2.25.1


^ permalink raw reply related	[relevance 1%]

* [PATCH v5 2/2] docs/zh_TW: add translations for zh_TW/process
  @ 2021-07-25 14:14  1%   ` Hu Haowen
  0 siblings, 0 replies; 200+ results
From: Hu Haowen @ 2021-07-25 14:14 UTC (permalink / raw)
  To: corbet; +Cc: panyunwang849, linux-doc, linux-kernel

Create new translations for zh_TW/process and link them to index.

Signed-off-by: Hu Haowen <src.res@email.cn>
Reviewed-by: Pan Yunwang <panyunwang849@gmail.com>
---
 Documentation/translations/zh_TW/index.rst    |  10 +-
 .../translations/zh_TW/process/1.Intro.rst    | 199 ++++
 .../translations/zh_TW/process/2.Process.rst  | 369 +++++++
 .../zh_TW/process/3.Early-stage.rst           | 172 ++++
 .../translations/zh_TW/process/4.Coding.rst   | 297 ++++++
 .../translations/zh_TW/process/5.Posting.rst  | 251 +++++
 .../zh_TW/process/6.Followthrough.rst         | 156 +++
 .../zh_TW/process/7.AdvancedTopics.rst        | 137 +++
 .../zh_TW/process/8.Conclusion.rst            |  74 ++
 .../code-of-conduct-interpretation.rst        | 112 ++
 .../zh_TW/process/code-of-conduct.rst         |  76 ++
 .../zh_TW/process/coding-style.rst            | 958 ++++++++++++++++++
 .../zh_TW/process/development-process.rst     |  30 +
 .../zh_TW/process/email-clients.rst           | 252 +++++
 .../process/embargoed-hardware-issues.rst     | 232 +++++
 .../translations/zh_TW/process/howto.rst      | 500 +++++++++
 .../translations/zh_TW/process/index.rst      |  67 ++
 .../zh_TW/process/kernel-driver-statement.rst | 203 ++++
 .../process/kernel-enforcement-statement.rst  | 155 +++
 .../zh_TW/process/license-rules.rst           | 374 +++++++
 .../zh_TW/process/magic-number.rst            | 148 +++
 .../zh_TW/process/management-style.rst        | 211 ++++
 .../zh_TW/process/programming-language.rst    |  76 ++
 .../zh_TW/process/stable-api-nonsense.rst     | 159 +++
 .../zh_TW/process/stable-kernel-rules.rst     |  68 ++
 .../zh_TW/process/submit-checklist.rst        | 109 ++
 .../zh_TW/process/submitting-drivers.rst      | 164 +++
 .../zh_TW/process/submitting-patches.rst      | 686 +++++++++++++
 .../process/volatile-considered-harmful.rst   | 110 ++
 29 files changed, 6351 insertions(+), 4 deletions(-)
 create mode 100644 Documentation/translations/zh_TW/process/1.Intro.rst
 create mode 100644 Documentation/translations/zh_TW/process/2.Process.rst
 create mode 100644 Documentation/translations/zh_TW/process/3.Early-stage.rst
 create mode 100644 Documentation/translations/zh_TW/process/4.Coding.rst
 create mode 100644 Documentation/translations/zh_TW/process/5.Posting.rst
 create mode 100644 Documentation/translations/zh_TW/process/6.Followthrough.rst
 create mode 100644 Documentation/translations/zh_TW/process/7.AdvancedTopics.rst
 create mode 100644 Documentation/translations/zh_TW/process/8.Conclusion.rst
 create mode 100644 Documentation/translations/zh_TW/process/code-of-conduct-interpretation.rst
 create mode 100644 Documentation/translations/zh_TW/process/code-of-conduct.rst
 create mode 100644 Documentation/translations/zh_TW/process/coding-style.rst
 create mode 100644 Documentation/translations/zh_TW/process/development-process.rst
 create mode 100644 Documentation/translations/zh_TW/process/email-clients.rst
 create mode 100644 Documentation/translations/zh_TW/process/embargoed-hardware-issues.rst
 create mode 100644 Documentation/translations/zh_TW/process/howto.rst
 create mode 100644 Documentation/translations/zh_TW/process/index.rst
 create mode 100644 Documentation/translations/zh_TW/process/kernel-driver-statement.rst
 create mode 100644 Documentation/translations/zh_TW/process/kernel-enforcement-statement.rst
 create mode 100644 Documentation/translations/zh_TW/process/license-rules.rst
 create mode 100644 Documentation/translations/zh_TW/process/magic-number.rst
 create mode 100644 Documentation/translations/zh_TW/process/management-style.rst
 create mode 100644 Documentation/translations/zh_TW/process/programming-language.rst
 create mode 100644 Documentation/translations/zh_TW/process/stable-api-nonsense.rst
 create mode 100644 Documentation/translations/zh_TW/process/stable-kernel-rules.rst
 create mode 100644 Documentation/translations/zh_TW/process/submit-checklist.rst
 create mode 100644 Documentation/translations/zh_TW/process/submitting-drivers.rst
 create mode 100644 Documentation/translations/zh_TW/process/submitting-patches.rst
 create mode 100644 Documentation/translations/zh_TW/process/volatile-considered-harmful.rst

diff --git a/Documentation/translations/zh_TW/index.rst b/Documentation/translations/zh_TW/index.rst
index cab58e428825..76981b2111f6 100644
--- a/Documentation/translations/zh_TW/index.rst
+++ b/Documentation/translations/zh_TW/index.rst
@@ -22,9 +22,7 @@
 下面的文檔介紹了Linux內核原始碼的許可證(GPLv2)、如何在原始碼樹中正確標記
 單個文件的許可證、以及指向完整許可證文本的連結。
 
-TODOList:
-
-* Documentation/translations/zh_TW/process/license-rules.rst
+Documentation/translations/zh_TW/process/license-rules.rst
 
 用戶文檔
 --------
@@ -67,9 +65,13 @@ TODOlist:
 開發人員做出貢獻。與任何大型社區一樣,知道如何完成任務將使得更改合併的過程
 變得更加容易。
 
+.. toctree::
+   :maxdepth: 2
+
+   process/index
+
 TODOList:
 
-* process/index
 * dev-tools/index
 * doc-guide/index
 * kernel-hacking/index
diff --git a/Documentation/translations/zh_TW/process/1.Intro.rst b/Documentation/translations/zh_TW/process/1.Intro.rst
new file mode 100644
index 000000000000..ca2b931be6c5
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/1.Intro.rst
@@ -0,0 +1,199 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/1.Intro.rst <development_process_intro>`
+
+:Translator:
+
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+
+:校譯:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+.. _tw_development_process_intro:
+
+引言
+====
+
+內容提要
+--------
+
+本節的其餘部分涵蓋了內核開發的過程,以及開發人員及其僱主在這方面可能遇到的
+各種問題。有很多原因使內核代碼應被合併到正式的(「主線」)內核中,包括對用戶
+的自動可用性、多種形式的社區支持以及影響內核開發方向的能力。提供給Linux內核
+的代碼必須在與GPL兼容的許可證下可用。
+
+:ref:`tw_development_process` 介紹了開發過程、內核發布周期和合併窗口的機制。
+涵蓋了補丁開發、審查和合併周期中的各個階段。還有一些關於工具和郵件列表的討論?
+鼓勵希望開始內核開發的開發人員跟蹤並修復缺陷以作爲初步練習。
+
+
+:ref:`tw_development_early_stage` 包括項目的早期規劃,重點是儘快讓開發社區
+參與進來。
+
+:ref:`tw_development_coding` 是關於編程過程的;介紹了其他開發人員遇到的幾個
+陷阱。也涵蓋了對補丁的一些要求,並且介紹了一些工具,這些工具有助於確保內核
+補丁是正確的。
+
+:ref:`tw_development_posting` 描述發布補丁以供評審的過程。爲了讓開發社區能
+認真對待,補丁必須被正確格式化和描述,並且必須發送到正確的地方。遵循本節中的
+建議有助於確保您的工作能被較好地接納。
+
+:ref:`tw_development_followthrough` 介紹了發布補丁之後發生的事情;工作在這時
+還遠遠沒有完成。與審閱者一起工作是開發過程中的一個重要部分;本節提供了一些
+關於如何在這個重要階段避免問題的提示。當補丁被合併到主線中時,開發人員要注意
+不要假定任務已經完成。
+
+:ref:`tw_development_advancedtopics` 介紹了兩個「高級」主題:使用Git管理補丁
+和查看其他人發布的補丁。
+
+:ref:`tw_development_conclusion` 總結了有關內核開發的更多信息,附帶有相關資源
+連結。
+
+這個文檔是關於什麼的
+--------------------
+
+Linux內核有超過800萬行代碼,每個版本的貢獻者超過1000人,是現存最大、最活躍的
+免費軟體項目之一。從1991年開始,這個內核已經發展成爲一個最好的作業系統組件,
+運行在袖珍數位音樂播放器、桌上型電腦、現存最大的超級計算機以及所有類型的系統上。
+它是一種適用於幾乎任何情況的健壯、高效和可擴展的解決方案。
+
+隨著Linux的發展,希望參與其開發的開發人員(和公司)的數量也在增加。硬體供應商
+希望確保Linux能夠很好地支持他們的產品,使這些產品對Linux用戶具有吸引力。嵌入
+式系統供應商使用Linux作爲集成產品的組件,希望Linux能夠儘可能地勝任手頭的任務。
+分銷商和其他基於Linux的軟體供應商切實關心Linux內核的功能、性能和可靠性。最終
+用戶也常常希望修改Linux,使之能更好地滿足他們的需求。
+
+Linux最引人注目的特性之一是這些開發人員可以訪問它;任何具備必要技能的人都可以
+改進Linux並影響其開發方向。專有產品不能提供這種開放性,這是自由軟體的一個特點。
+如果有什麼不同的話,那就是內核比大多數其他自由軟體項目更開放。一個典型的三個
+月內核開發周期可以涉及1000多個開發人員,他們爲100多個不同的公司(或者根本不
+隸屬公司)工作。
+
+與內核開發社區合作並不是特別困難。但儘管如此,仍有許多潛在的貢獻者在嘗試做
+內核工作時遇到了困難。內核社區已經發展出自己獨特的操作方式,使其能夠在每天
+都要更改數千行代碼的環境中順利運行(並生成高質量的產品)。因此,Linux內核開發
+過程與專有的開發模式有很大的不同也就不足爲奇了。
+
+對於新開發人員來說,內核的開發過程可能會讓人感到奇怪和恐懼,但這背後有充分的
+理由和堅實的經驗。一個不了解內核社區工作方式的開發人員(或者更糟的是,他們
+試圖拋棄或規避之)會得到令人沮喪的體驗。開發社區在幫助那些試圖學習的人的同時,
+沒有時間幫助那些不願意傾聽或不關心開發過程的人。
+
+希望閱讀本文的人能夠避免這種令人沮喪的經歷。這些材料很長,但閱讀它們時所做的
+努力會在短時間內得到回報。開發社區總是需要能讓內核變更好的開發人員;下面的
+文字應該幫助您或爲您工作的人員加入我們的社區。
+
+致謝
+----
+
+本文檔由Jonathan Corbet <corbet@lwn.net> 撰寫。以下人員的建議使之更爲完善:
+Johannes Berg, James Berry, Alex Chiang, Roland Dreier, Randy Dunlap,
+Jake Edge, Jiri Kosina, Matt Mackall, Arthur Marsh, Amanda McPherson,
+Andrew Morton, Andrew Price, Tsugikazu Shibata 和 Jochen Voß 。
+
+這項工作得到了Linux基金會的支持,特別感謝Amanda McPherson,他看到了這項工作
+的價值並將其變成現實。
+
+代碼進入主線的重要性
+--------------------
+
+有些公司和開發人員偶爾會想,爲什麼他們要費心學習如何與內核社區合作,並將代碼
+放入主線內核(「主線」是由Linus Torvalds維護的內核,Linux發行商將其用作基礎)。
+在短期內,貢獻代碼看起來像是一種可以避免的開銷;維護獨立代碼並直接支持用戶
+似乎更容易。事實上,保持代碼獨立(「樹外」)是在經濟上是錯誤的。
+
+爲了說明樹外代碼成本,下面給出內核開發過程的一些相關方面;本文稍後將更詳細地
+討論其中的大部分內容。請考慮:
+
+- 所有Linux用戶都可以使用合併到主線內核中的代碼。它將自動出現在所有啓用它的
+  發行版上。無需驅動程序磁碟、額外下載,也不需要爲多個發行版的多個版本提供
+  支持;這一切將方便所有開發人員和用戶。併入主線解決了大量的分發和支持問題。
+
+- 當內核開發人員努力維護一個穩定的用戶空間接口時,內核內部API處於不斷變化之中。
+  不維持穩定的內部接口是一個慎重的設計決策;它允許在任何時候進行基本的改進,
+  並產出更高質量的代碼。但該策略導致結果是,若要使用新的內核,任何樹外代碼都
+  需要持續的維護。維護樹外代碼會需要大量的工作才能使代碼保持正常運行。
+
+  相反,位於主線中的代碼不需要這樣做,因爲基本規則要求進行API更改的任何開發
+  人員也必須修復由於該更改而破壞的任何代碼。因此,合併到主線中的代碼大大降低
+  了維護成本。
+
+- 除此之外,內核中的代碼通常會被其他開發人員改進。您授權的用戶社區和客戶對您
+  產品的改進可能會令人驚喜。
+
+- 內核代碼在合併到主線之前和之後都要經過審查。無論原始開發人員的技能有多強,
+  這個審查過程總是能找到改進代碼的方法。審查經常發現嚴重的錯誤和安全問題。
+  對於在封閉環境中開發的代碼尤其如此;這種代碼從外部開發人員的審查中獲益匪淺。
+  樹外代碼是低質量代碼。
+
+- 參與開發過程是您影響內核開發方向的方式。旁觀者的抱怨會被聽到,但是活躍的
+  開發人員有更強的聲音——並且能夠實現使內核更好地滿足其需求的更改。
+
+- 當單獨維護代碼時,總是存在第三方爲類似功能提供不同實現的可能性。如果發生
+  這種情況,合併代碼將變得更加困難——甚至成爲不可能。之後,您將面臨以下令人
+  不快的選擇:(1)無限期地維護樹外的非標準特性,或(2)放棄代碼並將用戶遷移
+  到樹內版本。
+
+- 代碼的貢獻是使整個流程工作的根本。通過貢獻代碼,您可以向內核添加新功能,並
+  提供其他內核開發人員使用的功能和示例。如果您已經爲Linux開發了代碼(或者正在
+  考慮這樣做),那麼您顯然對這個平台的持續成功感興趣;貢獻代碼是確保成功的
+  最好方法之一。
+
+上述所有理由都適用於任何樹外內核代碼,包括以專有的、僅二進位形式分發的代碼。
+然而,在考慮任何類型的純二進位內核代碼分布之前,還需要考慮其他因素。包括:
+
+- 圍繞專有內核模塊分發的法律問題其實較爲模糊;相當多的內核版權所有者認爲,
+  大多數僅二進位的模塊是內核的派生產品,因此,它們的分發違反了GNU通用公共
+  許可證(下面將詳細介紹)。本文作者不是律師,本文檔中的任何內容都不可能被
+  視爲法律建議。封閉原始碼模塊的真實法律地位只能由法院決定。但不管怎樣,困擾
+  這些模塊的不確定性仍然存在。
+
+- 二進位模塊大大增加了調試內核問題的難度,以至於大多數內核開發人員甚至都不會
+  嘗試。因此,只分發二進位模塊將使您的用戶更難從社區獲得支持。
+
+- 對於僅二進位的模塊的發行者來說,支持也更加困難,他們必須爲他們希望支持的
+  每個發行版和每個內核版本提供不同版本的模塊。爲了提供較爲全面的覆蓋範圍,
+  可能需要一個模塊的幾十個構建,並且每次升級內核時,您的用戶都必須單獨升級
+  這些模塊。
+
+- 上面提到的關於代碼評審的所有問題都更加存在於封閉原始碼中。由於該代碼根本
+  不可得,因此社區無法對其進行審查,毫無疑問,它將存在嚴重問題。
+
+尤其是嵌入式系統的製造商,可能會傾向於忽視本節中所說的大部分內容;因爲他們
+相信自己正在商用一種使用凍結內核版本的獨立產品,在發布後不需要再進行開發。
+這個論點忽略了廣泛的代碼審查的價值以及允許用戶向產品添加功能的價值。但這些
+產品的商業壽命有限,之後必須發布新版本的產品。在這一點上,代碼在主線上並得到
+良好維護的供應商將能夠更好地占位,以使新產品快速上市。
+
+許可
+----
+
+代碼是根據一些許可證提供給Linux內核的,但是所有代碼都必須與GNU通用公共許可
+證(GPLV2)的版本2兼容,該版本是覆蓋整個內核分發的許可證。在實踐中,這意味
+著所有代碼貢獻都由GPLv2(可選地,語言允許在更高版本的GPL下分發)或3子句BSD
+許可(New BSD License,譯者注)覆蓋。任何不包含在兼容許可證中的貢獻都不會
+被接受到內核中。
+
+貢獻給內核的代碼不需要(或請求)版權分配。合併到主線內核中的所有代碼都保留
+其原始所有權;因此,內核現在擁有數千個所有者。
+
+這種所有權結構也暗示著,任何改變內核許可的嘗試都註定會失敗。很少有實際情況
+可以獲得所有版權所有者的同意(或者從內核中刪除他們的代碼)。因此,尤其是在
+可預見的將來,許可證不大可能遷移到GPL的版本3。
+
+所有貢獻給內核的代碼都必須是合法的免費軟體。因此,不接受匿名(或化名)貢獻
+者的代碼。所有貢獻者都需要在他們的代碼上「sign off(簽發)」,聲明代碼可以
+在GPL下與內核一起分發。無法提供未被其所有者許可爲免費軟體的代碼,或可能爲
+內核造成版權相關問題的代碼(例如,由缺乏適當保護的反向工程工作派生的代碼)
+不能被接受。
+
+有關版權問題的提問在Linux開發郵件列表中很常見。這樣的問題通常會得到不少答案,
+但請記住,回答這些問題的人不是律師,不能提供法律諮詢。如果您有關於Linux原始碼
+的法律問題,沒有什麼可以代替諮詢了解這一領域的律師。依賴從技術郵件列表中獲得
+的答案是一件冒險的事情。
+
+
diff --git a/Documentation/translations/zh_TW/process/2.Process.rst b/Documentation/translations/zh_TW/process/2.Process.rst
new file mode 100644
index 000000000000..b01cdd3a39ae
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/2.Process.rst
@@ -0,0 +1,369 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/2.Process.rst <development_process>`
+
+:Translator:
+
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+
+:校譯:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+.. _tw_development_process:
+
+開發流程如何進行
+================
+
+90年代早期的Linux內核開發是一件相當鬆散的事情,涉及的用戶和開發人員相對較少。
+由於擁有數以百萬計的用戶羣,且每年有大約2000名開發人員參與進來,內核因此必須
+發展出許多既定流程來保證開發的順利進行。要參與到流程中來,需要對此流程的進行
+方式有一個紮實的理解。
+
+總覽
+----
+
+內核開發人員使用一個鬆散的基於時間的發布過程,每兩到三個月發布一次新的主要
+內核版本。最近的發布歷史記錄如下:
+
+	======  =================
+	5.0	2019年3月3日
+	5.1	2019年5月5日
+	5.2	2019年7月7日
+	5.3	2019年9月15日
+	5.4	2019年11月24日
+	5.5	2020年1月6日
+	======  =================
+
+每個5.x版本都是一個主要的內核版本,具有新特性、內部API更改等等。一個典型的5.x
+版本包含大約13000個變更集,變更了幾十萬行代碼。因此,5.x是Linux內核開發的前
+沿;內核使用滾動開發模型,不斷集成重大變化。
+
+對於每個版本的補丁合併,遵循一個相對簡單的規則。在每個開發周期的開頭,「合併
+窗口」被打開。這時,被認爲足夠穩定(並且被開發社區接受)的代碼被合併到主線內
+核中。在這段時間內,新開發周期的大部分變更(以及所有主要變更)將以接近每天
+1000次變更(「補丁」或「變更集」)的速度合併。
+
+(順便說一句,值得注意的是,合併窗口期間集成的更改並不是憑空產生的;它們是經
+提前收集、測試和分級的。稍後將詳細描述該過程的工作方式。)
+
+合併窗口持續大約兩周。在這段時間結束時,LinusTorvalds將聲明窗口已關閉,並
+釋放第一個「rc」內核。例如,對於目標爲5.6的內核,在合併窗口結束時發生的釋放
+將被稱爲5.6-rc1。-rc1 版本是一個信號,表示合併新特性的時間已經過去,穩定下一
+個內核的時間已經到來。
+
+在接下來的6到10周內,只有修復問題的補丁才應該提交給主線。有時會允許更大的
+更改,但這種情況很少發生;試圖在合併窗口外合併新功能的開發人員往往受不到
+友好的接待。一般來說,如果您錯過了給定特性的合併窗口,最好的做法是等待下一
+個開發周期。(偶爾會對未支持硬體的驅動程序進行例外;如果它們不改變已有代碼,
+則不會導致回歸,應該可以隨時被安全地加入)。
+
+隨著修復程序進入主線,補丁速度將隨著時間的推移而變慢。Linus大約每周發布一次
+新的-rc內核;在內核被認爲足夠穩定並最終發布前,一般會達到-rc6到-rc9之間。
+然後,整個過程又重新開始了。
+
+例如,這裡是5.4的開發周期進行情況(2019年):
+
+	==============  ==============================
+	九月 15         5.3 穩定版發布
+	九月 30         5.4-rc1 合併窗口關閉
+	十月 6          5.4-rc2
+	十月 13         5.4-rc3
+	十月 20         5.4-rc4
+	十月 27         5.4-rc5
+	十一月 3        5.4-rc6
+	十一月 10       5.4-rc7
+	十一月 17       5.4-rc8
+	十一月 24       5.4 穩定版發布
+	==============  ==============================
+
+開發人員如何決定何時結束開發周期並創建穩定版本?最重要的指標是以前版本的
+回歸列表。不歡迎出現任何錯誤,但是那些破壞了以前能工作的系統的錯誤被認爲是
+特別嚴重的。因此,導致回歸的補丁是不受歡迎的,很可能在穩定期內刪除。
+
+開發人員的目標是在穩定發布之前修復所有已知的回歸。在現實世界中,這種完美是
+很難實現的;在這種規模的項目中,變數太多了。需要說明的是,延遲最終版本只會
+使問題變得更糟;等待下一個合併窗口的更改將變多,導致下次出現更多的回歸錯誤。
+因此,大多數5.x內核都有一些已知的回歸錯誤,不過,希望沒有一個是嚴重的。
+
+一旦一個穩定的版本發布,它的持續維護工作就被移交給「穩定團隊」,目前由
+Greg Kroah-Hartman領導。穩定團隊將使用5.x.y編號方案不定期地發布穩定版本的
+更新。要合入更新版本,補丁必須(1)修復一個重要的缺陷,且(2)已經合併到
+下一個開發版本主線中。內核通常會在其初始版本後的一個以上的開發周期內收到
+穩定版更新。例如,5.2內核的歷史如下(2019年):
+
+	==============  ===============================
+        七月 7 	        5.2 穩定版發布
+	七月 13	        5.2.1
+	七月 21	        5.2.2
+	七月 26	        5.2.3
+	七月 28	        5.2.4
+	七月 31	        5.2.5
+	...	        ...
+	十月 11         5.2.21
+	==============  ===============================
+
+5.2.21是5.2版本的最終穩定更新。
+
+有些內核被指定爲「長期」內核;它們將得到更長時間的支持。在本文中,當前的長期
+內核及其維護者是:
+
+	======  ================================	================
+	3.16	Ben Hutchings				(長期穩定內核)
+	4.4	Greg Kroah-Hartman & Sasha Levin	(長期穩定內核)
+	4.9	Greg Kroah-Hartman & Sasha Levin
+	4.14	Greg Kroah-Hartman & Sasha Levin
+	4.19	Greg Kroah-Hartman & Sasha Levin
+	5.4	Greg Kroah-Hartman & Sasha Levin
+	======  ================================	================
+
+長期支持內核的選擇純粹是維護人員是否有需求和時間來維護該版本的問題。
+目前還沒有爲即將發布的任何特定版本提供長期支持的已知計劃。
+
+補丁的生命周期
+--------------
+
+補丁不會直接從開發人員的鍵盤進入主線內核。相反,有一個稍微複雜(如果有些非
+正式)的過程,旨在確保對每個補丁進行質量審查,並確保每個補丁實現了一個在主線
+中需要的更改。對於小的修復,這個過程可能會很快完成,,而對於較大或有爭議的
+變更,可能會持續數年。許多開發人員的沮喪來自於對這個過程缺乏理解或者試圖繞過它。
+
+爲了減少這種挫敗,本文將描述補丁如何進入內核。下面的介紹以一種較爲理想化的
+方式描述了這個過程。更詳細的過程將在後面的章節中介紹。
+
+補丁通常要經歷以下階段:
+
+- 設計。這就是補丁的真正需求——以及滿足這些需求的方式——所在。設計工作通常
+  是在不涉及社區的情況下完成的,但是如果可能的話,最好是在公開的情況下完成
+  這項工作;這樣可以節省很多稍後再重新設計的時間。
+
+- 早期評審。補丁被發布到相關的郵件列表中,列表中的開發人員會回復他們可能有
+  的任何評論。如果一切順利的話,這個過程應該會發現補丁的任何主要問題。
+
+- 更廣泛的評審。當補丁接近準備好納入主線時,它應該被相關的子系統維護人員
+  接受——儘管這種接受並不能保證補丁會一直延伸到主線。補丁將出現在維護人員的
+  子系統樹中,並進入 -next 樹(如下所述)。當流程進行時,此步驟將會對補丁
+  進行更廣泛的審查,並發現由於將此補丁與其他人所做的工作合併而導致的任何
+  問題。
+
+- 請注意,大多數維護人員也有日常工作,因此合併補丁可能不是他們的最優先工作。
+  如果您的補丁得到了需要更改的反饋,那麼您應該進行這些更改,或者解釋爲何
+  不應該進行這些更改。如果您的補丁沒有評審意見,也沒有被其相應的子系統或
+  驅動程序維護者接受,那麼您應該堅持不懈地將補丁更新到當前內核使其可被正常
+  應用,並不斷地發送它以供審查和合併。
+
+- 合併到主線。最終,一個成功的補丁將被合併到由LinusTorvalds管理的主線存儲庫
+  中。此時可能會出現更多的評論和/或問題;對開發人員來說應對這些問題並解決
+  出現的任何問題仍很重要。
+
+- 穩定版發布。大量用戶可能受此補丁影響,因此可能再次出現新的問題。
+
+- 長期維護。雖然開發人員在合併代碼後可能會忘記代碼,但這種行爲往往會給開發
+  社區留下不良印象。合併代碼消除了一些維護負擔,因爲其他人將修復由API更改
+  引起的問題。但是,如果代碼要長期保持可用,原始開發人員應該繼續爲代碼負責。
+
+內核開發人員(或他們的僱主)犯的最大錯誤之一是試圖將流程簡化爲一個「合併到
+主線」步驟。這種方法總是會讓所有相關人員感到沮喪。
+
+補丁如何進入內核
+----------------
+
+只有一個人可以將補丁合併到主線內核存儲庫中:LinusTorvalds。但是,在進入
+2.6.38內核的9500多個補丁中,只有112個(大約1.3%)是由Linus自己直接選擇的。
+內核項目已經發展到一個沒有一個開發人員可以在沒有支持的情況下檢查和選擇每個
+補丁的規模。內核開發人員處理這種增長的方式是使用圍繞信任鏈構建的助理系統。
+
+內核代碼庫在邏輯上被分解爲一組子系統:網絡、特定體系結構支持、內存管理、視
+頻設備等。大多數子系統都有一個指定的維護人員,其總體負責該子系統中的代碼。
+這些子系統維護者(鬆散地)是他們所管理的內核部分的「守門員」;他們(通常)
+會接受一個補丁以包含到主線內核中。
+
+子系統維護人員每個人都管理著自己版本的內核原始碼樹,通常(並非總是)使用Git。
+Git等工具(以及Quilt或Mercurial等相關工具)允許維護人員跟蹤補丁列表,包括作者
+信息和其他元數據。在任何給定的時間,維護人員都可以確定他或她的存儲庫中的哪
+些補丁在主線中找不到。
+
+當合併窗口打開時,頂級維護人員將要求Linus從存儲庫中「拉出」他們爲合併選擇
+的補丁。如果Linus同意,補丁流將流向他的存儲庫,成爲主線內核的一部分。
+Linus對拉取中接收到的特定補丁的關注程度各不相同。很明顯,有時他看起來很
+關注。但是一般來說,Linus相信子系統維護人員不會向上游發送壞補丁。
+
+子系統維護人員反過來也可以從其他維護人員那裡獲取補丁。例如,網絡樹是由首先
+在專用於網絡設備驅動程序、無線網絡等的樹中積累的補丁構建的。此存儲鏈可以
+任意長,但很少超過兩個或三個連結。由於鏈中的每個維護者都信任那些管理較低
+級別樹的維護者,所以這個過程稱爲「信任鏈」。
+
+顯然,在這樣的系統中,獲取內核補丁取決於找到正確的維護者。直接向Linus發送
+補丁通常不是正確的方法。
+
+Next 樹
+-------
+
+子系統樹鏈引導補丁流到內核,但它也提出了一個有趣的問題:如果有人想查看爲
+下一個合併窗口準備的所有補丁怎麼辦?開發人員將感興趣的是,還有什麼其他的
+更改有待解決,以了解是否存在需要擔心的衝突;例如,更改核心內核函數原型的
+修補程序將與使用該函數舊形式的任何其他修補程序衝突。審查人員和測試人員希望
+在所有這些變更到達主線內核之前,能夠訪問它們的集成形式的變更。您可以從所有
+相關的子系統樹中提取更改,但這將是一項複雜且容易出錯的工作。
+
+解決方案以-next樹的形式出現,在這裡子系統樹被收集以供測試和審查。這些樹中
+由Andrew Morton維護的較老的一個,被稱爲「-mm」(用於內存管理,創建時爲此)。
+-mm 樹集成了一長串子系統樹中的補丁;它還包含一些旨在幫助調試的補丁。
+
+除此之外,-mm 還包含大量由Andrew直接選擇的補丁。這些補丁可能已經發布在郵件
+列表上,或者它們可能應用於內核中未指定子系統樹的部分。同時,-mm 作爲最後
+手段的子系統樹;如果沒有其他明顯的路徑可以讓補丁進入主線,那麼它很可能最
+終選擇-mm 樹。累積在-mm 中的各種補丁最終將被轉發到適當的子系統樹,或者直接
+發送到Linus。在典型的開發周期中,大約5-10%的補丁通過-mm 進入主線。
+
+當前-mm 補丁可在「mmotm」(-mm of the moment)目錄中找到:
+
+        https://www.ozlabs.org/~akpm/mmotm/
+
+然而,使用MMOTM樹可能會十分令人頭疼;它甚至可能無法編譯。
+
+下一個周期補丁合併的主要樹是linux-next,由Stephen Rothwell 維護。根據設計
+linux-next 是下一個合併窗口關閉後主線的快照。linux-next樹在Linux-kernel 和
+Linux-next 郵件列表中發布,可從以下位置下載:
+
+        https://www.kernel.org/pub/linux/kernel/next/
+
+Linux-next 已經成爲內核開發過程中不可或缺的一部分;在一個給定的合併窗口中合併
+的所有補丁都應該在合併窗口打開之前的一段時間內找到進入Linux-next 的方法。
+
+Staging 樹
+----------
+
+內核原始碼樹包含drivers/staging/目錄,其中有許多驅動程序或文件系統的子目錄
+正在被添加到內核樹中。它們在仍然需要更多的修正的時候可以保留在driver/staging/
+目錄中;一旦完成,就可以將它們移到內核中。這是一種跟蹤不符合Linux內核編碼或
+質量標準的驅動程序的方法,人們可能希望使用它們並跟蹤開發。
+
+Greg Kroah Hartman 目前負責維護staging 樹。仍需要修正的驅動程序將發送給他,
+每個驅動程序在drivers/staging/中都有自己的子目錄。除了驅動程序源文件之外,
+目錄中還應該有一個TODO文件。TODO文件列出了驅動程序需要接受的暫停的工作,
+以及驅動程序的任何補丁都應該抄送的人員列表。當前的規則要求,staging的驅動
+程序必須至少正確編譯。
+
+Staging 是一種讓新的驅動程序進入主線的相對容易的方法,它們會幸運地引起其他
+開發人員的注意,並迅速改進。然而,進入staging並不是故事的結尾;staging中
+沒有看到常規進展的代碼最終將被刪除。經銷商也傾向於相對不願意使用staging驅動
+程序。因此,在成爲一個合適的主線驅動的路上,staging 僅是一個中轉站。
+
+工具
+----
+
+從上面的文本可以看出,內核開發過程在很大程度上依賴於在不同方向上聚集補丁的
+能力。如果沒有適當強大的工具,整個系統將無法在任何地方正常工作。關於如何使用
+這些工具的教程遠遠超出了本文檔的範圍,但還是用一點篇幅介紹一些關鍵點。
+
+到目前爲止,內核社區使用的主要原始碼管理系統是git。Git是在自由軟體社區中開發
+的許多分布式版本控制系統之一。它非常適合內核開發,因爲它在處理大型存儲庫和
+大量補丁時性能非常好。它也以難以學習和使用而著稱,儘管隨著時間的推移它變得
+更好了。對於內核開發人員來說,對Git的某種熟悉幾乎是一種要求;即使他們不將它
+用於自己的工作,他們也需要Git來跟上其他開發人員(以及主線)正在做的事情。
+
+現在幾乎所有的Linux發行版都打包了Git。Git主頁位於:
+
+        https://git-scm.com/
+
+此頁面包含了文檔和教程的連結。
+
+在不使用git的內核開發人員中,最流行的選擇幾乎肯定是Mercurial:
+
+        http://www.seleric.com/mercurial/
+
+Mercurial與Git共享許多特性,但它提供了一個界面,許多人覺得它更易於使用。
+
+另一個值得了解的工具是Quilt:
+
+        https://savannah.nongnu.org/projects/quilt
+
+Quilt 是一個補丁管理系統,而不是原始碼管理系統。它不會隨著時間的推移跟蹤歷史;
+相反,它面向根據不斷發展的代碼庫跟蹤一組特定的更改。一些主要的子系統維護人員
+使用Quilt來管理打算向上游移動的補丁。對於某些樹的管理(例如-mm),quilt 是
+最好的工具。
+
+郵件列表
+--------
+
+大量的Linux內核開發工作是通過郵件列表完成的。如果不加入至少一個某個列表,
+就很難成爲社區中的一個「全功能」成員。但是,Linux郵件列表對開發人員來說也是
+一個潛在的危險,他們可能會被一堆電子郵件淹沒、違反Linux列表上使用的約定,
+或者兩者兼而有之。
+
+大多數內核郵件列表都在vger.kernel.org上運行;主列表位於:
+
+        http://vger.kernel.org/vger-lists.html
+
+不過,也有一些列表託管在別處;其中一些列表位於
+redhat.com/mailman/listinfo。
+
+當然,內核開發的核心郵件列表是linux-kernel。這個列表是一個令人生畏的地方:
+每天的信息量可以達到500條,噪音很高,談話技術性很強,且參與者並不總是表現出
+高度的禮貌。但是,沒有其他地方可以讓內核開發社區作爲一個整體聚集在一起;
+不使用此列表的開發人員將錯過重要信息。
+
+以下一些提示可以幫助在linux-kernel生存:
+
+- 將郵件轉移到單獨的文件夾,而不是主郵箱文件夾。我們必須能夠持續地忽略洪流。
+
+- 不要試圖跟上每一次談話——沒人會這樣。重要的是要篩選感興趣的主題(但請注意
+  長時間的對話可能會偏離原來的主題,儘管未改變電子郵件的主題)和參與的人。
+
+- 不要回復挑事的人。如果有人試圖激起憤怒,請忽略他們。
+
+- 當回復Linux內核電子郵件(或其他列表上的電子郵件)時,請爲所有相關人員保留
+  Cc: 抄送頭。如果沒有確實的理由(如明確的請求),則不應刪除收件人。一定要
+  確保你要回復的人在抄送列表中。這個慣例也使你不必在回覆郵件時明確要求被抄送。
+
+- 在提出問題之前,搜索列表存檔(和整個網絡)。有些開發人員可能會對那些顯然
+  沒有完成家庭作業的人感到不耐煩。
+
+- 避免頂部回復(把你的答案放在你要回復的引文上面的做法)。這會讓你的回答更難
+  理解,印象也很差。
+
+- 在正確的郵件列表發問。linux-kernel 可能是通用的討論場所,但它不是尋找所有
+  子系統開發人員的最佳場所。
+
+最後一點——找到正確的郵件列表——是開發人員常出錯的地方。在linux-kernel上
+提出與網絡相關的問題的人幾乎肯定會收到一個禮貌的建議,轉到netdev列表上提出,
+因爲這是大多數網絡開發人員經常出現的列表。還有其他列表可用於scsi、video4linux、
+ide、filesystem等子系統。查找郵件列表的最佳位置是與內核原始碼一起打包的
+MAINTAINERS文件。
+
+開始內核開發
+------------
+
+關於如何開始內核開發過程的問題很常見——個人和公司皆然。同樣常見的是失誤,這
+使得關係的開始比本應的更困難。
+
+公司通常希望聘請知名的開發人員來啓動開發團隊。實際上,這是一種有效的技術。
+但它也往往是昂貴的,而且對增加有經驗的內核開發人員的數量沒有多大幫助。考
+慮到時間投入,可以讓內部開發人員加快Linux內核的開發速度。利用這段時間可以
+讓僱主擁有一批既了解內核又了解公司的開發人員,還可以幫助培訓其他人。從中期
+來看,這通常是更有利可圖的方法。
+
+可以理解的是,單個開發人員往往對起步感到茫然。從一個大型項目開始可能會很
+嚇人;人們往往想先用一些較小的東西來試試水。由此,一些開發人員開始創建修補
+拼寫錯誤或輕微編碼風格問題的補丁。不幸的是,這樣的補丁會產生一定程度的噪音,
+這會分散整個開發社區的注意力,因此,它們越來越被人不看重。希望向社區介紹
+自己的新開發人員將無法通過這些方式獲得他們期待的反響。
+
+Andrew Morton 爲有抱負的內核開發人員提供了如下建議
+
+::
+
+	所有內核開發者的第一個項目肯定應該是「確保內核在您可以操作的所有
+	機器上始終完美運行」。通常的方法是和其他人一起解決問題(這可能需
+	要堅持!),但就是如此——這是內核開發的一部分。
+
+(http://lwn.net/articles/283982/)
+
+在沒有明顯問題需要解決的情況下,通常建議開發人員查看當前的回歸和開放缺陷
+列表。從來都不缺少需要解決的問題;通過解決這些問題,開發人員將從該過程獲得
+經驗,同時與開發社區的其他成員建立相互尊重。
+
diff --git a/Documentation/translations/zh_TW/process/3.Early-stage.rst b/Documentation/translations/zh_TW/process/3.Early-stage.rst
new file mode 100644
index 000000000000..ab2a45fd65a4
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/3.Early-stage.rst
@@ -0,0 +1,172 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/3.Early-stage.rst <development_early_stage>`
+
+:Translator:
+
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+
+:校譯:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+.. _tw_development_early_stage:
+
+早期規劃
+========
+
+當考慮一個Linux內核開發項目時,很可能會直接跳進去開始編碼。然而,與任何重要
+的項目一樣,許多成功的基礎最好是在第一行代碼編寫之前就打下。在早期計劃和
+溝通中花費一些時間可以在之後節省更多的時間。
+
+搞清問題
+--------
+
+與任何工程項目一樣,成功的內核改善從清晰描述要解決的問題開始。在某些情況
+下,這個步驟很容易:例如當某個特定硬體需要驅動程序時。不過,在其他情況下,
+很容易將實際問題與建議的解決方案混在一起,這可能會導致麻煩。
+
+舉個例子:幾年前,Linux音頻的開發人員尋求一種方法來運行應用程式,而不會因
+系統延遲過大而導致退出或其他問題。他們得到的解決方案是一個連接到Linux安全
+模塊(LSM)框架中的內核模塊;這個模塊可以配置爲允許特定的應用程式訪問實時
+調度程序。這個模塊被實現並發到linux-kernel郵件列表,在那裡它立即遇到了麻煩。
+
+對於音頻開發人員來說,這個安全模塊足以解決他們當前的問題。但是,對於更廣泛的
+內核社區來說,這被視爲對LSM框架的濫用(LSM框架並不打算授予他們原本不具備的
+進程特權),並對系統穩定性造成風險。他們首選的解決方案包括短期的通過rlimit
+機制進行實時調度訪問,以及長期的減少延遲的工作。
+
+然而,音頻社區無法超越他們實施的特定解決方案來看問題;他們不願意接受替代方案。
+由此產生的分歧使這些開發人員對整個內核開發過程感到失望;其中一個開發人員返回
+到audio列表並發布了以下內容:
+
+	有很多非常好的Linux內核開發人員,但他們往往會被一羣傲慢的傻瓜所壓倒。
+	試圖向這些人傳達用戶需求是浪費時間。他們太「聰明」了,根本聽不到少數
+	人的話。
+
+(http://lwn.net/articles/131776/)
+
+實際情況卻是不同的;與特定模塊相比,內核開發人員更關心系統穩定性、長期維護
+以及找到問題的正確解決方案。這個故事的寓意是把重點放在問題上——而不是具體的
+解決方案上——並在開始編寫代碼之前與開發社區討論這個問題。
+
+因此,在考慮一個內核開發項目時,我們應該得到一組簡短問題的答案:
+
+ - 需要解決的問題究竟是什麼?
+
+ - 受此問題影響的用戶有哪些?解決方案應該解決哪些使用案例?
+
+ - 內核現在爲何沒能解決這個問題?
+
+只有這樣,才能開始考慮可能的解決方案。
+
+
+早期討論
+--------
+
+在計劃內核開發項目時,在開始實施之前與社區進行討論是很有意義的。早期溝通可以
+通過多種方式節省時間和麻煩:
+
+ - 很可能問題是由內核以您不理解的方式解決的。Linux內核很大,具有許多不明顯
+   的特性和功能。並不是所有的內核功能都像人們所希望的那樣有文檔記錄,而且很
+   容易遺漏一些東西。某作者發布了一個完整的驅動程序,重複了一個其不
+   知道的現有驅動程序。重新發明現有輪子的代碼不僅浪費,而且不會被接受到主線
+   內核中。
+
+ - 建議的解決方案中可能有一些要素不適合併入主線。在編寫代碼之前,最好先了解
+   這樣的問題。
+
+ - 其他開發人員完全有可能考慮過這個問題;他們可能有更好的解決方案的想法,並且
+   可能願意幫助創建這個解決方案。
+
+在內核開發社區的多年經驗給了我們一個明確的教訓:閉門設計和開發的內核代碼總是
+有一些問題,這些問題只有在代碼發布到社區中時才會被發現。有時這些問題很嚴重,
+需要數月或數年的努力才能使代碼達到內核社區的標準。例如:
+
+ - 設計並實現了單處理器系統的DeviceScape網絡棧。只有使其適合於多處理器系統,
+   才能將其合併到主線中。在代碼中修改鎖等等是一項困難的任務;因此,這段代碼
+   (現在稱爲mac80211)的合併被推遲了一年多。
+
+ - Reiser4文件系統包含許多功能,核心內核開發人員認爲這些功能應該在虛擬文件
+   系統層中實現。它還包括一些特性,這些特性在不將系統暴露於用戶引起的死鎖的
+   情況下是不容易實現的。這些問題過遲發現——以及拒絕處理其中一些問題——已經
+   導致Reiser4置身主線內核之外。
+
+ - Apparmor安全模塊以被認爲不安全和不可靠的方式使用內部虛擬文件系統數據結構。
+   這種擔心(包括其他)使Apparmor多年來無法進入主線。
+
+在這些情況下,與內核開發人員的早期討論,可以避免大量的痛苦和額外的工作。
+
+找誰交流?
+----------
+
+當開發人員決定公開他們的計劃時,下一個問題是:我們從哪裡開始?答案是找到正確
+的郵件列表和正確的維護者。對於郵件列表,最好的方法是在維護者(MAINTAINERS)文件
+中查找要發布的相關位置。如果有一個合適的子系統列表,那麼其上發布通常比在
+linux-kernel上發布更可取;您更有可能接觸到在相關子系統中具有專業知識的開發
+人員,並且環境可能具支持性。
+
+找到維護人員可能會有點困難。同樣,維護者文件是開始的地方。但是,該文件往往不
+是最新的,並且並非所有子系統都在那裡顯示。實際上,維護者文件中列出的人員可能
+不是當前實際擔任該角色的人員。因此,當對聯繫誰有疑問時,一個有用的技巧是使用
+git(尤其是「git-log」)查看感興趣的子系統中當前活動的用戶。看看誰在寫補丁、
+誰會在這些補丁上加上Signed-off-by行簽名(如有)。這些人將是幫助新開發項目的
+最佳人選。
+
+找到合適的維護者有時是非常具有挑戰性的,以至於內核開發人員添加了一個腳本來
+簡化這個過程:
+
+::
+
+	.../scripts/get_maintainer.pl
+
+當給定「-f」選項時,此腳本將返回指定文件或目錄的當前維護者。如果在命令行上
+給出了一個補丁,它將列出可能接收補丁副本的維護人員。有許多選項可以調節
+get_maintainer.pl搜索維護者的嚴格程度;請小心使用更激進的選項,因爲最終結果
+可能會包括對您正在修改的代碼沒有真正興趣的開發人員。
+
+如果所有其他方法都失敗了,那麼與Andrew Morton交流是跟蹤特定代碼段維護人員
+的一種有效方法。
+
+何時郵寄?
+----------
+
+如果可能的話,在早期階段發布你的計劃只會更有幫助。描述正在解決的問題以及已經
+制定的關於如何實施的任何計劃。您可以提供的任何信息都可以幫助開發社區爲項目
+提供有用的輸入。
+
+在這個階段可能發生的一件令人沮喪的事情不是得到反對意見,而是很少或根本沒有
+反饋。令人傷心的事實是:(1)內核開發人員往往很忙;(2)不缺少有宏偉計劃但
+代碼(甚至代碼設想)很少的人去支持他們;(3)沒有人有義務審查或評論別人發表
+的想法。除此之外,高層級的設計常常隱藏著一些問題,這些問題只有在有人真正嘗試
+實現這些設計時才會被發現;因此,內核開發人員寧願看到代碼。
+
+如果發布請求評論(RFC)並沒得到什麼有用的評論,不要以爲這意味著無人對此項目
+有興趣,同時你也不能假設你的想法沒有問題。在這種情況下,最好的做法是繼續進
+行,把你的進展隨時通知社區。
+
+獲得官方認可
+-----------------------
+
+如果您的工作是在公司環境中完成的,就像大多數Linux內核工作一樣;顯然,在您將
+公司的計劃或代碼發布到公共郵件列表之前,必須獲得有適當權利經理的許可。發布
+不確定是否兼容GPL的代碼尤其會帶來問題;公司的管理層和法律人員越早能夠就發布
+內核開發項目達成一致,對參與的每個人都越好。
+
+一些讀者可能會認爲他們的核心工作是爲了支持還沒有正式承認存在的產品。將僱主
+的計劃公布在公共郵件列表上可能不是一個可行的選擇。在這種情況下,有必要考慮
+保密是否真的是必要的;通常不需要把開發計劃關在門內。
+
+的確,有些情況下一家公司在開發過程的早期無法合法地披露其計劃。擁有經驗豐富
+的內核開發人員的公司可能選擇以開環的方式進行開發,前提是他們以後能夠避免
+嚴重的集成問題。對於沒有這種內部專業知識的公司,最好的選擇往往是聘請外部
+開發者根據保密協議審查計劃。Linux基金會運行了一個NDA程序,旨在幫助解決這種
+情況;更多信息參見:
+
+    http://www.linuxfoundation.org/nda/
+
+這種審查通常足以避免以後出現嚴重問題,而無需公開披露項目。
+
diff --git a/Documentation/translations/zh_TW/process/4.Coding.rst b/Documentation/translations/zh_TW/process/4.Coding.rst
new file mode 100644
index 000000000000..ccc3946227a0
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/4.Coding.rst
@@ -0,0 +1,297 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/4.Coding.rst <development_coding>`
+
+:Translator:
+
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+
+:校譯:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+.. _tw_development_coding:
+
+使代碼正確
+======================
+
+雖然一個堅實的、面向社區的設計過程有很多值得說道的,但是任何內核開發項目工作
+的證明都反映在代碼中。它是將由其他開發人員檢查併合並(或不合併)到主線樹中
+的代碼。所以這段代碼的質量決定了項目的最終成功。
+
+本節將檢查編碼過程。我們將從內核開發人員常犯的幾種錯誤開始。然後重點將轉移
+到正確的做法和相關有用的工具上。
+
+陷阱
+----
+
+代碼風格
+********
+
+內核長期以來都有其標準的代碼風格,如
+:ref:`Documentation/translations/zh_TW/process/coding-style.rst <tw_codingstyle>`
+中所述。在多數時候,該文檔中描述的準則至多被認爲是建議性的。因此,內核中存在
+大量不符合代碼風格準則的代碼。這種代碼的存在會給內核開發人員帶來兩方面的危害。
+
+首先,相信內核代碼標準並不重要,也不強制執行。但事實上,如果沒有按照標準
+編寫代碼,那麼新代碼將很難加入到內核中;許多開發人員甚至會在審查代碼之前要求
+對代碼進行重新格式化。一個像內核這麼大的代碼庫需要一些統一格式的代碼,以使
+開發人員能夠快速理解其中的任何部分。所以再也經不起奇怪格式的代碼的折騰了。
+
+內核的代碼風格偶爾會與僱主的強制風格發生衝突。在這種情況下,必須在代碼合併
+之前遵從內核代碼風格。將代碼放入內核意味著以多種方式放棄一定程度的控制權——
+包括控制代碼樣式。
+
+另一個危害是認爲已經在內核中的代碼迫切需要修復代碼樣式。開發者可能會開始編寫
+重新格式化補丁,作爲熟悉開發過程的一種方式,或者作爲將其名字寫入內核變更日誌
+的一種方式,或者兩者兼而有之。但是純代碼風格的修復被開發社區視爲噪音,它們往
+往受到冷遇。因此,最好避免編寫這種類型的補丁。在由於其他原因處理一段代碼的
+同時順帶修復其樣式是很自然的,但是不應該僅爲了更改代碼樣式而更改之。
+
+代碼風格文檔也不應該被視爲絕對不可違反的規則。如果有一個足夠的理由反對這種
+樣式(例如爲了80列限制拆分行會導致可讀性大大降低),那麼就這樣做吧。
+
+注意您還可以使用 ``clang-format`` 工具來幫助您處理這些規則,快速自動重新格式
+化部分代碼,和審閱完整的文件以發現代碼樣式錯誤、拼寫錯誤和可能的改進。它還
+可以方便地排序 ``#includes`` 、對齊變量/宏、重排文本和其他類似任務。有關詳細
+信息,請參閱文檔 :ref:`Documentation/process/clang-format.rst <clangformat>`
+
+抽象層
+******
+
+計算機科學教授教學生以靈活性和信息隱藏的名義廣泛使用抽象層。當然,內核廣泛
+地使用了抽象;任何涉及數百萬行代碼的項目都必須做到這一點以存續下來。但經驗
+表明,過度或過早的抽象可能和過早的優化一樣有害。抽象應用在適當層級,
+不要過度。
+
+簡單點,先考慮一個調用時始終只有一個參數且總爲零的函數。我們可以保留這個參數,
+以在需要使用它時提供的額外靈活性。不過,在那時實現了這個額外參數的代碼很有
+可能以某種從未被注意到的微妙方式被破壞——因爲它從未被使用過。或者當需要額外
+的靈活性時,它並未以符合程式設計師當初期望的方式來實現。內核開發人員通常會提交
+補丁來刪除未使用的參數;一般來說,一開始就不應該添加這些參數。
+
+隱藏硬體訪問的抽象層——通常爲了允許大量的驅動程序兼容多個作業系統——尤其不受
+歡迎。這樣的層使代碼變得模糊,可能會造成性能損失;它們不屬於Linux內核。
+
+另一方面,如果您發現自己從另一個內核子系統複製了大量的代碼,那麼是時候
+了解一下:是否需要將這些代碼中的部分提取到單獨的庫中,或者在更高的層次上
+實現這些功能。在整個內核中複製相同的代碼沒有價值。
+
+#ifdef 和預處理
+***************
+
+C預處理器似乎給一些C程式設計師帶來了強大的誘惑,他們認爲它是一種將大量靈活性加入
+原始碼中的方法。但是預處理器不是C,大量使用它會導致代碼對其他人來說更難閱讀,
+對編譯器來說更難檢查正確性。使用了大量預處理器幾乎總是代碼需要一些
+清理工作的標誌。
+
+使用#ifdef的條件編譯實際上是一個強大的功能,它在內核中使用。但是很少有人希望
+看到代碼被鋪滿#ifdef塊。一般規定,ifdef的使用應儘可能限制在頭文件中。條件
+編譯代碼可以限制函數,如果代碼不存在,這些函數就直接變成空的。然後編譯器將
+悄悄地優化對空函數的調用。使得代碼更加清晰,更容易理解。
+
+C預處理器宏存在許多危險性,包括可能對具有副作用且沒有類型安全的表達式進行多
+重評估。如果您試圖定義宏,請考慮創建一個內聯函數替代。結果相同的代碼,內聯
+函數更容易閱讀,不會多次計算其參數,並且允許編譯器對參數和返回值執行類型檢查。
+
+內聯函數
+********
+
+不過,內聯函數本身也存在風險。程式設計師可以傾心於避免函數調用和用內聯函數填充源
+文件所固有的效率。然而,這些功能實際上會降低性能。因爲它們的代碼在每個調用站
+點都被複製一遍,所以最終會增加編譯內核的大小。此外,這也對處理器的內存緩存
+造成壓力,從而大大降低執行速度。通常內聯函數應該非常小,而且相對較少。畢竟
+函數調用的成本並不高;大量創建內聯函數是過早優化的典型例子。
+
+一般來說,內核程式設計師會自冒風險忽略緩存效果。在數據結構課程開頭中的經典
+時間/空間權衡通常不適用於當代硬體。空間 *就是* 時間,因爲一個大的程序比一個
+更緊湊的程序運行得慢。
+
+較新的編譯器越來越激進地決定一個給定函數是否應該內聯。因此,隨意放置使用
+「inline」關鍵字可能不僅僅是過度的,也可能是無用的。
+
+鎖
+**
+
+2006年5月,「deviceescape」網絡堆棧在前呼後擁下以GPL發布,並被納入主線內核。
+這是一個受歡迎的消息;Linux中對無線網絡的支持充其量被認爲是不合格的,而
+Deviceescape堆棧承諾修復這種情況。然而直到2007年6月(2.6.22),這段代碼才真
+正進入主線。發生了什麼?
+
+這段代碼出現了許多閉門造車的跡象。但一個大麻煩是,它並不是爲多處理器系統而
+設計。在合併這個網絡堆棧(現在稱爲mac80211)之前,需要對其進行一個鎖方案的
+改造。
+
+曾經,Linux內核代碼可以在不考慮多處理器系統所帶來的並發性問題的情況下進行
+開發。然而現在,這個文檔就是在雙核筆記本電腦上寫的。即使在單處理器系統上,
+爲提高響應能力所做的工作也會提高內核內的並發性水平。編寫內核代碼而不考慮鎖
+的日子早已遠去。
+
+可以由多個線程並發訪問的任何資源(數據結構、硬體寄存器等)必須由鎖保護。新
+的代碼應該謹記這一要求;事後修改鎖是一項相當困難的任務。內核開發人員應該花
+時間充分了解可用的鎖原語,以便爲工作選擇正確的工具。對並發性缺乏關注的代碼
+很難進入主線。
+
+回歸
+****
+
+最後一個值得一提的危險是回歸:它可能會引起導致現有用戶的某些東西中斷的改變
+(這也可能會帶來很大的改進)。這種變化被稱爲「回歸」,回歸已經成爲主線內核
+最不受歡迎的問題。除了少數例外情況,如果回歸不能及時修正,會導致回歸的修改
+將被取消。最好首先避免回歸發生。
+
+人們常常爭論,如果回歸帶來的功能遠超過產生的問題,那麼回歸是否爲可接受的。
+如果它破壞了一個系統卻爲十個系統帶來新的功能,爲何不改改態度呢?2007年7月,
+Linus對這個問題給出了最佳答案:
+
+::
+
+	所以我們不會通過引入新問題來修復錯誤。這種方式是靠不住的,沒人知道
+	是否真的有進展。是前進兩步、後退一步,還是前進一步、後退兩步?
+
+(http://lwn.net/articles/243460/)
+
+特別不受歡迎的一種回歸類型是用戶空間ABI的任何變化。一旦接口被導出到用戶空間,
+就必須無限期地支持它。這一事實使得用戶空間接口的創建特別具有挑戰性:因爲它們
+不能以不兼容的方式進行更改,所以必須一次就對。因此,用戶空間接口總是需要大量
+的思考、清晰的文檔和廣泛的審查。
+
+
+代碼檢查工具
+------------
+
+至少目前,編寫無錯誤代碼仍然是我們中很少人能達到的理想狀態。不過,我們希望做
+的是,在代碼進入主線內核之前,儘可能多地捕獲並修復這些錯誤。爲此,內核開發人
+員已經提供了一系列令人印象深刻的工具,可以自動捕獲各種各樣的隱藏問題。計算機
+發現的任何問題都是一個以後不會困擾用戶的問題,因此,只要有可能,就應該使用
+自動化工具。
+
+第一步是注意編譯器產生的警告。當前版本的GCC可以檢測(並警告)大量潛在錯誤。
+通常,這些警告都指向真正的問題。提交以供審閱的代碼一般不會產生任何編譯器警告。
+在消除警告時,注意了解真正的原因,並儘量避免僅「修復」使警告消失而不解決其原因。
+
+請注意,並非所有編譯器警告都默認啓用。使用「make KCFLAGS=-W」構建內核以
+獲得完整集合。
+
+內核提供了幾個配置選項,可以打開調試功能;大多數配置選項位於「kernel hacking」
+子菜單中。對於任何用於開發或測試目的的內核,都應該啓用其中幾個選項。特別是,
+您應該打開:
+
+ - FRAME_WARN 獲取大於給定數量的堆棧幀的警告。
+   這些警告生成的輸出可能比較冗長,但您不必擔心來自內核其他部分的警告。
+
+ - DEBUG_OBJECTS 將添加代碼以跟蹤內核創建的各種對象的生命周期,並在出現問題
+   時發出警告。如果你要添加創建(和導出)關於其自己的複雜對象的子系統,請
+   考慮打開對象調試基礎結構的支持。
+
+ - DEBUG_SLAB 可以發現各種內存分配和使用錯誤;它應該用於大多數開發內核。
+
+ - DEBUG_SPINLOCK, DEBUG_ATOMIC_SLEEP 和 DEBUG_MUTEXES 會發現許多常見的
+   鎖錯誤。
+
+還有很多其他調試選項,其中一些將在下面討論。其中一些有顯著的性能影響,不應
+一直使用。在學習可用選項上花費一些時間,可能會在短期內得到許多回報。
+
+其中一個較重的調試工具是鎖檢查器或「lockdep」。該工具將跟蹤系統中每個鎖
+(spinlock或mutex)的獲取和釋放、獲取鎖的相對順序、當前中斷環境等等。然後,
+它可以確保總是以相同的順序獲取鎖,相同的中斷假設適用於所有情況等等。換句話
+說,lockdep可以找到許多導致系統死鎖的場景。在部署的系統中,這種問題可能會
+很痛苦(對於開發人員和用戶而言);LockDep允許提前以自動方式發現問題。具有
+任何類型的非普通鎖的代碼在提交合併前應在啓用lockdep的情況下運行測試。
+
+作爲一個勤奮的內核程式設計師,毫無疑問,您將檢查任何可能失敗的操作(如內存分配)
+的返回狀態。然而,事實上,最終的故障復現路徑可能完全沒有經過測試。未測試的
+代碼往往會出問題;如果所有這些錯誤處理路徑都被執行了幾次,那麼您可能對代碼
+更有信心。
+
+內核提供了一個可以做到這一點的錯誤注入框架,特別是在涉及內存分配的情況下。
+啓用故障注入後,內存分配的可配置失敗的百分比;這些失敗可以限定在特定的代碼
+範圍內。在啓用了故障注入的情況下運行,程式設計師可以看到當情況惡化時代碼如何響
+應。有關如何使用此工具的詳細信息,請參閱
+Documentation/fault-injection/fault-injection.rst。
+
+「sparse」靜態分析工具可以發現其他類型的錯誤。sparse可以警告程式設計師用戶空間
+和內核空間地址之間的混淆、大端序與小端序的混淆、在需要一組位標誌的地方傳遞
+整數值等等。sparse必須單獨安裝(如果您的分發伺服器沒有將其打包,
+可以在 https://sparse.wiki.kernel.org/index.php/Main_page 找到),
+然後可以通過在make命令中添加「C=1」在代碼上運行它。
+
+「Coccinelle」工具 :ref:`http://coccinelle.lip6.fr/ <devtools_coccinelle>`
+能夠發現各種潛在的編碼問題;它還可以爲這些問題提出修複方案。在
+scripts/coccinelle目錄下已經打包了相當多的內核「語義補丁」;運行
+「make coccicheck」將運行這些語義補丁並報告發現的任何問題。有關詳細信息,請參閱
+:ref:`Documentation/dev-tools/coccinelle.rst <devtools_coccinelle>`
+
+
+其他類型的可移植性錯誤最好通過爲其他體系結構編譯代碼來發現。如果沒有S/390系統
+或Blackfin開發板,您仍然可以執行編譯步驟。可以在以下位置找到一大堆用於x86系統的
+交叉編譯器:
+
+        https://www.kernel.org/pub/tools/crosstool/
+
+花一些時間安裝和使用這些編譯器將有助於避免以後的尷尬。
+
+文檔
+----
+
+文檔通常比內核開發規則更爲例外。即便如此,足夠的文檔將有助於簡化將新代碼合併
+到內核中的過程,使其他開發人員的生活更輕鬆,並對您的用戶有所幫助。在許多情況
+下,添加文檔已基本上是強制性的。
+
+任何補丁的第一個文檔是其關聯的變更日誌。日誌條目應該描述正在解決的問題、解決
+方案的形式、處理補丁的人員、對性能的任何相關影響,以及理解補丁可能需要的任何
+其他內容。確保變更日誌說明了*爲什麼*補丁值得應用;大量開發者未能提供這些信息。
+
+任何添加新用戶空間接口的代碼——包括新的sysfs或/proc文件——都應該包含該接口
+的文檔,該文檔使用戶空間開發人員能夠知道他們在使用什麼。請參閱
+Documentation/ABI/README,了解如何此文檔格式以及需要提供哪些信息。
+
+文檔 :ref:`Documentation/admin-guide/kernel-parameters.rst <kernelparameters>`
+描述了內核的所有引導時間參數。任何添加新參數的補丁都應該向該文檔添加適當的
+條目。
+
+任何新的配置選項都必須附有幫助文本,幫助文本需清楚地解釋這些選項以及用戶可能
+希望何時使用它們。
+
+許多子系統的內部API信息通過專門格式化的注釋進行記錄;這些注釋可以通過
+「kernel-doc」腳本以多種方式提取和格式化。如果您在具有kerneldoc注釋的子系統中
+工作,則應該維護它們,並根據需要爲外部可用的功能添加它們。即使在沒有如此記錄
+的領域中,爲將來添加kerneldoc注釋也沒有壞處;實際上,這對於剛開始開發內核的人
+來說是一個有用的活動。這些注釋的格式以及如何創建kerneldoc模板的一些信息可以在
+:ref:`Documentation/doc-guide/ <doc_guide>` 上找到。
+
+任何閱讀大量現有內核代碼的人都會注意到,注釋的缺失往往是最值得注意的。同時,
+對新代碼的要求比過去更高;合併未注釋的代碼將更加困難。這就是說,人們並不期望
+詳細注釋的代碼。代碼本身應該是自解釋的,注釋闡釋了更微妙的方面。
+
+某些事情應該總是被注釋。使用內存屏障時,應附上一行文字,解釋爲什麼需要設置內存
+屏障。數據結構的鎖規則通常需要在某個地方解釋。一般來說,主要數據結構需要全面
+的文檔。應該指出代碼中分立的位之間不明顯的依賴性。任何可能誘使代碼管理人進行
+錯誤的「清理」的事情都需要一個注釋來說明爲什麼要這樣做。等等。
+
+
+內部API更改
+-----------
+
+內核提供給用戶空間的二進位接口不能被破壞,除非逼不得已。而內核的內部編程接口
+是高度流動的,當需要時可以更改。如果你發現自己不得不處理一個內核API,或者僅
+僅因爲它不滿足你的需求導致無法使用特定的功能,這可能是API需要改變的一個標誌。
+作爲內核開發人員,您有權進行此類更改。
+
+的確可以進行API更改,但更改必須是合理的。因此任何進行內部API更改的補丁都應該
+附帶關於更改內容和必要原因的描述。這種變化也應該拆分成一個單獨的補丁,而不是
+埋在一個更大的補丁中。
+
+另一個要點是,更改內部API的開發人員通常要負責修復內核樹中被更改破壞的任何代碼。
+對於一個廣泛使用的函數,這個責任可以導致成百上千的變化,其中許多變化可能與其他
+開發人員正在做的工作相衝突。不用說,這可能是一項大工程,所以最好確保理由是
+可靠的。請注意,coccinelle工具可以幫助進行廣泛的API更改。
+
+在進行不兼容的API更改時,應儘可能確保編譯器捕獲未更新的代碼。這將幫助您確保找
+到該接口的樹內用處。它還將警告開發人員樹外代碼存在他們需要響應的更改。支持樹外
+代碼不是內核開發人員需要擔心的事情,但是我們也不必使樹外開發人員的生活有不必要
+的困難。
+
diff --git a/Documentation/translations/zh_TW/process/5.Posting.rst b/Documentation/translations/zh_TW/process/5.Posting.rst
new file mode 100644
index 000000000000..5578bca403e6
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/5.Posting.rst
@@ -0,0 +1,251 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/5.Posting.rst <development_posting>`
+
+:Translator:
+
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+
+:校譯:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+.. _tw_development_posting:
+
+發布補丁
+========
+
+您的工作遲早會準備好提交給社區進行審查,並最終包含到主線內核中。毫不稀奇,
+內核開發社區已經發展出一套用於發布補丁的約定和過程;遵循這些約定和過程將使
+參與其中的每個人的生活更加輕鬆。本文檔試圖描述這些約定的部分細節;更多信息
+也可在以下文檔中找到
+:ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`,
+:ref:`Documentation/translations/zh_TW/process/submitting-drivers.rst <tw_submittingdrivers>`
+和 :ref:`Documentation/translations/zh_TW/process/submit-checklist.rst <tw_submitchecklist>`。
+
+何時郵寄
+--------
+
+在補丁完全「準備好」之前,避免發布補丁是一種持續的誘惑。對於簡單的補丁,這
+不是問題。但是如果正在完成的工作很複雜,那麼在工作完成之前從社區獲得反饋就
+可以獲得很多好處。因此,您應該考慮發布正在進行的工作,甚至維護一個可用的Git
+樹,以便感興趣的開發人員可以隨時趕上您的工作。
+
+當發布中有尚未準備好被包含的代碼,最好在發布中說明。還應提及任何有待完成的
+主要工作和任何已知問題。很少有人會願意看那些被認爲是半生不熟的補丁,但是
+那些願意的人會帶著他們的點子來一起幫助你把工作推向正確的方向。
+
+創建補丁之前
+------------
+
+在考慮將補丁發送到開發社區之前,有許多事情應該做。包括:
+
+ - 儘可能地測試代碼。利用內核的調試工具,確保內核使用了所有可能的配置選項組合
+   進行構建,使用交叉編譯器爲不同的體系結構進行構建等。
+
+ - 確保您的代碼符合內核代碼風格指南。
+
+ - 您的更改是否具有性能影響?如果是這樣,您應該運行基準測試來顯示您的變更的
+   影響(或好處);結果的摘要應該包含在補丁中。
+
+ - 確保您有權發布代碼。如果這項工作是爲僱主完成的,僱主對這項工作具有所有權,
+   並且必須同意根據GPL對其進行發布。
+
+一般來說,在發布代碼之前進行一些額外的思考,幾乎總是能在短時間內得到回報。
+
+補丁準備
+--------
+
+準備補丁發布的工作量可能很驚人,但在此嘗試節省時間通常是不明智的,即使在短期
+內亦然。
+
+必須針對內核的特定版本準備補丁。一般來說,補丁應該基於Linus的Git樹中的當前
+主線。當以主線爲基礎時,請從一個衆所周知的發布點開始——如穩定版本或 -rc
+版本發布點——而不是在一個任意的主線分支點。
+
+也可能需要針對-mm、linux-next或子系統樹生成版本,以便於更廣泛的測試和審查。
+根據補丁的區域以及其他地方的情況,針對其他樹建立的補丁可能需要大量的工作來
+解決衝突和處理API更改。
+
+只有最簡單的更改才應格式化爲單個補丁;其他所有更改都應作爲一系列邏輯更改進行。
+分割補丁是一門藝術;一些開發人員花了很長時間來弄清楚如何按照社區期望的方式來
+分割。不過,這些經驗法則也許有幫助:
+
+ - 您發布的補丁系列幾乎肯定不會是開發過程中版本控制系統中的一系列更改。相反,
+   需要對您所做更改的最終形式加以考慮,然後以有意義的方式進行拆分。開發人員對
+   離散的、自包含的更改感興趣,而不是您創造這些更改的原始路徑。
+
+ - 每個邏輯上獨立的變更都應該格式化爲單獨的補丁。這些更改可以是小的(如「向
+   此結構體添加欄位」)或大的(如添加一個重要的新驅動程序),但它們在概念上
+   應該是小的,並且可以在一行內簡述。每個補丁都應該做一個特定的、可以單獨
+   檢查並驗證它所做的事情的更改。
+
+ - 換種方式重申上述準則,也就是說:不要在同一補丁中混合不同類型的更改。如果
+   一個補丁修復了一個關鍵的安全漏洞,又重新排列了一些結構,還重新格式化了代
+   碼,那麼它很有可能會被忽略,從而導致重要的修復丟失。
+
+ - 每個補丁都應該能創建一個可以正確地構建和運行的內核;如果補丁系列在中間被
+   斷開,那麼結果仍應是一個正常工作的內核。部分應用一系列補丁是使用
+   「git bisct」工具查找回歸的一個常見場景;如果結果是一個損壞的內核,那麼將使
+   那些從事追蹤問題的高尚工作的開發人員和用戶的生活更加艱難。
+
+ - 不要過分分割。一位開發人員曾經將一組針對單個文件的編輯分成500個單獨的補丁
+   發布,這並沒有使他成爲內核郵件列表中最受歡迎的人。一個補丁可以相當大,
+   只要它仍然包含一個單一的 *邏輯* 變更。
+
+ - 用一系列補丁添加一個全新的基礎設施,但是該設施在系列中的最後一個補丁啓用
+   整個變更之前不能使用,這看起來很誘人。如果可能的話,應該避免這種誘惑;
+   如果這個系列增加了回歸,那麼二分法將指出最後一個補丁是導致問題的補丁,
+   即使真正的bug在其他地方。只要有可能,添加新代碼的補丁程序應該立即激活該
+   代碼。
+
+創建完美補丁系列的工作可能是一個令人沮喪的過程,在完成「真正的工作」之後需要
+花費大量的時間和思考。但是如果做得好,花費的時間就是值得的。
+
+補丁格式和更改日誌
+------------------
+
+所以現在你有了一系列完美的補丁可以發布,但是這項工作還沒有完成。每個補丁都
+需要被格式化成一條消息,以快速而清晰地將其目的傳達到世界其他地方。爲此,
+每個補丁將由以下部分組成:
+
+ - 可選的「From」行,表明補丁作者。只有當你通過電子郵件發送別人的補丁時,這一行
+   才是必須的,但是爲防止疑問加上它也不會有什麼壞處。
+
+ - 一行描述,說明補丁的作用。對於在沒有其他上下文的情況下看到該消息的讀者來說,
+   該消息應足以確定修補程序的範圍;此行將顯示在「short form(簡短格式)」變更
+   日誌中。此消息通常需要先加上子系統名稱前綴,然後是補丁的目的。例如:
+
+   ::
+
+        gpio: fix build on CONFIG_GPIO_SYSFS=n
+
+ - 一行空白,後接補丁內容的詳細描述。此描述可以是任意需要的長度;它應該說明補丁
+   的作用以及爲什麼它應該應用於內核。
+
+ - 一個或多個標記行,至少有一個由補丁作者的 Signed-off-by 簽名。標記將在下面
+   詳細描述。
+
+上面的項目一起構成補丁的變更日誌。寫一則好的變更日誌是一門至關重要但常常被
+忽視的藝術;值得花一點時間來討論這個問題。當你編寫變更日誌時,你應該記住有
+很多不同的人會讀你的話。其中包括子系統維護人員和審查人員,他們需要決定是否
+應該合併補丁,分銷商和其他維護人員試圖決定是否應該將補丁反向移植到其他內核,
+缺陷搜尋人員想知道補丁是否導致他們正在追查的問題,以及想知道內核如何變化的
+用戶等等。一個好的變更日誌以最直接和最簡潔的方式向所有這些人傳達所需的信息。
+
+在結尾,總結行應該描述變更的影響和動機,以及在一行約束條件下可能發生的變化。
+然後,詳細的描述可以詳述這些主題,並提供任何需要的附加信息。如果補丁修復了
+一個缺陷,請引用引入該缺陷的提交(如果可能,請在引用提交時同時提供其 id 和
+標題)。如果某個問題與特定的日誌或編譯器輸出相關聯,請包含該輸出以幫助其他
+人搜索同一問題的解決方案。如果更改是爲了支持以後補丁中的其他更改,那麼應當
+說明。如果更改了內部API,請詳細說明這些更改以及其他開發人員應該如何響應。
+一般來說,你越把自己放在每個閱讀你變更日誌的人的位置上,變更日誌(和內核
+作爲一個整體)就越好。
+
+不消說,變更日誌是將變更提交到版本控制系統時使用的文本。接下來將是:
+
+ - 補丁本身,採用統一的(「-u」)補丁格式。使用「-p」選項來diff將使函數名與
+   更改相關聯,從而使結果補丁更容易被其他人讀取。
+
+您應該避免在補丁中包括與更改不相關文件(例如,構建過程生成的文件或編輯器
+備份文件)。文檔目錄中的「dontdiff」文件在這方面有幫助;使用「-X」選項將
+其傳遞給diff。
+
+上面提到的標籤(tag)用於描述各種開發人員如何與這個補丁的開發相關聯。
+:ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+文檔中對它們進行了詳細描述;下面是一個簡短的總結。每一行的格式如下:
+
+::
+
+	tag: Full Name <email address>  optional-other-stuff
+
+常用的標籤有:
+
+ - Signed-off-by: 這是一個開發人員的證明,證明他或她有權提交補丁以包含到內核
+   中。這表明同意開發者來源認證協議,其全文見
+   :ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+   如果沒有合適的簽字,則不能合併到主線中。
+
+ - Co-developed-by: 聲明補丁是由多個開發人員共同創建的;當幾個人在一個補丁上
+   工作時,它用於給出共同作者(除了 From: 所給出的作者之外)。由於
+   Co-developed-by: 表示作者身份,所以每個共同開發人,必須緊跟在相關合作作者
+   的Signed-off-by之後。具體內容和示例見以下文件
+   :ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+
+ - Acked-by: 表示另一個開發人員(通常是相關代碼的維護人員)同意補丁適合包含
+   在內核中。
+
+ - Tested-by: 聲明某人已經測試了補丁並確認它可以工作。
+
+ - Reviewed-by: 表示某開發人員已經審查了補丁的正確性;有關詳細信息,請參閱
+   :ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+
+ - Reported-by: 指定報告此補丁修復的問題的用戶;此標記用於表示感謝。
+
+ - Cc:指定某人收到了補丁的副本,並有機會對此發表評論。
+
+在補丁中添加標籤時要小心:只有Cc:才適合在沒有指定人員明確許可的情況下添加。
+
+發送補丁
+--------
+
+在寄出補丁之前,您還需要注意以下幾點:
+
+ - 您確定您的郵件發送程序不會損壞補丁嗎?被郵件客戶端更改空白或修飾了行的補丁
+   無法被另一端接受,並且通常不會進行任何詳細檢查。如果有任何疑問,先把補丁寄
+   給你自己,讓你自己確定它是完好無損的。
+
+   :ref:`Documentation/translations/zh_TW/process/email-clients.rst <tw_email_clients>`
+   提供了一些有用的提示,可以讓特定的郵件客戶端正常發送補丁。
+
+ - 你確定你的補丁沒有荒唐的錯誤嗎?您應該始終通過scripts/checkpatch.pl檢查
+   補丁程序,並解決它提出的問題。請記住,checkpatch.pl,雖然體現了對內核補丁
+   應該是什麼樣的大量思考,但它並不比您聰明。如果修復checkpatch.pl給的問題會
+   使代碼變得更糟,請不要這樣做。
+
+補丁應始終以純文本形式發送。請不要將它們作爲附件發送;這使得審閱者在答覆中更難
+引用補丁的部分。相反,只需將補丁直接放到您的消息中。
+
+寄出補丁時,重要的是將副本發送給任何可能感興趣的人。與其他一些項目不同,內核
+鼓勵人們甚至錯誤地發送過多的副本;不要假定相關人員會看到您在郵件列表中的發布。
+尤其是,副本應發送至:
+
+ - 受影響子系統的維護人員。如前所述,維護人員文件是查找這些人員的首選地方。
+
+ - 其他在同一領域工作的開發人員,尤其是那些現在可能在那裡工作的開發人員。使用
+   git查看還有誰修改了您正在處理的文件,這很有幫助。
+
+ - 如果您對某錯誤報告或功能請求做出響應,也可以抄送原始發送人。
+
+ - 將副本發送到相關郵件列表,或者若無相關列表,則發送到linux-kernel列表。
+
+ - 如果您正在修復一個缺陷,請考慮該修復是否應進入下一個穩定更新。如果是這樣,
+   補丁副本也應發到stable@vger.kernel.org 。另外,在補丁本身的標籤中添加一個
+   「Cc: stable@vger.kernel.org」;這將使穩定版團隊在修復進入主線時收到通知。
+
+當爲一個補丁選擇接收者時,最好清楚你認爲誰最終會接受這個補丁並將其合併。雖然
+可以將補丁直接發給Linus Torvalds並讓他合併,但通常情況下不會這樣做。Linus很
+忙,並且有子系統維護人員負責監視內核的特定部分。通常您會希望維護人員合併您的
+補丁。如果沒有明顯的維護人員,Andrew Morton通常是最後的補丁接收者。
+
+補丁需要好的主題行。補丁主題行的規範格式如下:
+
+::
+
+	[PATCH nn/mm] subsys: one-line description of the patch
+
+其中「nn」是補丁的序號,「mm」是系列中補丁的總數,「subsys」是受影響子系統的
+名稱。當然,一個單獨的補丁可以省略nn/mm。
+
+如果您有一系列重要的補丁,那麼通常發送一個簡介作爲第〇部分。不過,這個約定
+並沒有得到普遍遵循;如果您使用它,請記住簡介中的信息不會進入內核變更日誌。
+因此,請確保補丁本身具有完整的變更日誌信息。
+
+一般來說,多部分補丁的第二部分和後續部分應作爲對第一部分的回覆發送,以便它們
+在接收端都連接在一起。像git和coilt這樣的工具有命令,可以通過適當的線程發送
+一組補丁。但是,如果您有一長串補丁,並正使用git,請不要使用–-chain-reply-to
+選項,以避免創建過深的嵌套。
+
diff --git a/Documentation/translations/zh_TW/process/6.Followthrough.rst b/Documentation/translations/zh_TW/process/6.Followthrough.rst
new file mode 100644
index 000000000000..4af782742db3
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/6.Followthrough.rst
@@ -0,0 +1,156 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/6.Followthrough.rst <development_followthrough>`
+
+:Translator:
+
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+
+:校譯:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+.. _tw_development_followthrough:
+
+跟進
+====
+
+此時,您已經遵循了到目前爲止給出的指導方針,並且,隨著您自己的工程技能的增加,
+已經發布了一系列完美的補丁。即使是經驗豐富的內核開發人員也能犯的最大錯誤之一
+是,認爲他們的工作現在已經完成了。事實上,發布補丁意味著進入流程的下一個階段,
+可能還需要做很多工作。
+
+一個補丁在首次發布時就非常出色、沒有改進的餘地,這是很罕見的。內核開發流程已
+認識到這一事實,因此它非常注重對已發布代碼的改進。作爲代碼的作者,您應該與
+內核社區合作,以確保您的代碼符合內核的質量標準。如果不參與這個過程,很可能會
+無法將補丁合併到主線中。
+
+與審閱者合作
+------------
+
+任何意義上的補丁都會導致其他開發人員在審查代碼時發表大量評論。對於許多開發
+人員來說,與審閱人員合作可能是內核開發過程中最令人生畏的部分。但是如果你
+記住一些事情,生活會變得容易得多:
+
+ - 如果你已經很好地解釋了你的補丁,審閱人員會理解它的價值,以及爲什麼你會
+   費盡心思去寫它。但是這個並不能阻止他們提出一個基本的問題:在五年或十年後
+   維護含有此代碼的內核會怎麼樣?你可能被要求做出的許多改變——從編碼風格的
+   調整到大量的重寫——都來自於對Linux的理解,即從現在起十年後,Linux仍將
+   在開發中。
+
+ - 代碼審查是一項艱苦的工作,這是一項相對吃力不討好的工作;人們記得誰編寫了
+   內核代碼,但對於那些審查它的人來說,幾乎沒有什麼長久的名聲。因此,審閱
+   人員可能會變得暴躁,尤其是當他們看到同樣的錯誤被一遍又一遍地犯下時。如果
+   你得到了一個看起來憤怒、侮辱或完全冒犯你的評論,請抑制以同樣方式回應的衝動。
+   代碼審查是關於代碼的,而不是關於人的,代碼審閱人員不會親自攻擊您。
+
+ - 同樣,代碼審閱人員也不想以犧牲你僱主的利益爲代價來宣傳他們僱主的議程。
+   內核開發人員通常希望今後幾年能在內核上工作,但他們明白他們的僱主可能會改
+   變。他們真的,幾乎毫無例外地,致力於創造他們所能做到的最好的內核;他們並
+   沒有試圖給僱主的競爭對手造成不適。
+
+所有這些歸根結底就是,當審閱者向您發送評論時,您需要注意他們正在進行的技術
+評論。不要讓他們的表達方式或你自己的驕傲阻止此事。當你在一個補丁上得到評論
+時,花點時間去理解評論人想說什麼。如果可能的話,請修覆審閱者要求您修復的內
+容。然後回覆審閱者:謝謝他們,並描述你將如何回答他們的問題。
+
+請注意,您不必同意審閱者建議的每個更改。如果您認爲審閱者誤解了您的代碼,請
+解釋到底發生了什麼。如果您對建議的更改有技術上的異議,請描述它並證明您對該
+問題的解決方案是正確的。如果你的解釋有道理,審閱者會接受的。不過,如果你的
+解釋證明缺乏說服力,尤其是當其他人開始同意審稿人的觀點時,請花些時間重新考慮
+一下。你很容易對自己解決問題的方法視而不見,以至於你沒有意識到某些東西完全
+是錯誤的,或者你甚至沒有解決正確的問題。
+
+Andrew Morton建議,每一個不會導致代碼更改的審閱評論都應該產生一個額外的代碼
+注釋;這可以幫助未來的審閱人員避免第一次出現的問題。
+
+一個致命的錯誤是忽視評論,希望它們會消失。它們不會走的。如果您在沒有對之前
+收到的評論做出響應的情況下重新發布代碼,那麼很可能會發現補丁毫無用處。
+
+說到重新發布代碼:請記住,審閱者不會記住您上次發布的代碼的所有細節。因此,
+提醒審閱人員以前提出的問題以及您如何處理這些問題總是一個好主意;補丁變更
+日誌是提供此類信息的好地方。審閱者不必搜索列表檔案來熟悉上次所說的內容;
+如果您幫助他們直接開始,當他們重新查看您的代碼時,心情會更好。
+
+如果你已經試著做正確的事情,但事情仍然沒有進展呢?大多數技術上的分歧都可以
+通過討論來解決,但有時人們仍需要做出決定。如果你真的認爲這個決定對你不利,
+你可以試著向有更高權力的人上訴。對於本文,更高權力的人是 Andrew Morton 。
+Andrew 在內核開發社區中非常受尊敬;他經常爲似乎被絕望阻塞的事情清障。儘管
+如此,不應輕易就直接找 Andrew ,也不應在所有其他替代方案都被嘗試之前找他。
+當然,記住,他也可能不同意你的意見。
+
+接下來會發生什麼
+----------------
+
+如果一個補丁被認爲適合添加到內核中,並且大多數審查問題得到解決,下一步通常
+是進入子系統維護人員的樹中。工作方式因子系統而異;每個維護人員都有自己的
+工作方式。特別是可能有不止一棵樹——也許一棵樹專門用於計劃下一個合併窗口的
+補丁,另一棵樹用於長期工作。
+
+對於應用到不屬於明顯子系統樹(例如內存管理修補程序)的區域的修補程序,默認樹
+通常上溯到-mm。影響多個子系統的補丁也可以最終進入-mm樹。
+
+包含在子系統樹中可以提高補丁的可見性。現在,使用該樹的其他開發人員將默認獲
+得補丁。子系統樹通常也爲Linux提供支持,使其內容對整個開發社區可見。在這一點
+上,您很可能會從一組新的審閱者那裡得到更多的評論;這些評論需要像上一輪那樣
+得到回應。
+
+在這時也會發生點什麼,這取決於你的補丁的性質,是否與其他人正在做的工作發生
+衝突。在最壞的情況下,嚴重的補丁衝突可能會導致一些工作被擱置,以便剩餘的補丁
+可以成形併合並。另一些時候,衝突解決將涉及到與其他開發人員合作,可能還會
+在樹之間移動一些補丁,以確保所有的應用都是乾淨的。這項工作可能是一件痛苦的
+事情,但也需慶幸現在的幸福:在linux-next樹出現之前,這些衝突通常只在合併窗口
+中出現,必須迅速解決。現在可以在合併窗口打開之前的空閒時間解決這些問題。
+
+有朝一日,如果一切順利,您將登錄並看到您的補丁已經合併到主線內核中。祝賀你!
+然而,一旦慶祝完了(並且您已經將自己添加到維護人員文件中),就一定要記住
+一個重要的小事實:工作仍然沒有完成。併入主線也帶來了它的挑戰。
+
+首先,補丁的可見性再次提高。可能會有以前不知道這個補丁的開發者的新一輪評論。
+忽略它們可能很有誘惑力,因爲您的代碼不再存在任何被合併的問題。但是,要抵制
+這種誘惑,您仍然需要對有問題或建議的開發人員作出響應。
+
+不過,更重要的是:將代碼包含在主線中會將代碼交給更多的一些測試人員。即使您
+爲尚未可用的硬體提供了驅動程序,您也會驚訝於有多少人會將您的代碼構建到內核
+中。當然,如果有測試人員,也可能會有錯誤報告。
+
+最糟糕的錯誤報告是回歸。如果你的補丁導致回歸,你會發現多到讓你不舒服的眼睛盯
+著你;回歸需要儘快修復。如果您不願意或無法修復回歸(其他人都不會爲您修復),
+那麼在穩定期內,您的補丁幾乎肯定會被移除。除了否定您爲使補丁進入主線所做的
+所有工作之外,如果由於未能修復回歸而取消補丁,很可能會使將來的工作更難被合併。
+
+在處理完任何回歸之後,可能還有其他普通缺陷需要處理。穩定期是修復這些錯誤並
+確保代碼在主線內核版本中的首次發布儘可能可靠的最好機會。所以,請回應錯誤
+報告,並儘可能解決問題。這就是穩定期的目的;一旦解決了舊補丁的任何問題,就
+可以開始盡情創建新補丁。
+
+別忘了,還有其他節點也可能會創建缺陷報告:下一個主線穩定版本,當著名的發行
+商選擇包含您補丁的內核版本時等等。繼續響應這些報告是您工作的基本素養。但是
+如果這不能提供足夠的動機,那麼也需要考慮:開發社區會記住那些在合併後對代碼
+失去興趣的開發人員。下一次你發布補丁時,他們會以你以後不會持續維護它爲前提
+來評估它。
+
+其他可能發生的事情
+------------------
+
+某天,當你打開你的郵件客戶端時,看到有人給你寄了一個代碼補丁。畢竟,這是
+讓您的代碼公開存在的好處之一。如果您同意這個補丁,您可以將它轉發給子系統
+維護人員(確保包含一個正確的From:行,這樣屬性是正確的,並添加一個您自己的
+signoff ),或者回復一個 Acked-by: 讓原始發送者向上發送它。
+
+如果您不同意補丁,請禮貌地回復,解釋原因。如果可能的話,告訴作者需要做哪些
+更改才能讓您接受補丁。合併代碼的編寫者和維護者所反對的補丁的確存在著一定的
+阻力,但僅此而已。如果你被認爲不必要的阻礙了好的工作,那麼這些補丁最終會
+繞過你並進入主線。在Linux內核中,沒有人對任何代碼擁有絕對的否決權。可能除
+了Linus。
+
+在非常罕見的情況下,您可能會看到完全不同的東西:另一個開發人員發布了針對您
+的問題的不同解決方案。在這時,兩個補丁之一可能不會被合併,「我的補丁首先
+發布」不被認爲是一個令人信服的技術論據。如果有別人的補丁取代了你的補丁而進
+入了主線,那麼只有一種方法可以回應你:很高興你的問題解決了,請繼續工作吧。
+以這種方式把某人的工作推到一邊可能導致傷心和氣餒,但是社區會記住你的反應,
+即使很久以後他們已經忘記了誰的補丁真正被合併。
+
diff --git a/Documentation/translations/zh_TW/process/7.AdvancedTopics.rst b/Documentation/translations/zh_TW/process/7.AdvancedTopics.rst
new file mode 100644
index 000000000000..3de093d0f170
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/7.AdvancedTopics.rst
@@ -0,0 +1,137 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/7.AdvancedTopics.rst <development_advancedtopics>`
+
+:Translator:
+
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+
+:校譯:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+.. _tw_development_advancedtopics:
+
+高級主題
+========
+
+現在,希望您能夠掌握開發流程的工作方式。然而,還有更多的東西要學!本節將介紹
+一些主題,這些主題對希望成爲Linux內核開發過程常規部分的開發人員有幫助。
+
+使用Git管理補丁
+---------------
+
+內核使用分布式版本控制始於2002年初,當時Linus首次開始使用專有的Bitkeeper應用
+程序。雖然BitKeeper存在爭議,但它所體現的軟體版本管理方法卻肯定不是。分布式
+版本控制可以立即加速內核開發項目。現在有好幾種免費的BitKeeper替代品。
+但無論好壞,內核項目都已經選擇了Git作爲其工具。
+
+使用Git管理補丁可以使開發人員的生活更加輕鬆,尤其是隨著補丁數量的增長。Git也
+有其粗糙的邊角和一定的危險性,它是一個年輕和強大的工具,仍然在其開發人員完善
+中。本文檔不會試圖教會讀者如何使用git;這會是個巨長的文檔。相反,這裡的重點
+將是Git如何特別適合內核開發過程。想要加快用Git速度的開發人員可以在以下網站上
+找到更多信息:
+
+	https://git-scm.com/
+
+	https://www.kernel.org/pub/software/scm/git/docs/user-manual.html
+
+同時網上也能找到各種各樣的教程。
+
+在嘗試使用它生成補丁供他人使用之前,第一要務是閱讀上述網頁,對Git的工作方式
+有一個紮實的了解。使用Git的開發人員應能進行拉取主線存儲庫的副本,查詢修訂
+歷史,提交對樹的更改,使用分支等操作。了解Git用於重寫歷史的工具(如rebase)
+也很有用。Git有自己的術語和概念;Git的新用戶應該了解引用、遠程分支、索引、
+快進合併、推拉、游離頭等。一開始可能有點嚇人,但這些概念不難通過一點學習來
+理解。
+
+使用git生成通過電子郵件提交的補丁是提高速度的一個很好的練習。
+
+當您準備好開始建立Git樹供其他人查看時,無疑需要一個可以從中拉取的伺服器。
+如果您有一個可以訪問網際網路的系統,那麼使用git-daemon設置這樣的伺服器相對
+簡單。同時,免費的公共託管網站(例如github)也開始出現在網絡上。成熟的開發
+人員可以在kernel.org上獲得一個帳戶,但這些帳戶並不容易得到;更多有關信息,
+請參閱 https://kernel.org/faq/ 。
+
+正常的Git工作流程涉及到許多分支的使用。每一條開發線都可以分爲單獨的「主題
+分支」,並獨立維護。Git的分支很容易使用,沒有理由不使用它們。而且,在任何
+情況下,您都不應該在任何您打算讓其他人從中拉取的分支中進行開發。應該小心地
+創建公開可用的分支;當開發分支處於完整狀態並已準備好時(而不是之前)才合併
+開發分支的補丁。
+
+Git提供了一些強大的工具,可以讓您重寫開發歷史。一個不方便的補丁(比如說,
+一個打破二分法的補丁,或者有其他一些明顯的缺陷)可以在適當的位置修復,或者
+完全從歷史中消失。一個補丁系列可以被重寫,就好像它是在今天的主線上寫的一樣,
+即使你已經花了幾個月的時間在寫它。可以透明地將更改從一個分支轉移到另一個
+分支。等等。明智地使用git修改歷史的能力可以幫助創建問題更少的乾淨補丁集。
+
+然而,過度使用這種功能可能會導致其他問題,而不僅僅是對創建完美項目歷史的
+簡單癡迷。重寫歷史將重寫該歷史中包含的更改,將經過測試(希望如此)的內核樹
+變爲未經測試的內核樹。除此之外,如果開發人員沒有共享項目歷史,他們就無法
+輕鬆地協作;如果您重寫了其他開發人員拉入他們存儲庫的歷史,您將使這些開發
+人員的生活更加困難。因此,這裡有一個簡單的經驗法則:被導出到其他地方的歷史
+在此後通常被認爲是不可變的。
+
+因此,一旦將一組更改推送到公開可用的伺服器上,就不應該重寫這些更改。如果您
+嘗試強制進行無法快進合併的更改(即不共享同一歷史記錄的更改),Git將嘗試強制
+執行此規則。這可能覆蓋檢查,有時甚至需要重寫導出的樹。在樹之間移動變更集以
+避免linux-next中的衝突就是一個例子。但這種行爲應該是罕見的。這就是爲什麼
+開發應該在私有分支中進行(必要時可以重寫)並且只有在公共分支處於合理的較新
+狀態時才轉移到公共分支中的原因之一。
+
+當主線(或其他一組變更所基於的樹)前進時,很容易與該樹合併以保持領先地位。
+對於一個私有的分支,rebasing 可能是一個很容易跟上另一棵樹的方法,但是一旦
+一棵樹被導出到外界,rebasing就不可取了。一旦發生這種情況,就必須進行完全
+合併(merge)。合併有時是很有意義的,但是過於頻繁的合併會不必要地擾亂歷史。
+在這種情況下建議的做法是不要頻繁合併,通常只在特定的發布點(如主線-rc發布)
+合併。如果您對特定的更改感到緊張,則可以始終在私有分支中執行測試合併。在
+這種情況下,git「rerere」工具很有用;它能記住合併衝突是如何解決的,這樣您
+就不必重複相同的工作。
+
+關於Git這樣的工具的一個最大的反覆抱怨是:補丁從一個存儲庫到另一個存儲庫的
+大量移動使得很容易陷入錯誤建議的變更中,這些變更避開審查雷達進入主線。當內
+核開發人員看到這種情況發生時,他們往往會感到不高興;在Git樹上放置未審閱或
+主題外的補丁可能會影響您將來讓樹被拉取的能力。引用Linus的話:
+
+::
+
+   你可以給我發補丁,但當我從你那裡拉取一個Git補丁時,我需要知道你清楚
+   自己在做什麼,我需要能夠相信事情而 *無需* 手動檢查每個單獨的更改。
+
+(http://lwn.net/articles/224135/)。
+
+爲了避免這種情況,請確保給定分支中的所有補丁都與相關主題緊密相關;「驅動程序
+修復」分支不應更改核心內存管理代碼。而且,最重要的是,不要使用Git樹來繞過
+審查過程。不時的將樹的摘要發布到相關的列表中,在合適時候請求linux-next中
+包含該樹。
+
+如果其他人開始發送補丁以包含到您的樹中,不要忘記審閱它們。還要確保您維護正確
+的作者信息; git 「am」工具在這方面做得最好,但是如果補丁通過第三方轉發給您,
+您可能需要在補丁中添加「From:」行。
+
+請求拉取時,請務必提供所有相關信息:樹的位置、要拉取的分支以及拉取將導致的
+更改。在這方面 git request-pull 命令非常有用;它將按照其他開發人員所期望的
+格式化請求,並檢查以確保您已記得將這些更改推送到公共伺服器。
+
+審閱補丁
+--------
+
+一些讀者顯然會反對將本節與「高級主題」放在一起,因爲即使是剛開始的內核開發人員
+也應該審閱補丁。當然,沒有比查看其他人發布的代碼更好的方法來學習如何在內核環境
+中編程了。此外,審閱者永遠供不應求;通過審閱代碼,您可以對整個流程做出重大貢獻。
+
+審查代碼可能是一副令人生畏的圖景,特別是對一個新的內核開發人員來說,他們
+可能會對公開詢問代碼感到緊張,而這些代碼是由那些有更多經驗的人發布的。不過,
+即使是最有經驗的開發人員編寫的代碼也可以得到改進。也許對(所有)審閱者最好
+的建議是:把審閱評論當成問題而不是批評。詢問「在這條路徑中如何釋放鎖?」
+總是比說「這裡的鎖是錯誤的」更好。
+
+不同的開發人員將從不同的角度審查代碼。部分人會主要關注代碼風格以及代碼行是
+否有尾隨空格。其他人會主要關注補丁作爲一個整體實現的變更是否對內核有好處。
+同時也有人會檢查是否存在鎖問題、堆棧使用過度、可能的安全問題、在其他地方
+發現的代碼重複、足夠的文檔、對性能的不利影響、用戶空間ABI更改等。所有類型
+的檢查,只要它們能引導更好的代碼進入內核,都是受歡迎和值得的。
+
diff --git a/Documentation/translations/zh_TW/process/8.Conclusion.rst b/Documentation/translations/zh_TW/process/8.Conclusion.rst
new file mode 100644
index 000000000000..7572b17667d9
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/8.Conclusion.rst
@@ -0,0 +1,74 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/8.Conclusion.rst <development_conclusion>`
+:Translator:
+
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+
+:校譯:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+.. _tw_development_conclusion:
+
+更多信息
+========
+
+關於Linux內核開發和相關主題的信息來源很多。首先是在內核原始碼分發中找到的
+文檔目錄。頂級
+:ref:`Documentation/translations/zh_TW/process/howto.rst <tw_process_howto>`
+文件是一個重要的起點;
+:ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+和 :ref:`Documentation/translations/zh_TW/process/submitting-drivers.rst <tw_submittingdrivers>`
+也是所有內核開發人員都應該閱讀的內容。許多內部內核API都是使用kerneldoc機制
+記錄的;「make htmldocs」或「make pdfdocs」可用於以HTML或PDF格式生成這些文檔
+(儘管某些發行版提供的tex版本會遇到內部限制,無法正確處理文檔)。
+
+不同的網站在各個細節層次上討論內核開發。本文作者想謙虛地建議用 https://lwn.net/
+作爲來源;有關許多特定內核主題的信息可以通過以下網址的 LWN 內核索引找到:
+
+  http://lwn.net/kernel/index/
+
+除此之外,內核開發人員的一個寶貴資源是:
+
+  https://kernelnewbies.org/
+
+當然,也不應該忘記 https://kernel.org/ ,這是內核發布信息的最終位置。
+
+關於內核開發有很多書:
+
+  《Linux設備驅動程序》第三版(Jonathan Corbet、Alessandro Rubini和Greg Kroah Hartman)
+  線上版本在 http://lwn.net/kernel/ldd3/
+
+  《Linux內核設計與實現》(Robert Love)
+
+  《深入理解Linux內核》(Daniel Bovet和Marco Cesati)
+
+然而,所有這些書都有一個共同的缺點:它們上架時就往往有些過時,而且已經上架
+一段時間了。不過,在那裡還是可以找到相當多的好信息。
+
+有關git的文檔,請訪問:
+
+  https://www.kernel.org/pub/software/scm/git/docs/
+
+  https://www.kernel.org/pub/software/scm/git/docs/user-manual.html
+
+結論
+====
+
+祝賀所有通過這篇冗長的文檔的人。希望它能夠幫助您理解Linux內核是如何開發的,
+以及您如何參與這個過程。
+
+最後,重要的是參與。任何開源軟體項目都不會超過其貢獻者投入其中的總和。Linux
+內核的發展速度和以前一樣快,因爲它得到了大量開發人員的幫助,他們都在努力使它
+變得更好。內核是一個最成功的例子,說明了當成千上萬的人爲了一個共同的目標一起
+工作時,可以做出什麼。
+
+不過,內核總是可以從更大的開發人員基礎中獲益。總有更多的工作要做。但是同樣
+重要的是,Linux生態系統中的大多數其他參與者可以通過爲內核做出貢獻而受益。使
+代碼進入主線是提高代碼質量、降低維護和分發成本、提高對內核開發方向的影響程度
+等的關鍵。這是一種共贏的局面。啓動你的編輯器,來加入我們吧;你會非常受歡迎的。
+
diff --git a/Documentation/translations/zh_TW/process/code-of-conduct-interpretation.rst b/Documentation/translations/zh_TW/process/code-of-conduct-interpretation.rst
new file mode 100644
index 000000000000..949d831aaf6c
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/code-of-conduct-interpretation.rst
@@ -0,0 +1,112 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/code-of-conduct-interpretation.rst <code_of_conduct_interpretation>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+.. _tw_code_of_conduct_interpretation:
+
+Linux內核貢獻者契約行為準則解釋
+===============================
+
+:ref:`tw_code_of_conduct` 準則是一個通用文檔,旨在爲幾乎所有開源社區提供一套規則。
+每個開源社區都是獨一無二的,Linux內核也不例外。因此,本文描述了Linux內核社區中
+如何解釋它。我們也不希望這種解釋隨著時間的推移是靜態的,並將根據需要進行調整。
+
+與開發軟體的「傳統」方法相比,Linux內核開發工作是一個非常個人化的過程。你的貢獻
+和背後的想法將被仔細審查,往往導致批判和批評。審查將幾乎總是需要改進,材料才
+能包括在內核中。要知道這是因爲所有相關人員都希望看到Linux整體成功的最佳解決方
+案。這個開發過程已經被證明可以創建有史以來最健壯的作業系統內核,我們不想做任何
+事情來導致提交質量和最終結果的下降。
+
+維護者
+------
+
+行為準則多次使用「維護者」一詞。在內核社區中,「維護者」是負責子系統、驅動程序或
+文件的任何人,並在內核原始碼樹的維護者文件中列出。
+
+責任
+----
+
+《行為準則》提到了維護人員的權利和責任,這需要進一步澄清。
+
+首先,最重要的是,有一個合理的期望是由維護人員通過實例來領導。
+
+也就是說,我們的社區是廣闊的,對維護者沒有新的要求,他們單方面處理其他人在
+他們活躍的社區的行爲。這一責任由我們所有人承擔,最終《行為準則》記錄了最終的
+上訴路徑,以防有關行爲問題的問題懸而未決。
+
+維護人員應該願意在出現問題時提供幫助,並在需要時與社區中的其他人合作。如果您
+不確定如何處理出現的情況,請不要害怕聯繫技術諮詢委員會(TAB)或其他維護人員。
+除非您願意,否則不會將其視爲違規報告。如果您不確定是否該聯繫TAB 或任何其他維
+護人員,請聯繫我們的衝突調解人 Mishi Choudhary <mishi@linux.com>。
+
+最後,「善待對方」才是每個人的最終目標。我們知道每個人都是人,有時我們都會失敗,
+但我們所有人的首要目標應該是努力友好地解決問題。執行行為準則將是最後的選擇。
+
+我們的目標是創建一個強大的、技術先進的作業系統,以及所涉及的技術複雜性,這自
+然需要專業知識和決策。
+
+所需的專業知識因貢獻領域而異。它主要由上下文和技術複雜性決定,其次由貢獻者和
+維護者的期望決定。
+
+專家的期望和決策都要經過討論,但在最後,爲了取得進展,必須能夠做出決策。這一
+特權掌握在維護人員和項目領導的手中,預計將善意使用。
+
+因此,設定專業知識期望、作出決定和拒絕不適當的貢獻不被視爲違反行為準則。
+
+雖然維護人員一般都歡迎新來者,但他們幫助(新)貢獻者克服障礙的能力有限,因此
+他們必須確定優先事項。這也不應被視爲違反了行為準則。內核社區意識到這一點,並
+以各種形式提供入門級節目,如 kernelnewbies.org 。
+
+範圍
+----
+
+Linux內核社區主要在一組公共電子郵件列表上進行交互,這些列表分布在由多個不同
+公司或個人控制的多個不同伺服器上。所有這些列表都在內核原始碼樹中的
+MAINTAINERS 文件中定義。發送到這些郵件列表的任何電子郵件都被視爲包含在行爲
+準則中。
+
+使用 kernel.org bugzilla和其他子系統bugzilla 或bug跟蹤工具的開發人員應該遵循
+行為準則的指導原則。Linux內核社區沒有「官方」項目電子郵件地址或「官方」社交媒體
+地址。使用kernel.org電子郵件帳戶執行的任何活動必須遵循爲kernel.org發布的行爲
+準則,就像任何使用公司電子郵件帳戶的個人必須遵循該公司的特定規則一樣。
+
+行為準則並不禁止在郵件列表消息、內核更改日誌消息或代碼注釋中繼續包含名稱、
+電子郵件地址和相關注釋。
+
+其他論壇中的互動包括在適用於上述論壇的任何規則中,通常不包括在行為準則中。
+除了在極端情況下可考慮的例外情況。
+
+提交給內核的貢獻應該使用適當的語言。在行為準則之前已經存在的內容現在不會被
+視爲違反。然而,不適當的語言可以被視爲一個bug;如果任何相關方提交補丁,
+這樣的bug將被更快地修復。當前屬於用戶/內核API的一部分的表達式,或者反映已
+發布標準或規範中使用的術語的表達式,不被視爲bug。
+
+執行
+----
+
+行為準則中列出的地址屬於行為準則委員會。https://kernel.org/code-of-conduct.html
+列出了在任何給定時間接收這些電子郵件的確切成員。成員不能訪問在加入委員會之前
+或離開委員會之後所做的報告。
+
+最初的行為準則委員會由TAB的志願者以及作爲中立第三方的專業調解人組成。委員會
+的首要任務是建立文件化的流程,並將其公開。
+
+如果報告人不希望將整個委員會納入投訴或關切,可直接聯繫委員會的任何成員,包括
+調解人。
+
+行為準則委員會根據流程審查案例(見上文),並根據需要和適當與TAB協商,例如請求
+和接收有關內核社區的信息。
+
+委員會做出的任何決定都將提交到表中,以便在必要時與相關維護人員一起執行。行爲
+準則委員會的決定可以通過三分之二的投票推翻。
+
+每季度,行為準則委員會和標籤將提供一份報告,概述行為準則委員會收到的匿名報告
+及其狀態,以及任何否決決定的細節,包括完整和可識別的投票細節。
+
+我們希望在啓動期之後爲行為準則委員會人員配備建立一個不同的流程。發生此情況時,
+將使用該信息更新此文檔。
+
diff --git a/Documentation/translations/zh_TW/process/code-of-conduct.rst b/Documentation/translations/zh_TW/process/code-of-conduct.rst
new file mode 100644
index 000000000000..716e5843b6e9
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/code-of-conduct.rst
@@ -0,0 +1,76 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/code-of-conduct.rst <code_of_conduct>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+.. _tw_code_of_conduct:
+
+貢獻者契約行為準則
+++++++++++++++++++
+
+我們的誓言
+==========
+
+爲了營造一個開放、友好的環境,我們作爲貢獻者和維護人承諾,讓我們的社區和參
+與者,擁有一個無騷擾的體驗,無論年齡、體型、殘疾、種族、性別特徵、性別認同
+和表達、經驗水平、教育程度、社會狀況,經濟地位、國籍、個人外貌、種族、宗教
+或性身份和取向。
+
+我們的標準
+==========
+
+有助於創造積極環境的行爲包括:
+
+* 使用歡迎和包容的語言
+* 尊重不同的觀點和經驗
+* 優雅地接受建設性的批評
+* 關注什麼對社區最有利
+* 對其他社區成員表示同情
+
+參與者的不可接受行爲包括:
+
+* 使用性意味的語言或意象以及不受歡迎的性注意或者更過分的行爲
+* 煽動、侮辱/貶損評論以及個人或政治攻擊
+* 公開或私下騷擾
+* 未經明確許可,發布他人的私人信息,如物理或電子地址。
+* 在專業場合被合理認爲不適當的其他行爲
+
+我們的責任
+==========
+
+維護人員負責澄清可接受行爲的標準,並應針對任何不可接受行爲採取適當和公平的
+糾正措施。
+
+維護人員有權和責任刪除、編輯或拒絕與本行為準則不一致的評論、承諾、代碼、
+wiki編輯、問題和其他貢獻,或暫時或永久禁止任何貢獻者從事他們認爲不適當、
+威脅、冒犯或有害的其他行爲。
+
+範圍
+====
+
+當個人代表項目或其社區時,本行為準則既適用於項目空間,也適用於公共空間。
+代表一個項目或社區的例子包括使用一個正式的項目電子郵件地址,通過一個正式
+的社交媒體帳戶發布,或者在在線或離線事件中擔任指定的代表。項目維護人員可以
+進一步定義和澄清項目的表示。
+
+執行
+====
+
+如有濫用、騷擾或其他不可接受的行爲,可聯繫行為準則委員會<conduct@kernel.org>。
+所有投訴都將接受審查和調查,並將得到必要和適當的答覆。行為準則委員會有義務
+對事件報告人保密。具體執行政策的進一步細節可單獨公布。
+
+歸屬
+====
+
+本行為準則改編自《貢獻者契約》,版本1.4,可從
+https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 獲取。
+
+解釋
+====
+
+有關Linux內核社區如何解釋此文檔,請參閱 :ref:`tw_code_of_conduct_interpretation`
+
diff --git a/Documentation/translations/zh_TW/process/coding-style.rst b/Documentation/translations/zh_TW/process/coding-style.rst
new file mode 100644
index 000000000000..61e614aad6a7
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/coding-style.rst
@@ -0,0 +1,958 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/coding-style.rst <codingstyle>`
+
+.. _tw_codingstyle:
+
+譯者::
+
+  中文版維護者: 張樂 Zhang Le <r0bertz@gentoo.org>
+  中文版翻譯者: 張樂 Zhang Le <r0bertz@gentoo.org>
+  中文版校譯者: 王聰 Wang Cong <xiyou.wangcong@gmail.com>
+                 wheelz <kernel.zeng@gmail.com>
+                 管旭東 Xudong Guan <xudong.guan@gmail.com>
+                 Li Zefan <lizf@cn.fujitsu.com>
+                 Wang Chen <wangchen@cn.fujitsu.com>
+                 Hu Haowen <src.res@email.cn>
+
+Linux 內核代碼風格
+=========================
+
+這是一個簡短的文檔,描述了 linux 內核的首選代碼風格。代碼風格是因人而異的,
+而且我不願意把自己的觀點強加給任何人,但這就像我去做任何事情都必須遵循的原則
+那樣,我也希望在絕大多數事上保持這種的態度。請 (在寫代碼時) 至少考慮一下這裡
+的代碼風格。
+
+首先,我建議你列印一份 GNU 代碼規範,然後不要讀。燒了它,這是一個具有重大象徵
+性意義的動作。
+
+不管怎樣,現在我們開始:
+
+
+1) 縮進
+--------------
+
+制表符是 8 個字符,所以縮進也是 8 個字符。有些異端運動試圖將縮進變爲 4 (甚至
+2!) 字符深,這幾乎相當於嘗試將圓周率的值定義爲 3。
+
+理由:縮進的全部意義就在於清楚的定義一個控制塊起止於何處。尤其是當你盯著你的
+屏幕連續看了 20 小時之後,你將會發現大一點的縮進會使你更容易分辨縮進。
+
+現在,有些人會抱怨 8 個字符的縮進會使代碼向右邊移動的太遠,在 80 個字符的終端
+屏幕上就很難讀這樣的代碼。這個問題的答案是,如果你需要 3 級以上的縮進,不管用
+何種方式你的代碼已經有問題了,應該修正你的程序。
+
+簡而言之,8 個字符的縮進可以讓代碼更容易閱讀,還有一個好處是當你的函數嵌套太
+深的時候可以給你警告。留心這個警告。
+
+在 switch 語句中消除多級縮進的首選的方式是讓 ``switch`` 和從屬於它的 ``case``
+標籤對齊於同一列,而不要 ``兩次縮進`` ``case`` 標籤。比如:
+
+.. code-block:: c
+
+	switch (suffix) {
+	case 'G':
+	case 'g':
+		mem <<= 30;
+		break;
+	case 'M':
+	case 'm':
+		mem <<= 20;
+		break;
+	case 'K':
+	case 'k':
+		mem <<= 10;
+		fallthrough;
+	default:
+		break;
+	}
+
+不要把多個語句放在一行里,除非你有什麼東西要隱藏:
+
+.. code-block:: c
+
+	if (condition) do_this;
+	  do_something_everytime;
+
+也不要在一行里放多個賦值語句。內核代碼風格超級簡單。就是避免可能導致別人誤讀
+的表達式。
+
+除了注釋、文檔和 Kconfig 之外,不要使用空格來縮進,前面的例子是例外,是有意爲
+之。
+
+選用一個好的編輯器,不要在行尾留空格。
+
+
+2) 把長的行和字符串打散
+------------------------------
+
+代碼風格的意義就在於使用平常使用的工具來維持代碼的可讀性和可維護性。
+
+每一行的長度的限制是 80 列,我們強烈建議您遵守這個慣例。
+
+長於 80 列的語句要打散成有意義的片段。除非超過 80 列能顯著增加可讀性,並且不
+會隱藏信息。子片段要明顯短於母片段,並明顯靠右。這同樣適用於有著很長參數列表
+的函數頭。然而,絕對不要打散對用戶可見的字符串,例如 printk 信息,因爲這樣就
+很難對它們 grep。
+
+
+3) 大括號和空格的放置
+------------------------------
+
+C 語言風格中另外一個常見問題是大括號的放置。和縮進大小不同,選擇或棄用某种放
+置策略並沒有多少技術上的原因,不過首選的方式,就像 Kernighan 和 Ritchie 展示
+給我們的,是把起始大括號放在行尾,而把結束大括號放在行首,所以:
+
+.. code-block:: c
+
+	if (x is true) {
+		we do y
+	}
+
+這適用於所有的非函數語句塊 (if, switch, for, while, do)。比如:
+
+.. code-block:: c
+
+	switch (action) {
+	case KOBJ_ADD:
+		return "add";
+	case KOBJ_REMOVE:
+		return "remove";
+	case KOBJ_CHANGE:
+		return "change";
+	default:
+		return NULL;
+	}
+
+不過,有一個例外,那就是函數:函數的起始大括號放置於下一行的開頭,所以:
+
+.. code-block:: c
+
+	int function(int x)
+	{
+		body of function
+	}
+
+全世界的異端可能會抱怨這個不一致性是... 呃... 不一致的,不過所有思維健全的人
+都知道 (a) K&R 是 **正確的** 並且 (b) K&R 是正確的。此外,不管怎樣函數都是特
+殊的 (C 函數是不能嵌套的)。
+
+注意結束大括號獨自占據一行,除非它後面跟著同一個語句的剩餘部分,也就是 do 語
+句中的 "while" 或者 if 語句中的 "else",像這樣:
+
+.. code-block:: c
+
+	do {
+		body of do-loop
+	} while (condition);
+
+和
+
+.. code-block:: c
+
+	if (x == y) {
+		..
+	} else if (x > y) {
+		...
+	} else {
+		....
+	}
+
+理由:K&R。
+
+也請注意這種大括號的放置方式也能使空 (或者差不多空的) 行的數量最小化,同時不
+失可讀性。因此,由於你的屏幕上的新行是不可再生資源 (想想 25 行的終端屏幕),你
+將會有更多的空行來放置注釋。
+
+當只有一個單獨的語句的時候,不用加不必要的大括號。
+
+.. code-block:: c
+
+	if (condition)
+		action();
+
+和
+
+.. code-block:: c
+
+	if (condition)
+		do_this();
+	else
+		do_that();
+
+這並不適用於只有一個條件分支是單語句的情況;這時所有分支都要使用大括號:
+
+.. code-block:: c
+
+	if (condition) {
+		do_this();
+		do_that();
+	} else {
+		otherwise();
+	}
+
+3.1) 空格
+********************
+
+Linux 內核的空格使用方式 (主要) 取決於它是用於函數還是關鍵字。(大多數) 關鍵字
+後要加一個空格。值得注意的例外是 sizeof, typeof, alignof 和 __attribute__,這
+些關鍵字某些程度上看起來更像函數 (它們在 Linux 里也常常伴隨小括號而使用,儘管
+在 C 里這樣的小括號不是必需的,就像 ``struct fileinfo info;`` 聲明過後的
+``sizeof info``)。
+
+所以在這些關鍵字之後放一個空格::
+
+	if, switch, case, for, do, while
+
+但是不要在 sizeof, typeof, alignof 或者 __attribute__ 這些關鍵字之後放空格。
+例如,
+
+.. code-block:: c
+
+	s = sizeof(struct file);
+
+不要在小括號里的表達式兩側加空格。這是一個 **反例** :
+
+.. code-block:: c
+
+	s = sizeof( struct file );
+
+當聲明指針類型或者返回指針類型的函數時, ``*`` 的首選使用方式是使之靠近變量名
+或者函數名,而不是靠近類型名。例子:
+
+.. code-block:: c
+
+	char *linux_banner;
+	unsigned long long memparse(char *ptr, char **retptr);
+	char *match_strdup(substring_t *s);
+
+在大多數二元和三元操作符兩側使用一個空格,例如下面所有這些操作符::
+
+	=  +  -  <  >  *  /  %  |  &  ^  <=  >=  ==  !=  ?  :
+
+但是一元操作符後不要加空格::
+
+	&  *  +  -  ~  !  sizeof  typeof  alignof  __attribute__  defined
+
+後綴自加和自減一元操作符前不加空格::
+
+	++  --
+
+前綴自加和自減一元操作符後不加空格::
+
+	++  --
+
+``.`` 和 ``->`` 結構體成員操作符前後不加空格。
+
+不要在行尾留空白。有些可以自動縮進的編輯器會在新行的行首加入適量的空白,然後
+你就可以直接在那一行輸入代碼。不過假如你最後沒有在那一行輸入代碼,有些編輯器
+就不會移除已經加入的空白,就像你故意留下一個只有空白的行。包含行尾空白的行就
+這樣產生了。
+
+當 git 發現補丁包含了行尾空白的時候會警告你,並且可以應你的要求去掉行尾空白;
+不過如果你是正在打一系列補丁,這樣做會導致後面的補丁失敗,因爲你改變了補丁的
+上下文。
+
+
+4) 命名
+------------------------------
+
+C 是一個簡樸的語言,你的命名也應該這樣。和 Modula-2 和 Pascal 程式設計師不同,
+C 程式設計師不使用類似 ThisVariableIsATemporaryCounter 這樣華麗的名字。C 程式設計師會
+稱那個變量爲 ``tmp`` ,這樣寫起來會更容易,而且至少不會令其難於理解。
+
+不過,雖然混用大小寫的名字是不提倡使用的,但是全局變量還是需要一個具描述性的
+名字。稱一個全局函數爲 ``foo`` 是一個難以饒恕的錯誤。
+
+全局變量 (只有當你 **真正** 需要它們的時候再用它) 需要有一個具描述性的名字,就
+像全局函數。如果你有一個可以計算活動用戶數量的函數,你應該叫它
+``count_active_users()`` 或者類似的名字,你不應該叫它 ``cntuser()`` 。
+
+在函數名中包含函數類型 (所謂的匈牙利命名法) 是腦子出了問題——編譯器知道那些類
+型而且能夠檢查那些類型,這樣做只能把程式設計師弄糊塗了。難怪微軟總是製造出有問題
+的程序。
+
+本地變量名應該簡短,而且能夠表達相關的含義。如果你有一些隨機的整數型的循環計
+數器,它應該被稱爲 ``i`` 。叫它 ``loop_counter`` 並無益處,如果它沒有被誤解的
+可能的話。類似的, ``tmp`` 可以用來稱呼任意類型的臨時變量。
+
+如果你怕混淆了你的本地變量名,你就遇到另一個問題了,叫做函數增長荷爾蒙失衡綜
+合症。請看第六章 (函數)。
+
+
+5) Typedef
+-----------
+
+不要使用類似 ``vps_t`` 之類的東西。
+
+對結構體和指針使用 typedef 是一個 **錯誤** 。當你在代碼里看到:
+
+.. code-block:: c
+
+	vps_t a;
+
+這代表什麼意思呢?
+
+相反,如果是這樣
+
+.. code-block:: c
+
+	struct virtual_container *a;
+
+你就知道 ``a`` 是什麼了。
+
+很多人認爲 typedef ``能提高可讀性`` 。實際不是這樣的。它們只在下列情況下有用:
+
+ (a) 完全不透明的對象 (這種情況下要主動使用 typedef 來 **隱藏** 這個對象實際上
+     是什麼)。
+
+     例如: ``pte_t`` 等不透明對象,你只能用合適的訪問函數來訪問它們。
+
+     .. note::
+
+       不透明性和 "訪問函數" 本身是不好的。我們使用 pte_t 等類型的原因在於真
+       的是完全沒有任何共用的可訪問信息。
+
+ (b) 清楚的整數類型,如此,這層抽象就可以 **幫助** 消除到底是 ``int`` 還是
+     ``long`` 的混淆。
+
+     u8/u16/u32 是完全沒有問題的 typedef,不過它們更符合類別 (d) 而不是這裡。
+
+     .. note::
+
+       要這樣做,必須事出有因。如果某個變量是 ``unsigned long`` ,那麼沒有必要
+
+	typedef unsigned long myflags_t;
+
+     不過如果有一個明確的原因,比如它在某種情況下可能會是一個 ``unsigned int``
+     而在其他情況下可能爲 ``unsigned long`` ,那麼就不要猶豫,請務必使用
+     typedef。
+
+ (c) 當你使用 sparse 按字面的創建一個 **新** 類型來做類型檢查的時候。
+
+ (d) 和標準 C99 類型相同的類型,在某些例外的情況下。
+
+     雖然讓眼睛和腦筋來適應新的標準類型比如 ``uint32_t`` 不需要花很多時間,可
+     是有些人仍然拒絕使用它們。
+
+     因此,Linux 特有的等同於標準類型的 ``u8/u16/u32/u64`` 類型和它們的有符號
+     類型是被允許的——儘管在你自己的新代碼中,它們不是強制要求要使用的。
+
+     當編輯已經使用了某個類型集的已有代碼時,你應該遵循那些代碼中已經做出的選
+     擇。
+
+ (e) 可以在用戶空間安全使用的類型。
+
+     在某些用戶空間可見的結構體裡,我們不能要求 C99 類型而且不能用上面提到的
+     ``u32`` 類型。因此,我們在與用戶空間共享的所有結構體中使用 __u32 和類似
+     的類型。
+
+可能還有其他的情況,不過基本的規則是 **永遠不要** 使用 typedef,除非你可以明
+確的應用上述某個規則中的一個。
+
+總的來說,如果一個指針或者一個結構體裡的元素可以合理的被直接訪問到,那麼它們
+就不應該是一個 typedef。
+
+
+6) 函數
+------------------------------
+
+函數應該簡短而漂亮,並且只完成一件事情。函數應該可以一屏或者兩屏顯示完 (我們
+都知道 ISO/ANSI 屏幕大小是 80x24),只做一件事情,而且把它做好。
+
+一個函數的最大長度是和該函數的複雜度和縮進級數成反比的。所以,如果你有一個理
+論上很簡單的只有一個很長 (但是簡單) 的 case 語句的函數,而且你需要在每個 case
+里做很多很小的事情,這樣的函數儘管很長,但也是可以的。
+
+不過,如果你有一個複雜的函數,而且你懷疑一個天分不是很高的高中一年級學生可能
+甚至搞不清楚這個函數的目的,你應該嚴格遵守前面提到的長度限制。使用輔助函數,
+並爲之取個具描述性的名字 (如果你覺得它們的性能很重要的話,可以讓編譯器內聯它
+們,這樣的效果往往會比你寫一個複雜函數的效果要好。)
+
+函數的另外一個衡量標準是本地變量的數量。此數量不應超過 5-10 個,否則你的函數
+就有問題了。重新考慮一下你的函數,把它分拆成更小的函數。人的大腦一般可以輕鬆
+的同時跟蹤 7 個不同的事物,如果再增多的話,就會糊塗了。即便你聰穎過人,你也可
+能會記不清你 2 個星期前做過的事情。
+
+在源文件里,使用空行隔開不同的函數。如果該函數需要被導出,它的 **EXPORT** 宏
+應該緊貼在它的結束大括號之下。比如:
+
+.. code-block:: c
+
+	int system_is_up(void)
+	{
+		return system_state == SYSTEM_RUNNING;
+	}
+	EXPORT_SYMBOL(system_is_up);
+
+在函數原型中,包含函數名和它們的數據類型。雖然 C 語言裡沒有這樣的要求,在
+Linux 里這是提倡的做法,因爲這樣可以很簡單的給讀者提供更多的有價值的信息。
+
+
+7) 集中的函數退出途徑
+------------------------------
+
+雖然被某些人聲稱已經過時,但是 goto 語句的等價物還是經常被編譯器所使用,具體
+形式是無條件跳轉指令。
+
+當一個函數從多個位置退出,並且需要做一些類似清理的常見操作時,goto 語句就很方
+便了。如果並不需要清理操作,那麼直接 return 即可。
+
+選擇一個能夠說明 goto 行爲或它爲何存在的標籤名。如果 goto 要釋放 ``buffer``,
+一個不錯的名字可以是 ``out_free_buffer:`` 。別去使用像 ``err1:`` 和 ``err2:``
+這樣的GW_BASIC 名稱,因爲一旦你添加或刪除了 (函數的) 退出路徑,你就必須對它們
+重新編號,這樣會難以去檢驗正確性。
+
+使用 goto 的理由是:
+
+- 無條件語句容易理解和跟蹤
+- 嵌套程度減小
+- 可以避免由於修改時忘記更新個別的退出點而導致錯誤
+- 讓編譯器省去刪除冗餘代碼的工作 ;)
+
+.. code-block:: c
+
+	int fun(int a)
+	{
+		int result = 0;
+		char *buffer;
+
+		buffer = kmalloc(SIZE, GFP_KERNEL);
+		if (!buffer)
+			return -ENOMEM;
+
+		if (condition1) {
+			while (loop1) {
+				...
+			}
+			result = 1;
+			goto out_free_buffer;
+		}
+		...
+	out_free_buffer:
+		kfree(buffer);
+		return result;
+	}
+
+一個需要注意的常見錯誤是 ``一個 err 錯誤`` ,就像這樣:
+
+.. code-block:: c
+
+	err:
+		kfree(foo->bar);
+		kfree(foo);
+		return ret;
+
+這段代碼的錯誤是,在某些退出路徑上 ``foo`` 是 NULL。通常情況下,通過把它分離
+成兩個錯誤標籤 ``err_free_bar:`` 和 ``err_free_foo:`` 來修復這個錯誤:
+
+.. code-block:: c
+
+	 err_free_bar:
+		kfree(foo->bar);
+	 err_free_foo:
+		kfree(foo);
+		return ret;
+
+理想情況下,你應該模擬錯誤來測試所有退出路徑。
+
+
+8) 注釋
+------------------------------
+
+注釋是好的,不過有過度注釋的危險。永遠不要在注釋里解釋你的代碼是如何運作的:
+更好的做法是讓別人一看你的代碼就可以明白,解釋寫的很差的代碼是浪費時間。
+
+一般的,你想要你的注釋告訴別人你的代碼做了什麼,而不是怎麼做的。也請你不要把
+注釋放在一個函數體內部:如果函數複雜到你需要獨立的注釋其中的一部分,你很可能
+需要回到第六章看一看。你可以做一些小注釋來註明或警告某些很聰明 (或者槽糕) 的
+做法,但不要加太多。你應該做的,是把注釋放在函數的頭部,告訴人們它做了什麼,
+也可以加上它做這些事情的原因。
+
+當注釋內核 API 函數時,請使用 kernel-doc 格式。請看
+Documentation/doc-guide/ 和 scripts/kernel-doc 以獲得詳細信息。
+
+長 (多行) 注釋的首選風格是:
+
+.. code-block:: c
+
+	/*
+	 * This is the preferred style for multi-line
+	 * comments in the Linux kernel source code.
+	 * Please use it consistently.
+	 *
+	 * Description:  A column of asterisks on the left side,
+	 * with beginning and ending almost-blank lines.
+	 */
+
+對於在 net/ 和 drivers/net/ 的文件,首選的長 (多行) 注釋風格有些不同。
+
+.. code-block:: c
+
+	/* The preferred comment style for files in net/ and drivers/net
+	 * looks like this.
+	 *
+	 * It is nearly the same as the generally preferred comment style,
+	 * but there is no initial almost-blank line.
+	 */
+
+注釋數據也是很重要的,不管是基本類型還是衍生類型。爲了方便實現這一點,每一行
+應只聲明一個數據 (不要使用逗號來一次聲明多個數據)。這樣你就有空間來爲每個數據
+寫一段小注釋來解釋它們的用途了。
+
+
+9) 你已經把事情弄糟了
+------------------------------
+
+這沒什麼,我們都是這樣。可能你的使用了很長時間 Unix 的朋友已經告訴你
+``GNU emacs`` 能自動幫你格式化 C 原始碼,而且你也注意到了,確實是這樣,不過它
+所使用的默認值和我們想要的相去甚遠 (實際上,甚至比隨機打的還要差——無數個猴子
+在 GNU emacs 里打字永遠不會創造出一個好程序) (譯註:Infinite Monkey Theorem)
+
+所以你要麼放棄 GNU emacs,要麼改變它讓它使用更合理的設定。要採用後一個方案,
+你可以把下面這段粘貼到你的 .emacs 文件里。
+
+.. code-block:: none
+
+  (defun c-lineup-arglist-tabs-only (ignored)
+    "Line up argument lists by tabs, not spaces"
+    (let* ((anchor (c-langelem-pos c-syntactic-element))
+           (column (c-langelem-2nd-pos c-syntactic-element))
+           (offset (- (1+ column) anchor))
+           (steps (floor offset c-basic-offset)))
+      (* (max steps 1)
+         c-basic-offset)))
+
+  (dir-locals-set-class-variables
+   'linux-kernel
+   '((c-mode . (
+          (c-basic-offset . 8)
+          (c-label-minimum-indentation . 0)
+          (c-offsets-alist . (
+                  (arglist-close         . c-lineup-arglist-tabs-only)
+                  (arglist-cont-nonempty .
+		      (c-lineup-gcc-asm-reg c-lineup-arglist-tabs-only))
+                  (arglist-intro         . +)
+                  (brace-list-intro      . +)
+                  (c                     . c-lineup-C-comments)
+                  (case-label            . 0)
+                  (comment-intro         . c-lineup-comment)
+                  (cpp-define-intro      . +)
+                  (cpp-macro             . -1000)
+                  (cpp-macro-cont        . +)
+                  (defun-block-intro     . +)
+                  (else-clause           . 0)
+                  (func-decl-cont        . +)
+                  (inclass               . +)
+                  (inher-cont            . c-lineup-multi-inher)
+                  (knr-argdecl-intro     . 0)
+                  (label                 . -1000)
+                  (statement             . 0)
+                  (statement-block-intro . +)
+                  (statement-case-intro  . +)
+                  (statement-cont        . +)
+                  (substatement          . +)
+                  ))
+          (indent-tabs-mode . t)
+          (show-trailing-whitespace . t)
+          ))))
+
+  (dir-locals-set-directory-class
+   (expand-file-name "~/src/linux-trees")
+   'linux-kernel)
+
+這會讓 emacs 在 ``~/src/linux-trees`` 下的 C 源文件獲得更好的內核代碼風格。
+
+不過就算你嘗試讓 emacs 正確的格式化代碼失敗了,也並不意味著你失去了一切:還可
+以用 ``indent`` 。
+
+不過,GNU indent 也有和 GNU emacs 一樣有問題的設定,所以你需要給它一些命令選
+項。不過,這還不算太糟糕,因爲就算是 GNU indent 的作者也認同 K&R 的權威性
+(GNU 的人並不是壞人,他們只是在這個問題上被嚴重的誤導了),所以你只要給 indent
+指定選項 ``-kr -i8`` (代表 ``K&R,8 字符縮進``),或使用 ``scripts/Lindent``
+這樣就可以以最時髦的方式縮進原始碼。
+
+``indent`` 有很多選項,特別是重新格式化注釋的時候,你可能需要看一下它的手冊。
+不過記住: ``indent`` 不能修正壞的編程習慣。
+
+
+10) Kconfig 配置文件
+------------------------------
+
+對於遍布源碼樹的所有 Kconfig* 配置文件來說,它們縮進方式有所不同。緊挨著
+``config`` 定義的行,用一個制表符縮進,然而 help 信息的縮進則額外增加 2 個空
+格。舉個例子::
+
+  config AUDIT
+	bool "Auditing support"
+	depends on NET
+	help
+	  Enable auditing infrastructure that can be used with another
+	  kernel subsystem, such as SELinux (which requires this for
+	  logging of avc messages output).  Does not do system-call
+	  auditing without CONFIG_AUDITSYSCALL.
+
+而那些危險的功能 (比如某些文件系統的寫支持) 應該在它們的提示字符串里顯著的聲
+明這一點::
+
+  config ADFS_FS_RW
+	bool "ADFS write support (DANGEROUS)"
+	depends on ADFS_FS
+	...
+
+要查看配置文件的完整文檔,請看 Documentation/kbuild/kconfig-language.rst。
+
+
+11) 數據結構
+------------------------------
+
+如果一個數據結構,在創建和銷毀它的單線執行環境之外可見,那麼它必須要有一個引
+用計數器。內核里沒有垃圾收集 (並且內核之外的垃圾收集慢且效率低下),這意味著你
+絕對需要記錄你對這種數據結構的使用情況。
+
+引用計數意味著你能夠避免上鎖,並且允許多個用戶並行訪問這個數據結構——而不需要
+擔心這個數據結構僅僅因爲暫時不被使用就消失了,那些用戶可能不過是沉睡了一陣或
+者做了一些其他事情而已。
+
+注意上鎖 **不能** 取代引用計數。上鎖是爲了保持數據結構的一致性,而引用計數是一
+個內存管理技巧。通常二者都需要,不要把兩個搞混了。
+
+很多數據結構實際上有 2 級引用計數,它們通常有不同 ``類`` 的用戶。子類計數器統
+計子類用戶的數量,每當子類計數器減至零時,全局計數器減一。
+
+這種 ``多級引用計數`` 的例子可以在內存管理 (``struct mm_struct``: mm_users 和
+mm_count),和文件系統 (``struct super_block``: s_count 和 s_active) 中找到。
+
+記住:如果另一個執行線索可以找到你的數據結構,但這個數據結構沒有引用計數器,
+這裡幾乎肯定是一個 bug。
+
+
+12) 宏,枚舉和RTL
+------------------------------
+
+用於定義常量的宏的名字及枚舉里的標籤需要大寫。
+
+.. code-block:: c
+
+	#define CONSTANT 0x12345
+
+在定義幾個相關的常量時,最好用枚舉。
+
+宏的名字請用大寫字母,不過形如函數的宏的名字可以用小寫字母。
+
+一般的,如果能寫成內聯函數就不要寫成像函數的宏。
+
+含有多個語句的宏應該被包含在一個 do-while 代碼塊里:
+
+.. code-block:: c
+
+	#define macrofun(a, b, c)			\
+		do {					\
+			if (a == 5)			\
+				do_this(b, c);		\
+		} while (0)
+
+使用宏的時候應避免的事情:
+
+1) 影響控制流程的宏:
+
+.. code-block:: c
+
+	#define FOO(x)					\
+		do {					\
+			if (blah(x) < 0)		\
+				return -EBUGGERED;	\
+		} while (0)
+
+**非常** 不好。它看起來像一個函數,不過卻能導致 ``調用`` 它的函數退出;不要打
+亂讀者大腦里的語法分析器。
+
+2) 依賴於一個固定名字的本地變量的宏:
+
+.. code-block:: c
+
+	#define FOO(val) bar(index, val)
+
+可能看起來像是個不錯的東西,不過它非常容易把讀代碼的人搞糊塗,而且容易導致看起
+來不相關的改動帶來錯誤。
+
+3) 作爲左值的帶參數的宏: FOO(x) = y;如果有人把 FOO 變成一個內聯函數的話,這
+   種用法就會出錯了。
+
+4) 忘記了優先級:使用表達式定義常量的宏必須將表達式置於一對小括號之內。帶參數
+   的宏也要注意此類問題。
+
+.. code-block:: c
+
+	#define CONSTANT 0x4000
+	#define CONSTEXP (CONSTANT | 3)
+
+5) 在宏里定義類似函數的本地變量時命名衝突:
+
+.. code-block:: c
+
+	#define FOO(x)				\
+	({					\
+		typeof(x) ret;			\
+		ret = calc_ret(x);		\
+		(ret);				\
+	})
+
+ret 是本地變量的通用名字 - __foo_ret 更不容易與一個已存在的變量衝突。
+
+cpp 手冊對宏的講解很詳細。gcc internals 手冊也詳細講解了 RTL,內核里的彙編語
+言經常用到它。
+
+
+13) 列印內核消息
+------------------------------
+
+內核開發者應該是受過良好教育的。請一定注意內核信息的拼寫,以給人以好的印象。
+不要用不規範的單詞比如 ``dont``,而要用 ``do not`` 或者 ``don't`` 。保證這些信
+息簡單明了,無歧義。
+
+內核信息不必以英文句號結束。
+
+在小括號里列印數字 (%d) 沒有任何價值,應該避免這樣做。
+
+<linux/device.h> 里有一些驅動模型診斷宏,你應該使用它們,以確保信息對應於正確
+的設備和驅動,並且被標記了正確的消息級別。這些宏有:dev_err(), dev_warn(),
+dev_info() 等等。對於那些不和某個特定設備相關連的信息,<linux/printk.h> 定義
+了 pr_notice(), pr_info(), pr_warn(), pr_err() 和其他。
+
+寫出好的調試信息可以是一個很大的挑戰;一旦你寫出後,這些信息在遠程除錯時能提
+供極大的幫助。然而列印調試信息的處理方式同列印非調試信息不同。其他 pr_XXX()
+函數能無條件地列印,pr_debug() 卻不;默認情況下它不會被編譯,除非定義了 DEBUG
+或設定了 CONFIG_DYNAMIC_DEBUG。實際這同樣是爲了 dev_dbg(),一個相關約定是在一
+個已經開啓了 DEBUG 時,使用 VERBOSE_DEBUG 來添加 dev_vdbg()。
+
+許多子系統擁有 Kconfig 調試選項來開啓 -DDEBUG 在對應的 Makefile 裡面;在其他
+情況下,特殊文件使用 #define DEBUG。當一條調試信息需要被無條件列印時,例如,
+如果已經包含一個調試相關的 #ifdef 條件,printk(KERN_DEBUG ...) 就可被使用。
+
+
+14) 分配內存
+------------------------------
+
+內核提供了下面的一般用途的內存分配函數:
+kmalloc(), kzalloc(), kmalloc_array(), kcalloc(), vmalloc() 和 vzalloc()。
+請參考 API 文檔以獲取有關它們的詳細信息。
+
+傳遞結構體大小的首選形式是這樣的:
+
+.. code-block:: c
+
+	p = kmalloc(sizeof(*p), ...);
+
+另外一種傳遞方式中,sizeof 的操作數是結構體的名字,這樣會降低可讀性,並且可能
+會引入 bug。有可能指針變量類型被改變時,而對應的傳遞給內存分配函數的 sizeof
+的結果不變。
+
+強制轉換一個 void 指針返回值是多餘的。C 語言本身保證了從 void 指針到其他任何
+指針類型的轉換是沒有問題的。
+
+分配一個數組的首選形式是這樣的:
+
+.. code-block:: c
+
+	p = kmalloc_array(n, sizeof(...), ...);
+
+分配一個零長數組的首選形式是這樣的:
+
+.. code-block:: c
+
+	p = kcalloc(n, sizeof(...), ...);
+
+兩種形式檢查分配大小 n * sizeof(...) 的溢出,如果溢出返回 NULL。
+
+
+15) 內聯弊病
+------------------------------
+
+有一個常見的誤解是 ``內聯`` 是 gcc 提供的可以讓代碼運行更快的一個選項。雖然使
+用內聯函數有時候是恰當的 (比如作爲一種替代宏的方式,請看第十二章),不過很多情
+況下不是這樣。inline 的過度使用會使內核變大,從而使整個系統運行速度變慢。
+因爲體積大內核會占用更多的指令高速緩存,而且會導致 pagecache 的可用內存減少。
+想像一下,一次 pagecache 未命中就會導致一次磁碟尋址,將耗時 5 毫秒。5 毫秒的
+時間內 CPU 能執行很多很多指令。
+
+一個基本的原則是如果一個函數有 3 行以上,就不要把它變成內聯函數。這個原則的一
+個例外是,如果你知道某個參數是一個編譯時常量,而且因爲這個常量你確定編譯器在
+編譯時能優化掉你的函數的大部分代碼,那仍然可以給它加上 inline 關鍵字。
+kmalloc() 內聯函數就是一個很好的例子。
+
+人們經常主張給 static 的而且只用了一次的函數加上 inline,如此不會有任何損失,
+因爲沒有什麼好權衡的。雖然從技術上說這是正確的,但是實際上這種情況下即使不加
+inline gcc 也可以自動使其內聯。而且其他用戶可能會要求移除 inline,由此而來的
+爭論會抵消 inline 自身的潛在價值,得不償失。
+
+
+16) 函數返回值及命名
+------------------------------
+
+函數可以返回多種不同類型的值,最常見的一種是表明函數執行成功或者失敗的值。這樣
+的一個值可以表示爲一個錯誤代碼整數 (-Exxx=失敗,0=成功) 或者一個 ``成功``
+布爾值 (0=失敗,非0=成功)。
+
+混合使用這兩種表達方式是難於發現的 bug 的來源。如果 C 語言本身嚴格區分整形和
+布爾型變量,那麼編譯器就能夠幫我們發現這些錯誤... 不過 C 語言不區分。爲了避免
+產生這種 bug,請遵循下面的慣例::
+
+	如果函數的名字是一個動作或者強制性的命令,那麼這個函數應該返回錯誤代
+	碼整數。如果是一個判斷,那麼函數應該返回一個 "成功" 布爾值。
+
+比如, ``add work`` 是一個命令,所以 add_work() 在成功時返回 0,在失敗時返回
+-EBUSY。類似的,因爲 ``PCI device present`` 是一個判斷,所以 pci_dev_present()
+在成功找到一個匹配的設備時應該返回 1,如果找不到時應該返回 0。
+
+所有 EXPORTed 函數都必須遵守這個慣例,所有的公共函數也都應該如此。私有
+(static) 函數不需要如此,但是我們也推薦這樣做。
+
+返回值是實際計算結果而不是計算是否成功的標誌的函數不受此慣例的限制。一般的,
+他們通過返回一些正常值範圍之外的結果來表示出錯。典型的例子是返回指針的函數,
+他們使用 NULL 或者 ERR_PTR 機制來報告錯誤。
+
+
+17) 不要重新發明內核宏
+------------------------------
+
+頭文件 include/linux/kernel.h 包含了一些宏,你應該使用它們,而不要自己寫一些
+它們的變種。比如,如果你需要計算一個數組的長度,使用這個宏
+
+.. code-block:: c
+
+	#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+類似的,如果你要計算某結構體成員的大小,使用
+
+.. code-block:: c
+
+	#define sizeof_field(t, f) (sizeof(((t*)0)->f))
+
+還有可以做嚴格的類型檢查的 min() 和 max() 宏,如果你需要可以使用它們。你可以
+自己看看那個頭文件里還定義了什麼你可以拿來用的東西,如果有定義的話,你就不應
+在你的代碼里自己重新定義。
+
+
+18) 編輯器模式行和其他需要羅嗦的事情
+--------------------------------------------------
+
+有一些編輯器可以解釋嵌入在源文件里的由一些特殊標記標明的配置信息。比如,emacs
+能夠解釋被標記成這樣的行:
+
+.. code-block:: c
+
+	-*- mode: c -*-
+
+或者這樣的:
+
+.. code-block:: c
+
+	/*
+	Local Variables:
+	compile-command: "gcc -DMAGIC_DEBUG_FLAG foo.c"
+	End:
+	*/
+
+Vim 能夠解釋這樣的標記:
+
+.. code-block:: c
+
+	/* vim:set sw=8 noet */
+
+不要在原始碼中包含任何這樣的內容。每個人都有他自己的編輯器配置,你的源文件不
+應該覆蓋別人的配置。這包括有關縮進和模式配置的標記。人們可以使用他們自己定製
+的模式,或者使用其他可以產生正確的縮進的巧妙方法。
+
+
+19) 內聯彙編
+------------------------------
+
+在特定架構的代碼中,你可能需要內聯彙編與 CPU 和平台相關功能連接。需要這麼做時
+就不要猶豫。然而,當 C 可以完成工作時,不要平白無故地使用內聯彙編。在可能的情
+況下,你可以並且應該用 C 和硬體溝通。
+
+請考慮去寫捆綁通用位元 (wrap common bits) 的內聯彙編的簡單輔助函數,別去重複
+地寫下只有細微差異內聯彙編。記住內聯彙編可以使用 C 參數。
+
+大型,有一定複雜度的彙編函數應該放在 .S 文件內,用相應的 C 原型定義在 C 頭文
+件中。彙編函數的 C 原型應該使用 ``asmlinkage`` 。
+
+你可能需要把彙編語句標記爲 volatile,用來阻止 GCC 在沒發現任何副作用後就把它
+移除了。你不必總是這樣做,儘管,這不必要的舉動會限制優化。
+
+在寫一個包含多條指令的單個內聯彙編語句時,把每條指令用引號分割而且各占一行,
+除了最後一條指令外,在每個指令結尾加上 \n\t,讓彙編輸出時可以正確地縮進下一條
+指令:
+
+.. code-block:: c
+
+	asm ("magic %reg1, #42\n\t"
+	     "more_magic %reg2, %reg3"
+	     : /* outputs */ : /* inputs */ : /* clobbers */);
+
+
+20) 條件編譯
+------------------------------
+
+只要可能,就不要在 .c 文件裡面使用預處理條件 (#if, #ifdef);這樣做讓代碼更難
+閱讀並且更難去跟蹤邏輯。替代方案是,在頭文件中用預處理條件提供給那些 .c 文件
+使用,再給 #else 提供一個空樁 (no-op stub) 版本,然後在 .c 文件內無條件地調用
+那些 (定義在頭文件內的) 函數。這樣做,編譯器會避免爲樁函數 (stub) 的調用生成
+任何代碼,產生的結果是相同的,但邏輯將更加清晰。
+
+最好傾向於編譯整個函數,而不是函數的一部分或表達式的一部分。與其放一個 ifdef
+在表達式內,不如分解出部分或全部表達式,放進一個單獨的輔助函數,並應用預處理
+條件到這個輔助函數內。
+
+如果你有一個在特定配置中,可能變成未使用的函數或變量,編譯器會警告它定義了但
+未使用,把它標記爲 __maybe_unused 而不是將它包含在一個預處理條件中。(然而,如
+果一個函數或變量總是未使用,就直接刪除它。)
+
+在代碼中,儘可能地使用 IS_ENABLED 宏來轉化某個 Kconfig 標記爲 C 的布爾
+表達式,並在一般的 C 條件中使用它:
+
+.. code-block:: c
+
+	if (IS_ENABLED(CONFIG_SOMETHING)) {
+		...
+	}
+
+編譯器會做常量摺疊,然後就像使用 #ifdef 那樣去包含或排除代碼塊,所以這不會帶
+來任何運行時開銷。然而,這種方法依舊允許 C 編譯器查看塊內的代碼,並檢查它的正
+確性 (語法,類型,符號引用,等等)。因此,如果條件不滿足,代碼塊內的引用符號就
+不存在時,你還是必須去用 #ifdef。
+
+在任何有意義的 #if 或 #ifdef 塊的末尾 (超過幾行的),在 #endif 同一行的後面寫下
+註解,注釋這個條件表達式。例如:
+
+.. code-block:: c
+
+	#ifdef CONFIG_SOMETHING
+	...
+	#endif /* CONFIG_SOMETHING */
+
+
+附錄 I) 參考
+-------------------
+
+The C Programming Language, 第二版
+作者:Brian W. Kernighan 和 Denni M. Ritchie.
+Prentice Hall, Inc., 1988.
+ISBN 0-13-110362-8 (軟皮), 0-13-110370-9 (硬皮).
+
+The Practice of Programming
+作者:Brian W. Kernighan 和 Rob Pike.
+Addison-Wesley, Inc., 1999.
+ISBN 0-201-61586-X.
+
+GNU 手冊 - 遵循 K&R 標準和此文本 - cpp, gcc, gcc internals and indent,
+都可以從 https://www.gnu.org/manual/ 找到
+
+WG14 是 C 語言的國際標準化工作組,URL: http://www.open-std.org/JTC1/SC22/WG14/
+
+Kernel process/coding-style.rst,作者 greg@kroah.com 發表於 OLS 2002:
+http://www.kroah.com/linux/talks/ols_2002_kernel_codingstyle_talk/html/
+
diff --git a/Documentation/translations/zh_TW/process/development-process.rst b/Documentation/translations/zh_TW/process/development-process.rst
new file mode 100644
index 000000000000..45e6385647cd
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/development-process.rst
@@ -0,0 +1,30 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/development-process.rst <development_process_main>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+.. _tw_development_process_main:
+
+內核開發過程指南
+================
+
+內容:
+
+.. toctree::
+   :numbered:
+   :maxdepth: 2
+
+   1.Intro
+   2.Process
+   3.Early-stage
+   4.Coding
+   5.Posting
+   6.Followthrough
+   7.AdvancedTopics
+   8.Conclusion
+
+本文檔的目的是幫助開發人員(及其經理)以最小的挫折感與開發社區合作。它試圖記錄這個社區如何以一種不熟悉Linux內核開發(或者實際上是自由軟體開發)的人可以訪問的方式工作。雖然這裡有一些技術資料,但這是一個面向過程的討論,不需要深入了解內核編程就可以理解。
+
diff --git a/Documentation/translations/zh_TW/process/email-clients.rst b/Documentation/translations/zh_TW/process/email-clients.rst
new file mode 100644
index 000000000000..4ba543d06f3b
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/email-clients.rst
@@ -0,0 +1,252 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _tw_email_clients:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/email-clients.rst <email_clients>`
+
+譯者::
+
+        中文版維護者: 賈威威  Harry Wei <harryxiyou@gmail.com>
+        中文版翻譯者: 賈威威  Harry Wei <harryxiyou@gmail.com>
+                       時奎亮  Alex Shi <alex.shi@linux.alibaba.com>
+        中文版校譯者: Yinglin Luan <synmyth@gmail.com>
+        	       Xiaochen Wang <wangxiaochen0@gmail.com>
+                       yaxinsn <yaxinsn@163.com>
+                      Hu Haowen <src.res@email.cn>
+
+Linux郵件客戶端配置信息
+=======================
+
+Git
+---
+
+現在大多數開發人員使用 ``git send-email`` 而不是常規的電子郵件客戶端。這方面
+的手冊非常好。在接收端,維護人員使用 ``git am`` 加載補丁。
+
+如果你是 ``git`` 新手,那麼把你的第一個補丁發送給你自己。將其保存爲包含所有
+標題的原始文本。運行 ``git am raw_email.txt`` ,然後使用 ``git log`` 查看更
+改日誌。如果工作正常,再將補丁發送到相應的郵件列表。
+
+
+普通配置
+--------
+Linux內核補丁是通過郵件被提交的,最好把補丁作爲郵件體的內嵌文本。有些維護者
+接收附件,但是附件的內容格式應該是"text/plain"。然而,附件一般是不贊成的,
+因爲這會使補丁的引用部分在評論過程中變的很困難。
+
+用來發送Linux內核補丁的郵件客戶端在發送補丁時應該處於文本的原始狀態。例如,
+他們不能改變或者刪除制表符或者空格,甚至是在每一行的開頭或者結尾。
+
+不要通過"format=flowed"模式發送補丁。這樣會引起不可預期以及有害的斷行。
+
+不要讓你的郵件客戶端進行自動換行。這樣也會破壞你的補丁。
+
+郵件客戶端不能改變文本的字符集編碼方式。要發送的補丁只能是ASCII或者UTF-8編碼方式,
+如果你使用UTF-8編碼方式發送郵件,那麼你將會避免一些可能發生的字符集問題。
+
+郵件客戶端應該形成並且保持 References: 或者 In-Reply-To: 標題,那麼
+郵件話題就不會中斷。
+
+複製粘帖(或者剪貼粘帖)通常不能用於補丁,因爲制表符會轉換爲空格。使用xclipboard, xclip
+或者xcutsel也許可以,但是最好測試一下或者避免使用複製粘帖。
+
+不要在使用PGP/GPG署名的郵件中包含補丁。這樣會使得很多腳本不能讀取和適用於你的補丁。
+(這個問題應該是可以修復的)
+
+在給內核郵件列表發送補丁之前,給自己發送一個補丁是個不錯的主意,保存接收到的
+郵件,將補丁用'patch'命令打上,如果成功了,再給內核郵件列表發送。
+
+
+一些郵件客戶端提示
+------------------
+這裡給出一些詳細的MUA配置提示,可以用於給Linux內核發送補丁。這些並不意味是
+所有的軟體包配置總結。
+
+說明:
+TUI = 以文本爲基礎的用戶接口
+GUI = 圖形界面用戶接口
+
+Alpine (TUI)
+~~~~~~~~~~~~
+
+配置選項:
+在"Sending Preferences"部分:
+
+- "Do Not Send Flowed Text"必須開啓
+- "Strip Whitespace Before Sending"必須關閉
+
+當寫郵件時,光標應該放在補丁會出現的地方,然後按下CTRL-R組合鍵,使指定的
+補丁文件嵌入到郵件中。
+
+Evolution (GUI)
+~~~~~~~~~~~~~~~
+
+一些開發者成功的使用它發送補丁
+
+當選擇郵件選項:Preformat
+  從Format->Heading->Preformatted (Ctrl-7)或者工具欄
+
+然後使用:
+  Insert->Text File... (Alt-n x)插入補丁文件。
+
+你還可以"diff -Nru old.c new.c | xclip",選擇Preformat,然後使用中間鍵進行粘帖。
+
+Kmail (GUI)
+~~~~~~~~~~~
+
+一些開發者成功的使用它發送補丁。
+
+默認設置不爲HTML格式是合適的;不要啓用它。
+
+當書寫一封郵件的時候,在選項下面不要選擇自動換行。唯一的缺點就是你在郵件中輸入的任何文本
+都不會被自動換行,因此你必須在發送補丁之前手動換行。最簡單的方法就是啓用自動換行來書寫郵件,
+然後把它保存爲草稿。一旦你在草稿中再次打開它,它已經全部自動換行了,那麼你的郵件雖然沒有
+選擇自動換行,但是還不會失去已有的自動換行。
+
+在郵件的底部,插入補丁之前,放上常用的補丁定界符:三個連字號(---)。
+
+然後在"Message"菜單條目,選擇插入文件,接著選取你的補丁文件。還有一個額外的選項,你可以
+通過它配置你的郵件建立工具欄菜單,還可以帶上"insert file"圖標。
+
+你可以安全地通過GPG標記附件,但是內嵌補丁最好不要使用GPG標記它們。作爲內嵌文本的簽發補丁,
+當從GPG中提取7位編碼時會使他們變的更加複雜。
+
+如果你非要以附件的形式發送補丁,那麼就右鍵點擊附件,然後選中屬性,突出"Suggest automatic
+display",這樣內嵌附件更容易讓讀者看到。
+
+當你要保存將要發送的內嵌文本補丁,你可以從消息列表窗格選擇包含補丁的郵件,然後右擊選擇
+"save as"。你可以使用一個沒有更改的包含補丁的郵件,如果它是以正確的形式組成。當你正真在它
+自己的窗口之下察看,那時沒有選項可以保存郵件--已經有一個這樣的bug被匯報到了kmail的bugzilla
+並且希望這將會被處理。郵件是以只針對某個用戶可讀寫的權限被保存的,所以如果你想把郵件複製到其他地方,
+你不得不把他們的權限改爲組或者整體可讀。
+
+Lotus Notes (GUI)
+~~~~~~~~~~~~~~~~~
+
+不要使用它。
+
+Mutt (TUI)
+~~~~~~~~~~
+
+很多Linux開發人員使用mutt客戶端,所以證明它肯定工作的非常漂亮。
+
+Mutt不自帶編輯器,所以不管你使用什麼編輯器都不應該帶有自動斷行。大多數編輯器都帶有
+一個"insert file"選項,它可以通過不改變文件內容的方式插入文件。
+
+'vim'作爲mutt的編輯器:
+  set editor="vi"
+
+  如果使用xclip,敲入以下命令
+  :set paste
+  按中鍵之前或者shift-insert或者使用
+  :r filename
+
+如果想要把補丁作爲內嵌文本。
+(a)ttach工作的很好,不帶有"set paste"。
+
+你可以通過 ``git format-patch`` 生成補丁,然後用 Mutt發送它們::
+
+        $ mutt -H 0001-some-bug-fix.patch
+
+配置選項:
+它應該以默認設置的形式工作。
+然而,把"send_charset"設置爲"us-ascii::utf-8"也是一個不錯的主意。
+
+Mutt 是高度可配置的。 這裡是個使用mutt通過 Gmail 發送的補丁的最小配置::
+
+  # .muttrc
+  # ================  IMAP ====================
+  set imap_user = 'yourusername@gmail.com'
+  set imap_pass = 'yourpassword'
+  set spoolfile = imaps://imap.gmail.com/INBOX
+  set folder = imaps://imap.gmail.com/
+  set record="imaps://imap.gmail.com/[Gmail]/Sent Mail"
+  set postponed="imaps://imap.gmail.com/[Gmail]/Drafts"
+  set mbox="imaps://imap.gmail.com/[Gmail]/All Mail"
+
+  # ================  SMTP  ====================
+  set smtp_url = "smtp://username@smtp.gmail.com:587/"
+  set smtp_pass = $imap_pass
+  set ssl_force_tls = yes # Require encrypted connection
+
+  # ================  Composition  ====================
+  set editor = `echo \$EDITOR`
+  set edit_headers = yes  # See the headers when editing
+  set charset = UTF-8     # value of $LANG; also fallback for send_charset
+  # Sender, email address, and sign-off line must match
+  unset use_domain        # because joe@localhost is just embarrassing
+  set realname = "YOUR NAME"
+  set from = "username@gmail.com"
+  set use_from = yes
+
+Mutt文檔含有更多信息:
+
+    http://dev.mutt.org/trac/wiki/UseCases/Gmail
+
+    http://dev.mutt.org/doc/manual.html
+
+Pine (TUI)
+~~~~~~~~~~
+
+Pine過去有一些空格刪減問題,但是這些現在應該都被修復了。
+
+如果可以,請使用alpine(pine的繼承者)
+
+配置選項:
+- 最近的版本需要消除流程文本
+- "no-strip-whitespace-before-send"選項也是需要的。
+
+
+Sylpheed (GUI)
+~~~~~~~~~~~~~~
+
+- 內嵌文本可以很好的工作(或者使用附件)。
+- 允許使用外部的編輯器。
+- 對於目錄較多時非常慢。
+- 如果通過non-SSL連接,無法使用TLS SMTP授權。
+- 在組成窗口中有一個很有用的ruler bar。
+- 給地址本中添加地址就不會正確的了解顯示名。
+
+Thunderbird (GUI)
+~~~~~~~~~~~~~~~~~
+
+默認情況下,thunderbird很容易損壞文本,但是還有一些方法可以強制它變得更好。
+
+- 在用戶帳號設置里,組成和尋址,不要選擇"Compose messages in HTML format"。
+
+- 編輯你的Thunderbird配置設置來使它不要拆行使用:user_pref("mailnews.wraplength", 0);
+
+- 編輯你的Thunderbird配置設置,使它不要使用"format=flowed"格式:user_pref("mailnews.
+  send_plaintext_flowed", false);
+
+- 你需要使Thunderbird變爲預先格式方式:
+  如果默認情況下你書寫的是HTML格式,那不是很難。僅僅從標題欄的下拉框中選擇"Preformat"格式。
+  如果默認情況下你書寫的是文本格式,你不得把它改爲HTML格式(僅僅作爲一次性的)來書寫新的消息,
+  然後強制使它回到文本格式,否則它就會拆行。要實現它,在寫信的圖標上使用shift鍵來使它變爲HTML
+  格式,然後標題欄的下拉框中選擇"Preformat"格式。
+
+- 允許使用外部的編輯器:
+  針對Thunderbird打補丁最簡單的方法就是使用一個"external editor"擴展,然後使用你最喜歡的
+  $EDITOR來讀取或者合併補丁到文本中。要實現它,可以下載並且安裝這個擴展,然後添加一個使用它的
+  按鍵View->Toolbars->Customize...最後當你書寫信息的時候僅僅點擊它就可以了。
+
+TkRat (GUI)
+~~~~~~~~~~~
+
+可以使用它。使用"Insert file..."或者外部的編輯器。
+
+Gmail (Web GUI)
+~~~~~~~~~~~~~~~
+
+不要使用它發送補丁。
+
+Gmail網頁客戶端自動地把制表符轉換爲空格。
+
+雖然制表符轉換爲空格問題可以被外部編輯器解決,同時它還會使用回車換行把每行拆分爲78個字符。
+
+另一個問題是Gmail還會把任何不是ASCII的字符的信息改爲base64編碼。它把東西變的像歐洲人的名字。
+
+                                ###
+
diff --git a/Documentation/translations/zh_TW/process/embargoed-hardware-issues.rst b/Documentation/translations/zh_TW/process/embargoed-hardware-issues.rst
new file mode 100644
index 000000000000..d676cef16646
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/embargoed-hardware-issues.rst
@@ -0,0 +1,232 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/embargoed-hardware-issues.rst <embargoed_hardware_issues>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+被限制的硬體問題
+================
+
+範圍
+----
+
+導致安全問題的硬體問題與只影響Linux內核的純軟體錯誤是不同的安全錯誤類別。
+
+必須區別對待諸如熔毀(Meltdown)、Spectre、L1TF等硬體問題,因爲它們通常會影響
+所有作業系統(「OS」),因此需要在不同的OS供應商、發行版、硬體供應商和其他各方
+之間進行協調。對於某些問題,軟體緩解可能依賴於微碼或固件更新,這需要進一步的
+協調。
+
+.. _zh_Contact:
+
+接觸
+----
+
+Linux內核硬體安全小組獨立於普通的Linux內核安全小組。
+
+該小組只負責協調被限制的硬體安全問題。Linux內核中純軟體安全漏洞的報告不由該
+小組處理,報告者將被引導至常規Linux內核安全小組(:ref:`Documentation/admin-guide/
+<securitybugs>`)聯繫。
+
+可以通過電子郵件 <hardware-security@kernel.org> 與小組聯繫。這是一份私密的安全
+官名單,他們將幫助您根據我們的文檔化流程協調問題。
+
+郵件列表是加密的,發送到列表的電子郵件可以通過PGP或S/MIME加密,並且必須使用報告
+者的PGP密鑰或S/MIME證書籤名。該列表的PGP密鑰和S/MIME證書可從
+https://www.kernel.org/.... 獲得。
+
+雖然硬體安全問題通常由受影響的硬體供應商處理,但我們歡迎發現潛在硬體缺陷的研究
+人員或個人與我們聯繫。
+
+硬體安全官
+^^^^^^^^^^
+
+目前的硬體安全官小組:
+
+  - Linus Torvalds(Linux基金會院士)
+  - Greg Kroah Hartman(Linux基金會院士)
+  - Thomas Gleixner(Linux基金會院士)
+
+郵件列表的操作
+^^^^^^^^^^^^^^
+
+處理流程中使用的加密郵件列表託管在Linux Foundation的IT基礎設施上。通過提供這項
+服務,Linux基金會的IT基礎設施安全總監在技術上有能力訪問被限制的信息,但根據他
+的僱傭合同,他必須保密。Linux基金會的IT基礎設施安全總監還負責 kernel.org 基礎
+設施。
+
+Linux基金會目前的IT基礎設施安全總監是 Konstantin Ryabitsev。
+
+保密協議
+--------
+
+Linux內核硬體安全小組不是正式的機構,因此無法簽訂任何保密協議。核心社區意識到
+這些問題的敏感性,並提供了一份諒解備忘錄。
+
+諒解備忘錄
+----------
+
+Linux內核社區深刻理解在不同作業系統供應商、發行商、硬體供應商和其他各方之間
+進行協調時,保持硬體安全問題處於限制狀態的要求。
+
+Linux內核社區在過去已經成功地處理了硬體安全問題,並且有必要的機制允許在限制
+限制下進行符合社區的開發。
+
+Linux內核社區有一個專門的硬體安全小組負責初始聯繫,並監督在限制規則下處理
+此類問題的過程。
+
+硬體安全小組確定開發人員(領域專家),他們將組成特定問題的初始響應小組。最初
+的響應小組可以引入更多的開發人員(領域專家)以最佳的技術方式解決這個問題。
+
+所有相關開發商承諾遵守限制規定,並對收到的信息保密。違反承諾將導致立即從當前
+問題中排除,並從所有相關郵件列表中刪除。此外,硬體安全小組還將把違反者排除在
+未來的問題之外。這一後果的影響在我們社區是一種非常有效的威懾。如果發生違規
+情況,硬體安全小組將立即通知相關方。如果您或任何人發現潛在的違規行爲,請立即
+向硬體安全人員報告。
+
+流程
+^^^^
+
+由於Linux內核開發的全球分布式特性,面對面的會議幾乎不可能解決硬體安全問題。
+由於時區和其他因素,電話會議很難協調,只能在絕對必要時使用。加密電子郵件已被
+證明是解決此類問題的最有效和最安全的通信方法。
+
+開始披露
+""""""""
+
+披露內容首先通過電子郵件聯繫Linux內核硬體安全小組。此初始聯繫人應包含問題的
+描述和任何已知受影響硬體的列表。如果您的組織製造或分發受影響的硬體,我們建議
+您也考慮哪些其他硬體可能會受到影響。
+
+硬體安全小組將提供一個特定於事件的加密郵件列表,用於與報告者進行初步討論、
+進一步披露和協調。
+
+硬體安全小組將向披露方提供一份開發人員(領域專家)名單,在與開發人員確認他們
+將遵守本諒解備忘錄和文件化流程後,應首先告知開發人員有關該問題的信息。這些開發
+人員組成初始響應小組,並在初始接觸後負責處理問題。硬體安全小組支持響應小組,
+但不一定參與緩解開發過程。
+
+雖然個別開發人員可能通過其僱主受到保密協議的保護,但他們不能以Linux內核開發
+人員的身份簽訂個別保密協議。但是,他們將同意遵守這一書面程序和諒解備忘錄。
+
+披露方應提供已經或應該被告知該問題的所有其他實體的聯繫人名單。這有幾個目的:
+
+  - 披露的實體列表允許跨行業通信,例如其他作業系統供應商、硬體供應商等。
+
+  - 可聯繫已披露的實體,指定應參與緩解措施開發的專家。
+
+  - 如果需要處理某一問題的專家受僱於某一上市實體或某一上市實體的成員,則響應
+    小組可要求該實體披露該專家。這確保專家也是實體反應小組的一部分。
+
+披露
+""""
+
+披露方通過特定的加密郵件列表向初始響應小組提供詳細信息。
+
+根據我們的經驗,這些問題的技術文檔通常是一個足夠的起點,最好通過電子郵件進行
+進一步的技術澄清。
+
+緩解開發
+""""""""
+
+初始響應小組設置加密郵件列表,或在適當的情況下重新修改現有郵件列表。
+
+使用郵件列表接近於正常的Linux開發過程,並且在過去已經成功地用於爲各種硬體安全
+問題開發緩解措施。
+
+郵件列表的操作方式與正常的Linux開發相同。發布、討論和審查修補程序,如果同意,
+則應用於非公共git存儲庫,參與開發人員只能通過安全連接訪問該存儲庫。存儲庫包含
+針對主線內核的主開發分支,並根據需要爲穩定的內核版本提供向後移植分支。
+
+最初的響應小組將根據需要從Linux內核開發人員社區中確定更多的專家。引進專家可以
+在開發過程中的任何時候發生,需要及時處理。
+
+如果專家受僱於披露方提供的披露清單上的實體或其成員,則相關實體將要求其參與。
+
+否則,披露方將被告知專家參與的情況。諒解備忘錄涵蓋了專家,要求披露方確認參與。
+如果披露方有令人信服的理由提出異議,則必須在五個工作日內提出異議,並立即與事件
+小組解決。如果披露方在五個工作日內未作出回應,則視爲默許。
+
+在確認或解決異議後,專家由事件小組披露,並進入開發過程。
+
+協調發布
+""""""""
+
+有關各方將協商限制結束的日期和時間。此時,準備好的緩解措施集成到相關的內核樹中
+並發布。
+
+雖然我們理解硬體安全問題需要協調限制時間,但限制時間應限制在所有有關各方制定、
+測試和準備緩解措施所需的最短時間內。人爲地延長限制時間以滿足會議討論日期或其他
+非技術原因,會給相關的開發人員和響應小組帶來了更多的工作和負擔,因爲補丁需要
+保持最新,以便跟蹤正在進行的上游內核開發,這可能會造成衝突的更改。
+
+CVE分配
+"""""""
+
+硬體安全小組和初始響應小組都不分配CVE,開發過程也不需要CVE。如果CVE是由披露方
+提供的,則可用於文檔中。
+
+流程專使
+--------
+
+爲了協助這一進程,我們在各組織設立了專使,他們可以回答有關報告流程和進一步處理
+的問題或提供指導。專使不參與特定問題的披露,除非響應小組或相關披露方提出要求。
+現任專使名單:
+
+  ============= ========================================================
+  ARM
+  AMD		Tom Lendacky <tom.lendacky@amd.com>
+  IBM
+  Intel		Tony Luck <tony.luck@intel.com>
+  Qualcomm	Trilok Soni <tsoni@codeaurora.org>
+
+  Microsoft	Sasha Levin <sashal@kernel.org>
+  VMware
+  Xen		Andrew Cooper <andrew.cooper3@citrix.com>
+
+  Canonical	John Johansen <john.johansen@canonical.com>
+  Debian	Ben Hutchings <ben@decadent.org.uk>
+  Oracle	Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
+  Red Hat	Josh Poimboeuf <jpoimboe@redhat.com>
+  SUSE		Jiri Kosina <jkosina@suse.cz>
+
+  Amazon
+  Google	Kees Cook <keescook@chromium.org>
+  ============= ========================================================
+
+如果要將您的組織添加到專使名單中,請與硬體安全小組聯繫。被提名的專使必須完全
+理解和支持我們的過程,並且在Linux內核社區中很容易聯繫。
+
+加密郵件列表
+------------
+
+我們使用加密郵件列表進行通信。這些列表的工作原理是,發送到列表的電子郵件使用
+列表的PGP密鑰或列表的/MIME證書進行加密。郵件列表軟體對電子郵件進行解密,並
+使用訂閱者的PGP密鑰或S/MIME證書爲每個訂閱者分別對其進行重新加密。有關郵件列表
+軟體和用於確保列表安全和數據保護的設置的詳細信息,請訪問:
+https://www.kernel.org/....
+
+關鍵點
+^^^^^^
+
+初次接觸見 :ref:`zh_Contact`. 對於特定於事件的郵件列表,密鑰和S/MIME證書通過
+特定列表發送的電子郵件傳遞給訂閱者。
+
+訂閱事件特定列表
+^^^^^^^^^^^^^^^^
+
+訂閱由響應小組處理。希望參與通信的披露方將潛在訂戶的列表發送給響應組,以便
+響應組可以驗證訂閱請求。
+
+每個訂戶都需要通過電子郵件向響應小組發送訂閱請求。電子郵件必須使用訂閱伺服器
+的PGP密鑰或S/MIME證書籤名。如果使用PGP密鑰,則必須從公鑰伺服器獲得該密鑰,
+並且理想情況下該密鑰連接到Linux內核的PGP信任網。另請參見:
+https://www.kernel.org/signature.html.
+
+響應小組驗證訂閱者,並將訂閱者添加到列表中。訂閱後,訂閱者將收到來自郵件列表
+的電子郵件,該郵件列表使用列表的PGP密鑰或列表的/MIME證書籤名。訂閱者的電子郵件
+客戶端可以從簽名中提取PGP密鑰或S/MIME證書,以便訂閱者可以向列表發送加密電子
+郵件。
+
diff --git a/Documentation/translations/zh_TW/process/howto.rst b/Documentation/translations/zh_TW/process/howto.rst
new file mode 100644
index 000000000000..2043691b92e3
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/howto.rst
@@ -0,0 +1,500 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _tw_process_howto:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/howto.rst <process_howto>`
+
+譯者::
+
+    英文版維護者: Greg Kroah-Hartman <greg@kroah.com>
+    中文版維護者: 李陽  Li Yang <leoyang.li@nxp.com>
+    中文版翻譯者: 李陽  Li Yang <leoyang.li@nxp.com>
+                   時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+    中文版校譯者:
+                   鍾宇  TripleX Chung <xxx.phy@gmail.com>
+                   陳琦  Maggie Chen <chenqi@beyondsoft.com>
+                   王聰  Wang Cong <xiyou.wangcong@gmail.com>
+                   胡皓文 Hu Haowen <src.res@email.cn>
+
+如何參與Linux內核開發
+=====================
+
+這是一篇將如何參與Linux內核開發的相關問題一網打盡的終極祕笈。它將指導你
+成爲一名Linux內核開發者,並且學會如何同Linux內核開發社區合作。它儘可能不
+包括任何關於內核編程的技術細節,但會給你指引一條獲得這些知識的正確途徑。
+
+如果這篇文章中的任何內容不再適用,請給文末列出的文件維護者發送補丁。
+
+
+入門
+----
+
+你想了解如何成爲一名Linux內核開發者?或者老闆吩咐你「給這個設備寫個Linux
+驅動程序」?這篇文章的目的就是教會你達成這些目標的全部訣竅,它將描述你需
+要經過的流程以及給出如何同內核社區合作的一些提示。它還將試圖解釋內核社區
+爲何這樣運作。
+
+Linux內核大部分是由C語言寫成的,一些體系結構相關的代碼用到了彙編語言。要
+參與內核開發,你必須精通C語言。除非你想爲某個架構開發底層代碼,否則你並
+不需要了解(任何體系結構的)彙編語言。下面列舉的書籍雖然不能替代紮實的C
+語言教育和多年的開發經驗,但如果需要的話,做爲參考還是不錯的:
+
+ - "The C Programming Language" by Kernighan and Ritchie [Prentice Hall]
+   《C程序設計語言(第2版·新版)》(徐寶文 李志 譯)[機械工業出版社]
+ - "Practical C Programming" by Steve Oualline [O'Reilly]
+   《實用C語言編程(第三版)》(郭大海 譯)[中國電力出版社]
+ - "C:  A Reference Manual" by Harbison and Steele [Prentice Hall]
+   《C語言參考手冊(原書第5版)》(邱仲潘 等譯)[機械工業出版社]
+
+Linux內核使用GNU C和GNU工具鏈開發。雖然它遵循ISO C89標準,但也用到了一些
+標準中沒有定義的擴展。內核是自給自足的C環境,不依賴於標準C庫的支持,所以
+並不支持C標準中的部分定義。比如long long類型的大數除法和浮點運算就不允許
+使用。有時候確實很難弄清楚內核對工具鏈的要求和它所使用的擴展,不幸的是目
+前還沒有明確的參考資料可以解釋它們。請查閱gcc信息頁(使用「info gcc」命令
+顯示)獲得一些這方面信息。
+
+請記住你是在學習怎麼和已經存在的開發社區打交道。它由一羣形形色色的人組成,
+他們對代碼、風格和過程有著很高的標準。這些標準是在長期實踐中總結出來的,
+適應於地理上分散的大型開發團隊。它們已經被很好得整理成檔,建議你在開發
+之前儘可能多的學習這些標準,而不要期望別人來適應你或者你公司的行爲方式。
+
+
+法律問題
+--------
+
+Linux內核原始碼都是在GPL(通用公共許可證)的保護下發布的。要了解這種許可
+的細節請查看原始碼主目錄下的COPYING文件。Linux內核許可準則和如何使用
+`SPDX <https://spdx.org/>` 標誌符說明在這個文件中
+:ref:`Documentation/translations/zh_TW/process/license-rules.rst <tw_kernel_licensing>`
+如果你對它還有更深入問題請聯繫律師,而不要在Linux內核郵件組上提問。因爲
+郵件組裡的人並不是律師,不要期望他們的話有法律效力。
+
+對於GPL的常見問題和解答,請訪問以下連結:
+	https://www.gnu.org/licenses/gpl-faq.html
+
+
+文檔
+----
+
+Linux內核代碼中包含有大量的文檔。這些文檔對於學習如何與內核社區互動有著
+不可估量的價值。當一個新的功能被加入內核,最好把解釋如何使用這個功能的文
+檔也放進內核。當內核的改動導致面向用戶空間的接口發生變化時,最好將相關信
+息或手冊頁(manpages)的補丁發到mtk.manpages@gmail.com,以向手冊頁(manpages)
+的維護者解釋這些變化。
+
+以下是內核代碼中需要閱讀的文檔:
+  :ref:`Documentation/admin-guide/README.rst <readme>`
+    文件簡要介紹了Linux內核的背景,並且描述了如何配置和編譯內核。內核的
+    新用戶應該從這裡開始。
+
+
+  :ref:`Documentation/process/changes.rst <changes>`
+    文件給出了用來編譯和使用內核所需要的最小軟體包列表。
+
+  :ref:`Documentation/translations/zh_TW/process/coding-style.rst <tw_codingstyle>`
+    描述Linux內核的代碼風格和理由。所有新代碼需要遵守這篇文檔中定義的規
+    范。大多數維護者只會接收符合規定的補丁,很多人也只會幫忙檢查符合風格
+    的代碼。
+
+  :ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+  :ref:`Documentation/process/submitting-drivers.rst <submittingdrivers>`
+
+    這兩份文檔明確描述如何創建和發送補丁,其中包括(但不僅限於):
+       - 郵件內容
+       - 郵件格式
+       - 選擇收件人
+
+    遵守這些規定並不能保證提交成功(因爲所有補丁需要通過嚴格的內容和風格
+    審查),但是忽視他們幾乎就意味著失敗。
+
+    其他關於如何正確地生成補丁的優秀文檔包括:
+    "The Perfect Patch"
+
+        https://www.ozlabs.org/~akpm/stuff/tpp.txt
+
+    "Linux kernel patch submission format"
+
+        https://web.archive.org/web/20180829112450/http://linux.yyz.us/patch-format.html
+
+  :ref:`Documentation/translations/zh_TW/process/stable-api-nonsense.rst <tw_stable_api_nonsense>`
+    論證內核爲什麼特意不包括穩定的內核內部API,也就是說不包括像這樣的特
+    性:
+
+       - 子系統中間層(爲了兼容性?)
+       - 在不同作業系統間易於移植的驅動程序
+       - 減緩(甚至阻止)內核代碼的快速變化
+
+    這篇文檔對於理解Linux的開發哲學至關重要。對於將開發平台從其他操作系
+    統轉移到Linux的人來說也很重要。
+
+  :ref:`Documentation/admin-guide/security-bugs.rst <securitybugs>`
+    如果你認爲自己發現了Linux內核的安全性問題,請根據這篇文檔中的步驟來
+    提醒其他內核開發者並幫助解決這個問題。
+
+  :ref:`Documentation/translations/zh_TW/process/management-style.rst <tw_managementstyle>`
+
+    描述內核維護者的工作方法及其共有特點。這對於剛剛接觸內核開發(或者對
+    它感到好奇)的人來說很重要,因爲它解釋了很多對於內核維護者獨特行爲的
+    普遍誤解與迷惑。
+
+  :ref:`Documentation/process/stable-kernel-rules.rst <stable_kernel_rules>`
+    解釋了穩定版內核發布的規則,以及如何將改動放入這些版本的步驟。
+
+  :ref:`Documentation/process/kernel-docs.rst <kernel_docs>`
+    有助於內核開發的外部文檔列表。如果你在內核自帶的文檔中沒有找到你想找
+    的內容,可以查看這些文檔。
+
+  :ref:`Documentation/process/applying-patches.rst <applying_patches>`
+    關於補丁是什麼以及如何將它打在不同內核開發分支上的好介紹
+
+內核還擁有大量從代碼自動生成或者從 ReStructuredText(ReST) 標記生成的文檔,
+比如這個文檔,它包含內核內部API的全面介紹以及如何妥善處理加鎖的規則。所有
+這些文檔都可以通過運行以下命令從內核代碼中生成爲PDF或HTML文檔::
+
+    make pdfdocs
+    make htmldocs
+
+ReST格式的文檔會生成在 Documentation/output. 目錄中。
+它們也可以用下列命令生成 LaTeX 和 ePub 格式文檔::
+
+    make latexdocs
+    make epubdocs
+
+如何成爲內核開發者
+------------------
+如果你對Linux內核開發一無所知,你應該訪問「Linux內核新手」計劃:
+
+	https://kernelnewbies.org
+
+它擁有一個可以問各種最基本的內核開發問題的郵件列表(在提問之前一定要記得
+查找已往的郵件,確認是否有人已經回答過相同的問題)。它還擁有一個可以獲得
+實時反饋的IRC聊天頻道,以及大量對於學習Linux內核開發相當有幫助的文檔。
+
+網站簡要介紹了原始碼組織結構、子系統劃分以及目前正在進行的項目(包括內核
+中的和單獨維護的)。它還提供了一些基本的幫助信息,比如如何編譯內核和打補
+丁。
+
+如果你想加入內核開發社區並協助完成一些任務,卻找不到從哪裡開始,可以訪問
+「Linux內核房管員」計劃:
+
+	https://kernelnewbies.org/KernelJanitors
+
+這是極佳的起點。它提供一個相對簡單的任務列表,列出內核代碼中需要被重新
+整理或者改正的地方。通過和負責這個計劃的開發者們一同工作,你會學到將補丁
+集成進內核的基本原理。如果還沒有決定下一步要做什麼的話,你還可能會得到方
+向性的指點。
+
+在真正動手修改內核代碼之前,理解要修改的代碼如何運作是必需的。要達到這個
+目的,沒什麼辦法比直接讀代碼更有效了(大多數花招都會有相應的注釋),而且
+一些特製的工具還可以提供幫助。例如,「Linux代碼交叉引用」項目就是一個值得
+特別推薦的幫助工具,它將原始碼顯示在有編目和索引的網頁上。其中一個更新及
+時的內核源碼庫,可以通過以下地址訪問:
+
+        https://elixir.bootlin.com/
+
+
+開發流程
+--------
+
+目前Linux內核開發流程包括幾個「主內核分支」和很多子系統相關的內核分支。這
+些分支包括:
+
+  - Linus 的內核源碼樹
+  - 多個主要版本的穩定版內核樹
+  - 子系統相關的內核樹
+  - linux-next 集成測試樹
+
+
+主線樹
+------
+主線樹是由Linus Torvalds 維護的。你可以在https://kernel.org 網站或者代碼
+庫中下找到它。它的開發遵循以下步驟:
+
+  - 每當一個新版本的內核被發布,爲期兩周的集成窗口將被打開。在這段時間裡
+    維護者可以向Linus提交大段的修改,通常這些修改已經被放到-mm內核中幾個
+    星期了。提交大量修改的首選方式是使用git工具(內核的代碼版本管理工具
+    ,更多的信息可以在 https://git-scm.com/ 獲取),不過使用普通補丁也是
+    可以的。
+  - 兩個星期以後-rc1版本內核發布。之後只有不包含可能影響整個內核穩定性的
+    新功能的補丁才可能被接受。請注意一個全新的驅動程序(或者文件系統)有
+    可能在-rc1後被接受是因爲這樣的修改完全獨立,不會影響其他的代碼,所以
+    沒有造成內核退步的風險。在-rc1以後也可以用git向Linus提交補丁,不過所
+    有的補丁需要同時被發送到相應的公衆郵件列表以徵詢意見。
+  - 當Linus認爲當前的git源碼樹已經達到一個合理健全的狀態足以發布供人測試
+    時,一個新的-rc版本就會被發布。計劃是每周都發布新的-rc版本。
+  - 這個過程一直持續下去直到內核被認爲達到足夠穩定的狀態,持續時間大概是
+    6個星期。
+
+關於內核發布,值得一提的是Andrew Morton在linux-kernel郵件列表中如是說:
+	「沒有人知道新內核何時會被發布,因爲發布是根據已知bug的情況來決定
+	的,而不是根據一個事先制定好的時間表。」
+
+子系統特定樹
+------------
+
+各種內核子系統的維護者——以及許多內核子系統開發人員——在原始碼庫中公開了他們
+當前的開發狀態。這樣,其他人就可以看到內核的不同區域發生了什麼。在開發速度
+很快的領域,可能會要求開發人員將提交的內容建立在這樣的子系統內核樹上,這樣
+就避免了提交與其他已經進行的工作之間的衝突。
+
+這些存儲庫中的大多數都是Git樹,但是也有其他的scm在使用,或者補丁隊列被發布
+爲Quilt系列。這些子系統存儲庫的地址列在MAINTAINERS文件中。其中許多可以在
+https://git.kernel.org/上瀏覽。
+
+在將一個建議的補丁提交到這樣的子系統樹之前,需要對它進行審查,審查主要發生
+在郵件列表上(請參見下面相應的部分)。對於幾個內核子系統,這個審查過程是通
+過工具補丁跟蹤的。Patchwork提供了一個Web界面,顯示補丁發布、對補丁的任何評
+論或修訂,維護人員可以將補丁標記爲正在審查、接受或拒絕。大多數補丁網站都列
+在 https://patchwork.kernel.org/
+
+Linux-next 集成測試樹
+---------------------
+
+在將子系統樹的更新合併到主線樹之前,需要對它們進行集成測試。爲此,存在一個
+特殊的測試存儲庫,其中幾乎每天都會提取所有子系統樹:
+
+        https://git.kernel.org/?p=linux/kernel/git/next/linux-next.git
+
+通過這種方式,Linux-next 對下一個合併階段將進入主線內核的內容給出了一個概要
+展望。非常歡冒險的測試者運行測試Linux-next。
+
+多個主要版本的穩定版內核樹
+-----------------------------------
+由3個數字組成的內核版本號說明此內核是-stable版本。它們包含內核的相對較小且
+至關重要的修補,這些修補針對安全性問題或者嚴重的內核退步。
+
+這種版本的內核適用於那些期望獲得最新的穩定版內核並且不想參與測試開發版或
+者實驗版的用戶。
+
+穩定版內核樹版本由「穩定版」小組(郵件地址<stable@vger.kernel.org>)維護,一般
+隔周發布新版本。
+
+內核源碼中的 :ref:`Documentation/process/stable-kernel-rules.rst <stable_kernel_rules>`
+文件具體描述了可被穩定版內核接受的修改類型以及發布的流程。
+
+
+報告bug
+-------
+
+bugzilla.kernel.org是Linux內核開發者們用來跟蹤內核Bug的網站。我們鼓勵用
+戶在這個工具中報告找到的所有bug。如何使用內核bugzilla的細節請訪問:
+
+	http://test.kernel.org/bugzilla/faq.html
+
+內核源碼主目錄中的:ref:`admin-guide/reporting-bugs.rst <reportingbugs>`
+文件里有一個很好的模板。它指導用戶如何報告可能的內核bug以及需要提供哪些信息
+來幫助內核開發者們找到問題的根源。
+
+
+利用bug報告
+-----------
+
+練習內核開發技能的最好辦法就是修改其他人報告的bug。你不光可以幫助內核變
+得更加穩定,還可以學會如何解決實際問題從而提高自己的技能,並且讓其他開發
+者感受到你的存在。修改bug是贏得其他開發者讚譽的最好辦法,因爲並不是很多
+人都喜歡浪費時間去修改別人報告的bug。
+
+要嘗試修改已知的bug,請訪問 http://bugzilla.kernel.org 網址。
+
+
+郵件列表
+--------
+
+正如上面的文檔所描述,大多數的骨幹內核開發者都加入了Linux Kernel郵件列
+表。如何訂閱和退訂列表的細節可以在這裡找到:
+
+	http://vger.kernel.org/vger-lists.html#linux-kernel
+
+網上很多地方都有這個郵件列表的存檔(archive)。可以使用搜尋引擎來找到這些
+存檔。比如:
+
+	http://dir.gmane.org/gmane.linux.kernel
+
+在發信之前,我們強烈建議你先在存檔中搜索你想要討論的問題。很多已經被詳細
+討論過的問題只在郵件列表的存檔中可以找到。
+
+大多數內核子系統也有自己獨立的郵件列表來協調各自的開發工作。從
+MAINTAINERS文件中可以找到不同話題對應的郵件列表。
+
+很多郵件列表架設在kernel.org伺服器上。這些列表的信息可以在這裡找到:
+
+	http://vger.kernel.org/vger-lists.html
+
+在使用這些郵件列表時,請記住保持良好的行爲習慣。下面的連結提供了與這些列
+表(或任何其它郵件列表)交流的一些簡單規則,雖然內容有點濫竽充數。
+
+	http://www.albion.com/netiquette/
+
+當有很多人回覆你的郵件時,郵件的抄送列表會變得很長。請不要將任何人從抄送
+列表中刪除,除非你有足夠的理由這麼做。也不要只回復到郵件列表。請習慣於同
+一封郵件接收兩次(一封來自發送者一封來自郵件列表),而不要試圖通過添加一
+些奇特的郵件頭來解決這個問題,人們不會喜歡的。
+
+記住保留你所回復內容的上下文和源頭。在你回覆郵件的頂部保留「某某某說到……」
+這幾行。將你的評論加在被引用的段落之間而不要放在郵件的頂部。
+
+如果你在郵件中附帶補丁,請確認它們是可以直接閱讀的純文本(如
+:ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+文檔中所述)。內核開發者們不希望遇到附件或者被壓縮了的補丁。只有這樣才能
+保證他們可以直接評論你的每行代碼。請確保你使用的郵件發送程序不會修改空格
+和制表符。一個防範性的測試方法是先將郵件發送給自己,然後自己嘗試是否可以
+順利地打上收到的補丁。如果測試不成功,請調整或者更換你的郵件發送程序直到
+它正確工作爲止。
+
+總而言之,請尊重其他的郵件列表訂閱者。
+
+
+同內核社區合作
+----------------
+
+內核社區的目標就是提供盡善盡美的內核。所以當你提交補丁期望被接受進內核的
+時候,它的技術價值以及其他方面都將被評審。那麼你可能會得到什麼呢?
+
+  - 批評
+  - 評論
+  - 要求修改
+  - 要求證明修改的必要性
+  - 沉默
+
+要記住,這些是把補丁放進內核的正常情況。你必須學會聽取對補丁的批評和評論,
+從技術層面評估它們,然後要麼重寫你的補丁要麼簡明扼要地論證修改是不必要
+的。如果你發的郵件沒有得到任何回應,請過幾天後再試一次,因爲有時信件會湮
+沒在茫茫信海中。
+
+你不應該做的事情:
+
+  - 期望自己的補丁不受任何質疑就直接被接受
+  - 翻臉
+  - 忽略別人的評論
+  - 沒有按照別人的要求做任何修改就重新提交
+
+在一個努力追尋最好技術方案的社區里,對於一個補丁有多少好處總會有不同的見
+解。你必須要抱著合作的態度,願意改變自己的觀點來適應內核的風格。或者至少
+願意去證明你的想法是有價值的。記住,犯錯誤是允許的,只要你願意朝著正確的
+方案去努力。
+
+如果你的第一個補丁換來的是一堆修改建議,這是很正常的。這並不代表你的補丁
+不會被接受,也不意味著有人和你作對。你只需要改正所有提出的問題然後重新發
+送你的補丁。
+
+內核社區和公司文化的差異
+------------------------
+
+內核社區的工作模式同大多數傳統公司開發隊伍的工作模式並不相同。下面這些例
+子,可以幫助你避免某些可能發生問題:
+用這些話介紹你的修改提案會有好處:
+
+    - 它同時解決了多個問題
+    - 它刪除了2000行代碼
+    - 這是補丁,它已經解釋了我想要說明的
+    - 我在5種不同的體系結構上測試過它……
+    - 這是一系列小補丁用來……
+    - 這個修改提高了普通機器的性能……
+
+應該避免如下的說法:
+
+    - 我們在AIX/ptx/Solaris就是這麼做的,所以這麼做肯定是好的……
+    - 我做這行已經20年了,所以……
+    - 爲了我們公司賺錢考慮必須這麼做
+    - 這是我們的企業產品線所需要的
+    - 這裡是描述我觀點的1000頁設計文檔
+    - 這是一個5000行的補丁用來……
+    - 我重寫了現在亂七八糟的代碼,這就是……
+    - 我被規定了最後期限,所以這個補丁需要立刻被接受
+
+另外一個內核社區與大部分傳統公司的軟體開發隊伍不同的地方是無法面對面地交
+流。使用電子郵件和IRC聊天工具做爲主要溝通工具的一個好處是性別和種族歧視
+將會更少。Linux內核的工作環境更能接受婦女和少數族羣,因爲每個人在別人眼
+里只是一個郵件地址。國際化也幫助了公平的實現,因爲你無法通過姓名來判斷人
+的性別。男人有可能叫李麗,女人也有可能叫王剛。大多數在Linux內核上工作過
+並表達過看法的女性對在linux上工作的經歷都給出了正面的評價。
+
+對於一些不習慣使用英語的人來說,語言可能是一個引起問題的障礙。在郵件列表
+中要正確地表達想法必需良好地掌握語言,所以建議你在發送郵件之前最好檢查一
+下英文寫得是否正確。
+
+
+拆分修改
+--------
+
+Linux內核社區並不喜歡一下接收大段的代碼。修改需要被恰當地介紹、討論並且
+拆分成獨立的小段。這幾乎完全和公司中的習慣背道而馳。你的想法應該在開發最
+開始的階段就讓大家知道,這樣你就可以及時獲得對你正在進行的開發的反饋。這
+樣也會讓社區覺得你是在和他們協作,而不是僅僅把他們當作傾銷新功能的對象。
+無論如何,你不要一次性地向郵件列表發送50封信,你的補丁序列應該永遠用不到
+這麼多。
+
+將補丁拆開的原因如下:
+
+1) 小的補丁更有可能被接受,因爲它們不需要太多的時間和精力去驗證其正確性。
+   一個5行的補丁,可能在維護者看了一眼以後就會被接受。而500行的補丁則
+   需要數個小時來審查其正確性(所需時間隨補丁大小增加大約呈指數級增長)。
+
+   當出了問題的時候,小的補丁也會讓調試變得非常容易。一個一個補丁地回溯
+   將會比仔細剖析一個被打上的大補丁(這個補丁破壞了其他東西)容易得多。
+
+2)不光發送小的補丁很重要,在提交之前重新編排、化簡(或者僅僅重新排列)
+   補丁也是很重要的。
+
+這裡有內核開發者Al Viro打的一個比方:
+	「想像一個老師正在給學生批改數學作業。老師並不希望看到學生爲了得
+	到正確解法所進行的嘗試和產生的錯誤。他希望看到的是最乾淨最優雅的
+	解答。好學生了解這點,絕不會把最終解決之前的中間方案提交上去。」
+
+	內核開發也是這樣。維護者和評審者不希望看到一個人在解決問題時的思
+	考過程。他們只希望看到簡單和優雅的解決方案。
+
+直接給出一流的解決方案,和社區一起協作討論尚未完成的工作,這兩者之間似乎
+很難找到一個平衡點。所以最好儘早開始收集有利於你進行改進的反饋;同時也要
+保證修改分成很多小塊,這樣在整個項目都準備好被包含進內核之前,其中的一部
+分可能會先被接收。
+
+必須了解這樣做是不可接受的:試圖將未完成的工作提交進內核,然後再找時間修
+復。
+
+
+證明修改的必要性
+----------------
+除了將補丁拆成小塊,很重要的一點是讓Linux社區了解他們爲什麼需要這樣修改。
+你必須證明新功能是有人需要的並且是有用的。
+
+
+記錄修改
+--------
+
+當你發送補丁的時候,需要特別留意郵件正文的內容。因爲這裡的信息將會做爲補
+丁的修改記錄(ChangeLog),會被一直保留以備大家查閱。它需要完全地描述補丁,
+包括:
+
+  - 爲什麼需要這個修改
+  - 補丁的總體設計
+  - 實現細節
+  - 測試結果
+
+想了解它具體應該看起來像什麼,請查閱以下文檔中的「ChangeLog」章節:
+  「The Perfect Patch」
+  	 https://www.ozlabs.org/~akpm/stuff/tpp.txt
+
+
+這些事情有時候做起來很難。要在任何方面都做到完美可能需要好幾年時間。這是
+一個持續提高的過程,它需要大量的耐心和決心。只要不放棄,你一定可以做到。
+很多人已經做到了,而他們都曾經和現在的你站在同樣的起點上。
+
+
+感謝
+----
+感謝Paolo Ciarrocchi允許「開發流程」部分基於他所寫的文章
+(http://www.kerneltravel.net/newbie/2.6-development_process),感謝Randy
+Dunlap和Gerrit Huizenga完善了應該說和不該說的列表。感謝Pat Mochel, Hanna
+Linder, Randy Dunlap, Kay Sievers, Vojtech Pavlik, Jan Kara, Josh Boyer,
+Kees Cook, Andrew Morton, Andi Kleen, Vadim Lobanov, Jesper Juhl, Adrian
+Bunk, Keri Harris, Frans Pop, David A. Wheeler, Junio Hamano, Michael
+Kerrisk和Alex Shepard的評審、建議和貢獻。沒有他們的幫助,這篇文檔是不可
+能完成的。
+
+
+
+英文版維護者: Greg Kroah-Hartman <greg@kroah.com>
+
diff --git a/Documentation/translations/zh_TW/process/index.rst b/Documentation/translations/zh_TW/process/index.rst
new file mode 100644
index 000000000000..ec7ad14bfd13
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/index.rst
@@ -0,0 +1,67 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. raw:: latex
+
+	\renewcommand\thesection*
+	\renewcommand\thesubsection*
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/index.rst <process_index>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+.. _tw_process_index:
+
+與Linux 內核社區一起工作
+========================
+
+你想成爲Linux內核開發人員嗎?歡迎之至!在學習許多關於內核的技術知識的同時,
+了解我們社區的工作方式也很重要。閱讀這些文檔可以讓您以更輕鬆的、麻煩更少的
+方式將更改合併到內核。
+
+以下是每位開發人員都應閱讀的基本指南:
+
+.. toctree::
+   :maxdepth: 1
+
+   howto
+   code-of-conduct
+   code-of-conduct-interpretation
+   submitting-patches
+   programming-language
+   coding-style
+   development-process
+   email-clients
+   license-rules
+   kernel-enforcement-statement
+   kernel-driver-statement
+
+其它大多數開發人員感興趣的社區指南:
+
+
+.. toctree::
+   :maxdepth: 1
+
+   submitting-drivers
+   submit-checklist
+   stable-api-nonsense
+   stable-kernel-rules
+   management-style
+   embargoed-hardware-issues
+
+這些是一些總體性技術指南,由於不大好分類而放在這裡:
+
+.. toctree::
+   :maxdepth: 1
+
+   magic-number
+   volatile-considered-harmful
+
+.. only::  subproject and html
+
+   目錄
+   ====
+
+   * :ref:`genindex`
+
diff --git a/Documentation/translations/zh_TW/process/kernel-driver-statement.rst b/Documentation/translations/zh_TW/process/kernel-driver-statement.rst
new file mode 100644
index 000000000000..8f225379b12c
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/kernel-driver-statement.rst
@@ -0,0 +1,203 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _zh_process_statement_driver:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/kernel-driver-statement.rst <process_statement_driver>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+內核驅動聲明
+------------
+
+關於Linux內核模塊的立場聲明
+===========================
+
+我們,以下署名的Linux內核開發人員,認爲任何封閉源Linux內核模塊或驅動程序都是
+有害的和不可取的。我們已經一再發現它們對Linux用戶,企業和更大的Linux生態系統
+有害。這樣的模塊否定了Linux開發模型的開放性,穩定性,靈活性和可維護性,並使
+他們的用戶無法使用Linux社區的專業知識。提供閉源內核模塊的供應商迫使其客戶
+放棄Linux的主要優勢或選擇新的供應商。因此,爲了充分利用開源所提供的成本節省和
+共享支持優勢,我們敦促供應商採取措施,以開源內核代碼在Linux上爲其客戶提供支持。
+
+我們只爲自己說話,而不是我們今天可能會爲之工作,過去或將來會爲之工作的任何公司。
+
+ - Dave Airlie
+ - Nick Andrew
+ - Jens Axboe
+ - Ralf Baechle
+ - Felipe Balbi
+ - Ohad Ben-Cohen
+ - Muli Ben-Yehuda
+ - Jiri Benc
+ - Arnd Bergmann
+ - Thomas Bogendoerfer
+ - Vitaly Bordug
+ - James Bottomley
+ - Josh Boyer
+ - Neil Brown
+ - Mark Brown
+ - David Brownell
+ - Michael Buesch
+ - Franck Bui-Huu
+ - Adrian Bunk
+ - François Cami
+ - Ralph Campbell
+ - Luiz Fernando N. Capitulino
+ - Mauro Carvalho Chehab
+ - Denis Cheng
+ - Jonathan Corbet
+ - Glauber Costa
+ - Alan Cox
+ - Magnus Damm
+ - Ahmed S. Darwish
+ - Robert P. J. Day
+ - Hans de Goede
+ - Arnaldo Carvalho de Melo
+ - Helge Deller
+ - Jean Delvare
+ - Mathieu Desnoyers
+ - Sven-Thorsten Dietrich
+ - Alexey Dobriyan
+ - Daniel Drake
+ - Alex Dubov
+ - Randy Dunlap
+ - Michael Ellerman
+ - Pekka Enberg
+ - Jan Engelhardt
+ - Mark Fasheh
+ - J. Bruce Fields
+ - Larry Finger
+ - Jeremy Fitzhardinge
+ - Mike Frysinger
+ - Kumar Gala
+ - Robin Getz
+ - Liam Girdwood
+ - Jan-Benedict Glaw
+ - Thomas Gleixner
+ - Brice Goglin
+ - Cyrill Gorcunov
+ - Andy Gospodarek
+ - Thomas Graf
+ - Krzysztof Halasa
+ - Harvey Harrison
+ - Stephen Hemminger
+ - Michael Hennerich
+ - Tejun Heo
+ - Benjamin Herrenschmidt
+ - Kristian Høgsberg
+ - Henrique de Moraes Holschuh
+ - Marcel Holtmann
+ - Mike Isely
+ - Takashi Iwai
+ - Olof Johansson
+ - Dave Jones
+ - Jesper Juhl
+ - Matthias Kaehlcke
+ - Kenji Kaneshige
+ - Jan Kara
+ - Jeremy Kerr
+ - Russell King
+ - Olaf Kirch
+ - Roel Kluin
+ - Hans-Jürgen Koch
+ - Auke Kok
+ - Peter Korsgaard
+ - Jiri Kosina
+ - Aaro Koskinen
+ - Mariusz Kozlowski
+ - Greg Kroah-Hartman
+ - Michael Krufky
+ - Aneesh Kumar
+ - Clemens Ladisch
+ - Christoph Lameter
+ - Gunnar Larisch
+ - Anders Larsen
+ - Grant Likely
+ - John W. Linville
+ - Yinghai Lu
+ - Tony Luck
+ - Pavel Machek
+ - Matt Mackall
+ - Paul Mackerras
+ - Roland McGrath
+ - Patrick McHardy
+ - Kyle McMartin
+ - Paul Menage
+ - Thierry Merle
+ - Eric Miao
+ - Akinobu Mita
+ - Ingo Molnar
+ - James Morris
+ - Andrew Morton
+ - Paul Mundt
+ - Oleg Nesterov
+ - Luca Olivetti
+ - S.Çağlar Onur
+ - Pierre Ossman
+ - Keith Owens
+ - Venkatesh Pallipadi
+ - Nick Piggin
+ - Nicolas Pitre
+ - Evgeniy Polyakov
+ - Richard Purdie
+ - Mike Rapoport
+ - Sam Ravnborg
+ - Gerrit Renker
+ - Stefan Richter
+ - David Rientjes
+ - Luis R. Rodriguez
+ - Stefan Roese
+ - Francois Romieu
+ - Rami Rosen
+ - Stephen Rothwell
+ - Maciej W. Rozycki
+ - Mark Salyzyn
+ - Yoshinori Sato
+ - Deepak Saxena
+ - Holger Schurig
+ - Amit Shah
+ - Yoshihiro Shimoda
+ - Sergei Shtylyov
+ - Kay Sievers
+ - Sebastian Siewior
+ - Rik Snel
+ - Jes Sorensen
+ - Alexey Starikovskiy
+ - Alan Stern
+ - Timur Tabi
+ - Hirokazu Takata
+ - Eliezer Tamir
+ - Eugene Teo
+ - Doug Thompson
+ - FUJITA Tomonori
+ - Dmitry Torokhov
+ - Marcelo Tosatti
+ - Steven Toth
+ - Theodore Tso
+ - Matthias Urlichs
+ - Geert Uytterhoeven
+ - Arjan van de Ven
+ - Ivo van Doorn
+ - Rik van Riel
+ - Wim Van Sebroeck
+ - Hans Verkuil
+ - Horst H. von Brand
+ - Dmitri Vorobiev
+ - Anton Vorontsov
+ - Daniel Walker
+ - Johannes Weiner
+ - Harald Welte
+ - Matthew Wilcox
+ - Dan J. Williams
+ - Darrick J. Wong
+ - David Woodhouse
+ - Chris Wright
+ - Bryan Wu
+ - Rafael J. Wysocki
+ - Herbert Xu
+ - Vlad Yasevich
+ - Peter Zijlstra
+ - Bartlomiej Zolnierkiewicz
+
diff --git a/Documentation/translations/zh_TW/process/kernel-enforcement-statement.rst b/Documentation/translations/zh_TW/process/kernel-enforcement-statement.rst
new file mode 100644
index 000000000000..99e21d22800d
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/kernel-enforcement-statement.rst
@@ -0,0 +1,155 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _tw_process_statement_kernel:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/kernel-enforcement-statement.rst <process_statement_kernel>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+Linux 內核執行聲明
+------------------
+
+作爲Linux內核的開發人員,我們對如何使用我們的軟體以及如何實施軟體許可證有著
+濃厚的興趣。遵守GPL-2.0的互惠共享義務對我們軟體和社區的長期可持續性至關重要。
+
+雖然有權強制執行對我們社區的貢獻中的單獨版權權益,但我們有共同的利益,即確保
+個人強制執行行動的方式有利於我們的社區,不會對我們軟體生態系統的健康和增長
+產生意外的負面影響。爲了阻止無益的執法行動,我們同意代表我們自己和我們版權
+利益的任何繼承人對Linux內核用戶作出以下符合我們開發社區最大利益的承諾:
+
+    儘管有GPL-2.0的終止條款,我們同意,採用以下GPL-3.0條款作爲我們許可證下的
+    附加許可,作爲任何對許可證下權利的非防禦性主張,這符合我們開發社區的最佳
+    利益。
+
+        但是,如果您停止所有違反本許可證的行爲,則您從特定版權持有人處獲得的
+        許可證將被恢復:(a)暫時恢復,除非版權持有人明確並最終終止您的許可證;
+        以及(b)永久恢復, 如果版權持有人未能在你終止違反後60天內以合理方式
+        通知您違反本許可證的行爲,則永久恢復您的許可證。
+
+        此外,如果版權所有者以某種合理的方式通知您違反了本許可,這是您第一次
+        從該版權所有者處收到違反本許可的通知(對於任何作品),並且您在收到通知
+        後的30天內糾正違規行爲。則您從特定版權所有者處獲得的許可將永久恢復.
+
+我們提供這些保證的目的是鼓勵更多地使用該軟體。我們希望公司和個人使用、修改和
+分發此軟體。我們希望以公開和透明的方式與用戶合作,以消除我們對法規遵從性或強制
+執行的任何不確定性,這些不確定性可能會限制我們軟體的採用。我們將法律行動視爲
+最後手段,只有在其他社區努力未能解決這一問題時才採取行動。
+
+最後,一旦一個不合規問題得到解決,我們希望用戶會感到歡迎,加入我們爲之努力的
+這個項目。共同努力,我們會更強大。
+
+除了下面提到的以外,我們只爲自己說話,而不是爲今天、過去或將來可能爲之工作的
+任何公司說話。
+
+  - Laura Abbott
+  - Bjorn Andersson (Linaro)
+  - Andrea Arcangeli
+  - Neil Armstrong
+  - Jens Axboe
+  - Pablo Neira Ayuso
+  - Khalid Aziz
+  - Ralf Baechle
+  - Felipe Balbi
+  - Arnd Bergmann
+  - Ard Biesheuvel
+  - Tim Bird
+  - Paolo Bonzini
+  - Christian Borntraeger
+  - Mark Brown (Linaro)
+  - Paul Burton
+  - Javier Martinez Canillas
+  - Rob Clark
+  - Kees Cook (Google)
+  - Jonathan Corbet
+  - Dennis Dalessandro
+  - Vivien Didelot (Savoir-faire Linux)
+  - Hans de Goede
+  - Mel Gorman (SUSE)
+  - Sven Eckelmann
+  - Alex Elder (Linaro)
+  - Fabio Estevam
+  - Larry Finger
+  - Bhumika Goyal
+  - Andy Gross
+  - Juergen Gross
+  - Shawn Guo
+  - Ulf Hansson
+  - Stephen Hemminger (Microsoft)
+  - Tejun Heo
+  - Rob Herring
+  - Masami Hiramatsu
+  - Michal Hocko
+  - Simon Horman
+  - Johan Hovold (Hovold Consulting AB)
+  - Christophe JAILLET
+  - Olof Johansson
+  - Lee Jones (Linaro)
+  - Heiner Kallweit
+  - Srinivas Kandagatla
+  - Jan Kara
+  - Shuah Khan (Samsung)
+  - David Kershner
+  - Jaegeuk Kim
+  - Namhyung Kim
+  - Colin Ian King
+  - Jeff Kirsher
+  - Greg Kroah-Hartman (Linux Foundation)
+  - Christian König
+  - Vinod Koul
+  - Krzysztof Kozlowski
+  - Viresh Kumar
+  - Aneesh Kumar K.V
+  - Julia Lawall
+  - Doug Ledford
+  - Chuck Lever (Oracle)
+  - Daniel Lezcano
+  - Shaohua Li
+  - Xin Long
+  - Tony Luck
+  - Catalin Marinas (Arm Ltd)
+  - Mike Marshall
+  - Chris Mason
+  - Paul E. McKenney
+  - Arnaldo Carvalho de Melo
+  - David S. Miller
+  - Ingo Molnar
+  - Kuninori Morimoto
+  - Trond Myklebust
+  - Martin K. Petersen (Oracle)
+  - Borislav Petkov
+  - Jiri Pirko
+  - Josh Poimboeuf
+  - Sebastian Reichel (Collabora)
+  - Guenter Roeck
+  - Joerg Roedel
+  - Leon Romanovsky
+  - Steven Rostedt (VMware)
+  - Frank Rowand
+  - Ivan Safonov
+  - Anna Schumaker
+  - Jes Sorensen
+  - K.Y. Srinivasan
+  - David Sterba (SUSE)
+  - Heiko Stuebner
+  - Jiri Kosina (SUSE)
+  - Willy Tarreau
+  - Dmitry Torokhov
+  - Linus Torvalds
+  - Thierry Reding
+  - Rik van Riel
+  - Luis R. Rodriguez
+  - Geert Uytterhoeven (Glider bvba)
+  - Eduardo Valentin (Amazon.com)
+  - Daniel Vetter
+  - Linus Walleij
+  - Richard Weinberger
+  - Dan Williams
+  - Rafael J. Wysocki
+  - Arvind Yadav
+  - Masahiro Yamada
+  - Wei Yongjun
+  - Lv Zheng
+  - Marc Zyngier (Arm Ltd)
+
diff --git a/Documentation/translations/zh_TW/process/license-rules.rst b/Documentation/translations/zh_TW/process/license-rules.rst
new file mode 100644
index 000000000000..ad2b80f97123
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/license-rules.rst
@@ -0,0 +1,374 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/license-rules.rst <kernel_licensing>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+.. _tw_kernel_licensing:
+
+Linux內核許可規則
+=================
+
+Linux內核根據LICENSES/preferred/GPL-2.0中提供的GNU通用公共許可證版本2
+(GPL-2.0)的條款提供,並在LICENSES/exceptions/Linux-syscall-note中顯式
+描述了例外的系統調用,如COPYING文件中所述。
+
+此文檔文件提供了如何對每個源文件進行注釋以使其許可證清晰明確的說明。
+它不會取代內核的許可證。
+
+內核原始碼作爲一個整體適用於COPYING文件中描述的許可證,但是單個源文件可以
+具有不同的與GPL-20兼容的許可證::
+
+    GPL-1.0+ : GNU通用公共許可證v1.0或更高版本
+    GPL-2.0+ : GNU通用公共許可證v2.0或更高版本
+    LGPL-2.0 : 僅限GNU庫通用公共許可證v2
+    LGPL-2.0+: GNU 庫通用公共許可證v2或更高版本
+    LGPL-2.1 : 僅限GNU寬通用公共許可證v2.1
+    LGPL-2.1+: GNU寬通用公共許可證v2.1或更高版本
+
+除此之外,個人文件可以在雙重許可下提供,例如一個兼容的GPL變體,或者BSD,
+MIT等許可。
+
+用戶空間API(UAPI)頭文件描述了用戶空間程序與內核的接口,這是一種特殊情況。
+根據內核COPYING文件中的注釋,syscall接口是一個明確的邊界,它不會將GPL要求
+擴展到任何使用它與內核通信的軟體。由於UAPI頭文件必須包含在創建在Linux內核
+上運行的可執行文件的任何源文件中,因此此例外必須記錄在特別的許可證表述中。
+
+表達源文件許可證的常用方法是將匹配的樣板文本添加到文件的頂部注釋中。由於
+格式,拼寫錯誤等,這些「樣板」很難通過那些在上下文中使用的驗證許可證合規性
+的工具。
+
+樣板文本的替代方法是在每個源文件中使用軟體包數據交換(SPDX)許可證標識符。
+SPDX許可證標識符是機器可解析的,並且是用於提供文件內容的許可證的精確縮寫。
+SPDX許可證標識符由Linux 基金會的SPDX 工作組管理,並得到了整個行業,工具
+供應商和法律團隊的合作夥伴的一致同意。有關詳細信息,請參閱
+https://spdx.org/
+
+Linux內核需要所有源文件中的精確SPDX標識符。內核中使用的有效標識符在
+`許可標識符`_ 一節中進行了解釋,並且已可以在
+https://spdx.org/licenses/ 上的官方SPDX許可證列表中檢索,並附帶許可證
+文本。
+
+許可標識符語法
+--------------
+
+1.安置:
+
+   內核文件中的SPDX許可證標識符應添加到可包含注釋的文件中的第一行。對於大多
+   數文件,這是第一行,除了那些在第一行中需要'#!PATH_TO_INTERPRETER'的腳本。
+   對於這些腳本,SPDX標識符進入第二行。
+
+|
+
+2. 風格:
+
+   SPDX許可證標識符以注釋的形式添加。注釋樣式取決於文件類型::
+
+      C source:	// SPDX-License-Identifier: <SPDX License Expression>
+      C header:	/* SPDX-License-Identifier: <SPDX License Expression> */
+      ASM:	/* SPDX-License-Identifier: <SPDX License Expression> */
+      scripts:	# SPDX-License-Identifier: <SPDX License Expression>
+      .rst:	.. SPDX-License-Identifier: <SPDX License Expression>
+      .dts{i}:	// SPDX-License-Identifier: <SPDX License Expression>
+
+   如果特定工具無法處理標準注釋樣式,則應使用工具接受的相應注釋機制。這是在
+   C 頭文件中使用「/\*\*/」樣式注釋的原因。過去在使用生成的.lds文件中觀察到
+   構建被破壞,其中'ld'無法解析C++注釋。現在已經解決了這個問題,但仍然有較
+   舊的彙編程序工具無法處理C++樣式的注釋。
+
+|
+
+3. 句法:
+
+   <SPDX許可證表達式>是SPDX許可證列表中的SPDX短格式許可證標識符,或者在許可
+   證例外適用時由「WITH」分隔的兩個SPDX短格式許可證標識符的組合。當應用多個許
+   可證時,表達式由分隔子表達式的關鍵字「AND」,「OR」組成,並由「(」,「)」包圍。
+
+   帶有「或更高」選項的[L]GPL等許可證的許可證標識符通過使用「+」來表示「或更高」
+   選項來構建。::
+
+      // SPDX-License-Identifier: GPL-2.0+
+      // SPDX-License-Identifier: LGPL-2.1+
+
+   當需要修正的許可證時,應使用WITH。 例如,linux內核UAPI文件使用表達式::
+
+      // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
+      // SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note
+
+   其它在內核中使用WITH例外的事例如下::
+
+      // SPDX-License-Identifier: GPL-2.0 WITH mif-exception
+      // SPDX-License-Identifier: GPL-2.0+ WITH GCC-exception-2.0
+
+   例外只能與特定的許可證標識符一起使用。有效的許可證標識符列在異常文本文件
+   的標記中。有關詳細信息,請參閱 `許可標識符`_ 一章中的 `例外`_ 。
+
+   如果文件是雙重許可且只選擇一個許可證,則應使用OR。例如,一些dtsi文件在雙
+   許可下可用::
+
+      // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+
+   內核中雙許可文件中許可表達式的示例::
+
+      // SPDX-License-Identifier: GPL-2.0 OR MIT
+      // SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+      // SPDX-License-Identifier: GPL-2.0 OR Apache-2.0
+      // SPDX-License-Identifier: GPL-2.0 OR MPL-1.1
+      // SPDX-License-Identifier: (GPL-2.0 WITH Linux-syscall-note) OR MIT
+      // SPDX-License-Identifier: GPL-1.0+ OR BSD-3-Clause OR OpenSSL
+
+   如果文件具有多個許可證,其條款全部適用於使用該文件,則應使用AND。例如,
+   如果代碼是從另一個項目繼承的,並且已經授予了將其放入內核的權限,但原始
+   許可條款需要保持有效::
+
+      // SPDX-License-Identifier: (GPL-2.0 WITH Linux-syscall-note) AND MIT
+
+   另一個需要遵守兩套許可條款的例子是::
+
+      // SPDX-License-Identifier: GPL-1.0+ AND LGPL-2.1+
+
+許可標識符
+----------
+
+當前使用的許可證以及添加到內核的代碼許可證可以分解爲:
+
+1. _`優先許可`:
+
+   應儘可能使用這些許可證,因爲它們已知完全兼容並廣泛使用。這些許可證在內核
+   目錄::
+
+      LICENSES/preferred/
+
+   此目錄中的文件包含完整的許可證文本和 `元標記`_ 。文件名與SPDX許可證標識
+   符相同,後者應用於源文件中的許可證。
+
+   例如::
+
+      LICENSES/preferred/GPL-2.0
+
+   包含GPLv2許可證文本和所需的元標籤::
+
+      LICENSES/preferred/MIT
+
+   包含MIT許可證文本和所需的元標記
+
+   _`元標記`:
+
+   許可證文件中必須包含以下元標記:
+
+   - Valid-License-Identifier:
+
+     一行或多行, 聲明那些許可標識符在項目內有效, 以引用此特定許可的文本。通
+     常這是一個有效的標識符,但是例如對於帶有'或更高'選項的許可證,兩個標識
+     符都有效。
+
+   - SPDX-URL:
+
+     SPDX頁面的URL,其中包含與許可證相關的其他信息.
+
+   - Usage-Guidance:
+
+     使用建議的自由格式文本。該文本必須包含SPDX許可證標識符的正確示例,因爲
+     它們應根據 `許可標識符語法`_ 指南放入源文件中。
+
+   - License-Text:
+
+     此標記之後的所有文本都被視爲原始許可文本
+
+   文件格式示例::
+
+      Valid-License-Identifier: GPL-2.0
+      Valid-License-Identifier: GPL-2.0+
+      SPDX-URL: https://spdx.org/licenses/GPL-2.0.html
+      Usage-Guide:
+        To use this license in source code, put one of the following SPDX
+	tag/value pairs into a comment according to the placement
+	guidelines in the licensing rules documentation.
+	For 'GNU General Public License (GPL) version 2 only' use:
+	  SPDX-License-Identifier: GPL-2.0
+	For 'GNU General Public License (GPL) version 2 or any later version' use:
+	  SPDX-License-Identifier: GPL-2.0+
+      License-Text:
+        Full license text
+
+   ::
+
+      SPDX-License-Identifier: MIT
+      SPDX-URL: https://spdx.org/licenses/MIT.html
+      Usage-Guide:
+	To use this license in source code, put the following SPDX
+	tag/value pair into a comment according to the placement
+	guidelines in the licensing rules documentation.
+	  SPDX-License-Identifier: MIT
+      License-Text:
+        Full license text
+
+|
+
+2. 不推薦的許可證:
+
+   這些許可證只應用於現有代碼或從其他項目導入代碼。這些許可證在內核目錄::
+
+      LICENSES/other/
+
+   此目錄中的文件包含完整的許可證文本和 `元標記`_ 。文件名與SPDX許可證標識
+   符相同,後者應用於源文件中的許可證。
+
+   例如::
+
+      LICENSES/other/ISC
+
+   包含國際系統聯合許可文本和所需的元標籤::
+
+      LICENSES/other/ZLib
+
+   包含ZLIB許可文本和所需的元標籤.
+
+   元標籤:
+
+   「其他」許可證的元標籤要求與 `優先許可`_ 的要求相同。
+
+   文件格式示例::
+
+      Valid-License-Identifier: ISC
+      SPDX-URL: https://spdx.org/licenses/ISC.html
+      Usage-Guide:
+        Usage of this license in the kernel for new code is discouraged
+	and it should solely be used for importing code from an already
+	existing project.
+        To use this license in source code, put the following SPDX
+	tag/value pair into a comment according to the placement
+	guidelines in the licensing rules documentation.
+	  SPDX-License-Identifier: ISC
+      License-Text:
+        Full license text
+
+|
+
+3. _`例外`:
+
+   某些許可證可以修改,並允許原始許可證不具有的某些例外權利。這些例外在
+   內核目錄::
+
+      LICENSES/exceptions/
+
+   此目錄中的文件包含完整的例外文本和所需的 `例外元標記`_ 。
+
+   例如::
+
+      LICENSES/exceptions/Linux-syscall-note
+
+   包含Linux內核的COPYING文件中記錄的Linux系統調用例外,該文件用於UAPI
+   頭文件。例如::
+
+      LICENSES/exceptions/GCC-exception-2.0
+
+   包含GCC'連結例外',它允許獨立於其許可證的任何二進位文件與標記有此例外的
+   文件的編譯版本連結。這是從GPL不兼容原始碼創建可運行的可執行文件所必需的。
+
+   _`例外元標記`:
+
+   以下元標記必須在例外文件中可用:
+
+   - SPDX-Exception-Identifier:
+
+     一個可與SPDX許可證標識符一起使用的例外標識符。
+
+   - SPDX-URL:
+
+     SPDX頁面的URL,其中包含與例外相關的其他信息。
+
+   - SPDX-Licenses:
+
+     以逗號分隔的例外可用的SPDX許可證標識符列表。
+
+   - Usage-Guidance:
+
+     使用建議的自由格式文本。必須在文本後面加上SPDX許可證標識符的正確示例,
+     因爲它們應根據 `許可標識符語法`_ 指南放入源文件中。
+
+   - Exception-Text:
+
+     此標記之後的所有文本都被視爲原始異常文本
+
+   文件格式示例::
+
+      SPDX-Exception-Identifier: Linux-syscall-note
+      SPDX-URL: https://spdx.org/licenses/Linux-syscall-note.html
+      SPDX-Licenses: GPL-2.0, GPL-2.0+, GPL-1.0+, LGPL-2.0, LGPL-2.0+, LGPL-2.1, LGPL-2.1+
+      Usage-Guidance:
+        This exception is used together with one of the above SPDX-Licenses
+	to mark user-space API (uapi) header files so they can be included
+	into non GPL compliant user-space application code.
+        To use this exception add it with the keyword WITH to one of the
+	identifiers in the SPDX-Licenses tag:
+	  SPDX-License-Identifier: <SPDX-License> WITH Linux-syscall-note
+      Exception-Text:
+        Full exception text
+
+   ::
+
+      SPDX-Exception-Identifier: GCC-exception-2.0
+      SPDX-URL: https://spdx.org/licenses/GCC-exception-2.0.html
+      SPDX-Licenses: GPL-2.0, GPL-2.0+
+      Usage-Guidance:
+        The "GCC Runtime Library exception 2.0" is used together with one
+	of the above SPDX-Licenses for code imported from the GCC runtime
+	library.
+        To use this exception add it with the keyword WITH to one of the
+	identifiers in the SPDX-Licenses tag:
+	  SPDX-License-Identifier: <SPDX-License> WITH GCC-exception-2.0
+      Exception-Text:
+        Full exception text
+
+
+所有SPDX許可證標識符和例外都必須在LICENSES子目錄中具有相應的文件。這是允許
+工具驗證(例如checkpatch.pl)以及準備好從源讀取和提取許可證所必需的, 這是
+各種FOSS組織推薦的,例如 `FSFE REUSE initiative <https://reuse.software/>`_.
+
+_`模塊許可`
+-----------------
+
+   可加載內核模塊還需要MODULE_LICENSE()標記。此標記既不替代正確的原始碼
+   許可證信息(SPDX-License-Identifier),也不以任何方式表示或確定提供模塊
+   原始碼的確切許可證。
+
+   此標記的唯一目的是提供足夠的信息,該模塊是否是自由軟體或者是內核模塊加
+   載器和用戶空間工具的專有模塊。
+
+   MODULE_LICENSE()的有效許可證字符串是:
+
+    ============================= =============================================
+    "GPL"			  模塊是根據GPL版本2許可的。這並不表示僅限於
+                                  GPL-2.0或GPL-2.0或更高版本之間的任何區別。
+                                  最正確許可證信息只能通過相應源文件中的許可證
+                                  信息來確定
+
+    "GPL v2"			  和"GPL"相同,它的存在是因爲歷史原因。
+
+    "GPL and additional rights"   表示模塊源在GPL v2變體和MIT許可下雙重許可的
+                                  歷史變體。請不要在新代碼中使用。
+
+    "Dual MIT/GPL"		  表達該模塊在GPL v2變體或MIT許可證選擇下雙重
+                                  許可的正確方式。
+
+    "Dual BSD/GPL"		  該模塊根據GPL v2變體或BSD許可證選擇進行雙重
+                                  許可。 BSD許可證的確切變體只能通過相應源文件
+                                  中的許可證信息來確定。
+
+    "Dual MPL/GPL"		  該模塊根據GPL v2變體或Mozilla Public License
+                                  (MPL)選項進行雙重許可。 MPL許可證的確切變體
+                                  只能通過相應的源文件中的許可證信息來確定。
+
+    "Proprietary"		  該模塊屬於專有許可。此字符串僅用於專有的第三
+                                  方模塊,不能用於在內核樹中具有原始碼的模塊。
+                                  以這種方式標記的模塊在加載時會使用'P'標記汙
+                                  染內核,並且內核模塊加載器拒絕將這些模塊連結
+                                  到使用EXPORT_SYMBOL_GPL()導出的符號。
+    ============================= =============================================
+
+
diff --git a/Documentation/translations/zh_TW/process/magic-number.rst b/Documentation/translations/zh_TW/process/magic-number.rst
new file mode 100644
index 000000000000..ae321a9aaece
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/magic-number.rst
@@ -0,0 +1,148 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _tw_magicnumbers:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/magic-number.rst <magicnumbers>`
+
+如果想評論或更新本文的內容,請直接發信到LKML。如果你使用英文交流有困難的話,也可
+以向中文版維護者求助。如果本翻譯更新不及時或者翻譯存在問題,請聯繫中文版維護者::
+
+        中文版維護者: 賈威威 Jia Wei Wei <harryxiyou@gmail.com>
+        中文版翻譯者: 賈威威 Jia Wei Wei <harryxiyou@gmail.com>
+        中文版校譯者: 賈威威 Jia Wei Wei <harryxiyou@gmail.com>
+                      胡皓文 Hu Haowen <src.res@email.cn>
+
+Linux 魔術數
+============
+
+這個文件是有關當前使用的魔術值註冊表。當你給一個結構添加了一個魔術值,你也應該把這個魔術值添加到這個文件,因爲我們最好把用於各種結構的魔術值統一起來。
+
+使用魔術值來保護內核數據結構是一個非常好的主意。這就允許你在運行期檢查(a)一個結構是否已經被攻擊,或者(b)你已經給一個例行程序通過了一個錯誤的結構。後一種情況特別地有用---特別是當你通過一個空指針指向結構體的時候。tty源碼,例如,經常通過特定驅動使用這種方法並且反覆地排列特定方面的結構。
+
+使用魔術值的方法是在結構的開始處聲明的,如下::
+
+        struct tty_ldisc {
+	        int	magic;
+        	...
+        };
+
+當你以後給內核添加增強功能的時候,請遵守這條規則!這樣就會節省數不清的調試時間,特別是一些古怪的情況,例如,數組超出範圍並且重新寫了超出部分。遵守這個規則,‪這些情況可以被快速地,安全地避免。
+
+		Theodore Ts'o
+		  31 Mar 94
+
+給當前的Linux 2.1.55添加魔術表。
+
+		Michael Chastain
+		<mailto:mec@shout.net>
+		22 Sep 1997
+
+現在應該最新的Linux 2.1.112.因爲在特性凍結期間,不能在2.2.x前改變任何東西。這些條目被數域所排序。
+
+		Krzysztof G.Baranowski
+	        <mailto: kgb@knm.org.pl>
+		29 Jul 1998
+
+更新魔術表到Linux 2.5.45。剛好越過特性凍結,但是有可能還會有一些新的魔術值在2.6.x之前融入到內核中。
+
+		Petr Baudis
+		<pasky@ucw.cz>
+		03 Nov 2002
+
+更新魔術表到Linux 2.5.74。
+
+		Fabian Frederick
+                <ffrederick@users.sourceforge.net>
+		09 Jul 2003
+
+===================== ================ ======================== ==========================================
+魔術數名              數字             結構                     文件
+===================== ================ ======================== ==========================================
+PG_MAGIC              'P'              pg_{read,write}_hdr      ``include/linux/pg.h``
+CMAGIC                0x0111           user                     ``include/linux/a.out.h``
+MKISS_DRIVER_MAGIC    0x04bf           mkiss_channel            ``drivers/net/mkiss.h``
+HDLC_MAGIC            0x239e           n_hdlc                   ``drivers/char/n_hdlc.c``
+APM_BIOS_MAGIC        0x4101           apm_user                 ``arch/x86/kernel/apm_32.c``
+DB_MAGIC              0x4442           fc_info                  ``drivers/net/iph5526_novram.c``
+DL_MAGIC              0x444d           fc_info                  ``drivers/net/iph5526_novram.c``
+FASYNC_MAGIC          0x4601           fasync_struct            ``include/linux/fs.h``
+FF_MAGIC              0x4646           fc_info                  ``drivers/net/iph5526_novram.c``
+PTY_MAGIC             0x5001                                    ``drivers/char/pty.c``
+PPP_MAGIC             0x5002           ppp                      ``include/linux/if_pppvar.h``
+SSTATE_MAGIC          0x5302           serial_state             ``include/linux/serial.h``
+SLIP_MAGIC            0x5302           slip                     ``drivers/net/slip.h``
+STRIP_MAGIC           0x5303           strip                    ``drivers/net/strip.c``
+SIXPACK_MAGIC         0x5304           sixpack                  ``drivers/net/hamradio/6pack.h``
+AX25_MAGIC            0x5316           ax_disp                  ``drivers/net/mkiss.h``
+TTY_MAGIC             0x5401           tty_struct               ``include/linux/tty.h``
+MGSL_MAGIC            0x5401           mgsl_info                ``drivers/char/synclink.c``
+TTY_DRIVER_MAGIC      0x5402           tty_driver               ``include/linux/tty_driver.h``
+MGSLPC_MAGIC          0x5402           mgslpc_info              ``drivers/char/pcmcia/synclink_cs.c``
+USB_SERIAL_MAGIC      0x6702           usb_serial               ``drivers/usb/serial/usb-serial.h``
+FULL_DUPLEX_MAGIC     0x6969                                    ``drivers/net/ethernet/dec/tulip/de2104x.c``
+USB_BLUETOOTH_MAGIC   0x6d02           usb_bluetooth            ``drivers/usb/class/bluetty.c``
+RFCOMM_TTY_MAGIC      0x6d02                                    ``net/bluetooth/rfcomm/tty.c``
+USB_SERIAL_PORT_MAGIC 0x7301           usb_serial_port          ``drivers/usb/serial/usb-serial.h``
+CG_MAGIC              0x00090255       ufs_cylinder_group       ``include/linux/ufs_fs.h``
+LSEMAGIC              0x05091998       lse                      ``drivers/fc4/fc.c``
+GDTIOCTL_MAGIC        0x06030f07       gdth_iowr_str            ``drivers/scsi/gdth_ioctl.h``
+RIEBL_MAGIC           0x09051990                                ``drivers/net/atarilance.c``
+NBD_REQUEST_MAGIC     0x12560953       nbd_request              ``include/linux/nbd.h``
+RED_MAGIC2            0x170fc2a5       (any)                    ``mm/slab.c``
+BAYCOM_MAGIC          0x19730510       baycom_state             ``drivers/net/baycom_epp.c``
+ISDN_X25IFACE_MAGIC   0x1e75a2b9       isdn_x25iface_proto_data ``drivers/isdn/isdn_x25iface.h``
+ECP_MAGIC             0x21504345       cdkecpsig                ``include/linux/cdk.h``
+LSOMAGIC              0x27091997       lso                      ``drivers/fc4/fc.c``
+LSMAGIC               0x2a3b4d2a       ls                       ``drivers/fc4/fc.c``
+WANPIPE_MAGIC         0x414C4453       sdla_{dump,exec}         ``include/linux/wanpipe.h``
+CS_CARD_MAGIC         0x43525553       cs_card                  ``sound/oss/cs46xx.c``
+LABELCL_MAGIC         0x4857434c       labelcl_info_s           ``include/asm/ia64/sn/labelcl.h``
+ISDN_ASYNC_MAGIC      0x49344C01       modem_info               ``include/linux/isdn.h``
+CTC_ASYNC_MAGIC       0x49344C01       ctc_tty_info             ``drivers/s390/net/ctctty.c``
+ISDN_NET_MAGIC        0x49344C02       isdn_net_local_s         ``drivers/isdn/i4l/isdn_net_lib.h``
+SAVEKMSG_MAGIC2       0x4B4D5347       savekmsg                 ``arch/*/amiga/config.c``
+CS_STATE_MAGIC        0x4c4f4749       cs_state                 ``sound/oss/cs46xx.c``
+SLAB_C_MAGIC          0x4f17a36d       kmem_cache               ``mm/slab.c``
+COW_MAGIC             0x4f4f4f4d       cow_header_v1            ``arch/um/drivers/ubd_user.c``
+I810_CARD_MAGIC       0x5072696E       i810_card                ``sound/oss/i810_audio.c``
+TRIDENT_CARD_MAGIC    0x5072696E       trident_card             ``sound/oss/trident.c``
+ROUTER_MAGIC          0x524d4157       wan_device               [in ``wanrouter.h`` pre 3.9]
+SAVEKMSG_MAGIC1       0x53415645       savekmsg                 ``arch/*/amiga/config.c``
+GDA_MAGIC             0x58464552       gda                      ``arch/mips/include/asm/sn/gda.h``
+RED_MAGIC1            0x5a2cf071       (any)                    ``mm/slab.c``
+EEPROM_MAGIC_VALUE    0x5ab478d2       lanai_dev                ``drivers/atm/lanai.c``
+HDLCDRV_MAGIC         0x5ac6e778       hdlcdrv_state            ``include/linux/hdlcdrv.h``
+PCXX_MAGIC            0x5c6df104       channel                  ``drivers/char/pcxx.h``
+KV_MAGIC              0x5f4b565f       kernel_vars_s            ``arch/mips/include/asm/sn/klkernvars.h``
+I810_STATE_MAGIC      0x63657373       i810_state               ``sound/oss/i810_audio.c``
+TRIDENT_STATE_MAGIC   0x63657373       trient_state             ``sound/oss/trident.c``
+M3_CARD_MAGIC         0x646e6f50       m3_card                  ``sound/oss/maestro3.c``
+FW_HEADER_MAGIC       0x65726F66       fw_header                ``drivers/atm/fore200e.h``
+SLOT_MAGIC            0x67267321       slot                     ``drivers/hotplug/cpqphp.h``
+SLOT_MAGIC            0x67267322       slot                     ``drivers/hotplug/acpiphp.h``
+LO_MAGIC              0x68797548       nbd_device               ``include/linux/nbd.h``
+M3_STATE_MAGIC        0x734d724d       m3_state                 ``sound/oss/maestro3.c``
+VMALLOC_MAGIC         0x87654320       snd_alloc_track          ``sound/core/memory.c``
+KMALLOC_MAGIC         0x87654321       snd_alloc_track          ``sound/core/memory.c``
+PWC_MAGIC             0x89DC10AB       pwc_device               ``drivers/usb/media/pwc.h``
+NBD_REPLY_MAGIC       0x96744668       nbd_reply                ``include/linux/nbd.h``
+ENI155_MAGIC          0xa54b872d       midway_eprom	        ``drivers/atm/eni.h``
+CODA_MAGIC            0xC0DAC0DA       coda_file_info           ``fs/coda/coda_fs_i.h``
+DPMEM_MAGIC           0xc0ffee11       gdt_pci_sram             ``drivers/scsi/gdth.h``
+YAM_MAGIC             0xF10A7654       yam_port                 ``drivers/net/hamradio/yam.c``
+CCB_MAGIC             0xf2691ad2       ccb                      ``drivers/scsi/ncr53c8xx.c``
+QUEUE_MAGIC_FREE      0xf7e1c9a3       queue_entry              ``drivers/scsi/arm/queue.c``
+QUEUE_MAGIC_USED      0xf7e1cc33       queue_entry              ``drivers/scsi/arm/queue.c``
+HTB_CMAGIC            0xFEFAFEF1       htb_class                ``net/sched/sch_htb.c``
+NMI_MAGIC             0x48414d4d455201 nmi_s                    ``arch/mips/include/asm/sn/nmi.h``
+===================== ================ ======================== ==========================================
+
+
+請注意,在聲音記憶管理中仍然有一些特殊的爲每個驅動定義的魔術值。查看include/sound/sndmagic.h來獲取他們完整的列表信息。很多OSS聲音驅動擁有自己從音效卡PCI ID構建的魔術值-他們也沒有被列在這裡。
+
+IrDA子系統也使用了大量的自己的魔術值,查看include/net/irda/irda.h來獲取他們完整的信息。
+
+HFS是另外一個比較大的使用魔術值的文件系統-你可以在fs/hfs/hfs.h中找到他們。
+
diff --git a/Documentation/translations/zh_TW/process/management-style.rst b/Documentation/translations/zh_TW/process/management-style.rst
new file mode 100644
index 000000000000..dce248470063
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/management-style.rst
@@ -0,0 +1,211 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/management-style.rst <managementstyle>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+.. _tw_managementstyle:
+
+Linux內核管理風格
+=================
+
+這是一個簡短的文檔,描述了Linux內核首選的(或胡編的,取決於您問誰)管理風格。
+它的目的是在某種程度上參照 :ref:`process/coding-style.rst <codingstyle>`
+主要是爲了避免反覆回答 [#cnf1]_ 相同(或類似)的問題。
+
+管理風格是非常個人化的,比簡單的編碼風格規則更難以量化,因此本文檔可能與實
+際情況有關,也可能與實際情況無關。起初它是一個玩笑,但這並不意味著它可能不
+是真的。你得自己決定。
+
+順便說一句,在談到「核心管理者」時,主要是技術負責人,而不是在公司內部進行傳
+統管理的人。如果你簽署了採購訂單或者對你的團隊的預算有任何了解,你幾乎肯定
+不是一個核心管理者。這些建議可能適用於您,也可能不適用於您。
+
+首先,我建議你購買「高效人的七個習慣」,而不是閱讀它。燒了它,這是一個偉大的
+象徵性姿態。
+
+.. [#cnf1] 本文件並不是通過回答問題,而是通過讓提問者痛苦地明白,我們不知道
+   答案是什麼。
+
+不管怎樣,這裡是:
+
+.. _tw_decisions:
+
+1)決策
+-------
+
+每個人都認爲管理者做決定,而且決策很重要。決定越大越痛苦,管理者就必須越高級。
+這很明顯,但事實並非如此。
+
+遊戲的名字是 **避免** 做出決定。尤其是,如果有人告訴你「選擇(a)或(b),
+我們真的需要你來做決定」,你就是陷入麻煩的管理者。你管理的人比你更了解細節,
+所以如果他們來找你做技術決策,你完蛋了。你顯然沒有能力爲他們做這個決定。
+
+(推論:如果你管理的人不比你更了解細節,你也會被搞砸,儘管原因完全不同。
+也就是說,你的工作是錯的,他們應該管理你的才智)
+
+所以遊戲的名字是 **避免** 做出決定,至少是那些大而痛苦的決定。做一些小的
+和非結果性的決定是很好的,並且使您看起來好像知道自己在做什麼,所以內核管理者
+需要做的是將那些大的和痛苦的決定變成那些沒有人真正關心的小事情。
+
+這有助於認識到一個大的決定和一個小的決定之間的關鍵區別是你是否可以在事後修正
+你的決定。任何決定都可以通過始終確保如果你錯了(而且你一定會錯),你以後總是
+可以通過回溯來彌補損失。突然間,你就要做兩個無關緊要的決定,一個是錯誤的,另
+一個是正確的。
+
+人們甚至會認爲這是真正的領導能力(咳,胡說,咳)。
+
+因此,避免重大決策的關鍵在於避免做那些無法挽回的事情。不要被引導到一個你無法
+逃離的角落。走投無路的老鼠可能很危險——走投無路的管理者真可憐。
+
+事實證明,由於沒有人會愚蠢到讓內核管理者承擔巨大的財政責任,所以通常很容易
+回溯。既然你不可能浪費掉你無法償還的巨額資金,你唯一可以回溯的就是技術決策,
+而回溯很容易:只要告訴大家你是個不稱職的傻瓜,說對不起,然後撤銷你去年讓別
+人所做的毫無價值的工作。突然間,你一年前做的決定不在是一個重大的決定,因爲
+它很容易被推翻。
+
+事實證明,有些人對接受這種方法有困難,原因有兩個:
+
+ - 承認你是個白癡比看起來更難。我們都喜歡保持形象,在公共場合說你錯了有時
+   確實很難。
+ - 如果有人告訴你,你去年所做的工作終究是不值得的,那麼對那些可憐的低級工
+   程師來說也是很困難的,雖然實際的 **工作** 很容易刪除,但你可能已經不可
+   挽回地失去了工程師的信任。記住:「不可撤銷」是我們一開始就試圖避免的,
+   而你的決定終究是一個重大的決定。
+
+令人欣慰的是,這兩個原因都可以通過預先承認你沒有任何線索,提前告訴人們你的
+決定完全是初步的,而且可能是錯誤的事情來有效地緩解。你應該始終保留改變主意
+的權利,並讓人們 **意識** 到這一點。當你 **還沒有** 做過真正愚蠢的事情的時
+候,承認自己是愚蠢的要容易得多。
+
+然後,當它真的被證明是愚蠢的時候,人們就轉動他們的眼珠說「哎呀,下次不要了」。
+
+這種對不稱職的先發制人的承認,也可能使真正做這項工作的人也會三思是否值得做。
+畢竟,如果他們不確定這是否是一個好主意,你肯定不應該通過向他們保證他們所做
+的工作將會進入(內核)鼓勵他們。在他們開始一項巨大的努力之前,至少讓他們三
+思而後行。
+
+記住:他們最好比你更了解細節,而且他們通常認爲他們對每件事都有答案。作爲一
+個管理者,你能做的最好的事情不是灌輸自信,而是對他們所做的事情進行健康的批
+判性思考。
+
+順便說一句,另一種避免做出決定的方法是看起來很可憐的抱怨 「我們不能兩者兼
+得嗎?」 相信我,它是有效的。如果不清楚哪種方法更好,他們最終會弄清楚的。
+最終的答案可能是兩個團隊都會因爲這種情況而感到沮喪,以至於他們放棄了。
+
+這聽起來像是一個失敗,但這通常是一個跡象,表明兩個項目都有問題,而參與其中
+的人不能做決定的原因是他們都是錯誤的。你最終會聞到玫瑰的味道,你避免了另一
+個你本可以搞砸的決定。
+
+2)人
+-----
+
+大多數人都是白癡,做一名管理者意味著你必須處理好這件事,也許更重要的是,
+**他們** 必須處理好你。
+
+事實證明,雖然很容易糾正技術錯誤,但不容易糾正人格障礙。你只能和他們的和
+你的(人格障礙)共處。
+
+但是,爲了做好作爲內核管理者的準備,最好記住不要燒掉任何橋樑,不要轟炸任何
+無辜的村民,也不要疏遠太多的內核開發人員。事實證明,疏遠人是相當容易的,而
+親近一個疏遠的人是很難的。因此,「疏遠」立即屬於「不可逆」的範疇,並根據
+:ref:`tw_decisions` 成爲絕不可以做的事情。
+
+這裡只有幾個簡單的規則:
+
+ (1) 不要叫人笨蛋(至少不要在公共場合)
+ (2) 學習如何在忘記規則(1)時道歉
+
+問題在於 #1 很容易去做,因爲你可以用數百萬種不同的方式說「你是一個笨蛋」 [#cnf2]_
+有時甚至沒有意識到,而且幾乎總是帶著一種白熱化的信念,認爲你是對的。
+
+你越確信自己是對的(讓我們面對現實吧,你可以把幾乎所有人都稱爲壞人,而且你
+經常是對的),事後道歉就越難。
+
+要解決此問題,您實際上只有兩個選項:
+
+ - 非常擅長道歉
+ - 把「愛」均勻地散開,沒有人會真正感覺到自己被不公平地瞄準了。讓它有足夠的
+   創造性,他們甚至可能會覺得好笑。
+
+選擇永遠保持禮貌是不存在的。沒有人會相信一個如此明顯地隱藏了他們真實性格的人。
+
+.. [#cnf2] 保羅·西蒙演唱了「離開愛人的50種方法」,因爲坦率地說,「告訴開發者
+   他們是D*CKHEAD" 的100萬種方法都無法確認。但我確信他已經這麼想了。
+
+3)人2 - 好人
+-------------
+
+雖然大多數人都是白癡,但不幸的是,據此推論你也是白癡,儘管我們都自我感覺良
+好,我們比普通人更好(讓我們面對現實吧,沒有人相信他們是普通人或低於普通人),
+我們也應該承認我們不是最鋒利的刀,而且會有其他人比你更不像白癡。
+
+有些人對聰明人反應不好。其他人利用它們。
+
+作爲內核維護人員,確保您在第二組中。接受他們,因爲他們會讓你的工作更容易。
+特別是,他們能夠爲你做決定,這就是遊戲的全部內容。
+
+所以當你發現一個比你聰明的人時,就順其自然吧。你的管理職責在很大程度上變成
+了「聽起來像是個好主意——去嘗試吧」,或者「聽起來不錯,但是XXX呢?」「。第二個版
+本尤其是一個很好的方法,要麼學習一些關於「XXX」的新東西,要麼通過指出一些聰明
+人沒有想到的東西來顯得更具管理性。無論哪種情況,你都會贏。
+
+要注意的一件事是認識到一個領域的偉大不一定會轉化爲其他領域。所以你可能會向
+特定的方向刺激人們,但讓我們面對現實吧,他們可能擅長他們所做的事情,而且對
+其他事情都很差勁。好消息是,人們往往會自然而然地重拾他們擅長的東西,所以當
+你向某個方向刺激他們時,你並不是在做不可逆轉的事情,只是不要用力推。
+
+4)責備
+-------
+
+事情會出問題的,人們希望去責備人。貼標籤,你就是受責備的人。
+
+事實上,接受責備並不難,尤其是當人們意識到這不 **全是** 你的過錯時。這讓我
+們找到了承擔責任的最佳方式:爲別人承擔這件事。你會感覺很好,他們會感覺很好,
+沒有受到指責. 那誰,失去了他們的全部36GB色情收藏的人,因爲你的無能將勉強承
+認,你至少沒有試圖逃避責任。
+
+然後讓真正搞砸了的開發人員(如果你能找到他們)私下知道他們搞砸了。不僅是爲
+了將來可以避免,而且爲了讓他們知道他們欠你一個人情。而且,也許更重要的是,
+他們也可能是能夠解決問題的人。因爲,讓我們面對現實吧,肯定不是你。
+
+承擔責任也是你首先成爲管理者的原因。這是讓人們信任你,讓你獲得潛在的榮耀的
+一部分,因爲你就是那個會說「我搞砸了」的人。如果你已經遵循了以前的規則,你現
+在已經很擅長說了。
+
+5)應避免的事情
+---------------
+
+有一件事人們甚至比被稱爲「笨蛋」更討厭,那就是在一個神聖的聲音中被稱爲「笨蛋」。
+第一個你可以道歉,第二個你不會真正得到機會。即使你做得很好,他們也可能不再
+傾聽。
+
+我們都認爲自己比別人強,這意味著當別人裝腔作勢時,這會讓我們很惱火。你也許
+在道德和智力上比你周圍的每個人都優越,但不要試圖太明顯,除非你真的打算激怒
+某人 [#cnf3]_
+
+同樣,不要對事情太客氣或太微妙。禮貌很容易落得落花流水,把問題隱藏起來,
+正如他們所說,「在網際網路上,沒人能聽到你的含蓄。」用一個鈍器把這一點錘進去,
+因爲你不能真的依靠別人來獲得你的觀點。
+
+一些幽默可以幫助緩和直率和道德化。過度到荒謬的地步,可以灌輸一個觀點,而不
+會讓接受者感到痛苦,他們只是認爲你是愚蠢的。因此,它可以幫助我們擺脫對批評
+的個人心理障礙。
+
+.. [#cnf3] 提示:與你的工作沒有直接關係的網絡新聞組是消除你對他人不滿的好
+   方法。偶爾寫些侮辱性的帖子,打個噴嚏,讓你的情緒得到淨化。別把牢騷帶回家
+
+6)爲什麼是我?
+---------------
+
+既然你的主要責任似乎是爲別人的錯誤承擔責任,並且讓別人痛苦地明白你是不稱職
+的,那麼顯而易見的問題之一就變成了爲什麼首先要這樣做。
+
+首先,雖然你可能會或可能不會聽到十幾歲女孩(或男孩,讓我們不要在這裡評判或
+性別歧視)敲你的更衣室門,你會得到一個巨大的個人成就感爲「負責」。別介意你真
+的在領導別人,你要跟上別人,儘可能快地追趕他們。每個人都會認爲你是負責人。
+
+如果你可以做到這個, 這是個偉大的工作!
+
diff --git a/Documentation/translations/zh_TW/process/programming-language.rst b/Documentation/translations/zh_TW/process/programming-language.rst
new file mode 100644
index 000000000000..54e3699eadf8
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/programming-language.rst
@@ -0,0 +1,76 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/programming-language.rst <programming_language>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+.. _tw_programming_language:
+
+程序設計語言
+============
+
+內核是用C語言 :ref:`c-language <tw_c-language>` 編寫的。更準確地說,內核通常是用 :ref:`gcc <tw_gcc>`
+在 ``-std=gnu89`` :ref:`gcc-c-dialect-options <tw_gcc-c-dialect-options>` 下編譯的:ISO C90的 GNU 方言(
+包括一些C99特性)
+
+這種方言包含對語言 :ref:`gnu-extensions <tw_gnu-extensions>` 的許多擴展,當然,它們許多都在內核中使用。
+
+對於一些體系結構,有一些使用 :ref:`clang <tw_clang>` 和 :ref:`icc <tw_icc>` 編譯內核
+的支持,儘管在編寫此文檔時還沒有完成,仍需要第三方補丁。
+
+屬性
+----
+
+在整個內核中使用的一個常見擴展是屬性(attributes) :ref:`gcc-attribute-syntax <tw_gcc-attribute-syntax>`
+屬性允許將實現定義的語義引入語言實體(如變量、函數或類型),而無需對語言進行
+重大的語法更改(例如添加新關鍵字) :ref:`n2049 <tw_n2049>`
+
+在某些情況下,屬性是可選的(即不支持這些屬性的編譯器仍然應該生成正確的代碼,
+即使其速度較慢或執行的編譯時檢查/診斷次數不夠)
+
+內核定義了僞關鍵字(例如, ``pure`` ),而不是直接使用GNU屬性語法(例如,
+``__attribute__((__pure__))`` ),以檢測可以使用哪些關鍵字和/或縮短代碼, 具體
+請參閱 ``include/linux/compiler_attributes.h``
+
+.. _tw_c-language:
+
+c-language
+   http://www.open-std.org/jtc1/sc22/wg14/www/standards
+
+.. _tw_gcc:
+
+gcc
+   https://gcc.gnu.org
+
+.. _tw_clang:
+
+clang
+   https://clang.llvm.org
+
+.. _tw_icc:
+
+icc
+   https://software.intel.com/en-us/c-compilers
+
+.. _tw_gcc-c-dialect-options:
+
+c-dialect-options
+   https://gcc.gnu.org/onlinedocs/gcc/C-Dialect-Options.html
+
+.. _tw_gnu-extensions:
+
+gnu-extensions
+   https://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html
+
+.. _tw_gcc-attribute-syntax:
+
+gcc-attribute-syntax
+   https://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html
+
+.. _tw_n2049:
+
+n2049
+   http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2049.pdf
+
diff --git a/Documentation/translations/zh_TW/process/stable-api-nonsense.rst b/Documentation/translations/zh_TW/process/stable-api-nonsense.rst
new file mode 100644
index 000000000000..22caa5b8d422
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/stable-api-nonsense.rst
@@ -0,0 +1,159 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _tw_stable_api_nonsense:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/stable-api-nonsense.rst
+           <stable_api_nonsense>`
+
+譯者::
+
+        中文版維護者: 鍾宇  TripleX Chung <xxx.phy@gmail.com>
+        中文版翻譯者: 鍾宇  TripleX Chung <xxx.phy@gmail.com>
+        中文版校譯者: 李陽  Li Yang <leoyang.li@nxp.com>
+                      胡皓文 Hu Haowen <src.res@email.cn>
+
+Linux 內核驅動接口
+==================
+
+寫作本文檔的目的,是爲了解釋爲什麼Linux既沒有二進位內核接口,也沒有穩定
+的內核接口。這裡所說的內核接口,是指內核里的接口,而不是內核和用戶空間
+的接口。內核到用戶空間的接口,是提供給應用程式使用的系統調用,系統調用
+在歷史上幾乎沒有過變化,將來也不會有變化。我有一些老應用程式是在0.9版本
+或者更早版本的內核上編譯的,在使用2.6版本內核的Linux發布上依然用得很好
+。用戶和應用程式作者可以將這個接口看成是穩定的。
+
+
+執行綱要
+--------
+
+你也許以爲自己想要穩定的內核接口,但是你不清楚你要的實際上不是它。你需
+要的其實是穩定的驅動程序,而你只有將驅動程序放到公版內核的原始碼樹里,
+才有可能達到這個目的。而且這樣做還有很多其它好處,正是因爲這些好處使得
+Linux能成爲強壯,穩定,成熟的作業系統,這也是你最開始選擇Linux的原因。
+
+
+入門
+-----
+
+只有那些寫驅動程序的「怪人」才會擔心內核接口的改變,對廣大用戶來說,既
+看不到內核接口,也不需要去關心它。
+
+首先,我不打算討論關於任何非GPL許可的內核驅動的法律問題,這些非GPL許可
+的驅動程序包括不公開原始碼,隱藏原始碼,二進位或者是用原始碼包裝,或者
+是其它任何形式的不能以GPL許可公開原始碼的驅動程序。如果有法律問題,請咨
+詢律師,我只是一個程式設計師,所以我只打算探討技術問題(不是小看法律問題,
+法律問題很實際,並且需要一直關注)。
+
+既然只談技術問題,我們就有了下面兩個主題:二進位內核接口和穩定的內核源
+代碼接口。這兩個問題是互相關聯的,讓我們先解決掉二進位接口的問題。
+
+
+二進位內核接口
+--------------
+假如我們有一個穩定的內核原始碼接口,那麼自然而然的,我們就擁有了穩定的
+二進位接口,是這樣的嗎?錯。讓我們看看關於Linux內核的幾點事實:
+
+    - 取決於所用的C編譯器的版本,不同的內核數據結構里的結構體的對齊方
+      式會有差別,代碼中不同函數的表現形式也不一樣(函數是不是被inline
+      編譯取決於編譯器行爲)。不同的函數的表現形式並不重要,但是數據
+      結構內部的對齊方式很關鍵。
+
+    - 取決於內核的配置選項,不同的選項會讓內核的很多東西發生改變:
+
+      - 同一個結構體可能包含不同的成員變量
+      - 有的函數可能根本不會被實現(比如編譯的時候沒有選擇SMP支持
+        一些鎖函數就會被定義成空函數)。
+      - 內核使用的內存會以不同的方式對齊,這取決於不同的內核配置選
+        項。
+
+    - Linux可以在很多的不同體系結構的處理器上運行。在某個體系結構上編
+      譯好的二進位驅動程序,不可能在另外一個體系結構上正確的運行。
+
+對於一個特定的內核,滿足這些條件並不難,使用同一個C編譯器和同樣的內核配
+置選項來編譯驅動程序模塊就可以了。這對於給一個特定Linux發布的特定版本提
+供驅動程序,是完全可以滿足需求的。但是如果你要給不同發布的不同版本都發
+布一個驅動程序,就需要在每個發布上用不同的內核設置參數都編譯一次內核,
+這簡直跟噩夢一樣。而且還要注意到,每個Linux發布還提供不同的Linux內核,
+這些內核都針對不同的硬體類型進行了優化(有很多種不同的處理器,還有不同
+的內核設置選項)。所以每發布一次驅動程序,都需要提供很多不同版本的內核
+模塊。
+
+相信我,如果你真的要採取這種發布方式,一定會慢慢瘋掉,我很久以前就有過
+深刻的教訓...
+
+
+穩定的內核原始碼接口
+--------------------
+
+如果有人不將他的內核驅動程序,放入公版內核的原始碼樹,而又想讓驅動程序
+一直保持在最新的內核中可用,那麼這個話題將會變得沒完沒了。
+內核開發是持續而且快節奏的,從來都不會慢下來。內核開發人員在當前接口中
+找到bug,或者找到更好的實現方式。一旦發現這些,他們就很快會去修改當前的
+接口。修改接口意味著,函數名可能會改變,結構體可能被擴充或者刪減,函數
+的參數也可能發生改變。一旦接口被修改,內核中使用這些接口的地方需要同時
+修正,這樣才能保證所有的東西繼續工作。
+
+舉一個例子,內核的USB驅動程序接口在USB子系統的整個生命周期中,至少經歷
+了三次重寫。這些重寫解決以下問題:
+
+    - 把數據流從同步模式改成非同步模式,這個改動減少了一些驅動程序的
+      複雜度,提高了所有USB驅動程序的吞吐率,這樣幾乎所有的USB設備都
+      能以最大速率工作了。
+    - 修改了USB核心代碼中爲USB驅動分配數據包內存的方式,所有的驅動都
+      需要提供更多的參數給USB核心,以修正了很多已經被記錄在案的死鎖。
+
+這和一些封閉原始碼的作業系統形成鮮明的對比,在那些作業系統上,不得不額
+外的維護舊的USB接口。這導致了一個可能性,新的開發者依然會不小心使用舊的
+接口,以不恰當的方式編寫代碼,進而影響到作業系統的穩定性。
+在上面的例子中,所有的開發者都同意這些重要的改動,在這樣的情況下修改代
+價很低。如果Linux保持一個穩定的內核原始碼接口,那麼就得創建一個新的接口
+;舊的,有問題的接口必須一直維護,給Linux USB開發者帶來額外的工作。既然
+所有的Linux USB驅動的作者都是利用自己的時間工作,那麼要求他們去做毫無意
+義的免費額外工作,是不可能的。
+安全問題對Linux來說十分重要。一個安全問題被發現,就會在短時間內得到修
+正。在很多情況下,這將導致Linux內核中的一些接口被重寫,以從根本上避免安
+全問題。一旦接口被重寫,所有使用這些接口的驅動程序,必須同時得到修正,
+以確定安全問題已經得到修復並且不可能在未來還有同樣的安全問題。如果內核
+內部接口不允許改變,那麼就不可能修復這樣的安全問題,也不可能確認這樣的
+安全問題以後不會發生。
+開發者一直在清理內核接口。如果一個接口沒有人在使用了,它就會被刪除。這
+樣可以確保內核儘可能的小,而且所有潛在的接口都會得到儘可能完整的測試
+(沒有人使用的接口是不可能得到良好的測試的)。
+
+
+要做什麼
+--------
+
+如果你寫了一個Linux內核驅動,但是它還不在Linux原始碼樹里,作爲一個開發
+者,你應該怎麼做?爲每個發布的每個版本提供一個二進位驅動,那簡直是一個
+噩夢,要跟上永遠處於變化之中的內核接口,也是一件辛苦活。
+很簡單,讓你的驅動進入內核原始碼樹(要記得我們在談論的是以GPL許可發行
+的驅動,如果你的代碼不符合GPL,那麼祝你好運,你只能自己解決這個問題了,
+你這個吸血鬼<把Andrew和Linus對吸血鬼的定義連結到這裡>)。當你的代碼加入
+公版內核原始碼樹之後,如果一個內核接口改變,你的驅動會直接被修改接口的
+那個人修改。保證你的驅動永遠都可以編譯通過,並且一直工作,你幾乎不需要
+做什麼事情。
+
+把驅動放到內核原始碼樹里會有很多的好處:
+
+    - 驅動的質量會提升,而維護成本(對原始作者來說)會下降。
+    - 其他人會給驅動添加新特性。
+    - 其他人會找到驅動中的bug並修復。
+    - 其他人會在驅動中找到性能優化的機會。
+    - 當外部的接口的改變需要修改驅動程序的時候,其他人會修改驅動程序
+    - 不需要聯繫任何發行商,這個驅動會自動的隨著所有的Linux發布一起發
+      布。
+
+和別的作業系統相比,Linux爲更多不同的設備提供現成的驅動,而且能在更多不
+同體系結構的處理器上支持這些設備。這個經過考驗的開發模式,必然是錯不了
+的 :)
+
+感謝
+----
+感謝 Randy Dunlap, Andrew Morton, David Brownell, Hanna Linder,
+Robert Love, and Nishanth Aravamudan 對於本文檔早期版本的評審和建議。
+
+英文版維護者: Greg Kroah-Hartman <greg@kroah.com>
+
diff --git a/Documentation/translations/zh_TW/process/stable-kernel-rules.rst b/Documentation/translations/zh_TW/process/stable-kernel-rules.rst
new file mode 100644
index 000000000000..9bb0d9b4f3ac
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/stable-kernel-rules.rst
@@ -0,0 +1,68 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _tw_stable_kernel_rules:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/stable-kernel-rules.rst <stable_kernel_rules>`
+
+如果想評論或更新本文的內容,請直接聯繫原文檔的維護者。如果你使用英文
+交流有困難的話,也可以向中文版維護者求助。如果本翻譯更新不及時或者翻
+譯存在問題,請聯繫中文版維護者::
+
+        中文版維護者: 鍾宇  TripleX Chung <xxx.phy@gmail.com>
+        中文版翻譯者: 鍾宇  TripleX Chung <xxx.phy@gmail.com>
+        中文版校譯者:
+            - 李陽  Li Yang <leoyang.li@nxp.com>
+            - Kangkai Yin <e12051@motorola.com>
+            - 胡皓文 Hu Haowen <src.res@email.cn>
+
+所有你想知道的事情 - 關於linux穩定版發布
+========================================
+
+關於Linux 2.6穩定版發布,所有你想知道的事情。
+
+關於哪些類型的補丁可以被接收進入穩定版代碼樹,哪些不可以的規則:
+----------------------------------------------------------------
+
+  - 必須是顯而易見的正確,並且經過測試的。
+  - 連同上下文,不能大於100行。
+  - 必須只修正一件事情。
+  - 必須修正了一個給大家帶來麻煩的真正的bug(不是「這也許是一個問題...」
+    那樣的東西)。
+  - 必須修正帶來如下後果的問題:編譯錯誤(對被標記爲CONFIG_BROKEN的例外),
+    內核崩潰,掛起,數據損壞,真正的安全問題,或者一些類似「哦,這不
+    好」的問題。簡短的說,就是一些致命的問題。
+  - 沒有「理論上的競爭條件」,除非能給出競爭條件如何被利用的解釋。
+  - 不能存在任何的「瑣碎的」修正(拼寫修正,去掉多餘空格之類的)。
+  - 必須被相關子系統的維護者接受。
+  - 必須遵循Documentation/translations/zh_TW/process/submitting-patches.rst里的規則。
+
+向穩定版代碼樹提交補丁的過程:
+------------------------------
+
+  - 在確認了補丁符合以上的規則後,將補丁發送到stable@vger.kernel.org。
+  - 如果補丁被接受到隊列里,發送者會收到一個ACK回復,如果沒有被接受,收
+    到的是NAK回復。回復需要幾天的時間,這取決於開發者的時間安排。
+  - 被接受的補丁會被加到穩定版本隊列里,等待其他開發者的審查。
+  - 安全方面的補丁不要發到這個列表,應該發送到security@kernel.org。
+
+審查周期:
+----------
+
+  - 當穩定版的維護者決定開始一個審查周期,補丁將被發送到審查委員會,以
+    及被補丁影響的領域的維護者(除非提交者就是該領域的維護者)並且抄送
+    到linux-kernel郵件列表。
+  - 審查委員會有48小時的時間,用來決定給該補丁回復ACK還是NAK。
+  - 如果委員會中有成員拒絕這個補丁,或者linux-kernel列表上有人反對這個
+    補丁,並提出維護者和審查委員會之前沒有意識到的問題,補丁會從隊列中
+    丟棄。
+  - 在審查周期結束的時候,那些得到ACK回應的補丁將會被加入到最新的穩定版
+    發布中,一個新的穩定版發布就此產生。
+  - 安全性補丁將從內核安全小組那裡直接接收到穩定版代碼樹中,而不是通過
+    通常的審查周期。請聯繫內核安全小組以獲得關於這個過程的更多細節。
+
+審查委員會:
+------------
+  - 由一些自願承擔這項任務的內核開發者,和幾個非志願的組成。
+
diff --git a/Documentation/translations/zh_TW/process/submit-checklist.rst b/Documentation/translations/zh_TW/process/submit-checklist.rst
new file mode 100644
index 000000000000..ff2f89cba83f
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/submit-checklist.rst
@@ -0,0 +1,109 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/submit-checklist.rst <submitchecklist>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+.. _tw_submitchecklist:
+
+Linux內核補丁提交清單
+~~~~~~~~~~~~~~~~~~~~~
+
+如果開發人員希望看到他們的內核補丁提交更快地被接受,那麼他們應該做一些基本
+的事情。
+
+這些都是在
+:ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+和其他有關提交Linux內核補丁的文檔中提供的。
+
+1) 如果使用工具,則包括定義/聲明該工具的文件。不要依賴於其他頭文件拉入您使用
+   的頭文件。
+
+2) 乾淨的編譯:
+
+   a) 使用適用或修改的 ``CONFIG`` 選項 ``=y``、``=m`` 和 ``=n`` 。沒有GCC
+      警告/錯誤,沒有連結器警告/錯誤。
+
+   b) 通過allnoconfig、allmodconfig
+
+   c) 使用 ``O=builddir`` 時可以成功編譯
+
+3) 通過使用本地交叉編譯工具或其他一些構建場在多個CPU體系結構上構建。
+
+4) PPC64是一種很好的交叉編譯檢查體系結構,因爲它傾向於對64位的數使用無符號
+   長整型。
+
+5) 如下所述 :ref:`Documentation/translations/zh_TW/process/coding-style.rst <tw_codingstyle>`.
+   檢查您的補丁是否爲常規樣式。在提交( ``scripts/check patch.pl`` )之前,
+   使用補丁樣式檢查器檢查是否有輕微的衝突。您應該能夠處理您的補丁中存在的所有
+   違規行爲。
+
+6) 任何新的或修改過的 ``CONFIG`` 選項都不會弄髒配置菜單,並默認爲關閉,除非
+   它們符合 ``Documentation/kbuild/kconfig-language.rst`` 中記錄的異常條件,
+   菜單屬性:默認值.
+
+7) 所有新的 ``kconfig`` 選項都有幫助文本。
+
+8) 已仔細審查了相關的 ``Kconfig`` 組合。這很難用測試來糾正——腦力在這裡是有
+   回報的。
+
+9) 用 sparse 檢查乾淨。
+
+10) 使用 ``make checkstack`` 和 ``make namespacecheck`` 並修復他們發現的任何
+    問題。
+
+    .. note::
+
+        ``checkstack`` 並沒有明確指出問題,但是任何一個在堆棧上使用超過512
+        字節的函數都可以進行更改。
+
+11) 包括 :ref:`kernel-doc <kernel_doc>` 內核文檔以記錄全局內核API。(靜態函數
+    不需要,但也可以。)使用 ``make htmldocs`` 或 ``make pdfdocs`` 檢查
+    :ref:`kernel-doc <kernel_doc>` 並修復任何問題。
+
+12) 通過以下選項同時啓用的測試 ``CONFIG_PREEMPT``, ``CONFIG_DEBUG_PREEMPT``,
+    ``CONFIG_DEBUG_SLAB``, ``CONFIG_DEBUG_PAGEALLOC``, ``CONFIG_DEBUG_MUTEXES``,
+    ``CONFIG_DEBUG_SPINLOCK``, ``CONFIG_DEBUG_ATOMIC_SLEEP``,
+    ``CONFIG_PROVE_RCU`` and ``CONFIG_DEBUG_OBJECTS_RCU_HEAD``
+
+13) 已經過構建和運行時測試,包括有或沒有 ``CONFIG_SMP``, ``CONFIG_PREEMPT``.
+
+14) 如果補丁程序影響IO/磁碟等:使用或不使用 ``CONFIG_LBDAF`` 進行測試。
+
+15) 所有代碼路徑都已在啓用所有lockdep功能的情況下運行。
+
+16) 所有新的/proc條目都記錄在 ``Documentation/``
+
+17) 所有新的內核引導參數都記錄在
+    Documentation/admin-guide/kernel-parameters.rst 中。
+
+18) 所有新的模塊參數都記錄在 ``MODULE_PARM_DESC()``
+
+19) 所有新的用戶空間接口都記錄在 ``Documentation/ABI/`` 中。有關詳細信息,
+    請參閱 ``Documentation/ABI/README`` 。更改用戶空間接口的補丁應該抄送
+    linux-api@vger.kernel.org。
+
+20) 已通過至少注入slab和page分配失敗進行檢查。請參閱 ``Documentation/fault-injection/``
+    如果新代碼是實質性的,那麼添加子系統特定的故障注入可能是合適的。
+
+21) 新添加的代碼已經用 ``gcc -W`` 編譯(使用 ``make EXTRA-CFLAGS=-W`` )。這
+    將產生大量噪聲,但對於查找諸如「警告:有符號和無符號之間的比較」之類的錯誤
+    很有用。
+
+22) 在它被合併到-mm補丁集中之後進行測試,以確保它仍然與所有其他排隊的補丁以
+    及VM、VFS和其他子系統中的各種更改一起工作。
+
+23) 所有內存屏障例如 ``barrier()``, ``rmb()``, ``wmb()`` 都需要原始碼中的注
+    釋來解釋它們正在執行的操作及其原因的邏輯。
+
+24) 如果補丁添加了任何ioctl,那麼也要更新 ``Documentation/userspace-api/ioctl/ioctl-number.rst``
+
+25) 如果修改後的原始碼依賴或使用與以下 ``Kconfig`` 符號相關的任何內核API或
+    功能,則在禁用相關 ``Kconfig`` 符號和/或 ``=m`` (如果該選項可用)的情況
+    下測試以下多個構建[並非所有這些都同時存在,只是它們的各種/隨機組合]:
+
+    ``CONFIG_SMP``, ``CONFIG_SYSFS``, ``CONFIG_PROC_FS``, ``CONFIG_INPUT``, ``CONFIG_PCI``, ``CONFIG_BLOCK``, ``CONFIG_PM``, ``CONFIG_MAGIC_SYSRQ``,
+    ``CONFIG_NET``, ``CONFIG_INET=n`` (但是後者伴隨 ``CONFIG_NET=y``).
+
diff --git a/Documentation/translations/zh_TW/process/submitting-drivers.rst b/Documentation/translations/zh_TW/process/submitting-drivers.rst
new file mode 100644
index 000000000000..2fdd742318ba
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/submitting-drivers.rst
@@ -0,0 +1,164 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _tw_submittingdrivers:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/submitting-drivers.rst
+           <submittingdrivers>`
+
+如果想評論或更新本文的內容,請直接聯繫原文檔的維護者。如果你使用英文
+交流有困難的話,也可以向中文版維護者求助。如果本翻譯更新不及時或者翻
+譯存在問題,請聯繫中文版維護者::
+
+        中文版維護者: 李陽  Li Yang <leoyang.li@nxp.com>
+        中文版翻譯者: 李陽  Li Yang <leoyang.li@nxp.com>
+        中文版校譯者: 陳琦 Maggie Chen <chenqi@beyondsoft.com>
+                       王聰 Wang Cong <xiyou.wangcong@gmail.com>
+                       張巍 Zhang Wei <wezhang@outlook.com>
+                       胡皓文 Hu Haowen <src.res@email.cn>
+
+如何向 Linux 內核提交驅動程序
+=============================
+
+這篇文檔將會解釋如何向不同的內核源碼樹提交設備驅動程序。請注意,如果你感
+興趣的是顯卡驅動程序,你也許應該訪問 XFree86 項目(https://www.xfree86.org/)
+和/或 X.org 項目 (https://x.org)。
+
+另請參閱 Documentation/translations/zh_TW/process/submitting-patches.rst 文檔。
+
+
+分配設備號
+----------
+
+塊設備和字符設備的主設備號與從設備號是由 Linux 命名編號分配權威 LANANA(
+現在是 Torben Mathiasen)負責分配。申請的網址是 https://www.lanana.org/。
+即使不準備提交到主流內核的設備驅動也需要在這裡分配設備號。有關詳細信息,
+請參閱 Documentation/admin-guide/devices.rst。
+
+如果你使用的不是已經分配的設備號,那麼當你提交設備驅動的時候,它將會被強
+制分配一個新的設備號,即便這個設備號和你之前發給客戶的截然不同。
+
+設備驅動的提交對象
+------------------
+
+Linux 2.0:
+	此內核源碼樹不接受新的驅動程序。
+
+Linux 2.2:
+	此內核源碼樹不接受新的驅動程序。
+
+Linux 2.4:
+	如果所屬的代碼領域在內核的 MAINTAINERS 文件中列有一個總維護者,
+	那麼請將驅動程序提交給他。如果此維護者沒有回應或者你找不到恰當的
+	維護者,那麼請聯繫 Willy Tarreau <w@1wt.eu>。
+
+Linux 2.6:
+	除了遵循和 2.4 版內核同樣的規則外,你還需要在 linux-kernel 郵件
+	列表上跟蹤最新的 API 變化。向 Linux 2.6 內核提交驅動的頂級聯繫人
+	是 Andrew Morton <akpm@linux-foundation.org>。
+
+決定設備驅動能否被接受的條件
+----------------------------
+
+許可:		代碼必須使用 GNU 通用公開許可證 (GPL) 提交給 Linux,但是
+		我們並不要求 GPL 是唯一的許可。你或許會希望同時使用多種
+		許可證發布,如果希望驅動程序可以被其他開源社區(比如BSD)
+		使用。請參考 include/linux/module.h 文件中所列出的可被
+		接受共存的許可。
+
+版權:		版權所有者必須同意使用 GPL 許可。最好提交者和版權所有者
+		是相同個人或實體。否則,必需列出授權使用 GPL 的版權所有
+		人或實體,以備驗證之需。
+
+接口:		如果你的驅動程序使用現成的接口並且和其他同類的驅動程序行
+		爲相似,而不是去發明無謂的新接口,那麼它將會更容易被接受。
+		如果你需要一個 Linux 和 NT 的通用驅動接口,那麼請在用
+		戶空間實現它。
+
+代碼:		請使用 Documentation/process/coding-style.rst 中所描述的 Linux 代碼風
+		格。如果你的某些代碼段(例如那些與 Windows 驅動程序包共
+		享的代碼段)需要使用其他格式,而你卻只希望維護一份代碼,
+		那麼請將它們很好地區分出來,並且註明原因。
+
+可移植性:	請注意,指針並不永遠是 32 位的,不是所有的計算機都使用小
+		尾模式 (little endian) 存儲數據,不是所有的人都擁有浮點
+		單元,不要隨便在你的驅動程序里嵌入 x86 彙編指令。只能在
+		x86 上運行的驅動程序一般是不受歡迎的。雖然你可能只有 x86
+		硬體,很難測試驅動程序在其他平台上是否可用,但是確保代碼
+		可以被輕鬆地移植卻是很簡單的。
+
+清晰度:	做到所有人都能修補這個驅動程序將會很有好處,因爲這樣你將
+		會直接收到修復的補丁而不是 bug 報告。如果你提交一個試圖
+		隱藏硬體工作機理的驅動程序,那麼它將會被扔進廢紙簍。
+
+電源管理:	因爲 Linux 正在被很多行動裝置和桌面系統使用,所以你的驅
+		動程序也很有可能被使用在這些設備上。它應該支持最基本的電
+		源管理,即在需要的情況下實現系統級休眠和喚醒要用到的
+		.suspend 和 .resume 函數。你應該檢查你的驅動程序是否能正
+		確地處理休眠與喚醒,如果實在無法確認,請至少把 .suspend
+		函數定義成返回 -ENOSYS(功能未實現)錯誤。你還應該嘗試確
+		保你的驅動在什麼都不乾的情況下將耗電降到最低。要獲得驅動
+		程序測試的指導,請參閱
+		Documentation/power/drivers-testing.rst。有關驅動程序電
+		源管理問題相對全面的概述,請參閱
+		Documentation/driver-api/pm/devices.rst。
+
+管理:		如果一個驅動程序的作者還在進行有效的維護,那麼通常除了那
+		些明顯正確且不需要任何檢查的補丁以外,其他所有的補丁都會
+		被轉發給作者。如果你希望成爲驅動程序的聯繫人和更新者,最
+		好在代碼注釋中寫明並且在 MAINTAINERS 文件中加入這個驅動
+		程序的條目。
+
+不影響設備驅動能否被接受的條件
+------------------------------
+
+供應商:	由硬體供應商來維護驅動程序通常是一件好事。不過,如果源碼
+		樹里已經有其他人提供了可穩定工作的驅動程序,那麼請不要期
+		望「我是供應商」會成爲內核改用你的驅動程序的理由。理想的情
+		況是:供應商與現有驅動程序的作者合作,構建一個統一完美的
+		驅動程序。
+
+作者:		驅動程序是由大的 Linux 公司研發還是由你個人編寫,並不影
+		響其是否能被內核接受。沒有人對內核源碼樹享有特權。只要你
+		充分了解內核社區,你就會發現這一點。
+
+
+資源列表
+--------
+
+Linux 內核主源碼樹:
+	ftp.??.kernel.org:/pub/linux/kernel/...
+	?? == 你的國家代碼,例如 "cn"、"us"、"uk"、"fr" 等等
+
+Linux 內核郵件列表:
+	linux-kernel@vger.kernel.org
+	[可通過向majordomo@vger.kernel.org發郵件來訂閱]
+
+Linux 設備驅動程序,第三版(探討 2.6.10 版內核):
+	https://lwn.net/Kernel/LDD3/ (免費版)
+
+LWN.net:
+	每周內核開發活動摘要 - https://lwn.net/
+
+	2.6 版中 API 的變更:
+
+		https://lwn.net/Articles/2.6-kernel-api/
+
+	將舊版內核的驅動程序移植到 2.6 版:
+
+		https://lwn.net/Articles/driver-porting/
+
+內核新手(KernelNewbies):
+	爲新的內核開發者提供文檔和幫助
+	https://kernelnewbies.org/
+
+Linux USB項目:
+	http://www.linux-usb.org/
+
+寫內核驅動的「不要」(Arjan van de Ven著):
+	http://www.fenrus.org/how-to-not-write-a-device-driver-paper.pdf
+
+內核清潔工 (Kernel Janitor):
+	https://kernelnewbies.org/KernelJanitors
+
diff --git a/Documentation/translations/zh_TW/process/submitting-patches.rst b/Documentation/translations/zh_TW/process/submitting-patches.rst
new file mode 100644
index 000000000000..cdf0b52e4a98
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/submitting-patches.rst
@@ -0,0 +1,686 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _tw_submittingpatches:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/submitting-patches.rst <submittingpatches>`
+
+譯者::
+
+        中文版維護者: 鍾宇 TripleX Chung <xxx.phy@gmail.com>
+        中文版翻譯者: 鍾宇 TripleX Chung <xxx.phy@gmail.com>
+                       時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+        中文版校譯者: 李陽 Li Yang <leoyang.li@nxp.com>
+                       王聰 Wang Cong <xiyou.wangcong@gmail.com>
+                       胡皓文 Hu Haowen <src.res@email.cn>
+
+
+如何讓你的改動進入內核
+======================
+
+對於想要將改動提交到 Linux 內核的個人或者公司來說,如果不熟悉「規矩」,
+提交的流程會讓人畏懼。本文檔收集了一系列建議,這些建議可以大大的提高你
+的改動被接受的機會.
+
+以下文檔含有大量簡潔的建議, 具體請見:
+:ref:`Documentation/process <development_process_main>`
+同樣,:ref:`Documentation/translations/zh_TW/process/submit-checklist.rst <tw_submitchecklist>`
+給出在提交代碼前需要檢查的項目的列表。如果你在提交一個驅動程序,那麼
+同時閱讀一下:
+:ref:`Documentation/process/submitting-drivers.rst <submittingdrivers>`
+
+其中許多步驟描述了Git版本控制系統的默認行爲;如果您使用Git來準備補丁,
+您將發現它爲您完成的大部分機械工作,儘管您仍然需要準備和記錄一組合理的
+補丁。一般來說,使用git將使您作爲內核開發人員的生活更輕鬆。
+
+
+0) 獲取當前源碼樹
+-----------------
+
+如果您沒有一個可以使用當前內核原始碼的存儲庫,請使用git獲取一個。您將要
+從主線存儲庫開始,它可以通過以下方式獲取::
+
+        git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
+
+但是,請注意,您可能不希望直接針對主線樹進行開發。大多數子系統維護人員運
+行自己的樹,並希望看到針對這些樹準備的補丁。請參見MAINTAINERS文件中子系
+統的 **T:** 項以查找該樹,或者簡單地詢問維護者該樹是否未在其中列出。
+
+仍然可以通過tarballs下載內核版本(如下一節所述),但這是進行內核開發的
+一種困難的方式。
+
+1) "diff -up"
+-------------
+
+使用 "diff -up" 或者 "diff -uprN" 來創建補丁。
+
+所有內核的改動,都是以補丁的形式呈現的,補丁由 diff(1) 生成。創建補丁的
+時候,要確認它是以 "unified diff" 格式創建的,這種格式由 diff(1) 的 '-u'
+參數生成。而且,請使用 '-p' 參數,那樣會顯示每個改動所在的C函數,使得
+產生的補丁容易讀得多。補丁應該基於內核原始碼樹的根目錄,而不是裡邊的任
+何子目錄。
+
+爲一個單獨的文件創建補丁,一般來說這樣做就夠了::
+
+        SRCTREE=linux
+        MYFILE=drivers/net/mydriver.c
+
+        cd $SRCTREE
+        cp $MYFILE $MYFILE.orig
+        vi $MYFILE      # make your change
+        cd ..
+        diff -up $SRCTREE/$MYFILE{.orig,} > /tmp/patch
+
+爲多個文件創建補丁,你可以解開一個沒有修改過的內核原始碼樹,然後和你自
+己的代碼樹之間做 diff 。例如::
+
+        MYSRC=/devel/linux
+
+        tar xvfz linux-3.19.tar.gz
+        mv linux-3.19 linux-3.19-vanilla
+        diff -uprN -X linux-3.19-vanilla/Documentation/dontdiff \
+                linux-3.19-vanilla $MYSRC > /tmp/patch
+
+"dontdiff" 是內核在編譯的時候產生的文件的列表,列表中的文件在 diff(1)
+產生的補丁里會被跳過。
+
+確定你的補丁里沒有包含任何不屬於這次補丁提交的額外文件。記得在用diff(1)
+生成補丁之後,審閱一次補丁,以確保準確。
+
+如果你的改動很散亂,你應該研究一下如何將補丁分割成獨立的部分,將改動分
+割成一系列合乎邏輯的步驟。這樣更容易讓其他內核開發者審核,如果你想你的
+補丁被接受,這是很重要的。請參閱:
+:ref:`tw_split_changes`
+
+如果你用 ``git`` , ``git rebase -i`` 可以幫助你這一點。如果你不用 ``git``,
+``quilt`` <https://savannah.nongnu.org/projects/quilt> 另外一個流行的選擇。
+
+.. _tw_describe_changes:
+
+2) 描述你的改動
+---------------
+
+描述你的問題。無論您的補丁是一行錯誤修復還是5000行新功能,都必須有一個潛在
+的問題激勵您完成這項工作。讓審稿人相信有一個問題值得解決,讓他們讀完第一段
+是有意義的。
+
+描述用戶可見的影響。直接崩潰和鎖定是相當有說服力的,但並不是所有的錯誤都那麼
+明目張胆。即使在代碼審查期間發現了這個問題,也要描述一下您認爲它可能對用戶產
+生的影響。請記住,大多數Linux安裝運行的內核來自二級穩定樹或特定於供應商/產品
+的樹,只從上游精選特定的補丁,因此請包含任何可以幫助您將更改定位到下游的內容:
+觸發的場景、DMESG的摘錄、崩潰描述、性能回歸、延遲尖峯、鎖定等。
+
+量化優化和權衡。如果您聲稱在性能、內存消耗、堆棧占用空間或二進位大小方面有所
+改進,請包括支持它們的數字。但也要描述不明顯的成本。優化通常不是免費的,而是
+在CPU、內存和可讀性之間進行權衡;或者,探索性的工作,在不同的工作負載之間進
+行權衡。請描述優化的預期缺點,以便審閱者可以權衡成本和收益。
+
+一旦問題建立起來,就要詳細地描述一下您實際在做什麼。對於審閱者來說,用簡單的
+英語描述代碼的變化是很重要的,以驗證代碼的行爲是否符合您的意願。
+
+如果您將補丁描述寫在一個表單中,這個表單可以很容易地作爲「提交日誌」放入Linux
+的原始碼管理系統git中,那麼維護人員將非常感謝您。見 :ref:`tw_explicit_in_reply_to`.
+
+每個補丁只解決一個問題。如果你的描述開始變長,這就表明你可能需要拆分你的補丁。
+請見 :ref:`tw_split_changes`
+
+提交或重新提交修補程序或修補程序系列時,請包括完整的修補程序說明和理由。不要
+只說這是補丁(系列)的第幾版。不要期望子系統維護人員引用更早的補丁版本或引用
+URL來查找補丁描述並將其放入補丁中。也就是說,補丁(系列)及其描述應該是獨立的。
+這對維護人員和審查人員都有好處。一些評審者可能甚至沒有收到補丁的早期版本。
+
+描述你在命令語氣中的變化,例如「make xyzzy do frotz」而不是「[這個補丁]make
+xyzzy do frotz」或「[我]changed xyzzy to do frotz」,就好像你在命令代碼庫改變
+它的行爲一樣。
+
+如果修補程序修復了一個記錄的bug條目,請按編號和URL引用該bug條目。如果補丁來
+自郵件列表討論,請給出郵件列表存檔的URL;使用帶有 ``Message-ID`` 的
+https://lkml.kernel.org/ 重定向,以確保連結不會過時。
+
+但是,在沒有外部資源的情況下,儘量讓你的解釋可理解。除了提供郵件列表存檔或
+bug的URL之外,還要總結需要提交補丁的相關討論要點。
+
+如果您想要引用一個特定的提交,不要只引用提交的 SHA-1 ID。還請包括提交的一行
+摘要,以便於審閱者了解它是關於什麼的。例如::
+
+        Commit e21d2170f36602ae2708 ("video: remove unnecessary
+        platform_set_drvdata()") removed the unnecessary
+        platform_set_drvdata(), but left the variable "dev" unused,
+        delete it.
+
+您還應該確保至少使用前12位 SHA-1 ID. 內核存儲庫包含*許多*對象,使與較短的ID
+發生衝突的可能性很大。記住,即使現在不會與您的六個字符ID發生衝突,這種情況
+可能五年後改變。
+
+如果修補程序修復了特定提交中的錯誤,例如,使用 ``git bisct`` ,請使用帶有前
+12個字符SHA-1 ID 的"Fixes:"標記和單行摘要。爲了簡化不要將標記拆分爲多個,
+行、標記不受分析腳本「75列換行」規則的限制。例如::
+
+        Fixes: 54a4f0239f2e ("KVM: MMU: make kvm_mmu_zap_page() return the number of pages it actually freed")
+
+下列 ``git config`` 設置可以添加讓 ``git log``, ``git show`` 漂亮的顯示格式::
+
+	[core]
+		abbrev = 12
+	[pretty]
+		fixes = Fixes: %h (\"%s\")
+
+.. _tw_split_changes:
+
+3) 拆分你的改動
+---------------
+
+將每個邏輯更改分隔成一個單獨的補丁。
+
+例如,如果你的改動里同時有bug修正和性能優化,那麼把這些改動拆分到兩個或
+者更多的補丁文件中。如果你的改動包含對API的修改,並且修改了驅動程序來適
+應這些新的API,那麼把這些修改分成兩個補丁。
+
+另一方面,如果你將一個單獨的改動做成多個補丁文件,那麼將它們合併成一個
+單獨的補丁文件。這樣一個邏輯上單獨的改動只被包含在一個補丁文件里。
+
+如果有一個補丁依賴另外一個補丁來完成它的改動,那沒問題。簡單的在你的補
+丁描述里指出「這個補丁依賴某補丁」就好了。
+
+在將您的更改劃分爲一系列補丁時,要特別注意確保內核在系列中的每個補丁之後
+都能正常構建和運行。使用 ``git bisect`` 來追蹤問題的開發者可能會在任何時
+候分割你的補丁系列;如果你在中間引入錯誤,他們不會感謝你。
+
+如果你不能將補丁濃縮成更少的文件,那麼每次大約發送出15個,然後等待審查
+和集成。
+
+4) 檢查你的更改風格
+-------------------
+
+檢查您的補丁是否存在基本樣式衝突,詳細信息可在
+:ref:`Documentation/translations/zh_TW/process/coding-style.rst <tw_codingstyle>`
+中找到。如果不這樣做,只會浪費審稿人的時間,並且會導致你的補丁被拒絕,甚至
+可能沒有被閱讀。
+
+一個重要的例外是在將代碼從一個文件移動到另一個文件時——在這種情況下,您不應
+該在移動代碼的同一個補丁中修改移動的代碼。這清楚地描述了移動代碼和您的更改
+的行爲。這大大有助於審查實際差異,並允許工具更好地跟蹤代碼本身的歷史。
+
+在提交之前,使用補丁樣式檢查程序檢查補丁(scripts/check patch.pl)。不過,
+請注意,樣式檢查程序應該被視爲一個指南,而不是作爲人類判斷的替代品。如果您
+的代碼看起來更好,但有違規行爲,那麼最好不要使用它。
+
+檢查者報告三個級別:
+
+ - ERROR:很可能出錯的事情
+ - WARNING:需要仔細審查的事項
+ - CHECK:需要思考的事情
+
+您應該能夠判斷您的補丁中存在的所有違規行爲。
+
+5) 選擇補丁收件人
+-----------------
+
+您應該總是在任何補丁上複製相應的子系統維護人員,以獲得他們維護的代碼;查看
+維護人員文件和原始碼修訂歷史記錄,以了解這些維護人員是誰。腳本
+scripts/get_Maintainer.pl在這個步驟中非常有用。如果您找不到正在工作的子系統
+的維護人員,那麼Andrew Morton(akpm@linux-foundation.org)將充當最後的維護
+人員。
+
+您通常還應該選擇至少一個郵件列表來接收補丁集的。linux-kernel@vger.kernel.org
+作爲最後一個解決辦法的列表,但是這個列表上的體積已經引起了許多開發人員的拒絕。
+在MAINTAINERS文件中查找子系統特定的列表;您的補丁可能會在那裡得到更多的關注。
+不過,請不要發送垃圾郵件到無關的列表。
+
+許多與內核相關的列表託管在vger.kernel.org上;您可以在
+http://vger.kernel.org/vger-lists.html 上找到它們的列表。不過,也有與內核相關
+的列表託管在其他地方。
+
+不要一次發送超過15個補丁到vger郵件列表!!!!
+
+Linus Torvalds 是決定改動能否進入 Linux 內核的最終裁決者。他的 e-mail
+地址是 <torvalds@linux-foundation.org> 。他收到的 e-mail 很多,所以一般
+的說,最好別給他發 e-mail。
+
+如果您有修復可利用安全漏洞的補丁,請將該補丁發送到 security@kernel.org。對於
+嚴重的bug,可以考慮短期暫停以允許分銷商向用戶發布補丁;在這種情況下,顯然不應
+將補丁發送到任何公共列表。
+
+修復已發布內核中嚴重錯誤的補丁程序應該指向穩定版維護人員,方法是放這樣的一行::
+
+        Cc: stable@vger.kernel.org
+
+進入補丁的簽准區(注意,不是電子郵件收件人)。除了這個文件之外,您還應該閱讀
+:ref:`Documentation/process/stable-kernel-rules.rst <stable_kernel_rules>`
+
+但是,請注意,一些子系統維護人員希望得出他們自己的結論,即哪些補丁應該被放到
+穩定的樹上。尤其是網絡維護人員,不希望看到單個開發人員在補丁中添加像上面這樣
+的行。
+
+如果更改影響到用戶和內核接口,請向手冊頁維護人員(如維護人員文件中所列)發送
+手冊頁補丁,或至少發送更改通知,以便一些信息進入手冊頁。還應將用戶空間API
+更改複製到 linux-api@vger.kernel.org。
+
+對於小的補丁,你也許會CC到搜集瑣碎補丁的郵件列表(Trivial Patch Monkey)
+trivial@kernel.org,那裡專門收集瑣碎的補丁。下面這樣的補丁會被看作「瑣碎的」
+補丁:
+
+ - 文檔的拼寫修正。
+ - 修正會影響到 grep(1) 的拼寫。
+ - 警告信息修正(頻繁的列印無用的警告是不好的。)
+ - 編譯錯誤修正(代碼邏輯的確是對的,只是編譯有問題。)
+ - 運行時修正(只要真的修正了錯誤。)
+ - 移除使用了被廢棄的函數/宏的代碼(例如 check_region。)
+ - 聯繫方式和文檔修正。
+ - 用可移植的代碼替換不可移植的代碼(即使在體系結構相關的代碼中,既然有
+ - 人拷貝,只要它是瑣碎的)
+ - 任何文件的作者/維護者對該文件的改動(例如 patch monkey 在重傳模式下)
+
+(譯註,關於「瑣碎補丁」的一些說明:因爲原文的這一部分寫得比較簡單,所以不得不
+違例寫一下譯註。"trivial"這個英文單詞的本意是「瑣碎的,不重要的。」但是在這裡
+有稍微有一些變化,例如對一些明顯的NULL指針的修正,屬於運行時修正,會被歸類
+到瑣碎補丁里。雖然NULL指針的修正很重要,但是這樣的修正往往很小而且很容易得到
+檢驗,所以也被歸入瑣碎補丁。瑣碎補丁更精確的歸類應該是
+「simple, localized & easy to verify」,也就是說簡單的,局部的和易於檢驗的。
+trivial@kernel.org郵件列表的目的是針對這樣的補丁,爲提交者提供一個中心,來
+降低提交的門檻。)
+
+6) 沒有 MIME 編碼,沒有連結,沒有壓縮,沒有附件,只有純文本
+-----------------------------------------------------------
+
+Linus 和其他的內核開發者需要閱讀和評論你提交的改動。對於內核開發者來說
+,可以「引用」你的改動很重要,使用一般的 e-mail 工具,他們就可以在你的
+代碼的任何位置添加評論。
+
+因爲這個原因,所有的提交的補丁都是 e-mail 中「內嵌」的。
+
+.. warning::
+   如果你使用剪切-粘貼你的補丁,小心你的編輯器的自動換行功能破壞你的補丁
+
+不要將補丁作爲 MIME 編碼的附件,不管是否壓縮。很多流行的 e-mail 軟體不
+是任何時候都將 MIME 編碼的附件當作純文本發送的,這會使得別人無法在你的
+代碼中加評論。另外,MIME 編碼的附件會讓 Linus 多花一點時間來處理,這就
+降低了你的改動被接受的可能性。
+
+例外:如果你的郵遞員弄壞了補丁,那麼有人可能會要求你使用mime重新發送補丁
+
+請參閱 :ref:`Documentation/translations/zh_TW/process/email-clients.rst <tw_email_clients>`
+以獲取有關配置電子郵件客戶端以使其不受影響地發送修補程序的提示。
+
+7) e-mail 的大小
+----------------
+
+大的改動對郵件列表不合適,對某些維護者也不合適。如果你的補丁,在不壓縮
+的情況下,超過了300kB,那麼你最好將補丁放在一個能通過 internet 訪問的服
+務器上,然後用指向你的補丁的 URL 替代。但是請注意,如果您的補丁超過了
+300kb,那麼它幾乎肯定需要被破壞。
+
+8)回複評審意見
+---------------
+
+你的補丁幾乎肯定會得到評審者對補丁改進方法的評論。您必須對這些評論作出
+回應;讓補丁被忽略的一個好辦法就是忽略審閱者的意見。不會導致代碼更改的
+意見或問題幾乎肯定會帶來注釋或變更日誌的改變,以便下一個評審者更好地了解
+正在發生的事情。
+
+一定要告訴審稿人你在做什麼改變,並感謝他們的時間。代碼審查是一個累人且
+耗時的過程,審查人員有時會變得暴躁。即使在這種情況下,也要禮貌地回應並
+解決他們指出的問題。
+
+9)不要洩氣或不耐煩
+-------------------
+
+提交更改後,請耐心等待。審閱者是忙碌的人,可能無法立即訪問您的修補程序。
+
+曾幾何時,補丁曾在沒有評論的情況下消失在空白中,但開發過程比現在更加順利。
+您應該在一周左右的時間內收到評論;如果沒有收到評論,請確保您已將補丁發送
+到正確的位置。在重新提交或聯繫審閱者之前至少等待一周-在諸如合併窗口之類的
+繁忙時間可能更長。
+
+10)主題中包含 PATCH
+--------------------
+
+由於到linus和linux內核的電子郵件流量很高,通常會在主題行前面加上[PATCH]
+前綴. 這使Linus和其他內核開發人員更容易將補丁與其他電子郵件討論區分開。
+
+11)簽署你的作品-開發者原始認證
+-------------------------------
+
+爲了加強對誰做了何事的追蹤,尤其是對那些透過好幾層的維護者的補丁,我們
+建議在發送出去的補丁上加一個 「sign-off」 的過程。
+
+"sign-off" 是在補丁的注釋的最後的簡單的一行文字,認證你編寫了它或者其他
+人有權力將它作爲開放原始碼的補丁傳遞。規則很簡單:如果你能認證如下信息:
+
+開發者來源證書 1.1
+^^^^^^^^^^^^^^^^^^
+
+對於本項目的貢獻,我認證如下信息:
+
+      (a)這些貢獻是完全或者部分的由我創建,我有權利以文件中指出
+           的開放原始碼許可證提交它;或者
+      (b)這些貢獻基於以前的工作,據我所知,這些以前的工作受恰當的開放
+           原始碼許可證保護,而且,根據許可證,我有權提交修改後的貢獻,
+           無論是完全還是部分由我創造,這些貢獻都使用同一個開放原始碼許可證
+           (除非我被允許用其它的許可證),正如文件中指出的;或者
+      (c)這些貢獻由認證(a),(b)或者(c)的人直接提供給我,而
+           且我沒有修改它。
+      (d)我理解並同意這個項目和貢獻是公開的,貢獻的記錄(包括我
+           一起提交的個人記錄,包括 sign-off )被永久維護並且可以和這個項目
+           或者開放原始碼的許可證同步地再發行。
+
+那麼加入這樣一行::
+
+       Signed-off-by: Random J Developer <random@developer.example.org>
+
+使用你的真名(抱歉,不能使用假名或者匿名。)
+
+有人在最後加上標籤。現在這些東西會被忽略,但是你可以這樣做,來標記公司
+內部的過程,或者只是指出關於 sign-off 的一些特殊細節。
+
+如果您是子系統或分支維護人員,有時需要稍微修改收到的補丁,以便合併它們,
+因爲樹和提交者中的代碼不完全相同。如果你嚴格遵守規則(c),你應該要求提交者
+重新發布,但這完全是在浪費時間和精力。規則(b)允許您調整代碼,但是更改一個
+提交者的代碼並讓他認可您的錯誤是非常不禮貌的。要解決此問題,建議在最後一個
+由簽名行和您的行之間添加一行,指示更改的性質。雖然這並不是強制性的,但似乎
+在描述前加上您的郵件和/或姓名(全部用方括號括起來),這足以讓人注意到您對最
+後一分鐘的更改負有責任。例如::
+
+	Signed-off-by: Random J Developer <random@developer.example.org>
+	[lucky@maintainer.example.org: struct foo moved from foo.c to foo.h]
+	Signed-off-by: Lucky K Maintainer <lucky@maintainer.example.org>
+
+如果您維護一個穩定的分支機構,同時希望對作者進行致謝、跟蹤更改、合併修復並
+保護提交者不受投訴,那麼這種做法尤其有用。請注意,在任何情況下都不能更改作者
+的ID(From 頭),因爲它是出現在更改日誌中的標識。
+
+對回合(back-porters)的特別說明:在提交消息的頂部(主題行之後)插入一個補丁
+的起源指示似乎是一種常見且有用的實踐,以便於跟蹤。例如,下面是我們在3.x穩定
+版本中看到的內容::
+
+  Date:   Tue Oct 7 07:26:38 2014 -0400
+
+    libata: Un-break ATA blacklist
+
+    commit 1c40279960bcd7d52dbdf1d466b20d24b99176c8 upstream.
+
+還有, 這裡是一個舊版內核中的一個回合補丁::
+
+    Date:   Tue May 13 22:12:27 2008 +0200
+
+        wireless, airo: waitbusy() won't delay
+
+        [backport of 2.6 commit b7acbdfbd1f277c1eb23f344f899cfa4cd0bf36a]
+
+12)何時使用Acked-by:,CC:,和Co-Developed by:
+----------------------------------------------
+
+Singed-off-by: 標記表示簽名者參與了補丁的開發,或者他/她在補丁的傳遞路徑中。
+
+如果一個人沒有直接參與補丁的準備或處理,但希望表示並記錄他們對補丁的批准,
+那麼他們可以要求在補丁的變更日誌中添加一個 Acked-by:
+
+Acked-by:通常由受影響代碼的維護者使用,當該維護者既沒有貢獻也沒有轉發補丁時。
+
+Acked-by: 不像簽字人那樣正式。這是一個記錄,確認人至少審查了補丁,並表示接受。
+因此,補丁合併有時會手動將Acker的「Yep,looks good to me」轉換爲 Acked-By:(但
+請注意,通常最好要求一個明確的Ack)。
+
+Acked-by:不一定表示對整個補丁的確認。例如,如果一個補丁影響多個子系統,並且
+有一個:來自一個子系統維護者,那麼這通常表示只確認影響維護者代碼的部分。這裡
+應該仔細判斷。如有疑問,應參考郵件列表檔案中的原始討論。
+
+如果某人有機會對補丁進行評論,但沒有提供此類評論,您可以選擇在補丁中添加 ``Cc:``
+這是唯一一個標籤,它可以在沒有被它命名的人顯式操作的情況下添加,但它應該表明
+這個人是在補丁上抄送的。討論中包含了潛在利益相關方。
+
+Co-developed-by: 聲明補丁是由多個開發人員共同創建的;當幾個人在一個補丁上工
+作時,它用於將屬性賦予共同作者(除了 From: 所賦予的作者之外)。因爲
+Co-developed-by: 表示作者身份,所以每個共同開發人:必須緊跟在相關合作作者的
+簽名之後。標準的簽核程序要求:標記的簽核順序應儘可能反映補丁的時間歷史,而不
+管作者是通過 From :還是由 Co-developed-by: 共同開發的。值得注意的是,最後一
+個簽字人:必須始終是提交補丁的開發人員。
+
+注意,當作者也是電子郵件標題「發件人:」行中列出的人時,「From: 」 標記是可選的。
+
+作者提交的補丁程序示例::
+
+	<changelog>
+
+	Co-developed-by: First Co-Author <first@coauthor.example.org>
+	Signed-off-by: First Co-Author <first@coauthor.example.org>
+	Co-developed-by: Second Co-Author <second@coauthor.example.org>
+	Signed-off-by: Second Co-Author <second@coauthor.example.org>
+	Signed-off-by: From Author <from@author.example.org>
+
+合作開發者提交的補丁示例::
+
+	From: From Author <from@author.example.org>
+
+	<changelog>
+
+	Co-developed-by: Random Co-Author <random@coauthor.example.org>
+	Signed-off-by: Random Co-Author <random@coauthor.example.org>
+	Signed-off-by: From Author <from@author.example.org>
+	Co-developed-by: Submitting Co-Author <sub@coauthor.example.org>
+	Signed-off-by: Submitting Co-Author <sub@coauthor.example.org>
+
+
+13)使用報告人:、測試人:、審核人:、建議人:、修復人:
+--------------------------------------------------------
+
+Reported-by: 給那些發現錯誤並報告錯誤的人致謝,它希望激勵他們在將來再次幫助
+我們。請注意,如果bug是以私有方式報告的,那麼在使用Reported-by標記之前,請
+先請求權限。
+
+Tested-by: 標記表示補丁已由指定的人(在某些環境中)成功測試。這個標籤通知
+維護人員已經執行了一些測試,爲將來的補丁提供了一種定位測試人員的方法,並確
+保測試人員的信譽。
+
+Reviewed-by:相反,根據審查人的聲明,表明該補丁已被審查並被認爲是可接受的:
+
+
+審查人的監督聲明
+^^^^^^^^^^^^^^^^
+
+通過提供我的 Reviewed-by,我聲明:
+
+        (a) 我已經對這個補丁進行了一次技術審查,以評估它是否適合被包含到
+            主線內核中。
+
+        (b) 與補丁相關的任何問題、顧慮或問題都已反饋給提交者。我對提交者對
+            我的評論的回應感到滿意。
+
+        (c) 雖然這一提交可能會改進一些東西,但我相信,此時,(1)對內核
+            進行了有價值的修改,(2)沒有包含爭論中涉及的已知問題。
+
+        (d) 雖然我已經審查了補丁並認爲它是健全的,但我不會(除非另有明確
+            說明)作出任何保證或保證它將在任何給定情況下實現其規定的目的
+            或正常運行。
+
+Reviewed-by 是一種觀點聲明,即補丁是對內核的適當修改,沒有任何遺留的嚴重技術
+問題。任何感興趣的審閱者(完成工作的人)都可以爲一個補丁提供一個 Review-by
+標籤。此標籤用於向審閱者提供致謝,並通知維護者已在修補程序上完成的審閱程度。
+Reviewed-by: 當由已知了解主題區域並執行徹底檢查的審閱者提供時,通常會增加
+補丁進入內核的可能性。
+
+Suggested-by: 表示補丁的想法是由指定的人提出的,並確保將此想法歸功於指定的
+人。請注意,未經許可,不得添加此標籤,特別是如果該想法未在公共論壇上發布。
+這就是說,如果我們勤快地致謝我們的創意者,他們很有希望在未來得到鼓舞,再次
+幫助我們。
+
+Fixes: 指示補丁在以前的提交中修復了一個問題。它可以很容易地確定錯誤的來源,
+這有助於檢查錯誤修復。這個標記還幫助穩定內核團隊確定應該接收修復的穩定內核
+版本。這是指示補丁修復的錯誤的首選方法。請參閱 :ref:`tw_describe_changes`
+描述您的更改以了解更多詳細信息。
+
+.. _tw_the_canonical_patch_format:
+
+12)標準補丁格式
+----------------
+
+本節描述如何格式化補丁本身。請注意,如果您的補丁存儲在 ``Git`` 存儲庫中,則
+可以使用 ``git format-patch`` 進行正確的補丁格式設置。但是,這些工具無法創建
+必要的文本,因此請務必閱讀下面的說明。
+
+標準的補丁,標題行是::
+
+    Subject: [PATCH 001/123] 子系統:一句話概述
+
+標準補丁的信體存在如下部分:
+
+  - 一個 "from" 行指出補丁作者。後跟空行(僅當發送修補程序的人不是作者時才需要)。
+
+  - 解釋的正文,行以75列包裝,這將被複製到永久變更日誌來描述這個補丁。
+
+  - 一個空行
+
+  - 上面描述的「Signed-off-by」 行,也將出現在更改日誌中。
+
+  - 只包含 ``---`` 的標記線。
+
+  - 任何其他不適合放在變更日誌的注釋。
+
+  - 實際補丁( ``diff`` 輸出)。
+
+標題行的格式,使得對標題行按字母序排序非常的容易 - 很多 e-mail 客戶端都
+可以支持 - 因爲序列號是用零填充的,所以按數字排序和按字母排序是一樣的。
+
+e-mail 標題中的「子系統」標識哪個內核子系統將被打補丁。
+
+e-mail 標題中的「一句話概述」扼要的描述 e-mail 中的補丁。「一句話概述」
+不應該是一個文件名。對於一個補丁系列(「補丁系列」指一系列的多個相關補
+丁),不要對每個補丁都使用同樣的「一句話概述」。
+
+記住 e-mail 的「一句話概述」會成爲該補丁的全局唯一標識。它會蔓延到 git
+的改動記錄里。然後「一句話概述」會被用在開發者的討論里,用來指代這個補
+丁。用戶將希望通過 google 來搜索"一句話概述"來找到那些討論這個補丁的文
+章。當人們在兩三個月後使用諸如 ``gitk`` 或 ``git log --oneline`` 之類
+的工具查看數千個補丁時,也會很快看到它。
+
+出於這些原因,概述必須不超過70-75個字符,並且必須描述補丁的更改以及爲
+什麼需要補丁。既要簡潔又要描述性很有挑戰性,但寫得好的概述應該這樣做。
+
+概述的前綴可以用方括號括起來:「Subject: [PATCH <tag>...] <概述>」。標記
+不被視爲概述的一部分,而是描述應該如何處理補丁。如果補丁的多個版本已發
+送出來以響應評審(即「v1,v2,v3」)或「rfc」,以指示評審請求,那麼通用標記
+可能包括版本描述符。如果一個補丁系列中有四個補丁,那麼各個補丁可以這樣
+編號:1/4、2/4、3/4、4/4。這可以確保開發人員了解補丁應用的順序,並且他們
+已經查看或應用了補丁系列中的所有補丁。
+
+一些標題的例子::
+
+    Subject: [patch 2/5] ext2: improve scalability of bitmap searching
+    Subject: [PATCHv2 001/207] x86: fix eflags tracking
+
+"From" 行是信體裡的最上面一行,具有如下格式:
+        From: Patch Author <author@example.com>
+
+"From" 行指明在永久改動日誌里,誰會被確認爲作者。如果沒有 "From" 行,那
+麼郵件頭裡的 "From: " 行會被用來決定改動日誌中的作者。
+
+說明的主題將會被提交到永久的原始碼改動日誌里,因此對那些早已經不記得和
+這個補丁相關的討論細節的有能力的讀者來說,是有意義的。包括補丁程序定位
+錯誤的(內核日誌消息、OOPS消息等)症狀,對於搜索提交日誌以尋找適用補丁的人
+尤其有用。如果一個補丁修復了一個編譯失敗,那麼可能不需要包含所有編譯失敗;
+只要足夠讓搜索補丁的人能夠找到它就行了。與概述一樣,既要簡潔又要描述性。
+
+"---" 標記行對於補丁處理工具要找到哪裡是改動日誌信息的結束,是不可缺少
+的。
+
+對於 "---" 標記之後的額外註解,一個好的用途就是用來寫 diffstat,用來顯
+示修改了什麼文件和每個文件都增加和刪除了多少行。diffstat 對於比較大的補
+丁特別有用。其餘那些只是和時刻或者開發者相關的註解,不合適放到永久的改
+動日誌里的,也應該放這裡。
+使用 diffstat的選項 "-p 1 -w 70" 這樣文件名就會從內核原始碼樹的目錄開始
+,不會占用太寬的空間(很容易適合80列的寬度,也許會有一些縮進。)
+
+在後面的參考資料中能看到適當的補丁格式的更多細節。
+
+.. _tw_explicit_in_reply_to:
+
+15) 明確回覆郵件頭(In-Reply-To)
+-------------------------------
+
+手動添加回復補丁的的標題頭(In-Reply_To:) 是有幫助的(例如,使用 ``git send-email`` )
+將補丁與以前的相關討論關聯起來,例如,將bug修復程序連結到電子郵件和bug報告。
+但是,對於多補丁系列,最好避免在回復時使用連結到該系列的舊版本。這樣,
+補丁的多個版本就不會成爲電子郵件客戶端中無法管理的引用序列。如果連結有用,
+可以使用 https://lkml.kernel.org/ 重定向器(例如,在封面電子郵件文本中)
+連結到補丁系列的早期版本。
+
+16) 發送git pull請求
+--------------------
+
+如果您有一系列補丁,那麼讓維護人員通過git pull操作將它們直接拉入子系統存儲
+庫可能是最方便的。但是,請注意,從開發人員那裡獲取補丁比從郵件列表中獲取補
+丁需要更高的信任度。因此,許多子系統維護人員不願意接受請求,特別是來自新的
+未知開發人員的請求。如果有疑問,您可以在封面郵件中使用pull 請求作爲補丁系列
+正常發布的一個選項,讓維護人員可以選擇使用其中之一。
+
+pull 請求的主題行中應該有[Git Pull]。請求本身應該在一行中包含存儲庫名稱和
+感興趣的分支;它應該看起來像::
+
+  Please pull from
+
+      git://jdelvare.pck.nerim.net/jdelvare-2.6 i2c-for-linus
+
+  to get these changes:
+
+
+pull 請求還應該包含一條整體消息,說明請求中將包含什麼,一個補丁本身的 ``Git shortlog``
+以及一個顯示補丁系列整體效果的 ``diffstat`` 。當然,將所有這些信息收集在一起
+的最簡單方法是讓 ``git`` 使用 ``git request-pull`` 命令爲您完成這些工作。
+
+一些維護人員(包括Linus)希望看到來自已簽名提交的請求;這增加了他們對你的
+請求信心。特別是,在沒有簽名標籤的情況下,Linus 不會從像 Github 這樣的公共
+託管站點拉請求。
+
+創建此類簽名的第一步是生成一個 GNRPG 密鑰,並由一個或多個核心內核開發人員對
+其進行簽名。這一步對新開發人員來說可能很困難,但沒有辦法繞過它。參加會議是
+找到可以簽署您的密鑰的開發人員的好方法。
+
+一旦您在Git 中準備了一個您希望有人拉的補丁系列,就用 ``git tag -s`` 創建一
+個簽名標記。這將創建一個新標記,標識該系列中的最後一次提交,並包含用您的私
+鑰創建的簽名。您還可以將changelog樣式的消息添加到標記中;這是一個描述拉請求
+整體效果的理想位置。
+
+如果維護人員將要從中提取的樹不是您正在使用的存儲庫,請不要忘記將已簽名的標記
+顯式推送到公共樹。
+
+生成拉請求時,請使用已簽名的標記作爲目標。這樣的命令可以實現::
+
+  git request-pull master git://my.public.tree/linux.git my-signed-tag
+
+參考文獻
+--------
+
+Andrew Morton, "The perfect patch" (tpp).
+  <https://www.ozlabs.org/~akpm/stuff/tpp.txt>
+
+Jeff Garzik, "Linux kernel patch submission format".
+  <https://web.archive.org/web/20180829112450/http://linux.yyz.us/patch-format.html>
+
+Greg Kroah-Hartman, "How to piss off a kernel subsystem maintainer".
+  <http://www.kroah.com/log/linux/maintainer.html>
+
+  <http://www.kroah.com/log/linux/maintainer-02.html>
+
+  <http://www.kroah.com/log/linux/maintainer-03.html>
+
+  <http://www.kroah.com/log/linux/maintainer-04.html>
+
+  <http://www.kroah.com/log/linux/maintainer-05.html>
+
+  <http://www.kroah.com/log/linux/maintainer-06.html>
+
+NO!!!! No more huge patch bombs to linux-kernel@vger.kernel.org people!
+  <https://lore.kernel.org/r/20050711.125305.08322243.davem@davemloft.net>
+
+Kernel Documentation/process/coding-style.rst:
+  :ref:`Documentation/translations/zh_TW/process/coding-style.rst <tw_codingstyle>`
+
+Linus Torvalds's mail on the canonical patch format:
+  <https://lore.kernel.org/r/Pine.LNX.4.58.0504071023190.28951@ppc970.osdl.org>
+
+Andi Kleen, "On submitting kernel patches"
+  Some strategies to get difficult or controversial changes in.
+
+  http://halobates.de/on-submitting-patches.pdf
+
diff --git a/Documentation/translations/zh_TW/process/volatile-considered-harmful.rst b/Documentation/translations/zh_TW/process/volatile-considered-harmful.rst
new file mode 100644
index 000000000000..097fe80352cb
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/volatile-considered-harmful.rst
@@ -0,0 +1,110 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _tw_volatile_considered_harmful:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/volatile-considered-harmful.rst
+           <volatile_considered_harmful>`
+
+如果想評論或更新本文的內容,請直接聯繫原文檔的維護者。如果你使用英文
+交流有困難的話,也可以向中文版維護者求助。如果本翻譯更新不及時或者翻
+譯存在問題,請聯繫中文版維護者::
+
+        英文版維護者: Jonathan Corbet <corbet@lwn.net>
+        中文版維護者: 伍鵬  Bryan Wu <bryan.wu@analog.com>
+        中文版翻譯者: 伍鵬  Bryan Wu <bryan.wu@analog.com>
+        中文版校譯者: 張漢輝  Eugene Teo <eugeneteo@kernel.sg>
+                       楊瑞  Dave Young <hidave.darkstar@gmail.com>
+                       時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+                       胡皓文 Hu Haowen <src.res@email.cn>
+
+爲什麼不應該使用「volatile」類型
+================================
+
+C程式設計師通常認爲volatile表示某個變量可以在當前執行的線程之外被改變;因此,在內核
+中用到共享數據結構時,常常會有C程式設計師喜歡使用volatile這類變量。換句話說,他們經
+常會把volatile類型看成某種簡易的原子變量,當然它們不是。在內核中使用volatile幾
+乎總是錯誤的;本文檔將解釋爲什麼這樣。
+
+理解volatile的關鍵是知道它的目的是用來消除優化,實際上很少有人真正需要這樣的應
+用。在內核中,程式設計師必須防止意外的並發訪問破壞共享的數據結構,這其實是一個完全
+不同的任務。用來防止意外並發訪問的保護措施,可以更加高效的避免大多數優化相關的
+問題。
+
+像volatile一樣,內核提供了很多原語來保證並發訪問時的數據安全(自旋鎖, 互斥量,內
+存屏障等等),同樣可以防止意外的優化。如果可以正確使用這些內核原語,那麼就沒有
+必要再使用volatile。如果仍然必須使用volatile,那麼幾乎可以肯定在代碼的某處有一
+個bug。在正確設計的內核代碼中,volatile能帶來的僅僅是使事情變慢。
+
+思考一下這段典型的內核代碼::
+
+    spin_lock(&the_lock);
+    do_something_on(&shared_data);
+    do_something_else_with(&shared_data);
+    spin_unlock(&the_lock);
+
+如果所有的代碼都遵循加鎖規則,當持有the_lock的時候,不可能意外的改變shared_data的
+值。任何可能訪問該數據的其他代碼都會在這個鎖上等待。自旋鎖原語跟內存屏障一樣—— 它
+們顯式的用來書寫成這樣 —— 意味著數據訪問不會跨越它們而被優化。所以本來編譯器認爲
+它知道在shared_data裡面將有什麼,但是因爲spin_lock()調用跟內存屏障一樣,會強制編
+譯器忘記它所知道的一切。那麼在訪問這些數據時不會有優化的問題。
+
+如果shared_data被聲名爲volatile,鎖操作將仍然是必須的。就算我們知道沒有其他人正在
+使用它,編譯器也將被阻止優化對臨界區內shared_data的訪問。在鎖有效的同時,
+shared_data不是volatile的。在處理共享數據的時候,適當的鎖操作可以不再需要
+volatile —— 並且是有潛在危害的。
+
+volatile的存儲類型最初是爲那些內存映射的I/O寄存器而定義。在內核里,寄存器訪問也應
+該被鎖保護,但是人們也不希望編譯器「優化」臨界區內的寄存器訪問。內核里I/O的內存訪問
+是通過訪問函數完成的;不贊成通過指針對I/O內存的直接訪問,並且不是在所有體系架構上
+都能工作。那些訪問函數正是爲了防止意外優化而寫的,因此,再說一次,volatile類型不
+是必需的。
+
+另一種引起用戶可能使用volatile的情況是當處理器正忙著等待一個變量的值。正確執行一
+個忙等待的方法是::
+
+    while (my_variable != what_i_want)
+        cpu_relax();
+
+cpu_relax()調用會降低CPU的能量消耗或者讓位於超線程雙處理器;它也作爲內存屏障一樣出
+現,所以,再一次,volatile不是必需的。當然,忙等待一開始就是一種反常規的做法。
+
+在內核中,一些稀少的情況下volatile仍然是有意義的:
+
+  - 在一些體系架構的系統上,允許直接的I/0內存訪問,那麼前面提到的訪問函數可以使用
+    volatile。基本上,每一個訪問函數調用它自己都是一個小的臨界區域並且保證了按照
+    程式設計師期望的那樣發生訪問操作。
+
+  - 某些會改變內存的內聯彙編代碼雖然沒有什麼其他明顯的附作用,但是有被GCC刪除的可
+    能性。在彙編聲明中加上volatile關鍵字可以防止這種刪除操作。
+
+  - Jiffies變量是一種特殊情況,雖然每次引用它的時候都可以有不同的值,但讀jiffies
+    變量時不需要任何特殊的加鎖保護。所以jiffies變量可以使用volatile,但是不贊成
+    其他跟jiffies相同類型變量使用volatile。Jiffies被認爲是一種「愚蠢的遺留物"
+    (Linus的話)因爲解決這個問題比保持現狀要麻煩的多。
+
+  - 由於某些I/0設備可能會修改連續一致的內存,所以有時,指向連續一致內存的數據結構
+    的指針需要正確的使用volatile。網絡適配器使用的環狀緩存區正是這類情形的一個例
+    子,其中適配器用改變指針來表示哪些描述符已經處理過了。
+
+對於大多代碼,上述幾種可以使用volatile的情況都不適用。所以,使用volatile是一種
+bug並且需要對這樣的代碼額外仔細檢查。那些試圖使用volatile的開發人員需要退一步想想
+他們真正想實現的是什麼。
+
+非常歡迎刪除volatile變量的補丁 - 只要證明這些補丁完整的考慮了並發問題。
+
+注釋
+----
+
+[1] https://lwn.net/Articles/233481/
+[2] https://lwn.net/Articles/233482/
+
+致謝
+----
+
+最初由Randy Dunlap推動並作初步研究
+由Jonathan Corbet撰寫
+參考Satyam Sharma,Johannes Stezenbach,Jesper Juhl,Heikki Orsila,
+H. Peter Anvin,Philipp Hahn和Stefan Richter的意見改善了本檔。
+
-- 
2.25.1


^ permalink raw reply related	[relevance 1%]

* [PATCH v4 2/2] docs/zh_TW: add translations for zh_TW/process
  @ 2021-07-21 14:25  1% ` Hu Haowen
    1 sibling, 0 replies; 200+ results
From: Hu Haowen @ 2021-07-21 14:25 UTC (permalink / raw)
  To: corbet; +Cc: linux-doc, linux-kernel, Hu Haowen

Create new translations for zh_TW/process and link them to index.

Signed-off-by: Hu Haowen <src.res@email.cn>
---
 Documentation/translations/zh_TW/index.rst    |  10 +-
 .../translations/zh_TW/process/1.Intro.rst    | 199 ++++
 .../translations/zh_TW/process/2.Process.rst  | 369 +++++++
 .../zh_TW/process/3.Early-stage.rst           | 172 ++++
 .../translations/zh_TW/process/4.Coding.rst   | 297 ++++++
 .../translations/zh_TW/process/5.Posting.rst  | 251 +++++
 .../zh_TW/process/6.Followthrough.rst         | 156 +++
 .../zh_TW/process/7.AdvancedTopics.rst        | 137 +++
 .../zh_TW/process/8.Conclusion.rst            |  74 ++
 .../code-of-conduct-interpretation.rst        | 112 ++
 .../zh_TW/process/code-of-conduct.rst         |  76 ++
 .../zh_TW/process/coding-style.rst            | 958 ++++++++++++++++++
 .../zh_TW/process/development-process.rst     |  30 +
 .../zh_TW/process/email-clients.rst           | 252 +++++
 .../process/embargoed-hardware-issues.rst     | 232 +++++
 .../translations/zh_TW/process/howto.rst      | 500 +++++++++
 .../translations/zh_TW/process/index.rst      |  67 ++
 .../zh_TW/process/kernel-driver-statement.rst | 203 ++++
 .../process/kernel-enforcement-statement.rst  | 155 +++
 .../zh_TW/process/license-rules.rst           | 374 +++++++
 .../zh_TW/process/magic-number.rst            | 148 +++
 .../zh_TW/process/management-style.rst        | 211 ++++
 .../zh_TW/process/programming-language.rst    |  76 ++
 .../zh_TW/process/stable-api-nonsense.rst     | 159 +++
 .../zh_TW/process/stable-kernel-rules.rst     |  68 ++
 .../zh_TW/process/submit-checklist.rst        | 109 ++
 .../zh_TW/process/submitting-drivers.rst      | 164 +++
 .../zh_TW/process/submitting-patches.rst      | 686 +++++++++++++
 .../process/volatile-considered-harmful.rst   | 110 ++
 29 files changed, 6351 insertions(+), 4 deletions(-)
 create mode 100644 Documentation/translations/zh_TW/process/1.Intro.rst
 create mode 100644 Documentation/translations/zh_TW/process/2.Process.rst
 create mode 100644 Documentation/translations/zh_TW/process/3.Early-stage.rst
 create mode 100644 Documentation/translations/zh_TW/process/4.Coding.rst
 create mode 100644 Documentation/translations/zh_TW/process/5.Posting.rst
 create mode 100644 Documentation/translations/zh_TW/process/6.Followthrough.rst
 create mode 100644 Documentation/translations/zh_TW/process/7.AdvancedTopics.rst
 create mode 100644 Documentation/translations/zh_TW/process/8.Conclusion.rst
 create mode 100644 Documentation/translations/zh_TW/process/code-of-conduct-interpretation.rst
 create mode 100644 Documentation/translations/zh_TW/process/code-of-conduct.rst
 create mode 100644 Documentation/translations/zh_TW/process/coding-style.rst
 create mode 100644 Documentation/translations/zh_TW/process/development-process.rst
 create mode 100644 Documentation/translations/zh_TW/process/email-clients.rst
 create mode 100644 Documentation/translations/zh_TW/process/embargoed-hardware-issues.rst
 create mode 100644 Documentation/translations/zh_TW/process/howto.rst
 create mode 100644 Documentation/translations/zh_TW/process/index.rst
 create mode 100644 Documentation/translations/zh_TW/process/kernel-driver-statement.rst
 create mode 100644 Documentation/translations/zh_TW/process/kernel-enforcement-statement.rst
 create mode 100644 Documentation/translations/zh_TW/process/license-rules.rst
 create mode 100644 Documentation/translations/zh_TW/process/magic-number.rst
 create mode 100644 Documentation/translations/zh_TW/process/management-style.rst
 create mode 100644 Documentation/translations/zh_TW/process/programming-language.rst
 create mode 100644 Documentation/translations/zh_TW/process/stable-api-nonsense.rst
 create mode 100644 Documentation/translations/zh_TW/process/stable-kernel-rules.rst
 create mode 100644 Documentation/translations/zh_TW/process/submit-checklist.rst
 create mode 100644 Documentation/translations/zh_TW/process/submitting-drivers.rst
 create mode 100644 Documentation/translations/zh_TW/process/submitting-patches.rst
 create mode 100644 Documentation/translations/zh_TW/process/volatile-considered-harmful.rst

diff --git a/Documentation/translations/zh_TW/index.rst b/Documentation/translations/zh_TW/index.rst
index cab58e428825..76981b2111f6 100644
--- a/Documentation/translations/zh_TW/index.rst
+++ b/Documentation/translations/zh_TW/index.rst
@@ -22,9 +22,7 @@
 下面的文檔介紹了Linux內核原始碼的許可證(GPLv2)、如何在原始碼樹中正確標記
 單個文件的許可證、以及指向完整許可證文本的連結。
 
-TODOList:
-
-* Documentation/translations/zh_TW/process/license-rules.rst
+Documentation/translations/zh_TW/process/license-rules.rst
 
 用戶文檔
 --------
@@ -67,9 +65,13 @@ TODOlist:
 開發人員做出貢獻。與任何大型社區一樣,知道如何完成任務將使得更改合併的過程
 變得更加容易。
 
+.. toctree::
+   :maxdepth: 2
+
+   process/index
+
 TODOList:
 
-* process/index
 * dev-tools/index
 * doc-guide/index
 * kernel-hacking/index
diff --git a/Documentation/translations/zh_TW/process/1.Intro.rst b/Documentation/translations/zh_TW/process/1.Intro.rst
new file mode 100644
index 000000000000..ca2b931be6c5
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/1.Intro.rst
@@ -0,0 +1,199 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/1.Intro.rst <development_process_intro>`
+
+:Translator:
+
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+
+:校譯:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+.. _tw_development_process_intro:
+
+引言
+====
+
+內容提要
+--------
+
+本節的其餘部分涵蓋了內核開發的過程,以及開發人員及其僱主在這方面可能遇到的
+各種問題。有很多原因使內核代碼應被合併到正式的(「主線」)內核中,包括對用戶
+的自動可用性、多種形式的社區支持以及影響內核開發方向的能力。提供給Linux內核
+的代碼必須在與GPL兼容的許可證下可用。
+
+:ref:`tw_development_process` 介紹了開發過程、內核發布周期和合併窗口的機制。
+涵蓋了補丁開發、審查和合併周期中的各個階段。還有一些關於工具和郵件列表的討論?
+鼓勵希望開始內核開發的開發人員跟蹤並修復缺陷以作爲初步練習。
+
+
+:ref:`tw_development_early_stage` 包括項目的早期規劃,重點是儘快讓開發社區
+參與進來。
+
+:ref:`tw_development_coding` 是關於編程過程的;介紹了其他開發人員遇到的幾個
+陷阱。也涵蓋了對補丁的一些要求,並且介紹了一些工具,這些工具有助於確保內核
+補丁是正確的。
+
+:ref:`tw_development_posting` 描述發布補丁以供評審的過程。爲了讓開發社區能
+認真對待,補丁必須被正確格式化和描述,並且必須發送到正確的地方。遵循本節中的
+建議有助於確保您的工作能被較好地接納。
+
+:ref:`tw_development_followthrough` 介紹了發布補丁之後發生的事情;工作在這時
+還遠遠沒有完成。與審閱者一起工作是開發過程中的一個重要部分;本節提供了一些
+關於如何在這個重要階段避免問題的提示。當補丁被合併到主線中時,開發人員要注意
+不要假定任務已經完成。
+
+:ref:`tw_development_advancedtopics` 介紹了兩個「高級」主題:使用Git管理補丁
+和查看其他人發布的補丁。
+
+:ref:`tw_development_conclusion` 總結了有關內核開發的更多信息,附帶有相關資源
+連結。
+
+這個文檔是關於什麼的
+--------------------
+
+Linux內核有超過800萬行代碼,每個版本的貢獻者超過1000人,是現存最大、最活躍的
+免費軟體項目之一。從1991年開始,這個內核已經發展成爲一個最好的作業系統組件,
+運行在袖珍數位音樂播放器、桌上型電腦、現存最大的超級計算機以及所有類型的系統上。
+它是一種適用於幾乎任何情況的健壯、高效和可擴展的解決方案。
+
+隨著Linux的發展,希望參與其開發的開發人員(和公司)的數量也在增加。硬體供應商
+希望確保Linux能夠很好地支持他們的產品,使這些產品對Linux用戶具有吸引力。嵌入
+式系統供應商使用Linux作爲集成產品的組件,希望Linux能夠儘可能地勝任手頭的任務。
+分銷商和其他基於Linux的軟體供應商切實關心Linux內核的功能、性能和可靠性。最終
+用戶也常常希望修改Linux,使之能更好地滿足他們的需求。
+
+Linux最引人注目的特性之一是這些開發人員可以訪問它;任何具備必要技能的人都可以
+改進Linux並影響其開發方向。專有產品不能提供這種開放性,這是自由軟體的一個特點。
+如果有什麼不同的話,那就是內核比大多數其他自由軟體項目更開放。一個典型的三個
+月內核開發周期可以涉及1000多個開發人員,他們爲100多個不同的公司(或者根本不
+隸屬公司)工作。
+
+與內核開發社區合作並不是特別困難。但儘管如此,仍有許多潛在的貢獻者在嘗試做
+內核工作時遇到了困難。內核社區已經發展出自己獨特的操作方式,使其能夠在每天
+都要更改數千行代碼的環境中順利運行(並生成高質量的產品)。因此,Linux內核開發
+過程與專有的開發模式有很大的不同也就不足爲奇了。
+
+對於新開發人員來說,內核的開發過程可能會讓人感到奇怪和恐懼,但這背後有充分的
+理由和堅實的經驗。一個不了解內核社區工作方式的開發人員(或者更糟的是,他們
+試圖拋棄或規避之)會得到令人沮喪的體驗。開發社區在幫助那些試圖學習的人的同時,
+沒有時間幫助那些不願意傾聽或不關心開發過程的人。
+
+希望閱讀本文的人能夠避免這種令人沮喪的經歷。這些材料很長,但閱讀它們時所做的
+努力會在短時間內得到回報。開發社區總是需要能讓內核變更好的開發人員;下面的
+文字應該幫助您或爲您工作的人員加入我們的社區。
+
+致謝
+----
+
+本文檔由Jonathan Corbet <corbet@lwn.net> 撰寫。以下人員的建議使之更爲完善:
+Johannes Berg, James Berry, Alex Chiang, Roland Dreier, Randy Dunlap,
+Jake Edge, Jiri Kosina, Matt Mackall, Arthur Marsh, Amanda McPherson,
+Andrew Morton, Andrew Price, Tsugikazu Shibata 和 Jochen Voß 。
+
+這項工作得到了Linux基金會的支持,特別感謝Amanda McPherson,他看到了這項工作
+的價值並將其變成現實。
+
+代碼進入主線的重要性
+--------------------
+
+有些公司和開發人員偶爾會想,爲什麼他們要費心學習如何與內核社區合作,並將代碼
+放入主線內核(「主線」是由Linus Torvalds維護的內核,Linux發行商將其用作基礎)。
+在短期內,貢獻代碼看起來像是一種可以避免的開銷;維護獨立代碼並直接支持用戶
+似乎更容易。事實上,保持代碼獨立(「樹外」)是在經濟上是錯誤的。
+
+爲了說明樹外代碼成本,下面給出內核開發過程的一些相關方面;本文稍後將更詳細地
+討論其中的大部分內容。請考慮:
+
+- 所有Linux用戶都可以使用合併到主線內核中的代碼。它將自動出現在所有啓用它的
+  發行版上。無需驅動程序磁碟、額外下載,也不需要爲多個發行版的多個版本提供
+  支持;這一切將方便所有開發人員和用戶。併入主線解決了大量的分發和支持問題。
+
+- 當內核開發人員努力維護一個穩定的用戶空間接口時,內核內部API處於不斷變化之中。
+  不維持穩定的內部接口是一個慎重的設計決策;它允許在任何時候進行基本的改進,
+  並產出更高質量的代碼。但該策略導致結果是,若要使用新的內核,任何樹外代碼都
+  需要持續的維護。維護樹外代碼會需要大量的工作才能使代碼保持正常運行。
+
+  相反,位於主線中的代碼不需要這樣做,因爲基本規則要求進行API更改的任何開發
+  人員也必須修復由於該更改而破壞的任何代碼。因此,合併到主線中的代碼大大降低
+  了維護成本。
+
+- 除此之外,內核中的代碼通常會被其他開發人員改進。您授權的用戶社區和客戶對您
+  產品的改進可能會令人驚喜。
+
+- 內核代碼在合併到主線之前和之後都要經過審查。無論原始開發人員的技能有多強,
+  這個審查過程總是能找到改進代碼的方法。審查經常發現嚴重的錯誤和安全問題。
+  對於在封閉環境中開發的代碼尤其如此;這種代碼從外部開發人員的審查中獲益匪淺。
+  樹外代碼是低質量代碼。
+
+- 參與開發過程是您影響內核開發方向的方式。旁觀者的抱怨會被聽到,但是活躍的
+  開發人員有更強的聲音——並且能夠實現使內核更好地滿足其需求的更改。
+
+- 當單獨維護代碼時,總是存在第三方爲類似功能提供不同實現的可能性。如果發生
+  這種情況,合併代碼將變得更加困難——甚至成爲不可能。之後,您將面臨以下令人
+  不快的選擇:(1)無限期地維護樹外的非標準特性,或(2)放棄代碼並將用戶遷移
+  到樹內版本。
+
+- 代碼的貢獻是使整個流程工作的根本。通過貢獻代碼,您可以向內核添加新功能,並
+  提供其他內核開發人員使用的功能和示例。如果您已經爲Linux開發了代碼(或者正在
+  考慮這樣做),那麼您顯然對這個平台的持續成功感興趣;貢獻代碼是確保成功的
+  最好方法之一。
+
+上述所有理由都適用於任何樹外內核代碼,包括以專有的、僅二進位形式分發的代碼。
+然而,在考慮任何類型的純二進位內核代碼分布之前,還需要考慮其他因素。包括:
+
+- 圍繞專有內核模塊分發的法律問題其實較爲模糊;相當多的內核版權所有者認爲,
+  大多數僅二進位的模塊是內核的派生產品,因此,它們的分發違反了GNU通用公共
+  許可證(下面將詳細介紹)。本文作者不是律師,本文檔中的任何內容都不可能被
+  視爲法律建議。封閉原始碼模塊的真實法律地位只能由法院決定。但不管怎樣,困擾
+  這些模塊的不確定性仍然存在。
+
+- 二進位模塊大大增加了調試內核問題的難度,以至於大多數內核開發人員甚至都不會
+  嘗試。因此,只分發二進位模塊將使您的用戶更難從社區獲得支持。
+
+- 對於僅二進位的模塊的發行者來說,支持也更加困難,他們必須爲他們希望支持的
+  每個發行版和每個內核版本提供不同版本的模塊。爲了提供較爲全面的覆蓋範圍,
+  可能需要一個模塊的幾十個構建,並且每次升級內核時,您的用戶都必須單獨升級
+  這些模塊。
+
+- 上面提到的關於代碼評審的所有問題都更加存在於封閉原始碼中。由於該代碼根本
+  不可得,因此社區無法對其進行審查,毫無疑問,它將存在嚴重問題。
+
+尤其是嵌入式系統的製造商,可能會傾向於忽視本節中所說的大部分內容;因爲他們
+相信自己正在商用一種使用凍結內核版本的獨立產品,在發布後不需要再進行開發。
+這個論點忽略了廣泛的代碼審查的價值以及允許用戶向產品添加功能的價值。但這些
+產品的商業壽命有限,之後必須發布新版本的產品。在這一點上,代碼在主線上並得到
+良好維護的供應商將能夠更好地占位,以使新產品快速上市。
+
+許可
+----
+
+代碼是根據一些許可證提供給Linux內核的,但是所有代碼都必須與GNU通用公共許可
+證(GPLV2)的版本2兼容,該版本是覆蓋整個內核分發的許可證。在實踐中,這意味
+著所有代碼貢獻都由GPLv2(可選地,語言允許在更高版本的GPL下分發)或3子句BSD
+許可(New BSD License,譯者注)覆蓋。任何不包含在兼容許可證中的貢獻都不會
+被接受到內核中。
+
+貢獻給內核的代碼不需要(或請求)版權分配。合併到主線內核中的所有代碼都保留
+其原始所有權;因此,內核現在擁有數千個所有者。
+
+這種所有權結構也暗示著,任何改變內核許可的嘗試都註定會失敗。很少有實際情況
+可以獲得所有版權所有者的同意(或者從內核中刪除他們的代碼)。因此,尤其是在
+可預見的將來,許可證不大可能遷移到GPL的版本3。
+
+所有貢獻給內核的代碼都必須是合法的免費軟體。因此,不接受匿名(或化名)貢獻
+者的代碼。所有貢獻者都需要在他們的代碼上「sign off(簽發)」,聲明代碼可以
+在GPL下與內核一起分發。無法提供未被其所有者許可爲免費軟體的代碼,或可能爲
+內核造成版權相關問題的代碼(例如,由缺乏適當保護的反向工程工作派生的代碼)
+不能被接受。
+
+有關版權問題的提問在Linux開發郵件列表中很常見。這樣的問題通常會得到不少答案,
+但請記住,回答這些問題的人不是律師,不能提供法律諮詢。如果您有關於Linux原始碼
+的法律問題,沒有什麼可以代替諮詢了解這一領域的律師。依賴從技術郵件列表中獲得
+的答案是一件冒險的事情。
+
+
diff --git a/Documentation/translations/zh_TW/process/2.Process.rst b/Documentation/translations/zh_TW/process/2.Process.rst
new file mode 100644
index 000000000000..b01cdd3a39ae
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/2.Process.rst
@@ -0,0 +1,369 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/2.Process.rst <development_process>`
+
+:Translator:
+
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+
+:校譯:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+.. _tw_development_process:
+
+開發流程如何進行
+================
+
+90年代早期的Linux內核開發是一件相當鬆散的事情,涉及的用戶和開發人員相對較少。
+由於擁有數以百萬計的用戶羣,且每年有大約2000名開發人員參與進來,內核因此必須
+發展出許多既定流程來保證開發的順利進行。要參與到流程中來,需要對此流程的進行
+方式有一個紮實的理解。
+
+總覽
+----
+
+內核開發人員使用一個鬆散的基於時間的發布過程,每兩到三個月發布一次新的主要
+內核版本。最近的發布歷史記錄如下:
+
+	======  =================
+	5.0	2019年3月3日
+	5.1	2019年5月5日
+	5.2	2019年7月7日
+	5.3	2019年9月15日
+	5.4	2019年11月24日
+	5.5	2020年1月6日
+	======  =================
+
+每個5.x版本都是一個主要的內核版本,具有新特性、內部API更改等等。一個典型的5.x
+版本包含大約13000個變更集,變更了幾十萬行代碼。因此,5.x是Linux內核開發的前
+沿;內核使用滾動開發模型,不斷集成重大變化。
+
+對於每個版本的補丁合併,遵循一個相對簡單的規則。在每個開發周期的開頭,「合併
+窗口」被打開。這時,被認爲足夠穩定(並且被開發社區接受)的代碼被合併到主線內
+核中。在這段時間內,新開發周期的大部分變更(以及所有主要變更)將以接近每天
+1000次變更(「補丁」或「變更集」)的速度合併。
+
+(順便說一句,值得注意的是,合併窗口期間集成的更改並不是憑空產生的;它們是經
+提前收集、測試和分級的。稍後將詳細描述該過程的工作方式。)
+
+合併窗口持續大約兩周。在這段時間結束時,LinusTorvalds將聲明窗口已關閉,並
+釋放第一個「rc」內核。例如,對於目標爲5.6的內核,在合併窗口結束時發生的釋放
+將被稱爲5.6-rc1。-rc1 版本是一個信號,表示合併新特性的時間已經過去,穩定下一
+個內核的時間已經到來。
+
+在接下來的6到10周內,只有修復問題的補丁才應該提交給主線。有時會允許更大的
+更改,但這種情況很少發生;試圖在合併窗口外合併新功能的開發人員往往受不到
+友好的接待。一般來說,如果您錯過了給定特性的合併窗口,最好的做法是等待下一
+個開發周期。(偶爾會對未支持硬體的驅動程序進行例外;如果它們不改變已有代碼,
+則不會導致回歸,應該可以隨時被安全地加入)。
+
+隨著修復程序進入主線,補丁速度將隨著時間的推移而變慢。Linus大約每周發布一次
+新的-rc內核;在內核被認爲足夠穩定並最終發布前,一般會達到-rc6到-rc9之間。
+然後,整個過程又重新開始了。
+
+例如,這裡是5.4的開發周期進行情況(2019年):
+
+	==============  ==============================
+	九月 15         5.3 穩定版發布
+	九月 30         5.4-rc1 合併窗口關閉
+	十月 6          5.4-rc2
+	十月 13         5.4-rc3
+	十月 20         5.4-rc4
+	十月 27         5.4-rc5
+	十一月 3        5.4-rc6
+	十一月 10       5.4-rc7
+	十一月 17       5.4-rc8
+	十一月 24       5.4 穩定版發布
+	==============  ==============================
+
+開發人員如何決定何時結束開發周期並創建穩定版本?最重要的指標是以前版本的
+回歸列表。不歡迎出現任何錯誤,但是那些破壞了以前能工作的系統的錯誤被認爲是
+特別嚴重的。因此,導致回歸的補丁是不受歡迎的,很可能在穩定期內刪除。
+
+開發人員的目標是在穩定發布之前修復所有已知的回歸。在現實世界中,這種完美是
+很難實現的;在這種規模的項目中,變數太多了。需要說明的是,延遲最終版本只會
+使問題變得更糟;等待下一個合併窗口的更改將變多,導致下次出現更多的回歸錯誤。
+因此,大多數5.x內核都有一些已知的回歸錯誤,不過,希望沒有一個是嚴重的。
+
+一旦一個穩定的版本發布,它的持續維護工作就被移交給「穩定團隊」,目前由
+Greg Kroah-Hartman領導。穩定團隊將使用5.x.y編號方案不定期地發布穩定版本的
+更新。要合入更新版本,補丁必須(1)修復一個重要的缺陷,且(2)已經合併到
+下一個開發版本主線中。內核通常會在其初始版本後的一個以上的開發周期內收到
+穩定版更新。例如,5.2內核的歷史如下(2019年):
+
+	==============  ===============================
+        七月 7 	        5.2 穩定版發布
+	七月 13	        5.2.1
+	七月 21	        5.2.2
+	七月 26	        5.2.3
+	七月 28	        5.2.4
+	七月 31	        5.2.5
+	...	        ...
+	十月 11         5.2.21
+	==============  ===============================
+
+5.2.21是5.2版本的最終穩定更新。
+
+有些內核被指定爲「長期」內核;它們將得到更長時間的支持。在本文中,當前的長期
+內核及其維護者是:
+
+	======  ================================	================
+	3.16	Ben Hutchings				(長期穩定內核)
+	4.4	Greg Kroah-Hartman & Sasha Levin	(長期穩定內核)
+	4.9	Greg Kroah-Hartman & Sasha Levin
+	4.14	Greg Kroah-Hartman & Sasha Levin
+	4.19	Greg Kroah-Hartman & Sasha Levin
+	5.4	Greg Kroah-Hartman & Sasha Levin
+	======  ================================	================
+
+長期支持內核的選擇純粹是維護人員是否有需求和時間來維護該版本的問題。
+目前還沒有爲即將發布的任何特定版本提供長期支持的已知計劃。
+
+補丁的生命周期
+--------------
+
+補丁不會直接從開發人員的鍵盤進入主線內核。相反,有一個稍微複雜(如果有些非
+正式)的過程,旨在確保對每個補丁進行質量審查,並確保每個補丁實現了一個在主線
+中需要的更改。對於小的修復,這個過程可能會很快完成,,而對於較大或有爭議的
+變更,可能會持續數年。許多開發人員的沮喪來自於對這個過程缺乏理解或者試圖繞過它。
+
+爲了減少這種挫敗,本文將描述補丁如何進入內核。下面的介紹以一種較爲理想化的
+方式描述了這個過程。更詳細的過程將在後面的章節中介紹。
+
+補丁通常要經歷以下階段:
+
+- 設計。這就是補丁的真正需求——以及滿足這些需求的方式——所在。設計工作通常
+  是在不涉及社區的情況下完成的,但是如果可能的話,最好是在公開的情況下完成
+  這項工作;這樣可以節省很多稍後再重新設計的時間。
+
+- 早期評審。補丁被發布到相關的郵件列表中,列表中的開發人員會回復他們可能有
+  的任何評論。如果一切順利的話,這個過程應該會發現補丁的任何主要問題。
+
+- 更廣泛的評審。當補丁接近準備好納入主線時,它應該被相關的子系統維護人員
+  接受——儘管這種接受並不能保證補丁會一直延伸到主線。補丁將出現在維護人員的
+  子系統樹中,並進入 -next 樹(如下所述)。當流程進行時,此步驟將會對補丁
+  進行更廣泛的審查,並發現由於將此補丁與其他人所做的工作合併而導致的任何
+  問題。
+
+- 請注意,大多數維護人員也有日常工作,因此合併補丁可能不是他們的最優先工作。
+  如果您的補丁得到了需要更改的反饋,那麼您應該進行這些更改,或者解釋爲何
+  不應該進行這些更改。如果您的補丁沒有評審意見,也沒有被其相應的子系統或
+  驅動程序維護者接受,那麼您應該堅持不懈地將補丁更新到當前內核使其可被正常
+  應用,並不斷地發送它以供審查和合併。
+
+- 合併到主線。最終,一個成功的補丁將被合併到由LinusTorvalds管理的主線存儲庫
+  中。此時可能會出現更多的評論和/或問題;對開發人員來說應對這些問題並解決
+  出現的任何問題仍很重要。
+
+- 穩定版發布。大量用戶可能受此補丁影響,因此可能再次出現新的問題。
+
+- 長期維護。雖然開發人員在合併代碼後可能會忘記代碼,但這種行爲往往會給開發
+  社區留下不良印象。合併代碼消除了一些維護負擔,因爲其他人將修復由API更改
+  引起的問題。但是,如果代碼要長期保持可用,原始開發人員應該繼續爲代碼負責。
+
+內核開發人員(或他們的僱主)犯的最大錯誤之一是試圖將流程簡化爲一個「合併到
+主線」步驟。這種方法總是會讓所有相關人員感到沮喪。
+
+補丁如何進入內核
+----------------
+
+只有一個人可以將補丁合併到主線內核存儲庫中:LinusTorvalds。但是,在進入
+2.6.38內核的9500多個補丁中,只有112個(大約1.3%)是由Linus自己直接選擇的。
+內核項目已經發展到一個沒有一個開發人員可以在沒有支持的情況下檢查和選擇每個
+補丁的規模。內核開發人員處理這種增長的方式是使用圍繞信任鏈構建的助理系統。
+
+內核代碼庫在邏輯上被分解爲一組子系統:網絡、特定體系結構支持、內存管理、視
+頻設備等。大多數子系統都有一個指定的維護人員,其總體負責該子系統中的代碼。
+這些子系統維護者(鬆散地)是他們所管理的內核部分的「守門員」;他們(通常)
+會接受一個補丁以包含到主線內核中。
+
+子系統維護人員每個人都管理著自己版本的內核原始碼樹,通常(並非總是)使用Git。
+Git等工具(以及Quilt或Mercurial等相關工具)允許維護人員跟蹤補丁列表,包括作者
+信息和其他元數據。在任何給定的時間,維護人員都可以確定他或她的存儲庫中的哪
+些補丁在主線中找不到。
+
+當合併窗口打開時,頂級維護人員將要求Linus從存儲庫中「拉出」他們爲合併選擇
+的補丁。如果Linus同意,補丁流將流向他的存儲庫,成爲主線內核的一部分。
+Linus對拉取中接收到的特定補丁的關注程度各不相同。很明顯,有時他看起來很
+關注。但是一般來說,Linus相信子系統維護人員不會向上游發送壞補丁。
+
+子系統維護人員反過來也可以從其他維護人員那裡獲取補丁。例如,網絡樹是由首先
+在專用於網絡設備驅動程序、無線網絡等的樹中積累的補丁構建的。此存儲鏈可以
+任意長,但很少超過兩個或三個連結。由於鏈中的每個維護者都信任那些管理較低
+級別樹的維護者,所以這個過程稱爲「信任鏈」。
+
+顯然,在這樣的系統中,獲取內核補丁取決於找到正確的維護者。直接向Linus發送
+補丁通常不是正確的方法。
+
+Next 樹
+-------
+
+子系統樹鏈引導補丁流到內核,但它也提出了一個有趣的問題:如果有人想查看爲
+下一個合併窗口準備的所有補丁怎麼辦?開發人員將感興趣的是,還有什麼其他的
+更改有待解決,以了解是否存在需要擔心的衝突;例如,更改核心內核函數原型的
+修補程序將與使用該函數舊形式的任何其他修補程序衝突。審查人員和測試人員希望
+在所有這些變更到達主線內核之前,能夠訪問它們的集成形式的變更。您可以從所有
+相關的子系統樹中提取更改,但這將是一項複雜且容易出錯的工作。
+
+解決方案以-next樹的形式出現,在這裡子系統樹被收集以供測試和審查。這些樹中
+由Andrew Morton維護的較老的一個,被稱爲「-mm」(用於內存管理,創建時爲此)。
+-mm 樹集成了一長串子系統樹中的補丁;它還包含一些旨在幫助調試的補丁。
+
+除此之外,-mm 還包含大量由Andrew直接選擇的補丁。這些補丁可能已經發布在郵件
+列表上,或者它們可能應用於內核中未指定子系統樹的部分。同時,-mm 作爲最後
+手段的子系統樹;如果沒有其他明顯的路徑可以讓補丁進入主線,那麼它很可能最
+終選擇-mm 樹。累積在-mm 中的各種補丁最終將被轉發到適當的子系統樹,或者直接
+發送到Linus。在典型的開發周期中,大約5-10%的補丁通過-mm 進入主線。
+
+當前-mm 補丁可在「mmotm」(-mm of the moment)目錄中找到:
+
+        https://www.ozlabs.org/~akpm/mmotm/
+
+然而,使用MMOTM樹可能會十分令人頭疼;它甚至可能無法編譯。
+
+下一個周期補丁合併的主要樹是linux-next,由Stephen Rothwell 維護。根據設計
+linux-next 是下一個合併窗口關閉後主線的快照。linux-next樹在Linux-kernel 和
+Linux-next 郵件列表中發布,可從以下位置下載:
+
+        https://www.kernel.org/pub/linux/kernel/next/
+
+Linux-next 已經成爲內核開發過程中不可或缺的一部分;在一個給定的合併窗口中合併
+的所有補丁都應該在合併窗口打開之前的一段時間內找到進入Linux-next 的方法。
+
+Staging 樹
+----------
+
+內核原始碼樹包含drivers/staging/目錄,其中有許多驅動程序或文件系統的子目錄
+正在被添加到內核樹中。它們在仍然需要更多的修正的時候可以保留在driver/staging/
+目錄中;一旦完成,就可以將它們移到內核中。這是一種跟蹤不符合Linux內核編碼或
+質量標準的驅動程序的方法,人們可能希望使用它們並跟蹤開發。
+
+Greg Kroah Hartman 目前負責維護staging 樹。仍需要修正的驅動程序將發送給他,
+每個驅動程序在drivers/staging/中都有自己的子目錄。除了驅動程序源文件之外,
+目錄中還應該有一個TODO文件。TODO文件列出了驅動程序需要接受的暫停的工作,
+以及驅動程序的任何補丁都應該抄送的人員列表。當前的規則要求,staging的驅動
+程序必須至少正確編譯。
+
+Staging 是一種讓新的驅動程序進入主線的相對容易的方法,它們會幸運地引起其他
+開發人員的注意,並迅速改進。然而,進入staging並不是故事的結尾;staging中
+沒有看到常規進展的代碼最終將被刪除。經銷商也傾向於相對不願意使用staging驅動
+程序。因此,在成爲一個合適的主線驅動的路上,staging 僅是一個中轉站。
+
+工具
+----
+
+從上面的文本可以看出,內核開發過程在很大程度上依賴於在不同方向上聚集補丁的
+能力。如果沒有適當強大的工具,整個系統將無法在任何地方正常工作。關於如何使用
+這些工具的教程遠遠超出了本文檔的範圍,但還是用一點篇幅介紹一些關鍵點。
+
+到目前爲止,內核社區使用的主要原始碼管理系統是git。Git是在自由軟體社區中開發
+的許多分布式版本控制系統之一。它非常適合內核開發,因爲它在處理大型存儲庫和
+大量補丁時性能非常好。它也以難以學習和使用而著稱,儘管隨著時間的推移它變得
+更好了。對於內核開發人員來說,對Git的某種熟悉幾乎是一種要求;即使他們不將它
+用於自己的工作,他們也需要Git來跟上其他開發人員(以及主線)正在做的事情。
+
+現在幾乎所有的Linux發行版都打包了Git。Git主頁位於:
+
+        https://git-scm.com/
+
+此頁面包含了文檔和教程的連結。
+
+在不使用git的內核開發人員中,最流行的選擇幾乎肯定是Mercurial:
+
+        http://www.seleric.com/mercurial/
+
+Mercurial與Git共享許多特性,但它提供了一個界面,許多人覺得它更易於使用。
+
+另一個值得了解的工具是Quilt:
+
+        https://savannah.nongnu.org/projects/quilt
+
+Quilt 是一個補丁管理系統,而不是原始碼管理系統。它不會隨著時間的推移跟蹤歷史;
+相反,它面向根據不斷發展的代碼庫跟蹤一組特定的更改。一些主要的子系統維護人員
+使用Quilt來管理打算向上游移動的補丁。對於某些樹的管理(例如-mm),quilt 是
+最好的工具。
+
+郵件列表
+--------
+
+大量的Linux內核開發工作是通過郵件列表完成的。如果不加入至少一個某個列表,
+就很難成爲社區中的一個「全功能」成員。但是,Linux郵件列表對開發人員來說也是
+一個潛在的危險,他們可能會被一堆電子郵件淹沒、違反Linux列表上使用的約定,
+或者兩者兼而有之。
+
+大多數內核郵件列表都在vger.kernel.org上運行;主列表位於:
+
+        http://vger.kernel.org/vger-lists.html
+
+不過,也有一些列表託管在別處;其中一些列表位於
+redhat.com/mailman/listinfo。
+
+當然,內核開發的核心郵件列表是linux-kernel。這個列表是一個令人生畏的地方:
+每天的信息量可以達到500條,噪音很高,談話技術性很強,且參與者並不總是表現出
+高度的禮貌。但是,沒有其他地方可以讓內核開發社區作爲一個整體聚集在一起;
+不使用此列表的開發人員將錯過重要信息。
+
+以下一些提示可以幫助在linux-kernel生存:
+
+- 將郵件轉移到單獨的文件夾,而不是主郵箱文件夾。我們必須能夠持續地忽略洪流。
+
+- 不要試圖跟上每一次談話——沒人會這樣。重要的是要篩選感興趣的主題(但請注意
+  長時間的對話可能會偏離原來的主題,儘管未改變電子郵件的主題)和參與的人。
+
+- 不要回復挑事的人。如果有人試圖激起憤怒,請忽略他們。
+
+- 當回復Linux內核電子郵件(或其他列表上的電子郵件)時,請爲所有相關人員保留
+  Cc: 抄送頭。如果沒有確實的理由(如明確的請求),則不應刪除收件人。一定要
+  確保你要回復的人在抄送列表中。這個慣例也使你不必在回覆郵件時明確要求被抄送。
+
+- 在提出問題之前,搜索列表存檔(和整個網絡)。有些開發人員可能會對那些顯然
+  沒有完成家庭作業的人感到不耐煩。
+
+- 避免頂部回復(把你的答案放在你要回復的引文上面的做法)。這會讓你的回答更難
+  理解,印象也很差。
+
+- 在正確的郵件列表發問。linux-kernel 可能是通用的討論場所,但它不是尋找所有
+  子系統開發人員的最佳場所。
+
+最後一點——找到正確的郵件列表——是開發人員常出錯的地方。在linux-kernel上
+提出與網絡相關的問題的人幾乎肯定會收到一個禮貌的建議,轉到netdev列表上提出,
+因爲這是大多數網絡開發人員經常出現的列表。還有其他列表可用於scsi、video4linux、
+ide、filesystem等子系統。查找郵件列表的最佳位置是與內核原始碼一起打包的
+MAINTAINERS文件。
+
+開始內核開發
+------------
+
+關於如何開始內核開發過程的問題很常見——個人和公司皆然。同樣常見的是失誤,這
+使得關係的開始比本應的更困難。
+
+公司通常希望聘請知名的開發人員來啓動開發團隊。實際上,這是一種有效的技術。
+但它也往往是昂貴的,而且對增加有經驗的內核開發人員的數量沒有多大幫助。考
+慮到時間投入,可以讓內部開發人員加快Linux內核的開發速度。利用這段時間可以
+讓僱主擁有一批既了解內核又了解公司的開發人員,還可以幫助培訓其他人。從中期
+來看,這通常是更有利可圖的方法。
+
+可以理解的是,單個開發人員往往對起步感到茫然。從一個大型項目開始可能會很
+嚇人;人們往往想先用一些較小的東西來試試水。由此,一些開發人員開始創建修補
+拼寫錯誤或輕微編碼風格問題的補丁。不幸的是,這樣的補丁會產生一定程度的噪音,
+這會分散整個開發社區的注意力,因此,它們越來越被人不看重。希望向社區介紹
+自己的新開發人員將無法通過這些方式獲得他們期待的反響。
+
+Andrew Morton 爲有抱負的內核開發人員提供了如下建議
+
+::
+
+	所有內核開發者的第一個項目肯定應該是「確保內核在您可以操作的所有
+	機器上始終完美運行」。通常的方法是和其他人一起解決問題(這可能需
+	要堅持!),但就是如此——這是內核開發的一部分。
+
+(http://lwn.net/articles/283982/)
+
+在沒有明顯問題需要解決的情況下,通常建議開發人員查看當前的回歸和開放缺陷
+列表。從來都不缺少需要解決的問題;通過解決這些問題,開發人員將從該過程獲得
+經驗,同時與開發社區的其他成員建立相互尊重。
+
diff --git a/Documentation/translations/zh_TW/process/3.Early-stage.rst b/Documentation/translations/zh_TW/process/3.Early-stage.rst
new file mode 100644
index 000000000000..ab2a45fd65a4
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/3.Early-stage.rst
@@ -0,0 +1,172 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/3.Early-stage.rst <development_early_stage>`
+
+:Translator:
+
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+
+:校譯:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+.. _tw_development_early_stage:
+
+早期規劃
+========
+
+當考慮一個Linux內核開發項目時,很可能會直接跳進去開始編碼。然而,與任何重要
+的項目一樣,許多成功的基礎最好是在第一行代碼編寫之前就打下。在早期計劃和
+溝通中花費一些時間可以在之後節省更多的時間。
+
+搞清問題
+--------
+
+與任何工程項目一樣,成功的內核改善從清晰描述要解決的問題開始。在某些情況
+下,這個步驟很容易:例如當某個特定硬體需要驅動程序時。不過,在其他情況下,
+很容易將實際問題與建議的解決方案混在一起,這可能會導致麻煩。
+
+舉個例子:幾年前,Linux音頻的開發人員尋求一種方法來運行應用程式,而不會因
+系統延遲過大而導致退出或其他問題。他們得到的解決方案是一個連接到Linux安全
+模塊(LSM)框架中的內核模塊;這個模塊可以配置爲允許特定的應用程式訪問實時
+調度程序。這個模塊被實現並發到linux-kernel郵件列表,在那裡它立即遇到了麻煩。
+
+對於音頻開發人員來說,這個安全模塊足以解決他們當前的問題。但是,對於更廣泛的
+內核社區來說,這被視爲對LSM框架的濫用(LSM框架並不打算授予他們原本不具備的
+進程特權),並對系統穩定性造成風險。他們首選的解決方案包括短期的通過rlimit
+機制進行實時調度訪問,以及長期的減少延遲的工作。
+
+然而,音頻社區無法超越他們實施的特定解決方案來看問題;他們不願意接受替代方案。
+由此產生的分歧使這些開發人員對整個內核開發過程感到失望;其中一個開發人員返回
+到audio列表並發布了以下內容:
+
+	有很多非常好的Linux內核開發人員,但他們往往會被一羣傲慢的傻瓜所壓倒。
+	試圖向這些人傳達用戶需求是浪費時間。他們太「聰明」了,根本聽不到少數
+	人的話。
+
+(http://lwn.net/articles/131776/)
+
+實際情況卻是不同的;與特定模塊相比,內核開發人員更關心系統穩定性、長期維護
+以及找到問題的正確解決方案。這個故事的寓意是把重點放在問題上——而不是具體的
+解決方案上——並在開始編寫代碼之前與開發社區討論這個問題。
+
+因此,在考慮一個內核開發項目時,我們應該得到一組簡短問題的答案:
+
+ - 需要解決的問題究竟是什麼?
+
+ - 受此問題影響的用戶有哪些?解決方案應該解決哪些使用案例?
+
+ - 內核現在爲何沒能解決這個問題?
+
+只有這樣,才能開始考慮可能的解決方案。
+
+
+早期討論
+--------
+
+在計劃內核開發項目時,在開始實施之前與社區進行討論是很有意義的。早期溝通可以
+通過多種方式節省時間和麻煩:
+
+ - 很可能問題是由內核以您不理解的方式解決的。Linux內核很大,具有許多不明顯
+   的特性和功能。並不是所有的內核功能都像人們所希望的那樣有文檔記錄,而且很
+   容易遺漏一些東西。某作者發布了一個完整的驅動程序,重複了一個其不
+   知道的現有驅動程序。重新發明現有輪子的代碼不僅浪費,而且不會被接受到主線
+   內核中。
+
+ - 建議的解決方案中可能有一些要素不適合併入主線。在編寫代碼之前,最好先了解
+   這樣的問題。
+
+ - 其他開發人員完全有可能考慮過這個問題;他們可能有更好的解決方案的想法,並且
+   可能願意幫助創建這個解決方案。
+
+在內核開發社區的多年經驗給了我們一個明確的教訓:閉門設計和開發的內核代碼總是
+有一些問題,這些問題只有在代碼發布到社區中時才會被發現。有時這些問題很嚴重,
+需要數月或數年的努力才能使代碼達到內核社區的標準。例如:
+
+ - 設計並實現了單處理器系統的DeviceScape網絡棧。只有使其適合於多處理器系統,
+   才能將其合併到主線中。在代碼中修改鎖等等是一項困難的任務;因此,這段代碼
+   (現在稱爲mac80211)的合併被推遲了一年多。
+
+ - Reiser4文件系統包含許多功能,核心內核開發人員認爲這些功能應該在虛擬文件
+   系統層中實現。它還包括一些特性,這些特性在不將系統暴露於用戶引起的死鎖的
+   情況下是不容易實現的。這些問題過遲發現——以及拒絕處理其中一些問題——已經
+   導致Reiser4置身主線內核之外。
+
+ - Apparmor安全模塊以被認爲不安全和不可靠的方式使用內部虛擬文件系統數據結構。
+   這種擔心(包括其他)使Apparmor多年來無法進入主線。
+
+在這些情況下,與內核開發人員的早期討論,可以避免大量的痛苦和額外的工作。
+
+找誰交流?
+----------
+
+當開發人員決定公開他們的計劃時,下一個問題是:我們從哪裡開始?答案是找到正確
+的郵件列表和正確的維護者。對於郵件列表,最好的方法是在維護者(MAINTAINERS)文件
+中查找要發布的相關位置。如果有一個合適的子系統列表,那麼其上發布通常比在
+linux-kernel上發布更可取;您更有可能接觸到在相關子系統中具有專業知識的開發
+人員,並且環境可能具支持性。
+
+找到維護人員可能會有點困難。同樣,維護者文件是開始的地方。但是,該文件往往不
+是最新的,並且並非所有子系統都在那裡顯示。實際上,維護者文件中列出的人員可能
+不是當前實際擔任該角色的人員。因此,當對聯繫誰有疑問時,一個有用的技巧是使用
+git(尤其是「git-log」)查看感興趣的子系統中當前活動的用戶。看看誰在寫補丁、
+誰會在這些補丁上加上Signed-off-by行簽名(如有)。這些人將是幫助新開發項目的
+最佳人選。
+
+找到合適的維護者有時是非常具有挑戰性的,以至於內核開發人員添加了一個腳本來
+簡化這個過程:
+
+::
+
+	.../scripts/get_maintainer.pl
+
+當給定「-f」選項時,此腳本將返回指定文件或目錄的當前維護者。如果在命令行上
+給出了一個補丁,它將列出可能接收補丁副本的維護人員。有許多選項可以調節
+get_maintainer.pl搜索維護者的嚴格程度;請小心使用更激進的選項,因爲最終結果
+可能會包括對您正在修改的代碼沒有真正興趣的開發人員。
+
+如果所有其他方法都失敗了,那麼與Andrew Morton交流是跟蹤特定代碼段維護人員
+的一種有效方法。
+
+何時郵寄?
+----------
+
+如果可能的話,在早期階段發布你的計劃只會更有幫助。描述正在解決的問題以及已經
+制定的關於如何實施的任何計劃。您可以提供的任何信息都可以幫助開發社區爲項目
+提供有用的輸入。
+
+在這個階段可能發生的一件令人沮喪的事情不是得到反對意見,而是很少或根本沒有
+反饋。令人傷心的事實是:(1)內核開發人員往往很忙;(2)不缺少有宏偉計劃但
+代碼(甚至代碼設想)很少的人去支持他們;(3)沒有人有義務審查或評論別人發表
+的想法。除此之外,高層級的設計常常隱藏著一些問題,這些問題只有在有人真正嘗試
+實現這些設計時才會被發現;因此,內核開發人員寧願看到代碼。
+
+如果發布請求評論(RFC)並沒得到什麼有用的評論,不要以爲這意味著無人對此項目
+有興趣,同時你也不能假設你的想法沒有問題。在這種情況下,最好的做法是繼續進
+行,把你的進展隨時通知社區。
+
+獲得官方認可
+-----------------------
+
+如果您的工作是在公司環境中完成的,就像大多數Linux內核工作一樣;顯然,在您將
+公司的計劃或代碼發布到公共郵件列表之前,必須獲得有適當權利經理的許可。發布
+不確定是否兼容GPL的代碼尤其會帶來問題;公司的管理層和法律人員越早能夠就發布
+內核開發項目達成一致,對參與的每個人都越好。
+
+一些讀者可能會認爲他們的核心工作是爲了支持還沒有正式承認存在的產品。將僱主
+的計劃公布在公共郵件列表上可能不是一個可行的選擇。在這種情況下,有必要考慮
+保密是否真的是必要的;通常不需要把開發計劃關在門內。
+
+的確,有些情況下一家公司在開發過程的早期無法合法地披露其計劃。擁有經驗豐富
+的內核開發人員的公司可能選擇以開環的方式進行開發,前提是他們以後能夠避免
+嚴重的集成問題。對於沒有這種內部專業知識的公司,最好的選擇往往是聘請外部
+開發者根據保密協議審查計劃。Linux基金會運行了一個NDA程序,旨在幫助解決這種
+情況;更多信息參見:
+
+    http://www.linuxfoundation.org/nda/
+
+這種審查通常足以避免以後出現嚴重問題,而無需公開披露項目。
+
diff --git a/Documentation/translations/zh_TW/process/4.Coding.rst b/Documentation/translations/zh_TW/process/4.Coding.rst
new file mode 100644
index 000000000000..ccc3946227a0
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/4.Coding.rst
@@ -0,0 +1,297 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/4.Coding.rst <development_coding>`
+
+:Translator:
+
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+
+:校譯:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+.. _tw_development_coding:
+
+使代碼正確
+======================
+
+雖然一個堅實的、面向社區的設計過程有很多值得說道的,但是任何內核開發項目工作
+的證明都反映在代碼中。它是將由其他開發人員檢查併合並(或不合併)到主線樹中
+的代碼。所以這段代碼的質量決定了項目的最終成功。
+
+本節將檢查編碼過程。我們將從內核開發人員常犯的幾種錯誤開始。然後重點將轉移
+到正確的做法和相關有用的工具上。
+
+陷阱
+----
+
+代碼風格
+********
+
+內核長期以來都有其標準的代碼風格,如
+:ref:`Documentation/translations/zh_TW/process/coding-style.rst <tw_codingstyle>`
+中所述。在多數時候,該文檔中描述的準則至多被認爲是建議性的。因此,內核中存在
+大量不符合代碼風格準則的代碼。這種代碼的存在會給內核開發人員帶來兩方面的危害。
+
+首先,相信內核代碼標準並不重要,也不強制執行。但事實上,如果沒有按照標準
+編寫代碼,那麼新代碼將很難加入到內核中;許多開發人員甚至會在審查代碼之前要求
+對代碼進行重新格式化。一個像內核這麼大的代碼庫需要一些統一格式的代碼,以使
+開發人員能夠快速理解其中的任何部分。所以再也經不起奇怪格式的代碼的折騰了。
+
+內核的代碼風格偶爾會與僱主的強制風格發生衝突。在這種情況下,必須在代碼合併
+之前遵從內核代碼風格。將代碼放入內核意味著以多種方式放棄一定程度的控制權——
+包括控制代碼樣式。
+
+另一個危害是認爲已經在內核中的代碼迫切需要修復代碼樣式。開發者可能會開始編寫
+重新格式化補丁,作爲熟悉開發過程的一種方式,或者作爲將其名字寫入內核變更日誌
+的一種方式,或者兩者兼而有之。但是純代碼風格的修復被開發社區視爲噪音,它們往
+往受到冷遇。因此,最好避免編寫這種類型的補丁。在由於其他原因處理一段代碼的
+同時順帶修復其樣式是很自然的,但是不應該僅爲了更改代碼樣式而更改之。
+
+代碼風格文檔也不應該被視爲絕對不可違反的規則。如果有一個足夠的理由反對這種
+樣式(例如爲了80列限制拆分行會導致可讀性大大降低),那麼就這樣做吧。
+
+注意您還可以使用 ``clang-format`` 工具來幫助您處理這些規則,快速自動重新格式
+化部分代碼,和審閱完整的文件以發現代碼樣式錯誤、拼寫錯誤和可能的改進。它還
+可以方便地排序 ``#includes`` 、對齊變量/宏、重排文本和其他類似任務。有關詳細
+信息,請參閱文檔 :ref:`Documentation/process/clang-format.rst <clangformat>`
+
+抽象層
+******
+
+計算機科學教授教學生以靈活性和信息隱藏的名義廣泛使用抽象層。當然,內核廣泛
+地使用了抽象;任何涉及數百萬行代碼的項目都必須做到這一點以存續下來。但經驗
+表明,過度或過早的抽象可能和過早的優化一樣有害。抽象應用在適當層級,
+不要過度。
+
+簡單點,先考慮一個調用時始終只有一個參數且總爲零的函數。我們可以保留這個參數,
+以在需要使用它時提供的額外靈活性。不過,在那時實現了這個額外參數的代碼很有
+可能以某種從未被注意到的微妙方式被破壞——因爲它從未被使用過。或者當需要額外
+的靈活性時,它並未以符合程式設計師當初期望的方式來實現。內核開發人員通常會提交
+補丁來刪除未使用的參數;一般來說,一開始就不應該添加這些參數。
+
+隱藏硬體訪問的抽象層——通常爲了允許大量的驅動程序兼容多個作業系統——尤其不受
+歡迎。這樣的層使代碼變得模糊,可能會造成性能損失;它們不屬於Linux內核。
+
+另一方面,如果您發現自己從另一個內核子系統複製了大量的代碼,那麼是時候
+了解一下:是否需要將這些代碼中的部分提取到單獨的庫中,或者在更高的層次上
+實現這些功能。在整個內核中複製相同的代碼沒有價值。
+
+#ifdef 和預處理
+***************
+
+C預處理器似乎給一些C程式設計師帶來了強大的誘惑,他們認爲它是一種將大量靈活性加入
+原始碼中的方法。但是預處理器不是C,大量使用它會導致代碼對其他人來說更難閱讀,
+對編譯器來說更難檢查正確性。使用了大量預處理器幾乎總是代碼需要一些
+清理工作的標誌。
+
+使用#ifdef的條件編譯實際上是一個強大的功能,它在內核中使用。但是很少有人希望
+看到代碼被鋪滿#ifdef塊。一般規定,ifdef的使用應儘可能限制在頭文件中。條件
+編譯代碼可以限制函數,如果代碼不存在,這些函數就直接變成空的。然後編譯器將
+悄悄地優化對空函數的調用。使得代碼更加清晰,更容易理解。
+
+C預處理器宏存在許多危險性,包括可能對具有副作用且沒有類型安全的表達式進行多
+重評估。如果您試圖定義宏,請考慮創建一個內聯函數替代。結果相同的代碼,內聯
+函數更容易閱讀,不會多次計算其參數,並且允許編譯器對參數和返回值執行類型檢查。
+
+內聯函數
+********
+
+不過,內聯函數本身也存在風險。程式設計師可以傾心於避免函數調用和用內聯函數填充源
+文件所固有的效率。然而,這些功能實際上會降低性能。因爲它們的代碼在每個調用站
+點都被複製一遍,所以最終會增加編譯內核的大小。此外,這也對處理器的內存緩存
+造成壓力,從而大大降低執行速度。通常內聯函數應該非常小,而且相對較少。畢竟
+函數調用的成本並不高;大量創建內聯函數是過早優化的典型例子。
+
+一般來說,內核程式設計師會自冒風險忽略緩存效果。在數據結構課程開頭中的經典
+時間/空間權衡通常不適用於當代硬體。空間 *就是* 時間,因爲一個大的程序比一個
+更緊湊的程序運行得慢。
+
+較新的編譯器越來越激進地決定一個給定函數是否應該內聯。因此,隨意放置使用
+「inline」關鍵字可能不僅僅是過度的,也可能是無用的。
+
+鎖
+**
+
+2006年5月,「deviceescape」網絡堆棧在前呼後擁下以GPL發布,並被納入主線內核。
+這是一個受歡迎的消息;Linux中對無線網絡的支持充其量被認爲是不合格的,而
+Deviceescape堆棧承諾修復這種情況。然而直到2007年6月(2.6.22),這段代碼才真
+正進入主線。發生了什麼?
+
+這段代碼出現了許多閉門造車的跡象。但一個大麻煩是,它並不是爲多處理器系統而
+設計。在合併這個網絡堆棧(現在稱爲mac80211)之前,需要對其進行一個鎖方案的
+改造。
+
+曾經,Linux內核代碼可以在不考慮多處理器系統所帶來的並發性問題的情況下進行
+開發。然而現在,這個文檔就是在雙核筆記本電腦上寫的。即使在單處理器系統上,
+爲提高響應能力所做的工作也會提高內核內的並發性水平。編寫內核代碼而不考慮鎖
+的日子早已遠去。
+
+可以由多個線程並發訪問的任何資源(數據結構、硬體寄存器等)必須由鎖保護。新
+的代碼應該謹記這一要求;事後修改鎖是一項相當困難的任務。內核開發人員應該花
+時間充分了解可用的鎖原語,以便爲工作選擇正確的工具。對並發性缺乏關注的代碼
+很難進入主線。
+
+回歸
+****
+
+最後一個值得一提的危險是回歸:它可能會引起導致現有用戶的某些東西中斷的改變
+(這也可能會帶來很大的改進)。這種變化被稱爲「回歸」,回歸已經成爲主線內核
+最不受歡迎的問題。除了少數例外情況,如果回歸不能及時修正,會導致回歸的修改
+將被取消。最好首先避免回歸發生。
+
+人們常常爭論,如果回歸帶來的功能遠超過產生的問題,那麼回歸是否爲可接受的。
+如果它破壞了一個系統卻爲十個系統帶來新的功能,爲何不改改態度呢?2007年7月,
+Linus對這個問題給出了最佳答案:
+
+::
+
+	所以我們不會通過引入新問題來修復錯誤。這種方式是靠不住的,沒人知道
+	是否真的有進展。是前進兩步、後退一步,還是前進一步、後退兩步?
+
+(http://lwn.net/articles/243460/)
+
+特別不受歡迎的一種回歸類型是用戶空間ABI的任何變化。一旦接口被導出到用戶空間,
+就必須無限期地支持它。這一事實使得用戶空間接口的創建特別具有挑戰性:因爲它們
+不能以不兼容的方式進行更改,所以必須一次就對。因此,用戶空間接口總是需要大量
+的思考、清晰的文檔和廣泛的審查。
+
+
+代碼檢查工具
+------------
+
+至少目前,編寫無錯誤代碼仍然是我們中很少人能達到的理想狀態。不過,我們希望做
+的是,在代碼進入主線內核之前,儘可能多地捕獲並修復這些錯誤。爲此,內核開發人
+員已經提供了一系列令人印象深刻的工具,可以自動捕獲各種各樣的隱藏問題。計算機
+發現的任何問題都是一個以後不會困擾用戶的問題,因此,只要有可能,就應該使用
+自動化工具。
+
+第一步是注意編譯器產生的警告。當前版本的GCC可以檢測(並警告)大量潛在錯誤。
+通常,這些警告都指向真正的問題。提交以供審閱的代碼一般不會產生任何編譯器警告。
+在消除警告時,注意了解真正的原因,並儘量避免僅「修復」使警告消失而不解決其原因。
+
+請注意,並非所有編譯器警告都默認啓用。使用「make KCFLAGS=-W」構建內核以
+獲得完整集合。
+
+內核提供了幾個配置選項,可以打開調試功能;大多數配置選項位於「kernel hacking」
+子菜單中。對於任何用於開發或測試目的的內核,都應該啓用其中幾個選項。特別是,
+您應該打開:
+
+ - FRAME_WARN 獲取大於給定數量的堆棧幀的警告。
+   這些警告生成的輸出可能比較冗長,但您不必擔心來自內核其他部分的警告。
+
+ - DEBUG_OBJECTS 將添加代碼以跟蹤內核創建的各種對象的生命周期,並在出現問題
+   時發出警告。如果你要添加創建(和導出)關於其自己的複雜對象的子系統,請
+   考慮打開對象調試基礎結構的支持。
+
+ - DEBUG_SLAB 可以發現各種內存分配和使用錯誤;它應該用於大多數開發內核。
+
+ - DEBUG_SPINLOCK, DEBUG_ATOMIC_SLEEP 和 DEBUG_MUTEXES 會發現許多常見的
+   鎖錯誤。
+
+還有很多其他調試選項,其中一些將在下面討論。其中一些有顯著的性能影響,不應
+一直使用。在學習可用選項上花費一些時間,可能會在短期內得到許多回報。
+
+其中一個較重的調試工具是鎖檢查器或「lockdep」。該工具將跟蹤系統中每個鎖
+(spinlock或mutex)的獲取和釋放、獲取鎖的相對順序、當前中斷環境等等。然後,
+它可以確保總是以相同的順序獲取鎖,相同的中斷假設適用於所有情況等等。換句話
+說,lockdep可以找到許多導致系統死鎖的場景。在部署的系統中,這種問題可能會
+很痛苦(對於開發人員和用戶而言);LockDep允許提前以自動方式發現問題。具有
+任何類型的非普通鎖的代碼在提交合併前應在啓用lockdep的情況下運行測試。
+
+作爲一個勤奮的內核程式設計師,毫無疑問,您將檢查任何可能失敗的操作(如內存分配)
+的返回狀態。然而,事實上,最終的故障復現路徑可能完全沒有經過測試。未測試的
+代碼往往會出問題;如果所有這些錯誤處理路徑都被執行了幾次,那麼您可能對代碼
+更有信心。
+
+內核提供了一個可以做到這一點的錯誤注入框架,特別是在涉及內存分配的情況下。
+啓用故障注入後,內存分配的可配置失敗的百分比;這些失敗可以限定在特定的代碼
+範圍內。在啓用了故障注入的情況下運行,程式設計師可以看到當情況惡化時代碼如何響
+應。有關如何使用此工具的詳細信息,請參閱
+Documentation/fault-injection/fault-injection.rst。
+
+「sparse」靜態分析工具可以發現其他類型的錯誤。sparse可以警告程式設計師用戶空間
+和內核空間地址之間的混淆、大端序與小端序的混淆、在需要一組位標誌的地方傳遞
+整數值等等。sparse必須單獨安裝(如果您的分發伺服器沒有將其打包,
+可以在 https://sparse.wiki.kernel.org/index.php/Main_page 找到),
+然後可以通過在make命令中添加「C=1」在代碼上運行它。
+
+「Coccinelle」工具 :ref:`http://coccinelle.lip6.fr/ <devtools_coccinelle>`
+能夠發現各種潛在的編碼問題;它還可以爲這些問題提出修複方案。在
+scripts/coccinelle目錄下已經打包了相當多的內核「語義補丁」;運行
+「make coccicheck」將運行這些語義補丁並報告發現的任何問題。有關詳細信息,請參閱
+:ref:`Documentation/dev-tools/coccinelle.rst <devtools_coccinelle>`
+
+
+其他類型的可移植性錯誤最好通過爲其他體系結構編譯代碼來發現。如果沒有S/390系統
+或Blackfin開發板,您仍然可以執行編譯步驟。可以在以下位置找到一大堆用於x86系統的
+交叉編譯器:
+
+        https://www.kernel.org/pub/tools/crosstool/
+
+花一些時間安裝和使用這些編譯器將有助於避免以後的尷尬。
+
+文檔
+----
+
+文檔通常比內核開發規則更爲例外。即便如此,足夠的文檔將有助於簡化將新代碼合併
+到內核中的過程,使其他開發人員的生活更輕鬆,並對您的用戶有所幫助。在許多情況
+下,添加文檔已基本上是強制性的。
+
+任何補丁的第一個文檔是其關聯的變更日誌。日誌條目應該描述正在解決的問題、解決
+方案的形式、處理補丁的人員、對性能的任何相關影響,以及理解補丁可能需要的任何
+其他內容。確保變更日誌說明了*爲什麼*補丁值得應用;大量開發者未能提供這些信息。
+
+任何添加新用戶空間接口的代碼——包括新的sysfs或/proc文件——都應該包含該接口
+的文檔,該文檔使用戶空間開發人員能夠知道他們在使用什麼。請參閱
+Documentation/ABI/README,了解如何此文檔格式以及需要提供哪些信息。
+
+文檔 :ref:`Documentation/admin-guide/kernel-parameters.rst <kernelparameters>`
+描述了內核的所有引導時間參數。任何添加新參數的補丁都應該向該文檔添加適當的
+條目。
+
+任何新的配置選項都必須附有幫助文本,幫助文本需清楚地解釋這些選項以及用戶可能
+希望何時使用它們。
+
+許多子系統的內部API信息通過專門格式化的注釋進行記錄;這些注釋可以通過
+「kernel-doc」腳本以多種方式提取和格式化。如果您在具有kerneldoc注釋的子系統中
+工作,則應該維護它們,並根據需要爲外部可用的功能添加它們。即使在沒有如此記錄
+的領域中,爲將來添加kerneldoc注釋也沒有壞處;實際上,這對於剛開始開發內核的人
+來說是一個有用的活動。這些注釋的格式以及如何創建kerneldoc模板的一些信息可以在
+:ref:`Documentation/doc-guide/ <doc_guide>` 上找到。
+
+任何閱讀大量現有內核代碼的人都會注意到,注釋的缺失往往是最值得注意的。同時,
+對新代碼的要求比過去更高;合併未注釋的代碼將更加困難。這就是說,人們並不期望
+詳細注釋的代碼。代碼本身應該是自解釋的,注釋闡釋了更微妙的方面。
+
+某些事情應該總是被注釋。使用內存屏障時,應附上一行文字,解釋爲什麼需要設置內存
+屏障。數據結構的鎖規則通常需要在某個地方解釋。一般來說,主要數據結構需要全面
+的文檔。應該指出代碼中分立的位之間不明顯的依賴性。任何可能誘使代碼管理人進行
+錯誤的「清理」的事情都需要一個注釋來說明爲什麼要這樣做。等等。
+
+
+內部API更改
+-----------
+
+內核提供給用戶空間的二進位接口不能被破壞,除非逼不得已。而內核的內部編程接口
+是高度流動的,當需要時可以更改。如果你發現自己不得不處理一個內核API,或者僅
+僅因爲它不滿足你的需求導致無法使用特定的功能,這可能是API需要改變的一個標誌。
+作爲內核開發人員,您有權進行此類更改。
+
+的確可以進行API更改,但更改必須是合理的。因此任何進行內部API更改的補丁都應該
+附帶關於更改內容和必要原因的描述。這種變化也應該拆分成一個單獨的補丁,而不是
+埋在一個更大的補丁中。
+
+另一個要點是,更改內部API的開發人員通常要負責修復內核樹中被更改破壞的任何代碼。
+對於一個廣泛使用的函數,這個責任可以導致成百上千的變化,其中許多變化可能與其他
+開發人員正在做的工作相衝突。不用說,這可能是一項大工程,所以最好確保理由是
+可靠的。請注意,coccinelle工具可以幫助進行廣泛的API更改。
+
+在進行不兼容的API更改時,應儘可能確保編譯器捕獲未更新的代碼。這將幫助您確保找
+到該接口的樹內用處。它還將警告開發人員樹外代碼存在他們需要響應的更改。支持樹外
+代碼不是內核開發人員需要擔心的事情,但是我們也不必使樹外開發人員的生活有不必要
+的困難。
+
diff --git a/Documentation/translations/zh_TW/process/5.Posting.rst b/Documentation/translations/zh_TW/process/5.Posting.rst
new file mode 100644
index 000000000000..5578bca403e6
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/5.Posting.rst
@@ -0,0 +1,251 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/5.Posting.rst <development_posting>`
+
+:Translator:
+
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+
+:校譯:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+.. _tw_development_posting:
+
+發布補丁
+========
+
+您的工作遲早會準備好提交給社區進行審查,並最終包含到主線內核中。毫不稀奇,
+內核開發社區已經發展出一套用於發布補丁的約定和過程;遵循這些約定和過程將使
+參與其中的每個人的生活更加輕鬆。本文檔試圖描述這些約定的部分細節;更多信息
+也可在以下文檔中找到
+:ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`,
+:ref:`Documentation/translations/zh_TW/process/submitting-drivers.rst <tw_submittingdrivers>`
+和 :ref:`Documentation/translations/zh_TW/process/submit-checklist.rst <tw_submitchecklist>`。
+
+何時郵寄
+--------
+
+在補丁完全「準備好」之前,避免發布補丁是一種持續的誘惑。對於簡單的補丁,這
+不是問題。但是如果正在完成的工作很複雜,那麼在工作完成之前從社區獲得反饋就
+可以獲得很多好處。因此,您應該考慮發布正在進行的工作,甚至維護一個可用的Git
+樹,以便感興趣的開發人員可以隨時趕上您的工作。
+
+當發布中有尚未準備好被包含的代碼,最好在發布中說明。還應提及任何有待完成的
+主要工作和任何已知問題。很少有人會願意看那些被認爲是半生不熟的補丁,但是
+那些願意的人會帶著他們的點子來一起幫助你把工作推向正確的方向。
+
+創建補丁之前
+------------
+
+在考慮將補丁發送到開發社區之前,有許多事情應該做。包括:
+
+ - 儘可能地測試代碼。利用內核的調試工具,確保內核使用了所有可能的配置選項組合
+   進行構建,使用交叉編譯器爲不同的體系結構進行構建等。
+
+ - 確保您的代碼符合內核代碼風格指南。
+
+ - 您的更改是否具有性能影響?如果是這樣,您應該運行基準測試來顯示您的變更的
+   影響(或好處);結果的摘要應該包含在補丁中。
+
+ - 確保您有權發布代碼。如果這項工作是爲僱主完成的,僱主對這項工作具有所有權,
+   並且必須同意根據GPL對其進行發布。
+
+一般來說,在發布代碼之前進行一些額外的思考,幾乎總是能在短時間內得到回報。
+
+補丁準備
+--------
+
+準備補丁發布的工作量可能很驚人,但在此嘗試節省時間通常是不明智的,即使在短期
+內亦然。
+
+必須針對內核的特定版本準備補丁。一般來說,補丁應該基於Linus的Git樹中的當前
+主線。當以主線爲基礎時,請從一個衆所周知的發布點開始——如穩定版本或 -rc
+版本發布點——而不是在一個任意的主線分支點。
+
+也可能需要針對-mm、linux-next或子系統樹生成版本,以便於更廣泛的測試和審查。
+根據補丁的區域以及其他地方的情況,針對其他樹建立的補丁可能需要大量的工作來
+解決衝突和處理API更改。
+
+只有最簡單的更改才應格式化爲單個補丁;其他所有更改都應作爲一系列邏輯更改進行。
+分割補丁是一門藝術;一些開發人員花了很長時間來弄清楚如何按照社區期望的方式來
+分割。不過,這些經驗法則也許有幫助:
+
+ - 您發布的補丁系列幾乎肯定不會是開發過程中版本控制系統中的一系列更改。相反,
+   需要對您所做更改的最終形式加以考慮,然後以有意義的方式進行拆分。開發人員對
+   離散的、自包含的更改感興趣,而不是您創造這些更改的原始路徑。
+
+ - 每個邏輯上獨立的變更都應該格式化爲單獨的補丁。這些更改可以是小的(如「向
+   此結構體添加欄位」)或大的(如添加一個重要的新驅動程序),但它們在概念上
+   應該是小的,並且可以在一行內簡述。每個補丁都應該做一個特定的、可以單獨
+   檢查並驗證它所做的事情的更改。
+
+ - 換種方式重申上述準則,也就是說:不要在同一補丁中混合不同類型的更改。如果
+   一個補丁修復了一個關鍵的安全漏洞,又重新排列了一些結構,還重新格式化了代
+   碼,那麼它很有可能會被忽略,從而導致重要的修復丟失。
+
+ - 每個補丁都應該能創建一個可以正確地構建和運行的內核;如果補丁系列在中間被
+   斷開,那麼結果仍應是一個正常工作的內核。部分應用一系列補丁是使用
+   「git bisct」工具查找回歸的一個常見場景;如果結果是一個損壞的內核,那麼將使
+   那些從事追蹤問題的高尚工作的開發人員和用戶的生活更加艱難。
+
+ - 不要過分分割。一位開發人員曾經將一組針對單個文件的編輯分成500個單獨的補丁
+   發布,這並沒有使他成爲內核郵件列表中最受歡迎的人。一個補丁可以相當大,
+   只要它仍然包含一個單一的 *邏輯* 變更。
+
+ - 用一系列補丁添加一個全新的基礎設施,但是該設施在系列中的最後一個補丁啓用
+   整個變更之前不能使用,這看起來很誘人。如果可能的話,應該避免這種誘惑;
+   如果這個系列增加了回歸,那麼二分法將指出最後一個補丁是導致問題的補丁,
+   即使真正的bug在其他地方。只要有可能,添加新代碼的補丁程序應該立即激活該
+   代碼。
+
+創建完美補丁系列的工作可能是一個令人沮喪的過程,在完成「真正的工作」之後需要
+花費大量的時間和思考。但是如果做得好,花費的時間就是值得的。
+
+補丁格式和更改日誌
+------------------
+
+所以現在你有了一系列完美的補丁可以發布,但是這項工作還沒有完成。每個補丁都
+需要被格式化成一條消息,以快速而清晰地將其目的傳達到世界其他地方。爲此,
+每個補丁將由以下部分組成:
+
+ - 可選的「From」行,表明補丁作者。只有當你通過電子郵件發送別人的補丁時,這一行
+   才是必須的,但是爲防止疑問加上它也不會有什麼壞處。
+
+ - 一行描述,說明補丁的作用。對於在沒有其他上下文的情況下看到該消息的讀者來說,
+   該消息應足以確定修補程序的範圍;此行將顯示在「short form(簡短格式)」變更
+   日誌中。此消息通常需要先加上子系統名稱前綴,然後是補丁的目的。例如:
+
+   ::
+
+        gpio: fix build on CONFIG_GPIO_SYSFS=n
+
+ - 一行空白,後接補丁內容的詳細描述。此描述可以是任意需要的長度;它應該說明補丁
+   的作用以及爲什麼它應該應用於內核。
+
+ - 一個或多個標記行,至少有一個由補丁作者的 Signed-off-by 簽名。標記將在下面
+   詳細描述。
+
+上面的項目一起構成補丁的變更日誌。寫一則好的變更日誌是一門至關重要但常常被
+忽視的藝術;值得花一點時間來討論這個問題。當你編寫變更日誌時,你應該記住有
+很多不同的人會讀你的話。其中包括子系統維護人員和審查人員,他們需要決定是否
+應該合併補丁,分銷商和其他維護人員試圖決定是否應該將補丁反向移植到其他內核,
+缺陷搜尋人員想知道補丁是否導致他們正在追查的問題,以及想知道內核如何變化的
+用戶等等。一個好的變更日誌以最直接和最簡潔的方式向所有這些人傳達所需的信息。
+
+在結尾,總結行應該描述變更的影響和動機,以及在一行約束條件下可能發生的變化。
+然後,詳細的描述可以詳述這些主題,並提供任何需要的附加信息。如果補丁修復了
+一個缺陷,請引用引入該缺陷的提交(如果可能,請在引用提交時同時提供其 id 和
+標題)。如果某個問題與特定的日誌或編譯器輸出相關聯,請包含該輸出以幫助其他
+人搜索同一問題的解決方案。如果更改是爲了支持以後補丁中的其他更改,那麼應當
+說明。如果更改了內部API,請詳細說明這些更改以及其他開發人員應該如何響應。
+一般來說,你越把自己放在每個閱讀你變更日誌的人的位置上,變更日誌(和內核
+作爲一個整體)就越好。
+
+不消說,變更日誌是將變更提交到版本控制系統時使用的文本。接下來將是:
+
+ - 補丁本身,採用統一的(「-u」)補丁格式。使用「-p」選項來diff將使函數名與
+   更改相關聯,從而使結果補丁更容易被其他人讀取。
+
+您應該避免在補丁中包括與更改不相關文件(例如,構建過程生成的文件或編輯器
+備份文件)。文檔目錄中的「dontdiff」文件在這方面有幫助;使用「-X」選項將
+其傳遞給diff。
+
+上面提到的標籤(tag)用於描述各種開發人員如何與這個補丁的開發相關聯。
+:ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+文檔中對它們進行了詳細描述;下面是一個簡短的總結。每一行的格式如下:
+
+::
+
+	tag: Full Name <email address>  optional-other-stuff
+
+常用的標籤有:
+
+ - Signed-off-by: 這是一個開發人員的證明,證明他或她有權提交補丁以包含到內核
+   中。這表明同意開發者來源認證協議,其全文見
+   :ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+   如果沒有合適的簽字,則不能合併到主線中。
+
+ - Co-developed-by: 聲明補丁是由多個開發人員共同創建的;當幾個人在一個補丁上
+   工作時,它用於給出共同作者(除了 From: 所給出的作者之外)。由於
+   Co-developed-by: 表示作者身份,所以每個共同開發人,必須緊跟在相關合作作者
+   的Signed-off-by之後。具體內容和示例見以下文件
+   :ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+
+ - Acked-by: 表示另一個開發人員(通常是相關代碼的維護人員)同意補丁適合包含
+   在內核中。
+
+ - Tested-by: 聲明某人已經測試了補丁並確認它可以工作。
+
+ - Reviewed-by: 表示某開發人員已經審查了補丁的正確性;有關詳細信息,請參閱
+   :ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+
+ - Reported-by: 指定報告此補丁修復的問題的用戶;此標記用於表示感謝。
+
+ - Cc:指定某人收到了補丁的副本,並有機會對此發表評論。
+
+在補丁中添加標籤時要小心:只有Cc:才適合在沒有指定人員明確許可的情況下添加。
+
+發送補丁
+--------
+
+在寄出補丁之前,您還需要注意以下幾點:
+
+ - 您確定您的郵件發送程序不會損壞補丁嗎?被郵件客戶端更改空白或修飾了行的補丁
+   無法被另一端接受,並且通常不會進行任何詳細檢查。如果有任何疑問,先把補丁寄
+   給你自己,讓你自己確定它是完好無損的。
+
+   :ref:`Documentation/translations/zh_TW/process/email-clients.rst <tw_email_clients>`
+   提供了一些有用的提示,可以讓特定的郵件客戶端正常發送補丁。
+
+ - 你確定你的補丁沒有荒唐的錯誤嗎?您應該始終通過scripts/checkpatch.pl檢查
+   補丁程序,並解決它提出的問題。請記住,checkpatch.pl,雖然體現了對內核補丁
+   應該是什麼樣的大量思考,但它並不比您聰明。如果修復checkpatch.pl給的問題會
+   使代碼變得更糟,請不要這樣做。
+
+補丁應始終以純文本形式發送。請不要將它們作爲附件發送;這使得審閱者在答覆中更難
+引用補丁的部分。相反,只需將補丁直接放到您的消息中。
+
+寄出補丁時,重要的是將副本發送給任何可能感興趣的人。與其他一些項目不同,內核
+鼓勵人們甚至錯誤地發送過多的副本;不要假定相關人員會看到您在郵件列表中的發布。
+尤其是,副本應發送至:
+
+ - 受影響子系統的維護人員。如前所述,維護人員文件是查找這些人員的首選地方。
+
+ - 其他在同一領域工作的開發人員,尤其是那些現在可能在那裡工作的開發人員。使用
+   git查看還有誰修改了您正在處理的文件,這很有幫助。
+
+ - 如果您對某錯誤報告或功能請求做出響應,也可以抄送原始發送人。
+
+ - 將副本發送到相關郵件列表,或者若無相關列表,則發送到linux-kernel列表。
+
+ - 如果您正在修復一個缺陷,請考慮該修復是否應進入下一個穩定更新。如果是這樣,
+   補丁副本也應發到stable@vger.kernel.org 。另外,在補丁本身的標籤中添加一個
+   「Cc: stable@vger.kernel.org」;這將使穩定版團隊在修復進入主線時收到通知。
+
+當爲一個補丁選擇接收者時,最好清楚你認爲誰最終會接受這個補丁並將其合併。雖然
+可以將補丁直接發給Linus Torvalds並讓他合併,但通常情況下不會這樣做。Linus很
+忙,並且有子系統維護人員負責監視內核的特定部分。通常您會希望維護人員合併您的
+補丁。如果沒有明顯的維護人員,Andrew Morton通常是最後的補丁接收者。
+
+補丁需要好的主題行。補丁主題行的規範格式如下:
+
+::
+
+	[PATCH nn/mm] subsys: one-line description of the patch
+
+其中「nn」是補丁的序號,「mm」是系列中補丁的總數,「subsys」是受影響子系統的
+名稱。當然,一個單獨的補丁可以省略nn/mm。
+
+如果您有一系列重要的補丁,那麼通常發送一個簡介作爲第〇部分。不過,這個約定
+並沒有得到普遍遵循;如果您使用它,請記住簡介中的信息不會進入內核變更日誌。
+因此,請確保補丁本身具有完整的變更日誌信息。
+
+一般來說,多部分補丁的第二部分和後續部分應作爲對第一部分的回覆發送,以便它們
+在接收端都連接在一起。像git和coilt這樣的工具有命令,可以通過適當的線程發送
+一組補丁。但是,如果您有一長串補丁,並正使用git,請不要使用–-chain-reply-to
+選項,以避免創建過深的嵌套。
+
diff --git a/Documentation/translations/zh_TW/process/6.Followthrough.rst b/Documentation/translations/zh_TW/process/6.Followthrough.rst
new file mode 100644
index 000000000000..4af782742db3
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/6.Followthrough.rst
@@ -0,0 +1,156 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/6.Followthrough.rst <development_followthrough>`
+
+:Translator:
+
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+
+:校譯:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+.. _tw_development_followthrough:
+
+跟進
+====
+
+此時,您已經遵循了到目前爲止給出的指導方針,並且,隨著您自己的工程技能的增加,
+已經發布了一系列完美的補丁。即使是經驗豐富的內核開發人員也能犯的最大錯誤之一
+是,認爲他們的工作現在已經完成了。事實上,發布補丁意味著進入流程的下一個階段,
+可能還需要做很多工作。
+
+一個補丁在首次發布時就非常出色、沒有改進的餘地,這是很罕見的。內核開發流程已
+認識到這一事實,因此它非常注重對已發布代碼的改進。作爲代碼的作者,您應該與
+內核社區合作,以確保您的代碼符合內核的質量標準。如果不參與這個過程,很可能會
+無法將補丁合併到主線中。
+
+與審閱者合作
+------------
+
+任何意義上的補丁都會導致其他開發人員在審查代碼時發表大量評論。對於許多開發
+人員來說,與審閱人員合作可能是內核開發過程中最令人生畏的部分。但是如果你
+記住一些事情,生活會變得容易得多:
+
+ - 如果你已經很好地解釋了你的補丁,審閱人員會理解它的價值,以及爲什麼你會
+   費盡心思去寫它。但是這個並不能阻止他們提出一個基本的問題:在五年或十年後
+   維護含有此代碼的內核會怎麼樣?你可能被要求做出的許多改變——從編碼風格的
+   調整到大量的重寫——都來自於對Linux的理解,即從現在起十年後,Linux仍將
+   在開發中。
+
+ - 代碼審查是一項艱苦的工作,這是一項相對吃力不討好的工作;人們記得誰編寫了
+   內核代碼,但對於那些審查它的人來說,幾乎沒有什麼長久的名聲。因此,審閱
+   人員可能會變得暴躁,尤其是當他們看到同樣的錯誤被一遍又一遍地犯下時。如果
+   你得到了一個看起來憤怒、侮辱或完全冒犯你的評論,請抑制以同樣方式回應的衝動。
+   代碼審查是關於代碼的,而不是關於人的,代碼審閱人員不會親自攻擊您。
+
+ - 同樣,代碼審閱人員也不想以犧牲你僱主的利益爲代價來宣傳他們僱主的議程。
+   內核開發人員通常希望今後幾年能在內核上工作,但他們明白他們的僱主可能會改
+   變。他們真的,幾乎毫無例外地,致力於創造他們所能做到的最好的內核;他們並
+   沒有試圖給僱主的競爭對手造成不適。
+
+所有這些歸根結底就是,當審閱者向您發送評論時,您需要注意他們正在進行的技術
+評論。不要讓他們的表達方式或你自己的驕傲阻止此事。當你在一個補丁上得到評論
+時,花點時間去理解評論人想說什麼。如果可能的話,請修覆審閱者要求您修復的內
+容。然後回覆審閱者:謝謝他們,並描述你將如何回答他們的問題。
+
+請注意,您不必同意審閱者建議的每個更改。如果您認爲審閱者誤解了您的代碼,請
+解釋到底發生了什麼。如果您對建議的更改有技術上的異議,請描述它並證明您對該
+問題的解決方案是正確的。如果你的解釋有道理,審閱者會接受的。不過,如果你的
+解釋證明缺乏說服力,尤其是當其他人開始同意審稿人的觀點時,請花些時間重新考慮
+一下。你很容易對自己解決問題的方法視而不見,以至於你沒有意識到某些東西完全
+是錯誤的,或者你甚至沒有解決正確的問題。
+
+Andrew Morton建議,每一個不會導致代碼更改的審閱評論都應該產生一個額外的代碼
+注釋;這可以幫助未來的審閱人員避免第一次出現的問題。
+
+一個致命的錯誤是忽視評論,希望它們會消失。它們不會走的。如果您在沒有對之前
+收到的評論做出響應的情況下重新發布代碼,那麼很可能會發現補丁毫無用處。
+
+說到重新發布代碼:請記住,審閱者不會記住您上次發布的代碼的所有細節。因此,
+提醒審閱人員以前提出的問題以及您如何處理這些問題總是一個好主意;補丁變更
+日誌是提供此類信息的好地方。審閱者不必搜索列表檔案來熟悉上次所說的內容;
+如果您幫助他們直接開始,當他們重新查看您的代碼時,心情會更好。
+
+如果你已經試著做正確的事情,但事情仍然沒有進展呢?大多數技術上的分歧都可以
+通過討論來解決,但有時人們仍需要做出決定。如果你真的認爲這個決定對你不利,
+你可以試著向有更高權力的人上訴。對於本文,更高權力的人是 Andrew Morton 。
+Andrew 在內核開發社區中非常受尊敬;他經常爲似乎被絕望阻塞的事情清障。儘管
+如此,不應輕易就直接找 Andrew ,也不應在所有其他替代方案都被嘗試之前找他。
+當然,記住,他也可能不同意你的意見。
+
+接下來會發生什麼
+----------------
+
+如果一個補丁被認爲適合添加到內核中,並且大多數審查問題得到解決,下一步通常
+是進入子系統維護人員的樹中。工作方式因子系統而異;每個維護人員都有自己的
+工作方式。特別是可能有不止一棵樹——也許一棵樹專門用於計劃下一個合併窗口的
+補丁,另一棵樹用於長期工作。
+
+對於應用到不屬於明顯子系統樹(例如內存管理修補程序)的區域的修補程序,默認樹
+通常上溯到-mm。影響多個子系統的補丁也可以最終進入-mm樹。
+
+包含在子系統樹中可以提高補丁的可見性。現在,使用該樹的其他開發人員將默認獲
+得補丁。子系統樹通常也爲Linux提供支持,使其內容對整個開發社區可見。在這一點
+上,您很可能會從一組新的審閱者那裡得到更多的評論;這些評論需要像上一輪那樣
+得到回應。
+
+在這時也會發生點什麼,這取決於你的補丁的性質,是否與其他人正在做的工作發生
+衝突。在最壞的情況下,嚴重的補丁衝突可能會導致一些工作被擱置,以便剩餘的補丁
+可以成形併合並。另一些時候,衝突解決將涉及到與其他開發人員合作,可能還會
+在樹之間移動一些補丁,以確保所有的應用都是乾淨的。這項工作可能是一件痛苦的
+事情,但也需慶幸現在的幸福:在linux-next樹出現之前,這些衝突通常只在合併窗口
+中出現,必須迅速解決。現在可以在合併窗口打開之前的空閒時間解決這些問題。
+
+有朝一日,如果一切順利,您將登錄並看到您的補丁已經合併到主線內核中。祝賀你!
+然而,一旦慶祝完了(並且您已經將自己添加到維護人員文件中),就一定要記住
+一個重要的小事實:工作仍然沒有完成。併入主線也帶來了它的挑戰。
+
+首先,補丁的可見性再次提高。可能會有以前不知道這個補丁的開發者的新一輪評論。
+忽略它們可能很有誘惑力,因爲您的代碼不再存在任何被合併的問題。但是,要抵制
+這種誘惑,您仍然需要對有問題或建議的開發人員作出響應。
+
+不過,更重要的是:將代碼包含在主線中會將代碼交給更多的一些測試人員。即使您
+爲尚未可用的硬體提供了驅動程序,您也會驚訝於有多少人會將您的代碼構建到內核
+中。當然,如果有測試人員,也可能會有錯誤報告。
+
+最糟糕的錯誤報告是回歸。如果你的補丁導致回歸,你會發現多到讓你不舒服的眼睛盯
+著你;回歸需要儘快修復。如果您不願意或無法修復回歸(其他人都不會爲您修復),
+那麼在穩定期內,您的補丁幾乎肯定會被移除。除了否定您爲使補丁進入主線所做的
+所有工作之外,如果由於未能修復回歸而取消補丁,很可能會使將來的工作更難被合併。
+
+在處理完任何回歸之後,可能還有其他普通缺陷需要處理。穩定期是修復這些錯誤並
+確保代碼在主線內核版本中的首次發布儘可能可靠的最好機會。所以,請回應錯誤
+報告,並儘可能解決問題。這就是穩定期的目的;一旦解決了舊補丁的任何問題,就
+可以開始盡情創建新補丁。
+
+別忘了,還有其他節點也可能會創建缺陷報告:下一個主線穩定版本,當著名的發行
+商選擇包含您補丁的內核版本時等等。繼續響應這些報告是您工作的基本素養。但是
+如果這不能提供足夠的動機,那麼也需要考慮:開發社區會記住那些在合併後對代碼
+失去興趣的開發人員。下一次你發布補丁時,他們會以你以後不會持續維護它爲前提
+來評估它。
+
+其他可能發生的事情
+------------------
+
+某天,當你打開你的郵件客戶端時,看到有人給你寄了一個代碼補丁。畢竟,這是
+讓您的代碼公開存在的好處之一。如果您同意這個補丁,您可以將它轉發給子系統
+維護人員(確保包含一個正確的From:行,這樣屬性是正確的,並添加一個您自己的
+signoff ),或者回復一個 Acked-by: 讓原始發送者向上發送它。
+
+如果您不同意補丁,請禮貌地回復,解釋原因。如果可能的話,告訴作者需要做哪些
+更改才能讓您接受補丁。合併代碼的編寫者和維護者所反對的補丁的確存在著一定的
+阻力,但僅此而已。如果你被認爲不必要的阻礙了好的工作,那麼這些補丁最終會
+繞過你並進入主線。在Linux內核中,沒有人對任何代碼擁有絕對的否決權。可能除
+了Linus。
+
+在非常罕見的情況下,您可能會看到完全不同的東西:另一個開發人員發布了針對您
+的問題的不同解決方案。在這時,兩個補丁之一可能不會被合併,「我的補丁首先
+發布」不被認爲是一個令人信服的技術論據。如果有別人的補丁取代了你的補丁而進
+入了主線,那麼只有一種方法可以回應你:很高興你的問題解決了,請繼續工作吧。
+以這種方式把某人的工作推到一邊可能導致傷心和氣餒,但是社區會記住你的反應,
+即使很久以後他們已經忘記了誰的補丁真正被合併。
+
diff --git a/Documentation/translations/zh_TW/process/7.AdvancedTopics.rst b/Documentation/translations/zh_TW/process/7.AdvancedTopics.rst
new file mode 100644
index 000000000000..3de093d0f170
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/7.AdvancedTopics.rst
@@ -0,0 +1,137 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/7.AdvancedTopics.rst <development_advancedtopics>`
+
+:Translator:
+
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+
+:校譯:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+.. _tw_development_advancedtopics:
+
+高級主題
+========
+
+現在,希望您能夠掌握開發流程的工作方式。然而,還有更多的東西要學!本節將介紹
+一些主題,這些主題對希望成爲Linux內核開發過程常規部分的開發人員有幫助。
+
+使用Git管理補丁
+---------------
+
+內核使用分布式版本控制始於2002年初,當時Linus首次開始使用專有的Bitkeeper應用
+程序。雖然BitKeeper存在爭議,但它所體現的軟體版本管理方法卻肯定不是。分布式
+版本控制可以立即加速內核開發項目。現在有好幾種免費的BitKeeper替代品。
+但無論好壞,內核項目都已經選擇了Git作爲其工具。
+
+使用Git管理補丁可以使開發人員的生活更加輕鬆,尤其是隨著補丁數量的增長。Git也
+有其粗糙的邊角和一定的危險性,它是一個年輕和強大的工具,仍然在其開發人員完善
+中。本文檔不會試圖教會讀者如何使用git;這會是個巨長的文檔。相反,這裡的重點
+將是Git如何特別適合內核開發過程。想要加快用Git速度的開發人員可以在以下網站上
+找到更多信息:
+
+	https://git-scm.com/
+
+	https://www.kernel.org/pub/software/scm/git/docs/user-manual.html
+
+同時網上也能找到各種各樣的教程。
+
+在嘗試使用它生成補丁供他人使用之前,第一要務是閱讀上述網頁,對Git的工作方式
+有一個紮實的了解。使用Git的開發人員應能進行拉取主線存儲庫的副本,查詢修訂
+歷史,提交對樹的更改,使用分支等操作。了解Git用於重寫歷史的工具(如rebase)
+也很有用。Git有自己的術語和概念;Git的新用戶應該了解引用、遠程分支、索引、
+快進合併、推拉、游離頭等。一開始可能有點嚇人,但這些概念不難通過一點學習來
+理解。
+
+使用git生成通過電子郵件提交的補丁是提高速度的一個很好的練習。
+
+當您準備好開始建立Git樹供其他人查看時,無疑需要一個可以從中拉取的伺服器。
+如果您有一個可以訪問網際網路的系統,那麼使用git-daemon設置這樣的伺服器相對
+簡單。同時,免費的公共託管網站(例如github)也開始出現在網絡上。成熟的開發
+人員可以在kernel.org上獲得一個帳戶,但這些帳戶並不容易得到;更多有關信息,
+請參閱 https://kernel.org/faq/ 。
+
+正常的Git工作流程涉及到許多分支的使用。每一條開發線都可以分爲單獨的「主題
+分支」,並獨立維護。Git的分支很容易使用,沒有理由不使用它們。而且,在任何
+情況下,您都不應該在任何您打算讓其他人從中拉取的分支中進行開發。應該小心地
+創建公開可用的分支;當開發分支處於完整狀態並已準備好時(而不是之前)才合併
+開發分支的補丁。
+
+Git提供了一些強大的工具,可以讓您重寫開發歷史。一個不方便的補丁(比如說,
+一個打破二分法的補丁,或者有其他一些明顯的缺陷)可以在適當的位置修復,或者
+完全從歷史中消失。一個補丁系列可以被重寫,就好像它是在今天的主線上寫的一樣,
+即使你已經花了幾個月的時間在寫它。可以透明地將更改從一個分支轉移到另一個
+分支。等等。明智地使用git修改歷史的能力可以幫助創建問題更少的乾淨補丁集。
+
+然而,過度使用這種功能可能會導致其他問題,而不僅僅是對創建完美項目歷史的
+簡單癡迷。重寫歷史將重寫該歷史中包含的更改,將經過測試(希望如此)的內核樹
+變爲未經測試的內核樹。除此之外,如果開發人員沒有共享項目歷史,他們就無法
+輕鬆地協作;如果您重寫了其他開發人員拉入他們存儲庫的歷史,您將使這些開發
+人員的生活更加困難。因此,這裡有一個簡單的經驗法則:被導出到其他地方的歷史
+在此後通常被認爲是不可變的。
+
+因此,一旦將一組更改推送到公開可用的伺服器上,就不應該重寫這些更改。如果您
+嘗試強制進行無法快進合併的更改(即不共享同一歷史記錄的更改),Git將嘗試強制
+執行此規則。這可能覆蓋檢查,有時甚至需要重寫導出的樹。在樹之間移動變更集以
+避免linux-next中的衝突就是一個例子。但這種行爲應該是罕見的。這就是爲什麼
+開發應該在私有分支中進行(必要時可以重寫)並且只有在公共分支處於合理的較新
+狀態時才轉移到公共分支中的原因之一。
+
+當主線(或其他一組變更所基於的樹)前進時,很容易與該樹合併以保持領先地位。
+對於一個私有的分支,rebasing 可能是一個很容易跟上另一棵樹的方法,但是一旦
+一棵樹被導出到外界,rebasing就不可取了。一旦發生這種情況,就必須進行完全
+合併(merge)。合併有時是很有意義的,但是過於頻繁的合併會不必要地擾亂歷史。
+在這種情況下建議的做法是不要頻繁合併,通常只在特定的發布點(如主線-rc發布)
+合併。如果您對特定的更改感到緊張,則可以始終在私有分支中執行測試合併。在
+這種情況下,git「rerere」工具很有用;它能記住合併衝突是如何解決的,這樣您
+就不必重複相同的工作。
+
+關於Git這樣的工具的一個最大的反覆抱怨是:補丁從一個存儲庫到另一個存儲庫的
+大量移動使得很容易陷入錯誤建議的變更中,這些變更避開審查雷達進入主線。當內
+核開發人員看到這種情況發生時,他們往往會感到不高興;在Git樹上放置未審閱或
+主題外的補丁可能會影響您將來讓樹被拉取的能力。引用Linus的話:
+
+::
+
+   你可以給我發補丁,但當我從你那裡拉取一個Git補丁時,我需要知道你清楚
+   自己在做什麼,我需要能夠相信事情而 *無需* 手動檢查每個單獨的更改。
+
+(http://lwn.net/articles/224135/)。
+
+爲了避免這種情況,請確保給定分支中的所有補丁都與相關主題緊密相關;「驅動程序
+修復」分支不應更改核心內存管理代碼。而且,最重要的是,不要使用Git樹來繞過
+審查過程。不時的將樹的摘要發布到相關的列表中,在合適時候請求linux-next中
+包含該樹。
+
+如果其他人開始發送補丁以包含到您的樹中,不要忘記審閱它們。還要確保您維護正確
+的作者信息; git 「am」工具在這方面做得最好,但是如果補丁通過第三方轉發給您,
+您可能需要在補丁中添加「From:」行。
+
+請求拉取時,請務必提供所有相關信息:樹的位置、要拉取的分支以及拉取將導致的
+更改。在這方面 git request-pull 命令非常有用;它將按照其他開發人員所期望的
+格式化請求,並檢查以確保您已記得將這些更改推送到公共伺服器。
+
+審閱補丁
+--------
+
+一些讀者顯然會反對將本節與「高級主題」放在一起,因爲即使是剛開始的內核開發人員
+也應該審閱補丁。當然,沒有比查看其他人發布的代碼更好的方法來學習如何在內核環境
+中編程了。此外,審閱者永遠供不應求;通過審閱代碼,您可以對整個流程做出重大貢獻。
+
+審查代碼可能是一副令人生畏的圖景,特別是對一個新的內核開發人員來說,他們
+可能會對公開詢問代碼感到緊張,而這些代碼是由那些有更多經驗的人發布的。不過,
+即使是最有經驗的開發人員編寫的代碼也可以得到改進。也許對(所有)審閱者最好
+的建議是:把審閱評論當成問題而不是批評。詢問「在這條路徑中如何釋放鎖?」
+總是比說「這裡的鎖是錯誤的」更好。
+
+不同的開發人員將從不同的角度審查代碼。部分人會主要關注代碼風格以及代碼行是
+否有尾隨空格。其他人會主要關注補丁作爲一個整體實現的變更是否對內核有好處。
+同時也有人會檢查是否存在鎖問題、堆棧使用過度、可能的安全問題、在其他地方
+發現的代碼重複、足夠的文檔、對性能的不利影響、用戶空間ABI更改等。所有類型
+的檢查,只要它們能引導更好的代碼進入內核,都是受歡迎和值得的。
+
diff --git a/Documentation/translations/zh_TW/process/8.Conclusion.rst b/Documentation/translations/zh_TW/process/8.Conclusion.rst
new file mode 100644
index 000000000000..7572b17667d9
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/8.Conclusion.rst
@@ -0,0 +1,74 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/8.Conclusion.rst <development_conclusion>`
+:Translator:
+
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+
+:校譯:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+.. _tw_development_conclusion:
+
+更多信息
+========
+
+關於Linux內核開發和相關主題的信息來源很多。首先是在內核原始碼分發中找到的
+文檔目錄。頂級
+:ref:`Documentation/translations/zh_TW/process/howto.rst <tw_process_howto>`
+文件是一個重要的起點;
+:ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+和 :ref:`Documentation/translations/zh_TW/process/submitting-drivers.rst <tw_submittingdrivers>`
+也是所有內核開發人員都應該閱讀的內容。許多內部內核API都是使用kerneldoc機制
+記錄的;「make htmldocs」或「make pdfdocs」可用於以HTML或PDF格式生成這些文檔
+(儘管某些發行版提供的tex版本會遇到內部限制,無法正確處理文檔)。
+
+不同的網站在各個細節層次上討論內核開發。本文作者想謙虛地建議用 https://lwn.net/
+作爲來源;有關許多特定內核主題的信息可以通過以下網址的 LWN 內核索引找到:
+
+  http://lwn.net/kernel/index/
+
+除此之外,內核開發人員的一個寶貴資源是:
+
+  https://kernelnewbies.org/
+
+當然,也不應該忘記 https://kernel.org/ ,這是內核發布信息的最終位置。
+
+關於內核開發有很多書:
+
+  《Linux設備驅動程序》第三版(Jonathan Corbet、Alessandro Rubini和Greg Kroah Hartman)
+  線上版本在 http://lwn.net/kernel/ldd3/
+
+  《Linux內核設計與實現》(Robert Love)
+
+  《深入理解Linux內核》(Daniel Bovet和Marco Cesati)
+
+然而,所有這些書都有一個共同的缺點:它們上架時就往往有些過時,而且已經上架
+一段時間了。不過,在那裡還是可以找到相當多的好信息。
+
+有關git的文檔,請訪問:
+
+  https://www.kernel.org/pub/software/scm/git/docs/
+
+  https://www.kernel.org/pub/software/scm/git/docs/user-manual.html
+
+結論
+====
+
+祝賀所有通過這篇冗長的文檔的人。希望它能夠幫助您理解Linux內核是如何開發的,
+以及您如何參與這個過程。
+
+最後,重要的是參與。任何開源軟體項目都不會超過其貢獻者投入其中的總和。Linux
+內核的發展速度和以前一樣快,因爲它得到了大量開發人員的幫助,他們都在努力使它
+變得更好。內核是一個最成功的例子,說明了當成千上萬的人爲了一個共同的目標一起
+工作時,可以做出什麼。
+
+不過,內核總是可以從更大的開發人員基礎中獲益。總有更多的工作要做。但是同樣
+重要的是,Linux生態系統中的大多數其他參與者可以通過爲內核做出貢獻而受益。使
+代碼進入主線是提高代碼質量、降低維護和分發成本、提高對內核開發方向的影響程度
+等的關鍵。這是一種共贏的局面。啓動你的編輯器,來加入我們吧;你會非常受歡迎的。
+
diff --git a/Documentation/translations/zh_TW/process/code-of-conduct-interpretation.rst b/Documentation/translations/zh_TW/process/code-of-conduct-interpretation.rst
new file mode 100644
index 000000000000..949d831aaf6c
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/code-of-conduct-interpretation.rst
@@ -0,0 +1,112 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/code-of-conduct-interpretation.rst <code_of_conduct_interpretation>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+.. _tw_code_of_conduct_interpretation:
+
+Linux內核貢獻者契約行為準則解釋
+===============================
+
+:ref:`tw_code_of_conduct` 準則是一個通用文檔,旨在爲幾乎所有開源社區提供一套規則。
+每個開源社區都是獨一無二的,Linux內核也不例外。因此,本文描述了Linux內核社區中
+如何解釋它。我們也不希望這種解釋隨著時間的推移是靜態的,並將根據需要進行調整。
+
+與開發軟體的「傳統」方法相比,Linux內核開發工作是一個非常個人化的過程。你的貢獻
+和背後的想法將被仔細審查,往往導致批判和批評。審查將幾乎總是需要改進,材料才
+能包括在內核中。要知道這是因爲所有相關人員都希望看到Linux整體成功的最佳解決方
+案。這個開發過程已經被證明可以創建有史以來最健壯的作業系統內核,我們不想做任何
+事情來導致提交質量和最終結果的下降。
+
+維護者
+------
+
+行為準則多次使用「維護者」一詞。在內核社區中,「維護者」是負責子系統、驅動程序或
+文件的任何人,並在內核原始碼樹的維護者文件中列出。
+
+責任
+----
+
+《行為準則》提到了維護人員的權利和責任,這需要進一步澄清。
+
+首先,最重要的是,有一個合理的期望是由維護人員通過實例來領導。
+
+也就是說,我們的社區是廣闊的,對維護者沒有新的要求,他們單方面處理其他人在
+他們活躍的社區的行爲。這一責任由我們所有人承擔,最終《行為準則》記錄了最終的
+上訴路徑,以防有關行爲問題的問題懸而未決。
+
+維護人員應該願意在出現問題時提供幫助,並在需要時與社區中的其他人合作。如果您
+不確定如何處理出現的情況,請不要害怕聯繫技術諮詢委員會(TAB)或其他維護人員。
+除非您願意,否則不會將其視爲違規報告。如果您不確定是否該聯繫TAB 或任何其他維
+護人員,請聯繫我們的衝突調解人 Mishi Choudhary <mishi@linux.com>。
+
+最後,「善待對方」才是每個人的最終目標。我們知道每個人都是人,有時我們都會失敗,
+但我們所有人的首要目標應該是努力友好地解決問題。執行行為準則將是最後的選擇。
+
+我們的目標是創建一個強大的、技術先進的作業系統,以及所涉及的技術複雜性,這自
+然需要專業知識和決策。
+
+所需的專業知識因貢獻領域而異。它主要由上下文和技術複雜性決定,其次由貢獻者和
+維護者的期望決定。
+
+專家的期望和決策都要經過討論,但在最後,爲了取得進展,必須能夠做出決策。這一
+特權掌握在維護人員和項目領導的手中,預計將善意使用。
+
+因此,設定專業知識期望、作出決定和拒絕不適當的貢獻不被視爲違反行為準則。
+
+雖然維護人員一般都歡迎新來者,但他們幫助(新)貢獻者克服障礙的能力有限,因此
+他們必須確定優先事項。這也不應被視爲違反了行為準則。內核社區意識到這一點,並
+以各種形式提供入門級節目,如 kernelnewbies.org 。
+
+範圍
+----
+
+Linux內核社區主要在一組公共電子郵件列表上進行交互,這些列表分布在由多個不同
+公司或個人控制的多個不同伺服器上。所有這些列表都在內核原始碼樹中的
+MAINTAINERS 文件中定義。發送到這些郵件列表的任何電子郵件都被視爲包含在行爲
+準則中。
+
+使用 kernel.org bugzilla和其他子系統bugzilla 或bug跟蹤工具的開發人員應該遵循
+行為準則的指導原則。Linux內核社區沒有「官方」項目電子郵件地址或「官方」社交媒體
+地址。使用kernel.org電子郵件帳戶執行的任何活動必須遵循爲kernel.org發布的行爲
+準則,就像任何使用公司電子郵件帳戶的個人必須遵循該公司的特定規則一樣。
+
+行為準則並不禁止在郵件列表消息、內核更改日誌消息或代碼注釋中繼續包含名稱、
+電子郵件地址和相關注釋。
+
+其他論壇中的互動包括在適用於上述論壇的任何規則中,通常不包括在行為準則中。
+除了在極端情況下可考慮的例外情況。
+
+提交給內核的貢獻應該使用適當的語言。在行為準則之前已經存在的內容現在不會被
+視爲違反。然而,不適當的語言可以被視爲一個bug;如果任何相關方提交補丁,
+這樣的bug將被更快地修復。當前屬於用戶/內核API的一部分的表達式,或者反映已
+發布標準或規範中使用的術語的表達式,不被視爲bug。
+
+執行
+----
+
+行為準則中列出的地址屬於行為準則委員會。https://kernel.org/code-of-conduct.html
+列出了在任何給定時間接收這些電子郵件的確切成員。成員不能訪問在加入委員會之前
+或離開委員會之後所做的報告。
+
+最初的行為準則委員會由TAB的志願者以及作爲中立第三方的專業調解人組成。委員會
+的首要任務是建立文件化的流程,並將其公開。
+
+如果報告人不希望將整個委員會納入投訴或關切,可直接聯繫委員會的任何成員,包括
+調解人。
+
+行為準則委員會根據流程審查案例(見上文),並根據需要和適當與TAB協商,例如請求
+和接收有關內核社區的信息。
+
+委員會做出的任何決定都將提交到表中,以便在必要時與相關維護人員一起執行。行爲
+準則委員會的決定可以通過三分之二的投票推翻。
+
+每季度,行為準則委員會和標籤將提供一份報告,概述行為準則委員會收到的匿名報告
+及其狀態,以及任何否決決定的細節,包括完整和可識別的投票細節。
+
+我們希望在啓動期之後爲行為準則委員會人員配備建立一個不同的流程。發生此情況時,
+將使用該信息更新此文檔。
+
diff --git a/Documentation/translations/zh_TW/process/code-of-conduct.rst b/Documentation/translations/zh_TW/process/code-of-conduct.rst
new file mode 100644
index 000000000000..716e5843b6e9
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/code-of-conduct.rst
@@ -0,0 +1,76 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/code-of-conduct.rst <code_of_conduct>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+.. _tw_code_of_conduct:
+
+貢獻者契約行為準則
+++++++++++++++++++
+
+我們的誓言
+==========
+
+爲了營造一個開放、友好的環境,我們作爲貢獻者和維護人承諾,讓我們的社區和參
+與者,擁有一個無騷擾的體驗,無論年齡、體型、殘疾、種族、性別特徵、性別認同
+和表達、經驗水平、教育程度、社會狀況,經濟地位、國籍、個人外貌、種族、宗教
+或性身份和取向。
+
+我們的標準
+==========
+
+有助於創造積極環境的行爲包括:
+
+* 使用歡迎和包容的語言
+* 尊重不同的觀點和經驗
+* 優雅地接受建設性的批評
+* 關注什麼對社區最有利
+* 對其他社區成員表示同情
+
+參與者的不可接受行爲包括:
+
+* 使用性意味的語言或意象以及不受歡迎的性注意或者更過分的行爲
+* 煽動、侮辱/貶損評論以及個人或政治攻擊
+* 公開或私下騷擾
+* 未經明確許可,發布他人的私人信息,如物理或電子地址。
+* 在專業場合被合理認爲不適當的其他行爲
+
+我們的責任
+==========
+
+維護人員負責澄清可接受行爲的標準,並應針對任何不可接受行爲採取適當和公平的
+糾正措施。
+
+維護人員有權和責任刪除、編輯或拒絕與本行為準則不一致的評論、承諾、代碼、
+wiki編輯、問題和其他貢獻,或暫時或永久禁止任何貢獻者從事他們認爲不適當、
+威脅、冒犯或有害的其他行爲。
+
+範圍
+====
+
+當個人代表項目或其社區時,本行為準則既適用於項目空間,也適用於公共空間。
+代表一個項目或社區的例子包括使用一個正式的項目電子郵件地址,通過一個正式
+的社交媒體帳戶發布,或者在在線或離線事件中擔任指定的代表。項目維護人員可以
+進一步定義和澄清項目的表示。
+
+執行
+====
+
+如有濫用、騷擾或其他不可接受的行爲,可聯繫行為準則委員會<conduct@kernel.org>。
+所有投訴都將接受審查和調查,並將得到必要和適當的答覆。行為準則委員會有義務
+對事件報告人保密。具體執行政策的進一步細節可單獨公布。
+
+歸屬
+====
+
+本行為準則改編自《貢獻者契約》,版本1.4,可從
+https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 獲取。
+
+解釋
+====
+
+有關Linux內核社區如何解釋此文檔,請參閱 :ref:`tw_code_of_conduct_interpretation`
+
diff --git a/Documentation/translations/zh_TW/process/coding-style.rst b/Documentation/translations/zh_TW/process/coding-style.rst
new file mode 100644
index 000000000000..61e614aad6a7
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/coding-style.rst
@@ -0,0 +1,958 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/coding-style.rst <codingstyle>`
+
+.. _tw_codingstyle:
+
+譯者::
+
+  中文版維護者: 張樂 Zhang Le <r0bertz@gentoo.org>
+  中文版翻譯者: 張樂 Zhang Le <r0bertz@gentoo.org>
+  中文版校譯者: 王聰 Wang Cong <xiyou.wangcong@gmail.com>
+                 wheelz <kernel.zeng@gmail.com>
+                 管旭東 Xudong Guan <xudong.guan@gmail.com>
+                 Li Zefan <lizf@cn.fujitsu.com>
+                 Wang Chen <wangchen@cn.fujitsu.com>
+                 Hu Haowen <src.res@email.cn>
+
+Linux 內核代碼風格
+=========================
+
+這是一個簡短的文檔,描述了 linux 內核的首選代碼風格。代碼風格是因人而異的,
+而且我不願意把自己的觀點強加給任何人,但這就像我去做任何事情都必須遵循的原則
+那樣,我也希望在絕大多數事上保持這種的態度。請 (在寫代碼時) 至少考慮一下這裡
+的代碼風格。
+
+首先,我建議你列印一份 GNU 代碼規範,然後不要讀。燒了它,這是一個具有重大象徵
+性意義的動作。
+
+不管怎樣,現在我們開始:
+
+
+1) 縮進
+--------------
+
+制表符是 8 個字符,所以縮進也是 8 個字符。有些異端運動試圖將縮進變爲 4 (甚至
+2!) 字符深,這幾乎相當於嘗試將圓周率的值定義爲 3。
+
+理由:縮進的全部意義就在於清楚的定義一個控制塊起止於何處。尤其是當你盯著你的
+屏幕連續看了 20 小時之後,你將會發現大一點的縮進會使你更容易分辨縮進。
+
+現在,有些人會抱怨 8 個字符的縮進會使代碼向右邊移動的太遠,在 80 個字符的終端
+屏幕上就很難讀這樣的代碼。這個問題的答案是,如果你需要 3 級以上的縮進,不管用
+何種方式你的代碼已經有問題了,應該修正你的程序。
+
+簡而言之,8 個字符的縮進可以讓代碼更容易閱讀,還有一個好處是當你的函數嵌套太
+深的時候可以給你警告。留心這個警告。
+
+在 switch 語句中消除多級縮進的首選的方式是讓 ``switch`` 和從屬於它的 ``case``
+標籤對齊於同一列,而不要 ``兩次縮進`` ``case`` 標籤。比如:
+
+.. code-block:: c
+
+	switch (suffix) {
+	case 'G':
+	case 'g':
+		mem <<= 30;
+		break;
+	case 'M':
+	case 'm':
+		mem <<= 20;
+		break;
+	case 'K':
+	case 'k':
+		mem <<= 10;
+		fallthrough;
+	default:
+		break;
+	}
+
+不要把多個語句放在一行里,除非你有什麼東西要隱藏:
+
+.. code-block:: c
+
+	if (condition) do_this;
+	  do_something_everytime;
+
+也不要在一行里放多個賦值語句。內核代碼風格超級簡單。就是避免可能導致別人誤讀
+的表達式。
+
+除了注釋、文檔和 Kconfig 之外,不要使用空格來縮進,前面的例子是例外,是有意爲
+之。
+
+選用一個好的編輯器,不要在行尾留空格。
+
+
+2) 把長的行和字符串打散
+------------------------------
+
+代碼風格的意義就在於使用平常使用的工具來維持代碼的可讀性和可維護性。
+
+每一行的長度的限制是 80 列,我們強烈建議您遵守這個慣例。
+
+長於 80 列的語句要打散成有意義的片段。除非超過 80 列能顯著增加可讀性,並且不
+會隱藏信息。子片段要明顯短於母片段,並明顯靠右。這同樣適用於有著很長參數列表
+的函數頭。然而,絕對不要打散對用戶可見的字符串,例如 printk 信息,因爲這樣就
+很難對它們 grep。
+
+
+3) 大括號和空格的放置
+------------------------------
+
+C 語言風格中另外一個常見問題是大括號的放置。和縮進大小不同,選擇或棄用某种放
+置策略並沒有多少技術上的原因,不過首選的方式,就像 Kernighan 和 Ritchie 展示
+給我們的,是把起始大括號放在行尾,而把結束大括號放在行首,所以:
+
+.. code-block:: c
+
+	if (x is true) {
+		we do y
+	}
+
+這適用於所有的非函數語句塊 (if, switch, for, while, do)。比如:
+
+.. code-block:: c
+
+	switch (action) {
+	case KOBJ_ADD:
+		return "add";
+	case KOBJ_REMOVE:
+		return "remove";
+	case KOBJ_CHANGE:
+		return "change";
+	default:
+		return NULL;
+	}
+
+不過,有一個例外,那就是函數:函數的起始大括號放置於下一行的開頭,所以:
+
+.. code-block:: c
+
+	int function(int x)
+	{
+		body of function
+	}
+
+全世界的異端可能會抱怨這個不一致性是... 呃... 不一致的,不過所有思維健全的人
+都知道 (a) K&R 是 **正確的** 並且 (b) K&R 是正確的。此外,不管怎樣函數都是特
+殊的 (C 函數是不能嵌套的)。
+
+注意結束大括號獨自占據一行,除非它後面跟著同一個語句的剩餘部分,也就是 do 語
+句中的 "while" 或者 if 語句中的 "else",像這樣:
+
+.. code-block:: c
+
+	do {
+		body of do-loop
+	} while (condition);
+
+和
+
+.. code-block:: c
+
+	if (x == y) {
+		..
+	} else if (x > y) {
+		...
+	} else {
+		....
+	}
+
+理由:K&R。
+
+也請注意這種大括號的放置方式也能使空 (或者差不多空的) 行的數量最小化,同時不
+失可讀性。因此,由於你的屏幕上的新行是不可再生資源 (想想 25 行的終端屏幕),你
+將會有更多的空行來放置注釋。
+
+當只有一個單獨的語句的時候,不用加不必要的大括號。
+
+.. code-block:: c
+
+	if (condition)
+		action();
+
+和
+
+.. code-block:: c
+
+	if (condition)
+		do_this();
+	else
+		do_that();
+
+這並不適用於只有一個條件分支是單語句的情況;這時所有分支都要使用大括號:
+
+.. code-block:: c
+
+	if (condition) {
+		do_this();
+		do_that();
+	} else {
+		otherwise();
+	}
+
+3.1) 空格
+********************
+
+Linux 內核的空格使用方式 (主要) 取決於它是用於函數還是關鍵字。(大多數) 關鍵字
+後要加一個空格。值得注意的例外是 sizeof, typeof, alignof 和 __attribute__,這
+些關鍵字某些程度上看起來更像函數 (它們在 Linux 里也常常伴隨小括號而使用,儘管
+在 C 里這樣的小括號不是必需的,就像 ``struct fileinfo info;`` 聲明過後的
+``sizeof info``)。
+
+所以在這些關鍵字之後放一個空格::
+
+	if, switch, case, for, do, while
+
+但是不要在 sizeof, typeof, alignof 或者 __attribute__ 這些關鍵字之後放空格。
+例如,
+
+.. code-block:: c
+
+	s = sizeof(struct file);
+
+不要在小括號里的表達式兩側加空格。這是一個 **反例** :
+
+.. code-block:: c
+
+	s = sizeof( struct file );
+
+當聲明指針類型或者返回指針類型的函數時, ``*`` 的首選使用方式是使之靠近變量名
+或者函數名,而不是靠近類型名。例子:
+
+.. code-block:: c
+
+	char *linux_banner;
+	unsigned long long memparse(char *ptr, char **retptr);
+	char *match_strdup(substring_t *s);
+
+在大多數二元和三元操作符兩側使用一個空格,例如下面所有這些操作符::
+
+	=  +  -  <  >  *  /  %  |  &  ^  <=  >=  ==  !=  ?  :
+
+但是一元操作符後不要加空格::
+
+	&  *  +  -  ~  !  sizeof  typeof  alignof  __attribute__  defined
+
+後綴自加和自減一元操作符前不加空格::
+
+	++  --
+
+前綴自加和自減一元操作符後不加空格::
+
+	++  --
+
+``.`` 和 ``->`` 結構體成員操作符前後不加空格。
+
+不要在行尾留空白。有些可以自動縮進的編輯器會在新行的行首加入適量的空白,然後
+你就可以直接在那一行輸入代碼。不過假如你最後沒有在那一行輸入代碼,有些編輯器
+就不會移除已經加入的空白,就像你故意留下一個只有空白的行。包含行尾空白的行就
+這樣產生了。
+
+當 git 發現補丁包含了行尾空白的時候會警告你,並且可以應你的要求去掉行尾空白;
+不過如果你是正在打一系列補丁,這樣做會導致後面的補丁失敗,因爲你改變了補丁的
+上下文。
+
+
+4) 命名
+------------------------------
+
+C 是一個簡樸的語言,你的命名也應該這樣。和 Modula-2 和 Pascal 程式設計師不同,
+C 程式設計師不使用類似 ThisVariableIsATemporaryCounter 這樣華麗的名字。C 程式設計師會
+稱那個變量爲 ``tmp`` ,這樣寫起來會更容易,而且至少不會令其難於理解。
+
+不過,雖然混用大小寫的名字是不提倡使用的,但是全局變量還是需要一個具描述性的
+名字。稱一個全局函數爲 ``foo`` 是一個難以饒恕的錯誤。
+
+全局變量 (只有當你 **真正** 需要它們的時候再用它) 需要有一個具描述性的名字,就
+像全局函數。如果你有一個可以計算活動用戶數量的函數,你應該叫它
+``count_active_users()`` 或者類似的名字,你不應該叫它 ``cntuser()`` 。
+
+在函數名中包含函數類型 (所謂的匈牙利命名法) 是腦子出了問題——編譯器知道那些類
+型而且能夠檢查那些類型,這樣做只能把程式設計師弄糊塗了。難怪微軟總是製造出有問題
+的程序。
+
+本地變量名應該簡短,而且能夠表達相關的含義。如果你有一些隨機的整數型的循環計
+數器,它應該被稱爲 ``i`` 。叫它 ``loop_counter`` 並無益處,如果它沒有被誤解的
+可能的話。類似的, ``tmp`` 可以用來稱呼任意類型的臨時變量。
+
+如果你怕混淆了你的本地變量名,你就遇到另一個問題了,叫做函數增長荷爾蒙失衡綜
+合症。請看第六章 (函數)。
+
+
+5) Typedef
+-----------
+
+不要使用類似 ``vps_t`` 之類的東西。
+
+對結構體和指針使用 typedef 是一個 **錯誤** 。當你在代碼里看到:
+
+.. code-block:: c
+
+	vps_t a;
+
+這代表什麼意思呢?
+
+相反,如果是這樣
+
+.. code-block:: c
+
+	struct virtual_container *a;
+
+你就知道 ``a`` 是什麼了。
+
+很多人認爲 typedef ``能提高可讀性`` 。實際不是這樣的。它們只在下列情況下有用:
+
+ (a) 完全不透明的對象 (這種情況下要主動使用 typedef 來 **隱藏** 這個對象實際上
+     是什麼)。
+
+     例如: ``pte_t`` 等不透明對象,你只能用合適的訪問函數來訪問它們。
+
+     .. note::
+
+       不透明性和 "訪問函數" 本身是不好的。我們使用 pte_t 等類型的原因在於真
+       的是完全沒有任何共用的可訪問信息。
+
+ (b) 清楚的整數類型,如此,這層抽象就可以 **幫助** 消除到底是 ``int`` 還是
+     ``long`` 的混淆。
+
+     u8/u16/u32 是完全沒有問題的 typedef,不過它們更符合類別 (d) 而不是這裡。
+
+     .. note::
+
+       要這樣做,必須事出有因。如果某個變量是 ``unsigned long`` ,那麼沒有必要
+
+	typedef unsigned long myflags_t;
+
+     不過如果有一個明確的原因,比如它在某種情況下可能會是一個 ``unsigned int``
+     而在其他情況下可能爲 ``unsigned long`` ,那麼就不要猶豫,請務必使用
+     typedef。
+
+ (c) 當你使用 sparse 按字面的創建一個 **新** 類型來做類型檢查的時候。
+
+ (d) 和標準 C99 類型相同的類型,在某些例外的情況下。
+
+     雖然讓眼睛和腦筋來適應新的標準類型比如 ``uint32_t`` 不需要花很多時間,可
+     是有些人仍然拒絕使用它們。
+
+     因此,Linux 特有的等同於標準類型的 ``u8/u16/u32/u64`` 類型和它們的有符號
+     類型是被允許的——儘管在你自己的新代碼中,它們不是強制要求要使用的。
+
+     當編輯已經使用了某個類型集的已有代碼時,你應該遵循那些代碼中已經做出的選
+     擇。
+
+ (e) 可以在用戶空間安全使用的類型。
+
+     在某些用戶空間可見的結構體裡,我們不能要求 C99 類型而且不能用上面提到的
+     ``u32`` 類型。因此,我們在與用戶空間共享的所有結構體中使用 __u32 和類似
+     的類型。
+
+可能還有其他的情況,不過基本的規則是 **永遠不要** 使用 typedef,除非你可以明
+確的應用上述某個規則中的一個。
+
+總的來說,如果一個指針或者一個結構體裡的元素可以合理的被直接訪問到,那麼它們
+就不應該是一個 typedef。
+
+
+6) 函數
+------------------------------
+
+函數應該簡短而漂亮,並且只完成一件事情。函數應該可以一屏或者兩屏顯示完 (我們
+都知道 ISO/ANSI 屏幕大小是 80x24),只做一件事情,而且把它做好。
+
+一個函數的最大長度是和該函數的複雜度和縮進級數成反比的。所以,如果你有一個理
+論上很簡單的只有一個很長 (但是簡單) 的 case 語句的函數,而且你需要在每個 case
+里做很多很小的事情,這樣的函數儘管很長,但也是可以的。
+
+不過,如果你有一個複雜的函數,而且你懷疑一個天分不是很高的高中一年級學生可能
+甚至搞不清楚這個函數的目的,你應該嚴格遵守前面提到的長度限制。使用輔助函數,
+並爲之取個具描述性的名字 (如果你覺得它們的性能很重要的話,可以讓編譯器內聯它
+們,這樣的效果往往會比你寫一個複雜函數的效果要好。)
+
+函數的另外一個衡量標準是本地變量的數量。此數量不應超過 5-10 個,否則你的函數
+就有問題了。重新考慮一下你的函數,把它分拆成更小的函數。人的大腦一般可以輕鬆
+的同時跟蹤 7 個不同的事物,如果再增多的話,就會糊塗了。即便你聰穎過人,你也可
+能會記不清你 2 個星期前做過的事情。
+
+在源文件里,使用空行隔開不同的函數。如果該函數需要被導出,它的 **EXPORT** 宏
+應該緊貼在它的結束大括號之下。比如:
+
+.. code-block:: c
+
+	int system_is_up(void)
+	{
+		return system_state == SYSTEM_RUNNING;
+	}
+	EXPORT_SYMBOL(system_is_up);
+
+在函數原型中,包含函數名和它們的數據類型。雖然 C 語言裡沒有這樣的要求,在
+Linux 里這是提倡的做法,因爲這樣可以很簡單的給讀者提供更多的有價值的信息。
+
+
+7) 集中的函數退出途徑
+------------------------------
+
+雖然被某些人聲稱已經過時,但是 goto 語句的等價物還是經常被編譯器所使用,具體
+形式是無條件跳轉指令。
+
+當一個函數從多個位置退出,並且需要做一些類似清理的常見操作時,goto 語句就很方
+便了。如果並不需要清理操作,那麼直接 return 即可。
+
+選擇一個能夠說明 goto 行爲或它爲何存在的標籤名。如果 goto 要釋放 ``buffer``,
+一個不錯的名字可以是 ``out_free_buffer:`` 。別去使用像 ``err1:`` 和 ``err2:``
+這樣的GW_BASIC 名稱,因爲一旦你添加或刪除了 (函數的) 退出路徑,你就必須對它們
+重新編號,這樣會難以去檢驗正確性。
+
+使用 goto 的理由是:
+
+- 無條件語句容易理解和跟蹤
+- 嵌套程度減小
+- 可以避免由於修改時忘記更新個別的退出點而導致錯誤
+- 讓編譯器省去刪除冗餘代碼的工作 ;)
+
+.. code-block:: c
+
+	int fun(int a)
+	{
+		int result = 0;
+		char *buffer;
+
+		buffer = kmalloc(SIZE, GFP_KERNEL);
+		if (!buffer)
+			return -ENOMEM;
+
+		if (condition1) {
+			while (loop1) {
+				...
+			}
+			result = 1;
+			goto out_free_buffer;
+		}
+		...
+	out_free_buffer:
+		kfree(buffer);
+		return result;
+	}
+
+一個需要注意的常見錯誤是 ``一個 err 錯誤`` ,就像這樣:
+
+.. code-block:: c
+
+	err:
+		kfree(foo->bar);
+		kfree(foo);
+		return ret;
+
+這段代碼的錯誤是,在某些退出路徑上 ``foo`` 是 NULL。通常情況下,通過把它分離
+成兩個錯誤標籤 ``err_free_bar:`` 和 ``err_free_foo:`` 來修復這個錯誤:
+
+.. code-block:: c
+
+	 err_free_bar:
+		kfree(foo->bar);
+	 err_free_foo:
+		kfree(foo);
+		return ret;
+
+理想情況下,你應該模擬錯誤來測試所有退出路徑。
+
+
+8) 注釋
+------------------------------
+
+注釋是好的,不過有過度注釋的危險。永遠不要在注釋里解釋你的代碼是如何運作的:
+更好的做法是讓別人一看你的代碼就可以明白,解釋寫的很差的代碼是浪費時間。
+
+一般的,你想要你的注釋告訴別人你的代碼做了什麼,而不是怎麼做的。也請你不要把
+注釋放在一個函數體內部:如果函數複雜到你需要獨立的注釋其中的一部分,你很可能
+需要回到第六章看一看。你可以做一些小注釋來註明或警告某些很聰明 (或者槽糕) 的
+做法,但不要加太多。你應該做的,是把注釋放在函數的頭部,告訴人們它做了什麼,
+也可以加上它做這些事情的原因。
+
+當注釋內核 API 函數時,請使用 kernel-doc 格式。請看
+Documentation/doc-guide/ 和 scripts/kernel-doc 以獲得詳細信息。
+
+長 (多行) 注釋的首選風格是:
+
+.. code-block:: c
+
+	/*
+	 * This is the preferred style for multi-line
+	 * comments in the Linux kernel source code.
+	 * Please use it consistently.
+	 *
+	 * Description:  A column of asterisks on the left side,
+	 * with beginning and ending almost-blank lines.
+	 */
+
+對於在 net/ 和 drivers/net/ 的文件,首選的長 (多行) 注釋風格有些不同。
+
+.. code-block:: c
+
+	/* The preferred comment style for files in net/ and drivers/net
+	 * looks like this.
+	 *
+	 * It is nearly the same as the generally preferred comment style,
+	 * but there is no initial almost-blank line.
+	 */
+
+注釋數據也是很重要的,不管是基本類型還是衍生類型。爲了方便實現這一點,每一行
+應只聲明一個數據 (不要使用逗號來一次聲明多個數據)。這樣你就有空間來爲每個數據
+寫一段小注釋來解釋它們的用途了。
+
+
+9) 你已經把事情弄糟了
+------------------------------
+
+這沒什麼,我們都是這樣。可能你的使用了很長時間 Unix 的朋友已經告訴你
+``GNU emacs`` 能自動幫你格式化 C 原始碼,而且你也注意到了,確實是這樣,不過它
+所使用的默認值和我們想要的相去甚遠 (實際上,甚至比隨機打的還要差——無數個猴子
+在 GNU emacs 里打字永遠不會創造出一個好程序) (譯註:Infinite Monkey Theorem)
+
+所以你要麼放棄 GNU emacs,要麼改變它讓它使用更合理的設定。要採用後一個方案,
+你可以把下面這段粘貼到你的 .emacs 文件里。
+
+.. code-block:: none
+
+  (defun c-lineup-arglist-tabs-only (ignored)
+    "Line up argument lists by tabs, not spaces"
+    (let* ((anchor (c-langelem-pos c-syntactic-element))
+           (column (c-langelem-2nd-pos c-syntactic-element))
+           (offset (- (1+ column) anchor))
+           (steps (floor offset c-basic-offset)))
+      (* (max steps 1)
+         c-basic-offset)))
+
+  (dir-locals-set-class-variables
+   'linux-kernel
+   '((c-mode . (
+          (c-basic-offset . 8)
+          (c-label-minimum-indentation . 0)
+          (c-offsets-alist . (
+                  (arglist-close         . c-lineup-arglist-tabs-only)
+                  (arglist-cont-nonempty .
+		      (c-lineup-gcc-asm-reg c-lineup-arglist-tabs-only))
+                  (arglist-intro         . +)
+                  (brace-list-intro      . +)
+                  (c                     . c-lineup-C-comments)
+                  (case-label            . 0)
+                  (comment-intro         . c-lineup-comment)
+                  (cpp-define-intro      . +)
+                  (cpp-macro             . -1000)
+                  (cpp-macro-cont        . +)
+                  (defun-block-intro     . +)
+                  (else-clause           . 0)
+                  (func-decl-cont        . +)
+                  (inclass               . +)
+                  (inher-cont            . c-lineup-multi-inher)
+                  (knr-argdecl-intro     . 0)
+                  (label                 . -1000)
+                  (statement             . 0)
+                  (statement-block-intro . +)
+                  (statement-case-intro  . +)
+                  (statement-cont        . +)
+                  (substatement          . +)
+                  ))
+          (indent-tabs-mode . t)
+          (show-trailing-whitespace . t)
+          ))))
+
+  (dir-locals-set-directory-class
+   (expand-file-name "~/src/linux-trees")
+   'linux-kernel)
+
+這會讓 emacs 在 ``~/src/linux-trees`` 下的 C 源文件獲得更好的內核代碼風格。
+
+不過就算你嘗試讓 emacs 正確的格式化代碼失敗了,也並不意味著你失去了一切:還可
+以用 ``indent`` 。
+
+不過,GNU indent 也有和 GNU emacs 一樣有問題的設定,所以你需要給它一些命令選
+項。不過,這還不算太糟糕,因爲就算是 GNU indent 的作者也認同 K&R 的權威性
+(GNU 的人並不是壞人,他們只是在這個問題上被嚴重的誤導了),所以你只要給 indent
+指定選項 ``-kr -i8`` (代表 ``K&R,8 字符縮進``),或使用 ``scripts/Lindent``
+這樣就可以以最時髦的方式縮進原始碼。
+
+``indent`` 有很多選項,特別是重新格式化注釋的時候,你可能需要看一下它的手冊。
+不過記住: ``indent`` 不能修正壞的編程習慣。
+
+
+10) Kconfig 配置文件
+------------------------------
+
+對於遍布源碼樹的所有 Kconfig* 配置文件來說,它們縮進方式有所不同。緊挨著
+``config`` 定義的行,用一個制表符縮進,然而 help 信息的縮進則額外增加 2 個空
+格。舉個例子::
+
+  config AUDIT
+	bool "Auditing support"
+	depends on NET
+	help
+	  Enable auditing infrastructure that can be used with another
+	  kernel subsystem, such as SELinux (which requires this for
+	  logging of avc messages output).  Does not do system-call
+	  auditing without CONFIG_AUDITSYSCALL.
+
+而那些危險的功能 (比如某些文件系統的寫支持) 應該在它們的提示字符串里顯著的聲
+明這一點::
+
+  config ADFS_FS_RW
+	bool "ADFS write support (DANGEROUS)"
+	depends on ADFS_FS
+	...
+
+要查看配置文件的完整文檔,請看 Documentation/kbuild/kconfig-language.rst。
+
+
+11) 數據結構
+------------------------------
+
+如果一個數據結構,在創建和銷毀它的單線執行環境之外可見,那麼它必須要有一個引
+用計數器。內核里沒有垃圾收集 (並且內核之外的垃圾收集慢且效率低下),這意味著你
+絕對需要記錄你對這種數據結構的使用情況。
+
+引用計數意味著你能夠避免上鎖,並且允許多個用戶並行訪問這個數據結構——而不需要
+擔心這個數據結構僅僅因爲暫時不被使用就消失了,那些用戶可能不過是沉睡了一陣或
+者做了一些其他事情而已。
+
+注意上鎖 **不能** 取代引用計數。上鎖是爲了保持數據結構的一致性,而引用計數是一
+個內存管理技巧。通常二者都需要,不要把兩個搞混了。
+
+很多數據結構實際上有 2 級引用計數,它們通常有不同 ``類`` 的用戶。子類計數器統
+計子類用戶的數量,每當子類計數器減至零時,全局計數器減一。
+
+這種 ``多級引用計數`` 的例子可以在內存管理 (``struct mm_struct``: mm_users 和
+mm_count),和文件系統 (``struct super_block``: s_count 和 s_active) 中找到。
+
+記住:如果另一個執行線索可以找到你的數據結構,但這個數據結構沒有引用計數器,
+這裡幾乎肯定是一個 bug。
+
+
+12) 宏,枚舉和RTL
+------------------------------
+
+用於定義常量的宏的名字及枚舉里的標籤需要大寫。
+
+.. code-block:: c
+
+	#define CONSTANT 0x12345
+
+在定義幾個相關的常量時,最好用枚舉。
+
+宏的名字請用大寫字母,不過形如函數的宏的名字可以用小寫字母。
+
+一般的,如果能寫成內聯函數就不要寫成像函數的宏。
+
+含有多個語句的宏應該被包含在一個 do-while 代碼塊里:
+
+.. code-block:: c
+
+	#define macrofun(a, b, c)			\
+		do {					\
+			if (a == 5)			\
+				do_this(b, c);		\
+		} while (0)
+
+使用宏的時候應避免的事情:
+
+1) 影響控制流程的宏:
+
+.. code-block:: c
+
+	#define FOO(x)					\
+		do {					\
+			if (blah(x) < 0)		\
+				return -EBUGGERED;	\
+		} while (0)
+
+**非常** 不好。它看起來像一個函數,不過卻能導致 ``調用`` 它的函數退出;不要打
+亂讀者大腦里的語法分析器。
+
+2) 依賴於一個固定名字的本地變量的宏:
+
+.. code-block:: c
+
+	#define FOO(val) bar(index, val)
+
+可能看起來像是個不錯的東西,不過它非常容易把讀代碼的人搞糊塗,而且容易導致看起
+來不相關的改動帶來錯誤。
+
+3) 作爲左值的帶參數的宏: FOO(x) = y;如果有人把 FOO 變成一個內聯函數的話,這
+   種用法就會出錯了。
+
+4) 忘記了優先級:使用表達式定義常量的宏必須將表達式置於一對小括號之內。帶參數
+   的宏也要注意此類問題。
+
+.. code-block:: c
+
+	#define CONSTANT 0x4000
+	#define CONSTEXP (CONSTANT | 3)
+
+5) 在宏里定義類似函數的本地變量時命名衝突:
+
+.. code-block:: c
+
+	#define FOO(x)				\
+	({					\
+		typeof(x) ret;			\
+		ret = calc_ret(x);		\
+		(ret);				\
+	})
+
+ret 是本地變量的通用名字 - __foo_ret 更不容易與一個已存在的變量衝突。
+
+cpp 手冊對宏的講解很詳細。gcc internals 手冊也詳細講解了 RTL,內核里的彙編語
+言經常用到它。
+
+
+13) 列印內核消息
+------------------------------
+
+內核開發者應該是受過良好教育的。請一定注意內核信息的拼寫,以給人以好的印象。
+不要用不規範的單詞比如 ``dont``,而要用 ``do not`` 或者 ``don't`` 。保證這些信
+息簡單明了,無歧義。
+
+內核信息不必以英文句號結束。
+
+在小括號里列印數字 (%d) 沒有任何價值,應該避免這樣做。
+
+<linux/device.h> 里有一些驅動模型診斷宏,你應該使用它們,以確保信息對應於正確
+的設備和驅動,並且被標記了正確的消息級別。這些宏有:dev_err(), dev_warn(),
+dev_info() 等等。對於那些不和某個特定設備相關連的信息,<linux/printk.h> 定義
+了 pr_notice(), pr_info(), pr_warn(), pr_err() 和其他。
+
+寫出好的調試信息可以是一個很大的挑戰;一旦你寫出後,這些信息在遠程除錯時能提
+供極大的幫助。然而列印調試信息的處理方式同列印非調試信息不同。其他 pr_XXX()
+函數能無條件地列印,pr_debug() 卻不;默認情況下它不會被編譯,除非定義了 DEBUG
+或設定了 CONFIG_DYNAMIC_DEBUG。實際這同樣是爲了 dev_dbg(),一個相關約定是在一
+個已經開啓了 DEBUG 時,使用 VERBOSE_DEBUG 來添加 dev_vdbg()。
+
+許多子系統擁有 Kconfig 調試選項來開啓 -DDEBUG 在對應的 Makefile 裡面;在其他
+情況下,特殊文件使用 #define DEBUG。當一條調試信息需要被無條件列印時,例如,
+如果已經包含一個調試相關的 #ifdef 條件,printk(KERN_DEBUG ...) 就可被使用。
+
+
+14) 分配內存
+------------------------------
+
+內核提供了下面的一般用途的內存分配函數:
+kmalloc(), kzalloc(), kmalloc_array(), kcalloc(), vmalloc() 和 vzalloc()。
+請參考 API 文檔以獲取有關它們的詳細信息。
+
+傳遞結構體大小的首選形式是這樣的:
+
+.. code-block:: c
+
+	p = kmalloc(sizeof(*p), ...);
+
+另外一種傳遞方式中,sizeof 的操作數是結構體的名字,這樣會降低可讀性,並且可能
+會引入 bug。有可能指針變量類型被改變時,而對應的傳遞給內存分配函數的 sizeof
+的結果不變。
+
+強制轉換一個 void 指針返回值是多餘的。C 語言本身保證了從 void 指針到其他任何
+指針類型的轉換是沒有問題的。
+
+分配一個數組的首選形式是這樣的:
+
+.. code-block:: c
+
+	p = kmalloc_array(n, sizeof(...), ...);
+
+分配一個零長數組的首選形式是這樣的:
+
+.. code-block:: c
+
+	p = kcalloc(n, sizeof(...), ...);
+
+兩種形式檢查分配大小 n * sizeof(...) 的溢出,如果溢出返回 NULL。
+
+
+15) 內聯弊病
+------------------------------
+
+有一個常見的誤解是 ``內聯`` 是 gcc 提供的可以讓代碼運行更快的一個選項。雖然使
+用內聯函數有時候是恰當的 (比如作爲一種替代宏的方式,請看第十二章),不過很多情
+況下不是這樣。inline 的過度使用會使內核變大,從而使整個系統運行速度變慢。
+因爲體積大內核會占用更多的指令高速緩存,而且會導致 pagecache 的可用內存減少。
+想像一下,一次 pagecache 未命中就會導致一次磁碟尋址,將耗時 5 毫秒。5 毫秒的
+時間內 CPU 能執行很多很多指令。
+
+一個基本的原則是如果一個函數有 3 行以上,就不要把它變成內聯函數。這個原則的一
+個例外是,如果你知道某個參數是一個編譯時常量,而且因爲這個常量你確定編譯器在
+編譯時能優化掉你的函數的大部分代碼,那仍然可以給它加上 inline 關鍵字。
+kmalloc() 內聯函數就是一個很好的例子。
+
+人們經常主張給 static 的而且只用了一次的函數加上 inline,如此不會有任何損失,
+因爲沒有什麼好權衡的。雖然從技術上說這是正確的,但是實際上這種情況下即使不加
+inline gcc 也可以自動使其內聯。而且其他用戶可能會要求移除 inline,由此而來的
+爭論會抵消 inline 自身的潛在價值,得不償失。
+
+
+16) 函數返回值及命名
+------------------------------
+
+函數可以返回多種不同類型的值,最常見的一種是表明函數執行成功或者失敗的值。這樣
+的一個值可以表示爲一個錯誤代碼整數 (-Exxx=失敗,0=成功) 或者一個 ``成功``
+布爾值 (0=失敗,非0=成功)。
+
+混合使用這兩種表達方式是難於發現的 bug 的來源。如果 C 語言本身嚴格區分整形和
+布爾型變量,那麼編譯器就能夠幫我們發現這些錯誤... 不過 C 語言不區分。爲了避免
+產生這種 bug,請遵循下面的慣例::
+
+	如果函數的名字是一個動作或者強制性的命令,那麼這個函數應該返回錯誤代
+	碼整數。如果是一個判斷,那麼函數應該返回一個 "成功" 布爾值。
+
+比如, ``add work`` 是一個命令,所以 add_work() 在成功時返回 0,在失敗時返回
+-EBUSY。類似的,因爲 ``PCI device present`` 是一個判斷,所以 pci_dev_present()
+在成功找到一個匹配的設備時應該返回 1,如果找不到時應該返回 0。
+
+所有 EXPORTed 函數都必須遵守這個慣例,所有的公共函數也都應該如此。私有
+(static) 函數不需要如此,但是我們也推薦這樣做。
+
+返回值是實際計算結果而不是計算是否成功的標誌的函數不受此慣例的限制。一般的,
+他們通過返回一些正常值範圍之外的結果來表示出錯。典型的例子是返回指針的函數,
+他們使用 NULL 或者 ERR_PTR 機制來報告錯誤。
+
+
+17) 不要重新發明內核宏
+------------------------------
+
+頭文件 include/linux/kernel.h 包含了一些宏,你應該使用它們,而不要自己寫一些
+它們的變種。比如,如果你需要計算一個數組的長度,使用這個宏
+
+.. code-block:: c
+
+	#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+類似的,如果你要計算某結構體成員的大小,使用
+
+.. code-block:: c
+
+	#define sizeof_field(t, f) (sizeof(((t*)0)->f))
+
+還有可以做嚴格的類型檢查的 min() 和 max() 宏,如果你需要可以使用它們。你可以
+自己看看那個頭文件里還定義了什麼你可以拿來用的東西,如果有定義的話,你就不應
+在你的代碼里自己重新定義。
+
+
+18) 編輯器模式行和其他需要羅嗦的事情
+--------------------------------------------------
+
+有一些編輯器可以解釋嵌入在源文件里的由一些特殊標記標明的配置信息。比如,emacs
+能夠解釋被標記成這樣的行:
+
+.. code-block:: c
+
+	-*- mode: c -*-
+
+或者這樣的:
+
+.. code-block:: c
+
+	/*
+	Local Variables:
+	compile-command: "gcc -DMAGIC_DEBUG_FLAG foo.c"
+	End:
+	*/
+
+Vim 能夠解釋這樣的標記:
+
+.. code-block:: c
+
+	/* vim:set sw=8 noet */
+
+不要在原始碼中包含任何這樣的內容。每個人都有他自己的編輯器配置,你的源文件不
+應該覆蓋別人的配置。這包括有關縮進和模式配置的標記。人們可以使用他們自己定製
+的模式,或者使用其他可以產生正確的縮進的巧妙方法。
+
+
+19) 內聯彙編
+------------------------------
+
+在特定架構的代碼中,你可能需要內聯彙編與 CPU 和平台相關功能連接。需要這麼做時
+就不要猶豫。然而,當 C 可以完成工作時,不要平白無故地使用內聯彙編。在可能的情
+況下,你可以並且應該用 C 和硬體溝通。
+
+請考慮去寫捆綁通用位元 (wrap common bits) 的內聯彙編的簡單輔助函數,別去重複
+地寫下只有細微差異內聯彙編。記住內聯彙編可以使用 C 參數。
+
+大型,有一定複雜度的彙編函數應該放在 .S 文件內,用相應的 C 原型定義在 C 頭文
+件中。彙編函數的 C 原型應該使用 ``asmlinkage`` 。
+
+你可能需要把彙編語句標記爲 volatile,用來阻止 GCC 在沒發現任何副作用後就把它
+移除了。你不必總是這樣做,儘管,這不必要的舉動會限制優化。
+
+在寫一個包含多條指令的單個內聯彙編語句時,把每條指令用引號分割而且各占一行,
+除了最後一條指令外,在每個指令結尾加上 \n\t,讓彙編輸出時可以正確地縮進下一條
+指令:
+
+.. code-block:: c
+
+	asm ("magic %reg1, #42\n\t"
+	     "more_magic %reg2, %reg3"
+	     : /* outputs */ : /* inputs */ : /* clobbers */);
+
+
+20) 條件編譯
+------------------------------
+
+只要可能,就不要在 .c 文件裡面使用預處理條件 (#if, #ifdef);這樣做讓代碼更難
+閱讀並且更難去跟蹤邏輯。替代方案是,在頭文件中用預處理條件提供給那些 .c 文件
+使用,再給 #else 提供一個空樁 (no-op stub) 版本,然後在 .c 文件內無條件地調用
+那些 (定義在頭文件內的) 函數。這樣做,編譯器會避免爲樁函數 (stub) 的調用生成
+任何代碼,產生的結果是相同的,但邏輯將更加清晰。
+
+最好傾向於編譯整個函數,而不是函數的一部分或表達式的一部分。與其放一個 ifdef
+在表達式內,不如分解出部分或全部表達式,放進一個單獨的輔助函數,並應用預處理
+條件到這個輔助函數內。
+
+如果你有一個在特定配置中,可能變成未使用的函數或變量,編譯器會警告它定義了但
+未使用,把它標記爲 __maybe_unused 而不是將它包含在一個預處理條件中。(然而,如
+果一個函數或變量總是未使用,就直接刪除它。)
+
+在代碼中,儘可能地使用 IS_ENABLED 宏來轉化某個 Kconfig 標記爲 C 的布爾
+表達式,並在一般的 C 條件中使用它:
+
+.. code-block:: c
+
+	if (IS_ENABLED(CONFIG_SOMETHING)) {
+		...
+	}
+
+編譯器會做常量摺疊,然後就像使用 #ifdef 那樣去包含或排除代碼塊,所以這不會帶
+來任何運行時開銷。然而,這種方法依舊允許 C 編譯器查看塊內的代碼,並檢查它的正
+確性 (語法,類型,符號引用,等等)。因此,如果條件不滿足,代碼塊內的引用符號就
+不存在時,你還是必須去用 #ifdef。
+
+在任何有意義的 #if 或 #ifdef 塊的末尾 (超過幾行的),在 #endif 同一行的後面寫下
+註解,注釋這個條件表達式。例如:
+
+.. code-block:: c
+
+	#ifdef CONFIG_SOMETHING
+	...
+	#endif /* CONFIG_SOMETHING */
+
+
+附錄 I) 參考
+-------------------
+
+The C Programming Language, 第二版
+作者:Brian W. Kernighan 和 Denni M. Ritchie.
+Prentice Hall, Inc., 1988.
+ISBN 0-13-110362-8 (軟皮), 0-13-110370-9 (硬皮).
+
+The Practice of Programming
+作者:Brian W. Kernighan 和 Rob Pike.
+Addison-Wesley, Inc., 1999.
+ISBN 0-201-61586-X.
+
+GNU 手冊 - 遵循 K&R 標準和此文本 - cpp, gcc, gcc internals and indent,
+都可以從 https://www.gnu.org/manual/ 找到
+
+WG14 是 C 語言的國際標準化工作組,URL: http://www.open-std.org/JTC1/SC22/WG14/
+
+Kernel process/coding-style.rst,作者 greg@kroah.com 發表於 OLS 2002:
+http://www.kroah.com/linux/talks/ols_2002_kernel_codingstyle_talk/html/
+
diff --git a/Documentation/translations/zh_TW/process/development-process.rst b/Documentation/translations/zh_TW/process/development-process.rst
new file mode 100644
index 000000000000..45e6385647cd
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/development-process.rst
@@ -0,0 +1,30 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/development-process.rst <development_process_main>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+.. _tw_development_process_main:
+
+內核開發過程指南
+================
+
+內容:
+
+.. toctree::
+   :numbered:
+   :maxdepth: 2
+
+   1.Intro
+   2.Process
+   3.Early-stage
+   4.Coding
+   5.Posting
+   6.Followthrough
+   7.AdvancedTopics
+   8.Conclusion
+
+本文檔的目的是幫助開發人員(及其經理)以最小的挫折感與開發社區合作。它試圖記錄這個社區如何以一種不熟悉Linux內核開發(或者實際上是自由軟體開發)的人可以訪問的方式工作。雖然這裡有一些技術資料,但這是一個面向過程的討論,不需要深入了解內核編程就可以理解。
+
diff --git a/Documentation/translations/zh_TW/process/email-clients.rst b/Documentation/translations/zh_TW/process/email-clients.rst
new file mode 100644
index 000000000000..4ba543d06f3b
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/email-clients.rst
@@ -0,0 +1,252 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _tw_email_clients:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/email-clients.rst <email_clients>`
+
+譯者::
+
+        中文版維護者: 賈威威  Harry Wei <harryxiyou@gmail.com>
+        中文版翻譯者: 賈威威  Harry Wei <harryxiyou@gmail.com>
+                       時奎亮  Alex Shi <alex.shi@linux.alibaba.com>
+        中文版校譯者: Yinglin Luan <synmyth@gmail.com>
+        	       Xiaochen Wang <wangxiaochen0@gmail.com>
+                       yaxinsn <yaxinsn@163.com>
+                      Hu Haowen <src.res@email.cn>
+
+Linux郵件客戶端配置信息
+=======================
+
+Git
+---
+
+現在大多數開發人員使用 ``git send-email`` 而不是常規的電子郵件客戶端。這方面
+的手冊非常好。在接收端,維護人員使用 ``git am`` 加載補丁。
+
+如果你是 ``git`` 新手,那麼把你的第一個補丁發送給你自己。將其保存爲包含所有
+標題的原始文本。運行 ``git am raw_email.txt`` ,然後使用 ``git log`` 查看更
+改日誌。如果工作正常,再將補丁發送到相應的郵件列表。
+
+
+普通配置
+--------
+Linux內核補丁是通過郵件被提交的,最好把補丁作爲郵件體的內嵌文本。有些維護者
+接收附件,但是附件的內容格式應該是"text/plain"。然而,附件一般是不贊成的,
+因爲這會使補丁的引用部分在評論過程中變的很困難。
+
+用來發送Linux內核補丁的郵件客戶端在發送補丁時應該處於文本的原始狀態。例如,
+他們不能改變或者刪除制表符或者空格,甚至是在每一行的開頭或者結尾。
+
+不要通過"format=flowed"模式發送補丁。這樣會引起不可預期以及有害的斷行。
+
+不要讓你的郵件客戶端進行自動換行。這樣也會破壞你的補丁。
+
+郵件客戶端不能改變文本的字符集編碼方式。要發送的補丁只能是ASCII或者UTF-8編碼方式,
+如果你使用UTF-8編碼方式發送郵件,那麼你將會避免一些可能發生的字符集問題。
+
+郵件客戶端應該形成並且保持 References: 或者 In-Reply-To: 標題,那麼
+郵件話題就不會中斷。
+
+複製粘帖(或者剪貼粘帖)通常不能用於補丁,因爲制表符會轉換爲空格。使用xclipboard, xclip
+或者xcutsel也許可以,但是最好測試一下或者避免使用複製粘帖。
+
+不要在使用PGP/GPG署名的郵件中包含補丁。這樣會使得很多腳本不能讀取和適用於你的補丁。
+(這個問題應該是可以修復的)
+
+在給內核郵件列表發送補丁之前,給自己發送一個補丁是個不錯的主意,保存接收到的
+郵件,將補丁用'patch'命令打上,如果成功了,再給內核郵件列表發送。
+
+
+一些郵件客戶端提示
+------------------
+這裡給出一些詳細的MUA配置提示,可以用於給Linux內核發送補丁。這些並不意味是
+所有的軟體包配置總結。
+
+說明:
+TUI = 以文本爲基礎的用戶接口
+GUI = 圖形界面用戶接口
+
+Alpine (TUI)
+~~~~~~~~~~~~
+
+配置選項:
+在"Sending Preferences"部分:
+
+- "Do Not Send Flowed Text"必須開啓
+- "Strip Whitespace Before Sending"必須關閉
+
+當寫郵件時,光標應該放在補丁會出現的地方,然後按下CTRL-R組合鍵,使指定的
+補丁文件嵌入到郵件中。
+
+Evolution (GUI)
+~~~~~~~~~~~~~~~
+
+一些開發者成功的使用它發送補丁
+
+當選擇郵件選項:Preformat
+  從Format->Heading->Preformatted (Ctrl-7)或者工具欄
+
+然後使用:
+  Insert->Text File... (Alt-n x)插入補丁文件。
+
+你還可以"diff -Nru old.c new.c | xclip",選擇Preformat,然後使用中間鍵進行粘帖。
+
+Kmail (GUI)
+~~~~~~~~~~~
+
+一些開發者成功的使用它發送補丁。
+
+默認設置不爲HTML格式是合適的;不要啓用它。
+
+當書寫一封郵件的時候,在選項下面不要選擇自動換行。唯一的缺點就是你在郵件中輸入的任何文本
+都不會被自動換行,因此你必須在發送補丁之前手動換行。最簡單的方法就是啓用自動換行來書寫郵件,
+然後把它保存爲草稿。一旦你在草稿中再次打開它,它已經全部自動換行了,那麼你的郵件雖然沒有
+選擇自動換行,但是還不會失去已有的自動換行。
+
+在郵件的底部,插入補丁之前,放上常用的補丁定界符:三個連字號(---)。
+
+然後在"Message"菜單條目,選擇插入文件,接著選取你的補丁文件。還有一個額外的選項,你可以
+通過它配置你的郵件建立工具欄菜單,還可以帶上"insert file"圖標。
+
+你可以安全地通過GPG標記附件,但是內嵌補丁最好不要使用GPG標記它們。作爲內嵌文本的簽發補丁,
+當從GPG中提取7位編碼時會使他們變的更加複雜。
+
+如果你非要以附件的形式發送補丁,那麼就右鍵點擊附件,然後選中屬性,突出"Suggest automatic
+display",這樣內嵌附件更容易讓讀者看到。
+
+當你要保存將要發送的內嵌文本補丁,你可以從消息列表窗格選擇包含補丁的郵件,然後右擊選擇
+"save as"。你可以使用一個沒有更改的包含補丁的郵件,如果它是以正確的形式組成。當你正真在它
+自己的窗口之下察看,那時沒有選項可以保存郵件--已經有一個這樣的bug被匯報到了kmail的bugzilla
+並且希望這將會被處理。郵件是以只針對某個用戶可讀寫的權限被保存的,所以如果你想把郵件複製到其他地方,
+你不得不把他們的權限改爲組或者整體可讀。
+
+Lotus Notes (GUI)
+~~~~~~~~~~~~~~~~~
+
+不要使用它。
+
+Mutt (TUI)
+~~~~~~~~~~
+
+很多Linux開發人員使用mutt客戶端,所以證明它肯定工作的非常漂亮。
+
+Mutt不自帶編輯器,所以不管你使用什麼編輯器都不應該帶有自動斷行。大多數編輯器都帶有
+一個"insert file"選項,它可以通過不改變文件內容的方式插入文件。
+
+'vim'作爲mutt的編輯器:
+  set editor="vi"
+
+  如果使用xclip,敲入以下命令
+  :set paste
+  按中鍵之前或者shift-insert或者使用
+  :r filename
+
+如果想要把補丁作爲內嵌文本。
+(a)ttach工作的很好,不帶有"set paste"。
+
+你可以通過 ``git format-patch`` 生成補丁,然後用 Mutt發送它們::
+
+        $ mutt -H 0001-some-bug-fix.patch
+
+配置選項:
+它應該以默認設置的形式工作。
+然而,把"send_charset"設置爲"us-ascii::utf-8"也是一個不錯的主意。
+
+Mutt 是高度可配置的。 這裡是個使用mutt通過 Gmail 發送的補丁的最小配置::
+
+  # .muttrc
+  # ================  IMAP ====================
+  set imap_user = 'yourusername@gmail.com'
+  set imap_pass = 'yourpassword'
+  set spoolfile = imaps://imap.gmail.com/INBOX
+  set folder = imaps://imap.gmail.com/
+  set record="imaps://imap.gmail.com/[Gmail]/Sent Mail"
+  set postponed="imaps://imap.gmail.com/[Gmail]/Drafts"
+  set mbox="imaps://imap.gmail.com/[Gmail]/All Mail"
+
+  # ================  SMTP  ====================
+  set smtp_url = "smtp://username@smtp.gmail.com:587/"
+  set smtp_pass = $imap_pass
+  set ssl_force_tls = yes # Require encrypted connection
+
+  # ================  Composition  ====================
+  set editor = `echo \$EDITOR`
+  set edit_headers = yes  # See the headers when editing
+  set charset = UTF-8     # value of $LANG; also fallback for send_charset
+  # Sender, email address, and sign-off line must match
+  unset use_domain        # because joe@localhost is just embarrassing
+  set realname = "YOUR NAME"
+  set from = "username@gmail.com"
+  set use_from = yes
+
+Mutt文檔含有更多信息:
+
+    http://dev.mutt.org/trac/wiki/UseCases/Gmail
+
+    http://dev.mutt.org/doc/manual.html
+
+Pine (TUI)
+~~~~~~~~~~
+
+Pine過去有一些空格刪減問題,但是這些現在應該都被修復了。
+
+如果可以,請使用alpine(pine的繼承者)
+
+配置選項:
+- 最近的版本需要消除流程文本
+- "no-strip-whitespace-before-send"選項也是需要的。
+
+
+Sylpheed (GUI)
+~~~~~~~~~~~~~~
+
+- 內嵌文本可以很好的工作(或者使用附件)。
+- 允許使用外部的編輯器。
+- 對於目錄較多時非常慢。
+- 如果通過non-SSL連接,無法使用TLS SMTP授權。
+- 在組成窗口中有一個很有用的ruler bar。
+- 給地址本中添加地址就不會正確的了解顯示名。
+
+Thunderbird (GUI)
+~~~~~~~~~~~~~~~~~
+
+默認情況下,thunderbird很容易損壞文本,但是還有一些方法可以強制它變得更好。
+
+- 在用戶帳號設置里,組成和尋址,不要選擇"Compose messages in HTML format"。
+
+- 編輯你的Thunderbird配置設置來使它不要拆行使用:user_pref("mailnews.wraplength", 0);
+
+- 編輯你的Thunderbird配置設置,使它不要使用"format=flowed"格式:user_pref("mailnews.
+  send_plaintext_flowed", false);
+
+- 你需要使Thunderbird變爲預先格式方式:
+  如果默認情況下你書寫的是HTML格式,那不是很難。僅僅從標題欄的下拉框中選擇"Preformat"格式。
+  如果默認情況下你書寫的是文本格式,你不得把它改爲HTML格式(僅僅作爲一次性的)來書寫新的消息,
+  然後強制使它回到文本格式,否則它就會拆行。要實現它,在寫信的圖標上使用shift鍵來使它變爲HTML
+  格式,然後標題欄的下拉框中選擇"Preformat"格式。
+
+- 允許使用外部的編輯器:
+  針對Thunderbird打補丁最簡單的方法就是使用一個"external editor"擴展,然後使用你最喜歡的
+  $EDITOR來讀取或者合併補丁到文本中。要實現它,可以下載並且安裝這個擴展,然後添加一個使用它的
+  按鍵View->Toolbars->Customize...最後當你書寫信息的時候僅僅點擊它就可以了。
+
+TkRat (GUI)
+~~~~~~~~~~~
+
+可以使用它。使用"Insert file..."或者外部的編輯器。
+
+Gmail (Web GUI)
+~~~~~~~~~~~~~~~
+
+不要使用它發送補丁。
+
+Gmail網頁客戶端自動地把制表符轉換爲空格。
+
+雖然制表符轉換爲空格問題可以被外部編輯器解決,同時它還會使用回車換行把每行拆分爲78個字符。
+
+另一個問題是Gmail還會把任何不是ASCII的字符的信息改爲base64編碼。它把東西變的像歐洲人的名字。
+
+                                ###
+
diff --git a/Documentation/translations/zh_TW/process/embargoed-hardware-issues.rst b/Documentation/translations/zh_TW/process/embargoed-hardware-issues.rst
new file mode 100644
index 000000000000..d676cef16646
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/embargoed-hardware-issues.rst
@@ -0,0 +1,232 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/embargoed-hardware-issues.rst <embargoed_hardware_issues>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+被限制的硬體問題
+================
+
+範圍
+----
+
+導致安全問題的硬體問題與只影響Linux內核的純軟體錯誤是不同的安全錯誤類別。
+
+必須區別對待諸如熔毀(Meltdown)、Spectre、L1TF等硬體問題,因爲它們通常會影響
+所有作業系統(「OS」),因此需要在不同的OS供應商、發行版、硬體供應商和其他各方
+之間進行協調。對於某些問題,軟體緩解可能依賴於微碼或固件更新,這需要進一步的
+協調。
+
+.. _zh_Contact:
+
+接觸
+----
+
+Linux內核硬體安全小組獨立於普通的Linux內核安全小組。
+
+該小組只負責協調被限制的硬體安全問題。Linux內核中純軟體安全漏洞的報告不由該
+小組處理,報告者將被引導至常規Linux內核安全小組(:ref:`Documentation/admin-guide/
+<securitybugs>`)聯繫。
+
+可以通過電子郵件 <hardware-security@kernel.org> 與小組聯繫。這是一份私密的安全
+官名單,他們將幫助您根據我們的文檔化流程協調問題。
+
+郵件列表是加密的,發送到列表的電子郵件可以通過PGP或S/MIME加密,並且必須使用報告
+者的PGP密鑰或S/MIME證書籤名。該列表的PGP密鑰和S/MIME證書可從
+https://www.kernel.org/.... 獲得。
+
+雖然硬體安全問題通常由受影響的硬體供應商處理,但我們歡迎發現潛在硬體缺陷的研究
+人員或個人與我們聯繫。
+
+硬體安全官
+^^^^^^^^^^
+
+目前的硬體安全官小組:
+
+  - Linus Torvalds(Linux基金會院士)
+  - Greg Kroah Hartman(Linux基金會院士)
+  - Thomas Gleixner(Linux基金會院士)
+
+郵件列表的操作
+^^^^^^^^^^^^^^
+
+處理流程中使用的加密郵件列表託管在Linux Foundation的IT基礎設施上。通過提供這項
+服務,Linux基金會的IT基礎設施安全總監在技術上有能力訪問被限制的信息,但根據他
+的僱傭合同,他必須保密。Linux基金會的IT基礎設施安全總監還負責 kernel.org 基礎
+設施。
+
+Linux基金會目前的IT基礎設施安全總監是 Konstantin Ryabitsev。
+
+保密協議
+--------
+
+Linux內核硬體安全小組不是正式的機構,因此無法簽訂任何保密協議。核心社區意識到
+這些問題的敏感性,並提供了一份諒解備忘錄。
+
+諒解備忘錄
+----------
+
+Linux內核社區深刻理解在不同作業系統供應商、發行商、硬體供應商和其他各方之間
+進行協調時,保持硬體安全問題處於限制狀態的要求。
+
+Linux內核社區在過去已經成功地處理了硬體安全問題,並且有必要的機制允許在限制
+限制下進行符合社區的開發。
+
+Linux內核社區有一個專門的硬體安全小組負責初始聯繫,並監督在限制規則下處理
+此類問題的過程。
+
+硬體安全小組確定開發人員(領域專家),他們將組成特定問題的初始響應小組。最初
+的響應小組可以引入更多的開發人員(領域專家)以最佳的技術方式解決這個問題。
+
+所有相關開發商承諾遵守限制規定,並對收到的信息保密。違反承諾將導致立即從當前
+問題中排除,並從所有相關郵件列表中刪除。此外,硬體安全小組還將把違反者排除在
+未來的問題之外。這一後果的影響在我們社區是一種非常有效的威懾。如果發生違規
+情況,硬體安全小組將立即通知相關方。如果您或任何人發現潛在的違規行爲,請立即
+向硬體安全人員報告。
+
+流程
+^^^^
+
+由於Linux內核開發的全球分布式特性,面對面的會議幾乎不可能解決硬體安全問題。
+由於時區和其他因素,電話會議很難協調,只能在絕對必要時使用。加密電子郵件已被
+證明是解決此類問題的最有效和最安全的通信方法。
+
+開始披露
+""""""""
+
+披露內容首先通過電子郵件聯繫Linux內核硬體安全小組。此初始聯繫人應包含問題的
+描述和任何已知受影響硬體的列表。如果您的組織製造或分發受影響的硬體,我們建議
+您也考慮哪些其他硬體可能會受到影響。
+
+硬體安全小組將提供一個特定於事件的加密郵件列表,用於與報告者進行初步討論、
+進一步披露和協調。
+
+硬體安全小組將向披露方提供一份開發人員(領域專家)名單,在與開發人員確認他們
+將遵守本諒解備忘錄和文件化流程後,應首先告知開發人員有關該問題的信息。這些開發
+人員組成初始響應小組,並在初始接觸後負責處理問題。硬體安全小組支持響應小組,
+但不一定參與緩解開發過程。
+
+雖然個別開發人員可能通過其僱主受到保密協議的保護,但他們不能以Linux內核開發
+人員的身份簽訂個別保密協議。但是,他們將同意遵守這一書面程序和諒解備忘錄。
+
+披露方應提供已經或應該被告知該問題的所有其他實體的聯繫人名單。這有幾個目的:
+
+  - 披露的實體列表允許跨行業通信,例如其他作業系統供應商、硬體供應商等。
+
+  - 可聯繫已披露的實體,指定應參與緩解措施開發的專家。
+
+  - 如果需要處理某一問題的專家受僱於某一上市實體或某一上市實體的成員,則響應
+    小組可要求該實體披露該專家。這確保專家也是實體反應小組的一部分。
+
+披露
+""""
+
+披露方通過特定的加密郵件列表向初始響應小組提供詳細信息。
+
+根據我們的經驗,這些問題的技術文檔通常是一個足夠的起點,最好通過電子郵件進行
+進一步的技術澄清。
+
+緩解開發
+""""""""
+
+初始響應小組設置加密郵件列表,或在適當的情況下重新修改現有郵件列表。
+
+使用郵件列表接近於正常的Linux開發過程,並且在過去已經成功地用於爲各種硬體安全
+問題開發緩解措施。
+
+郵件列表的操作方式與正常的Linux開發相同。發布、討論和審查修補程序,如果同意,
+則應用於非公共git存儲庫,參與開發人員只能通過安全連接訪問該存儲庫。存儲庫包含
+針對主線內核的主開發分支,並根據需要爲穩定的內核版本提供向後移植分支。
+
+最初的響應小組將根據需要從Linux內核開發人員社區中確定更多的專家。引進專家可以
+在開發過程中的任何時候發生,需要及時處理。
+
+如果專家受僱於披露方提供的披露清單上的實體或其成員,則相關實體將要求其參與。
+
+否則,披露方將被告知專家參與的情況。諒解備忘錄涵蓋了專家,要求披露方確認參與。
+如果披露方有令人信服的理由提出異議,則必須在五個工作日內提出異議,並立即與事件
+小組解決。如果披露方在五個工作日內未作出回應,則視爲默許。
+
+在確認或解決異議後,專家由事件小組披露,並進入開發過程。
+
+協調發布
+""""""""
+
+有關各方將協商限制結束的日期和時間。此時,準備好的緩解措施集成到相關的內核樹中
+並發布。
+
+雖然我們理解硬體安全問題需要協調限制時間,但限制時間應限制在所有有關各方制定、
+測試和準備緩解措施所需的最短時間內。人爲地延長限制時間以滿足會議討論日期或其他
+非技術原因,會給相關的開發人員和響應小組帶來了更多的工作和負擔,因爲補丁需要
+保持最新,以便跟蹤正在進行的上游內核開發,這可能會造成衝突的更改。
+
+CVE分配
+"""""""
+
+硬體安全小組和初始響應小組都不分配CVE,開發過程也不需要CVE。如果CVE是由披露方
+提供的,則可用於文檔中。
+
+流程專使
+--------
+
+爲了協助這一進程,我們在各組織設立了專使,他們可以回答有關報告流程和進一步處理
+的問題或提供指導。專使不參與特定問題的披露,除非響應小組或相關披露方提出要求。
+現任專使名單:
+
+  ============= ========================================================
+  ARM
+  AMD		Tom Lendacky <tom.lendacky@amd.com>
+  IBM
+  Intel		Tony Luck <tony.luck@intel.com>
+  Qualcomm	Trilok Soni <tsoni@codeaurora.org>
+
+  Microsoft	Sasha Levin <sashal@kernel.org>
+  VMware
+  Xen		Andrew Cooper <andrew.cooper3@citrix.com>
+
+  Canonical	John Johansen <john.johansen@canonical.com>
+  Debian	Ben Hutchings <ben@decadent.org.uk>
+  Oracle	Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
+  Red Hat	Josh Poimboeuf <jpoimboe@redhat.com>
+  SUSE		Jiri Kosina <jkosina@suse.cz>
+
+  Amazon
+  Google	Kees Cook <keescook@chromium.org>
+  ============= ========================================================
+
+如果要將您的組織添加到專使名單中,請與硬體安全小組聯繫。被提名的專使必須完全
+理解和支持我們的過程,並且在Linux內核社區中很容易聯繫。
+
+加密郵件列表
+------------
+
+我們使用加密郵件列表進行通信。這些列表的工作原理是,發送到列表的電子郵件使用
+列表的PGP密鑰或列表的/MIME證書進行加密。郵件列表軟體對電子郵件進行解密,並
+使用訂閱者的PGP密鑰或S/MIME證書爲每個訂閱者分別對其進行重新加密。有關郵件列表
+軟體和用於確保列表安全和數據保護的設置的詳細信息,請訪問:
+https://www.kernel.org/....
+
+關鍵點
+^^^^^^
+
+初次接觸見 :ref:`zh_Contact`. 對於特定於事件的郵件列表,密鑰和S/MIME證書通過
+特定列表發送的電子郵件傳遞給訂閱者。
+
+訂閱事件特定列表
+^^^^^^^^^^^^^^^^
+
+訂閱由響應小組處理。希望參與通信的披露方將潛在訂戶的列表發送給響應組,以便
+響應組可以驗證訂閱請求。
+
+每個訂戶都需要通過電子郵件向響應小組發送訂閱請求。電子郵件必須使用訂閱伺服器
+的PGP密鑰或S/MIME證書籤名。如果使用PGP密鑰,則必須從公鑰伺服器獲得該密鑰,
+並且理想情況下該密鑰連接到Linux內核的PGP信任網。另請參見:
+https://www.kernel.org/signature.html.
+
+響應小組驗證訂閱者,並將訂閱者添加到列表中。訂閱後,訂閱者將收到來自郵件列表
+的電子郵件,該郵件列表使用列表的PGP密鑰或列表的/MIME證書籤名。訂閱者的電子郵件
+客戶端可以從簽名中提取PGP密鑰或S/MIME證書,以便訂閱者可以向列表發送加密電子
+郵件。
+
diff --git a/Documentation/translations/zh_TW/process/howto.rst b/Documentation/translations/zh_TW/process/howto.rst
new file mode 100644
index 000000000000..2043691b92e3
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/howto.rst
@@ -0,0 +1,500 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _tw_process_howto:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/howto.rst <process_howto>`
+
+譯者::
+
+    英文版維護者: Greg Kroah-Hartman <greg@kroah.com>
+    中文版維護者: 李陽  Li Yang <leoyang.li@nxp.com>
+    中文版翻譯者: 李陽  Li Yang <leoyang.li@nxp.com>
+                   時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+    中文版校譯者:
+                   鍾宇  TripleX Chung <xxx.phy@gmail.com>
+                   陳琦  Maggie Chen <chenqi@beyondsoft.com>
+                   王聰  Wang Cong <xiyou.wangcong@gmail.com>
+                   胡皓文 Hu Haowen <src.res@email.cn>
+
+如何參與Linux內核開發
+=====================
+
+這是一篇將如何參與Linux內核開發的相關問題一網打盡的終極祕笈。它將指導你
+成爲一名Linux內核開發者,並且學會如何同Linux內核開發社區合作。它儘可能不
+包括任何關於內核編程的技術細節,但會給你指引一條獲得這些知識的正確途徑。
+
+如果這篇文章中的任何內容不再適用,請給文末列出的文件維護者發送補丁。
+
+
+入門
+----
+
+你想了解如何成爲一名Linux內核開發者?或者老闆吩咐你「給這個設備寫個Linux
+驅動程序」?這篇文章的目的就是教會你達成這些目標的全部訣竅,它將描述你需
+要經過的流程以及給出如何同內核社區合作的一些提示。它還將試圖解釋內核社區
+爲何這樣運作。
+
+Linux內核大部分是由C語言寫成的,一些體系結構相關的代碼用到了彙編語言。要
+參與內核開發,你必須精通C語言。除非你想爲某個架構開發底層代碼,否則你並
+不需要了解(任何體系結構的)彙編語言。下面列舉的書籍雖然不能替代紮實的C
+語言教育和多年的開發經驗,但如果需要的話,做爲參考還是不錯的:
+
+ - "The C Programming Language" by Kernighan and Ritchie [Prentice Hall]
+   《C程序設計語言(第2版·新版)》(徐寶文 李志 譯)[機械工業出版社]
+ - "Practical C Programming" by Steve Oualline [O'Reilly]
+   《實用C語言編程(第三版)》(郭大海 譯)[中國電力出版社]
+ - "C:  A Reference Manual" by Harbison and Steele [Prentice Hall]
+   《C語言參考手冊(原書第5版)》(邱仲潘 等譯)[機械工業出版社]
+
+Linux內核使用GNU C和GNU工具鏈開發。雖然它遵循ISO C89標準,但也用到了一些
+標準中沒有定義的擴展。內核是自給自足的C環境,不依賴於標準C庫的支持,所以
+並不支持C標準中的部分定義。比如long long類型的大數除法和浮點運算就不允許
+使用。有時候確實很難弄清楚內核對工具鏈的要求和它所使用的擴展,不幸的是目
+前還沒有明確的參考資料可以解釋它們。請查閱gcc信息頁(使用「info gcc」命令
+顯示)獲得一些這方面信息。
+
+請記住你是在學習怎麼和已經存在的開發社區打交道。它由一羣形形色色的人組成,
+他們對代碼、風格和過程有著很高的標準。這些標準是在長期實踐中總結出來的,
+適應於地理上分散的大型開發團隊。它們已經被很好得整理成檔,建議你在開發
+之前儘可能多的學習這些標準,而不要期望別人來適應你或者你公司的行爲方式。
+
+
+法律問題
+--------
+
+Linux內核原始碼都是在GPL(通用公共許可證)的保護下發布的。要了解這種許可
+的細節請查看原始碼主目錄下的COPYING文件。Linux內核許可準則和如何使用
+`SPDX <https://spdx.org/>` 標誌符說明在這個文件中
+:ref:`Documentation/translations/zh_TW/process/license-rules.rst <tw_kernel_licensing>`
+如果你對它還有更深入問題請聯繫律師,而不要在Linux內核郵件組上提問。因爲
+郵件組裡的人並不是律師,不要期望他們的話有法律效力。
+
+對於GPL的常見問題和解答,請訪問以下連結:
+	https://www.gnu.org/licenses/gpl-faq.html
+
+
+文檔
+----
+
+Linux內核代碼中包含有大量的文檔。這些文檔對於學習如何與內核社區互動有著
+不可估量的價值。當一個新的功能被加入內核,最好把解釋如何使用這個功能的文
+檔也放進內核。當內核的改動導致面向用戶空間的接口發生變化時,最好將相關信
+息或手冊頁(manpages)的補丁發到mtk.manpages@gmail.com,以向手冊頁(manpages)
+的維護者解釋這些變化。
+
+以下是內核代碼中需要閱讀的文檔:
+  :ref:`Documentation/admin-guide/README.rst <readme>`
+    文件簡要介紹了Linux內核的背景,並且描述了如何配置和編譯內核。內核的
+    新用戶應該從這裡開始。
+
+
+  :ref:`Documentation/process/changes.rst <changes>`
+    文件給出了用來編譯和使用內核所需要的最小軟體包列表。
+
+  :ref:`Documentation/translations/zh_TW/process/coding-style.rst <tw_codingstyle>`
+    描述Linux內核的代碼風格和理由。所有新代碼需要遵守這篇文檔中定義的規
+    范。大多數維護者只會接收符合規定的補丁,很多人也只會幫忙檢查符合風格
+    的代碼。
+
+  :ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+  :ref:`Documentation/process/submitting-drivers.rst <submittingdrivers>`
+
+    這兩份文檔明確描述如何創建和發送補丁,其中包括(但不僅限於):
+       - 郵件內容
+       - 郵件格式
+       - 選擇收件人
+
+    遵守這些規定並不能保證提交成功(因爲所有補丁需要通過嚴格的內容和風格
+    審查),但是忽視他們幾乎就意味著失敗。
+
+    其他關於如何正確地生成補丁的優秀文檔包括:
+    "The Perfect Patch"
+
+        https://www.ozlabs.org/~akpm/stuff/tpp.txt
+
+    "Linux kernel patch submission format"
+
+        https://web.archive.org/web/20180829112450/http://linux.yyz.us/patch-format.html
+
+  :ref:`Documentation/translations/zh_TW/process/stable-api-nonsense.rst <tw_stable_api_nonsense>`
+    論證內核爲什麼特意不包括穩定的內核內部API,也就是說不包括像這樣的特
+    性:
+
+       - 子系統中間層(爲了兼容性?)
+       - 在不同作業系統間易於移植的驅動程序
+       - 減緩(甚至阻止)內核代碼的快速變化
+
+    這篇文檔對於理解Linux的開發哲學至關重要。對於將開發平台從其他操作系
+    統轉移到Linux的人來說也很重要。
+
+  :ref:`Documentation/admin-guide/security-bugs.rst <securitybugs>`
+    如果你認爲自己發現了Linux內核的安全性問題,請根據這篇文檔中的步驟來
+    提醒其他內核開發者並幫助解決這個問題。
+
+  :ref:`Documentation/translations/zh_TW/process/management-style.rst <tw_managementstyle>`
+
+    描述內核維護者的工作方法及其共有特點。這對於剛剛接觸內核開發(或者對
+    它感到好奇)的人來說很重要,因爲它解釋了很多對於內核維護者獨特行爲的
+    普遍誤解與迷惑。
+
+  :ref:`Documentation/process/stable-kernel-rules.rst <stable_kernel_rules>`
+    解釋了穩定版內核發布的規則,以及如何將改動放入這些版本的步驟。
+
+  :ref:`Documentation/process/kernel-docs.rst <kernel_docs>`
+    有助於內核開發的外部文檔列表。如果你在內核自帶的文檔中沒有找到你想找
+    的內容,可以查看這些文檔。
+
+  :ref:`Documentation/process/applying-patches.rst <applying_patches>`
+    關於補丁是什麼以及如何將它打在不同內核開發分支上的好介紹
+
+內核還擁有大量從代碼自動生成或者從 ReStructuredText(ReST) 標記生成的文檔,
+比如這個文檔,它包含內核內部API的全面介紹以及如何妥善處理加鎖的規則。所有
+這些文檔都可以通過運行以下命令從內核代碼中生成爲PDF或HTML文檔::
+
+    make pdfdocs
+    make htmldocs
+
+ReST格式的文檔會生成在 Documentation/output. 目錄中。
+它們也可以用下列命令生成 LaTeX 和 ePub 格式文檔::
+
+    make latexdocs
+    make epubdocs
+
+如何成爲內核開發者
+------------------
+如果你對Linux內核開發一無所知,你應該訪問「Linux內核新手」計劃:
+
+	https://kernelnewbies.org
+
+它擁有一個可以問各種最基本的內核開發問題的郵件列表(在提問之前一定要記得
+查找已往的郵件,確認是否有人已經回答過相同的問題)。它還擁有一個可以獲得
+實時反饋的IRC聊天頻道,以及大量對於學習Linux內核開發相當有幫助的文檔。
+
+網站簡要介紹了原始碼組織結構、子系統劃分以及目前正在進行的項目(包括內核
+中的和單獨維護的)。它還提供了一些基本的幫助信息,比如如何編譯內核和打補
+丁。
+
+如果你想加入內核開發社區並協助完成一些任務,卻找不到從哪裡開始,可以訪問
+「Linux內核房管員」計劃:
+
+	https://kernelnewbies.org/KernelJanitors
+
+這是極佳的起點。它提供一個相對簡單的任務列表,列出內核代碼中需要被重新
+整理或者改正的地方。通過和負責這個計劃的開發者們一同工作,你會學到將補丁
+集成進內核的基本原理。如果還沒有決定下一步要做什麼的話,你還可能會得到方
+向性的指點。
+
+在真正動手修改內核代碼之前,理解要修改的代碼如何運作是必需的。要達到這個
+目的,沒什麼辦法比直接讀代碼更有效了(大多數花招都會有相應的注釋),而且
+一些特製的工具還可以提供幫助。例如,「Linux代碼交叉引用」項目就是一個值得
+特別推薦的幫助工具,它將原始碼顯示在有編目和索引的網頁上。其中一個更新及
+時的內核源碼庫,可以通過以下地址訪問:
+
+        https://elixir.bootlin.com/
+
+
+開發流程
+--------
+
+目前Linux內核開發流程包括幾個「主內核分支」和很多子系統相關的內核分支。這
+些分支包括:
+
+  - Linus 的內核源碼樹
+  - 多個主要版本的穩定版內核樹
+  - 子系統相關的內核樹
+  - linux-next 集成測試樹
+
+
+主線樹
+------
+主線樹是由Linus Torvalds 維護的。你可以在https://kernel.org 網站或者代碼
+庫中下找到它。它的開發遵循以下步驟:
+
+  - 每當一個新版本的內核被發布,爲期兩周的集成窗口將被打開。在這段時間裡
+    維護者可以向Linus提交大段的修改,通常這些修改已經被放到-mm內核中幾個
+    星期了。提交大量修改的首選方式是使用git工具(內核的代碼版本管理工具
+    ,更多的信息可以在 https://git-scm.com/ 獲取),不過使用普通補丁也是
+    可以的。
+  - 兩個星期以後-rc1版本內核發布。之後只有不包含可能影響整個內核穩定性的
+    新功能的補丁才可能被接受。請注意一個全新的驅動程序(或者文件系統)有
+    可能在-rc1後被接受是因爲這樣的修改完全獨立,不會影響其他的代碼,所以
+    沒有造成內核退步的風險。在-rc1以後也可以用git向Linus提交補丁,不過所
+    有的補丁需要同時被發送到相應的公衆郵件列表以徵詢意見。
+  - 當Linus認爲當前的git源碼樹已經達到一個合理健全的狀態足以發布供人測試
+    時,一個新的-rc版本就會被發布。計劃是每周都發布新的-rc版本。
+  - 這個過程一直持續下去直到內核被認爲達到足夠穩定的狀態,持續時間大概是
+    6個星期。
+
+關於內核發布,值得一提的是Andrew Morton在linux-kernel郵件列表中如是說:
+	「沒有人知道新內核何時會被發布,因爲發布是根據已知bug的情況來決定
+	的,而不是根據一個事先制定好的時間表。」
+
+子系統特定樹
+------------
+
+各種內核子系統的維護者——以及許多內核子系統開發人員——在原始碼庫中公開了他們
+當前的開發狀態。這樣,其他人就可以看到內核的不同區域發生了什麼。在開發速度
+很快的領域,可能會要求開發人員將提交的內容建立在這樣的子系統內核樹上,這樣
+就避免了提交與其他已經進行的工作之間的衝突。
+
+這些存儲庫中的大多數都是Git樹,但是也有其他的scm在使用,或者補丁隊列被發布
+爲Quilt系列。這些子系統存儲庫的地址列在MAINTAINERS文件中。其中許多可以在
+https://git.kernel.org/上瀏覽。
+
+在將一個建議的補丁提交到這樣的子系統樹之前,需要對它進行審查,審查主要發生
+在郵件列表上(請參見下面相應的部分)。對於幾個內核子系統,這個審查過程是通
+過工具補丁跟蹤的。Patchwork提供了一個Web界面,顯示補丁發布、對補丁的任何評
+論或修訂,維護人員可以將補丁標記爲正在審查、接受或拒絕。大多數補丁網站都列
+在 https://patchwork.kernel.org/
+
+Linux-next 集成測試樹
+---------------------
+
+在將子系統樹的更新合併到主線樹之前,需要對它們進行集成測試。爲此,存在一個
+特殊的測試存儲庫,其中幾乎每天都會提取所有子系統樹:
+
+        https://git.kernel.org/?p=linux/kernel/git/next/linux-next.git
+
+通過這種方式,Linux-next 對下一個合併階段將進入主線內核的內容給出了一個概要
+展望。非常歡冒險的測試者運行測試Linux-next。
+
+多個主要版本的穩定版內核樹
+-----------------------------------
+由3個數字組成的內核版本號說明此內核是-stable版本。它們包含內核的相對較小且
+至關重要的修補,這些修補針對安全性問題或者嚴重的內核退步。
+
+這種版本的內核適用於那些期望獲得最新的穩定版內核並且不想參與測試開發版或
+者實驗版的用戶。
+
+穩定版內核樹版本由「穩定版」小組(郵件地址<stable@vger.kernel.org>)維護,一般
+隔周發布新版本。
+
+內核源碼中的 :ref:`Documentation/process/stable-kernel-rules.rst <stable_kernel_rules>`
+文件具體描述了可被穩定版內核接受的修改類型以及發布的流程。
+
+
+報告bug
+-------
+
+bugzilla.kernel.org是Linux內核開發者們用來跟蹤內核Bug的網站。我們鼓勵用
+戶在這個工具中報告找到的所有bug。如何使用內核bugzilla的細節請訪問:
+
+	http://test.kernel.org/bugzilla/faq.html
+
+內核源碼主目錄中的:ref:`admin-guide/reporting-bugs.rst <reportingbugs>`
+文件里有一個很好的模板。它指導用戶如何報告可能的內核bug以及需要提供哪些信息
+來幫助內核開發者們找到問題的根源。
+
+
+利用bug報告
+-----------
+
+練習內核開發技能的最好辦法就是修改其他人報告的bug。你不光可以幫助內核變
+得更加穩定,還可以學會如何解決實際問題從而提高自己的技能,並且讓其他開發
+者感受到你的存在。修改bug是贏得其他開發者讚譽的最好辦法,因爲並不是很多
+人都喜歡浪費時間去修改別人報告的bug。
+
+要嘗試修改已知的bug,請訪問 http://bugzilla.kernel.org 網址。
+
+
+郵件列表
+--------
+
+正如上面的文檔所描述,大多數的骨幹內核開發者都加入了Linux Kernel郵件列
+表。如何訂閱和退訂列表的細節可以在這裡找到:
+
+	http://vger.kernel.org/vger-lists.html#linux-kernel
+
+網上很多地方都有這個郵件列表的存檔(archive)。可以使用搜尋引擎來找到這些
+存檔。比如:
+
+	http://dir.gmane.org/gmane.linux.kernel
+
+在發信之前,我們強烈建議你先在存檔中搜索你想要討論的問題。很多已經被詳細
+討論過的問題只在郵件列表的存檔中可以找到。
+
+大多數內核子系統也有自己獨立的郵件列表來協調各自的開發工作。從
+MAINTAINERS文件中可以找到不同話題對應的郵件列表。
+
+很多郵件列表架設在kernel.org伺服器上。這些列表的信息可以在這裡找到:
+
+	http://vger.kernel.org/vger-lists.html
+
+在使用這些郵件列表時,請記住保持良好的行爲習慣。下面的連結提供了與這些列
+表(或任何其它郵件列表)交流的一些簡單規則,雖然內容有點濫竽充數。
+
+	http://www.albion.com/netiquette/
+
+當有很多人回覆你的郵件時,郵件的抄送列表會變得很長。請不要將任何人從抄送
+列表中刪除,除非你有足夠的理由這麼做。也不要只回復到郵件列表。請習慣於同
+一封郵件接收兩次(一封來自發送者一封來自郵件列表),而不要試圖通過添加一
+些奇特的郵件頭來解決這個問題,人們不會喜歡的。
+
+記住保留你所回復內容的上下文和源頭。在你回覆郵件的頂部保留「某某某說到……」
+這幾行。將你的評論加在被引用的段落之間而不要放在郵件的頂部。
+
+如果你在郵件中附帶補丁,請確認它們是可以直接閱讀的純文本(如
+:ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+文檔中所述)。內核開發者們不希望遇到附件或者被壓縮了的補丁。只有這樣才能
+保證他們可以直接評論你的每行代碼。請確保你使用的郵件發送程序不會修改空格
+和制表符。一個防範性的測試方法是先將郵件發送給自己,然後自己嘗試是否可以
+順利地打上收到的補丁。如果測試不成功,請調整或者更換你的郵件發送程序直到
+它正確工作爲止。
+
+總而言之,請尊重其他的郵件列表訂閱者。
+
+
+同內核社區合作
+----------------
+
+內核社區的目標就是提供盡善盡美的內核。所以當你提交補丁期望被接受進內核的
+時候,它的技術價值以及其他方面都將被評審。那麼你可能會得到什麼呢?
+
+  - 批評
+  - 評論
+  - 要求修改
+  - 要求證明修改的必要性
+  - 沉默
+
+要記住,這些是把補丁放進內核的正常情況。你必須學會聽取對補丁的批評和評論,
+從技術層面評估它們,然後要麼重寫你的補丁要麼簡明扼要地論證修改是不必要
+的。如果你發的郵件沒有得到任何回應,請過幾天後再試一次,因爲有時信件會湮
+沒在茫茫信海中。
+
+你不應該做的事情:
+
+  - 期望自己的補丁不受任何質疑就直接被接受
+  - 翻臉
+  - 忽略別人的評論
+  - 沒有按照別人的要求做任何修改就重新提交
+
+在一個努力追尋最好技術方案的社區里,對於一個補丁有多少好處總會有不同的見
+解。你必須要抱著合作的態度,願意改變自己的觀點來適應內核的風格。或者至少
+願意去證明你的想法是有價值的。記住,犯錯誤是允許的,只要你願意朝著正確的
+方案去努力。
+
+如果你的第一個補丁換來的是一堆修改建議,這是很正常的。這並不代表你的補丁
+不會被接受,也不意味著有人和你作對。你只需要改正所有提出的問題然後重新發
+送你的補丁。
+
+內核社區和公司文化的差異
+------------------------
+
+內核社區的工作模式同大多數傳統公司開發隊伍的工作模式並不相同。下面這些例
+子,可以幫助你避免某些可能發生問題:
+用這些話介紹你的修改提案會有好處:
+
+    - 它同時解決了多個問題
+    - 它刪除了2000行代碼
+    - 這是補丁,它已經解釋了我想要說明的
+    - 我在5種不同的體系結構上測試過它……
+    - 這是一系列小補丁用來……
+    - 這個修改提高了普通機器的性能……
+
+應該避免如下的說法:
+
+    - 我們在AIX/ptx/Solaris就是這麼做的,所以這麼做肯定是好的……
+    - 我做這行已經20年了,所以……
+    - 爲了我們公司賺錢考慮必須這麼做
+    - 這是我們的企業產品線所需要的
+    - 這裡是描述我觀點的1000頁設計文檔
+    - 這是一個5000行的補丁用來……
+    - 我重寫了現在亂七八糟的代碼,這就是……
+    - 我被規定了最後期限,所以這個補丁需要立刻被接受
+
+另外一個內核社區與大部分傳統公司的軟體開發隊伍不同的地方是無法面對面地交
+流。使用電子郵件和IRC聊天工具做爲主要溝通工具的一個好處是性別和種族歧視
+將會更少。Linux內核的工作環境更能接受婦女和少數族羣,因爲每個人在別人眼
+里只是一個郵件地址。國際化也幫助了公平的實現,因爲你無法通過姓名來判斷人
+的性別。男人有可能叫李麗,女人也有可能叫王剛。大多數在Linux內核上工作過
+並表達過看法的女性對在linux上工作的經歷都給出了正面的評價。
+
+對於一些不習慣使用英語的人來說,語言可能是一個引起問題的障礙。在郵件列表
+中要正確地表達想法必需良好地掌握語言,所以建議你在發送郵件之前最好檢查一
+下英文寫得是否正確。
+
+
+拆分修改
+--------
+
+Linux內核社區並不喜歡一下接收大段的代碼。修改需要被恰當地介紹、討論並且
+拆分成獨立的小段。這幾乎完全和公司中的習慣背道而馳。你的想法應該在開發最
+開始的階段就讓大家知道,這樣你就可以及時獲得對你正在進行的開發的反饋。這
+樣也會讓社區覺得你是在和他們協作,而不是僅僅把他們當作傾銷新功能的對象。
+無論如何,你不要一次性地向郵件列表發送50封信,你的補丁序列應該永遠用不到
+這麼多。
+
+將補丁拆開的原因如下:
+
+1) 小的補丁更有可能被接受,因爲它們不需要太多的時間和精力去驗證其正確性。
+   一個5行的補丁,可能在維護者看了一眼以後就會被接受。而500行的補丁則
+   需要數個小時來審查其正確性(所需時間隨補丁大小增加大約呈指數級增長)。
+
+   當出了問題的時候,小的補丁也會讓調試變得非常容易。一個一個補丁地回溯
+   將會比仔細剖析一個被打上的大補丁(這個補丁破壞了其他東西)容易得多。
+
+2)不光發送小的補丁很重要,在提交之前重新編排、化簡(或者僅僅重新排列)
+   補丁也是很重要的。
+
+這裡有內核開發者Al Viro打的一個比方:
+	「想像一個老師正在給學生批改數學作業。老師並不希望看到學生爲了得
+	到正確解法所進行的嘗試和產生的錯誤。他希望看到的是最乾淨最優雅的
+	解答。好學生了解這點,絕不會把最終解決之前的中間方案提交上去。」
+
+	內核開發也是這樣。維護者和評審者不希望看到一個人在解決問題時的思
+	考過程。他們只希望看到簡單和優雅的解決方案。
+
+直接給出一流的解決方案,和社區一起協作討論尚未完成的工作,這兩者之間似乎
+很難找到一個平衡點。所以最好儘早開始收集有利於你進行改進的反饋;同時也要
+保證修改分成很多小塊,這樣在整個項目都準備好被包含進內核之前,其中的一部
+分可能會先被接收。
+
+必須了解這樣做是不可接受的:試圖將未完成的工作提交進內核,然後再找時間修
+復。
+
+
+證明修改的必要性
+----------------
+除了將補丁拆成小塊,很重要的一點是讓Linux社區了解他們爲什麼需要這樣修改。
+你必須證明新功能是有人需要的並且是有用的。
+
+
+記錄修改
+--------
+
+當你發送補丁的時候,需要特別留意郵件正文的內容。因爲這裡的信息將會做爲補
+丁的修改記錄(ChangeLog),會被一直保留以備大家查閱。它需要完全地描述補丁,
+包括:
+
+  - 爲什麼需要這個修改
+  - 補丁的總體設計
+  - 實現細節
+  - 測試結果
+
+想了解它具體應該看起來像什麼,請查閱以下文檔中的「ChangeLog」章節:
+  「The Perfect Patch」
+  	 https://www.ozlabs.org/~akpm/stuff/tpp.txt
+
+
+這些事情有時候做起來很難。要在任何方面都做到完美可能需要好幾年時間。這是
+一個持續提高的過程,它需要大量的耐心和決心。只要不放棄,你一定可以做到。
+很多人已經做到了,而他們都曾經和現在的你站在同樣的起點上。
+
+
+感謝
+----
+感謝Paolo Ciarrocchi允許「開發流程」部分基於他所寫的文章
+(http://www.kerneltravel.net/newbie/2.6-development_process),感謝Randy
+Dunlap和Gerrit Huizenga完善了應該說和不該說的列表。感謝Pat Mochel, Hanna
+Linder, Randy Dunlap, Kay Sievers, Vojtech Pavlik, Jan Kara, Josh Boyer,
+Kees Cook, Andrew Morton, Andi Kleen, Vadim Lobanov, Jesper Juhl, Adrian
+Bunk, Keri Harris, Frans Pop, David A. Wheeler, Junio Hamano, Michael
+Kerrisk和Alex Shepard的評審、建議和貢獻。沒有他們的幫助,這篇文檔是不可
+能完成的。
+
+
+
+英文版維護者: Greg Kroah-Hartman <greg@kroah.com>
+
diff --git a/Documentation/translations/zh_TW/process/index.rst b/Documentation/translations/zh_TW/process/index.rst
new file mode 100644
index 000000000000..ec7ad14bfd13
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/index.rst
@@ -0,0 +1,67 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. raw:: latex
+
+	\renewcommand\thesection*
+	\renewcommand\thesubsection*
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/index.rst <process_index>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+.. _tw_process_index:
+
+與Linux 內核社區一起工作
+========================
+
+你想成爲Linux內核開發人員嗎?歡迎之至!在學習許多關於內核的技術知識的同時,
+了解我們社區的工作方式也很重要。閱讀這些文檔可以讓您以更輕鬆的、麻煩更少的
+方式將更改合併到內核。
+
+以下是每位開發人員都應閱讀的基本指南:
+
+.. toctree::
+   :maxdepth: 1
+
+   howto
+   code-of-conduct
+   code-of-conduct-interpretation
+   submitting-patches
+   programming-language
+   coding-style
+   development-process
+   email-clients
+   license-rules
+   kernel-enforcement-statement
+   kernel-driver-statement
+
+其它大多數開發人員感興趣的社區指南:
+
+
+.. toctree::
+   :maxdepth: 1
+
+   submitting-drivers
+   submit-checklist
+   stable-api-nonsense
+   stable-kernel-rules
+   management-style
+   embargoed-hardware-issues
+
+這些是一些總體性技術指南,由於不大好分類而放在這裡:
+
+.. toctree::
+   :maxdepth: 1
+
+   magic-number
+   volatile-considered-harmful
+
+.. only::  subproject and html
+
+   目錄
+   ====
+
+   * :ref:`genindex`
+
diff --git a/Documentation/translations/zh_TW/process/kernel-driver-statement.rst b/Documentation/translations/zh_TW/process/kernel-driver-statement.rst
new file mode 100644
index 000000000000..8f225379b12c
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/kernel-driver-statement.rst
@@ -0,0 +1,203 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _zh_process_statement_driver:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/kernel-driver-statement.rst <process_statement_driver>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+內核驅動聲明
+------------
+
+關於Linux內核模塊的立場聲明
+===========================
+
+我們,以下署名的Linux內核開發人員,認爲任何封閉源Linux內核模塊或驅動程序都是
+有害的和不可取的。我們已經一再發現它們對Linux用戶,企業和更大的Linux生態系統
+有害。這樣的模塊否定了Linux開發模型的開放性,穩定性,靈活性和可維護性,並使
+他們的用戶無法使用Linux社區的專業知識。提供閉源內核模塊的供應商迫使其客戶
+放棄Linux的主要優勢或選擇新的供應商。因此,爲了充分利用開源所提供的成本節省和
+共享支持優勢,我們敦促供應商採取措施,以開源內核代碼在Linux上爲其客戶提供支持。
+
+我們只爲自己說話,而不是我們今天可能會爲之工作,過去或將來會爲之工作的任何公司。
+
+ - Dave Airlie
+ - Nick Andrew
+ - Jens Axboe
+ - Ralf Baechle
+ - Felipe Balbi
+ - Ohad Ben-Cohen
+ - Muli Ben-Yehuda
+ - Jiri Benc
+ - Arnd Bergmann
+ - Thomas Bogendoerfer
+ - Vitaly Bordug
+ - James Bottomley
+ - Josh Boyer
+ - Neil Brown
+ - Mark Brown
+ - David Brownell
+ - Michael Buesch
+ - Franck Bui-Huu
+ - Adrian Bunk
+ - François Cami
+ - Ralph Campbell
+ - Luiz Fernando N. Capitulino
+ - Mauro Carvalho Chehab
+ - Denis Cheng
+ - Jonathan Corbet
+ - Glauber Costa
+ - Alan Cox
+ - Magnus Damm
+ - Ahmed S. Darwish
+ - Robert P. J. Day
+ - Hans de Goede
+ - Arnaldo Carvalho de Melo
+ - Helge Deller
+ - Jean Delvare
+ - Mathieu Desnoyers
+ - Sven-Thorsten Dietrich
+ - Alexey Dobriyan
+ - Daniel Drake
+ - Alex Dubov
+ - Randy Dunlap
+ - Michael Ellerman
+ - Pekka Enberg
+ - Jan Engelhardt
+ - Mark Fasheh
+ - J. Bruce Fields
+ - Larry Finger
+ - Jeremy Fitzhardinge
+ - Mike Frysinger
+ - Kumar Gala
+ - Robin Getz
+ - Liam Girdwood
+ - Jan-Benedict Glaw
+ - Thomas Gleixner
+ - Brice Goglin
+ - Cyrill Gorcunov
+ - Andy Gospodarek
+ - Thomas Graf
+ - Krzysztof Halasa
+ - Harvey Harrison
+ - Stephen Hemminger
+ - Michael Hennerich
+ - Tejun Heo
+ - Benjamin Herrenschmidt
+ - Kristian Høgsberg
+ - Henrique de Moraes Holschuh
+ - Marcel Holtmann
+ - Mike Isely
+ - Takashi Iwai
+ - Olof Johansson
+ - Dave Jones
+ - Jesper Juhl
+ - Matthias Kaehlcke
+ - Kenji Kaneshige
+ - Jan Kara
+ - Jeremy Kerr
+ - Russell King
+ - Olaf Kirch
+ - Roel Kluin
+ - Hans-Jürgen Koch
+ - Auke Kok
+ - Peter Korsgaard
+ - Jiri Kosina
+ - Aaro Koskinen
+ - Mariusz Kozlowski
+ - Greg Kroah-Hartman
+ - Michael Krufky
+ - Aneesh Kumar
+ - Clemens Ladisch
+ - Christoph Lameter
+ - Gunnar Larisch
+ - Anders Larsen
+ - Grant Likely
+ - John W. Linville
+ - Yinghai Lu
+ - Tony Luck
+ - Pavel Machek
+ - Matt Mackall
+ - Paul Mackerras
+ - Roland McGrath
+ - Patrick McHardy
+ - Kyle McMartin
+ - Paul Menage
+ - Thierry Merle
+ - Eric Miao
+ - Akinobu Mita
+ - Ingo Molnar
+ - James Morris
+ - Andrew Morton
+ - Paul Mundt
+ - Oleg Nesterov
+ - Luca Olivetti
+ - S.Çağlar Onur
+ - Pierre Ossman
+ - Keith Owens
+ - Venkatesh Pallipadi
+ - Nick Piggin
+ - Nicolas Pitre
+ - Evgeniy Polyakov
+ - Richard Purdie
+ - Mike Rapoport
+ - Sam Ravnborg
+ - Gerrit Renker
+ - Stefan Richter
+ - David Rientjes
+ - Luis R. Rodriguez
+ - Stefan Roese
+ - Francois Romieu
+ - Rami Rosen
+ - Stephen Rothwell
+ - Maciej W. Rozycki
+ - Mark Salyzyn
+ - Yoshinori Sato
+ - Deepak Saxena
+ - Holger Schurig
+ - Amit Shah
+ - Yoshihiro Shimoda
+ - Sergei Shtylyov
+ - Kay Sievers
+ - Sebastian Siewior
+ - Rik Snel
+ - Jes Sorensen
+ - Alexey Starikovskiy
+ - Alan Stern
+ - Timur Tabi
+ - Hirokazu Takata
+ - Eliezer Tamir
+ - Eugene Teo
+ - Doug Thompson
+ - FUJITA Tomonori
+ - Dmitry Torokhov
+ - Marcelo Tosatti
+ - Steven Toth
+ - Theodore Tso
+ - Matthias Urlichs
+ - Geert Uytterhoeven
+ - Arjan van de Ven
+ - Ivo van Doorn
+ - Rik van Riel
+ - Wim Van Sebroeck
+ - Hans Verkuil
+ - Horst H. von Brand
+ - Dmitri Vorobiev
+ - Anton Vorontsov
+ - Daniel Walker
+ - Johannes Weiner
+ - Harald Welte
+ - Matthew Wilcox
+ - Dan J. Williams
+ - Darrick J. Wong
+ - David Woodhouse
+ - Chris Wright
+ - Bryan Wu
+ - Rafael J. Wysocki
+ - Herbert Xu
+ - Vlad Yasevich
+ - Peter Zijlstra
+ - Bartlomiej Zolnierkiewicz
+
diff --git a/Documentation/translations/zh_TW/process/kernel-enforcement-statement.rst b/Documentation/translations/zh_TW/process/kernel-enforcement-statement.rst
new file mode 100644
index 000000000000..99e21d22800d
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/kernel-enforcement-statement.rst
@@ -0,0 +1,155 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _tw_process_statement_kernel:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/kernel-enforcement-statement.rst <process_statement_kernel>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+Linux 內核執行聲明
+------------------
+
+作爲Linux內核的開發人員,我們對如何使用我們的軟體以及如何實施軟體許可證有著
+濃厚的興趣。遵守GPL-2.0的互惠共享義務對我們軟體和社區的長期可持續性至關重要。
+
+雖然有權強制執行對我們社區的貢獻中的單獨版權權益,但我們有共同的利益,即確保
+個人強制執行行動的方式有利於我們的社區,不會對我們軟體生態系統的健康和增長
+產生意外的負面影響。爲了阻止無益的執法行動,我們同意代表我們自己和我們版權
+利益的任何繼承人對Linux內核用戶作出以下符合我們開發社區最大利益的承諾:
+
+    儘管有GPL-2.0的終止條款,我們同意,採用以下GPL-3.0條款作爲我們許可證下的
+    附加許可,作爲任何對許可證下權利的非防禦性主張,這符合我們開發社區的最佳
+    利益。
+
+        但是,如果您停止所有違反本許可證的行爲,則您從特定版權持有人處獲得的
+        許可證將被恢復:(a)暫時恢復,除非版權持有人明確並最終終止您的許可證;
+        以及(b)永久恢復, 如果版權持有人未能在你終止違反後60天內以合理方式
+        通知您違反本許可證的行爲,則永久恢復您的許可證。
+
+        此外,如果版權所有者以某種合理的方式通知您違反了本許可,這是您第一次
+        從該版權所有者處收到違反本許可的通知(對於任何作品),並且您在收到通知
+        後的30天內糾正違規行爲。則您從特定版權所有者處獲得的許可將永久恢復.
+
+我們提供這些保證的目的是鼓勵更多地使用該軟體。我們希望公司和個人使用、修改和
+分發此軟體。我們希望以公開和透明的方式與用戶合作,以消除我們對法規遵從性或強制
+執行的任何不確定性,這些不確定性可能會限制我們軟體的採用。我們將法律行動視爲
+最後手段,只有在其他社區努力未能解決這一問題時才採取行動。
+
+最後,一旦一個不合規問題得到解決,我們希望用戶會感到歡迎,加入我們爲之努力的
+這個項目。共同努力,我們會更強大。
+
+除了下面提到的以外,我們只爲自己說話,而不是爲今天、過去或將來可能爲之工作的
+任何公司說話。
+
+  - Laura Abbott
+  - Bjorn Andersson (Linaro)
+  - Andrea Arcangeli
+  - Neil Armstrong
+  - Jens Axboe
+  - Pablo Neira Ayuso
+  - Khalid Aziz
+  - Ralf Baechle
+  - Felipe Balbi
+  - Arnd Bergmann
+  - Ard Biesheuvel
+  - Tim Bird
+  - Paolo Bonzini
+  - Christian Borntraeger
+  - Mark Brown (Linaro)
+  - Paul Burton
+  - Javier Martinez Canillas
+  - Rob Clark
+  - Kees Cook (Google)
+  - Jonathan Corbet
+  - Dennis Dalessandro
+  - Vivien Didelot (Savoir-faire Linux)
+  - Hans de Goede
+  - Mel Gorman (SUSE)
+  - Sven Eckelmann
+  - Alex Elder (Linaro)
+  - Fabio Estevam
+  - Larry Finger
+  - Bhumika Goyal
+  - Andy Gross
+  - Juergen Gross
+  - Shawn Guo
+  - Ulf Hansson
+  - Stephen Hemminger (Microsoft)
+  - Tejun Heo
+  - Rob Herring
+  - Masami Hiramatsu
+  - Michal Hocko
+  - Simon Horman
+  - Johan Hovold (Hovold Consulting AB)
+  - Christophe JAILLET
+  - Olof Johansson
+  - Lee Jones (Linaro)
+  - Heiner Kallweit
+  - Srinivas Kandagatla
+  - Jan Kara
+  - Shuah Khan (Samsung)
+  - David Kershner
+  - Jaegeuk Kim
+  - Namhyung Kim
+  - Colin Ian King
+  - Jeff Kirsher
+  - Greg Kroah-Hartman (Linux Foundation)
+  - Christian König
+  - Vinod Koul
+  - Krzysztof Kozlowski
+  - Viresh Kumar
+  - Aneesh Kumar K.V
+  - Julia Lawall
+  - Doug Ledford
+  - Chuck Lever (Oracle)
+  - Daniel Lezcano
+  - Shaohua Li
+  - Xin Long
+  - Tony Luck
+  - Catalin Marinas (Arm Ltd)
+  - Mike Marshall
+  - Chris Mason
+  - Paul E. McKenney
+  - Arnaldo Carvalho de Melo
+  - David S. Miller
+  - Ingo Molnar
+  - Kuninori Morimoto
+  - Trond Myklebust
+  - Martin K. Petersen (Oracle)
+  - Borislav Petkov
+  - Jiri Pirko
+  - Josh Poimboeuf
+  - Sebastian Reichel (Collabora)
+  - Guenter Roeck
+  - Joerg Roedel
+  - Leon Romanovsky
+  - Steven Rostedt (VMware)
+  - Frank Rowand
+  - Ivan Safonov
+  - Anna Schumaker
+  - Jes Sorensen
+  - K.Y. Srinivasan
+  - David Sterba (SUSE)
+  - Heiko Stuebner
+  - Jiri Kosina (SUSE)
+  - Willy Tarreau
+  - Dmitry Torokhov
+  - Linus Torvalds
+  - Thierry Reding
+  - Rik van Riel
+  - Luis R. Rodriguez
+  - Geert Uytterhoeven (Glider bvba)
+  - Eduardo Valentin (Amazon.com)
+  - Daniel Vetter
+  - Linus Walleij
+  - Richard Weinberger
+  - Dan Williams
+  - Rafael J. Wysocki
+  - Arvind Yadav
+  - Masahiro Yamada
+  - Wei Yongjun
+  - Lv Zheng
+  - Marc Zyngier (Arm Ltd)
+
diff --git a/Documentation/translations/zh_TW/process/license-rules.rst b/Documentation/translations/zh_TW/process/license-rules.rst
new file mode 100644
index 000000000000..ad2b80f97123
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/license-rules.rst
@@ -0,0 +1,374 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/license-rules.rst <kernel_licensing>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+.. _tw_kernel_licensing:
+
+Linux內核許可規則
+=================
+
+Linux內核根據LICENSES/preferred/GPL-2.0中提供的GNU通用公共許可證版本2
+(GPL-2.0)的條款提供,並在LICENSES/exceptions/Linux-syscall-note中顯式
+描述了例外的系統調用,如COPYING文件中所述。
+
+此文檔文件提供了如何對每個源文件進行注釋以使其許可證清晰明確的說明。
+它不會取代內核的許可證。
+
+內核原始碼作爲一個整體適用於COPYING文件中描述的許可證,但是單個源文件可以
+具有不同的與GPL-20兼容的許可證::
+
+    GPL-1.0+ : GNU通用公共許可證v1.0或更高版本
+    GPL-2.0+ : GNU通用公共許可證v2.0或更高版本
+    LGPL-2.0 : 僅限GNU庫通用公共許可證v2
+    LGPL-2.0+: GNU 庫通用公共許可證v2或更高版本
+    LGPL-2.1 : 僅限GNU寬通用公共許可證v2.1
+    LGPL-2.1+: GNU寬通用公共許可證v2.1或更高版本
+
+除此之外,個人文件可以在雙重許可下提供,例如一個兼容的GPL變體,或者BSD,
+MIT等許可。
+
+用戶空間API(UAPI)頭文件描述了用戶空間程序與內核的接口,這是一種特殊情況。
+根據內核COPYING文件中的注釋,syscall接口是一個明確的邊界,它不會將GPL要求
+擴展到任何使用它與內核通信的軟體。由於UAPI頭文件必須包含在創建在Linux內核
+上運行的可執行文件的任何源文件中,因此此例外必須記錄在特別的許可證表述中。
+
+表達源文件許可證的常用方法是將匹配的樣板文本添加到文件的頂部注釋中。由於
+格式,拼寫錯誤等,這些「樣板」很難通過那些在上下文中使用的驗證許可證合規性
+的工具。
+
+樣板文本的替代方法是在每個源文件中使用軟體包數據交換(SPDX)許可證標識符。
+SPDX許可證標識符是機器可解析的,並且是用於提供文件內容的許可證的精確縮寫。
+SPDX許可證標識符由Linux 基金會的SPDX 工作組管理,並得到了整個行業,工具
+供應商和法律團隊的合作夥伴的一致同意。有關詳細信息,請參閱
+https://spdx.org/
+
+Linux內核需要所有源文件中的精確SPDX標識符。內核中使用的有效標識符在
+`許可標識符`_ 一節中進行了解釋,並且已可以在
+https://spdx.org/licenses/ 上的官方SPDX許可證列表中檢索,並附帶許可證
+文本。
+
+許可標識符語法
+--------------
+
+1.安置:
+
+   內核文件中的SPDX許可證標識符應添加到可包含注釋的文件中的第一行。對於大多
+   數文件,這是第一行,除了那些在第一行中需要'#!PATH_TO_INTERPRETER'的腳本。
+   對於這些腳本,SPDX標識符進入第二行。
+
+|
+
+2. 風格:
+
+   SPDX許可證標識符以注釋的形式添加。注釋樣式取決於文件類型::
+
+      C source:	// SPDX-License-Identifier: <SPDX License Expression>
+      C header:	/* SPDX-License-Identifier: <SPDX License Expression> */
+      ASM:	/* SPDX-License-Identifier: <SPDX License Expression> */
+      scripts:	# SPDX-License-Identifier: <SPDX License Expression>
+      .rst:	.. SPDX-License-Identifier: <SPDX License Expression>
+      .dts{i}:	// SPDX-License-Identifier: <SPDX License Expression>
+
+   如果特定工具無法處理標準注釋樣式,則應使用工具接受的相應注釋機制。這是在
+   C 頭文件中使用「/\*\*/」樣式注釋的原因。過去在使用生成的.lds文件中觀察到
+   構建被破壞,其中'ld'無法解析C++注釋。現在已經解決了這個問題,但仍然有較
+   舊的彙編程序工具無法處理C++樣式的注釋。
+
+|
+
+3. 句法:
+
+   <SPDX許可證表達式>是SPDX許可證列表中的SPDX短格式許可證標識符,或者在許可
+   證例外適用時由「WITH」分隔的兩個SPDX短格式許可證標識符的組合。當應用多個許
+   可證時,表達式由分隔子表達式的關鍵字「AND」,「OR」組成,並由「(」,「)」包圍。
+
+   帶有「或更高」選項的[L]GPL等許可證的許可證標識符通過使用「+」來表示「或更高」
+   選項來構建。::
+
+      // SPDX-License-Identifier: GPL-2.0+
+      // SPDX-License-Identifier: LGPL-2.1+
+
+   當需要修正的許可證時,應使用WITH。 例如,linux內核UAPI文件使用表達式::
+
+      // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
+      // SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note
+
+   其它在內核中使用WITH例外的事例如下::
+
+      // SPDX-License-Identifier: GPL-2.0 WITH mif-exception
+      // SPDX-License-Identifier: GPL-2.0+ WITH GCC-exception-2.0
+
+   例外只能與特定的許可證標識符一起使用。有效的許可證標識符列在異常文本文件
+   的標記中。有關詳細信息,請參閱 `許可標識符`_ 一章中的 `例外`_ 。
+
+   如果文件是雙重許可且只選擇一個許可證,則應使用OR。例如,一些dtsi文件在雙
+   許可下可用::
+
+      // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+
+   內核中雙許可文件中許可表達式的示例::
+
+      // SPDX-License-Identifier: GPL-2.0 OR MIT
+      // SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+      // SPDX-License-Identifier: GPL-2.0 OR Apache-2.0
+      // SPDX-License-Identifier: GPL-2.0 OR MPL-1.1
+      // SPDX-License-Identifier: (GPL-2.0 WITH Linux-syscall-note) OR MIT
+      // SPDX-License-Identifier: GPL-1.0+ OR BSD-3-Clause OR OpenSSL
+
+   如果文件具有多個許可證,其條款全部適用於使用該文件,則應使用AND。例如,
+   如果代碼是從另一個項目繼承的,並且已經授予了將其放入內核的權限,但原始
+   許可條款需要保持有效::
+
+      // SPDX-License-Identifier: (GPL-2.0 WITH Linux-syscall-note) AND MIT
+
+   另一個需要遵守兩套許可條款的例子是::
+
+      // SPDX-License-Identifier: GPL-1.0+ AND LGPL-2.1+
+
+許可標識符
+----------
+
+當前使用的許可證以及添加到內核的代碼許可證可以分解爲:
+
+1. _`優先許可`:
+
+   應儘可能使用這些許可證,因爲它們已知完全兼容並廣泛使用。這些許可證在內核
+   目錄::
+
+      LICENSES/preferred/
+
+   此目錄中的文件包含完整的許可證文本和 `元標記`_ 。文件名與SPDX許可證標識
+   符相同,後者應用於源文件中的許可證。
+
+   例如::
+
+      LICENSES/preferred/GPL-2.0
+
+   包含GPLv2許可證文本和所需的元標籤::
+
+      LICENSES/preferred/MIT
+
+   包含MIT許可證文本和所需的元標記
+
+   _`元標記`:
+
+   許可證文件中必須包含以下元標記:
+
+   - Valid-License-Identifier:
+
+     一行或多行, 聲明那些許可標識符在項目內有效, 以引用此特定許可的文本。通
+     常這是一個有效的標識符,但是例如對於帶有'或更高'選項的許可證,兩個標識
+     符都有效。
+
+   - SPDX-URL:
+
+     SPDX頁面的URL,其中包含與許可證相關的其他信息.
+
+   - Usage-Guidance:
+
+     使用建議的自由格式文本。該文本必須包含SPDX許可證標識符的正確示例,因爲
+     它們應根據 `許可標識符語法`_ 指南放入源文件中。
+
+   - License-Text:
+
+     此標記之後的所有文本都被視爲原始許可文本
+
+   文件格式示例::
+
+      Valid-License-Identifier: GPL-2.0
+      Valid-License-Identifier: GPL-2.0+
+      SPDX-URL: https://spdx.org/licenses/GPL-2.0.html
+      Usage-Guide:
+        To use this license in source code, put one of the following SPDX
+	tag/value pairs into a comment according to the placement
+	guidelines in the licensing rules documentation.
+	For 'GNU General Public License (GPL) version 2 only' use:
+	  SPDX-License-Identifier: GPL-2.0
+	For 'GNU General Public License (GPL) version 2 or any later version' use:
+	  SPDX-License-Identifier: GPL-2.0+
+      License-Text:
+        Full license text
+
+   ::
+
+      SPDX-License-Identifier: MIT
+      SPDX-URL: https://spdx.org/licenses/MIT.html
+      Usage-Guide:
+	To use this license in source code, put the following SPDX
+	tag/value pair into a comment according to the placement
+	guidelines in the licensing rules documentation.
+	  SPDX-License-Identifier: MIT
+      License-Text:
+        Full license text
+
+|
+
+2. 不推薦的許可證:
+
+   這些許可證只應用於現有代碼或從其他項目導入代碼。這些許可證在內核目錄::
+
+      LICENSES/other/
+
+   此目錄中的文件包含完整的許可證文本和 `元標記`_ 。文件名與SPDX許可證標識
+   符相同,後者應用於源文件中的許可證。
+
+   例如::
+
+      LICENSES/other/ISC
+
+   包含國際系統聯合許可文本和所需的元標籤::
+
+      LICENSES/other/ZLib
+
+   包含ZLIB許可文本和所需的元標籤.
+
+   元標籤:
+
+   「其他」許可證的元標籤要求與 `優先許可`_ 的要求相同。
+
+   文件格式示例::
+
+      Valid-License-Identifier: ISC
+      SPDX-URL: https://spdx.org/licenses/ISC.html
+      Usage-Guide:
+        Usage of this license in the kernel for new code is discouraged
+	and it should solely be used for importing code from an already
+	existing project.
+        To use this license in source code, put the following SPDX
+	tag/value pair into a comment according to the placement
+	guidelines in the licensing rules documentation.
+	  SPDX-License-Identifier: ISC
+      License-Text:
+        Full license text
+
+|
+
+3. _`例外`:
+
+   某些許可證可以修改,並允許原始許可證不具有的某些例外權利。這些例外在
+   內核目錄::
+
+      LICENSES/exceptions/
+
+   此目錄中的文件包含完整的例外文本和所需的 `例外元標記`_ 。
+
+   例如::
+
+      LICENSES/exceptions/Linux-syscall-note
+
+   包含Linux內核的COPYING文件中記錄的Linux系統調用例外,該文件用於UAPI
+   頭文件。例如::
+
+      LICENSES/exceptions/GCC-exception-2.0
+
+   包含GCC'連結例外',它允許獨立於其許可證的任何二進位文件與標記有此例外的
+   文件的編譯版本連結。這是從GPL不兼容原始碼創建可運行的可執行文件所必需的。
+
+   _`例外元標記`:
+
+   以下元標記必須在例外文件中可用:
+
+   - SPDX-Exception-Identifier:
+
+     一個可與SPDX許可證標識符一起使用的例外標識符。
+
+   - SPDX-URL:
+
+     SPDX頁面的URL,其中包含與例外相關的其他信息。
+
+   - SPDX-Licenses:
+
+     以逗號分隔的例外可用的SPDX許可證標識符列表。
+
+   - Usage-Guidance:
+
+     使用建議的自由格式文本。必須在文本後面加上SPDX許可證標識符的正確示例,
+     因爲它們應根據 `許可標識符語法`_ 指南放入源文件中。
+
+   - Exception-Text:
+
+     此標記之後的所有文本都被視爲原始異常文本
+
+   文件格式示例::
+
+      SPDX-Exception-Identifier: Linux-syscall-note
+      SPDX-URL: https://spdx.org/licenses/Linux-syscall-note.html
+      SPDX-Licenses: GPL-2.0, GPL-2.0+, GPL-1.0+, LGPL-2.0, LGPL-2.0+, LGPL-2.1, LGPL-2.1+
+      Usage-Guidance:
+        This exception is used together with one of the above SPDX-Licenses
+	to mark user-space API (uapi) header files so they can be included
+	into non GPL compliant user-space application code.
+        To use this exception add it with the keyword WITH to one of the
+	identifiers in the SPDX-Licenses tag:
+	  SPDX-License-Identifier: <SPDX-License> WITH Linux-syscall-note
+      Exception-Text:
+        Full exception text
+
+   ::
+
+      SPDX-Exception-Identifier: GCC-exception-2.0
+      SPDX-URL: https://spdx.org/licenses/GCC-exception-2.0.html
+      SPDX-Licenses: GPL-2.0, GPL-2.0+
+      Usage-Guidance:
+        The "GCC Runtime Library exception 2.0" is used together with one
+	of the above SPDX-Licenses for code imported from the GCC runtime
+	library.
+        To use this exception add it with the keyword WITH to one of the
+	identifiers in the SPDX-Licenses tag:
+	  SPDX-License-Identifier: <SPDX-License> WITH GCC-exception-2.0
+      Exception-Text:
+        Full exception text
+
+
+所有SPDX許可證標識符和例外都必須在LICENSES子目錄中具有相應的文件。這是允許
+工具驗證(例如checkpatch.pl)以及準備好從源讀取和提取許可證所必需的, 這是
+各種FOSS組織推薦的,例如 `FSFE REUSE initiative <https://reuse.software/>`_.
+
+_`模塊許可`
+-----------------
+
+   可加載內核模塊還需要MODULE_LICENSE()標記。此標記既不替代正確的原始碼
+   許可證信息(SPDX-License-Identifier),也不以任何方式表示或確定提供模塊
+   原始碼的確切許可證。
+
+   此標記的唯一目的是提供足夠的信息,該模塊是否是自由軟體或者是內核模塊加
+   載器和用戶空間工具的專有模塊。
+
+   MODULE_LICENSE()的有效許可證字符串是:
+
+    ============================= =============================================
+    "GPL"			  模塊是根據GPL版本2許可的。這並不表示僅限於
+                                  GPL-2.0或GPL-2.0或更高版本之間的任何區別。
+                                  最正確許可證信息只能通過相應源文件中的許可證
+                                  信息來確定
+
+    "GPL v2"			  和"GPL"相同,它的存在是因爲歷史原因。
+
+    "GPL and additional rights"   表示模塊源在GPL v2變體和MIT許可下雙重許可的
+                                  歷史變體。請不要在新代碼中使用。
+
+    "Dual MIT/GPL"		  表達該模塊在GPL v2變體或MIT許可證選擇下雙重
+                                  許可的正確方式。
+
+    "Dual BSD/GPL"		  該模塊根據GPL v2變體或BSD許可證選擇進行雙重
+                                  許可。 BSD許可證的確切變體只能通過相應源文件
+                                  中的許可證信息來確定。
+
+    "Dual MPL/GPL"		  該模塊根據GPL v2變體或Mozilla Public License
+                                  (MPL)選項進行雙重許可。 MPL許可證的確切變體
+                                  只能通過相應的源文件中的許可證信息來確定。
+
+    "Proprietary"		  該模塊屬於專有許可。此字符串僅用於專有的第三
+                                  方模塊,不能用於在內核樹中具有原始碼的模塊。
+                                  以這種方式標記的模塊在加載時會使用'P'標記汙
+                                  染內核,並且內核模塊加載器拒絕將這些模塊連結
+                                  到使用EXPORT_SYMBOL_GPL()導出的符號。
+    ============================= =============================================
+
+
diff --git a/Documentation/translations/zh_TW/process/magic-number.rst b/Documentation/translations/zh_TW/process/magic-number.rst
new file mode 100644
index 000000000000..ae321a9aaece
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/magic-number.rst
@@ -0,0 +1,148 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _tw_magicnumbers:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/magic-number.rst <magicnumbers>`
+
+如果想評論或更新本文的內容,請直接發信到LKML。如果你使用英文交流有困難的話,也可
+以向中文版維護者求助。如果本翻譯更新不及時或者翻譯存在問題,請聯繫中文版維護者::
+
+        中文版維護者: 賈威威 Jia Wei Wei <harryxiyou@gmail.com>
+        中文版翻譯者: 賈威威 Jia Wei Wei <harryxiyou@gmail.com>
+        中文版校譯者: 賈威威 Jia Wei Wei <harryxiyou@gmail.com>
+                      胡皓文 Hu Haowen <src.res@email.cn>
+
+Linux 魔術數
+============
+
+這個文件是有關當前使用的魔術值註冊表。當你給一個結構添加了一個魔術值,你也應該把這個魔術值添加到這個文件,因爲我們最好把用於各種結構的魔術值統一起來。
+
+使用魔術值來保護內核數據結構是一個非常好的主意。這就允許你在運行期檢查(a)一個結構是否已經被攻擊,或者(b)你已經給一個例行程序通過了一個錯誤的結構。後一種情況特別地有用---特別是當你通過一個空指針指向結構體的時候。tty源碼,例如,經常通過特定驅動使用這種方法並且反覆地排列特定方面的結構。
+
+使用魔術值的方法是在結構的開始處聲明的,如下::
+
+        struct tty_ldisc {
+	        int	magic;
+        	...
+        };
+
+當你以後給內核添加增強功能的時候,請遵守這條規則!這樣就會節省數不清的調試時間,特別是一些古怪的情況,例如,數組超出範圍並且重新寫了超出部分。遵守這個規則,‪這些情況可以被快速地,安全地避免。
+
+		Theodore Ts'o
+		  31 Mar 94
+
+給當前的Linux 2.1.55添加魔術表。
+
+		Michael Chastain
+		<mailto:mec@shout.net>
+		22 Sep 1997
+
+現在應該最新的Linux 2.1.112.因爲在特性凍結期間,不能在2.2.x前改變任何東西。這些條目被數域所排序。
+
+		Krzysztof G.Baranowski
+	        <mailto: kgb@knm.org.pl>
+		29 Jul 1998
+
+更新魔術表到Linux 2.5.45。剛好越過特性凍結,但是有可能還會有一些新的魔術值在2.6.x之前融入到內核中。
+
+		Petr Baudis
+		<pasky@ucw.cz>
+		03 Nov 2002
+
+更新魔術表到Linux 2.5.74。
+
+		Fabian Frederick
+                <ffrederick@users.sourceforge.net>
+		09 Jul 2003
+
+===================== ================ ======================== ==========================================
+魔術數名              數字             結構                     文件
+===================== ================ ======================== ==========================================
+PG_MAGIC              'P'              pg_{read,write}_hdr      ``include/linux/pg.h``
+CMAGIC                0x0111           user                     ``include/linux/a.out.h``
+MKISS_DRIVER_MAGIC    0x04bf           mkiss_channel            ``drivers/net/mkiss.h``
+HDLC_MAGIC            0x239e           n_hdlc                   ``drivers/char/n_hdlc.c``
+APM_BIOS_MAGIC        0x4101           apm_user                 ``arch/x86/kernel/apm_32.c``
+DB_MAGIC              0x4442           fc_info                  ``drivers/net/iph5526_novram.c``
+DL_MAGIC              0x444d           fc_info                  ``drivers/net/iph5526_novram.c``
+FASYNC_MAGIC          0x4601           fasync_struct            ``include/linux/fs.h``
+FF_MAGIC              0x4646           fc_info                  ``drivers/net/iph5526_novram.c``
+PTY_MAGIC             0x5001                                    ``drivers/char/pty.c``
+PPP_MAGIC             0x5002           ppp                      ``include/linux/if_pppvar.h``
+SSTATE_MAGIC          0x5302           serial_state             ``include/linux/serial.h``
+SLIP_MAGIC            0x5302           slip                     ``drivers/net/slip.h``
+STRIP_MAGIC           0x5303           strip                    ``drivers/net/strip.c``
+SIXPACK_MAGIC         0x5304           sixpack                  ``drivers/net/hamradio/6pack.h``
+AX25_MAGIC            0x5316           ax_disp                  ``drivers/net/mkiss.h``
+TTY_MAGIC             0x5401           tty_struct               ``include/linux/tty.h``
+MGSL_MAGIC            0x5401           mgsl_info                ``drivers/char/synclink.c``
+TTY_DRIVER_MAGIC      0x5402           tty_driver               ``include/linux/tty_driver.h``
+MGSLPC_MAGIC          0x5402           mgslpc_info              ``drivers/char/pcmcia/synclink_cs.c``
+USB_SERIAL_MAGIC      0x6702           usb_serial               ``drivers/usb/serial/usb-serial.h``
+FULL_DUPLEX_MAGIC     0x6969                                    ``drivers/net/ethernet/dec/tulip/de2104x.c``
+USB_BLUETOOTH_MAGIC   0x6d02           usb_bluetooth            ``drivers/usb/class/bluetty.c``
+RFCOMM_TTY_MAGIC      0x6d02                                    ``net/bluetooth/rfcomm/tty.c``
+USB_SERIAL_PORT_MAGIC 0x7301           usb_serial_port          ``drivers/usb/serial/usb-serial.h``
+CG_MAGIC              0x00090255       ufs_cylinder_group       ``include/linux/ufs_fs.h``
+LSEMAGIC              0x05091998       lse                      ``drivers/fc4/fc.c``
+GDTIOCTL_MAGIC        0x06030f07       gdth_iowr_str            ``drivers/scsi/gdth_ioctl.h``
+RIEBL_MAGIC           0x09051990                                ``drivers/net/atarilance.c``
+NBD_REQUEST_MAGIC     0x12560953       nbd_request              ``include/linux/nbd.h``
+RED_MAGIC2            0x170fc2a5       (any)                    ``mm/slab.c``
+BAYCOM_MAGIC          0x19730510       baycom_state             ``drivers/net/baycom_epp.c``
+ISDN_X25IFACE_MAGIC   0x1e75a2b9       isdn_x25iface_proto_data ``drivers/isdn/isdn_x25iface.h``
+ECP_MAGIC             0x21504345       cdkecpsig                ``include/linux/cdk.h``
+LSOMAGIC              0x27091997       lso                      ``drivers/fc4/fc.c``
+LSMAGIC               0x2a3b4d2a       ls                       ``drivers/fc4/fc.c``
+WANPIPE_MAGIC         0x414C4453       sdla_{dump,exec}         ``include/linux/wanpipe.h``
+CS_CARD_MAGIC         0x43525553       cs_card                  ``sound/oss/cs46xx.c``
+LABELCL_MAGIC         0x4857434c       labelcl_info_s           ``include/asm/ia64/sn/labelcl.h``
+ISDN_ASYNC_MAGIC      0x49344C01       modem_info               ``include/linux/isdn.h``
+CTC_ASYNC_MAGIC       0x49344C01       ctc_tty_info             ``drivers/s390/net/ctctty.c``
+ISDN_NET_MAGIC        0x49344C02       isdn_net_local_s         ``drivers/isdn/i4l/isdn_net_lib.h``
+SAVEKMSG_MAGIC2       0x4B4D5347       savekmsg                 ``arch/*/amiga/config.c``
+CS_STATE_MAGIC        0x4c4f4749       cs_state                 ``sound/oss/cs46xx.c``
+SLAB_C_MAGIC          0x4f17a36d       kmem_cache               ``mm/slab.c``
+COW_MAGIC             0x4f4f4f4d       cow_header_v1            ``arch/um/drivers/ubd_user.c``
+I810_CARD_MAGIC       0x5072696E       i810_card                ``sound/oss/i810_audio.c``
+TRIDENT_CARD_MAGIC    0x5072696E       trident_card             ``sound/oss/trident.c``
+ROUTER_MAGIC          0x524d4157       wan_device               [in ``wanrouter.h`` pre 3.9]
+SAVEKMSG_MAGIC1       0x53415645       savekmsg                 ``arch/*/amiga/config.c``
+GDA_MAGIC             0x58464552       gda                      ``arch/mips/include/asm/sn/gda.h``
+RED_MAGIC1            0x5a2cf071       (any)                    ``mm/slab.c``
+EEPROM_MAGIC_VALUE    0x5ab478d2       lanai_dev                ``drivers/atm/lanai.c``
+HDLCDRV_MAGIC         0x5ac6e778       hdlcdrv_state            ``include/linux/hdlcdrv.h``
+PCXX_MAGIC            0x5c6df104       channel                  ``drivers/char/pcxx.h``
+KV_MAGIC              0x5f4b565f       kernel_vars_s            ``arch/mips/include/asm/sn/klkernvars.h``
+I810_STATE_MAGIC      0x63657373       i810_state               ``sound/oss/i810_audio.c``
+TRIDENT_STATE_MAGIC   0x63657373       trient_state             ``sound/oss/trident.c``
+M3_CARD_MAGIC         0x646e6f50       m3_card                  ``sound/oss/maestro3.c``
+FW_HEADER_MAGIC       0x65726F66       fw_header                ``drivers/atm/fore200e.h``
+SLOT_MAGIC            0x67267321       slot                     ``drivers/hotplug/cpqphp.h``
+SLOT_MAGIC            0x67267322       slot                     ``drivers/hotplug/acpiphp.h``
+LO_MAGIC              0x68797548       nbd_device               ``include/linux/nbd.h``
+M3_STATE_MAGIC        0x734d724d       m3_state                 ``sound/oss/maestro3.c``
+VMALLOC_MAGIC         0x87654320       snd_alloc_track          ``sound/core/memory.c``
+KMALLOC_MAGIC         0x87654321       snd_alloc_track          ``sound/core/memory.c``
+PWC_MAGIC             0x89DC10AB       pwc_device               ``drivers/usb/media/pwc.h``
+NBD_REPLY_MAGIC       0x96744668       nbd_reply                ``include/linux/nbd.h``
+ENI155_MAGIC          0xa54b872d       midway_eprom	        ``drivers/atm/eni.h``
+CODA_MAGIC            0xC0DAC0DA       coda_file_info           ``fs/coda/coda_fs_i.h``
+DPMEM_MAGIC           0xc0ffee11       gdt_pci_sram             ``drivers/scsi/gdth.h``
+YAM_MAGIC             0xF10A7654       yam_port                 ``drivers/net/hamradio/yam.c``
+CCB_MAGIC             0xf2691ad2       ccb                      ``drivers/scsi/ncr53c8xx.c``
+QUEUE_MAGIC_FREE      0xf7e1c9a3       queue_entry              ``drivers/scsi/arm/queue.c``
+QUEUE_MAGIC_USED      0xf7e1cc33       queue_entry              ``drivers/scsi/arm/queue.c``
+HTB_CMAGIC            0xFEFAFEF1       htb_class                ``net/sched/sch_htb.c``
+NMI_MAGIC             0x48414d4d455201 nmi_s                    ``arch/mips/include/asm/sn/nmi.h``
+===================== ================ ======================== ==========================================
+
+
+請注意,在聲音記憶管理中仍然有一些特殊的爲每個驅動定義的魔術值。查看include/sound/sndmagic.h來獲取他們完整的列表信息。很多OSS聲音驅動擁有自己從音效卡PCI ID構建的魔術值-他們也沒有被列在這裡。
+
+IrDA子系統也使用了大量的自己的魔術值,查看include/net/irda/irda.h來獲取他們完整的信息。
+
+HFS是另外一個比較大的使用魔術值的文件系統-你可以在fs/hfs/hfs.h中找到他們。
+
diff --git a/Documentation/translations/zh_TW/process/management-style.rst b/Documentation/translations/zh_TW/process/management-style.rst
new file mode 100644
index 000000000000..dce248470063
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/management-style.rst
@@ -0,0 +1,211 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/management-style.rst <managementstyle>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+.. _tw_managementstyle:
+
+Linux內核管理風格
+=================
+
+這是一個簡短的文檔,描述了Linux內核首選的(或胡編的,取決於您問誰)管理風格。
+它的目的是在某種程度上參照 :ref:`process/coding-style.rst <codingstyle>`
+主要是爲了避免反覆回答 [#cnf1]_ 相同(或類似)的問題。
+
+管理風格是非常個人化的,比簡單的編碼風格規則更難以量化,因此本文檔可能與實
+際情況有關,也可能與實際情況無關。起初它是一個玩笑,但這並不意味著它可能不
+是真的。你得自己決定。
+
+順便說一句,在談到「核心管理者」時,主要是技術負責人,而不是在公司內部進行傳
+統管理的人。如果你簽署了採購訂單或者對你的團隊的預算有任何了解,你幾乎肯定
+不是一個核心管理者。這些建議可能適用於您,也可能不適用於您。
+
+首先,我建議你購買「高效人的七個習慣」,而不是閱讀它。燒了它,這是一個偉大的
+象徵性姿態。
+
+.. [#cnf1] 本文件並不是通過回答問題,而是通過讓提問者痛苦地明白,我們不知道
+   答案是什麼。
+
+不管怎樣,這裡是:
+
+.. _tw_decisions:
+
+1)決策
+-------
+
+每個人都認爲管理者做決定,而且決策很重要。決定越大越痛苦,管理者就必須越高級。
+這很明顯,但事實並非如此。
+
+遊戲的名字是 **避免** 做出決定。尤其是,如果有人告訴你「選擇(a)或(b),
+我們真的需要你來做決定」,你就是陷入麻煩的管理者。你管理的人比你更了解細節,
+所以如果他們來找你做技術決策,你完蛋了。你顯然沒有能力爲他們做這個決定。
+
+(推論:如果你管理的人不比你更了解細節,你也會被搞砸,儘管原因完全不同。
+也就是說,你的工作是錯的,他們應該管理你的才智)
+
+所以遊戲的名字是 **避免** 做出決定,至少是那些大而痛苦的決定。做一些小的
+和非結果性的決定是很好的,並且使您看起來好像知道自己在做什麼,所以內核管理者
+需要做的是將那些大的和痛苦的決定變成那些沒有人真正關心的小事情。
+
+這有助於認識到一個大的決定和一個小的決定之間的關鍵區別是你是否可以在事後修正
+你的決定。任何決定都可以通過始終確保如果你錯了(而且你一定會錯),你以後總是
+可以通過回溯來彌補損失。突然間,你就要做兩個無關緊要的決定,一個是錯誤的,另
+一個是正確的。
+
+人們甚至會認爲這是真正的領導能力(咳,胡說,咳)。
+
+因此,避免重大決策的關鍵在於避免做那些無法挽回的事情。不要被引導到一個你無法
+逃離的角落。走投無路的老鼠可能很危險——走投無路的管理者真可憐。
+
+事實證明,由於沒有人會愚蠢到讓內核管理者承擔巨大的財政責任,所以通常很容易
+回溯。既然你不可能浪費掉你無法償還的巨額資金,你唯一可以回溯的就是技術決策,
+而回溯很容易:只要告訴大家你是個不稱職的傻瓜,說對不起,然後撤銷你去年讓別
+人所做的毫無價值的工作。突然間,你一年前做的決定不在是一個重大的決定,因爲
+它很容易被推翻。
+
+事實證明,有些人對接受這種方法有困難,原因有兩個:
+
+ - 承認你是個白癡比看起來更難。我們都喜歡保持形象,在公共場合說你錯了有時
+   確實很難。
+ - 如果有人告訴你,你去年所做的工作終究是不值得的,那麼對那些可憐的低級工
+   程師來說也是很困難的,雖然實際的 **工作** 很容易刪除,但你可能已經不可
+   挽回地失去了工程師的信任。記住:「不可撤銷」是我們一開始就試圖避免的,
+   而你的決定終究是一個重大的決定。
+
+令人欣慰的是,這兩個原因都可以通過預先承認你沒有任何線索,提前告訴人們你的
+決定完全是初步的,而且可能是錯誤的事情來有效地緩解。你應該始終保留改變主意
+的權利,並讓人們 **意識** 到這一點。當你 **還沒有** 做過真正愚蠢的事情的時
+候,承認自己是愚蠢的要容易得多。
+
+然後,當它真的被證明是愚蠢的時候,人們就轉動他們的眼珠說「哎呀,下次不要了」。
+
+這種對不稱職的先發制人的承認,也可能使真正做這項工作的人也會三思是否值得做。
+畢竟,如果他們不確定這是否是一個好主意,你肯定不應該通過向他們保證他們所做
+的工作將會進入(內核)鼓勵他們。在他們開始一項巨大的努力之前,至少讓他們三
+思而後行。
+
+記住:他們最好比你更了解細節,而且他們通常認爲他們對每件事都有答案。作爲一
+個管理者,你能做的最好的事情不是灌輸自信,而是對他們所做的事情進行健康的批
+判性思考。
+
+順便說一句,另一種避免做出決定的方法是看起來很可憐的抱怨 「我們不能兩者兼
+得嗎?」 相信我,它是有效的。如果不清楚哪種方法更好,他們最終會弄清楚的。
+最終的答案可能是兩個團隊都會因爲這種情況而感到沮喪,以至於他們放棄了。
+
+這聽起來像是一個失敗,但這通常是一個跡象,表明兩個項目都有問題,而參與其中
+的人不能做決定的原因是他們都是錯誤的。你最終會聞到玫瑰的味道,你避免了另一
+個你本可以搞砸的決定。
+
+2)人
+-----
+
+大多數人都是白癡,做一名管理者意味著你必須處理好這件事,也許更重要的是,
+**他們** 必須處理好你。
+
+事實證明,雖然很容易糾正技術錯誤,但不容易糾正人格障礙。你只能和他們的和
+你的(人格障礙)共處。
+
+但是,爲了做好作爲內核管理者的準備,最好記住不要燒掉任何橋樑,不要轟炸任何
+無辜的村民,也不要疏遠太多的內核開發人員。事實證明,疏遠人是相當容易的,而
+親近一個疏遠的人是很難的。因此,「疏遠」立即屬於「不可逆」的範疇,並根據
+:ref:`tw_decisions` 成爲絕不可以做的事情。
+
+這裡只有幾個簡單的規則:
+
+ (1) 不要叫人笨蛋(至少不要在公共場合)
+ (2) 學習如何在忘記規則(1)時道歉
+
+問題在於 #1 很容易去做,因爲你可以用數百萬種不同的方式說「你是一個笨蛋」 [#cnf2]_
+有時甚至沒有意識到,而且幾乎總是帶著一種白熱化的信念,認爲你是對的。
+
+你越確信自己是對的(讓我們面對現實吧,你可以把幾乎所有人都稱爲壞人,而且你
+經常是對的),事後道歉就越難。
+
+要解決此問題,您實際上只有兩個選項:
+
+ - 非常擅長道歉
+ - 把「愛」均勻地散開,沒有人會真正感覺到自己被不公平地瞄準了。讓它有足夠的
+   創造性,他們甚至可能會覺得好笑。
+
+選擇永遠保持禮貌是不存在的。沒有人會相信一個如此明顯地隱藏了他們真實性格的人。
+
+.. [#cnf2] 保羅·西蒙演唱了「離開愛人的50種方法」,因爲坦率地說,「告訴開發者
+   他們是D*CKHEAD" 的100萬種方法都無法確認。但我確信他已經這麼想了。
+
+3)人2 - 好人
+-------------
+
+雖然大多數人都是白癡,但不幸的是,據此推論你也是白癡,儘管我們都自我感覺良
+好,我們比普通人更好(讓我們面對現實吧,沒有人相信他們是普通人或低於普通人),
+我們也應該承認我們不是最鋒利的刀,而且會有其他人比你更不像白癡。
+
+有些人對聰明人反應不好。其他人利用它們。
+
+作爲內核維護人員,確保您在第二組中。接受他們,因爲他們會讓你的工作更容易。
+特別是,他們能夠爲你做決定,這就是遊戲的全部內容。
+
+所以當你發現一個比你聰明的人時,就順其自然吧。你的管理職責在很大程度上變成
+了「聽起來像是個好主意——去嘗試吧」,或者「聽起來不錯,但是XXX呢?」「。第二個版
+本尤其是一個很好的方法,要麼學習一些關於「XXX」的新東西,要麼通過指出一些聰明
+人沒有想到的東西來顯得更具管理性。無論哪種情況,你都會贏。
+
+要注意的一件事是認識到一個領域的偉大不一定會轉化爲其他領域。所以你可能會向
+特定的方向刺激人們,但讓我們面對現實吧,他們可能擅長他們所做的事情,而且對
+其他事情都很差勁。好消息是,人們往往會自然而然地重拾他們擅長的東西,所以當
+你向某個方向刺激他們時,你並不是在做不可逆轉的事情,只是不要用力推。
+
+4)責備
+-------
+
+事情會出問題的,人們希望去責備人。貼標籤,你就是受責備的人。
+
+事實上,接受責備並不難,尤其是當人們意識到這不 **全是** 你的過錯時。這讓我
+們找到了承擔責任的最佳方式:爲別人承擔這件事。你會感覺很好,他們會感覺很好,
+沒有受到指責. 那誰,失去了他們的全部36GB色情收藏的人,因爲你的無能將勉強承
+認,你至少沒有試圖逃避責任。
+
+然後讓真正搞砸了的開發人員(如果你能找到他們)私下知道他們搞砸了。不僅是爲
+了將來可以避免,而且爲了讓他們知道他們欠你一個人情。而且,也許更重要的是,
+他們也可能是能夠解決問題的人。因爲,讓我們面對現實吧,肯定不是你。
+
+承擔責任也是你首先成爲管理者的原因。這是讓人們信任你,讓你獲得潛在的榮耀的
+一部分,因爲你就是那個會說「我搞砸了」的人。如果你已經遵循了以前的規則,你現
+在已經很擅長說了。
+
+5)應避免的事情
+---------------
+
+有一件事人們甚至比被稱爲「笨蛋」更討厭,那就是在一個神聖的聲音中被稱爲「笨蛋」。
+第一個你可以道歉,第二個你不會真正得到機會。即使你做得很好,他們也可能不再
+傾聽。
+
+我們都認爲自己比別人強,這意味著當別人裝腔作勢時,這會讓我們很惱火。你也許
+在道德和智力上比你周圍的每個人都優越,但不要試圖太明顯,除非你真的打算激怒
+某人 [#cnf3]_
+
+同樣,不要對事情太客氣或太微妙。禮貌很容易落得落花流水,把問題隱藏起來,
+正如他們所說,「在網際網路上,沒人能聽到你的含蓄。」用一個鈍器把這一點錘進去,
+因爲你不能真的依靠別人來獲得你的觀點。
+
+一些幽默可以幫助緩和直率和道德化。過度到荒謬的地步,可以灌輸一個觀點,而不
+會讓接受者感到痛苦,他們只是認爲你是愚蠢的。因此,它可以幫助我們擺脫對批評
+的個人心理障礙。
+
+.. [#cnf3] 提示:與你的工作沒有直接關係的網絡新聞組是消除你對他人不滿的好
+   方法。偶爾寫些侮辱性的帖子,打個噴嚏,讓你的情緒得到淨化。別把牢騷帶回家
+
+6)爲什麼是我?
+---------------
+
+既然你的主要責任似乎是爲別人的錯誤承擔責任,並且讓別人痛苦地明白你是不稱職
+的,那麼顯而易見的問題之一就變成了爲什麼首先要這樣做。
+
+首先,雖然你可能會或可能不會聽到十幾歲女孩(或男孩,讓我們不要在這裡評判或
+性別歧視)敲你的更衣室門,你會得到一個巨大的個人成就感爲「負責」。別介意你真
+的在領導別人,你要跟上別人,儘可能快地追趕他們。每個人都會認爲你是負責人。
+
+如果你可以做到這個, 這是個偉大的工作!
+
diff --git a/Documentation/translations/zh_TW/process/programming-language.rst b/Documentation/translations/zh_TW/process/programming-language.rst
new file mode 100644
index 000000000000..54e3699eadf8
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/programming-language.rst
@@ -0,0 +1,76 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/programming-language.rst <programming_language>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+.. _tw_programming_language:
+
+程序設計語言
+============
+
+內核是用C語言 :ref:`c-language <tw_c-language>` 編寫的。更準確地說,內核通常是用 :ref:`gcc <tw_gcc>`
+在 ``-std=gnu89`` :ref:`gcc-c-dialect-options <tw_gcc-c-dialect-options>` 下編譯的:ISO C90的 GNU 方言(
+包括一些C99特性)
+
+這種方言包含對語言 :ref:`gnu-extensions <tw_gnu-extensions>` 的許多擴展,當然,它們許多都在內核中使用。
+
+對於一些體系結構,有一些使用 :ref:`clang <tw_clang>` 和 :ref:`icc <tw_icc>` 編譯內核
+的支持,儘管在編寫此文檔時還沒有完成,仍需要第三方補丁。
+
+屬性
+----
+
+在整個內核中使用的一個常見擴展是屬性(attributes) :ref:`gcc-attribute-syntax <tw_gcc-attribute-syntax>`
+屬性允許將實現定義的語義引入語言實體(如變量、函數或類型),而無需對語言進行
+重大的語法更改(例如添加新關鍵字) :ref:`n2049 <tw_n2049>`
+
+在某些情況下,屬性是可選的(即不支持這些屬性的編譯器仍然應該生成正確的代碼,
+即使其速度較慢或執行的編譯時檢查/診斷次數不夠)
+
+內核定義了僞關鍵字(例如, ``pure`` ),而不是直接使用GNU屬性語法(例如,
+``__attribute__((__pure__))`` ),以檢測可以使用哪些關鍵字和/或縮短代碼, 具體
+請參閱 ``include/linux/compiler_attributes.h``
+
+.. _tw_c-language:
+
+c-language
+   http://www.open-std.org/jtc1/sc22/wg14/www/standards
+
+.. _tw_gcc:
+
+gcc
+   https://gcc.gnu.org
+
+.. _tw_clang:
+
+clang
+   https://clang.llvm.org
+
+.. _tw_icc:
+
+icc
+   https://software.intel.com/en-us/c-compilers
+
+.. _tw_gcc-c-dialect-options:
+
+c-dialect-options
+   https://gcc.gnu.org/onlinedocs/gcc/C-Dialect-Options.html
+
+.. _tw_gnu-extensions:
+
+gnu-extensions
+   https://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html
+
+.. _tw_gcc-attribute-syntax:
+
+gcc-attribute-syntax
+   https://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html
+
+.. _tw_n2049:
+
+n2049
+   http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2049.pdf
+
diff --git a/Documentation/translations/zh_TW/process/stable-api-nonsense.rst b/Documentation/translations/zh_TW/process/stable-api-nonsense.rst
new file mode 100644
index 000000000000..22caa5b8d422
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/stable-api-nonsense.rst
@@ -0,0 +1,159 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _tw_stable_api_nonsense:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/stable-api-nonsense.rst
+           <stable_api_nonsense>`
+
+譯者::
+
+        中文版維護者: 鍾宇  TripleX Chung <xxx.phy@gmail.com>
+        中文版翻譯者: 鍾宇  TripleX Chung <xxx.phy@gmail.com>
+        中文版校譯者: 李陽  Li Yang <leoyang.li@nxp.com>
+                      胡皓文 Hu Haowen <src.res@email.cn>
+
+Linux 內核驅動接口
+==================
+
+寫作本文檔的目的,是爲了解釋爲什麼Linux既沒有二進位內核接口,也沒有穩定
+的內核接口。這裡所說的內核接口,是指內核里的接口,而不是內核和用戶空間
+的接口。內核到用戶空間的接口,是提供給應用程式使用的系統調用,系統調用
+在歷史上幾乎沒有過變化,將來也不會有變化。我有一些老應用程式是在0.9版本
+或者更早版本的內核上編譯的,在使用2.6版本內核的Linux發布上依然用得很好
+。用戶和應用程式作者可以將這個接口看成是穩定的。
+
+
+執行綱要
+--------
+
+你也許以爲自己想要穩定的內核接口,但是你不清楚你要的實際上不是它。你需
+要的其實是穩定的驅動程序,而你只有將驅動程序放到公版內核的原始碼樹里,
+才有可能達到這個目的。而且這樣做還有很多其它好處,正是因爲這些好處使得
+Linux能成爲強壯,穩定,成熟的作業系統,這也是你最開始選擇Linux的原因。
+
+
+入門
+-----
+
+只有那些寫驅動程序的「怪人」才會擔心內核接口的改變,對廣大用戶來說,既
+看不到內核接口,也不需要去關心它。
+
+首先,我不打算討論關於任何非GPL許可的內核驅動的法律問題,這些非GPL許可
+的驅動程序包括不公開原始碼,隱藏原始碼,二進位或者是用原始碼包裝,或者
+是其它任何形式的不能以GPL許可公開原始碼的驅動程序。如果有法律問題,請咨
+詢律師,我只是一個程式設計師,所以我只打算探討技術問題(不是小看法律問題,
+法律問題很實際,並且需要一直關注)。
+
+既然只談技術問題,我們就有了下面兩個主題:二進位內核接口和穩定的內核源
+代碼接口。這兩個問題是互相關聯的,讓我們先解決掉二進位接口的問題。
+
+
+二進位內核接口
+--------------
+假如我們有一個穩定的內核原始碼接口,那麼自然而然的,我們就擁有了穩定的
+二進位接口,是這樣的嗎?錯。讓我們看看關於Linux內核的幾點事實:
+
+    - 取決於所用的C編譯器的版本,不同的內核數據結構里的結構體的對齊方
+      式會有差別,代碼中不同函數的表現形式也不一樣(函數是不是被inline
+      編譯取決於編譯器行爲)。不同的函數的表現形式並不重要,但是數據
+      結構內部的對齊方式很關鍵。
+
+    - 取決於內核的配置選項,不同的選項會讓內核的很多東西發生改變:
+
+      - 同一個結構體可能包含不同的成員變量
+      - 有的函數可能根本不會被實現(比如編譯的時候沒有選擇SMP支持
+        一些鎖函數就會被定義成空函數)。
+      - 內核使用的內存會以不同的方式對齊,這取決於不同的內核配置選
+        項。
+
+    - Linux可以在很多的不同體系結構的處理器上運行。在某個體系結構上編
+      譯好的二進位驅動程序,不可能在另外一個體系結構上正確的運行。
+
+對於一個特定的內核,滿足這些條件並不難,使用同一個C編譯器和同樣的內核配
+置選項來編譯驅動程序模塊就可以了。這對於給一個特定Linux發布的特定版本提
+供驅動程序,是完全可以滿足需求的。但是如果你要給不同發布的不同版本都發
+布一個驅動程序,就需要在每個發布上用不同的內核設置參數都編譯一次內核,
+這簡直跟噩夢一樣。而且還要注意到,每個Linux發布還提供不同的Linux內核,
+這些內核都針對不同的硬體類型進行了優化(有很多種不同的處理器,還有不同
+的內核設置選項)。所以每發布一次驅動程序,都需要提供很多不同版本的內核
+模塊。
+
+相信我,如果你真的要採取這種發布方式,一定會慢慢瘋掉,我很久以前就有過
+深刻的教訓...
+
+
+穩定的內核原始碼接口
+--------------------
+
+如果有人不將他的內核驅動程序,放入公版內核的原始碼樹,而又想讓驅動程序
+一直保持在最新的內核中可用,那麼這個話題將會變得沒完沒了。
+內核開發是持續而且快節奏的,從來都不會慢下來。內核開發人員在當前接口中
+找到bug,或者找到更好的實現方式。一旦發現這些,他們就很快會去修改當前的
+接口。修改接口意味著,函數名可能會改變,結構體可能被擴充或者刪減,函數
+的參數也可能發生改變。一旦接口被修改,內核中使用這些接口的地方需要同時
+修正,這樣才能保證所有的東西繼續工作。
+
+舉一個例子,內核的USB驅動程序接口在USB子系統的整個生命周期中,至少經歷
+了三次重寫。這些重寫解決以下問題:
+
+    - 把數據流從同步模式改成非同步模式,這個改動減少了一些驅動程序的
+      複雜度,提高了所有USB驅動程序的吞吐率,這樣幾乎所有的USB設備都
+      能以最大速率工作了。
+    - 修改了USB核心代碼中爲USB驅動分配數據包內存的方式,所有的驅動都
+      需要提供更多的參數給USB核心,以修正了很多已經被記錄在案的死鎖。
+
+這和一些封閉原始碼的作業系統形成鮮明的對比,在那些作業系統上,不得不額
+外的維護舊的USB接口。這導致了一個可能性,新的開發者依然會不小心使用舊的
+接口,以不恰當的方式編寫代碼,進而影響到作業系統的穩定性。
+在上面的例子中,所有的開發者都同意這些重要的改動,在這樣的情況下修改代
+價很低。如果Linux保持一個穩定的內核原始碼接口,那麼就得創建一個新的接口
+;舊的,有問題的接口必須一直維護,給Linux USB開發者帶來額外的工作。既然
+所有的Linux USB驅動的作者都是利用自己的時間工作,那麼要求他們去做毫無意
+義的免費額外工作,是不可能的。
+安全問題對Linux來說十分重要。一個安全問題被發現,就會在短時間內得到修
+正。在很多情況下,這將導致Linux內核中的一些接口被重寫,以從根本上避免安
+全問題。一旦接口被重寫,所有使用這些接口的驅動程序,必須同時得到修正,
+以確定安全問題已經得到修復並且不可能在未來還有同樣的安全問題。如果內核
+內部接口不允許改變,那麼就不可能修復這樣的安全問題,也不可能確認這樣的
+安全問題以後不會發生。
+開發者一直在清理內核接口。如果一個接口沒有人在使用了,它就會被刪除。這
+樣可以確保內核儘可能的小,而且所有潛在的接口都會得到儘可能完整的測試
+(沒有人使用的接口是不可能得到良好的測試的)。
+
+
+要做什麼
+--------
+
+如果你寫了一個Linux內核驅動,但是它還不在Linux原始碼樹里,作爲一個開發
+者,你應該怎麼做?爲每個發布的每個版本提供一個二進位驅動,那簡直是一個
+噩夢,要跟上永遠處於變化之中的內核接口,也是一件辛苦活。
+很簡單,讓你的驅動進入內核原始碼樹(要記得我們在談論的是以GPL許可發行
+的驅動,如果你的代碼不符合GPL,那麼祝你好運,你只能自己解決這個問題了,
+你這個吸血鬼<把Andrew和Linus對吸血鬼的定義連結到這裡>)。當你的代碼加入
+公版內核原始碼樹之後,如果一個內核接口改變,你的驅動會直接被修改接口的
+那個人修改。保證你的驅動永遠都可以編譯通過,並且一直工作,你幾乎不需要
+做什麼事情。
+
+把驅動放到內核原始碼樹里會有很多的好處:
+
+    - 驅動的質量會提升,而維護成本(對原始作者來說)會下降。
+    - 其他人會給驅動添加新特性。
+    - 其他人會找到驅動中的bug並修復。
+    - 其他人會在驅動中找到性能優化的機會。
+    - 當外部的接口的改變需要修改驅動程序的時候,其他人會修改驅動程序
+    - 不需要聯繫任何發行商,這個驅動會自動的隨著所有的Linux發布一起發
+      布。
+
+和別的作業系統相比,Linux爲更多不同的設備提供現成的驅動,而且能在更多不
+同體系結構的處理器上支持這些設備。這個經過考驗的開發模式,必然是錯不了
+的 :)
+
+感謝
+----
+感謝 Randy Dunlap, Andrew Morton, David Brownell, Hanna Linder,
+Robert Love, and Nishanth Aravamudan 對於本文檔早期版本的評審和建議。
+
+英文版維護者: Greg Kroah-Hartman <greg@kroah.com>
+
diff --git a/Documentation/translations/zh_TW/process/stable-kernel-rules.rst b/Documentation/translations/zh_TW/process/stable-kernel-rules.rst
new file mode 100644
index 000000000000..9bb0d9b4f3ac
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/stable-kernel-rules.rst
@@ -0,0 +1,68 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _tw_stable_kernel_rules:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/stable-kernel-rules.rst <stable_kernel_rules>`
+
+如果想評論或更新本文的內容,請直接聯繫原文檔的維護者。如果你使用英文
+交流有困難的話,也可以向中文版維護者求助。如果本翻譯更新不及時或者翻
+譯存在問題,請聯繫中文版維護者::
+
+        中文版維護者: 鍾宇  TripleX Chung <xxx.phy@gmail.com>
+        中文版翻譯者: 鍾宇  TripleX Chung <xxx.phy@gmail.com>
+        中文版校譯者:
+            - 李陽  Li Yang <leoyang.li@nxp.com>
+            - Kangkai Yin <e12051@motorola.com>
+            - 胡皓文 Hu Haowen <src.res@email.cn>
+
+所有你想知道的事情 - 關於linux穩定版發布
+========================================
+
+關於Linux 2.6穩定版發布,所有你想知道的事情。
+
+關於哪些類型的補丁可以被接收進入穩定版代碼樹,哪些不可以的規則:
+----------------------------------------------------------------
+
+  - 必須是顯而易見的正確,並且經過測試的。
+  - 連同上下文,不能大於100行。
+  - 必須只修正一件事情。
+  - 必須修正了一個給大家帶來麻煩的真正的bug(不是「這也許是一個問題...」
+    那樣的東西)。
+  - 必須修正帶來如下後果的問題:編譯錯誤(對被標記爲CONFIG_BROKEN的例外),
+    內核崩潰,掛起,數據損壞,真正的安全問題,或者一些類似「哦,這不
+    好」的問題。簡短的說,就是一些致命的問題。
+  - 沒有「理論上的競爭條件」,除非能給出競爭條件如何被利用的解釋。
+  - 不能存在任何的「瑣碎的」修正(拼寫修正,去掉多餘空格之類的)。
+  - 必須被相關子系統的維護者接受。
+  - 必須遵循Documentation/translations/zh_TW/process/submitting-patches.rst里的規則。
+
+向穩定版代碼樹提交補丁的過程:
+------------------------------
+
+  - 在確認了補丁符合以上的規則後,將補丁發送到stable@vger.kernel.org。
+  - 如果補丁被接受到隊列里,發送者會收到一個ACK回復,如果沒有被接受,收
+    到的是NAK回復。回復需要幾天的時間,這取決於開發者的時間安排。
+  - 被接受的補丁會被加到穩定版本隊列里,等待其他開發者的審查。
+  - 安全方面的補丁不要發到這個列表,應該發送到security@kernel.org。
+
+審查周期:
+----------
+
+  - 當穩定版的維護者決定開始一個審查周期,補丁將被發送到審查委員會,以
+    及被補丁影響的領域的維護者(除非提交者就是該領域的維護者)並且抄送
+    到linux-kernel郵件列表。
+  - 審查委員會有48小時的時間,用來決定給該補丁回復ACK還是NAK。
+  - 如果委員會中有成員拒絕這個補丁,或者linux-kernel列表上有人反對這個
+    補丁,並提出維護者和審查委員會之前沒有意識到的問題,補丁會從隊列中
+    丟棄。
+  - 在審查周期結束的時候,那些得到ACK回應的補丁將會被加入到最新的穩定版
+    發布中,一個新的穩定版發布就此產生。
+  - 安全性補丁將從內核安全小組那裡直接接收到穩定版代碼樹中,而不是通過
+    通常的審查周期。請聯繫內核安全小組以獲得關於這個過程的更多細節。
+
+審查委員會:
+------------
+  - 由一些自願承擔這項任務的內核開發者,和幾個非志願的組成。
+
diff --git a/Documentation/translations/zh_TW/process/submit-checklist.rst b/Documentation/translations/zh_TW/process/submit-checklist.rst
new file mode 100644
index 000000000000..ff2f89cba83f
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/submit-checklist.rst
@@ -0,0 +1,109 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/submit-checklist.rst <submitchecklist>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+.. _tw_submitchecklist:
+
+Linux內核補丁提交清單
+~~~~~~~~~~~~~~~~~~~~~
+
+如果開發人員希望看到他們的內核補丁提交更快地被接受,那麼他們應該做一些基本
+的事情。
+
+這些都是在
+:ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+和其他有關提交Linux內核補丁的文檔中提供的。
+
+1) 如果使用工具,則包括定義/聲明該工具的文件。不要依賴於其他頭文件拉入您使用
+   的頭文件。
+
+2) 乾淨的編譯:
+
+   a) 使用適用或修改的 ``CONFIG`` 選項 ``=y``、``=m`` 和 ``=n`` 。沒有GCC
+      警告/錯誤,沒有連結器警告/錯誤。
+
+   b) 通過allnoconfig、allmodconfig
+
+   c) 使用 ``O=builddir`` 時可以成功編譯
+
+3) 通過使用本地交叉編譯工具或其他一些構建場在多個CPU體系結構上構建。
+
+4) PPC64是一種很好的交叉編譯檢查體系結構,因爲它傾向於對64位的數使用無符號
+   長整型。
+
+5) 如下所述 :ref:`Documentation/translations/zh_TW/process/coding-style.rst <tw_codingstyle>`.
+   檢查您的補丁是否爲常規樣式。在提交( ``scripts/check patch.pl`` )之前,
+   使用補丁樣式檢查器檢查是否有輕微的衝突。您應該能夠處理您的補丁中存在的所有
+   違規行爲。
+
+6) 任何新的或修改過的 ``CONFIG`` 選項都不會弄髒配置菜單,並默認爲關閉,除非
+   它們符合 ``Documentation/kbuild/kconfig-language.rst`` 中記錄的異常條件,
+   菜單屬性:默認值.
+
+7) 所有新的 ``kconfig`` 選項都有幫助文本。
+
+8) 已仔細審查了相關的 ``Kconfig`` 組合。這很難用測試來糾正——腦力在這裡是有
+   回報的。
+
+9) 用 sparse 檢查乾淨。
+
+10) 使用 ``make checkstack`` 和 ``make namespacecheck`` 並修復他們發現的任何
+    問題。
+
+    .. note::
+
+        ``checkstack`` 並沒有明確指出問題,但是任何一個在堆棧上使用超過512
+        字節的函數都可以進行更改。
+
+11) 包括 :ref:`kernel-doc <kernel_doc>` 內核文檔以記錄全局內核API。(靜態函數
+    不需要,但也可以。)使用 ``make htmldocs`` 或 ``make pdfdocs`` 檢查
+    :ref:`kernel-doc <kernel_doc>` 並修復任何問題。
+
+12) 通過以下選項同時啓用的測試 ``CONFIG_PREEMPT``, ``CONFIG_DEBUG_PREEMPT``,
+    ``CONFIG_DEBUG_SLAB``, ``CONFIG_DEBUG_PAGEALLOC``, ``CONFIG_DEBUG_MUTEXES``,
+    ``CONFIG_DEBUG_SPINLOCK``, ``CONFIG_DEBUG_ATOMIC_SLEEP``,
+    ``CONFIG_PROVE_RCU`` and ``CONFIG_DEBUG_OBJECTS_RCU_HEAD``
+
+13) 已經過構建和運行時測試,包括有或沒有 ``CONFIG_SMP``, ``CONFIG_PREEMPT``.
+
+14) 如果補丁程序影響IO/磁碟等:使用或不使用 ``CONFIG_LBDAF`` 進行測試。
+
+15) 所有代碼路徑都已在啓用所有lockdep功能的情況下運行。
+
+16) 所有新的/proc條目都記錄在 ``Documentation/``
+
+17) 所有新的內核引導參數都記錄在
+    Documentation/admin-guide/kernel-parameters.rst 中。
+
+18) 所有新的模塊參數都記錄在 ``MODULE_PARM_DESC()``
+
+19) 所有新的用戶空間接口都記錄在 ``Documentation/ABI/`` 中。有關詳細信息,
+    請參閱 ``Documentation/ABI/README`` 。更改用戶空間接口的補丁應該抄送
+    linux-api@vger.kernel.org。
+
+20) 已通過至少注入slab和page分配失敗進行檢查。請參閱 ``Documentation/fault-injection/``
+    如果新代碼是實質性的,那麼添加子系統特定的故障注入可能是合適的。
+
+21) 新添加的代碼已經用 ``gcc -W`` 編譯(使用 ``make EXTRA-CFLAGS=-W`` )。這
+    將產生大量噪聲,但對於查找諸如「警告:有符號和無符號之間的比較」之類的錯誤
+    很有用。
+
+22) 在它被合併到-mm補丁集中之後進行測試,以確保它仍然與所有其他排隊的補丁以
+    及VM、VFS和其他子系統中的各種更改一起工作。
+
+23) 所有內存屏障例如 ``barrier()``, ``rmb()``, ``wmb()`` 都需要原始碼中的注
+    釋來解釋它們正在執行的操作及其原因的邏輯。
+
+24) 如果補丁添加了任何ioctl,那麼也要更新 ``Documentation/userspace-api/ioctl/ioctl-number.rst``
+
+25) 如果修改後的原始碼依賴或使用與以下 ``Kconfig`` 符號相關的任何內核API或
+    功能,則在禁用相關 ``Kconfig`` 符號和/或 ``=m`` (如果該選項可用)的情況
+    下測試以下多個構建[並非所有這些都同時存在,只是它們的各種/隨機組合]:
+
+    ``CONFIG_SMP``, ``CONFIG_SYSFS``, ``CONFIG_PROC_FS``, ``CONFIG_INPUT``, ``CONFIG_PCI``, ``CONFIG_BLOCK``, ``CONFIG_PM``, ``CONFIG_MAGIC_SYSRQ``,
+    ``CONFIG_NET``, ``CONFIG_INET=n`` (但是後者伴隨 ``CONFIG_NET=y``).
+
diff --git a/Documentation/translations/zh_TW/process/submitting-drivers.rst b/Documentation/translations/zh_TW/process/submitting-drivers.rst
new file mode 100644
index 000000000000..2fdd742318ba
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/submitting-drivers.rst
@@ -0,0 +1,164 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _tw_submittingdrivers:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/submitting-drivers.rst
+           <submittingdrivers>`
+
+如果想評論或更新本文的內容,請直接聯繫原文檔的維護者。如果你使用英文
+交流有困難的話,也可以向中文版維護者求助。如果本翻譯更新不及時或者翻
+譯存在問題,請聯繫中文版維護者::
+
+        中文版維護者: 李陽  Li Yang <leoyang.li@nxp.com>
+        中文版翻譯者: 李陽  Li Yang <leoyang.li@nxp.com>
+        中文版校譯者: 陳琦 Maggie Chen <chenqi@beyondsoft.com>
+                       王聰 Wang Cong <xiyou.wangcong@gmail.com>
+                       張巍 Zhang Wei <wezhang@outlook.com>
+                       胡皓文 Hu Haowen <src.res@email.cn>
+
+如何向 Linux 內核提交驅動程序
+=============================
+
+這篇文檔將會解釋如何向不同的內核源碼樹提交設備驅動程序。請注意,如果你感
+興趣的是顯卡驅動程序,你也許應該訪問 XFree86 項目(https://www.xfree86.org/)
+和/或 X.org 項目 (https://x.org)。
+
+另請參閱 Documentation/translations/zh_TW/process/submitting-patches.rst 文檔。
+
+
+分配設備號
+----------
+
+塊設備和字符設備的主設備號與從設備號是由 Linux 命名編號分配權威 LANANA(
+現在是 Torben Mathiasen)負責分配。申請的網址是 https://www.lanana.org/。
+即使不準備提交到主流內核的設備驅動也需要在這裡分配設備號。有關詳細信息,
+請參閱 Documentation/admin-guide/devices.rst。
+
+如果你使用的不是已經分配的設備號,那麼當你提交設備驅動的時候,它將會被強
+制分配一個新的設備號,即便這個設備號和你之前發給客戶的截然不同。
+
+設備驅動的提交對象
+------------------
+
+Linux 2.0:
+	此內核源碼樹不接受新的驅動程序。
+
+Linux 2.2:
+	此內核源碼樹不接受新的驅動程序。
+
+Linux 2.4:
+	如果所屬的代碼領域在內核的 MAINTAINERS 文件中列有一個總維護者,
+	那麼請將驅動程序提交給他。如果此維護者沒有回應或者你找不到恰當的
+	維護者,那麼請聯繫 Willy Tarreau <w@1wt.eu>。
+
+Linux 2.6:
+	除了遵循和 2.4 版內核同樣的規則外,你還需要在 linux-kernel 郵件
+	列表上跟蹤最新的 API 變化。向 Linux 2.6 內核提交驅動的頂級聯繫人
+	是 Andrew Morton <akpm@linux-foundation.org>。
+
+決定設備驅動能否被接受的條件
+----------------------------
+
+許可:		代碼必須使用 GNU 通用公開許可證 (GPL) 提交給 Linux,但是
+		我們並不要求 GPL 是唯一的許可。你或許會希望同時使用多種
+		許可證發布,如果希望驅動程序可以被其他開源社區(比如BSD)
+		使用。請參考 include/linux/module.h 文件中所列出的可被
+		接受共存的許可。
+
+版權:		版權所有者必須同意使用 GPL 許可。最好提交者和版權所有者
+		是相同個人或實體。否則,必需列出授權使用 GPL 的版權所有
+		人或實體,以備驗證之需。
+
+接口:		如果你的驅動程序使用現成的接口並且和其他同類的驅動程序行
+		爲相似,而不是去發明無謂的新接口,那麼它將會更容易被接受。
+		如果你需要一個 Linux 和 NT 的通用驅動接口,那麼請在用
+		戶空間實現它。
+
+代碼:		請使用 Documentation/process/coding-style.rst 中所描述的 Linux 代碼風
+		格。如果你的某些代碼段(例如那些與 Windows 驅動程序包共
+		享的代碼段)需要使用其他格式,而你卻只希望維護一份代碼,
+		那麼請將它們很好地區分出來,並且註明原因。
+
+可移植性:	請注意,指針並不永遠是 32 位的,不是所有的計算機都使用小
+		尾模式 (little endian) 存儲數據,不是所有的人都擁有浮點
+		單元,不要隨便在你的驅動程序里嵌入 x86 彙編指令。只能在
+		x86 上運行的驅動程序一般是不受歡迎的。雖然你可能只有 x86
+		硬體,很難測試驅動程序在其他平台上是否可用,但是確保代碼
+		可以被輕鬆地移植卻是很簡單的。
+
+清晰度:	做到所有人都能修補這個驅動程序將會很有好處,因爲這樣你將
+		會直接收到修復的補丁而不是 bug 報告。如果你提交一個試圖
+		隱藏硬體工作機理的驅動程序,那麼它將會被扔進廢紙簍。
+
+電源管理:	因爲 Linux 正在被很多行動裝置和桌面系統使用,所以你的驅
+		動程序也很有可能被使用在這些設備上。它應該支持最基本的電
+		源管理,即在需要的情況下實現系統級休眠和喚醒要用到的
+		.suspend 和 .resume 函數。你應該檢查你的驅動程序是否能正
+		確地處理休眠與喚醒,如果實在無法確認,請至少把 .suspend
+		函數定義成返回 -ENOSYS(功能未實現)錯誤。你還應該嘗試確
+		保你的驅動在什麼都不乾的情況下將耗電降到最低。要獲得驅動
+		程序測試的指導,請參閱
+		Documentation/power/drivers-testing.rst。有關驅動程序電
+		源管理問題相對全面的概述,請參閱
+		Documentation/driver-api/pm/devices.rst。
+
+管理:		如果一個驅動程序的作者還在進行有效的維護,那麼通常除了那
+		些明顯正確且不需要任何檢查的補丁以外,其他所有的補丁都會
+		被轉發給作者。如果你希望成爲驅動程序的聯繫人和更新者,最
+		好在代碼注釋中寫明並且在 MAINTAINERS 文件中加入這個驅動
+		程序的條目。
+
+不影響設備驅動能否被接受的條件
+------------------------------
+
+供應商:	由硬體供應商來維護驅動程序通常是一件好事。不過,如果源碼
+		樹里已經有其他人提供了可穩定工作的驅動程序,那麼請不要期
+		望「我是供應商」會成爲內核改用你的驅動程序的理由。理想的情
+		況是:供應商與現有驅動程序的作者合作,構建一個統一完美的
+		驅動程序。
+
+作者:		驅動程序是由大的 Linux 公司研發還是由你個人編寫,並不影
+		響其是否能被內核接受。沒有人對內核源碼樹享有特權。只要你
+		充分了解內核社區,你就會發現這一點。
+
+
+資源列表
+--------
+
+Linux 內核主源碼樹:
+	ftp.??.kernel.org:/pub/linux/kernel/...
+	?? == 你的國家代碼,例如 "cn"、"us"、"uk"、"fr" 等等
+
+Linux 內核郵件列表:
+	linux-kernel@vger.kernel.org
+	[可通過向majordomo@vger.kernel.org發郵件來訂閱]
+
+Linux 設備驅動程序,第三版(探討 2.6.10 版內核):
+	https://lwn.net/Kernel/LDD3/ (免費版)
+
+LWN.net:
+	每周內核開發活動摘要 - https://lwn.net/
+
+	2.6 版中 API 的變更:
+
+		https://lwn.net/Articles/2.6-kernel-api/
+
+	將舊版內核的驅動程序移植到 2.6 版:
+
+		https://lwn.net/Articles/driver-porting/
+
+內核新手(KernelNewbies):
+	爲新的內核開發者提供文檔和幫助
+	https://kernelnewbies.org/
+
+Linux USB項目:
+	http://www.linux-usb.org/
+
+寫內核驅動的「不要」(Arjan van de Ven著):
+	http://www.fenrus.org/how-to-not-write-a-device-driver-paper.pdf
+
+內核清潔工 (Kernel Janitor):
+	https://kernelnewbies.org/KernelJanitors
+
diff --git a/Documentation/translations/zh_TW/process/submitting-patches.rst b/Documentation/translations/zh_TW/process/submitting-patches.rst
new file mode 100644
index 000000000000..cdf0b52e4a98
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/submitting-patches.rst
@@ -0,0 +1,686 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _tw_submittingpatches:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/submitting-patches.rst <submittingpatches>`
+
+譯者::
+
+        中文版維護者: 鍾宇 TripleX Chung <xxx.phy@gmail.com>
+        中文版翻譯者: 鍾宇 TripleX Chung <xxx.phy@gmail.com>
+                       時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+        中文版校譯者: 李陽 Li Yang <leoyang.li@nxp.com>
+                       王聰 Wang Cong <xiyou.wangcong@gmail.com>
+                       胡皓文 Hu Haowen <src.res@email.cn>
+
+
+如何讓你的改動進入內核
+======================
+
+對於想要將改動提交到 Linux 內核的個人或者公司來說,如果不熟悉「規矩」,
+提交的流程會讓人畏懼。本文檔收集了一系列建議,這些建議可以大大的提高你
+的改動被接受的機會.
+
+以下文檔含有大量簡潔的建議, 具體請見:
+:ref:`Documentation/process <development_process_main>`
+同樣,:ref:`Documentation/translations/zh_TW/process/submit-checklist.rst <tw_submitchecklist>`
+給出在提交代碼前需要檢查的項目的列表。如果你在提交一個驅動程序,那麼
+同時閱讀一下:
+:ref:`Documentation/process/submitting-drivers.rst <submittingdrivers>`
+
+其中許多步驟描述了Git版本控制系統的默認行爲;如果您使用Git來準備補丁,
+您將發現它爲您完成的大部分機械工作,儘管您仍然需要準備和記錄一組合理的
+補丁。一般來說,使用git將使您作爲內核開發人員的生活更輕鬆。
+
+
+0) 獲取當前源碼樹
+-----------------
+
+如果您沒有一個可以使用當前內核原始碼的存儲庫,請使用git獲取一個。您將要
+從主線存儲庫開始,它可以通過以下方式獲取::
+
+        git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
+
+但是,請注意,您可能不希望直接針對主線樹進行開發。大多數子系統維護人員運
+行自己的樹,並希望看到針對這些樹準備的補丁。請參見MAINTAINERS文件中子系
+統的 **T:** 項以查找該樹,或者簡單地詢問維護者該樹是否未在其中列出。
+
+仍然可以通過tarballs下載內核版本(如下一節所述),但這是進行內核開發的
+一種困難的方式。
+
+1) "diff -up"
+-------------
+
+使用 "diff -up" 或者 "diff -uprN" 來創建補丁。
+
+所有內核的改動,都是以補丁的形式呈現的,補丁由 diff(1) 生成。創建補丁的
+時候,要確認它是以 "unified diff" 格式創建的,這種格式由 diff(1) 的 '-u'
+參數生成。而且,請使用 '-p' 參數,那樣會顯示每個改動所在的C函數,使得
+產生的補丁容易讀得多。補丁應該基於內核原始碼樹的根目錄,而不是裡邊的任
+何子目錄。
+
+爲一個單獨的文件創建補丁,一般來說這樣做就夠了::
+
+        SRCTREE=linux
+        MYFILE=drivers/net/mydriver.c
+
+        cd $SRCTREE
+        cp $MYFILE $MYFILE.orig
+        vi $MYFILE      # make your change
+        cd ..
+        diff -up $SRCTREE/$MYFILE{.orig,} > /tmp/patch
+
+爲多個文件創建補丁,你可以解開一個沒有修改過的內核原始碼樹,然後和你自
+己的代碼樹之間做 diff 。例如::
+
+        MYSRC=/devel/linux
+
+        tar xvfz linux-3.19.tar.gz
+        mv linux-3.19 linux-3.19-vanilla
+        diff -uprN -X linux-3.19-vanilla/Documentation/dontdiff \
+                linux-3.19-vanilla $MYSRC > /tmp/patch
+
+"dontdiff" 是內核在編譯的時候產生的文件的列表,列表中的文件在 diff(1)
+產生的補丁里會被跳過。
+
+確定你的補丁里沒有包含任何不屬於這次補丁提交的額外文件。記得在用diff(1)
+生成補丁之後,審閱一次補丁,以確保準確。
+
+如果你的改動很散亂,你應該研究一下如何將補丁分割成獨立的部分,將改動分
+割成一系列合乎邏輯的步驟。這樣更容易讓其他內核開發者審核,如果你想你的
+補丁被接受,這是很重要的。請參閱:
+:ref:`tw_split_changes`
+
+如果你用 ``git`` , ``git rebase -i`` 可以幫助你這一點。如果你不用 ``git``,
+``quilt`` <https://savannah.nongnu.org/projects/quilt> 另外一個流行的選擇。
+
+.. _tw_describe_changes:
+
+2) 描述你的改動
+---------------
+
+描述你的問題。無論您的補丁是一行錯誤修復還是5000行新功能,都必須有一個潛在
+的問題激勵您完成這項工作。讓審稿人相信有一個問題值得解決,讓他們讀完第一段
+是有意義的。
+
+描述用戶可見的影響。直接崩潰和鎖定是相當有說服力的,但並不是所有的錯誤都那麼
+明目張胆。即使在代碼審查期間發現了這個問題,也要描述一下您認爲它可能對用戶產
+生的影響。請記住,大多數Linux安裝運行的內核來自二級穩定樹或特定於供應商/產品
+的樹,只從上游精選特定的補丁,因此請包含任何可以幫助您將更改定位到下游的內容:
+觸發的場景、DMESG的摘錄、崩潰描述、性能回歸、延遲尖峯、鎖定等。
+
+量化優化和權衡。如果您聲稱在性能、內存消耗、堆棧占用空間或二進位大小方面有所
+改進,請包括支持它們的數字。但也要描述不明顯的成本。優化通常不是免費的,而是
+在CPU、內存和可讀性之間進行權衡;或者,探索性的工作,在不同的工作負載之間進
+行權衡。請描述優化的預期缺點,以便審閱者可以權衡成本和收益。
+
+一旦問題建立起來,就要詳細地描述一下您實際在做什麼。對於審閱者來說,用簡單的
+英語描述代碼的變化是很重要的,以驗證代碼的行爲是否符合您的意願。
+
+如果您將補丁描述寫在一個表單中,這個表單可以很容易地作爲「提交日誌」放入Linux
+的原始碼管理系統git中,那麼維護人員將非常感謝您。見 :ref:`tw_explicit_in_reply_to`.
+
+每個補丁只解決一個問題。如果你的描述開始變長,這就表明你可能需要拆分你的補丁。
+請見 :ref:`tw_split_changes`
+
+提交或重新提交修補程序或修補程序系列時,請包括完整的修補程序說明和理由。不要
+只說這是補丁(系列)的第幾版。不要期望子系統維護人員引用更早的補丁版本或引用
+URL來查找補丁描述並將其放入補丁中。也就是說,補丁(系列)及其描述應該是獨立的。
+這對維護人員和審查人員都有好處。一些評審者可能甚至沒有收到補丁的早期版本。
+
+描述你在命令語氣中的變化,例如「make xyzzy do frotz」而不是「[這個補丁]make
+xyzzy do frotz」或「[我]changed xyzzy to do frotz」,就好像你在命令代碼庫改變
+它的行爲一樣。
+
+如果修補程序修復了一個記錄的bug條目,請按編號和URL引用該bug條目。如果補丁來
+自郵件列表討論,請給出郵件列表存檔的URL;使用帶有 ``Message-ID`` 的
+https://lkml.kernel.org/ 重定向,以確保連結不會過時。
+
+但是,在沒有外部資源的情況下,儘量讓你的解釋可理解。除了提供郵件列表存檔或
+bug的URL之外,還要總結需要提交補丁的相關討論要點。
+
+如果您想要引用一個特定的提交,不要只引用提交的 SHA-1 ID。還請包括提交的一行
+摘要,以便於審閱者了解它是關於什麼的。例如::
+
+        Commit e21d2170f36602ae2708 ("video: remove unnecessary
+        platform_set_drvdata()") removed the unnecessary
+        platform_set_drvdata(), but left the variable "dev" unused,
+        delete it.
+
+您還應該確保至少使用前12位 SHA-1 ID. 內核存儲庫包含*許多*對象,使與較短的ID
+發生衝突的可能性很大。記住,即使現在不會與您的六個字符ID發生衝突,這種情況
+可能五年後改變。
+
+如果修補程序修復了特定提交中的錯誤,例如,使用 ``git bisct`` ,請使用帶有前
+12個字符SHA-1 ID 的"Fixes:"標記和單行摘要。爲了簡化不要將標記拆分爲多個,
+行、標記不受分析腳本「75列換行」規則的限制。例如::
+
+        Fixes: 54a4f0239f2e ("KVM: MMU: make kvm_mmu_zap_page() return the number of pages it actually freed")
+
+下列 ``git config`` 設置可以添加讓 ``git log``, ``git show`` 漂亮的顯示格式::
+
+	[core]
+		abbrev = 12
+	[pretty]
+		fixes = Fixes: %h (\"%s\")
+
+.. _tw_split_changes:
+
+3) 拆分你的改動
+---------------
+
+將每個邏輯更改分隔成一個單獨的補丁。
+
+例如,如果你的改動里同時有bug修正和性能優化,那麼把這些改動拆分到兩個或
+者更多的補丁文件中。如果你的改動包含對API的修改,並且修改了驅動程序來適
+應這些新的API,那麼把這些修改分成兩個補丁。
+
+另一方面,如果你將一個單獨的改動做成多個補丁文件,那麼將它們合併成一個
+單獨的補丁文件。這樣一個邏輯上單獨的改動只被包含在一個補丁文件里。
+
+如果有一個補丁依賴另外一個補丁來完成它的改動,那沒問題。簡單的在你的補
+丁描述里指出「這個補丁依賴某補丁」就好了。
+
+在將您的更改劃分爲一系列補丁時,要特別注意確保內核在系列中的每個補丁之後
+都能正常構建和運行。使用 ``git bisect`` 來追蹤問題的開發者可能會在任何時
+候分割你的補丁系列;如果你在中間引入錯誤,他們不會感謝你。
+
+如果你不能將補丁濃縮成更少的文件,那麼每次大約發送出15個,然後等待審查
+和集成。
+
+4) 檢查你的更改風格
+-------------------
+
+檢查您的補丁是否存在基本樣式衝突,詳細信息可在
+:ref:`Documentation/translations/zh_TW/process/coding-style.rst <tw_codingstyle>`
+中找到。如果不這樣做,只會浪費審稿人的時間,並且會導致你的補丁被拒絕,甚至
+可能沒有被閱讀。
+
+一個重要的例外是在將代碼從一個文件移動到另一個文件時——在這種情況下,您不應
+該在移動代碼的同一個補丁中修改移動的代碼。這清楚地描述了移動代碼和您的更改
+的行爲。這大大有助於審查實際差異,並允許工具更好地跟蹤代碼本身的歷史。
+
+在提交之前,使用補丁樣式檢查程序檢查補丁(scripts/check patch.pl)。不過,
+請注意,樣式檢查程序應該被視爲一個指南,而不是作爲人類判斷的替代品。如果您
+的代碼看起來更好,但有違規行爲,那麼最好不要使用它。
+
+檢查者報告三個級別:
+
+ - ERROR:很可能出錯的事情
+ - WARNING:需要仔細審查的事項
+ - CHECK:需要思考的事情
+
+您應該能夠判斷您的補丁中存在的所有違規行爲。
+
+5) 選擇補丁收件人
+-----------------
+
+您應該總是在任何補丁上複製相應的子系統維護人員,以獲得他們維護的代碼;查看
+維護人員文件和原始碼修訂歷史記錄,以了解這些維護人員是誰。腳本
+scripts/get_Maintainer.pl在這個步驟中非常有用。如果您找不到正在工作的子系統
+的維護人員,那麼Andrew Morton(akpm@linux-foundation.org)將充當最後的維護
+人員。
+
+您通常還應該選擇至少一個郵件列表來接收補丁集的。linux-kernel@vger.kernel.org
+作爲最後一個解決辦法的列表,但是這個列表上的體積已經引起了許多開發人員的拒絕。
+在MAINTAINERS文件中查找子系統特定的列表;您的補丁可能會在那裡得到更多的關注。
+不過,請不要發送垃圾郵件到無關的列表。
+
+許多與內核相關的列表託管在vger.kernel.org上;您可以在
+http://vger.kernel.org/vger-lists.html 上找到它們的列表。不過,也有與內核相關
+的列表託管在其他地方。
+
+不要一次發送超過15個補丁到vger郵件列表!!!!
+
+Linus Torvalds 是決定改動能否進入 Linux 內核的最終裁決者。他的 e-mail
+地址是 <torvalds@linux-foundation.org> 。他收到的 e-mail 很多,所以一般
+的說,最好別給他發 e-mail。
+
+如果您有修復可利用安全漏洞的補丁,請將該補丁發送到 security@kernel.org。對於
+嚴重的bug,可以考慮短期暫停以允許分銷商向用戶發布補丁;在這種情況下,顯然不應
+將補丁發送到任何公共列表。
+
+修復已發布內核中嚴重錯誤的補丁程序應該指向穩定版維護人員,方法是放這樣的一行::
+
+        Cc: stable@vger.kernel.org
+
+進入補丁的簽准區(注意,不是電子郵件收件人)。除了這個文件之外,您還應該閱讀
+:ref:`Documentation/process/stable-kernel-rules.rst <stable_kernel_rules>`
+
+但是,請注意,一些子系統維護人員希望得出他們自己的結論,即哪些補丁應該被放到
+穩定的樹上。尤其是網絡維護人員,不希望看到單個開發人員在補丁中添加像上面這樣
+的行。
+
+如果更改影響到用戶和內核接口,請向手冊頁維護人員(如維護人員文件中所列)發送
+手冊頁補丁,或至少發送更改通知,以便一些信息進入手冊頁。還應將用戶空間API
+更改複製到 linux-api@vger.kernel.org。
+
+對於小的補丁,你也許會CC到搜集瑣碎補丁的郵件列表(Trivial Patch Monkey)
+trivial@kernel.org,那裡專門收集瑣碎的補丁。下面這樣的補丁會被看作「瑣碎的」
+補丁:
+
+ - 文檔的拼寫修正。
+ - 修正會影響到 grep(1) 的拼寫。
+ - 警告信息修正(頻繁的列印無用的警告是不好的。)
+ - 編譯錯誤修正(代碼邏輯的確是對的,只是編譯有問題。)
+ - 運行時修正(只要真的修正了錯誤。)
+ - 移除使用了被廢棄的函數/宏的代碼(例如 check_region。)
+ - 聯繫方式和文檔修正。
+ - 用可移植的代碼替換不可移植的代碼(即使在體系結構相關的代碼中,既然有
+ - 人拷貝,只要它是瑣碎的)
+ - 任何文件的作者/維護者對該文件的改動(例如 patch monkey 在重傳模式下)
+
+(譯註,關於「瑣碎補丁」的一些說明:因爲原文的這一部分寫得比較簡單,所以不得不
+違例寫一下譯註。"trivial"這個英文單詞的本意是「瑣碎的,不重要的。」但是在這裡
+有稍微有一些變化,例如對一些明顯的NULL指針的修正,屬於運行時修正,會被歸類
+到瑣碎補丁里。雖然NULL指針的修正很重要,但是這樣的修正往往很小而且很容易得到
+檢驗,所以也被歸入瑣碎補丁。瑣碎補丁更精確的歸類應該是
+「simple, localized & easy to verify」,也就是說簡單的,局部的和易於檢驗的。
+trivial@kernel.org郵件列表的目的是針對這樣的補丁,爲提交者提供一個中心,來
+降低提交的門檻。)
+
+6) 沒有 MIME 編碼,沒有連結,沒有壓縮,沒有附件,只有純文本
+-----------------------------------------------------------
+
+Linus 和其他的內核開發者需要閱讀和評論你提交的改動。對於內核開發者來說
+,可以「引用」你的改動很重要,使用一般的 e-mail 工具,他們就可以在你的
+代碼的任何位置添加評論。
+
+因爲這個原因,所有的提交的補丁都是 e-mail 中「內嵌」的。
+
+.. warning::
+   如果你使用剪切-粘貼你的補丁,小心你的編輯器的自動換行功能破壞你的補丁
+
+不要將補丁作爲 MIME 編碼的附件,不管是否壓縮。很多流行的 e-mail 軟體不
+是任何時候都將 MIME 編碼的附件當作純文本發送的,這會使得別人無法在你的
+代碼中加評論。另外,MIME 編碼的附件會讓 Linus 多花一點時間來處理,這就
+降低了你的改動被接受的可能性。
+
+例外:如果你的郵遞員弄壞了補丁,那麼有人可能會要求你使用mime重新發送補丁
+
+請參閱 :ref:`Documentation/translations/zh_TW/process/email-clients.rst <tw_email_clients>`
+以獲取有關配置電子郵件客戶端以使其不受影響地發送修補程序的提示。
+
+7) e-mail 的大小
+----------------
+
+大的改動對郵件列表不合適,對某些維護者也不合適。如果你的補丁,在不壓縮
+的情況下,超過了300kB,那麼你最好將補丁放在一個能通過 internet 訪問的服
+務器上,然後用指向你的補丁的 URL 替代。但是請注意,如果您的補丁超過了
+300kb,那麼它幾乎肯定需要被破壞。
+
+8)回複評審意見
+---------------
+
+你的補丁幾乎肯定會得到評審者對補丁改進方法的評論。您必須對這些評論作出
+回應;讓補丁被忽略的一個好辦法就是忽略審閱者的意見。不會導致代碼更改的
+意見或問題幾乎肯定會帶來注釋或變更日誌的改變,以便下一個評審者更好地了解
+正在發生的事情。
+
+一定要告訴審稿人你在做什麼改變,並感謝他們的時間。代碼審查是一個累人且
+耗時的過程,審查人員有時會變得暴躁。即使在這種情況下,也要禮貌地回應並
+解決他們指出的問題。
+
+9)不要洩氣或不耐煩
+-------------------
+
+提交更改後,請耐心等待。審閱者是忙碌的人,可能無法立即訪問您的修補程序。
+
+曾幾何時,補丁曾在沒有評論的情況下消失在空白中,但開發過程比現在更加順利。
+您應該在一周左右的時間內收到評論;如果沒有收到評論,請確保您已將補丁發送
+到正確的位置。在重新提交或聯繫審閱者之前至少等待一周-在諸如合併窗口之類的
+繁忙時間可能更長。
+
+10)主題中包含 PATCH
+--------------------
+
+由於到linus和linux內核的電子郵件流量很高,通常會在主題行前面加上[PATCH]
+前綴. 這使Linus和其他內核開發人員更容易將補丁與其他電子郵件討論區分開。
+
+11)簽署你的作品-開發者原始認證
+-------------------------------
+
+爲了加強對誰做了何事的追蹤,尤其是對那些透過好幾層的維護者的補丁,我們
+建議在發送出去的補丁上加一個 「sign-off」 的過程。
+
+"sign-off" 是在補丁的注釋的最後的簡單的一行文字,認證你編寫了它或者其他
+人有權力將它作爲開放原始碼的補丁傳遞。規則很簡單:如果你能認證如下信息:
+
+開發者來源證書 1.1
+^^^^^^^^^^^^^^^^^^
+
+對於本項目的貢獻,我認證如下信息:
+
+      (a)這些貢獻是完全或者部分的由我創建,我有權利以文件中指出
+           的開放原始碼許可證提交它;或者
+      (b)這些貢獻基於以前的工作,據我所知,這些以前的工作受恰當的開放
+           原始碼許可證保護,而且,根據許可證,我有權提交修改後的貢獻,
+           無論是完全還是部分由我創造,這些貢獻都使用同一個開放原始碼許可證
+           (除非我被允許用其它的許可證),正如文件中指出的;或者
+      (c)這些貢獻由認證(a),(b)或者(c)的人直接提供給我,而
+           且我沒有修改它。
+      (d)我理解並同意這個項目和貢獻是公開的,貢獻的記錄(包括我
+           一起提交的個人記錄,包括 sign-off )被永久維護並且可以和這個項目
+           或者開放原始碼的許可證同步地再發行。
+
+那麼加入這樣一行::
+
+       Signed-off-by: Random J Developer <random@developer.example.org>
+
+使用你的真名(抱歉,不能使用假名或者匿名。)
+
+有人在最後加上標籤。現在這些東西會被忽略,但是你可以這樣做,來標記公司
+內部的過程,或者只是指出關於 sign-off 的一些特殊細節。
+
+如果您是子系統或分支維護人員,有時需要稍微修改收到的補丁,以便合併它們,
+因爲樹和提交者中的代碼不完全相同。如果你嚴格遵守規則(c),你應該要求提交者
+重新發布,但這完全是在浪費時間和精力。規則(b)允許您調整代碼,但是更改一個
+提交者的代碼並讓他認可您的錯誤是非常不禮貌的。要解決此問題,建議在最後一個
+由簽名行和您的行之間添加一行,指示更改的性質。雖然這並不是強制性的,但似乎
+在描述前加上您的郵件和/或姓名(全部用方括號括起來),這足以讓人注意到您對最
+後一分鐘的更改負有責任。例如::
+
+	Signed-off-by: Random J Developer <random@developer.example.org>
+	[lucky@maintainer.example.org: struct foo moved from foo.c to foo.h]
+	Signed-off-by: Lucky K Maintainer <lucky@maintainer.example.org>
+
+如果您維護一個穩定的分支機構,同時希望對作者進行致謝、跟蹤更改、合併修復並
+保護提交者不受投訴,那麼這種做法尤其有用。請注意,在任何情況下都不能更改作者
+的ID(From 頭),因爲它是出現在更改日誌中的標識。
+
+對回合(back-porters)的特別說明:在提交消息的頂部(主題行之後)插入一個補丁
+的起源指示似乎是一種常見且有用的實踐,以便於跟蹤。例如,下面是我們在3.x穩定
+版本中看到的內容::
+
+  Date:   Tue Oct 7 07:26:38 2014 -0400
+
+    libata: Un-break ATA blacklist
+
+    commit 1c40279960bcd7d52dbdf1d466b20d24b99176c8 upstream.
+
+還有, 這裡是一個舊版內核中的一個回合補丁::
+
+    Date:   Tue May 13 22:12:27 2008 +0200
+
+        wireless, airo: waitbusy() won't delay
+
+        [backport of 2.6 commit b7acbdfbd1f277c1eb23f344f899cfa4cd0bf36a]
+
+12)何時使用Acked-by:,CC:,和Co-Developed by:
+----------------------------------------------
+
+Singed-off-by: 標記表示簽名者參與了補丁的開發,或者他/她在補丁的傳遞路徑中。
+
+如果一個人沒有直接參與補丁的準備或處理,但希望表示並記錄他們對補丁的批准,
+那麼他們可以要求在補丁的變更日誌中添加一個 Acked-by:
+
+Acked-by:通常由受影響代碼的維護者使用,當該維護者既沒有貢獻也沒有轉發補丁時。
+
+Acked-by: 不像簽字人那樣正式。這是一個記錄,確認人至少審查了補丁,並表示接受。
+因此,補丁合併有時會手動將Acker的「Yep,looks good to me」轉換爲 Acked-By:(但
+請注意,通常最好要求一個明確的Ack)。
+
+Acked-by:不一定表示對整個補丁的確認。例如,如果一個補丁影響多個子系統,並且
+有一個:來自一個子系統維護者,那麼這通常表示只確認影響維護者代碼的部分。這裡
+應該仔細判斷。如有疑問,應參考郵件列表檔案中的原始討論。
+
+如果某人有機會對補丁進行評論,但沒有提供此類評論,您可以選擇在補丁中添加 ``Cc:``
+這是唯一一個標籤,它可以在沒有被它命名的人顯式操作的情況下添加,但它應該表明
+這個人是在補丁上抄送的。討論中包含了潛在利益相關方。
+
+Co-developed-by: 聲明補丁是由多個開發人員共同創建的;當幾個人在一個補丁上工
+作時,它用於將屬性賦予共同作者(除了 From: 所賦予的作者之外)。因爲
+Co-developed-by: 表示作者身份,所以每個共同開發人:必須緊跟在相關合作作者的
+簽名之後。標準的簽核程序要求:標記的簽核順序應儘可能反映補丁的時間歷史,而不
+管作者是通過 From :還是由 Co-developed-by: 共同開發的。值得注意的是,最後一
+個簽字人:必須始終是提交補丁的開發人員。
+
+注意,當作者也是電子郵件標題「發件人:」行中列出的人時,「From: 」 標記是可選的。
+
+作者提交的補丁程序示例::
+
+	<changelog>
+
+	Co-developed-by: First Co-Author <first@coauthor.example.org>
+	Signed-off-by: First Co-Author <first@coauthor.example.org>
+	Co-developed-by: Second Co-Author <second@coauthor.example.org>
+	Signed-off-by: Second Co-Author <second@coauthor.example.org>
+	Signed-off-by: From Author <from@author.example.org>
+
+合作開發者提交的補丁示例::
+
+	From: From Author <from@author.example.org>
+
+	<changelog>
+
+	Co-developed-by: Random Co-Author <random@coauthor.example.org>
+	Signed-off-by: Random Co-Author <random@coauthor.example.org>
+	Signed-off-by: From Author <from@author.example.org>
+	Co-developed-by: Submitting Co-Author <sub@coauthor.example.org>
+	Signed-off-by: Submitting Co-Author <sub@coauthor.example.org>
+
+
+13)使用報告人:、測試人:、審核人:、建議人:、修復人:
+--------------------------------------------------------
+
+Reported-by: 給那些發現錯誤並報告錯誤的人致謝,它希望激勵他們在將來再次幫助
+我們。請注意,如果bug是以私有方式報告的,那麼在使用Reported-by標記之前,請
+先請求權限。
+
+Tested-by: 標記表示補丁已由指定的人(在某些環境中)成功測試。這個標籤通知
+維護人員已經執行了一些測試,爲將來的補丁提供了一種定位測試人員的方法,並確
+保測試人員的信譽。
+
+Reviewed-by:相反,根據審查人的聲明,表明該補丁已被審查並被認爲是可接受的:
+
+
+審查人的監督聲明
+^^^^^^^^^^^^^^^^
+
+通過提供我的 Reviewed-by,我聲明:
+
+        (a) 我已經對這個補丁進行了一次技術審查,以評估它是否適合被包含到
+            主線內核中。
+
+        (b) 與補丁相關的任何問題、顧慮或問題都已反饋給提交者。我對提交者對
+            我的評論的回應感到滿意。
+
+        (c) 雖然這一提交可能會改進一些東西,但我相信,此時,(1)對內核
+            進行了有價值的修改,(2)沒有包含爭論中涉及的已知問題。
+
+        (d) 雖然我已經審查了補丁並認爲它是健全的,但我不會(除非另有明確
+            說明)作出任何保證或保證它將在任何給定情況下實現其規定的目的
+            或正常運行。
+
+Reviewed-by 是一種觀點聲明,即補丁是對內核的適當修改,沒有任何遺留的嚴重技術
+問題。任何感興趣的審閱者(完成工作的人)都可以爲一個補丁提供一個 Review-by
+標籤。此標籤用於向審閱者提供致謝,並通知維護者已在修補程序上完成的審閱程度。
+Reviewed-by: 當由已知了解主題區域並執行徹底檢查的審閱者提供時,通常會增加
+補丁進入內核的可能性。
+
+Suggested-by: 表示補丁的想法是由指定的人提出的,並確保將此想法歸功於指定的
+人。請注意,未經許可,不得添加此標籤,特別是如果該想法未在公共論壇上發布。
+這就是說,如果我們勤快地致謝我們的創意者,他們很有希望在未來得到鼓舞,再次
+幫助我們。
+
+Fixes: 指示補丁在以前的提交中修復了一個問題。它可以很容易地確定錯誤的來源,
+這有助於檢查錯誤修復。這個標記還幫助穩定內核團隊確定應該接收修復的穩定內核
+版本。這是指示補丁修復的錯誤的首選方法。請參閱 :ref:`tw_describe_changes`
+描述您的更改以了解更多詳細信息。
+
+.. _tw_the_canonical_patch_format:
+
+12)標準補丁格式
+----------------
+
+本節描述如何格式化補丁本身。請注意,如果您的補丁存儲在 ``Git`` 存儲庫中,則
+可以使用 ``git format-patch`` 進行正確的補丁格式設置。但是,這些工具無法創建
+必要的文本,因此請務必閱讀下面的說明。
+
+標準的補丁,標題行是::
+
+    Subject: [PATCH 001/123] 子系統:一句話概述
+
+標準補丁的信體存在如下部分:
+
+  - 一個 "from" 行指出補丁作者。後跟空行(僅當發送修補程序的人不是作者時才需要)。
+
+  - 解釋的正文,行以75列包裝,這將被複製到永久變更日誌來描述這個補丁。
+
+  - 一個空行
+
+  - 上面描述的「Signed-off-by」 行,也將出現在更改日誌中。
+
+  - 只包含 ``---`` 的標記線。
+
+  - 任何其他不適合放在變更日誌的注釋。
+
+  - 實際補丁( ``diff`` 輸出)。
+
+標題行的格式,使得對標題行按字母序排序非常的容易 - 很多 e-mail 客戶端都
+可以支持 - 因爲序列號是用零填充的,所以按數字排序和按字母排序是一樣的。
+
+e-mail 標題中的「子系統」標識哪個內核子系統將被打補丁。
+
+e-mail 標題中的「一句話概述」扼要的描述 e-mail 中的補丁。「一句話概述」
+不應該是一個文件名。對於一個補丁系列(「補丁系列」指一系列的多個相關補
+丁),不要對每個補丁都使用同樣的「一句話概述」。
+
+記住 e-mail 的「一句話概述」會成爲該補丁的全局唯一標識。它會蔓延到 git
+的改動記錄里。然後「一句話概述」會被用在開發者的討論里,用來指代這個補
+丁。用戶將希望通過 google 來搜索"一句話概述"來找到那些討論這個補丁的文
+章。當人們在兩三個月後使用諸如 ``gitk`` 或 ``git log --oneline`` 之類
+的工具查看數千個補丁時,也會很快看到它。
+
+出於這些原因,概述必須不超過70-75個字符,並且必須描述補丁的更改以及爲
+什麼需要補丁。既要簡潔又要描述性很有挑戰性,但寫得好的概述應該這樣做。
+
+概述的前綴可以用方括號括起來:「Subject: [PATCH <tag>...] <概述>」。標記
+不被視爲概述的一部分,而是描述應該如何處理補丁。如果補丁的多個版本已發
+送出來以響應評審(即「v1,v2,v3」)或「rfc」,以指示評審請求,那麼通用標記
+可能包括版本描述符。如果一個補丁系列中有四個補丁,那麼各個補丁可以這樣
+編號:1/4、2/4、3/4、4/4。這可以確保開發人員了解補丁應用的順序,並且他們
+已經查看或應用了補丁系列中的所有補丁。
+
+一些標題的例子::
+
+    Subject: [patch 2/5] ext2: improve scalability of bitmap searching
+    Subject: [PATCHv2 001/207] x86: fix eflags tracking
+
+"From" 行是信體裡的最上面一行,具有如下格式:
+        From: Patch Author <author@example.com>
+
+"From" 行指明在永久改動日誌里,誰會被確認爲作者。如果沒有 "From" 行,那
+麼郵件頭裡的 "From: " 行會被用來決定改動日誌中的作者。
+
+說明的主題將會被提交到永久的原始碼改動日誌里,因此對那些早已經不記得和
+這個補丁相關的討論細節的有能力的讀者來說,是有意義的。包括補丁程序定位
+錯誤的(內核日誌消息、OOPS消息等)症狀,對於搜索提交日誌以尋找適用補丁的人
+尤其有用。如果一個補丁修復了一個編譯失敗,那麼可能不需要包含所有編譯失敗;
+只要足夠讓搜索補丁的人能夠找到它就行了。與概述一樣,既要簡潔又要描述性。
+
+"---" 標記行對於補丁處理工具要找到哪裡是改動日誌信息的結束,是不可缺少
+的。
+
+對於 "---" 標記之後的額外註解,一個好的用途就是用來寫 diffstat,用來顯
+示修改了什麼文件和每個文件都增加和刪除了多少行。diffstat 對於比較大的補
+丁特別有用。其餘那些只是和時刻或者開發者相關的註解,不合適放到永久的改
+動日誌里的,也應該放這裡。
+使用 diffstat的選項 "-p 1 -w 70" 這樣文件名就會從內核原始碼樹的目錄開始
+,不會占用太寬的空間(很容易適合80列的寬度,也許會有一些縮進。)
+
+在後面的參考資料中能看到適當的補丁格式的更多細節。
+
+.. _tw_explicit_in_reply_to:
+
+15) 明確回覆郵件頭(In-Reply-To)
+-------------------------------
+
+手動添加回復補丁的的標題頭(In-Reply_To:) 是有幫助的(例如,使用 ``git send-email`` )
+將補丁與以前的相關討論關聯起來,例如,將bug修復程序連結到電子郵件和bug報告。
+但是,對於多補丁系列,最好避免在回復時使用連結到該系列的舊版本。這樣,
+補丁的多個版本就不會成爲電子郵件客戶端中無法管理的引用序列。如果連結有用,
+可以使用 https://lkml.kernel.org/ 重定向器(例如,在封面電子郵件文本中)
+連結到補丁系列的早期版本。
+
+16) 發送git pull請求
+--------------------
+
+如果您有一系列補丁,那麼讓維護人員通過git pull操作將它們直接拉入子系統存儲
+庫可能是最方便的。但是,請注意,從開發人員那裡獲取補丁比從郵件列表中獲取補
+丁需要更高的信任度。因此,許多子系統維護人員不願意接受請求,特別是來自新的
+未知開發人員的請求。如果有疑問,您可以在封面郵件中使用pull 請求作爲補丁系列
+正常發布的一個選項,讓維護人員可以選擇使用其中之一。
+
+pull 請求的主題行中應該有[Git Pull]。請求本身應該在一行中包含存儲庫名稱和
+感興趣的分支;它應該看起來像::
+
+  Please pull from
+
+      git://jdelvare.pck.nerim.net/jdelvare-2.6 i2c-for-linus
+
+  to get these changes:
+
+
+pull 請求還應該包含一條整體消息,說明請求中將包含什麼,一個補丁本身的 ``Git shortlog``
+以及一個顯示補丁系列整體效果的 ``diffstat`` 。當然,將所有這些信息收集在一起
+的最簡單方法是讓 ``git`` 使用 ``git request-pull`` 命令爲您完成這些工作。
+
+一些維護人員(包括Linus)希望看到來自已簽名提交的請求;這增加了他們對你的
+請求信心。特別是,在沒有簽名標籤的情況下,Linus 不會從像 Github 這樣的公共
+託管站點拉請求。
+
+創建此類簽名的第一步是生成一個 GNRPG 密鑰,並由一個或多個核心內核開發人員對
+其進行簽名。這一步對新開發人員來說可能很困難,但沒有辦法繞過它。參加會議是
+找到可以簽署您的密鑰的開發人員的好方法。
+
+一旦您在Git 中準備了一個您希望有人拉的補丁系列,就用 ``git tag -s`` 創建一
+個簽名標記。這將創建一個新標記,標識該系列中的最後一次提交,並包含用您的私
+鑰創建的簽名。您還可以將changelog樣式的消息添加到標記中;這是一個描述拉請求
+整體效果的理想位置。
+
+如果維護人員將要從中提取的樹不是您正在使用的存儲庫,請不要忘記將已簽名的標記
+顯式推送到公共樹。
+
+生成拉請求時,請使用已簽名的標記作爲目標。這樣的命令可以實現::
+
+  git request-pull master git://my.public.tree/linux.git my-signed-tag
+
+參考文獻
+--------
+
+Andrew Morton, "The perfect patch" (tpp).
+  <https://www.ozlabs.org/~akpm/stuff/tpp.txt>
+
+Jeff Garzik, "Linux kernel patch submission format".
+  <https://web.archive.org/web/20180829112450/http://linux.yyz.us/patch-format.html>
+
+Greg Kroah-Hartman, "How to piss off a kernel subsystem maintainer".
+  <http://www.kroah.com/log/linux/maintainer.html>
+
+  <http://www.kroah.com/log/linux/maintainer-02.html>
+
+  <http://www.kroah.com/log/linux/maintainer-03.html>
+
+  <http://www.kroah.com/log/linux/maintainer-04.html>
+
+  <http://www.kroah.com/log/linux/maintainer-05.html>
+
+  <http://www.kroah.com/log/linux/maintainer-06.html>
+
+NO!!!! No more huge patch bombs to linux-kernel@vger.kernel.org people!
+  <https://lore.kernel.org/r/20050711.125305.08322243.davem@davemloft.net>
+
+Kernel Documentation/process/coding-style.rst:
+  :ref:`Documentation/translations/zh_TW/process/coding-style.rst <tw_codingstyle>`
+
+Linus Torvalds's mail on the canonical patch format:
+  <https://lore.kernel.org/r/Pine.LNX.4.58.0504071023190.28951@ppc970.osdl.org>
+
+Andi Kleen, "On submitting kernel patches"
+  Some strategies to get difficult or controversial changes in.
+
+  http://halobates.de/on-submitting-patches.pdf
+
diff --git a/Documentation/translations/zh_TW/process/volatile-considered-harmful.rst b/Documentation/translations/zh_TW/process/volatile-considered-harmful.rst
new file mode 100644
index 000000000000..097fe80352cb
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/volatile-considered-harmful.rst
@@ -0,0 +1,110 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _tw_volatile_considered_harmful:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/volatile-considered-harmful.rst
+           <volatile_considered_harmful>`
+
+如果想評論或更新本文的內容,請直接聯繫原文檔的維護者。如果你使用英文
+交流有困難的話,也可以向中文版維護者求助。如果本翻譯更新不及時或者翻
+譯存在問題,請聯繫中文版維護者::
+
+        英文版維護者: Jonathan Corbet <corbet@lwn.net>
+        中文版維護者: 伍鵬  Bryan Wu <bryan.wu@analog.com>
+        中文版翻譯者: 伍鵬  Bryan Wu <bryan.wu@analog.com>
+        中文版校譯者: 張漢輝  Eugene Teo <eugeneteo@kernel.sg>
+                       楊瑞  Dave Young <hidave.darkstar@gmail.com>
+                       時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+                       胡皓文 Hu Haowen <src.res@email.cn>
+
+爲什麼不應該使用「volatile」類型
+================================
+
+C程式設計師通常認爲volatile表示某個變量可以在當前執行的線程之外被改變;因此,在內核
+中用到共享數據結構時,常常會有C程式設計師喜歡使用volatile這類變量。換句話說,他們經
+常會把volatile類型看成某種簡易的原子變量,當然它們不是。在內核中使用volatile幾
+乎總是錯誤的;本文檔將解釋爲什麼這樣。
+
+理解volatile的關鍵是知道它的目的是用來消除優化,實際上很少有人真正需要這樣的應
+用。在內核中,程式設計師必須防止意外的並發訪問破壞共享的數據結構,這其實是一個完全
+不同的任務。用來防止意外並發訪問的保護措施,可以更加高效的避免大多數優化相關的
+問題。
+
+像volatile一樣,內核提供了很多原語來保證並發訪問時的數據安全(自旋鎖, 互斥量,內
+存屏障等等),同樣可以防止意外的優化。如果可以正確使用這些內核原語,那麼就沒有
+必要再使用volatile。如果仍然必須使用volatile,那麼幾乎可以肯定在代碼的某處有一
+個bug。在正確設計的內核代碼中,volatile能帶來的僅僅是使事情變慢。
+
+思考一下這段典型的內核代碼::
+
+    spin_lock(&the_lock);
+    do_something_on(&shared_data);
+    do_something_else_with(&shared_data);
+    spin_unlock(&the_lock);
+
+如果所有的代碼都遵循加鎖規則,當持有the_lock的時候,不可能意外的改變shared_data的
+值。任何可能訪問該數據的其他代碼都會在這個鎖上等待。自旋鎖原語跟內存屏障一樣—— 它
+們顯式的用來書寫成這樣 —— 意味著數據訪問不會跨越它們而被優化。所以本來編譯器認爲
+它知道在shared_data裡面將有什麼,但是因爲spin_lock()調用跟內存屏障一樣,會強制編
+譯器忘記它所知道的一切。那麼在訪問這些數據時不會有優化的問題。
+
+如果shared_data被聲名爲volatile,鎖操作將仍然是必須的。就算我們知道沒有其他人正在
+使用它,編譯器也將被阻止優化對臨界區內shared_data的訪問。在鎖有效的同時,
+shared_data不是volatile的。在處理共享數據的時候,適當的鎖操作可以不再需要
+volatile —— 並且是有潛在危害的。
+
+volatile的存儲類型最初是爲那些內存映射的I/O寄存器而定義。在內核里,寄存器訪問也應
+該被鎖保護,但是人們也不希望編譯器「優化」臨界區內的寄存器訪問。內核里I/O的內存訪問
+是通過訪問函數完成的;不贊成通過指針對I/O內存的直接訪問,並且不是在所有體系架構上
+都能工作。那些訪問函數正是爲了防止意外優化而寫的,因此,再說一次,volatile類型不
+是必需的。
+
+另一種引起用戶可能使用volatile的情況是當處理器正忙著等待一個變量的值。正確執行一
+個忙等待的方法是::
+
+    while (my_variable != what_i_want)
+        cpu_relax();
+
+cpu_relax()調用會降低CPU的能量消耗或者讓位於超線程雙處理器;它也作爲內存屏障一樣出
+現,所以,再一次,volatile不是必需的。當然,忙等待一開始就是一種反常規的做法。
+
+在內核中,一些稀少的情況下volatile仍然是有意義的:
+
+  - 在一些體系架構的系統上,允許直接的I/0內存訪問,那麼前面提到的訪問函數可以使用
+    volatile。基本上,每一個訪問函數調用它自己都是一個小的臨界區域並且保證了按照
+    程式設計師期望的那樣發生訪問操作。
+
+  - 某些會改變內存的內聯彙編代碼雖然沒有什麼其他明顯的附作用,但是有被GCC刪除的可
+    能性。在彙編聲明中加上volatile關鍵字可以防止這種刪除操作。
+
+  - Jiffies變量是一種特殊情況,雖然每次引用它的時候都可以有不同的值,但讀jiffies
+    變量時不需要任何特殊的加鎖保護。所以jiffies變量可以使用volatile,但是不贊成
+    其他跟jiffies相同類型變量使用volatile。Jiffies被認爲是一種「愚蠢的遺留物"
+    (Linus的話)因爲解決這個問題比保持現狀要麻煩的多。
+
+  - 由於某些I/0設備可能會修改連續一致的內存,所以有時,指向連續一致內存的數據結構
+    的指針需要正確的使用volatile。網絡適配器使用的環狀緩存區正是這類情形的一個例
+    子,其中適配器用改變指針來表示哪些描述符已經處理過了。
+
+對於大多代碼,上述幾種可以使用volatile的情況都不適用。所以,使用volatile是一種
+bug並且需要對這樣的代碼額外仔細檢查。那些試圖使用volatile的開發人員需要退一步想想
+他們真正想實現的是什麼。
+
+非常歡迎刪除volatile變量的補丁 - 只要證明這些補丁完整的考慮了並發問題。
+
+注釋
+----
+
+[1] https://lwn.net/Articles/233481/
+[2] https://lwn.net/Articles/233482/
+
+致謝
+----
+
+最初由Randy Dunlap推動並作初步研究
+由Jonathan Corbet撰寫
+參考Satyam Sharma,Johannes Stezenbach,Jesper Juhl,Heikki Orsila,
+H. Peter Anvin,Philipp Hahn和Stefan Richter的意見改善了本檔。
+
-- 
2.25.1


^ permalink raw reply related	[relevance 1%]

* [PATCH v3 2/4] docs/zh_TW: add translations for zh_TW/process
  @ 2021-07-03 14:31  1% ` Hu Haowen
  0 siblings, 0 replies; 200+ results
From: Hu Haowen @ 2021-07-03 14:31 UTC (permalink / raw)
  To: corbet; +Cc: linux-doc, linux-kernel

Create new translations for zh_TW/process and link them to index.

Signed-off-by: Hu Haowen <src.res@email.cn>
---
 Documentation/translations/zh_TW/index.rst    |  10 +-
 .../translations/zh_TW/process/1.Intro.rst    | 197 ++++
 .../translations/zh_TW/process/2.Process.rst  | 367 +++++++
 .../zh_TW/process/3.Early-stage.rst           | 170 ++++
 .../translations/zh_TW/process/4.Coding.rst   | 295 ++++++
 .../translations/zh_TW/process/5.Posting.rst  | 249 +++++
 .../zh_TW/process/6.Followthrough.rst         | 154 +++
 .../zh_TW/process/7.AdvancedTopics.rst        | 135 +++
 .../zh_TW/process/8.Conclusion.rst            |  72 ++
 .../code-of-conduct-interpretation.rst        | 110 ++
 .../zh_TW/process/code-of-conduct.rst         |  74 ++
 .../zh_TW/process/coding-style.rst            | 956 ++++++++++++++++++
 .../zh_TW/process/development-process.rst     |  28 +
 .../zh_TW/process/email-clients.rst           | 250 +++++
 .../process/embargoed-hardware-issues.rst     | 230 +++++
 .../translations/zh_TW/process/howto.rst      | 498 +++++++++
 .../translations/zh_TW/process/index.rst      |  65 ++
 .../zh_TW/process/kernel-driver-statement.rst | 201 ++++
 .../process/kernel-enforcement-statement.rst  | 153 +++
 .../zh_TW/process/license-rules.rst           | 372 +++++++
 .../zh_TW/process/magic-number.rst            | 146 +++
 .../zh_TW/process/management-style.rst        | 209 ++++
 .../zh_TW/process/programming-language.rst    |  74 ++
 .../zh_TW/process/stable-api-nonsense.rst     | 157 +++
 .../zh_TW/process/stable-kernel-rules.rst     |  66 ++
 .../zh_TW/process/submit-checklist.rst        | 107 ++
 .../zh_TW/process/submitting-drivers.rst      | 162 +++
 .../zh_TW/process/submitting-patches.rst      | 684 +++++++++++++
 .../process/volatile-considered-harmful.rst   | 108 ++
 29 files changed, 6295 insertions(+), 4 deletions(-)
 create mode 100644 Documentation/translations/zh_TW/process/1.Intro.rst
 create mode 100644 Documentation/translations/zh_TW/process/2.Process.rst
 create mode 100644 Documentation/translations/zh_TW/process/3.Early-stage.rst
 create mode 100644 Documentation/translations/zh_TW/process/4.Coding.rst
 create mode 100644 Documentation/translations/zh_TW/process/5.Posting.rst
 create mode 100644 Documentation/translations/zh_TW/process/6.Followthrough.rst
 create mode 100644 Documentation/translations/zh_TW/process/7.AdvancedTopics.rst
 create mode 100644 Documentation/translations/zh_TW/process/8.Conclusion.rst
 create mode 100644 Documentation/translations/zh_TW/process/code-of-conduct-interpretation.rst
 create mode 100644 Documentation/translations/zh_TW/process/code-of-conduct.rst
 create mode 100644 Documentation/translations/zh_TW/process/coding-style.rst
 create mode 100644 Documentation/translations/zh_TW/process/development-process.rst
 create mode 100644 Documentation/translations/zh_TW/process/email-clients.rst
 create mode 100644 Documentation/translations/zh_TW/process/embargoed-hardware-issues.rst
 create mode 100644 Documentation/translations/zh_TW/process/howto.rst
 create mode 100644 Documentation/translations/zh_TW/process/index.rst
 create mode 100644 Documentation/translations/zh_TW/process/kernel-driver-statement.rst
 create mode 100644 Documentation/translations/zh_TW/process/kernel-enforcement-statement.rst
 create mode 100644 Documentation/translations/zh_TW/process/license-rules.rst
 create mode 100644 Documentation/translations/zh_TW/process/magic-number.rst
 create mode 100644 Documentation/translations/zh_TW/process/management-style.rst
 create mode 100644 Documentation/translations/zh_TW/process/programming-language.rst
 create mode 100644 Documentation/translations/zh_TW/process/stable-api-nonsense.rst
 create mode 100644 Documentation/translations/zh_TW/process/stable-kernel-rules.rst
 create mode 100644 Documentation/translations/zh_TW/process/submit-checklist.rst
 create mode 100644 Documentation/translations/zh_TW/process/submitting-drivers.rst
 create mode 100644 Documentation/translations/zh_TW/process/submitting-patches.rst
 create mode 100644 Documentation/translations/zh_TW/process/volatile-considered-harmful.rst

diff --git a/Documentation/translations/zh_TW/index.rst b/Documentation/translations/zh_TW/index.rst
index cab58e428825..76981b2111f6 100644
--- a/Documentation/translations/zh_TW/index.rst
+++ b/Documentation/translations/zh_TW/index.rst
@@ -22,9 +22,7 @@
 下面的文檔介紹了Linux內核原始碼的許可證(GPLv2)、如何在原始碼樹中正確標記
 單個文件的許可證、以及指向完整許可證文本的連結。
 
-TODOList:
-
-* Documentation/translations/zh_TW/process/license-rules.rst
+Documentation/translations/zh_TW/process/license-rules.rst
 
 用戶文檔
 --------
@@ -67,9 +65,13 @@ TODOlist:
 開發人員做出貢獻。與任何大型社區一樣,知道如何完成任務將使得更改合併的過程
 變得更加容易。
 
+.. toctree::
+   :maxdepth: 2
+
+   process/index
+
 TODOList:
 
-* process/index
 * dev-tools/index
 * doc-guide/index
 * kernel-hacking/index
diff --git a/Documentation/translations/zh_TW/process/1.Intro.rst b/Documentation/translations/zh_TW/process/1.Intro.rst
new file mode 100644
index 000000000000..a1207ef153d7
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/1.Intro.rst
@@ -0,0 +1,197 @@
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/1.Intro.rst <development_process_intro>`
+
+:Translator:
+
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+
+:校譯:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+.. _tw_development_process_intro:
+
+引言
+====
+
+內容提要
+--------
+
+本節的其餘部分涵蓋了內核開發的過程,以及開發人員及其僱主在這方面可能遇到的
+各種問題。有很多原因使內核代碼應被合併到正式的(「主線」)內核中,包括對用戶
+的自動可用性、多種形式的社區支持以及影響內核開發方向的能力。提供給Linux內核
+的代碼必須在與GPL兼容的許可證下可用。
+
+:ref:`tw_development_process` 介紹了開發過程、內核發布周期和合併窗口的機制。
+涵蓋了補丁開發、審查和合併周期中的各個階段。還有一些關於工具和郵件列表的討論?
+鼓勵希望開始內核開發的開發人員跟蹤並修復缺陷以作爲初步練習。
+
+
+:ref:`tw_development_early_stage` 包括項目的早期規劃,重點是儘快讓開發社區
+參與進來。
+
+:ref:`tw_development_coding` 是關於編程過程的;介紹了其他開發人員遇到的幾個
+陷阱。也涵蓋了對補丁的一些要求,並且介紹了一些工具,這些工具有助於確保內核
+補丁是正確的。
+
+:ref:`tw_development_posting` 描述發布補丁以供評審的過程。爲了讓開發社區能
+認真對待,補丁必須被正確格式化和描述,並且必須發送到正確的地方。遵循本節中的
+建議有助於確保您的工作能被較好地接納。
+
+:ref:`tw_development_followthrough` 介紹了發布補丁之後發生的事情;工作在這時
+還遠遠沒有完成。與審閱者一起工作是開發過程中的一個重要部分;本節提供了一些
+關於如何在這個重要階段避免問題的提示。當補丁被合併到主線中時,開發人員要注意
+不要假定任務已經完成。
+
+:ref:`tw_development_advancedtopics` 介紹了兩個「高級」主題:使用Git管理補丁
+和查看其他人發布的補丁。
+
+:ref:`tw_development_conclusion` 總結了有關內核開發的更多信息,附帶有相關資源
+連結。
+
+這個文檔是關於什麼的
+--------------------
+
+Linux內核有超過800萬行代碼,每個版本的貢獻者超過1000人,是現存最大、最活躍的
+免費軟體項目之一。從1991年開始,這個內核已經發展成爲一個最好的作業系統組件,
+運行在袖珍數位音樂播放器、桌上型電腦、現存最大的超級計算機以及所有類型的系統上。
+它是一種適用於幾乎任何情況的健壯、高效和可擴展的解決方案。
+
+隨著Linux的發展,希望參與其開發的開發人員(和公司)的數量也在增加。硬體供應商
+希望確保Linux能夠很好地支持他們的產品,使這些產品對Linux用戶具有吸引力。嵌入
+式系統供應商使用Linux作爲集成產品的組件,希望Linux能夠儘可能地勝任手頭的任務。
+分銷商和其他基於Linux的軟體供應商切實關心Linux內核的功能、性能和可靠性。最終
+用戶也常常希望修改Linux,使之能更好地滿足他們的需求。
+
+Linux最引人注目的特性之一是這些開發人員可以訪問它;任何具備必要技能的人都可以
+改進Linux並影響其開發方向。專有產品不能提供這種開放性,這是自由軟體的一個特點。
+如果有什麼不同的話,那就是內核比大多數其他自由軟體項目更開放。一個典型的三個
+月內核開發周期可以涉及1000多個開發人員,他們爲100多個不同的公司(或者根本不
+隸屬公司)工作。
+
+與內核開發社區合作並不是特別困難。但儘管如此,仍有許多潛在的貢獻者在嘗試做
+內核工作時遇到了困難。內核社區已經發展出自己獨特的操作方式,使其能夠在每天
+都要更改數千行代碼的環境中順利運行(並生成高質量的產品)。因此,Linux內核開發
+過程與專有的開發模式有很大的不同也就不足爲奇了。
+
+對於新開發人員來說,內核的開發過程可能會讓人感到奇怪和恐懼,但這背後有充分的
+理由和堅實的經驗。一個不了解內核社區工作方式的開發人員(或者更糟的是,他們
+試圖拋棄或規避之)會得到令人沮喪的體驗。開發社區在幫助那些試圖學習的人的同時,
+沒有時間幫助那些不願意傾聽或不關心開發過程的人。
+
+希望閱讀本文的人能夠避免這種令人沮喪的經歷。這些材料很長,但閱讀它們時所做的
+努力會在短時間內得到回報。開發社區總是需要能讓內核變更好的開發人員;下面的
+文字應該幫助您或爲您工作的人員加入我們的社區。
+
+致謝
+----
+
+本文檔由Jonathan Corbet <corbet@lwn.net> 撰寫。以下人員的建議使之更爲完善:
+Johannes Berg, James Berry, Alex Chiang, Roland Dreier, Randy Dunlap,
+Jake Edge, Jiri Kosina, Matt Mackall, Arthur Marsh, Amanda McPherson,
+Andrew Morton, Andrew Price, Tsugikazu Shibata 和 Jochen Voß 。
+
+這項工作得到了Linux基金會的支持,特別感謝Amanda McPherson,他看到了這項工作
+的價值並將其變成現實。
+
+代碼進入主線的重要性
+--------------------
+
+有些公司和開發人員偶爾會想,爲什麼他們要費心學習如何與內核社區合作,並將代碼
+放入主線內核(「主線」是由Linus Torvalds維護的內核,Linux發行商將其用作基礎)。
+在短期內,貢獻代碼看起來像是一種可以避免的開銷;維護獨立代碼並直接支持用戶
+似乎更容易。事實上,保持代碼獨立(「樹外」)是在經濟上是錯誤的。
+
+爲了說明樹外代碼成本,下面給出內核開發過程的一些相關方面;本文稍後將更詳細地
+討論其中的大部分內容。請考慮:
+
+- 所有Linux用戶都可以使用合併到主線內核中的代碼。它將自動出現在所有啓用它的
+  發行版上。無需驅動程序磁碟、額外下載,也不需要爲多個發行版的多個版本提供
+  支持;這一切將方便所有開發人員和用戶。併入主線解決了大量的分發和支持問題。
+
+- 當內核開發人員努力維護一個穩定的用戶空間接口時,內核內部API處於不斷變化之中。
+  不維持穩定的內部接口是一個慎重的設計決策;它允許在任何時候進行基本的改進,
+  並產出更高質量的代碼。但該策略導致結果是,若要使用新的內核,任何樹外代碼都
+  需要持續的維護。維護樹外代碼會需要大量的工作才能使代碼保持正常運行。
+
+  相反,位於主線中的代碼不需要這樣做,因爲基本規則要求進行API更改的任何開發
+  人員也必須修復由於該更改而破壞的任何代碼。因此,合併到主線中的代碼大大降低
+  了維護成本。
+
+- 除此之外,內核中的代碼通常會被其他開發人員改進。您授權的用戶社區和客戶對您
+  產品的改進可能會令人驚喜。
+
+- 內核代碼在合併到主線之前和之後都要經過審查。無論原始開發人員的技能有多強,
+  這個審查過程總是能找到改進代碼的方法。審查經常發現嚴重的錯誤和安全問題。
+  對於在封閉環境中開發的代碼尤其如此;這種代碼從外部開發人員的審查中獲益匪淺。
+  樹外代碼是低質量代碼。
+
+- 參與開發過程是您影響內核開發方向的方式。旁觀者的抱怨會被聽到,但是活躍的
+  開發人員有更強的聲音——並且能夠實現使內核更好地滿足其需求的更改。
+
+- 當單獨維護代碼時,總是存在第三方爲類似功能提供不同實現的可能性。如果發生
+  這種情況,合併代碼將變得更加困難——甚至成爲不可能。之後,您將面臨以下令人
+  不快的選擇:(1)無限期地維護樹外的非標準特性,或(2)放棄代碼並將用戶遷移
+  到樹內版本。
+
+- 代碼的貢獻是使整個流程工作的根本。通過貢獻代碼,您可以向內核添加新功能,並
+  提供其他內核開發人員使用的功能和示例。如果您已經爲Linux開發了代碼(或者正在
+  考慮這樣做),那麼您顯然對這個平台的持續成功感興趣;貢獻代碼是確保成功的
+  最好方法之一。
+
+上述所有理由都適用於任何樹外內核代碼,包括以專有的、僅二進位形式分發的代碼。
+然而,在考慮任何類型的純二進位內核代碼分布之前,還需要考慮其他因素。包括:
+
+- 圍繞專有內核模塊分發的法律問題其實較爲模糊;相當多的內核版權所有者認爲,
+  大多數僅二進位的模塊是內核的派生產品,因此,它們的分發違反了GNU通用公共
+  許可證(下面將詳細介紹)。本文作者不是律師,本文檔中的任何內容都不可能被
+  視爲法律建議。封閉原始碼模塊的真實法律地位只能由法院決定。但不管怎樣,困擾
+  這些模塊的不確定性仍然存在。
+
+- 二進位模塊大大增加了調試內核問題的難度,以至於大多數內核開發人員甚至都不會
+  嘗試。因此,只分發二進位模塊將使您的用戶更難從社區獲得支持。
+
+- 對於僅二進位的模塊的發行者來說,支持也更加困難,他們必須爲他們希望支持的
+  每個發行版和每個內核版本提供不同版本的模塊。爲了提供較爲全面的覆蓋範圍,
+  可能需要一個模塊的幾十個構建,並且每次升級內核時,您的用戶都必須單獨升級
+  這些模塊。
+
+- 上面提到的關於代碼評審的所有問題都更加存在於封閉原始碼中。由於該代碼根本
+  不可得,因此社區無法對其進行審查,毫無疑問,它將存在嚴重問題。
+
+尤其是嵌入式系統的製造商,可能會傾向於忽視本節中所說的大部分內容;因爲他們
+相信自己正在商用一種使用凍結內核版本的獨立產品,在發布後不需要再進行開發。
+這個論點忽略了廣泛的代碼審查的價值以及允許用戶向產品添加功能的價值。但這些
+產品的商業壽命有限,之後必須發布新版本的產品。在這一點上,代碼在主線上並得到
+良好維護的供應商將能夠更好地占位,以使新產品快速上市。
+
+許可
+----
+
+代碼是根據一些許可證提供給Linux內核的,但是所有代碼都必須與GNU通用公共許可
+證(GPLV2)的版本2兼容,該版本是覆蓋整個內核分發的許可證。在實踐中,這意味
+著所有代碼貢獻都由GPLv2(可選地,語言允許在更高版本的GPL下分發)或3子句BSD
+許可(New BSD License,譯者注)覆蓋。任何不包含在兼容許可證中的貢獻都不會
+被接受到內核中。
+
+貢獻給內核的代碼不需要(或請求)版權分配。合併到主線內核中的所有代碼都保留
+其原始所有權;因此,內核現在擁有數千個所有者。
+
+這種所有權結構也暗示著,任何改變內核許可的嘗試都註定會失敗。很少有實際情況
+可以獲得所有版權所有者的同意(或者從內核中刪除他們的代碼)。因此,尤其是在
+可預見的將來,許可證不大可能遷移到GPL的版本3。
+
+所有貢獻給內核的代碼都必須是合法的免費軟體。因此,不接受匿名(或化名)貢獻
+者的代碼。所有貢獻者都需要在他們的代碼上「sign off(簽發)」,聲明代碼可以
+在GPL下與內核一起分發。無法提供未被其所有者許可爲免費軟體的代碼,或可能爲
+內核造成版權相關問題的代碼(例如,由缺乏適當保護的反向工程工作派生的代碼)
+不能被接受。
+
+有關版權問題的提問在Linux開發郵件列表中很常見。這樣的問題通常會得到不少答案,
+但請記住,回答這些問題的人不是律師,不能提供法律諮詢。如果您有關於Linux原始碼
+的法律問題,沒有什麼可以代替諮詢了解這一領域的律師。依賴從技術郵件列表中獲得
+的答案是一件冒險的事情。
+
+
diff --git a/Documentation/translations/zh_TW/process/2.Process.rst b/Documentation/translations/zh_TW/process/2.Process.rst
new file mode 100644
index 000000000000..b71629cdc11a
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/2.Process.rst
@@ -0,0 +1,367 @@
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/2.Process.rst <development_process>`
+
+:Translator:
+
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+
+:校譯:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+.. _tw_development_process:
+
+開發流程如何進行
+================
+
+90年代早期的Linux內核開發是一件相當鬆散的事情,涉及的用戶和開發人員相對較少。
+由於擁有數以百萬計的用戶羣,且每年有大約2000名開發人員參與進來,內核因此必須
+發展出許多既定流程來保證開發的順利進行。要參與到流程中來,需要對此流程的進行
+方式有一個紮實的理解。
+
+總覽
+----
+
+內核開發人員使用一個鬆散的基於時間的發布過程,每兩到三個月發布一次新的主要
+內核版本。最近的發布歷史記錄如下:
+
+	======  =================
+	5.0	2019年3月3日
+	5.1	2019年5月5日
+	5.2	2019年7月7日
+	5.3	2019年9月15日
+	5.4	2019年11月24日
+	5.5	2020年1月6日
+	======  =================
+
+每個5.x版本都是一個主要的內核版本,具有新特性、內部API更改等等。一個典型的5.x
+版本包含大約13000個變更集,變更了幾十萬行代碼。因此,5.x是Linux內核開發的前
+沿;內核使用滾動開發模型,不斷集成重大變化。
+
+對於每個版本的補丁合併,遵循一個相對簡單的規則。在每個開發周期的開頭,「合併
+窗口」被打開。這時,被認爲足夠穩定(並且被開發社區接受)的代碼被合併到主線內
+核中。在這段時間內,新開發周期的大部分變更(以及所有主要變更)將以接近每天
+1000次變更(「補丁」或「變更集」)的速度合併。
+
+(順便說一句,值得注意的是,合併窗口期間集成的更改並不是憑空產生的;它們是經
+提前收集、測試和分級的。稍後將詳細描述該過程的工作方式。)
+
+合併窗口持續大約兩周。在這段時間結束時,LinusTorvalds將聲明窗口已關閉,並
+釋放第一個「rc」內核。例如,對於目標爲5.6的內核,在合併窗口結束時發生的釋放
+將被稱爲5.6-rc1。-rc1 版本是一個信號,表示合併新特性的時間已經過去,穩定下一
+個內核的時間已經到來。
+
+在接下來的6到10周內,只有修復問題的補丁才應該提交給主線。有時會允許更大的
+更改,但這種情況很少發生;試圖在合併窗口外合併新功能的開發人員往往受不到
+友好的接待。一般來說,如果您錯過了給定特性的合併窗口,最好的做法是等待下一
+個開發周期。(偶爾會對未支持硬體的驅動程序進行例外;如果它們不改變已有代碼,
+則不會導致回歸,應該可以隨時被安全地加入)。
+
+隨著修復程序進入主線,補丁速度將隨著時間的推移而變慢。Linus大約每周發布一次
+新的-rc內核;在內核被認爲足夠穩定並最終發布前,一般會達到-rc6到-rc9之間。
+然後,整個過程又重新開始了。
+
+例如,這裡是5.4的開發周期進行情況(2019年):
+
+	==============  ==============================
+	九月 15         5.3 穩定版發布
+	九月 30         5.4-rc1 合併窗口關閉
+	十月 6          5.4-rc2
+	十月 13         5.4-rc3
+	十月 20         5.4-rc4
+	十月 27         5.4-rc5
+	十一月 3        5.4-rc6
+	十一月 10       5.4-rc7
+	十一月 17       5.4-rc8
+	十一月 24       5.4 穩定版發布
+	==============  ==============================
+
+開發人員如何決定何時結束開發周期並創建穩定版本?最重要的指標是以前版本的
+回歸列表。不歡迎出現任何錯誤,但是那些破壞了以前能工作的系統的錯誤被認爲是
+特別嚴重的。因此,導致回歸的補丁是不受歡迎的,很可能在穩定期內刪除。
+
+開發人員的目標是在穩定發布之前修復所有已知的回歸。在現實世界中,這種完美是
+很難實現的;在這種規模的項目中,變數太多了。需要說明的是,延遲最終版本只會
+使問題變得更糟;等待下一個合併窗口的更改將變多,導致下次出現更多的回歸錯誤。
+因此,大多數5.x內核都有一些已知的回歸錯誤,不過,希望沒有一個是嚴重的。
+
+一旦一個穩定的版本發布,它的持續維護工作就被移交給「穩定團隊」,目前由
+Greg Kroah-Hartman領導。穩定團隊將使用5.x.y編號方案不定期地發布穩定版本的
+更新。要合入更新版本,補丁必須(1)修復一個重要的缺陷,且(2)已經合併到
+下一個開發版本主線中。內核通常會在其初始版本後的一個以上的開發周期內收到
+穩定版更新。例如,5.2內核的歷史如下(2019年):
+
+	==============  ===============================
+        七月 7 	        5.2 穩定版發布
+	七月 13	        5.2.1
+	七月 21	        5.2.2
+	七月 26	        5.2.3
+	七月 28	        5.2.4
+	七月 31	        5.2.5
+	...	        ...
+	十月 11         5.2.21
+	==============  ===============================
+
+5.2.21是5.2版本的最終穩定更新。
+
+有些內核被指定爲「長期」內核;它們將得到更長時間的支持。在本文中,當前的長期
+內核及其維護者是:
+
+	======  ================================	================
+	3.16	Ben Hutchings				(長期穩定內核)
+	4.4	Greg Kroah-Hartman & Sasha Levin	(長期穩定內核)
+	4.9	Greg Kroah-Hartman & Sasha Levin
+	4.14	Greg Kroah-Hartman & Sasha Levin
+	4.19	Greg Kroah-Hartman & Sasha Levin
+	5.4	Greg Kroah-Hartman & Sasha Levin
+	======  ================================	================
+
+長期支持內核的選擇純粹是維護人員是否有需求和時間來維護該版本的問題。
+目前還沒有爲即將發布的任何特定版本提供長期支持的已知計劃。
+
+補丁的生命周期
+--------------
+
+補丁不會直接從開發人員的鍵盤進入主線內核。相反,有一個稍微複雜(如果有些非
+正式)的過程,旨在確保對每個補丁進行質量審查,並確保每個補丁實現了一個在主線
+中需要的更改。對於小的修復,這個過程可能會很快完成,,而對於較大或有爭議的
+變更,可能會持續數年。許多開發人員的沮喪來自於對這個過程缺乏理解或者試圖繞過它。
+
+爲了減少這種挫敗,本文將描述補丁如何進入內核。下面的介紹以一種較爲理想化的
+方式描述了這個過程。更詳細的過程將在後面的章節中介紹。
+
+補丁通常要經歷以下階段:
+
+- 設計。這就是補丁的真正需求——以及滿足這些需求的方式——所在。設計工作通常
+  是在不涉及社區的情況下完成的,但是如果可能的話,最好是在公開的情況下完成
+  這項工作;這樣可以節省很多稍後再重新設計的時間。
+
+- 早期評審。補丁被發布到相關的郵件列表中,列表中的開發人員會回復他們可能有
+  的任何評論。如果一切順利的話,這個過程應該會發現補丁的任何主要問題。
+
+- 更廣泛的評審。當補丁接近準備好納入主線時,它應該被相關的子系統維護人員
+  接受——儘管這種接受並不能保證補丁會一直延伸到主線。補丁將出現在維護人員的
+  子系統樹中,並進入 -next 樹(如下所述)。當流程進行時,此步驟將會對補丁
+  進行更廣泛的審查,並發現由於將此補丁與其他人所做的工作合併而導致的任何
+  問題。
+
+- 請注意,大多數維護人員也有日常工作,因此合併補丁可能不是他們的最優先工作。
+  如果您的補丁得到了需要更改的反饋,那麼您應該進行這些更改,或者解釋爲何
+  不應該進行這些更改。如果您的補丁沒有評審意見,也沒有被其相應的子系統或
+  驅動程序維護者接受,那麼您應該堅持不懈地將補丁更新到當前內核使其可被正常
+  應用,並不斷地發送它以供審查和合併。
+
+- 合併到主線。最終,一個成功的補丁將被合併到由LinusTorvalds管理的主線存儲庫
+  中。此時可能會出現更多的評論和/或問題;對開發人員來說應對這些問題並解決
+  出現的任何問題仍很重要。
+
+- 穩定版發布。大量用戶可能受此補丁影響,因此可能再次出現新的問題。
+
+- 長期維護。雖然開發人員在合併代碼後可能會忘記代碼,但這種行爲往往會給開發
+  社區留下不良印象。合併代碼消除了一些維護負擔,因爲其他人將修復由API更改
+  引起的問題。但是,如果代碼要長期保持可用,原始開發人員應該繼續爲代碼負責。
+
+內核開發人員(或他們的僱主)犯的最大錯誤之一是試圖將流程簡化爲一個「合併到
+主線」步驟。這種方法總是會讓所有相關人員感到沮喪。
+
+補丁如何進入內核
+----------------
+
+只有一個人可以將補丁合併到主線內核存儲庫中:LinusTorvalds。但是,在進入
+2.6.38內核的9500多個補丁中,只有112個(大約1.3%)是由Linus自己直接選擇的。
+內核項目已經發展到一個沒有一個開發人員可以在沒有支持的情況下檢查和選擇每個
+補丁的規模。內核開發人員處理這種增長的方式是使用圍繞信任鏈構建的助理系統。
+
+內核代碼庫在邏輯上被分解爲一組子系統:網絡、特定體系結構支持、內存管理、視
+頻設備等。大多數子系統都有一個指定的維護人員,其總體負責該子系統中的代碼。
+這些子系統維護者(鬆散地)是他們所管理的內核部分的「守門員」;他們(通常)
+會接受一個補丁以包含到主線內核中。
+
+子系統維護人員每個人都管理著自己版本的內核原始碼樹,通常(並非總是)使用Git。
+Git等工具(以及Quilt或Mercurial等相關工具)允許維護人員跟蹤補丁列表,包括作者
+信息和其他元數據。在任何給定的時間,維護人員都可以確定他或她的存儲庫中的哪
+些補丁在主線中找不到。
+
+當合併窗口打開時,頂級維護人員將要求Linus從存儲庫中「拉出」他們爲合併選擇
+的補丁。如果Linus同意,補丁流將流向他的存儲庫,成爲主線內核的一部分。
+Linus對拉取中接收到的特定補丁的關注程度各不相同。很明顯,有時他看起來很
+關注。但是一般來說,Linus相信子系統維護人員不會向上游發送壞補丁。
+
+子系統維護人員反過來也可以從其他維護人員那裡獲取補丁。例如,網絡樹是由首先
+在專用於網絡設備驅動程序、無線網絡等的樹中積累的補丁構建的。此存儲鏈可以
+任意長,但很少超過兩個或三個連結。由於鏈中的每個維護者都信任那些管理較低
+級別樹的維護者,所以這個過程稱爲「信任鏈」。
+
+顯然,在這樣的系統中,獲取內核補丁取決於找到正確的維護者。直接向Linus發送
+補丁通常不是正確的方法。
+
+Next 樹
+-------
+
+子系統樹鏈引導補丁流到內核,但它也提出了一個有趣的問題:如果有人想查看爲
+下一個合併窗口準備的所有補丁怎麼辦?開發人員將感興趣的是,還有什麼其他的
+更改有待解決,以了解是否存在需要擔心的衝突;例如,更改核心內核函數原型的
+修補程序將與使用該函數舊形式的任何其他修補程序衝突。審查人員和測試人員希望
+在所有這些變更到達主線內核之前,能夠訪問它們的集成形式的變更。您可以從所有
+相關的子系統樹中提取更改,但這將是一項複雜且容易出錯的工作。
+
+解決方案以-next樹的形式出現,在這裡子系統樹被收集以供測試和審查。這些樹中
+由Andrew Morton維護的較老的一個,被稱爲「-mm」(用於內存管理,創建時爲此)。
+-mm 樹集成了一長串子系統樹中的補丁;它還包含一些旨在幫助調試的補丁。
+
+除此之外,-mm 還包含大量由Andrew直接選擇的補丁。這些補丁可能已經發布在郵件
+列表上,或者它們可能應用於內核中未指定子系統樹的部分。同時,-mm 作爲最後
+手段的子系統樹;如果沒有其他明顯的路徑可以讓補丁進入主線,那麼它很可能最
+終選擇-mm 樹。累積在-mm 中的各種補丁最終將被轉發到適當的子系統樹,或者直接
+發送到Linus。在典型的開發周期中,大約5-10%的補丁通過-mm 進入主線。
+
+當前-mm 補丁可在「mmotm」(-mm of the moment)目錄中找到:
+
+        https://www.ozlabs.org/~akpm/mmotm/
+
+然而,使用MMOTM樹可能會十分令人頭疼;它甚至可能無法編譯。
+
+下一個周期補丁合併的主要樹是linux-next,由Stephen Rothwell 維護。根據設計
+linux-next 是下一個合併窗口關閉後主線的快照。linux-next樹在Linux-kernel 和
+Linux-next 郵件列表中發布,可從以下位置下載:
+
+        https://www.kernel.org/pub/linux/kernel/next/
+
+Linux-next 已經成爲內核開發過程中不可或缺的一部分;在一個給定的合併窗口中合併
+的所有補丁都應該在合併窗口打開之前的一段時間內找到進入Linux-next 的方法。
+
+Staging 樹
+----------
+
+內核原始碼樹包含drivers/staging/目錄,其中有許多驅動程序或文件系統的子目錄
+正在被添加到內核樹中。它們在仍然需要更多的修正的時候可以保留在driver/staging/
+目錄中;一旦完成,就可以將它們移到內核中。這是一種跟蹤不符合Linux內核編碼或
+質量標準的驅動程序的方法,人們可能希望使用它們並跟蹤開發。
+
+Greg Kroah Hartman 目前負責維護staging 樹。仍需要修正的驅動程序將發送給他,
+每個驅動程序在drivers/staging/中都有自己的子目錄。除了驅動程序源文件之外,
+目錄中還應該有一個TODO文件。TODO文件列出了驅動程序需要接受的暫停的工作,
+以及驅動程序的任何補丁都應該抄送的人員列表。當前的規則要求,staging的驅動
+程序必須至少正確編譯。
+
+Staging 是一種讓新的驅動程序進入主線的相對容易的方法,它們會幸運地引起其他
+開發人員的注意,並迅速改進。然而,進入staging並不是故事的結尾;staging中
+沒有看到常規進展的代碼最終將被刪除。經銷商也傾向於相對不願意使用staging驅動
+程序。因此,在成爲一個合適的主線驅動的路上,staging 僅是一個中轉站。
+
+工具
+----
+
+從上面的文本可以看出,內核開發過程在很大程度上依賴於在不同方向上聚集補丁的
+能力。如果沒有適當強大的工具,整個系統將無法在任何地方正常工作。關於如何使用
+這些工具的教程遠遠超出了本文檔的範圍,但還是用一點篇幅介紹一些關鍵點。
+
+到目前爲止,內核社區使用的主要原始碼管理系統是git。Git是在自由軟體社區中開發
+的許多分布式版本控制系統之一。它非常適合內核開發,因爲它在處理大型存儲庫和
+大量補丁時性能非常好。它也以難以學習和使用而著稱,儘管隨著時間的推移它變得
+更好了。對於內核開發人員來說,對Git的某種熟悉幾乎是一種要求;即使他們不將它
+用於自己的工作,他們也需要Git來跟上其他開發人員(以及主線)正在做的事情。
+
+現在幾乎所有的Linux發行版都打包了Git。Git主頁位於:
+
+        https://git-scm.com/
+
+此頁面包含了文檔和教程的連結。
+
+在不使用git的內核開發人員中,最流行的選擇幾乎肯定是Mercurial:
+
+        http://www.seleric.com/mercurial/
+
+Mercurial與Git共享許多特性,但它提供了一個界面,許多人覺得它更易於使用。
+
+另一個值得了解的工具是Quilt:
+
+        https://savannah.nongnu.org/projects/quilt
+
+Quilt 是一個補丁管理系統,而不是原始碼管理系統。它不會隨著時間的推移跟蹤歷史;
+相反,它面向根據不斷發展的代碼庫跟蹤一組特定的更改。一些主要的子系統維護人員
+使用Quilt來管理打算向上游移動的補丁。對於某些樹的管理(例如-mm),quilt 是
+最好的工具。
+
+郵件列表
+--------
+
+大量的Linux內核開發工作是通過郵件列表完成的。如果不加入至少一個某個列表,
+就很難成爲社區中的一個「全功能」成員。但是,Linux郵件列表對開發人員來說也是
+一個潛在的危險,他們可能會被一堆電子郵件淹沒、違反Linux列表上使用的約定,
+或者兩者兼而有之。
+
+大多數內核郵件列表都在vger.kernel.org上運行;主列表位於:
+
+        http://vger.kernel.org/vger-lists.html
+
+不過,也有一些列表託管在別處;其中一些列表位於
+redhat.com/mailman/listinfo。
+
+當然,內核開發的核心郵件列表是linux-kernel。這個列表是一個令人生畏的地方:
+每天的信息量可以達到500條,噪音很高,談話技術性很強,且參與者並不總是表現出
+高度的禮貌。但是,沒有其他地方可以讓內核開發社區作爲一個整體聚集在一起;
+不使用此列表的開發人員將錯過重要信息。
+
+以下一些提示可以幫助在linux-kernel生存:
+
+- 將郵件轉移到單獨的文件夾,而不是主郵箱文件夾。我們必須能夠持續地忽略洪流。
+
+- 不要試圖跟上每一次談話——沒人會這樣。重要的是要篩選感興趣的主題(但請注意
+  長時間的對話可能會偏離原來的主題,儘管未改變電子郵件的主題)和參與的人。
+
+- 不要回復挑事的人。如果有人試圖激起憤怒,請忽略他們。
+
+- 當回復Linux內核電子郵件(或其他列表上的電子郵件)時,請爲所有相關人員保留
+  Cc: 抄送頭。如果沒有確實的理由(如明確的請求),則不應刪除收件人。一定要
+  確保你要回復的人在抄送列表中。這個慣例也使你不必在回覆郵件時明確要求被抄送。
+
+- 在提出問題之前,搜索列表存檔(和整個網絡)。有些開發人員可能會對那些顯然
+  沒有完成家庭作業的人感到不耐煩。
+
+- 避免頂部回復(把你的答案放在你要回復的引文上面的做法)。這會讓你的回答更難
+  理解,印象也很差。
+
+- 在正確的郵件列表發問。linux-kernel 可能是通用的討論場所,但它不是尋找所有
+  子系統開發人員的最佳場所。
+
+最後一點——找到正確的郵件列表——是開發人員常出錯的地方。在linux-kernel上
+提出與網絡相關的問題的人幾乎肯定會收到一個禮貌的建議,轉到netdev列表上提出,
+因爲這是大多數網絡開發人員經常出現的列表。還有其他列表可用於scsi、video4linux、
+ide、filesystem等子系統。查找郵件列表的最佳位置是與內核原始碼一起打包的
+MAINTAINERS文件。
+
+開始內核開發
+------------
+
+關於如何開始內核開發過程的問題很常見——個人和公司皆然。同樣常見的是失誤,這
+使得關係的開始比本應的更困難。
+
+公司通常希望聘請知名的開發人員來啓動開發團隊。實際上,這是一種有效的技術。
+但它也往往是昂貴的,而且對增加有經驗的內核開發人員的數量沒有多大幫助。考
+慮到時間投入,可以讓內部開發人員加快Linux內核的開發速度。利用這段時間可以
+讓僱主擁有一批既了解內核又了解公司的開發人員,還可以幫助培訓其他人。從中期
+來看,這通常是更有利可圖的方法。
+
+可以理解的是,單個開發人員往往對起步感到茫然。從一個大型項目開始可能會很
+嚇人;人們往往想先用一些較小的東西來試試水。由此,一些開發人員開始創建修補
+拼寫錯誤或輕微編碼風格問題的補丁。不幸的是,這樣的補丁會產生一定程度的噪音,
+這會分散整個開發社區的注意力,因此,它們越來越被人不看重。希望向社區介紹
+自己的新開發人員將無法通過這些方式獲得他們期待的反響。
+
+Andrew Morton 爲有抱負的內核開發人員提供了如下建議
+
+::
+
+	所有內核開發者的第一個項目肯定應該是「確保內核在您可以操作的所有
+	機器上始終完美運行」。通常的方法是和其他人一起解決問題(這可能需
+	要堅持!),但就是如此——這是內核開發的一部分。
+
+(http://lwn.net/articles/283982/)
+
+在沒有明顯問題需要解決的情況下,通常建議開發人員查看當前的回歸和開放缺陷
+列表。從來都不缺少需要解決的問題;通過解決這些問題,開發人員將從該過程獲得
+經驗,同時與開發社區的其他成員建立相互尊重。
+
diff --git a/Documentation/translations/zh_TW/process/3.Early-stage.rst b/Documentation/translations/zh_TW/process/3.Early-stage.rst
new file mode 100644
index 000000000000..ce85990fc98e
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/3.Early-stage.rst
@@ -0,0 +1,170 @@
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/3.Early-stage.rst <development_early_stage>`
+
+:Translator:
+
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+
+:校譯:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+.. _tw_development_early_stage:
+
+早期規劃
+========
+
+當考慮一個Linux內核開發項目時,很可能會直接跳進去開始編碼。然而,與任何重要
+的項目一樣,許多成功的基礎最好是在第一行代碼編寫之前就打下。在早期計劃和
+溝通中花費一些時間可以在之後節省更多的時間。
+
+搞清問題
+--------
+
+與任何工程項目一樣,成功的內核改善從清晰描述要解決的問題開始。在某些情況
+下,這個步驟很容易:例如當某個特定硬體需要驅動程序時。不過,在其他情況下,
+很容易將實際問題與建議的解決方案混在一起,這可能會導致麻煩。
+
+舉個例子:幾年前,Linux音頻的開發人員尋求一種方法來運行應用程式,而不會因
+系統延遲過大而導致退出或其他問題。他們得到的解決方案是一個連接到Linux安全
+模塊(LSM)框架中的內核模塊;這個模塊可以配置爲允許特定的應用程式訪問實時
+調度程序。這個模塊被實現並發到linux-kernel郵件列表,在那裡它立即遇到了麻煩。
+
+對於音頻開發人員來說,這個安全模塊足以解決他們當前的問題。但是,對於更廣泛的
+內核社區來說,這被視爲對LSM框架的濫用(LSM框架並不打算授予他們原本不具備的
+進程特權),並對系統穩定性造成風險。他們首選的解決方案包括短期的通過rlimit
+機制進行實時調度訪問,以及長期的減少延遲的工作。
+
+然而,音頻社區無法超越他們實施的特定解決方案來看問題;他們不願意接受替代方案。
+由此產生的分歧使這些開發人員對整個內核開發過程感到失望;其中一個開發人員返回
+到audio列表並發布了以下內容:
+
+	有很多非常好的Linux內核開發人員,但他們往往會被一羣傲慢的傻瓜所壓倒。
+	試圖向這些人傳達用戶需求是浪費時間。他們太「聰明」了,根本聽不到少數
+	人的話。
+
+(http://lwn.net/articles/131776/)
+
+實際情況卻是不同的;與特定模塊相比,內核開發人員更關心系統穩定性、長期維護
+以及找到問題的正確解決方案。這個故事的寓意是把重點放在問題上——而不是具體的
+解決方案上——並在開始編寫代碼之前與開發社區討論這個問題。
+
+因此,在考慮一個內核開發項目時,我們應該得到一組簡短問題的答案:
+
+ - 需要解決的問題究竟是什麼?
+
+ - 受此問題影響的用戶有哪些?解決方案應該解決哪些使用案例?
+
+ - 內核現在爲何沒能解決這個問題?
+
+只有這樣,才能開始考慮可能的解決方案。
+
+
+早期討論
+--------
+
+在計劃內核開發項目時,在開始實施之前與社區進行討論是很有意義的。早期溝通可以
+通過多種方式節省時間和麻煩:
+
+ - 很可能問題是由內核以您不理解的方式解決的。Linux內核很大,具有許多不明顯
+   的特性和功能。並不是所有的內核功能都像人們所希望的那樣有文檔記錄,而且很
+   容易遺漏一些東西。某作者發布了一個完整的驅動程序,重複了一個其不
+   知道的現有驅動程序。重新發明現有輪子的代碼不僅浪費,而且不會被接受到主線
+   內核中。
+
+ - 建議的解決方案中可能有一些要素不適合併入主線。在編寫代碼之前,最好先了解
+   這樣的問題。
+
+ - 其他開發人員完全有可能考慮過這個問題;他們可能有更好的解決方案的想法,並且
+   可能願意幫助創建這個解決方案。
+
+在內核開發社區的多年經驗給了我們一個明確的教訓:閉門設計和開發的內核代碼總是
+有一些問題,這些問題只有在代碼發布到社區中時才會被發現。有時這些問題很嚴重,
+需要數月或數年的努力才能使代碼達到內核社區的標準。例如:
+
+ - 設計並實現了單處理器系統的DeviceScape網絡棧。只有使其適合於多處理器系統,
+   才能將其合併到主線中。在代碼中修改鎖等等是一項困難的任務;因此,這段代碼
+   (現在稱爲mac80211)的合併被推遲了一年多。
+
+ - Reiser4文件系統包含許多功能,核心內核開發人員認爲這些功能應該在虛擬文件
+   系統層中實現。它還包括一些特性,這些特性在不將系統暴露於用戶引起的死鎖的
+   情況下是不容易實現的。這些問題過遲發現——以及拒絕處理其中一些問題——已經
+   導致Reiser4置身主線內核之外。
+
+ - Apparmor安全模塊以被認爲不安全和不可靠的方式使用內部虛擬文件系統數據結構。
+   這種擔心(包括其他)使Apparmor多年來無法進入主線。
+
+在這些情況下,與內核開發人員的早期討論,可以避免大量的痛苦和額外的工作。
+
+找誰交流?
+----------
+
+當開發人員決定公開他們的計劃時,下一個問題是:我們從哪裡開始?答案是找到正確
+的郵件列表和正確的維護者。對於郵件列表,最好的方法是在維護者(MAINTAINERS)文件
+中查找要發布的相關位置。如果有一個合適的子系統列表,那麼其上發布通常比在
+linux-kernel上發布更可取;您更有可能接觸到在相關子系統中具有專業知識的開發
+人員,並且環境可能具支持性。
+
+找到維護人員可能會有點困難。同樣,維護者文件是開始的地方。但是,該文件往往不
+是最新的,並且並非所有子系統都在那裡顯示。實際上,維護者文件中列出的人員可能
+不是當前實際擔任該角色的人員。因此,當對聯繫誰有疑問時,一個有用的技巧是使用
+git(尤其是「git-log」)查看感興趣的子系統中當前活動的用戶。看看誰在寫補丁、
+誰會在這些補丁上加上Signed-off-by行簽名(如有)。這些人將是幫助新開發項目的
+最佳人選。
+
+找到合適的維護者有時是非常具有挑戰性的,以至於內核開發人員添加了一個腳本來
+簡化這個過程:
+
+::
+
+	.../scripts/get_maintainer.pl
+
+當給定「-f」選項時,此腳本將返回指定文件或目錄的當前維護者。如果在命令行上
+給出了一個補丁,它將列出可能接收補丁副本的維護人員。有許多選項可以調節
+get_maintainer.pl搜索維護者的嚴格程度;請小心使用更激進的選項,因爲最終結果
+可能會包括對您正在修改的代碼沒有真正興趣的開發人員。
+
+如果所有其他方法都失敗了,那麼與Andrew Morton交流是跟蹤特定代碼段維護人員
+的一種有效方法。
+
+何時郵寄?
+----------
+
+如果可能的話,在早期階段發布你的計劃只會更有幫助。描述正在解決的問題以及已經
+制定的關於如何實施的任何計劃。您可以提供的任何信息都可以幫助開發社區爲項目
+提供有用的輸入。
+
+在這個階段可能發生的一件令人沮喪的事情不是得到反對意見,而是很少或根本沒有
+反饋。令人傷心的事實是:(1)內核開發人員往往很忙;(2)不缺少有宏偉計劃但
+代碼(甚至代碼設想)很少的人去支持他們;(3)沒有人有義務審查或評論別人發表
+的想法。除此之外,高層級的設計常常隱藏著一些問題,這些問題只有在有人真正嘗試
+實現這些設計時才會被發現;因此,內核開發人員寧願看到代碼。
+
+如果發布請求評論(RFC)並沒得到什麼有用的評論,不要以爲這意味著無人對此項目
+有興趣,同時你也不能假設你的想法沒有問題。在這種情況下,最好的做法是繼續進
+行,把你的進展隨時通知社區。
+
+獲得官方認可
+-----------------------
+
+如果您的工作是在公司環境中完成的,就像大多數Linux內核工作一樣;顯然,在您將
+公司的計劃或代碼發布到公共郵件列表之前,必須獲得有適當權利經理的許可。發布
+不確定是否兼容GPL的代碼尤其會帶來問題;公司的管理層和法律人員越早能夠就發布
+內核開發項目達成一致,對參與的每個人都越好。
+
+一些讀者可能會認爲他們的核心工作是爲了支持還沒有正式承認存在的產品。將僱主
+的計劃公布在公共郵件列表上可能不是一個可行的選擇。在這種情況下,有必要考慮
+保密是否真的是必要的;通常不需要把開發計劃關在門內。
+
+的確,有些情況下一家公司在開發過程的早期無法合法地披露其計劃。擁有經驗豐富
+的內核開發人員的公司可能選擇以開環的方式進行開發,前提是他們以後能夠避免
+嚴重的集成問題。對於沒有這種內部專業知識的公司,最好的選擇往往是聘請外部
+開發者根據保密協議審查計劃。Linux基金會運行了一個NDA程序,旨在幫助解決這種
+情況;更多信息參見:
+
+    http://www.linuxfoundation.org/nda/
+
+這種審查通常足以避免以後出現嚴重問題,而無需公開披露項目。
+
diff --git a/Documentation/translations/zh_TW/process/4.Coding.rst b/Documentation/translations/zh_TW/process/4.Coding.rst
new file mode 100644
index 000000000000..106b41c97223
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/4.Coding.rst
@@ -0,0 +1,295 @@
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/4.Coding.rst <development_coding>`
+
+:Translator:
+
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+
+:校譯:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+.. _tw_development_coding:
+
+使代碼正確
+======================
+
+雖然一個堅實的、面向社區的設計過程有很多值得說道的,但是任何內核開發項目工作
+的證明都反映在代碼中。它是將由其他開發人員檢查併合並(或不合併)到主線樹中
+的代碼。所以這段代碼的質量決定了項目的最終成功。
+
+本節將檢查編碼過程。我們將從內核開發人員常犯的幾種錯誤開始。然後重點將轉移
+到正確的做法和相關有用的工具上。
+
+陷阱
+----
+
+代碼風格
+********
+
+內核長期以來都有其標準的代碼風格,如
+:ref:`Documentation/translations/zh_TW/process/coding-style.rst <tw_codingstyle>`
+中所述。在多數時候,該文檔中描述的準則至多被認爲是建議性的。因此,內核中存在
+大量不符合代碼風格準則的代碼。這種代碼的存在會給內核開發人員帶來兩方面的危害。
+
+首先,相信內核代碼標準並不重要,也不強制執行。但事實上,如果沒有按照標準
+編寫代碼,那麼新代碼將很難加入到內核中;許多開發人員甚至會在審查代碼之前要求
+對代碼進行重新格式化。一個像內核這麼大的代碼庫需要一些統一格式的代碼,以使
+開發人員能夠快速理解其中的任何部分。所以再也經不起奇怪格式的代碼的折騰了。
+
+內核的代碼風格偶爾會與僱主的強制風格發生衝突。在這種情況下,必須在代碼合併
+之前遵從內核代碼風格。將代碼放入內核意味著以多種方式放棄一定程度的控制權——
+包括控制代碼樣式。
+
+另一個危害是認爲已經在內核中的代碼迫切需要修復代碼樣式。開發者可能會開始編寫
+重新格式化補丁,作爲熟悉開發過程的一種方式,或者作爲將其名字寫入內核變更日誌
+的一種方式,或者兩者兼而有之。但是純代碼風格的修復被開發社區視爲噪音,它們往
+往受到冷遇。因此,最好避免編寫這種類型的補丁。在由於其他原因處理一段代碼的
+同時順帶修復其樣式是很自然的,但是不應該僅爲了更改代碼樣式而更改之。
+
+代碼風格文檔也不應該被視爲絕對不可違反的規則。如果有一個足夠的理由反對這種
+樣式(例如爲了80列限制拆分行會導致可讀性大大降低),那麼就這樣做吧。
+
+注意您還可以使用 ``clang-format`` 工具來幫助您處理這些規則,快速自動重新格式
+化部分代碼,和審閱完整的文件以發現代碼樣式錯誤、拼寫錯誤和可能的改進。它還
+可以方便地排序 ``#includes`` 、對齊變量/宏、重排文本和其他類似任務。有關詳細
+信息,請參閱文檔 :ref:`Documentation/process/clang-format.rst <clangformat>`
+
+抽象層
+******
+
+計算機科學教授教學生以靈活性和信息隱藏的名義廣泛使用抽象層。當然,內核廣泛
+地使用了抽象;任何涉及數百萬行代碼的項目都必須做到這一點以存續下來。但經驗
+表明,過度或過早的抽象可能和過早的優化一樣有害。抽象應用在適當層級,
+不要過度。
+
+簡單點,先考慮一個調用時始終只有一個參數且總爲零的函數。我們可以保留這個參數,
+以在需要使用它時提供的額外靈活性。不過,在那時實現了這個額外參數的代碼很有
+可能以某種從未被注意到的微妙方式被破壞——因爲它從未被使用過。或者當需要額外
+的靈活性時,它並未以符合程式設計師當初期望的方式來實現。內核開發人員通常會提交
+補丁來刪除未使用的參數;一般來說,一開始就不應該添加這些參數。
+
+隱藏硬體訪問的抽象層——通常爲了允許大量的驅動程序兼容多個作業系統——尤其不受
+歡迎。這樣的層使代碼變得模糊,可能會造成性能損失;它們不屬於Linux內核。
+
+另一方面,如果您發現自己從另一個內核子系統複製了大量的代碼,那麼是時候
+了解一下:是否需要將這些代碼中的部分提取到單獨的庫中,或者在更高的層次上
+實現這些功能。在整個內核中複製相同的代碼沒有價值。
+
+#ifdef 和預處理
+***************
+
+C預處理器似乎給一些C程式設計師帶來了強大的誘惑,他們認爲它是一種將大量靈活性加入
+原始碼中的方法。但是預處理器不是C,大量使用它會導致代碼對其他人來說更難閱讀,
+對編譯器來說更難檢查正確性。使用了大量預處理器幾乎總是代碼需要一些
+清理工作的標誌。
+
+使用#ifdef的條件編譯實際上是一個強大的功能,它在內核中使用。但是很少有人希望
+看到代碼被鋪滿#ifdef塊。一般規定,ifdef的使用應儘可能限制在頭文件中。條件
+編譯代碼可以限制函數,如果代碼不存在,這些函數就直接變成空的。然後編譯器將
+悄悄地優化對空函數的調用。使得代碼更加清晰,更容易理解。
+
+C預處理器宏存在許多危險性,包括可能對具有副作用且沒有類型安全的表達式進行多
+重評估。如果您試圖定義宏,請考慮創建一個內聯函數替代。結果相同的代碼,內聯
+函數更容易閱讀,不會多次計算其參數,並且允許編譯器對參數和返回值執行類型檢查。
+
+內聯函數
+********
+
+不過,內聯函數本身也存在風險。程式設計師可以傾心於避免函數調用和用內聯函數填充源
+文件所固有的效率。然而,這些功能實際上會降低性能。因爲它們的代碼在每個調用站
+點都被複製一遍,所以最終會增加編譯內核的大小。此外,這也對處理器的內存緩存
+造成壓力,從而大大降低執行速度。通常內聯函數應該非常小,而且相對較少。畢竟
+函數調用的成本並不高;大量創建內聯函數是過早優化的典型例子。
+
+一般來說,內核程式設計師會自冒風險忽略緩存效果。在數據結構課程開頭中的經典
+時間/空間權衡通常不適用於當代硬體。空間 *就是* 時間,因爲一個大的程序比一個
+更緊湊的程序運行得慢。
+
+較新的編譯器越來越激進地決定一個給定函數是否應該內聯。因此,隨意放置使用
+「inline」關鍵字可能不僅僅是過度的,也可能是無用的。
+
+鎖
+**
+
+2006年5月,「deviceescape」網絡堆棧在前呼後擁下以GPL發布,並被納入主線內核。
+這是一個受歡迎的消息;Linux中對無線網絡的支持充其量被認爲是不合格的,而
+Deviceescape堆棧承諾修復這種情況。然而直到2007年6月(2.6.22),這段代碼才真
+正進入主線。發生了什麼?
+
+這段代碼出現了許多閉門造車的跡象。但一個大麻煩是,它並不是爲多處理器系統而
+設計。在合併這個網絡堆棧(現在稱爲mac80211)之前,需要對其進行一個鎖方案的
+改造。
+
+曾經,Linux內核代碼可以在不考慮多處理器系統所帶來的並發性問題的情況下進行
+開發。然而現在,這個文檔就是在雙核筆記本電腦上寫的。即使在單處理器系統上,
+爲提高響應能力所做的工作也會提高內核內的並發性水平。編寫內核代碼而不考慮鎖
+的日子早已遠去。
+
+可以由多個線程並發訪問的任何資源(數據結構、硬體寄存器等)必須由鎖保護。新
+的代碼應該謹記這一要求;事後修改鎖是一項相當困難的任務。內核開發人員應該花
+時間充分了解可用的鎖原語,以便爲工作選擇正確的工具。對並發性缺乏關注的代碼
+很難進入主線。
+
+回歸
+****
+
+最後一個值得一提的危險是回歸:它可能會引起導致現有用戶的某些東西中斷的改變
+(這也可能會帶來很大的改進)。這種變化被稱爲「回歸」,回歸已經成爲主線內核
+最不受歡迎的問題。除了少數例外情況,如果回歸不能及時修正,會導致回歸的修改
+將被取消。最好首先避免回歸發生。
+
+人們常常爭論,如果回歸帶來的功能遠超過產生的問題,那麼回歸是否爲可接受的。
+如果它破壞了一個系統卻爲十個系統帶來新的功能,爲何不改改態度呢?2007年7月,
+Linus對這個問題給出了最佳答案:
+
+::
+
+	所以我們不會通過引入新問題來修復錯誤。這種方式是靠不住的,沒人知道
+	是否真的有進展。是前進兩步、後退一步,還是前進一步、後退兩步?
+
+(http://lwn.net/articles/243460/)
+
+特別不受歡迎的一種回歸類型是用戶空間ABI的任何變化。一旦接口被導出到用戶空間,
+就必須無限期地支持它。這一事實使得用戶空間接口的創建特別具有挑戰性:因爲它們
+不能以不兼容的方式進行更改,所以必須一次就對。因此,用戶空間接口總是需要大量
+的思考、清晰的文檔和廣泛的審查。
+
+
+代碼檢查工具
+------------
+
+至少目前,編寫無錯誤代碼仍然是我們中很少人能達到的理想狀態。不過,我們希望做
+的是,在代碼進入主線內核之前,儘可能多地捕獲並修復這些錯誤。爲此,內核開發人
+員已經提供了一系列令人印象深刻的工具,可以自動捕獲各種各樣的隱藏問題。計算機
+發現的任何問題都是一個以後不會困擾用戶的問題,因此,只要有可能,就應該使用
+自動化工具。
+
+第一步是注意編譯器產生的警告。當前版本的GCC可以檢測(並警告)大量潛在錯誤。
+通常,這些警告都指向真正的問題。提交以供審閱的代碼一般不會產生任何編譯器警告。
+在消除警告時,注意了解真正的原因,並儘量避免僅「修復」使警告消失而不解決其原因。
+
+請注意,並非所有編譯器警告都默認啓用。使用「make KCFLAGS=-W」構建內核以
+獲得完整集合。
+
+內核提供了幾個配置選項,可以打開調試功能;大多數配置選項位於「kernel hacking」
+子菜單中。對於任何用於開發或測試目的的內核,都應該啓用其中幾個選項。特別是,
+您應該打開:
+
+ - FRAME_WARN 獲取大於給定數量的堆棧幀的警告。
+   這些警告生成的輸出可能比較冗長,但您不必擔心來自內核其他部分的警告。
+
+ - DEBUG_OBJECTS 將添加代碼以跟蹤內核創建的各種對象的生命周期,並在出現問題
+   時發出警告。如果你要添加創建(和導出)關於其自己的複雜對象的子系統,請
+   考慮打開對象調試基礎結構的支持。
+
+ - DEBUG_SLAB 可以發現各種內存分配和使用錯誤;它應該用於大多數開發內核。
+
+ - DEBUG_SPINLOCK, DEBUG_ATOMIC_SLEEP 和 DEBUG_MUTEXES 會發現許多常見的
+   鎖錯誤。
+
+還有很多其他調試選項,其中一些將在下面討論。其中一些有顯著的性能影響,不應
+一直使用。在學習可用選項上花費一些時間,可能會在短期內得到許多回報。
+
+其中一個較重的調試工具是鎖檢查器或「lockdep」。該工具將跟蹤系統中每個鎖
+(spinlock或mutex)的獲取和釋放、獲取鎖的相對順序、當前中斷環境等等。然後,
+它可以確保總是以相同的順序獲取鎖,相同的中斷假設適用於所有情況等等。換句話
+說,lockdep可以找到許多導致系統死鎖的場景。在部署的系統中,這種問題可能會
+很痛苦(對於開發人員和用戶而言);LockDep允許提前以自動方式發現問題。具有
+任何類型的非普通鎖的代碼在提交合併前應在啓用lockdep的情況下運行測試。
+
+作爲一個勤奮的內核程式設計師,毫無疑問,您將檢查任何可能失敗的操作(如內存分配)
+的返回狀態。然而,事實上,最終的故障復現路徑可能完全沒有經過測試。未測試的
+代碼往往會出問題;如果所有這些錯誤處理路徑都被執行了幾次,那麼您可能對代碼
+更有信心。
+
+內核提供了一個可以做到這一點的錯誤注入框架,特別是在涉及內存分配的情況下。
+啓用故障注入後,內存分配的可配置失敗的百分比;這些失敗可以限定在特定的代碼
+範圍內。在啓用了故障注入的情況下運行,程式設計師可以看到當情況惡化時代碼如何響
+應。有關如何使用此工具的詳細信息,請參閱
+Documentation/fault-injection/fault-injection.rst。
+
+「sparse」靜態分析工具可以發現其他類型的錯誤。sparse可以警告程式設計師用戶空間
+和內核空間地址之間的混淆、大端序與小端序的混淆、在需要一組位標誌的地方傳遞
+整數值等等。sparse必須單獨安裝(如果您的分發伺服器沒有將其打包,
+可以在 https://sparse.wiki.kernel.org/index.php/Main_page 找到),
+然後可以通過在make命令中添加「C=1」在代碼上運行它。
+
+「Coccinelle」工具 :ref:`http://coccinelle.lip6.fr/ <devtools_coccinelle>`
+能夠發現各種潛在的編碼問題;它還可以爲這些問題提出修複方案。在
+scripts/coccinelle目錄下已經打包了相當多的內核「語義補丁」;運行
+「make coccicheck」將運行這些語義補丁並報告發現的任何問題。有關詳細信息,請參閱
+:ref:`Documentation/dev-tools/coccinelle.rst <devtools_coccinelle>`
+
+
+其他類型的可移植性錯誤最好通過爲其他體系結構編譯代碼來發現。如果沒有S/390系統
+或Blackfin開發板,您仍然可以執行編譯步驟。可以在以下位置找到一大堆用於x86系統的
+交叉編譯器:
+
+        https://www.kernel.org/pub/tools/crosstool/
+
+花一些時間安裝和使用這些編譯器將有助於避免以後的尷尬。
+
+文檔
+----
+
+文檔通常比內核開發規則更爲例外。即便如此,足夠的文檔將有助於簡化將新代碼合併
+到內核中的過程,使其他開發人員的生活更輕鬆,並對您的用戶有所幫助。在許多情況
+下,添加文檔已基本上是強制性的。
+
+任何補丁的第一個文檔是其關聯的變更日誌。日誌條目應該描述正在解決的問題、解決
+方案的形式、處理補丁的人員、對性能的任何相關影響,以及理解補丁可能需要的任何
+其他內容。確保變更日誌說明了*爲什麼*補丁值得應用;大量開發者未能提供這些信息。
+
+任何添加新用戶空間接口的代碼——包括新的sysfs或/proc文件——都應該包含該接口
+的文檔,該文檔使用戶空間開發人員能夠知道他們在使用什麼。請參閱
+Documentation/ABI/README,了解如何此文檔格式以及需要提供哪些信息。
+
+文檔 :ref:`Documentation/admin-guide/kernel-parameters.rst <kernelparameters>`
+描述了內核的所有引導時間參數。任何添加新參數的補丁都應該向該文檔添加適當的
+條目。
+
+任何新的配置選項都必須附有幫助文本,幫助文本需清楚地解釋這些選項以及用戶可能
+希望何時使用它們。
+
+許多子系統的內部API信息通過專門格式化的注釋進行記錄;這些注釋可以通過
+「kernel-doc」腳本以多種方式提取和格式化。如果您在具有kerneldoc注釋的子系統中
+工作,則應該維護它們,並根據需要爲外部可用的功能添加它們。即使在沒有如此記錄
+的領域中,爲將來添加kerneldoc注釋也沒有壞處;實際上,這對於剛開始開發內核的人
+來說是一個有用的活動。這些注釋的格式以及如何創建kerneldoc模板的一些信息可以在
+:ref:`Documentation/doc-guide/ <doc_guide>` 上找到。
+
+任何閱讀大量現有內核代碼的人都會注意到,注釋的缺失往往是最值得注意的。同時,
+對新代碼的要求比過去更高;合併未注釋的代碼將更加困難。這就是說,人們並不期望
+詳細注釋的代碼。代碼本身應該是自解釋的,注釋闡釋了更微妙的方面。
+
+某些事情應該總是被注釋。使用內存屏障時,應附上一行文字,解釋爲什麼需要設置內存
+屏障。數據結構的鎖規則通常需要在某個地方解釋。一般來說,主要數據結構需要全面
+的文檔。應該指出代碼中分立的位之間不明顯的依賴性。任何可能誘使代碼管理人進行
+錯誤的「清理」的事情都需要一個注釋來說明爲什麼要這樣做。等等。
+
+
+內部API更改
+-----------
+
+內核提供給用戶空間的二進位接口不能被破壞,除非逼不得已。而內核的內部編程接口
+是高度流動的,當需要時可以更改。如果你發現自己不得不處理一個內核API,或者僅
+僅因爲它不滿足你的需求導致無法使用特定的功能,這可能是API需要改變的一個標誌。
+作爲內核開發人員,您有權進行此類更改。
+
+的確可以進行API更改,但更改必須是合理的。因此任何進行內部API更改的補丁都應該
+附帶關於更改內容和必要原因的描述。這種變化也應該拆分成一個單獨的補丁,而不是
+埋在一個更大的補丁中。
+
+另一個要點是,更改內部API的開發人員通常要負責修復內核樹中被更改破壞的任何代碼。
+對於一個廣泛使用的函數,這個責任可以導致成百上千的變化,其中許多變化可能與其他
+開發人員正在做的工作相衝突。不用說,這可能是一項大工程,所以最好確保理由是
+可靠的。請注意,coccinelle工具可以幫助進行廣泛的API更改。
+
+在進行不兼容的API更改時,應儘可能確保編譯器捕獲未更新的代碼。這將幫助您確保找
+到該接口的樹內用處。它還將警告開發人員樹外代碼存在他們需要響應的更改。支持樹外
+代碼不是內核開發人員需要擔心的事情,但是我們也不必使樹外開發人員的生活有不必要
+的困難。
+
diff --git a/Documentation/translations/zh_TW/process/5.Posting.rst b/Documentation/translations/zh_TW/process/5.Posting.rst
new file mode 100644
index 000000000000..3e09da2f3056
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/5.Posting.rst
@@ -0,0 +1,249 @@
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/5.Posting.rst <development_posting>`
+
+:Translator:
+
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+
+:校譯:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+.. _tw_development_posting:
+
+發布補丁
+========
+
+您的工作遲早會準備好提交給社區進行審查,並最終包含到主線內核中。毫不稀奇,
+內核開發社區已經發展出一套用於發布補丁的約定和過程;遵循這些約定和過程將使
+參與其中的每個人的生活更加輕鬆。本文檔試圖描述這些約定的部分細節;更多信息
+也可在以下文檔中找到
+:ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`,
+:ref:`Documentation/translations/zh_TW/process/submitting-drivers.rst <tw_submittingdrivers>`
+和 :ref:`Documentation/translations/zh_TW/process/submit-checklist.rst <tw_submitchecklist>`。
+
+何時郵寄
+--------
+
+在補丁完全「準備好」之前,避免發布補丁是一種持續的誘惑。對於簡單的補丁,這
+不是問題。但是如果正在完成的工作很複雜,那麼在工作完成之前從社區獲得反饋就
+可以獲得很多好處。因此,您應該考慮發布正在進行的工作,甚至維護一個可用的Git
+樹,以便感興趣的開發人員可以隨時趕上您的工作。
+
+當發布中有尚未準備好被包含的代碼,最好在發布中說明。還應提及任何有待完成的
+主要工作和任何已知問題。很少有人會願意看那些被認爲是半生不熟的補丁,但是
+那些願意的人會帶著他們的點子來一起幫助你把工作推向正確的方向。
+
+創建補丁之前
+------------
+
+在考慮將補丁發送到開發社區之前,有許多事情應該做。包括:
+
+ - 儘可能地測試代碼。利用內核的調試工具,確保內核使用了所有可能的配置選項組合
+   進行構建,使用交叉編譯器爲不同的體系結構進行構建等。
+
+ - 確保您的代碼符合內核代碼風格指南。
+
+ - 您的更改是否具有性能影響?如果是這樣,您應該運行基準測試來顯示您的變更的
+   影響(或好處);結果的摘要應該包含在補丁中。
+
+ - 確保您有權發布代碼。如果這項工作是爲僱主完成的,僱主對這項工作具有所有權,
+   並且必須同意根據GPL對其進行發布。
+
+一般來說,在發布代碼之前進行一些額外的思考,幾乎總是能在短時間內得到回報。
+
+補丁準備
+--------
+
+準備補丁發布的工作量可能很驚人,但在此嘗試節省時間通常是不明智的,即使在短期
+內亦然。
+
+必須針對內核的特定版本準備補丁。一般來說,補丁應該基於Linus的Git樹中的當前
+主線。當以主線爲基礎時,請從一個衆所周知的發布點開始——如穩定版本或 -rc
+版本發布點——而不是在一個任意的主線分支點。
+
+也可能需要針對-mm、linux-next或子系統樹生成版本,以便於更廣泛的測試和審查。
+根據補丁的區域以及其他地方的情況,針對其他樹建立的補丁可能需要大量的工作來
+解決衝突和處理API更改。
+
+只有最簡單的更改才應格式化爲單個補丁;其他所有更改都應作爲一系列邏輯更改進行。
+分割補丁是一門藝術;一些開發人員花了很長時間來弄清楚如何按照社區期望的方式來
+分割。不過,這些經驗法則也許有幫助:
+
+ - 您發布的補丁系列幾乎肯定不會是開發過程中版本控制系統中的一系列更改。相反,
+   需要對您所做更改的最終形式加以考慮,然後以有意義的方式進行拆分。開發人員對
+   離散的、自包含的更改感興趣,而不是您創造這些更改的原始路徑。
+
+ - 每個邏輯上獨立的變更都應該格式化爲單獨的補丁。這些更改可以是小的(如「向
+   此結構體添加欄位」)或大的(如添加一個重要的新驅動程序),但它們在概念上
+   應該是小的,並且可以在一行內簡述。每個補丁都應該做一個特定的、可以單獨
+   檢查並驗證它所做的事情的更改。
+
+ - 換種方式重申上述準則,也就是說:不要在同一補丁中混合不同類型的更改。如果
+   一個補丁修復了一個關鍵的安全漏洞,又重新排列了一些結構,還重新格式化了代
+   碼,那麼它很有可能會被忽略,從而導致重要的修復丟失。
+
+ - 每個補丁都應該能創建一個可以正確地構建和運行的內核;如果補丁系列在中間被
+   斷開,那麼結果仍應是一個正常工作的內核。部分應用一系列補丁是使用
+   「git bisct」工具查找回歸的一個常見場景;如果結果是一個損壞的內核,那麼將使
+   那些從事追蹤問題的高尚工作的開發人員和用戶的生活更加艱難。
+
+ - 不要過分分割。一位開發人員曾經將一組針對單個文件的編輯分成500個單獨的補丁
+   發布,這並沒有使他成爲內核郵件列表中最受歡迎的人。一個補丁可以相當大,
+   只要它仍然包含一個單一的 *邏輯* 變更。
+
+ - 用一系列補丁添加一個全新的基礎設施,但是該設施在系列中的最後一個補丁啓用
+   整個變更之前不能使用,這看起來很誘人。如果可能的話,應該避免這種誘惑;
+   如果這個系列增加了回歸,那麼二分法將指出最後一個補丁是導致問題的補丁,
+   即使真正的bug在其他地方。只要有可能,添加新代碼的補丁程序應該立即激活該
+   代碼。
+
+創建完美補丁系列的工作可能是一個令人沮喪的過程,在完成「真正的工作」之後需要
+花費大量的時間和思考。但是如果做得好,花費的時間就是值得的。
+
+補丁格式和更改日誌
+------------------
+
+所以現在你有了一系列完美的補丁可以發布,但是這項工作還沒有完成。每個補丁都
+需要被格式化成一條消息,以快速而清晰地將其目的傳達到世界其他地方。爲此,
+每個補丁將由以下部分組成:
+
+ - 可選的「From」行,表明補丁作者。只有當你通過電子郵件發送別人的補丁時,這一行
+   才是必須的,但是爲防止疑問加上它也不會有什麼壞處。
+
+ - 一行描述,說明補丁的作用。對於在沒有其他上下文的情況下看到該消息的讀者來說,
+   該消息應足以確定修補程序的範圍;此行將顯示在「short form(簡短格式)」變更
+   日誌中。此消息通常需要先加上子系統名稱前綴,然後是補丁的目的。例如:
+
+   ::
+
+        gpio: fix build on CONFIG_GPIO_SYSFS=n
+
+ - 一行空白,後接補丁內容的詳細描述。此描述可以是任意需要的長度;它應該說明補丁
+   的作用以及爲什麼它應該應用於內核。
+
+ - 一個或多個標記行,至少有一個由補丁作者的 Signed-off-by 簽名。標記將在下面
+   詳細描述。
+
+上面的項目一起構成補丁的變更日誌。寫一則好的變更日誌是一門至關重要但常常被
+忽視的藝術;值得花一點時間來討論這個問題。當你編寫變更日誌時,你應該記住有
+很多不同的人會讀你的話。其中包括子系統維護人員和審查人員,他們需要決定是否
+應該合併補丁,分銷商和其他維護人員試圖決定是否應該將補丁反向移植到其他內核,
+缺陷搜尋人員想知道補丁是否導致他們正在追查的問題,以及想知道內核如何變化的
+用戶等等。一個好的變更日誌以最直接和最簡潔的方式向所有這些人傳達所需的信息。
+
+在結尾,總結行應該描述變更的影響和動機,以及在一行約束條件下可能發生的變化。
+然後,詳細的描述可以詳述這些主題,並提供任何需要的附加信息。如果補丁修復了
+一個缺陷,請引用引入該缺陷的提交(如果可能,請在引用提交時同時提供其 id 和
+標題)。如果某個問題與特定的日誌或編譯器輸出相關聯,請包含該輸出以幫助其他
+人搜索同一問題的解決方案。如果更改是爲了支持以後補丁中的其他更改,那麼應當
+說明。如果更改了內部API,請詳細說明這些更改以及其他開發人員應該如何響應。
+一般來說,你越把自己放在每個閱讀你變更日誌的人的位置上,變更日誌(和內核
+作爲一個整體)就越好。
+
+不消說,變更日誌是將變更提交到版本控制系統時使用的文本。接下來將是:
+
+ - 補丁本身,採用統一的(「-u」)補丁格式。使用「-p」選項來diff將使函數名與
+   更改相關聯,從而使結果補丁更容易被其他人讀取。
+
+您應該避免在補丁中包括與更改不相關文件(例如,構建過程生成的文件或編輯器
+備份文件)。文檔目錄中的「dontdiff」文件在這方面有幫助;使用「-X」選項將
+其傳遞給diff。
+
+上面提到的標籤(tag)用於描述各種開發人員如何與這個補丁的開發相關聯。
+:ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+文檔中對它們進行了詳細描述;下面是一個簡短的總結。每一行的格式如下:
+
+::
+
+	tag: Full Name <email address>  optional-other-stuff
+
+常用的標籤有:
+
+ - Signed-off-by: 這是一個開發人員的證明,證明他或她有權提交補丁以包含到內核
+   中。這表明同意開發者來源認證協議,其全文見
+   :ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+   如果沒有合適的簽字,則不能合併到主線中。
+
+ - Co-developed-by: 聲明補丁是由多個開發人員共同創建的;當幾個人在一個補丁上
+   工作時,它用於給出共同作者(除了 From: 所給出的作者之外)。由於
+   Co-developed-by: 表示作者身份,所以每個共同開發人,必須緊跟在相關合作作者
+   的Signed-off-by之後。具體內容和示例見以下文件
+   :ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+
+ - Acked-by: 表示另一個開發人員(通常是相關代碼的維護人員)同意補丁適合包含
+   在內核中。
+
+ - Tested-by: 聲明某人已經測試了補丁並確認它可以工作。
+
+ - Reviewed-by: 表示某開發人員已經審查了補丁的正確性;有關詳細信息,請參閱
+   :ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+
+ - Reported-by: 指定報告此補丁修復的問題的用戶;此標記用於表示感謝。
+
+ - Cc:指定某人收到了補丁的副本,並有機會對此發表評論。
+
+在補丁中添加標籤時要小心:只有Cc:才適合在沒有指定人員明確許可的情況下添加。
+
+發送補丁
+--------
+
+在寄出補丁之前,您還需要注意以下幾點:
+
+ - 您確定您的郵件發送程序不會損壞補丁嗎?被郵件客戶端更改空白或修飾了行的補丁
+   無法被另一端接受,並且通常不會進行任何詳細檢查。如果有任何疑問,先把補丁寄
+   給你自己,讓你自己確定它是完好無損的。
+
+   :ref:`Documentation/translations/zh_TW/process/email-clients.rst <tw_email_clients>`
+   提供了一些有用的提示,可以讓特定的郵件客戶端正常發送補丁。
+
+ - 你確定你的補丁沒有荒唐的錯誤嗎?您應該始終通過scripts/checkpatch.pl檢查
+   補丁程序,並解決它提出的問題。請記住,checkpatch.pl,雖然體現了對內核補丁
+   應該是什麼樣的大量思考,但它並不比您聰明。如果修復checkpatch.pl給的問題會
+   使代碼變得更糟,請不要這樣做。
+
+補丁應始終以純文本形式發送。請不要將它們作爲附件發送;這使得審閱者在答覆中更難
+引用補丁的部分。相反,只需將補丁直接放到您的消息中。
+
+寄出補丁時,重要的是將副本發送給任何可能感興趣的人。與其他一些項目不同,內核
+鼓勵人們甚至錯誤地發送過多的副本;不要假定相關人員會看到您在郵件列表中的發布。
+尤其是,副本應發送至:
+
+ - 受影響子系統的維護人員。如前所述,維護人員文件是查找這些人員的首選地方。
+
+ - 其他在同一領域工作的開發人員,尤其是那些現在可能在那裡工作的開發人員。使用
+   git查看還有誰修改了您正在處理的文件,這很有幫助。
+
+ - 如果您對某錯誤報告或功能請求做出響應,也可以抄送原始發送人。
+
+ - 將副本發送到相關郵件列表,或者若無相關列表,則發送到linux-kernel列表。
+
+ - 如果您正在修復一個缺陷,請考慮該修復是否應進入下一個穩定更新。如果是這樣,
+   補丁副本也應發到stable@vger.kernel.org 。另外,在補丁本身的標籤中添加一個
+   「Cc: stable@vger.kernel.org」;這將使穩定版團隊在修復進入主線時收到通知。
+
+當爲一個補丁選擇接收者時,最好清楚你認爲誰最終會接受這個補丁並將其合併。雖然
+可以將補丁直接發給Linus Torvalds並讓他合併,但通常情況下不會這樣做。Linus很
+忙,並且有子系統維護人員負責監視內核的特定部分。通常您會希望維護人員合併您的
+補丁。如果沒有明顯的維護人員,Andrew Morton通常是最後的補丁接收者。
+
+補丁需要好的主題行。補丁主題行的規範格式如下:
+
+::
+
+	[PATCH nn/mm] subsys: one-line description of the patch
+
+其中「nn」是補丁的序號,「mm」是系列中補丁的總數,「subsys」是受影響子系統的
+名稱。當然,一個單獨的補丁可以省略nn/mm。
+
+如果您有一系列重要的補丁,那麼通常發送一個簡介作爲第〇部分。不過,這個約定
+並沒有得到普遍遵循;如果您使用它,請記住簡介中的信息不會進入內核變更日誌。
+因此,請確保補丁本身具有完整的變更日誌信息。
+
+一般來說,多部分補丁的第二部分和後續部分應作爲對第一部分的回覆發送,以便它們
+在接收端都連接在一起。像git和coilt這樣的工具有命令,可以通過適當的線程發送
+一組補丁。但是,如果您有一長串補丁,並正使用git,請不要使用–-chain-reply-to
+選項,以避免創建過深的嵌套。
+
diff --git a/Documentation/translations/zh_TW/process/6.Followthrough.rst b/Documentation/translations/zh_TW/process/6.Followthrough.rst
new file mode 100644
index 000000000000..233115bfff95
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/6.Followthrough.rst
@@ -0,0 +1,154 @@
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/6.Followthrough.rst <development_followthrough>`
+
+:Translator:
+
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+
+:校譯:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+.. _tw_development_followthrough:
+
+跟進
+====
+
+此時,您已經遵循了到目前爲止給出的指導方針,並且,隨著您自己的工程技能的增加,
+已經發布了一系列完美的補丁。即使是經驗豐富的內核開發人員也能犯的最大錯誤之一
+是,認爲他們的工作現在已經完成了。事實上,發布補丁意味著進入流程的下一個階段,
+可能還需要做很多工作。
+
+一個補丁在首次發布時就非常出色、沒有改進的餘地,這是很罕見的。內核開發流程已
+認識到這一事實,因此它非常注重對已發布代碼的改進。作爲代碼的作者,您應該與
+內核社區合作,以確保您的代碼符合內核的質量標準。如果不參與這個過程,很可能會
+無法將補丁合併到主線中。
+
+與審閱者合作
+------------
+
+任何意義上的補丁都會導致其他開發人員在審查代碼時發表大量評論。對於許多開發
+人員來說,與審閱人員合作可能是內核開發過程中最令人生畏的部分。但是如果你
+記住一些事情,生活會變得容易得多:
+
+ - 如果你已經很好地解釋了你的補丁,審閱人員會理解它的價值,以及爲什麼你會
+   費盡心思去寫它。但是這個並不能阻止他們提出一個基本的問題:在五年或十年後
+   維護含有此代碼的內核會怎麼樣?你可能被要求做出的許多改變——從編碼風格的
+   調整到大量的重寫——都來自於對Linux的理解,即從現在起十年後,Linux仍將
+   在開發中。
+
+ - 代碼審查是一項艱苦的工作,這是一項相對吃力不討好的工作;人們記得誰編寫了
+   內核代碼,但對於那些審查它的人來說,幾乎沒有什麼長久的名聲。因此,審閱
+   人員可能會變得暴躁,尤其是當他們看到同樣的錯誤被一遍又一遍地犯下時。如果
+   你得到了一個看起來憤怒、侮辱或完全冒犯你的評論,請抑制以同樣方式回應的衝動。
+   代碼審查是關於代碼的,而不是關於人的,代碼審閱人員不會親自攻擊您。
+
+ - 同樣,代碼審閱人員也不想以犧牲你僱主的利益爲代價來宣傳他們僱主的議程。
+   內核開發人員通常希望今後幾年能在內核上工作,但他們明白他們的僱主可能會改
+   變。他們真的,幾乎毫無例外地,致力於創造他們所能做到的最好的內核;他們並
+   沒有試圖給僱主的競爭對手造成不適。
+
+所有這些歸根結底就是,當審閱者向您發送評論時,您需要注意他們正在進行的技術
+評論。不要讓他們的表達方式或你自己的驕傲阻止此事。當你在一個補丁上得到評論
+時,花點時間去理解評論人想說什麼。如果可能的話,請修覆審閱者要求您修復的內
+容。然後回覆審閱者:謝謝他們,並描述你將如何回答他們的問題。
+
+請注意,您不必同意審閱者建議的每個更改。如果您認爲審閱者誤解了您的代碼,請
+解釋到底發生了什麼。如果您對建議的更改有技術上的異議,請描述它並證明您對該
+問題的解決方案是正確的。如果你的解釋有道理,審閱者會接受的。不過,如果你的
+解釋證明缺乏說服力,尤其是當其他人開始同意審稿人的觀點時,請花些時間重新考慮
+一下。你很容易對自己解決問題的方法視而不見,以至於你沒有意識到某些東西完全
+是錯誤的,或者你甚至沒有解決正確的問題。
+
+Andrew Morton建議,每一個不會導致代碼更改的審閱評論都應該產生一個額外的代碼
+注釋;這可以幫助未來的審閱人員避免第一次出現的問題。
+
+一個致命的錯誤是忽視評論,希望它們會消失。它們不會走的。如果您在沒有對之前
+收到的評論做出響應的情況下重新發布代碼,那麼很可能會發現補丁毫無用處。
+
+說到重新發布代碼:請記住,審閱者不會記住您上次發布的代碼的所有細節。因此,
+提醒審閱人員以前提出的問題以及您如何處理這些問題總是一個好主意;補丁變更
+日誌是提供此類信息的好地方。審閱者不必搜索列表檔案來熟悉上次所說的內容;
+如果您幫助他們直接開始,當他們重新查看您的代碼時,心情會更好。
+
+如果你已經試著做正確的事情,但事情仍然沒有進展呢?大多數技術上的分歧都可以
+通過討論來解決,但有時人們仍需要做出決定。如果你真的認爲這個決定對你不利,
+你可以試著向有更高權力的人上訴。對於本文,更高權力的人是 Andrew Morton 。
+Andrew 在內核開發社區中非常受尊敬;他經常爲似乎被絕望阻塞的事情清障。儘管
+如此,不應輕易就直接找 Andrew ,也不應在所有其他替代方案都被嘗試之前找他。
+當然,記住,他也可能不同意你的意見。
+
+接下來會發生什麼
+----------------
+
+如果一個補丁被認爲適合添加到內核中,並且大多數審查問題得到解決,下一步通常
+是進入子系統維護人員的樹中。工作方式因子系統而異;每個維護人員都有自己的
+工作方式。特別是可能有不止一棵樹——也許一棵樹專門用於計劃下一個合併窗口的
+補丁,另一棵樹用於長期工作。
+
+對於應用到不屬於明顯子系統樹(例如內存管理修補程序)的區域的修補程序,默認樹
+通常上溯到-mm。影響多個子系統的補丁也可以最終進入-mm樹。
+
+包含在子系統樹中可以提高補丁的可見性。現在,使用該樹的其他開發人員將默認獲
+得補丁。子系統樹通常也爲Linux提供支持,使其內容對整個開發社區可見。在這一點
+上,您很可能會從一組新的審閱者那裡得到更多的評論;這些評論需要像上一輪那樣
+得到回應。
+
+在這時也會發生點什麼,這取決於你的補丁的性質,是否與其他人正在做的工作發生
+衝突。在最壞的情況下,嚴重的補丁衝突可能會導致一些工作被擱置,以便剩餘的補丁
+可以成形併合並。另一些時候,衝突解決將涉及到與其他開發人員合作,可能還會
+在樹之間移動一些補丁,以確保所有的應用都是乾淨的。這項工作可能是一件痛苦的
+事情,但也需慶幸現在的幸福:在linux-next樹出現之前,這些衝突通常只在合併窗口
+中出現,必須迅速解決。現在可以在合併窗口打開之前的空閒時間解決這些問題。
+
+有朝一日,如果一切順利,您將登錄並看到您的補丁已經合併到主線內核中。祝賀你!
+然而,一旦慶祝完了(並且您已經將自己添加到維護人員文件中),就一定要記住
+一個重要的小事實:工作仍然沒有完成。併入主線也帶來了它的挑戰。
+
+首先,補丁的可見性再次提高。可能會有以前不知道這個補丁的開發者的新一輪評論。
+忽略它們可能很有誘惑力,因爲您的代碼不再存在任何被合併的問題。但是,要抵制
+這種誘惑,您仍然需要對有問題或建議的開發人員作出響應。
+
+不過,更重要的是:將代碼包含在主線中會將代碼交給更多的一些測試人員。即使您
+爲尚未可用的硬體提供了驅動程序,您也會驚訝於有多少人會將您的代碼構建到內核
+中。當然,如果有測試人員,也可能會有錯誤報告。
+
+最糟糕的錯誤報告是回歸。如果你的補丁導致回歸,你會發現多到讓你不舒服的眼睛盯
+著你;回歸需要儘快修復。如果您不願意或無法修復回歸(其他人都不會爲您修復),
+那麼在穩定期內,您的補丁幾乎肯定會被移除。除了否定您爲使補丁進入主線所做的
+所有工作之外,如果由於未能修復回歸而取消補丁,很可能會使將來的工作更難被合併。
+
+在處理完任何回歸之後,可能還有其他普通缺陷需要處理。穩定期是修復這些錯誤並
+確保代碼在主線內核版本中的首次發布儘可能可靠的最好機會。所以,請回應錯誤
+報告,並儘可能解決問題。這就是穩定期的目的;一旦解決了舊補丁的任何問題,就
+可以開始盡情創建新補丁。
+
+別忘了,還有其他節點也可能會創建缺陷報告:下一個主線穩定版本,當著名的發行
+商選擇包含您補丁的內核版本時等等。繼續響應這些報告是您工作的基本素養。但是
+如果這不能提供足夠的動機,那麼也需要考慮:開發社區會記住那些在合併後對代碼
+失去興趣的開發人員。下一次你發布補丁時,他們會以你以後不會持續維護它爲前提
+來評估它。
+
+其他可能發生的事情
+------------------
+
+某天,當你打開你的郵件客戶端時,看到有人給你寄了一個代碼補丁。畢竟,這是
+讓您的代碼公開存在的好處之一。如果您同意這個補丁,您可以將它轉發給子系統
+維護人員(確保包含一個正確的From:行,這樣屬性是正確的,並添加一個您自己的
+signoff ),或者回復一個 Acked-by: 讓原始發送者向上發送它。
+
+如果您不同意補丁,請禮貌地回復,解釋原因。如果可能的話,告訴作者需要做哪些
+更改才能讓您接受補丁。合併代碼的編寫者和維護者所反對的補丁的確存在著一定的
+阻力,但僅此而已。如果你被認爲不必要的阻礙了好的工作,那麼這些補丁最終會
+繞過你並進入主線。在Linux內核中,沒有人對任何代碼擁有絕對的否決權。可能除
+了Linus。
+
+在非常罕見的情況下,您可能會看到完全不同的東西:另一個開發人員發布了針對您
+的問題的不同解決方案。在這時,兩個補丁之一可能不會被合併,「我的補丁首先
+發布」不被認爲是一個令人信服的技術論據。如果有別人的補丁取代了你的補丁而進
+入了主線,那麼只有一種方法可以回應你:很高興你的問題解決了,請繼續工作吧。
+以這種方式把某人的工作推到一邊可能導致傷心和氣餒,但是社區會記住你的反應,
+即使很久以後他們已經忘記了誰的補丁真正被合併。
+
diff --git a/Documentation/translations/zh_TW/process/7.AdvancedTopics.rst b/Documentation/translations/zh_TW/process/7.AdvancedTopics.rst
new file mode 100644
index 000000000000..8d121a8c6535
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/7.AdvancedTopics.rst
@@ -0,0 +1,135 @@
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/7.AdvancedTopics.rst <development_advancedtopics>`
+
+:Translator:
+
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+
+:校譯:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+.. _tw_development_advancedtopics:
+
+高級主題
+========
+
+現在,希望您能夠掌握開發流程的工作方式。然而,還有更多的東西要學!本節將介紹
+一些主題,這些主題對希望成爲Linux內核開發過程常規部分的開發人員有幫助。
+
+使用Git管理補丁
+---------------
+
+內核使用分布式版本控制始於2002年初,當時Linus首次開始使用專有的Bitkeeper應用
+程序。雖然BitKeeper存在爭議,但它所體現的軟體版本管理方法卻肯定不是。分布式
+版本控制可以立即加速內核開發項目。現在有好幾種免費的BitKeeper替代品。
+但無論好壞,內核項目都已經選擇了Git作爲其工具。
+
+使用Git管理補丁可以使開發人員的生活更加輕鬆,尤其是隨著補丁數量的增長。Git也
+有其粗糙的邊角和一定的危險性,它是一個年輕和強大的工具,仍然在其開發人員完善
+中。本文檔不會試圖教會讀者如何使用git;這會是個巨長的文檔。相反,這裡的重點
+將是Git如何特別適合內核開發過程。想要加快用Git速度的開發人員可以在以下網站上
+找到更多信息:
+
+	https://git-scm.com/
+
+	https://www.kernel.org/pub/software/scm/git/docs/user-manual.html
+
+同時網上也能找到各種各樣的教程。
+
+在嘗試使用它生成補丁供他人使用之前,第一要務是閱讀上述網頁,對Git的工作方式
+有一個紮實的了解。使用Git的開發人員應能進行拉取主線存儲庫的副本,查詢修訂
+歷史,提交對樹的更改,使用分支等操作。了解Git用於重寫歷史的工具(如rebase)
+也很有用。Git有自己的術語和概念;Git的新用戶應該了解引用、遠程分支、索引、
+快進合併、推拉、游離頭等。一開始可能有點嚇人,但這些概念不難通過一點學習來
+理解。
+
+使用git生成通過電子郵件提交的補丁是提高速度的一個很好的練習。
+
+當您準備好開始建立Git樹供其他人查看時,無疑需要一個可以從中拉取的伺服器。
+如果您有一個可以訪問網際網路的系統,那麼使用git-daemon設置這樣的伺服器相對
+簡單。同時,免費的公共託管網站(例如github)也開始出現在網絡上。成熟的開發
+人員可以在kernel.org上獲得一個帳戶,但這些帳戶並不容易得到;更多有關信息,
+請參閱 https://kernel.org/faq/ 。
+
+正常的Git工作流程涉及到許多分支的使用。每一條開發線都可以分爲單獨的「主題
+分支」,並獨立維護。Git的分支很容易使用,沒有理由不使用它們。而且,在任何
+情況下,您都不應該在任何您打算讓其他人從中拉取的分支中進行開發。應該小心地
+創建公開可用的分支;當開發分支處於完整狀態並已準備好時(而不是之前)才合併
+開發分支的補丁。
+
+Git提供了一些強大的工具,可以讓您重寫開發歷史。一個不方便的補丁(比如說,
+一個打破二分法的補丁,或者有其他一些明顯的缺陷)可以在適當的位置修復,或者
+完全從歷史中消失。一個補丁系列可以被重寫,就好像它是在今天的主線上寫的一樣,
+即使你已經花了幾個月的時間在寫它。可以透明地將更改從一個分支轉移到另一個
+分支。等等。明智地使用git修改歷史的能力可以幫助創建問題更少的乾淨補丁集。
+
+然而,過度使用這種功能可能會導致其他問題,而不僅僅是對創建完美項目歷史的
+簡單癡迷。重寫歷史將重寫該歷史中包含的更改,將經過測試(希望如此)的內核樹
+變爲未經測試的內核樹。除此之外,如果開發人員沒有共享項目歷史,他們就無法
+輕鬆地協作;如果您重寫了其他開發人員拉入他們存儲庫的歷史,您將使這些開發
+人員的生活更加困難。因此,這裡有一個簡單的經驗法則:被導出到其他地方的歷史
+在此後通常被認爲是不可變的。
+
+因此,一旦將一組更改推送到公開可用的伺服器上,就不應該重寫這些更改。如果您
+嘗試強制進行無法快進合併的更改(即不共享同一歷史記錄的更改),Git將嘗試強制
+執行此規則。這可能覆蓋檢查,有時甚至需要重寫導出的樹。在樹之間移動變更集以
+避免linux-next中的衝突就是一個例子。但這種行爲應該是罕見的。這就是爲什麼
+開發應該在私有分支中進行(必要時可以重寫)並且只有在公共分支處於合理的較新
+狀態時才轉移到公共分支中的原因之一。
+
+當主線(或其他一組變更所基於的樹)前進時,很容易與該樹合併以保持領先地位。
+對於一個私有的分支,rebasing 可能是一個很容易跟上另一棵樹的方法,但是一旦
+一棵樹被導出到外界,rebasing就不可取了。一旦發生這種情況,就必須進行完全
+合併(merge)。合併有時是很有意義的,但是過於頻繁的合併會不必要地擾亂歷史。
+在這種情況下建議的做法是不要頻繁合併,通常只在特定的發布點(如主線-rc發布)
+合併。如果您對特定的更改感到緊張,則可以始終在私有分支中執行測試合併。在
+這種情況下,git「rerere」工具很有用;它能記住合併衝突是如何解決的,這樣您
+就不必重複相同的工作。
+
+關於Git這樣的工具的一個最大的反覆抱怨是:補丁從一個存儲庫到另一個存儲庫的
+大量移動使得很容易陷入錯誤建議的變更中,這些變更避開審查雷達進入主線。當內
+核開發人員看到這種情況發生時,他們往往會感到不高興;在Git樹上放置未審閱或
+主題外的補丁可能會影響您將來讓樹被拉取的能力。引用Linus的話:
+
+::
+
+   你可以給我發補丁,但當我從你那裡拉取一個Git補丁時,我需要知道你清楚
+   自己在做什麼,我需要能夠相信事情而 *無需* 手動檢查每個單獨的更改。
+
+(http://lwn.net/articles/224135/)。
+
+爲了避免這種情況,請確保給定分支中的所有補丁都與相關主題緊密相關;「驅動程序
+修復」分支不應更改核心內存管理代碼。而且,最重要的是,不要使用Git樹來繞過
+審查過程。不時的將樹的摘要發布到相關的列表中,在合適時候請求linux-next中
+包含該樹。
+
+如果其他人開始發送補丁以包含到您的樹中,不要忘記審閱它們。還要確保您維護正確
+的作者信息; git 「am」工具在這方面做得最好,但是如果補丁通過第三方轉發給您,
+您可能需要在補丁中添加「From:」行。
+
+請求拉取時,請務必提供所有相關信息:樹的位置、要拉取的分支以及拉取將導致的
+更改。在這方面 git request-pull 命令非常有用;它將按照其他開發人員所期望的
+格式化請求,並檢查以確保您已記得將這些更改推送到公共伺服器。
+
+審閱補丁
+--------
+
+一些讀者顯然會反對將本節與「高級主題」放在一起,因爲即使是剛開始的內核開發人員
+也應該審閱補丁。當然,沒有比查看其他人發布的代碼更好的方法來學習如何在內核環境
+中編程了。此外,審閱者永遠供不應求;通過審閱代碼,您可以對整個流程做出重大貢獻。
+
+審查代碼可能是一副令人生畏的圖景,特別是對一個新的內核開發人員來說,他們
+可能會對公開詢問代碼感到緊張,而這些代碼是由那些有更多經驗的人發布的。不過,
+即使是最有經驗的開發人員編寫的代碼也可以得到改進。也許對(所有)審閱者最好
+的建議是:把審閱評論當成問題而不是批評。詢問「在這條路徑中如何釋放鎖?」
+總是比說「這裡的鎖是錯誤的」更好。
+
+不同的開發人員將從不同的角度審查代碼。部分人會主要關注代碼風格以及代碼行是
+否有尾隨空格。其他人會主要關注補丁作爲一個整體實現的變更是否對內核有好處。
+同時也有人會檢查是否存在鎖問題、堆棧使用過度、可能的安全問題、在其他地方
+發現的代碼重複、足夠的文檔、對性能的不利影響、用戶空間ABI更改等。所有類型
+的檢查,只要它們能引導更好的代碼進入內核,都是受歡迎和值得的。
+
diff --git a/Documentation/translations/zh_TW/process/8.Conclusion.rst b/Documentation/translations/zh_TW/process/8.Conclusion.rst
new file mode 100644
index 000000000000..e35074f31f35
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/8.Conclusion.rst
@@ -0,0 +1,72 @@
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/8.Conclusion.rst <development_conclusion>`
+:Translator:
+
+ 時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+
+:校譯:
+
+ 吳想成 Wu XiangCheng <bobwxc@email.cn>
+ 胡皓文 Hu Haowen <src.res@email.cn>
+
+.. _tw_development_conclusion:
+
+更多信息
+========
+
+關於Linux內核開發和相關主題的信息來源很多。首先是在內核原始碼分發中找到的
+文檔目錄。頂級
+:ref:`Documentation/translations/zh_TW/process/howto.rst <tw_process_howto>`
+文件是一個重要的起點;
+:ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+和 :ref:`Documentation/translations/zh_TW/process/submitting-drivers.rst <tw_submittingdrivers>`
+也是所有內核開發人員都應該閱讀的內容。許多內部內核API都是使用kerneldoc機制
+記錄的;「make htmldocs」或「make pdfdocs」可用於以HTML或PDF格式生成這些文檔
+(儘管某些發行版提供的tex版本會遇到內部限制,無法正確處理文檔)。
+
+不同的網站在各個細節層次上討論內核開發。本文作者想謙虛地建議用 https://lwn.net/
+作爲來源;有關許多特定內核主題的信息可以通過以下網址的 LWN 內核索引找到:
+
+  http://lwn.net/kernel/index/
+
+除此之外,內核開發人員的一個寶貴資源是:
+
+  https://kernelnewbies.org/
+
+當然,也不應該忘記 https://kernel.org/ ,這是內核發布信息的最終位置。
+
+關於內核開發有很多書:
+
+  《Linux設備驅動程序》第三版(Jonathan Corbet、Alessandro Rubini和Greg Kroah Hartman)
+  線上版本在 http://lwn.net/kernel/ldd3/
+
+  《Linux內核設計與實現》(Robert Love)
+
+  《深入理解Linux內核》(Daniel Bovet和Marco Cesati)
+
+然而,所有這些書都有一個共同的缺點:它們上架時就往往有些過時,而且已經上架
+一段時間了。不過,在那裡還是可以找到相當多的好信息。
+
+有關git的文檔,請訪問:
+
+  https://www.kernel.org/pub/software/scm/git/docs/
+
+  https://www.kernel.org/pub/software/scm/git/docs/user-manual.html
+
+結論
+====
+
+祝賀所有通過這篇冗長的文檔的人。希望它能夠幫助您理解Linux內核是如何開發的,
+以及您如何參與這個過程。
+
+最後,重要的是參與。任何開源軟體項目都不會超過其貢獻者投入其中的總和。Linux
+內核的發展速度和以前一樣快,因爲它得到了大量開發人員的幫助,他們都在努力使它
+變得更好。內核是一個最成功的例子,說明了當成千上萬的人爲了一個共同的目標一起
+工作時,可以做出什麼。
+
+不過,內核總是可以從更大的開發人員基礎中獲益。總有更多的工作要做。但是同樣
+重要的是,Linux生態系統中的大多數其他參與者可以通過爲內核做出貢獻而受益。使
+代碼進入主線是提高代碼質量、降低維護和分發成本、提高對內核開發方向的影響程度
+等的關鍵。這是一種共贏的局面。啓動你的編輯器,來加入我們吧;你會非常受歡迎的。
+
diff --git a/Documentation/translations/zh_TW/process/code-of-conduct-interpretation.rst b/Documentation/translations/zh_TW/process/code-of-conduct-interpretation.rst
new file mode 100644
index 000000000000..457ae49ba4d4
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/code-of-conduct-interpretation.rst
@@ -0,0 +1,110 @@
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/code-of-conduct-interpretation.rst <code_of_conduct_interpretation>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+.. _tw_code_of_conduct_interpretation:
+
+Linux內核貢獻者契約行為準則解釋
+===============================
+
+:ref:`tw_code_of_conduct` 準則是一個通用文檔,旨在爲幾乎所有開源社區提供一套規則。
+每個開源社區都是獨一無二的,Linux內核也不例外。因此,本文描述了Linux內核社區中
+如何解釋它。我們也不希望這種解釋隨著時間的推移是靜態的,並將根據需要進行調整。
+
+與開發軟體的「傳統」方法相比,Linux內核開發工作是一個非常個人化的過程。你的貢獻
+和背後的想法將被仔細審查,往往導致批判和批評。審查將幾乎總是需要改進,材料才
+能包括在內核中。要知道這是因爲所有相關人員都希望看到Linux整體成功的最佳解決方
+案。這個開發過程已經被證明可以創建有史以來最健壯的作業系統內核,我們不想做任何
+事情來導致提交質量和最終結果的下降。
+
+維護者
+------
+
+行為準則多次使用「維護者」一詞。在內核社區中,「維護者」是負責子系統、驅動程序或
+文件的任何人,並在內核原始碼樹的維護者文件中列出。
+
+責任
+----
+
+《行為準則》提到了維護人員的權利和責任,這需要進一步澄清。
+
+首先,最重要的是,有一個合理的期望是由維護人員通過實例來領導。
+
+也就是說,我們的社區是廣闊的,對維護者沒有新的要求,他們單方面處理其他人在
+他們活躍的社區的行爲。這一責任由我們所有人承擔,最終《行為準則》記錄了最終的
+上訴路徑,以防有關行爲問題的問題懸而未決。
+
+維護人員應該願意在出現問題時提供幫助,並在需要時與社區中的其他人合作。如果您
+不確定如何處理出現的情況,請不要害怕聯繫技術諮詢委員會(TAB)或其他維護人員。
+除非您願意,否則不會將其視爲違規報告。如果您不確定是否該聯繫TAB 或任何其他維
+護人員,請聯繫我們的衝突調解人 Mishi Choudhary <mishi@linux.com>。
+
+最後,「善待對方」才是每個人的最終目標。我們知道每個人都是人,有時我們都會失敗,
+但我們所有人的首要目標應該是努力友好地解決問題。執行行為準則將是最後的選擇。
+
+我們的目標是創建一個強大的、技術先進的作業系統,以及所涉及的技術複雜性,這自
+然需要專業知識和決策。
+
+所需的專業知識因貢獻領域而異。它主要由上下文和技術複雜性決定,其次由貢獻者和
+維護者的期望決定。
+
+專家的期望和決策都要經過討論,但在最後,爲了取得進展,必須能夠做出決策。這一
+特權掌握在維護人員和項目領導的手中,預計將善意使用。
+
+因此,設定專業知識期望、作出決定和拒絕不適當的貢獻不被視爲違反行為準則。
+
+雖然維護人員一般都歡迎新來者,但他們幫助(新)貢獻者克服障礙的能力有限,因此
+他們必須確定優先事項。這也不應被視爲違反了行為準則。內核社區意識到這一點,並
+以各種形式提供入門級節目,如 kernelnewbies.org 。
+
+範圍
+----
+
+Linux內核社區主要在一組公共電子郵件列表上進行交互,這些列表分布在由多個不同
+公司或個人控制的多個不同伺服器上。所有這些列表都在內核原始碼樹中的
+MAINTAINERS 文件中定義。發送到這些郵件列表的任何電子郵件都被視爲包含在行爲
+準則中。
+
+使用 kernel.org bugzilla和其他子系統bugzilla 或bug跟蹤工具的開發人員應該遵循
+行為準則的指導原則。Linux內核社區沒有「官方」項目電子郵件地址或「官方」社交媒體
+地址。使用kernel.org電子郵件帳戶執行的任何活動必須遵循爲kernel.org發布的行爲
+準則,就像任何使用公司電子郵件帳戶的個人必須遵循該公司的特定規則一樣。
+
+行為準則並不禁止在郵件列表消息、內核更改日誌消息或代碼注釋中繼續包含名稱、
+電子郵件地址和相關注釋。
+
+其他論壇中的互動包括在適用於上述論壇的任何規則中,通常不包括在行為準則中。
+除了在極端情況下可考慮的例外情況。
+
+提交給內核的貢獻應該使用適當的語言。在行為準則之前已經存在的內容現在不會被
+視爲違反。然而,不適當的語言可以被視爲一個bug;如果任何相關方提交補丁,
+這樣的bug將被更快地修復。當前屬於用戶/內核API的一部分的表達式,或者反映已
+發布標準或規範中使用的術語的表達式,不被視爲bug。
+
+執行
+----
+
+行為準則中列出的地址屬於行為準則委員會。https://kernel.org/code-of-conduct.html
+列出了在任何給定時間接收這些電子郵件的確切成員。成員不能訪問在加入委員會之前
+或離開委員會之後所做的報告。
+
+最初的行為準則委員會由TAB的志願者以及作爲中立第三方的專業調解人組成。委員會
+的首要任務是建立文件化的流程,並將其公開。
+
+如果報告人不希望將整個委員會納入投訴或關切,可直接聯繫委員會的任何成員,包括
+調解人。
+
+行為準則委員會根據流程審查案例(見上文),並根據需要和適當與TAB協商,例如請求
+和接收有關內核社區的信息。
+
+委員會做出的任何決定都將提交到表中,以便在必要時與相關維護人員一起執行。行爲
+準則委員會的決定可以通過三分之二的投票推翻。
+
+每季度,行為準則委員會和標籤將提供一份報告,概述行為準則委員會收到的匿名報告
+及其狀態,以及任何否決決定的細節,包括完整和可識別的投票細節。
+
+我們希望在啓動期之後爲行為準則委員會人員配備建立一個不同的流程。發生此情況時,
+將使用該信息更新此文檔。
+
diff --git a/Documentation/translations/zh_TW/process/code-of-conduct.rst b/Documentation/translations/zh_TW/process/code-of-conduct.rst
new file mode 100644
index 000000000000..b44fea4e167a
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/code-of-conduct.rst
@@ -0,0 +1,74 @@
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/code-of-conduct.rst <code_of_conduct>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+.. _tw_code_of_conduct:
+
+貢獻者契約行為準則
+++++++++++++++++++
+
+我們的誓言
+==========
+
+爲了營造一個開放、友好的環境,我們作爲貢獻者和維護人承諾,讓我們的社區和參
+與者,擁有一個無騷擾的體驗,無論年齡、體型、殘疾、種族、性別特徵、性別認同
+和表達、經驗水平、教育程度、社會狀況,經濟地位、國籍、個人外貌、種族、宗教
+或性身份和取向。
+
+我們的標準
+==========
+
+有助於創造積極環境的行爲包括:
+
+* 使用歡迎和包容的語言
+* 尊重不同的觀點和經驗
+* 優雅地接受建設性的批評
+* 關注什麼對社區最有利
+* 對其他社區成員表示同情
+
+參與者的不可接受行爲包括:
+
+* 使用性意味的語言或意象以及不受歡迎的性注意或者更過分的行爲
+* 煽動、侮辱/貶損評論以及個人或政治攻擊
+* 公開或私下騷擾
+* 未經明確許可,發布他人的私人信息,如物理或電子地址。
+* 在專業場合被合理認爲不適當的其他行爲
+
+我們的責任
+==========
+
+維護人員負責澄清可接受行爲的標準,並應針對任何不可接受行爲採取適當和公平的
+糾正措施。
+
+維護人員有權和責任刪除、編輯或拒絕與本行為準則不一致的評論、承諾、代碼、
+wiki編輯、問題和其他貢獻,或暫時或永久禁止任何貢獻者從事他們認爲不適當、
+威脅、冒犯或有害的其他行爲。
+
+範圍
+====
+
+當個人代表項目或其社區時,本行為準則既適用於項目空間,也適用於公共空間。
+代表一個項目或社區的例子包括使用一個正式的項目電子郵件地址,通過一個正式
+的社交媒體帳戶發布,或者在在線或離線事件中擔任指定的代表。項目維護人員可以
+進一步定義和澄清項目的表示。
+
+執行
+====
+
+如有濫用、騷擾或其他不可接受的行爲,可聯繫行為準則委員會<conduct@kernel.org>。
+所有投訴都將接受審查和調查,並將得到必要和適當的答覆。行為準則委員會有義務
+對事件報告人保密。具體執行政策的進一步細節可單獨公布。
+
+歸屬
+====
+
+本行為準則改編自《貢獻者契約》,版本1.4,可從
+https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 獲取。
+
+解釋
+====
+
+有關Linux內核社區如何解釋此文檔,請參閱 :ref:`tw_code_of_conduct_interpretation`
+
diff --git a/Documentation/translations/zh_TW/process/coding-style.rst b/Documentation/translations/zh_TW/process/coding-style.rst
new file mode 100644
index 000000000000..21a9fe298c86
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/coding-style.rst
@@ -0,0 +1,956 @@
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/coding-style.rst <codingstyle>`
+
+.. _tw_codingstyle:
+
+譯者::
+
+  中文版維護者: 張樂 Zhang Le <r0bertz@gentoo.org>
+  中文版翻譯者: 張樂 Zhang Le <r0bertz@gentoo.org>
+  中文版校譯者: 王聰 Wang Cong <xiyou.wangcong@gmail.com>
+                 wheelz <kernel.zeng@gmail.com>
+                 管旭東 Xudong Guan <xudong.guan@gmail.com>
+                 Li Zefan <lizf@cn.fujitsu.com>
+                 Wang Chen <wangchen@cn.fujitsu.com>
+                 Hu Haowen <src.res@email.cn>
+
+Linux 內核代碼風格
+=========================
+
+這是一個簡短的文檔,描述了 linux 內核的首選代碼風格。代碼風格是因人而異的,
+而且我不願意把自己的觀點強加給任何人,但這就像我去做任何事情都必須遵循的原則
+那樣,我也希望在絕大多數事上保持這種的態度。請 (在寫代碼時) 至少考慮一下這裡
+的代碼風格。
+
+首先,我建議你列印一份 GNU 代碼規範,然後不要讀。燒了它,這是一個具有重大象徵
+性意義的動作。
+
+不管怎樣,現在我們開始:
+
+
+1) 縮進
+--------------
+
+制表符是 8 個字符,所以縮進也是 8 個字符。有些異端運動試圖將縮進變爲 4 (甚至
+2!) 字符深,這幾乎相當於嘗試將圓周率的值定義爲 3。
+
+理由:縮進的全部意義就在於清楚的定義一個控制塊起止於何處。尤其是當你盯著你的
+屏幕連續看了 20 小時之後,你將會發現大一點的縮進會使你更容易分辨縮進。
+
+現在,有些人會抱怨 8 個字符的縮進會使代碼向右邊移動的太遠,在 80 個字符的終端
+屏幕上就很難讀這樣的代碼。這個問題的答案是,如果你需要 3 級以上的縮進,不管用
+何種方式你的代碼已經有問題了,應該修正你的程序。
+
+簡而言之,8 個字符的縮進可以讓代碼更容易閱讀,還有一個好處是當你的函數嵌套太
+深的時候可以給你警告。留心這個警告。
+
+在 switch 語句中消除多級縮進的首選的方式是讓 ``switch`` 和從屬於它的 ``case``
+標籤對齊於同一列,而不要 ``兩次縮進`` ``case`` 標籤。比如:
+
+.. code-block:: c
+
+	switch (suffix) {
+	case 'G':
+	case 'g':
+		mem <<= 30;
+		break;
+	case 'M':
+	case 'm':
+		mem <<= 20;
+		break;
+	case 'K':
+	case 'k':
+		mem <<= 10;
+		fallthrough;
+	default:
+		break;
+	}
+
+不要把多個語句放在一行里,除非你有什麼東西要隱藏:
+
+.. code-block:: c
+
+	if (condition) do_this;
+	  do_something_everytime;
+
+也不要在一行里放多個賦值語句。內核代碼風格超級簡單。就是避免可能導致別人誤讀
+的表達式。
+
+除了注釋、文檔和 Kconfig 之外,不要使用空格來縮進,前面的例子是例外,是有意爲
+之。
+
+選用一個好的編輯器,不要在行尾留空格。
+
+
+2) 把長的行和字符串打散
+------------------------------
+
+代碼風格的意義就在於使用平常使用的工具來維持代碼的可讀性和可維護性。
+
+每一行的長度的限制是 80 列,我們強烈建議您遵守這個慣例。
+
+長於 80 列的語句要打散成有意義的片段。除非超過 80 列能顯著增加可讀性,並且不
+會隱藏信息。子片段要明顯短於母片段,並明顯靠右。這同樣適用於有著很長參數列表
+的函數頭。然而,絕對不要打散對用戶可見的字符串,例如 printk 信息,因爲這樣就
+很難對它們 grep。
+
+
+3) 大括號和空格的放置
+------------------------------
+
+C 語言風格中另外一個常見問題是大括號的放置。和縮進大小不同,選擇或棄用某种放
+置策略並沒有多少技術上的原因,不過首選的方式,就像 Kernighan 和 Ritchie 展示
+給我們的,是把起始大括號放在行尾,而把結束大括號放在行首,所以:
+
+.. code-block:: c
+
+	if (x is true) {
+		we do y
+	}
+
+這適用於所有的非函數語句塊 (if, switch, for, while, do)。比如:
+
+.. code-block:: c
+
+	switch (action) {
+	case KOBJ_ADD:
+		return "add";
+	case KOBJ_REMOVE:
+		return "remove";
+	case KOBJ_CHANGE:
+		return "change";
+	default:
+		return NULL;
+	}
+
+不過,有一個例外,那就是函數:函數的起始大括號放置於下一行的開頭,所以:
+
+.. code-block:: c
+
+	int function(int x)
+	{
+		body of function
+	}
+
+全世界的異端可能會抱怨這個不一致性是... 呃... 不一致的,不過所有思維健全的人
+都知道 (a) K&R 是 **正確的** 並且 (b) K&R 是正確的。此外,不管怎樣函數都是特
+殊的 (C 函數是不能嵌套的)。
+
+注意結束大括號獨自占據一行,除非它後面跟著同一個語句的剩餘部分,也就是 do 語
+句中的 "while" 或者 if 語句中的 "else",像這樣:
+
+.. code-block:: c
+
+	do {
+		body of do-loop
+	} while (condition);
+
+和
+
+.. code-block:: c
+
+	if (x == y) {
+		..
+	} else if (x > y) {
+		...
+	} else {
+		....
+	}
+
+理由:K&R。
+
+也請注意這種大括號的放置方式也能使空 (或者差不多空的) 行的數量最小化,同時不
+失可讀性。因此,由於你的屏幕上的新行是不可再生資源 (想想 25 行的終端屏幕),你
+將會有更多的空行來放置注釋。
+
+當只有一個單獨的語句的時候,不用加不必要的大括號。
+
+.. code-block:: c
+
+	if (condition)
+		action();
+
+和
+
+.. code-block:: c
+
+	if (condition)
+		do_this();
+	else
+		do_that();
+
+這並不適用於只有一個條件分支是單語句的情況;這時所有分支都要使用大括號:
+
+.. code-block:: c
+
+	if (condition) {
+		do_this();
+		do_that();
+	} else {
+		otherwise();
+	}
+
+3.1) 空格
+********************
+
+Linux 內核的空格使用方式 (主要) 取決於它是用於函數還是關鍵字。(大多數) 關鍵字
+後要加一個空格。值得注意的例外是 sizeof, typeof, alignof 和 __attribute__,這
+些關鍵字某些程度上看起來更像函數 (它們在 Linux 里也常常伴隨小括號而使用,儘管
+在 C 里這樣的小括號不是必需的,就像 ``struct fileinfo info;`` 聲明過後的
+``sizeof info``)。
+
+所以在這些關鍵字之後放一個空格::
+
+	if, switch, case, for, do, while
+
+但是不要在 sizeof, typeof, alignof 或者 __attribute__ 這些關鍵字之後放空格。
+例如,
+
+.. code-block:: c
+
+	s = sizeof(struct file);
+
+不要在小括號里的表達式兩側加空格。這是一個 **反例** :
+
+.. code-block:: c
+
+	s = sizeof( struct file );
+
+當聲明指針類型或者返回指針類型的函數時, ``*`` 的首選使用方式是使之靠近變量名
+或者函數名,而不是靠近類型名。例子:
+
+.. code-block:: c
+
+	char *linux_banner;
+	unsigned long long memparse(char *ptr, char **retptr);
+	char *match_strdup(substring_t *s);
+
+在大多數二元和三元操作符兩側使用一個空格,例如下面所有這些操作符::
+
+	=  +  -  <  >  *  /  %  |  &  ^  <=  >=  ==  !=  ?  :
+
+但是一元操作符後不要加空格::
+
+	&  *  +  -  ~  !  sizeof  typeof  alignof  __attribute__  defined
+
+後綴自加和自減一元操作符前不加空格::
+
+	++  --
+
+前綴自加和自減一元操作符後不加空格::
+
+	++  --
+
+``.`` 和 ``->`` 結構體成員操作符前後不加空格。
+
+不要在行尾留空白。有些可以自動縮進的編輯器會在新行的行首加入適量的空白,然後
+你就可以直接在那一行輸入代碼。不過假如你最後沒有在那一行輸入代碼,有些編輯器
+就不會移除已經加入的空白,就像你故意留下一個只有空白的行。包含行尾空白的行就
+這樣產生了。
+
+當 git 發現補丁包含了行尾空白的時候會警告你,並且可以應你的要求去掉行尾空白;
+不過如果你是正在打一系列補丁,這樣做會導致後面的補丁失敗,因爲你改變了補丁的
+上下文。
+
+
+4) 命名
+------------------------------
+
+C 是一個簡樸的語言,你的命名也應該這樣。和 Modula-2 和 Pascal 程式設計師不同,
+C 程式設計師不使用類似 ThisVariableIsATemporaryCounter 這樣華麗的名字。C 程式設計師會
+稱那個變量爲 ``tmp`` ,這樣寫起來會更容易,而且至少不會令其難於理解。
+
+不過,雖然混用大小寫的名字是不提倡使用的,但是全局變量還是需要一個具描述性的
+名字。稱一個全局函數爲 ``foo`` 是一個難以饒恕的錯誤。
+
+全局變量 (只有當你 **真正** 需要它們的時候再用它) 需要有一個具描述性的名字,就
+像全局函數。如果你有一個可以計算活動用戶數量的函數,你應該叫它
+``count_active_users()`` 或者類似的名字,你不應該叫它 ``cntuser()`` 。
+
+在函數名中包含函數類型 (所謂的匈牙利命名法) 是腦子出了問題——編譯器知道那些類
+型而且能夠檢查那些類型,這樣做只能把程式設計師弄糊塗了。難怪微軟總是製造出有問題
+的程序。
+
+本地變量名應該簡短,而且能夠表達相關的含義。如果你有一些隨機的整數型的循環計
+數器,它應該被稱爲 ``i`` 。叫它 ``loop_counter`` 並無益處,如果它沒有被誤解的
+可能的話。類似的, ``tmp`` 可以用來稱呼任意類型的臨時變量。
+
+如果你怕混淆了你的本地變量名,你就遇到另一個問題了,叫做函數增長荷爾蒙失衡綜
+合症。請看第六章 (函數)。
+
+
+5) Typedef
+-----------
+
+不要使用類似 ``vps_t`` 之類的東西。
+
+對結構體和指針使用 typedef 是一個 **錯誤** 。當你在代碼里看到:
+
+.. code-block:: c
+
+	vps_t a;
+
+這代表什麼意思呢?
+
+相反,如果是這樣
+
+.. code-block:: c
+
+	struct virtual_container *a;
+
+你就知道 ``a`` 是什麼了。
+
+很多人認爲 typedef ``能提高可讀性`` 。實際不是這樣的。它們只在下列情況下有用:
+
+ (a) 完全不透明的對象 (這種情況下要主動使用 typedef 來 **隱藏** 這個對象實際上
+     是什麼)。
+
+     例如: ``pte_t`` 等不透明對象,你只能用合適的訪問函數來訪問它們。
+
+     .. note::
+
+       不透明性和 "訪問函數" 本身是不好的。我們使用 pte_t 等類型的原因在於真
+       的是完全沒有任何共用的可訪問信息。
+
+ (b) 清楚的整數類型,如此,這層抽象就可以 **幫助** 消除到底是 ``int`` 還是
+     ``long`` 的混淆。
+
+     u8/u16/u32 是完全沒有問題的 typedef,不過它們更符合類別 (d) 而不是這裡。
+
+     .. note::
+
+       要這樣做,必須事出有因。如果某個變量是 ``unsigned long`` ,那麼沒有必要
+
+	typedef unsigned long myflags_t;
+
+     不過如果有一個明確的原因,比如它在某種情況下可能會是一個 ``unsigned int``
+     而在其他情況下可能爲 ``unsigned long`` ,那麼就不要猶豫,請務必使用
+     typedef。
+
+ (c) 當你使用 sparse 按字面的創建一個 **新** 類型來做類型檢查的時候。
+
+ (d) 和標準 C99 類型相同的類型,在某些例外的情況下。
+
+     雖然讓眼睛和腦筋來適應新的標準類型比如 ``uint32_t`` 不需要花很多時間,可
+     是有些人仍然拒絕使用它們。
+
+     因此,Linux 特有的等同於標準類型的 ``u8/u16/u32/u64`` 類型和它們的有符號
+     類型是被允許的——儘管在你自己的新代碼中,它們不是強制要求要使用的。
+
+     當編輯已經使用了某個類型集的已有代碼時,你應該遵循那些代碼中已經做出的選
+     擇。
+
+ (e) 可以在用戶空間安全使用的類型。
+
+     在某些用戶空間可見的結構體裡,我們不能要求 C99 類型而且不能用上面提到的
+     ``u32`` 類型。因此,我們在與用戶空間共享的所有結構體中使用 __u32 和類似
+     的類型。
+
+可能還有其他的情況,不過基本的規則是 **永遠不要** 使用 typedef,除非你可以明
+確的應用上述某個規則中的一個。
+
+總的來說,如果一個指針或者一個結構體裡的元素可以合理的被直接訪問到,那麼它們
+就不應該是一個 typedef。
+
+
+6) 函數
+------------------------------
+
+函數應該簡短而漂亮,並且只完成一件事情。函數應該可以一屏或者兩屏顯示完 (我們
+都知道 ISO/ANSI 屏幕大小是 80x24),只做一件事情,而且把它做好。
+
+一個函數的最大長度是和該函數的複雜度和縮進級數成反比的。所以,如果你有一個理
+論上很簡單的只有一個很長 (但是簡單) 的 case 語句的函數,而且你需要在每個 case
+里做很多很小的事情,這樣的函數儘管很長,但也是可以的。
+
+不過,如果你有一個複雜的函數,而且你懷疑一個天分不是很高的高中一年級學生可能
+甚至搞不清楚這個函數的目的,你應該嚴格遵守前面提到的長度限制。使用輔助函數,
+並爲之取個具描述性的名字 (如果你覺得它們的性能很重要的話,可以讓編譯器內聯它
+們,這樣的效果往往會比你寫一個複雜函數的效果要好。)
+
+函數的另外一個衡量標準是本地變量的數量。此數量不應超過 5-10 個,否則你的函數
+就有問題了。重新考慮一下你的函數,把它分拆成更小的函數。人的大腦一般可以輕鬆
+的同時跟蹤 7 個不同的事物,如果再增多的話,就會糊塗了。即便你聰穎過人,你也可
+能會記不清你 2 個星期前做過的事情。
+
+在源文件里,使用空行隔開不同的函數。如果該函數需要被導出,它的 **EXPORT** 宏
+應該緊貼在它的結束大括號之下。比如:
+
+.. code-block:: c
+
+	int system_is_up(void)
+	{
+		return system_state == SYSTEM_RUNNING;
+	}
+	EXPORT_SYMBOL(system_is_up);
+
+在函數原型中,包含函數名和它們的數據類型。雖然 C 語言裡沒有這樣的要求,在
+Linux 里這是提倡的做法,因爲這樣可以很簡單的給讀者提供更多的有價值的信息。
+
+
+7) 集中的函數退出途徑
+------------------------------
+
+雖然被某些人聲稱已經過時,但是 goto 語句的等價物還是經常被編譯器所使用,具體
+形式是無條件跳轉指令。
+
+當一個函數從多個位置退出,並且需要做一些類似清理的常見操作時,goto 語句就很方
+便了。如果並不需要清理操作,那麼直接 return 即可。
+
+選擇一個能夠說明 goto 行爲或它爲何存在的標籤名。如果 goto 要釋放 ``buffer``,
+一個不錯的名字可以是 ``out_free_buffer:`` 。別去使用像 ``err1:`` 和 ``err2:``
+這樣的GW_BASIC 名稱,因爲一旦你添加或刪除了 (函數的) 退出路徑,你就必須對它們
+重新編號,這樣會難以去檢驗正確性。
+
+使用 goto 的理由是:
+
+- 無條件語句容易理解和跟蹤
+- 嵌套程度減小
+- 可以避免由於修改時忘記更新個別的退出點而導致錯誤
+- 讓編譯器省去刪除冗餘代碼的工作 ;)
+
+.. code-block:: c
+
+	int fun(int a)
+	{
+		int result = 0;
+		char *buffer;
+
+		buffer = kmalloc(SIZE, GFP_KERNEL);
+		if (!buffer)
+			return -ENOMEM;
+
+		if (condition1) {
+			while (loop1) {
+				...
+			}
+			result = 1;
+			goto out_free_buffer;
+		}
+		...
+	out_free_buffer:
+		kfree(buffer);
+		return result;
+	}
+
+一個需要注意的常見錯誤是 ``一個 err 錯誤`` ,就像這樣:
+
+.. code-block:: c
+
+	err:
+		kfree(foo->bar);
+		kfree(foo);
+		return ret;
+
+這段代碼的錯誤是,在某些退出路徑上 ``foo`` 是 NULL。通常情況下,通過把它分離
+成兩個錯誤標籤 ``err_free_bar:`` 和 ``err_free_foo:`` 來修復這個錯誤:
+
+.. code-block:: c
+
+	 err_free_bar:
+		kfree(foo->bar);
+	 err_free_foo:
+		kfree(foo);
+		return ret;
+
+理想情況下,你應該模擬錯誤來測試所有退出路徑。
+
+
+8) 注釋
+------------------------------
+
+注釋是好的,不過有過度注釋的危險。永遠不要在注釋里解釋你的代碼是如何運作的:
+更好的做法是讓別人一看你的代碼就可以明白,解釋寫的很差的代碼是浪費時間。
+
+一般的,你想要你的注釋告訴別人你的代碼做了什麼,而不是怎麼做的。也請你不要把
+注釋放在一個函數體內部:如果函數複雜到你需要獨立的注釋其中的一部分,你很可能
+需要回到第六章看一看。你可以做一些小注釋來註明或警告某些很聰明 (或者槽糕) 的
+做法,但不要加太多。你應該做的,是把注釋放在函數的頭部,告訴人們它做了什麼,
+也可以加上它做這些事情的原因。
+
+當注釋內核 API 函數時,請使用 kernel-doc 格式。請看
+Documentation/doc-guide/ 和 scripts/kernel-doc 以獲得詳細信息。
+
+長 (多行) 注釋的首選風格是:
+
+.. code-block:: c
+
+	/*
+	 * This is the preferred style for multi-line
+	 * comments in the Linux kernel source code.
+	 * Please use it consistently.
+	 *
+	 * Description:  A column of asterisks on the left side,
+	 * with beginning and ending almost-blank lines.
+	 */
+
+對於在 net/ 和 drivers/net/ 的文件,首選的長 (多行) 注釋風格有些不同。
+
+.. code-block:: c
+
+	/* The preferred comment style for files in net/ and drivers/net
+	 * looks like this.
+	 *
+	 * It is nearly the same as the generally preferred comment style,
+	 * but there is no initial almost-blank line.
+	 */
+
+注釋數據也是很重要的,不管是基本類型還是衍生類型。爲了方便實現這一點,每一行
+應只聲明一個數據 (不要使用逗號來一次聲明多個數據)。這樣你就有空間來爲每個數據
+寫一段小注釋來解釋它們的用途了。
+
+
+9) 你已經把事情弄糟了
+------------------------------
+
+這沒什麼,我們都是這樣。可能你的使用了很長時間 Unix 的朋友已經告訴你
+``GNU emacs`` 能自動幫你格式化 C 原始碼,而且你也注意到了,確實是這樣,不過它
+所使用的默認值和我們想要的相去甚遠 (實際上,甚至比隨機打的還要差——無數個猴子
+在 GNU emacs 里打字永遠不會創造出一個好程序) (譯註:Infinite Monkey Theorem)
+
+所以你要麼放棄 GNU emacs,要麼改變它讓它使用更合理的設定。要採用後一個方案,
+你可以把下面這段粘貼到你的 .emacs 文件里。
+
+.. code-block:: none
+
+  (defun c-lineup-arglist-tabs-only (ignored)
+    "Line up argument lists by tabs, not spaces"
+    (let* ((anchor (c-langelem-pos c-syntactic-element))
+           (column (c-langelem-2nd-pos c-syntactic-element))
+           (offset (- (1+ column) anchor))
+           (steps (floor offset c-basic-offset)))
+      (* (max steps 1)
+         c-basic-offset)))
+
+  (dir-locals-set-class-variables
+   'linux-kernel
+   '((c-mode . (
+          (c-basic-offset . 8)
+          (c-label-minimum-indentation . 0)
+          (c-offsets-alist . (
+                  (arglist-close         . c-lineup-arglist-tabs-only)
+                  (arglist-cont-nonempty .
+		      (c-lineup-gcc-asm-reg c-lineup-arglist-tabs-only))
+                  (arglist-intro         . +)
+                  (brace-list-intro      . +)
+                  (c                     . c-lineup-C-comments)
+                  (case-label            . 0)
+                  (comment-intro         . c-lineup-comment)
+                  (cpp-define-intro      . +)
+                  (cpp-macro             . -1000)
+                  (cpp-macro-cont        . +)
+                  (defun-block-intro     . +)
+                  (else-clause           . 0)
+                  (func-decl-cont        . +)
+                  (inclass               . +)
+                  (inher-cont            . c-lineup-multi-inher)
+                  (knr-argdecl-intro     . 0)
+                  (label                 . -1000)
+                  (statement             . 0)
+                  (statement-block-intro . +)
+                  (statement-case-intro  . +)
+                  (statement-cont        . +)
+                  (substatement          . +)
+                  ))
+          (indent-tabs-mode . t)
+          (show-trailing-whitespace . t)
+          ))))
+
+  (dir-locals-set-directory-class
+   (expand-file-name "~/src/linux-trees")
+   'linux-kernel)
+
+這會讓 emacs 在 ``~/src/linux-trees`` 下的 C 源文件獲得更好的內核代碼風格。
+
+不過就算你嘗試讓 emacs 正確的格式化代碼失敗了,也並不意味著你失去了一切:還可
+以用 ``indent`` 。
+
+不過,GNU indent 也有和 GNU emacs 一樣有問題的設定,所以你需要給它一些命令選
+項。不過,這還不算太糟糕,因爲就算是 GNU indent 的作者也認同 K&R 的權威性
+(GNU 的人並不是壞人,他們只是在這個問題上被嚴重的誤導了),所以你只要給 indent
+指定選項 ``-kr -i8`` (代表 ``K&R,8 字符縮進``),或使用 ``scripts/Lindent``
+這樣就可以以最時髦的方式縮進原始碼。
+
+``indent`` 有很多選項,特別是重新格式化注釋的時候,你可能需要看一下它的手冊。
+不過記住: ``indent`` 不能修正壞的編程習慣。
+
+
+10) Kconfig 配置文件
+------------------------------
+
+對於遍布源碼樹的所有 Kconfig* 配置文件來說,它們縮進方式有所不同。緊挨著
+``config`` 定義的行,用一個制表符縮進,然而 help 信息的縮進則額外增加 2 個空
+格。舉個例子::
+
+  config AUDIT
+	bool "Auditing support"
+	depends on NET
+	help
+	  Enable auditing infrastructure that can be used with another
+	  kernel subsystem, such as SELinux (which requires this for
+	  logging of avc messages output).  Does not do system-call
+	  auditing without CONFIG_AUDITSYSCALL.
+
+而那些危險的功能 (比如某些文件系統的寫支持) 應該在它們的提示字符串里顯著的聲
+明這一點::
+
+  config ADFS_FS_RW
+	bool "ADFS write support (DANGEROUS)"
+	depends on ADFS_FS
+	...
+
+要查看配置文件的完整文檔,請看 Documentation/kbuild/kconfig-language.rst。
+
+
+11) 數據結構
+------------------------------
+
+如果一個數據結構,在創建和銷毀它的單線執行環境之外可見,那麼它必須要有一個引
+用計數器。內核里沒有垃圾收集 (並且內核之外的垃圾收集慢且效率低下),這意味著你
+絕對需要記錄你對這種數據結構的使用情況。
+
+引用計數意味著你能夠避免上鎖,並且允許多個用戶並行訪問這個數據結構——而不需要
+擔心這個數據結構僅僅因爲暫時不被使用就消失了,那些用戶可能不過是沉睡了一陣或
+者做了一些其他事情而已。
+
+注意上鎖 **不能** 取代引用計數。上鎖是爲了保持數據結構的一致性,而引用計數是一
+個內存管理技巧。通常二者都需要,不要把兩個搞混了。
+
+很多數據結構實際上有 2 級引用計數,它們通常有不同 ``類`` 的用戶。子類計數器統
+計子類用戶的數量,每當子類計數器減至零時,全局計數器減一。
+
+這種 ``多級引用計數`` 的例子可以在內存管理 (``struct mm_struct``: mm_users 和
+mm_count),和文件系統 (``struct super_block``: s_count 和 s_active) 中找到。
+
+記住:如果另一個執行線索可以找到你的數據結構,但這個數據結構沒有引用計數器,
+這裡幾乎肯定是一個 bug。
+
+
+12) 宏,枚舉和RTL
+------------------------------
+
+用於定義常量的宏的名字及枚舉里的標籤需要大寫。
+
+.. code-block:: c
+
+	#define CONSTANT 0x12345
+
+在定義幾個相關的常量時,最好用枚舉。
+
+宏的名字請用大寫字母,不過形如函數的宏的名字可以用小寫字母。
+
+一般的,如果能寫成內聯函數就不要寫成像函數的宏。
+
+含有多個語句的宏應該被包含在一個 do-while 代碼塊里:
+
+.. code-block:: c
+
+	#define macrofun(a, b, c)			\
+		do {					\
+			if (a == 5)			\
+				do_this(b, c);		\
+		} while (0)
+
+使用宏的時候應避免的事情:
+
+1) 影響控制流程的宏:
+
+.. code-block:: c
+
+	#define FOO(x)					\
+		do {					\
+			if (blah(x) < 0)		\
+				return -EBUGGERED;	\
+		} while (0)
+
+**非常** 不好。它看起來像一個函數,不過卻能導致 ``調用`` 它的函數退出;不要打
+亂讀者大腦里的語法分析器。
+
+2) 依賴於一個固定名字的本地變量的宏:
+
+.. code-block:: c
+
+	#define FOO(val) bar(index, val)
+
+可能看起來像是個不錯的東西,不過它非常容易把讀代碼的人搞糊塗,而且容易導致看起
+來不相關的改動帶來錯誤。
+
+3) 作爲左值的帶參數的宏: FOO(x) = y;如果有人把 FOO 變成一個內聯函數的話,這
+   種用法就會出錯了。
+
+4) 忘記了優先級:使用表達式定義常量的宏必須將表達式置於一對小括號之內。帶參數
+   的宏也要注意此類問題。
+
+.. code-block:: c
+
+	#define CONSTANT 0x4000
+	#define CONSTEXP (CONSTANT | 3)
+
+5) 在宏里定義類似函數的本地變量時命名衝突:
+
+.. code-block:: c
+
+	#define FOO(x)				\
+	({					\
+		typeof(x) ret;			\
+		ret = calc_ret(x);		\
+		(ret);				\
+	})
+
+ret 是本地變量的通用名字 - __foo_ret 更不容易與一個已存在的變量衝突。
+
+cpp 手冊對宏的講解很詳細。gcc internals 手冊也詳細講解了 RTL,內核里的彙編語
+言經常用到它。
+
+
+13) 列印內核消息
+------------------------------
+
+內核開發者應該是受過良好教育的。請一定注意內核信息的拼寫,以給人以好的印象。
+不要用不規範的單詞比如 ``dont``,而要用 ``do not`` 或者 ``don't`` 。保證這些信
+息簡單明了,無歧義。
+
+內核信息不必以英文句號結束。
+
+在小括號里列印數字 (%d) 沒有任何價值,應該避免這樣做。
+
+<linux/device.h> 里有一些驅動模型診斷宏,你應該使用它們,以確保信息對應於正確
+的設備和驅動,並且被標記了正確的消息級別。這些宏有:dev_err(), dev_warn(),
+dev_info() 等等。對於那些不和某個特定設備相關連的信息,<linux/printk.h> 定義
+了 pr_notice(), pr_info(), pr_warn(), pr_err() 和其他。
+
+寫出好的調試信息可以是一個很大的挑戰;一旦你寫出後,這些信息在遠程除錯時能提
+供極大的幫助。然而列印調試信息的處理方式同列印非調試信息不同。其他 pr_XXX()
+函數能無條件地列印,pr_debug() 卻不;默認情況下它不會被編譯,除非定義了 DEBUG
+或設定了 CONFIG_DYNAMIC_DEBUG。實際這同樣是爲了 dev_dbg(),一個相關約定是在一
+個已經開啓了 DEBUG 時,使用 VERBOSE_DEBUG 來添加 dev_vdbg()。
+
+許多子系統擁有 Kconfig 調試選項來開啓 -DDEBUG 在對應的 Makefile 裡面;在其他
+情況下,特殊文件使用 #define DEBUG。當一條調試信息需要被無條件列印時,例如,
+如果已經包含一個調試相關的 #ifdef 條件,printk(KERN_DEBUG ...) 就可被使用。
+
+
+14) 分配內存
+------------------------------
+
+內核提供了下面的一般用途的內存分配函數:
+kmalloc(), kzalloc(), kmalloc_array(), kcalloc(), vmalloc() 和 vzalloc()。
+請參考 API 文檔以獲取有關它們的詳細信息。
+
+傳遞結構體大小的首選形式是這樣的:
+
+.. code-block:: c
+
+	p = kmalloc(sizeof(*p), ...);
+
+另外一種傳遞方式中,sizeof 的操作數是結構體的名字,這樣會降低可讀性,並且可能
+會引入 bug。有可能指針變量類型被改變時,而對應的傳遞給內存分配函數的 sizeof
+的結果不變。
+
+強制轉換一個 void 指針返回值是多餘的。C 語言本身保證了從 void 指針到其他任何
+指針類型的轉換是沒有問題的。
+
+分配一個數組的首選形式是這樣的:
+
+.. code-block:: c
+
+	p = kmalloc_array(n, sizeof(...), ...);
+
+分配一個零長數組的首選形式是這樣的:
+
+.. code-block:: c
+
+	p = kcalloc(n, sizeof(...), ...);
+
+兩種形式檢查分配大小 n * sizeof(...) 的溢出,如果溢出返回 NULL。
+
+
+15) 內聯弊病
+------------------------------
+
+有一個常見的誤解是 ``內聯`` 是 gcc 提供的可以讓代碼運行更快的一個選項。雖然使
+用內聯函數有時候是恰當的 (比如作爲一種替代宏的方式,請看第十二章),不過很多情
+況下不是這樣。inline 的過度使用會使內核變大,從而使整個系統運行速度變慢。
+因爲體積大內核會占用更多的指令高速緩存,而且會導致 pagecache 的可用內存減少。
+想像一下,一次 pagecache 未命中就會導致一次磁碟尋址,將耗時 5 毫秒。5 毫秒的
+時間內 CPU 能執行很多很多指令。
+
+一個基本的原則是如果一個函數有 3 行以上,就不要把它變成內聯函數。這個原則的一
+個例外是,如果你知道某個參數是一個編譯時常量,而且因爲這個常量你確定編譯器在
+編譯時能優化掉你的函數的大部分代碼,那仍然可以給它加上 inline 關鍵字。
+kmalloc() 內聯函數就是一個很好的例子。
+
+人們經常主張給 static 的而且只用了一次的函數加上 inline,如此不會有任何損失,
+因爲沒有什麼好權衡的。雖然從技術上說這是正確的,但是實際上這種情況下即使不加
+inline gcc 也可以自動使其內聯。而且其他用戶可能會要求移除 inline,由此而來的
+爭論會抵消 inline 自身的潛在價值,得不償失。
+
+
+16) 函數返回值及命名
+------------------------------
+
+函數可以返回多種不同類型的值,最常見的一種是表明函數執行成功或者失敗的值。這樣
+的一個值可以表示爲一個錯誤代碼整數 (-Exxx=失敗,0=成功) 或者一個 ``成功``
+布爾值 (0=失敗,非0=成功)。
+
+混合使用這兩種表達方式是難於發現的 bug 的來源。如果 C 語言本身嚴格區分整形和
+布爾型變量,那麼編譯器就能夠幫我們發現這些錯誤... 不過 C 語言不區分。爲了避免
+產生這種 bug,請遵循下面的慣例::
+
+	如果函數的名字是一個動作或者強制性的命令,那麼這個函數應該返回錯誤代
+	碼整數。如果是一個判斷,那麼函數應該返回一個 "成功" 布爾值。
+
+比如, ``add work`` 是一個命令,所以 add_work() 在成功時返回 0,在失敗時返回
+-EBUSY。類似的,因爲 ``PCI device present`` 是一個判斷,所以 pci_dev_present()
+在成功找到一個匹配的設備時應該返回 1,如果找不到時應該返回 0。
+
+所有 EXPORTed 函數都必須遵守這個慣例,所有的公共函數也都應該如此。私有
+(static) 函數不需要如此,但是我們也推薦這樣做。
+
+返回值是實際計算結果而不是計算是否成功的標誌的函數不受此慣例的限制。一般的,
+他們通過返回一些正常值範圍之外的結果來表示出錯。典型的例子是返回指針的函數,
+他們使用 NULL 或者 ERR_PTR 機制來報告錯誤。
+
+
+17) 不要重新發明內核宏
+------------------------------
+
+頭文件 include/linux/kernel.h 包含了一些宏,你應該使用它們,而不要自己寫一些
+它們的變種。比如,如果你需要計算一個數組的長度,使用這個宏
+
+.. code-block:: c
+
+	#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+類似的,如果你要計算某結構體成員的大小,使用
+
+.. code-block:: c
+
+	#define sizeof_field(t, f) (sizeof(((t*)0)->f))
+
+還有可以做嚴格的類型檢查的 min() 和 max() 宏,如果你需要可以使用它們。你可以
+自己看看那個頭文件里還定義了什麼你可以拿來用的東西,如果有定義的話,你就不應
+在你的代碼里自己重新定義。
+
+
+18) 編輯器模式行和其他需要羅嗦的事情
+--------------------------------------------------
+
+有一些編輯器可以解釋嵌入在源文件里的由一些特殊標記標明的配置信息。比如,emacs
+能夠解釋被標記成這樣的行:
+
+.. code-block:: c
+
+	-*- mode: c -*-
+
+或者這樣的:
+
+.. code-block:: c
+
+	/*
+	Local Variables:
+	compile-command: "gcc -DMAGIC_DEBUG_FLAG foo.c"
+	End:
+	*/
+
+Vim 能夠解釋這樣的標記:
+
+.. code-block:: c
+
+	/* vim:set sw=8 noet */
+
+不要在原始碼中包含任何這樣的內容。每個人都有他自己的編輯器配置,你的源文件不
+應該覆蓋別人的配置。這包括有關縮進和模式配置的標記。人們可以使用他們自己定製
+的模式,或者使用其他可以產生正確的縮進的巧妙方法。
+
+
+19) 內聯彙編
+------------------------------
+
+在特定架構的代碼中,你可能需要內聯彙編與 CPU 和平台相關功能連接。需要這麼做時
+就不要猶豫。然而,當 C 可以完成工作時,不要平白無故地使用內聯彙編。在可能的情
+況下,你可以並且應該用 C 和硬體溝通。
+
+請考慮去寫捆綁通用位元 (wrap common bits) 的內聯彙編的簡單輔助函數,別去重複
+地寫下只有細微差異內聯彙編。記住內聯彙編可以使用 C 參數。
+
+大型,有一定複雜度的彙編函數應該放在 .S 文件內,用相應的 C 原型定義在 C 頭文
+件中。彙編函數的 C 原型應該使用 ``asmlinkage`` 。
+
+你可能需要把彙編語句標記爲 volatile,用來阻止 GCC 在沒發現任何副作用後就把它
+移除了。你不必總是這樣做,儘管,這不必要的舉動會限制優化。
+
+在寫一個包含多條指令的單個內聯彙編語句時,把每條指令用引號分割而且各占一行,
+除了最後一條指令外,在每個指令結尾加上 \n\t,讓彙編輸出時可以正確地縮進下一條
+指令:
+
+.. code-block:: c
+
+	asm ("magic %reg1, #42\n\t"
+	     "more_magic %reg2, %reg3"
+	     : /* outputs */ : /* inputs */ : /* clobbers */);
+
+
+20) 條件編譯
+------------------------------
+
+只要可能,就不要在 .c 文件裡面使用預處理條件 (#if, #ifdef);這樣做讓代碼更難
+閱讀並且更難去跟蹤邏輯。替代方案是,在頭文件中用預處理條件提供給那些 .c 文件
+使用,再給 #else 提供一個空樁 (no-op stub) 版本,然後在 .c 文件內無條件地調用
+那些 (定義在頭文件內的) 函數。這樣做,編譯器會避免爲樁函數 (stub) 的調用生成
+任何代碼,產生的結果是相同的,但邏輯將更加清晰。
+
+最好傾向於編譯整個函數,而不是函數的一部分或表達式的一部分。與其放一個 ifdef
+在表達式內,不如分解出部分或全部表達式,放進一個單獨的輔助函數,並應用預處理
+條件到這個輔助函數內。
+
+如果你有一個在特定配置中,可能變成未使用的函數或變量,編譯器會警告它定義了但
+未使用,把它標記爲 __maybe_unused 而不是將它包含在一個預處理條件中。(然而,如
+果一個函數或變量總是未使用,就直接刪除它。)
+
+在代碼中,儘可能地使用 IS_ENABLED 宏來轉化某個 Kconfig 標記爲 C 的布爾
+表達式,並在一般的 C 條件中使用它:
+
+.. code-block:: c
+
+	if (IS_ENABLED(CONFIG_SOMETHING)) {
+		...
+	}
+
+編譯器會做常量摺疊,然後就像使用 #ifdef 那樣去包含或排除代碼塊,所以這不會帶
+來任何運行時開銷。然而,這種方法依舊允許 C 編譯器查看塊內的代碼,並檢查它的正
+確性 (語法,類型,符號引用,等等)。因此,如果條件不滿足,代碼塊內的引用符號就
+不存在時,你還是必須去用 #ifdef。
+
+在任何有意義的 #if 或 #ifdef 塊的末尾 (超過幾行的),在 #endif 同一行的後面寫下
+註解,注釋這個條件表達式。例如:
+
+.. code-block:: c
+
+	#ifdef CONFIG_SOMETHING
+	...
+	#endif /* CONFIG_SOMETHING */
+
+
+附錄 I) 參考
+-------------------
+
+The C Programming Language, 第二版
+作者:Brian W. Kernighan 和 Denni M. Ritchie.
+Prentice Hall, Inc., 1988.
+ISBN 0-13-110362-8 (軟皮), 0-13-110370-9 (硬皮).
+
+The Practice of Programming
+作者:Brian W. Kernighan 和 Rob Pike.
+Addison-Wesley, Inc., 1999.
+ISBN 0-201-61586-X.
+
+GNU 手冊 - 遵循 K&R 標準和此文本 - cpp, gcc, gcc internals and indent,
+都可以從 https://www.gnu.org/manual/ 找到
+
+WG14 是 C 語言的國際標準化工作組,URL: http://www.open-std.org/JTC1/SC22/WG14/
+
+Kernel process/coding-style.rst,作者 greg@kroah.com 發表於 OLS 2002:
+http://www.kroah.com/linux/talks/ols_2002_kernel_codingstyle_talk/html/
+
diff --git a/Documentation/translations/zh_TW/process/development-process.rst b/Documentation/translations/zh_TW/process/development-process.rst
new file mode 100644
index 000000000000..cc25c554854e
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/development-process.rst
@@ -0,0 +1,28 @@
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/development-process.rst <development_process_main>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+.. _tw_development_process_main:
+
+內核開發過程指南
+================
+
+內容:
+
+.. toctree::
+   :numbered:
+   :maxdepth: 2
+
+   1.Intro
+   2.Process
+   3.Early-stage
+   4.Coding
+   5.Posting
+   6.Followthrough
+   7.AdvancedTopics
+   8.Conclusion
+
+本文檔的目的是幫助開發人員(及其經理)以最小的挫折感與開發社區合作。它試圖記錄這個社區如何以一種不熟悉Linux內核開發(或者實際上是自由軟體開發)的人可以訪問的方式工作。雖然這裡有一些技術資料,但這是一個面向過程的討論,不需要深入了解內核編程就可以理解。
+
diff --git a/Documentation/translations/zh_TW/process/email-clients.rst b/Documentation/translations/zh_TW/process/email-clients.rst
new file mode 100644
index 000000000000..9b7c1acf0a87
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/email-clients.rst
@@ -0,0 +1,250 @@
+.. _tw_email_clients:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/email-clients.rst <email_clients>`
+
+譯者::
+
+        中文版維護者: 賈威威  Harry Wei <harryxiyou@gmail.com>
+        中文版翻譯者: 賈威威  Harry Wei <harryxiyou@gmail.com>
+                       時奎亮  Alex Shi <alex.shi@linux.alibaba.com>
+        中文版校譯者: Yinglin Luan <synmyth@gmail.com>
+        	       Xiaochen Wang <wangxiaochen0@gmail.com>
+                       yaxinsn <yaxinsn@163.com>
+                      Hu Haowen <src.res@email.cn>
+
+Linux郵件客戶端配置信息
+=======================
+
+Git
+---
+
+現在大多數開發人員使用 ``git send-email`` 而不是常規的電子郵件客戶端。這方面
+的手冊非常好。在接收端,維護人員使用 ``git am`` 加載補丁。
+
+如果你是 ``git`` 新手,那麼把你的第一個補丁發送給你自己。將其保存爲包含所有
+標題的原始文本。運行 ``git am raw_email.txt`` ,然後使用 ``git log`` 查看更
+改日誌。如果工作正常,再將補丁發送到相應的郵件列表。
+
+
+普通配置
+--------
+Linux內核補丁是通過郵件被提交的,最好把補丁作爲郵件體的內嵌文本。有些維護者
+接收附件,但是附件的內容格式應該是"text/plain"。然而,附件一般是不贊成的,
+因爲這會使補丁的引用部分在評論過程中變的很困難。
+
+用來發送Linux內核補丁的郵件客戶端在發送補丁時應該處於文本的原始狀態。例如,
+他們不能改變或者刪除制表符或者空格,甚至是在每一行的開頭或者結尾。
+
+不要通過"format=flowed"模式發送補丁。這樣會引起不可預期以及有害的斷行。
+
+不要讓你的郵件客戶端進行自動換行。這樣也會破壞你的補丁。
+
+郵件客戶端不能改變文本的字符集編碼方式。要發送的補丁只能是ASCII或者UTF-8編碼方式,
+如果你使用UTF-8編碼方式發送郵件,那麼你將會避免一些可能發生的字符集問題。
+
+郵件客戶端應該形成並且保持 References: 或者 In-Reply-To: 標題,那麼
+郵件話題就不會中斷。
+
+複製粘帖(或者剪貼粘帖)通常不能用於補丁,因爲制表符會轉換爲空格。使用xclipboard, xclip
+或者xcutsel也許可以,但是最好測試一下或者避免使用複製粘帖。
+
+不要在使用PGP/GPG署名的郵件中包含補丁。這樣會使得很多腳本不能讀取和適用於你的補丁。
+(這個問題應該是可以修復的)
+
+在給內核郵件列表發送補丁之前,給自己發送一個補丁是個不錯的主意,保存接收到的
+郵件,將補丁用'patch'命令打上,如果成功了,再給內核郵件列表發送。
+
+
+一些郵件客戶端提示
+------------------
+這裡給出一些詳細的MUA配置提示,可以用於給Linux內核發送補丁。這些並不意味是
+所有的軟體包配置總結。
+
+說明:
+TUI = 以文本爲基礎的用戶接口
+GUI = 圖形界面用戶接口
+
+Alpine (TUI)
+~~~~~~~~~~~~
+
+配置選項:
+在"Sending Preferences"部分:
+
+- "Do Not Send Flowed Text"必須開啓
+- "Strip Whitespace Before Sending"必須關閉
+
+當寫郵件時,光標應該放在補丁會出現的地方,然後按下CTRL-R組合鍵,使指定的
+補丁文件嵌入到郵件中。
+
+Evolution (GUI)
+~~~~~~~~~~~~~~~
+
+一些開發者成功的使用它發送補丁
+
+當選擇郵件選項:Preformat
+  從Format->Heading->Preformatted (Ctrl-7)或者工具欄
+
+然後使用:
+  Insert->Text File... (Alt-n x)插入補丁文件。
+
+你還可以"diff -Nru old.c new.c | xclip",選擇Preformat,然後使用中間鍵進行粘帖。
+
+Kmail (GUI)
+~~~~~~~~~~~
+
+一些開發者成功的使用它發送補丁。
+
+默認設置不爲HTML格式是合適的;不要啓用它。
+
+當書寫一封郵件的時候,在選項下面不要選擇自動換行。唯一的缺點就是你在郵件中輸入的任何文本
+都不會被自動換行,因此你必須在發送補丁之前手動換行。最簡單的方法就是啓用自動換行來書寫郵件,
+然後把它保存爲草稿。一旦你在草稿中再次打開它,它已經全部自動換行了,那麼你的郵件雖然沒有
+選擇自動換行,但是還不會失去已有的自動換行。
+
+在郵件的底部,插入補丁之前,放上常用的補丁定界符:三個連字號(---)。
+
+然後在"Message"菜單條目,選擇插入文件,接著選取你的補丁文件。還有一個額外的選項,你可以
+通過它配置你的郵件建立工具欄菜單,還可以帶上"insert file"圖標。
+
+你可以安全地通過GPG標記附件,但是內嵌補丁最好不要使用GPG標記它們。作爲內嵌文本的簽發補丁,
+當從GPG中提取7位編碼時會使他們變的更加複雜。
+
+如果你非要以附件的形式發送補丁,那麼就右鍵點擊附件,然後選中屬性,突出"Suggest automatic
+display",這樣內嵌附件更容易讓讀者看到。
+
+當你要保存將要發送的內嵌文本補丁,你可以從消息列表窗格選擇包含補丁的郵件,然後右擊選擇
+"save as"。你可以使用一個沒有更改的包含補丁的郵件,如果它是以正確的形式組成。當你正真在它
+自己的窗口之下察看,那時沒有選項可以保存郵件--已經有一個這樣的bug被匯報到了kmail的bugzilla
+並且希望這將會被處理。郵件是以只針對某個用戶可讀寫的權限被保存的,所以如果你想把郵件複製到其他地方,
+你不得不把他們的權限改爲組或者整體可讀。
+
+Lotus Notes (GUI)
+~~~~~~~~~~~~~~~~~
+
+不要使用它。
+
+Mutt (TUI)
+~~~~~~~~~~
+
+很多Linux開發人員使用mutt客戶端,所以證明它肯定工作的非常漂亮。
+
+Mutt不自帶編輯器,所以不管你使用什麼編輯器都不應該帶有自動斷行。大多數編輯器都帶有
+一個"insert file"選項,它可以通過不改變文件內容的方式插入文件。
+
+'vim'作爲mutt的編輯器:
+  set editor="vi"
+
+  如果使用xclip,敲入以下命令
+  :set paste
+  按中鍵之前或者shift-insert或者使用
+  :r filename
+
+如果想要把補丁作爲內嵌文本。
+(a)ttach工作的很好,不帶有"set paste"。
+
+你可以通過 ``git format-patch`` 生成補丁,然後用 Mutt發送它們::
+
+        $ mutt -H 0001-some-bug-fix.patch
+
+配置選項:
+它應該以默認設置的形式工作。
+然而,把"send_charset"設置爲"us-ascii::utf-8"也是一個不錯的主意。
+
+Mutt 是高度可配置的。 這裡是個使用mutt通過 Gmail 發送的補丁的最小配置::
+
+  # .muttrc
+  # ================  IMAP ====================
+  set imap_user = 'yourusername@gmail.com'
+  set imap_pass = 'yourpassword'
+  set spoolfile = imaps://imap.gmail.com/INBOX
+  set folder = imaps://imap.gmail.com/
+  set record="imaps://imap.gmail.com/[Gmail]/Sent Mail"
+  set postponed="imaps://imap.gmail.com/[Gmail]/Drafts"
+  set mbox="imaps://imap.gmail.com/[Gmail]/All Mail"
+
+  # ================  SMTP  ====================
+  set smtp_url = "smtp://username@smtp.gmail.com:587/"
+  set smtp_pass = $imap_pass
+  set ssl_force_tls = yes # Require encrypted connection
+
+  # ================  Composition  ====================
+  set editor = `echo \$EDITOR`
+  set edit_headers = yes  # See the headers when editing
+  set charset = UTF-8     # value of $LANG; also fallback for send_charset
+  # Sender, email address, and sign-off line must match
+  unset use_domain        # because joe@localhost is just embarrassing
+  set realname = "YOUR NAME"
+  set from = "username@gmail.com"
+  set use_from = yes
+
+Mutt文檔含有更多信息:
+
+    http://dev.mutt.org/trac/wiki/UseCases/Gmail
+
+    http://dev.mutt.org/doc/manual.html
+
+Pine (TUI)
+~~~~~~~~~~
+
+Pine過去有一些空格刪減問題,但是這些現在應該都被修復了。
+
+如果可以,請使用alpine(pine的繼承者)
+
+配置選項:
+- 最近的版本需要消除流程文本
+- "no-strip-whitespace-before-send"選項也是需要的。
+
+
+Sylpheed (GUI)
+~~~~~~~~~~~~~~
+
+- 內嵌文本可以很好的工作(或者使用附件)。
+- 允許使用外部的編輯器。
+- 對於目錄較多時非常慢。
+- 如果通過non-SSL連接,無法使用TLS SMTP授權。
+- 在組成窗口中有一個很有用的ruler bar。
+- 給地址本中添加地址就不會正確的了解顯示名。
+
+Thunderbird (GUI)
+~~~~~~~~~~~~~~~~~
+
+默認情況下,thunderbird很容易損壞文本,但是還有一些方法可以強制它變得更好。
+
+- 在用戶帳號設置里,組成和尋址,不要選擇"Compose messages in HTML format"。
+
+- 編輯你的Thunderbird配置設置來使它不要拆行使用:user_pref("mailnews.wraplength", 0);
+
+- 編輯你的Thunderbird配置設置,使它不要使用"format=flowed"格式:user_pref("mailnews.
+  send_plaintext_flowed", false);
+
+- 你需要使Thunderbird變爲預先格式方式:
+  如果默認情況下你書寫的是HTML格式,那不是很難。僅僅從標題欄的下拉框中選擇"Preformat"格式。
+  如果默認情況下你書寫的是文本格式,你不得把它改爲HTML格式(僅僅作爲一次性的)來書寫新的消息,
+  然後強制使它回到文本格式,否則它就會拆行。要實現它,在寫信的圖標上使用shift鍵來使它變爲HTML
+  格式,然後標題欄的下拉框中選擇"Preformat"格式。
+
+- 允許使用外部的編輯器:
+  針對Thunderbird打補丁最簡單的方法就是使用一個"external editor"擴展,然後使用你最喜歡的
+  $EDITOR來讀取或者合併補丁到文本中。要實現它,可以下載並且安裝這個擴展,然後添加一個使用它的
+  按鍵View->Toolbars->Customize...最後當你書寫信息的時候僅僅點擊它就可以了。
+
+TkRat (GUI)
+~~~~~~~~~~~
+
+可以使用它。使用"Insert file..."或者外部的編輯器。
+
+Gmail (Web GUI)
+~~~~~~~~~~~~~~~
+
+不要使用它發送補丁。
+
+Gmail網頁客戶端自動地把制表符轉換爲空格。
+
+雖然制表符轉換爲空格問題可以被外部編輯器解決,同時它還會使用回車換行把每行拆分爲78個字符。
+
+另一個問題是Gmail還會把任何不是ASCII的字符的信息改爲base64編碼。它把東西變的像歐洲人的名字。
+
+                                ###
+
diff --git a/Documentation/translations/zh_TW/process/embargoed-hardware-issues.rst b/Documentation/translations/zh_TW/process/embargoed-hardware-issues.rst
new file mode 100644
index 000000000000..2cd100412655
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/embargoed-hardware-issues.rst
@@ -0,0 +1,230 @@
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/embargoed-hardware-issues.rst <embargoed_hardware_issues>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+被限制的硬體問題
+================
+
+範圍
+----
+
+導致安全問題的硬體問題與只影響Linux內核的純軟體錯誤是不同的安全錯誤類別。
+
+必須區別對待諸如熔毀(Meltdown)、Spectre、L1TF等硬體問題,因爲它們通常會影響
+所有作業系統(「OS」),因此需要在不同的OS供應商、發行版、硬體供應商和其他各方
+之間進行協調。對於某些問題,軟體緩解可能依賴於微碼或固件更新,這需要進一步的
+協調。
+
+.. _zh_Contact:
+
+接觸
+----
+
+Linux內核硬體安全小組獨立於普通的Linux內核安全小組。
+
+該小組只負責協調被限制的硬體安全問題。Linux內核中純軟體安全漏洞的報告不由該
+小組處理,報告者將被引導至常規Linux內核安全小組(:ref:`Documentation/admin-guide/
+<securitybugs>`)聯繫。
+
+可以通過電子郵件 <hardware-security@kernel.org> 與小組聯繫。這是一份私密的安全
+官名單,他們將幫助您根據我們的文檔化流程協調問題。
+
+郵件列表是加密的,發送到列表的電子郵件可以通過PGP或S/MIME加密,並且必須使用報告
+者的PGP密鑰或S/MIME證書籤名。該列表的PGP密鑰和S/MIME證書可從
+https://www.kernel.org/.... 獲得。
+
+雖然硬體安全問題通常由受影響的硬體供應商處理,但我們歡迎發現潛在硬體缺陷的研究
+人員或個人與我們聯繫。
+
+硬體安全官
+^^^^^^^^^^
+
+目前的硬體安全官小組:
+
+  - Linus Torvalds(Linux基金會院士)
+  - Greg Kroah Hartman(Linux基金會院士)
+  - Thomas Gleixner(Linux基金會院士)
+
+郵件列表的操作
+^^^^^^^^^^^^^^
+
+處理流程中使用的加密郵件列表託管在Linux Foundation的IT基礎設施上。通過提供這項
+服務,Linux基金會的IT基礎設施安全總監在技術上有能力訪問被限制的信息,但根據他
+的僱傭合同,他必須保密。Linux基金會的IT基礎設施安全總監還負責 kernel.org 基礎
+設施。
+
+Linux基金會目前的IT基礎設施安全總監是 Konstantin Ryabitsev。
+
+保密協議
+--------
+
+Linux內核硬體安全小組不是正式的機構,因此無法簽訂任何保密協議。核心社區意識到
+這些問題的敏感性,並提供了一份諒解備忘錄。
+
+諒解備忘錄
+----------
+
+Linux內核社區深刻理解在不同作業系統供應商、發行商、硬體供應商和其他各方之間
+進行協調時,保持硬體安全問題處於限制狀態的要求。
+
+Linux內核社區在過去已經成功地處理了硬體安全問題,並且有必要的機制允許在限制
+限制下進行符合社區的開發。
+
+Linux內核社區有一個專門的硬體安全小組負責初始聯繫,並監督在限制規則下處理
+此類問題的過程。
+
+硬體安全小組確定開發人員(領域專家),他們將組成特定問題的初始響應小組。最初
+的響應小組可以引入更多的開發人員(領域專家)以最佳的技術方式解決這個問題。
+
+所有相關開發商承諾遵守限制規定,並對收到的信息保密。違反承諾將導致立即從當前
+問題中排除,並從所有相關郵件列表中刪除。此外,硬體安全小組還將把違反者排除在
+未來的問題之外。這一後果的影響在我們社區是一種非常有效的威懾。如果發生違規
+情況,硬體安全小組將立即通知相關方。如果您或任何人發現潛在的違規行爲,請立即
+向硬體安全人員報告。
+
+流程
+^^^^
+
+由於Linux內核開發的全球分布式特性,面對面的會議幾乎不可能解決硬體安全問題。
+由於時區和其他因素,電話會議很難協調,只能在絕對必要時使用。加密電子郵件已被
+證明是解決此類問題的最有效和最安全的通信方法。
+
+開始披露
+""""""""
+
+披露內容首先通過電子郵件聯繫Linux內核硬體安全小組。此初始聯繫人應包含問題的
+描述和任何已知受影響硬體的列表。如果您的組織製造或分發受影響的硬體,我們建議
+您也考慮哪些其他硬體可能會受到影響。
+
+硬體安全小組將提供一個特定於事件的加密郵件列表,用於與報告者進行初步討論、
+進一步披露和協調。
+
+硬體安全小組將向披露方提供一份開發人員(領域專家)名單,在與開發人員確認他們
+將遵守本諒解備忘錄和文件化流程後,應首先告知開發人員有關該問題的信息。這些開發
+人員組成初始響應小組,並在初始接觸後負責處理問題。硬體安全小組支持響應小組,
+但不一定參與緩解開發過程。
+
+雖然個別開發人員可能通過其僱主受到保密協議的保護,但他們不能以Linux內核開發
+人員的身份簽訂個別保密協議。但是,他們將同意遵守這一書面程序和諒解備忘錄。
+
+披露方應提供已經或應該被告知該問題的所有其他實體的聯繫人名單。這有幾個目的:
+
+  - 披露的實體列表允許跨行業通信,例如其他作業系統供應商、硬體供應商等。
+
+  - 可聯繫已披露的實體,指定應參與緩解措施開發的專家。
+
+  - 如果需要處理某一問題的專家受僱於某一上市實體或某一上市實體的成員,則響應
+    小組可要求該實體披露該專家。這確保專家也是實體反應小組的一部分。
+
+披露
+""""
+
+披露方通過特定的加密郵件列表向初始響應小組提供詳細信息。
+
+根據我們的經驗,這些問題的技術文檔通常是一個足夠的起點,最好通過電子郵件進行
+進一步的技術澄清。
+
+緩解開發
+""""""""
+
+初始響應小組設置加密郵件列表,或在適當的情況下重新修改現有郵件列表。
+
+使用郵件列表接近於正常的Linux開發過程,並且在過去已經成功地用於爲各種硬體安全
+問題開發緩解措施。
+
+郵件列表的操作方式與正常的Linux開發相同。發布、討論和審查修補程序,如果同意,
+則應用於非公共git存儲庫,參與開發人員只能通過安全連接訪問該存儲庫。存儲庫包含
+針對主線內核的主開發分支,並根據需要爲穩定的內核版本提供向後移植分支。
+
+最初的響應小組將根據需要從Linux內核開發人員社區中確定更多的專家。引進專家可以
+在開發過程中的任何時候發生,需要及時處理。
+
+如果專家受僱於披露方提供的披露清單上的實體或其成員,則相關實體將要求其參與。
+
+否則,披露方將被告知專家參與的情況。諒解備忘錄涵蓋了專家,要求披露方確認參與。
+如果披露方有令人信服的理由提出異議,則必須在五個工作日內提出異議,並立即與事件
+小組解決。如果披露方在五個工作日內未作出回應,則視爲默許。
+
+在確認或解決異議後,專家由事件小組披露,並進入開發過程。
+
+協調發布
+""""""""
+
+有關各方將協商限制結束的日期和時間。此時,準備好的緩解措施集成到相關的內核樹中
+並發布。
+
+雖然我們理解硬體安全問題需要協調限制時間,但限制時間應限制在所有有關各方制定、
+測試和準備緩解措施所需的最短時間內。人爲地延長限制時間以滿足會議討論日期或其他
+非技術原因,會給相關的開發人員和響應小組帶來了更多的工作和負擔,因爲補丁需要
+保持最新,以便跟蹤正在進行的上游內核開發,這可能會造成衝突的更改。
+
+CVE分配
+"""""""
+
+硬體安全小組和初始響應小組都不分配CVE,開發過程也不需要CVE。如果CVE是由披露方
+提供的,則可用於文檔中。
+
+流程專使
+--------
+
+爲了協助這一進程,我們在各組織設立了專使,他們可以回答有關報告流程和進一步處理
+的問題或提供指導。專使不參與特定問題的披露,除非響應小組或相關披露方提出要求。
+現任專使名單:
+
+  ============= ========================================================
+  ARM
+  AMD		Tom Lendacky <tom.lendacky@amd.com>
+  IBM
+  Intel		Tony Luck <tony.luck@intel.com>
+  Qualcomm	Trilok Soni <tsoni@codeaurora.org>
+
+  Microsoft	Sasha Levin <sashal@kernel.org>
+  VMware
+  Xen		Andrew Cooper <andrew.cooper3@citrix.com>
+
+  Canonical	John Johansen <john.johansen@canonical.com>
+  Debian	Ben Hutchings <ben@decadent.org.uk>
+  Oracle	Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
+  Red Hat	Josh Poimboeuf <jpoimboe@redhat.com>
+  SUSE		Jiri Kosina <jkosina@suse.cz>
+
+  Amazon
+  Google	Kees Cook <keescook@chromium.org>
+  ============= ========================================================
+
+如果要將您的組織添加到專使名單中,請與硬體安全小組聯繫。被提名的專使必須完全
+理解和支持我們的過程,並且在Linux內核社區中很容易聯繫。
+
+加密郵件列表
+------------
+
+我們使用加密郵件列表進行通信。這些列表的工作原理是,發送到列表的電子郵件使用
+列表的PGP密鑰或列表的/MIME證書進行加密。郵件列表軟體對電子郵件進行解密,並
+使用訂閱者的PGP密鑰或S/MIME證書爲每個訂閱者分別對其進行重新加密。有關郵件列表
+軟體和用於確保列表安全和數據保護的設置的詳細信息,請訪問:
+https://www.kernel.org/....
+
+關鍵點
+^^^^^^
+
+初次接觸見 :ref:`zh_Contact`. 對於特定於事件的郵件列表,密鑰和S/MIME證書通過
+特定列表發送的電子郵件傳遞給訂閱者。
+
+訂閱事件特定列表
+^^^^^^^^^^^^^^^^
+
+訂閱由響應小組處理。希望參與通信的披露方將潛在訂戶的列表發送給響應組,以便
+響應組可以驗證訂閱請求。
+
+每個訂戶都需要通過電子郵件向響應小組發送訂閱請求。電子郵件必須使用訂閱伺服器
+的PGP密鑰或S/MIME證書籤名。如果使用PGP密鑰,則必須從公鑰伺服器獲得該密鑰,
+並且理想情況下該密鑰連接到Linux內核的PGP信任網。另請參見:
+https://www.kernel.org/signature.html.
+
+響應小組驗證訂閱者,並將訂閱者添加到列表中。訂閱後,訂閱者將收到來自郵件列表
+的電子郵件,該郵件列表使用列表的PGP密鑰或列表的/MIME證書籤名。訂閱者的電子郵件
+客戶端可以從簽名中提取PGP密鑰或S/MIME證書,以便訂閱者可以向列表發送加密電子
+郵件。
+
diff --git a/Documentation/translations/zh_TW/process/howto.rst b/Documentation/translations/zh_TW/process/howto.rst
new file mode 100644
index 000000000000..d1e3df96450a
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/howto.rst
@@ -0,0 +1,498 @@
+.. _tw_process_howto:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/howto.rst <process_howto>`
+
+譯者::
+
+    英文版維護者: Greg Kroah-Hartman <greg@kroah.com>
+    中文版維護者: 李陽  Li Yang <leoyang.li@nxp.com>
+    中文版翻譯者: 李陽  Li Yang <leoyang.li@nxp.com>
+                   時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+    中文版校譯者:
+                   鍾宇  TripleX Chung <xxx.phy@gmail.com>
+                   陳琦  Maggie Chen <chenqi@beyondsoft.com>
+                   王聰  Wang Cong <xiyou.wangcong@gmail.com>
+                   胡皓文 Hu Haowen <src.res@email.cn>
+
+如何參與Linux內核開發
+=====================
+
+這是一篇將如何參與Linux內核開發的相關問題一網打盡的終極祕笈。它將指導你
+成爲一名Linux內核開發者,並且學會如何同Linux內核開發社區合作。它儘可能不
+包括任何關於內核編程的技術細節,但會給你指引一條獲得這些知識的正確途徑。
+
+如果這篇文章中的任何內容不再適用,請給文末列出的文件維護者發送補丁。
+
+
+入門
+----
+
+你想了解如何成爲一名Linux內核開發者?或者老闆吩咐你「給這個設備寫個Linux
+驅動程序」?這篇文章的目的就是教會你達成這些目標的全部訣竅,它將描述你需
+要經過的流程以及給出如何同內核社區合作的一些提示。它還將試圖解釋內核社區
+爲何這樣運作。
+
+Linux內核大部分是由C語言寫成的,一些體系結構相關的代碼用到了彙編語言。要
+參與內核開發,你必須精通C語言。除非你想爲某個架構開發底層代碼,否則你並
+不需要了解(任何體系結構的)彙編語言。下面列舉的書籍雖然不能替代紮實的C
+語言教育和多年的開發經驗,但如果需要的話,做爲參考還是不錯的:
+
+ - "The C Programming Language" by Kernighan and Ritchie [Prentice Hall]
+   《C程序設計語言(第2版·新版)》(徐寶文 李志 譯)[機械工業出版社]
+ - "Practical C Programming" by Steve Oualline [O'Reilly]
+   《實用C語言編程(第三版)》(郭大海 譯)[中國電力出版社]
+ - "C:  A Reference Manual" by Harbison and Steele [Prentice Hall]
+   《C語言參考手冊(原書第5版)》(邱仲潘 等譯)[機械工業出版社]
+
+Linux內核使用GNU C和GNU工具鏈開發。雖然它遵循ISO C89標準,但也用到了一些
+標準中沒有定義的擴展。內核是自給自足的C環境,不依賴於標準C庫的支持,所以
+並不支持C標準中的部分定義。比如long long類型的大數除法和浮點運算就不允許
+使用。有時候確實很難弄清楚內核對工具鏈的要求和它所使用的擴展,不幸的是目
+前還沒有明確的參考資料可以解釋它們。請查閱gcc信息頁(使用「info gcc」命令
+顯示)獲得一些這方面信息。
+
+請記住你是在學習怎麼和已經存在的開發社區打交道。它由一羣形形色色的人組成,
+他們對代碼、風格和過程有著很高的標準。這些標準是在長期實踐中總結出來的,
+適應於地理上分散的大型開發團隊。它們已經被很好得整理成檔,建議你在開發
+之前儘可能多的學習這些標準,而不要期望別人來適應你或者你公司的行爲方式。
+
+
+法律問題
+--------
+
+Linux內核原始碼都是在GPL(通用公共許可證)的保護下發布的。要了解這種許可
+的細節請查看原始碼主目錄下的COPYING文件。Linux內核許可準則和如何使用
+`SPDX <https://spdx.org/>` 標誌符說明在這個文件中
+:ref:`Documentation/translations/zh_TW/process/license-rules.rst <tw_kernel_licensing>`
+如果你對它還有更深入問題請聯繫律師,而不要在Linux內核郵件組上提問。因爲
+郵件組裡的人並不是律師,不要期望他們的話有法律效力。
+
+對於GPL的常見問題和解答,請訪問以下連結:
+	https://www.gnu.org/licenses/gpl-faq.html
+
+
+文檔
+----
+
+Linux內核代碼中包含有大量的文檔。這些文檔對於學習如何與內核社區互動有著
+不可估量的價值。當一個新的功能被加入內核,最好把解釋如何使用這個功能的文
+檔也放進內核。當內核的改動導致面向用戶空間的接口發生變化時,最好將相關信
+息或手冊頁(manpages)的補丁發到mtk.manpages@gmail.com,以向手冊頁(manpages)
+的維護者解釋這些變化。
+
+以下是內核代碼中需要閱讀的文檔:
+  :ref:`Documentation/admin-guide/README.rst <readme>`
+    文件簡要介紹了Linux內核的背景,並且描述了如何配置和編譯內核。內核的
+    新用戶應該從這裡開始。
+
+
+  :ref:`Documentation/process/changes.rst <changes>`
+    文件給出了用來編譯和使用內核所需要的最小軟體包列表。
+
+  :ref:`Documentation/translations/zh_TW/process/coding-style.rst <tw_codingstyle>`
+    描述Linux內核的代碼風格和理由。所有新代碼需要遵守這篇文檔中定義的規
+    范。大多數維護者只會接收符合規定的補丁,很多人也只會幫忙檢查符合風格
+    的代碼。
+
+  :ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+  :ref:`Documentation/process/submitting-drivers.rst <submittingdrivers>`
+
+    這兩份文檔明確描述如何創建和發送補丁,其中包括(但不僅限於):
+       - 郵件內容
+       - 郵件格式
+       - 選擇收件人
+
+    遵守這些規定並不能保證提交成功(因爲所有補丁需要通過嚴格的內容和風格
+    審查),但是忽視他們幾乎就意味著失敗。
+
+    其他關於如何正確地生成補丁的優秀文檔包括:
+    "The Perfect Patch"
+
+        https://www.ozlabs.org/~akpm/stuff/tpp.txt
+
+    "Linux kernel patch submission format"
+
+        https://web.archive.org/web/20180829112450/http://linux.yyz.us/patch-format.html
+
+  :ref:`Documentation/translations/zh_TW/process/stable-api-nonsense.rst <tw_stable_api_nonsense>`
+    論證內核爲什麼特意不包括穩定的內核內部API,也就是說不包括像這樣的特
+    性:
+
+       - 子系統中間層(爲了兼容性?)
+       - 在不同作業系統間易於移植的驅動程序
+       - 減緩(甚至阻止)內核代碼的快速變化
+
+    這篇文檔對於理解Linux的開發哲學至關重要。對於將開發平台從其他操作系
+    統轉移到Linux的人來說也很重要。
+
+  :ref:`Documentation/admin-guide/security-bugs.rst <securitybugs>`
+    如果你認爲自己發現了Linux內核的安全性問題,請根據這篇文檔中的步驟來
+    提醒其他內核開發者並幫助解決這個問題。
+
+  :ref:`Documentation/translations/zh_TW/process/management-style.rst <tw_managementstyle>`
+
+    描述內核維護者的工作方法及其共有特點。這對於剛剛接觸內核開發(或者對
+    它感到好奇)的人來說很重要,因爲它解釋了很多對於內核維護者獨特行爲的
+    普遍誤解與迷惑。
+
+  :ref:`Documentation/process/stable-kernel-rules.rst <stable_kernel_rules>`
+    解釋了穩定版內核發布的規則,以及如何將改動放入這些版本的步驟。
+
+  :ref:`Documentation/process/kernel-docs.rst <kernel_docs>`
+    有助於內核開發的外部文檔列表。如果你在內核自帶的文檔中沒有找到你想找
+    的內容,可以查看這些文檔。
+
+  :ref:`Documentation/process/applying-patches.rst <applying_patches>`
+    關於補丁是什麼以及如何將它打在不同內核開發分支上的好介紹
+
+內核還擁有大量從代碼自動生成或者從 ReStructuredText(ReST) 標記生成的文檔,
+比如這個文檔,它包含內核內部API的全面介紹以及如何妥善處理加鎖的規則。所有
+這些文檔都可以通過運行以下命令從內核代碼中生成爲PDF或HTML文檔::
+
+    make pdfdocs
+    make htmldocs
+
+ReST格式的文檔會生成在 Documentation/output. 目錄中。
+它們也可以用下列命令生成 LaTeX 和 ePub 格式文檔::
+
+    make latexdocs
+    make epubdocs
+
+如何成爲內核開發者
+------------------
+如果你對Linux內核開發一無所知,你應該訪問「Linux內核新手」計劃:
+
+	https://kernelnewbies.org
+
+它擁有一個可以問各種最基本的內核開發問題的郵件列表(在提問之前一定要記得
+查找已往的郵件,確認是否有人已經回答過相同的問題)。它還擁有一個可以獲得
+實時反饋的IRC聊天頻道,以及大量對於學習Linux內核開發相當有幫助的文檔。
+
+網站簡要介紹了原始碼組織結構、子系統劃分以及目前正在進行的項目(包括內核
+中的和單獨維護的)。它還提供了一些基本的幫助信息,比如如何編譯內核和打補
+丁。
+
+如果你想加入內核開發社區並協助完成一些任務,卻找不到從哪裡開始,可以訪問
+「Linux內核房管員」計劃:
+
+	https://kernelnewbies.org/KernelJanitors
+
+這是極佳的起點。它提供一個相對簡單的任務列表,列出內核代碼中需要被重新
+整理或者改正的地方。通過和負責這個計劃的開發者們一同工作,你會學到將補丁
+集成進內核的基本原理。如果還沒有決定下一步要做什麼的話,你還可能會得到方
+向性的指點。
+
+在真正動手修改內核代碼之前,理解要修改的代碼如何運作是必需的。要達到這個
+目的,沒什麼辦法比直接讀代碼更有效了(大多數花招都會有相應的注釋),而且
+一些特製的工具還可以提供幫助。例如,「Linux代碼交叉引用」項目就是一個值得
+特別推薦的幫助工具,它將原始碼顯示在有編目和索引的網頁上。其中一個更新及
+時的內核源碼庫,可以通過以下地址訪問:
+
+        https://elixir.bootlin.com/
+
+
+開發流程
+--------
+
+目前Linux內核開發流程包括幾個「主內核分支」和很多子系統相關的內核分支。這
+些分支包括:
+
+  - Linus 的內核源碼樹
+  - 多個主要版本的穩定版內核樹
+  - 子系統相關的內核樹
+  - linux-next 集成測試樹
+
+
+主線樹
+------
+主線樹是由Linus Torvalds 維護的。你可以在https://kernel.org 網站或者代碼
+庫中下找到它。它的開發遵循以下步驟:
+
+  - 每當一個新版本的內核被發布,爲期兩周的集成窗口將被打開。在這段時間裡
+    維護者可以向Linus提交大段的修改,通常這些修改已經被放到-mm內核中幾個
+    星期了。提交大量修改的首選方式是使用git工具(內核的代碼版本管理工具
+    ,更多的信息可以在 https://git-scm.com/ 獲取),不過使用普通補丁也是
+    可以的。
+  - 兩個星期以後-rc1版本內核發布。之後只有不包含可能影響整個內核穩定性的
+    新功能的補丁才可能被接受。請注意一個全新的驅動程序(或者文件系統)有
+    可能在-rc1後被接受是因爲這樣的修改完全獨立,不會影響其他的代碼,所以
+    沒有造成內核退步的風險。在-rc1以後也可以用git向Linus提交補丁,不過所
+    有的補丁需要同時被發送到相應的公衆郵件列表以徵詢意見。
+  - 當Linus認爲當前的git源碼樹已經達到一個合理健全的狀態足以發布供人測試
+    時,一個新的-rc版本就會被發布。計劃是每周都發布新的-rc版本。
+  - 這個過程一直持續下去直到內核被認爲達到足夠穩定的狀態,持續時間大概是
+    6個星期。
+
+關於內核發布,值得一提的是Andrew Morton在linux-kernel郵件列表中如是說:
+	「沒有人知道新內核何時會被發布,因爲發布是根據已知bug的情況來決定
+	的,而不是根據一個事先制定好的時間表。」
+
+子系統特定樹
+------------
+
+各種內核子系統的維護者——以及許多內核子系統開發人員——在原始碼庫中公開了他們
+當前的開發狀態。這樣,其他人就可以看到內核的不同區域發生了什麼。在開發速度
+很快的領域,可能會要求開發人員將提交的內容建立在這樣的子系統內核樹上,這樣
+就避免了提交與其他已經進行的工作之間的衝突。
+
+這些存儲庫中的大多數都是Git樹,但是也有其他的scm在使用,或者補丁隊列被發布
+爲Quilt系列。這些子系統存儲庫的地址列在MAINTAINERS文件中。其中許多可以在
+https://git.kernel.org/上瀏覽。
+
+在將一個建議的補丁提交到這樣的子系統樹之前,需要對它進行審查,審查主要發生
+在郵件列表上(請參見下面相應的部分)。對於幾個內核子系統,這個審查過程是通
+過工具補丁跟蹤的。Patchwork提供了一個Web界面,顯示補丁發布、對補丁的任何評
+論或修訂,維護人員可以將補丁標記爲正在審查、接受或拒絕。大多數補丁網站都列
+在 https://patchwork.kernel.org/
+
+Linux-next 集成測試樹
+---------------------
+
+在將子系統樹的更新合併到主線樹之前,需要對它們進行集成測試。爲此,存在一個
+特殊的測試存儲庫,其中幾乎每天都會提取所有子系統樹:
+
+        https://git.kernel.org/?p=linux/kernel/git/next/linux-next.git
+
+通過這種方式,Linux-next 對下一個合併階段將進入主線內核的內容給出了一個概要
+展望。非常歡冒險的測試者運行測試Linux-next。
+
+多個主要版本的穩定版內核樹
+-----------------------------------
+由3個數字組成的內核版本號說明此內核是-stable版本。它們包含內核的相對較小且
+至關重要的修補,這些修補針對安全性問題或者嚴重的內核退步。
+
+這種版本的內核適用於那些期望獲得最新的穩定版內核並且不想參與測試開發版或
+者實驗版的用戶。
+
+穩定版內核樹版本由「穩定版」小組(郵件地址<stable@vger.kernel.org>)維護,一般
+隔周發布新版本。
+
+內核源碼中的 :ref:`Documentation/process/stable-kernel-rules.rst <stable_kernel_rules>`
+文件具體描述了可被穩定版內核接受的修改類型以及發布的流程。
+
+
+報告bug
+-------
+
+bugzilla.kernel.org是Linux內核開發者們用來跟蹤內核Bug的網站。我們鼓勵用
+戶在這個工具中報告找到的所有bug。如何使用內核bugzilla的細節請訪問:
+
+	http://test.kernel.org/bugzilla/faq.html
+
+內核源碼主目錄中的:ref:`admin-guide/reporting-bugs.rst <reportingbugs>`
+文件里有一個很好的模板。它指導用戶如何報告可能的內核bug以及需要提供哪些信息
+來幫助內核開發者們找到問題的根源。
+
+
+利用bug報告
+-----------
+
+練習內核開發技能的最好辦法就是修改其他人報告的bug。你不光可以幫助內核變
+得更加穩定,還可以學會如何解決實際問題從而提高自己的技能,並且讓其他開發
+者感受到你的存在。修改bug是贏得其他開發者讚譽的最好辦法,因爲並不是很多
+人都喜歡浪費時間去修改別人報告的bug。
+
+要嘗試修改已知的bug,請訪問 http://bugzilla.kernel.org 網址。
+
+
+郵件列表
+--------
+
+正如上面的文檔所描述,大多數的骨幹內核開發者都加入了Linux Kernel郵件列
+表。如何訂閱和退訂列表的細節可以在這裡找到:
+
+	http://vger.kernel.org/vger-lists.html#linux-kernel
+
+網上很多地方都有這個郵件列表的存檔(archive)。可以使用搜尋引擎來找到這些
+存檔。比如:
+
+	http://dir.gmane.org/gmane.linux.kernel
+
+在發信之前,我們強烈建議你先在存檔中搜索你想要討論的問題。很多已經被詳細
+討論過的問題只在郵件列表的存檔中可以找到。
+
+大多數內核子系統也有自己獨立的郵件列表來協調各自的開發工作。從
+MAINTAINERS文件中可以找到不同話題對應的郵件列表。
+
+很多郵件列表架設在kernel.org伺服器上。這些列表的信息可以在這裡找到:
+
+	http://vger.kernel.org/vger-lists.html
+
+在使用這些郵件列表時,請記住保持良好的行爲習慣。下面的連結提供了與這些列
+表(或任何其它郵件列表)交流的一些簡單規則,雖然內容有點濫竽充數。
+
+	http://www.albion.com/netiquette/
+
+當有很多人回覆你的郵件時,郵件的抄送列表會變得很長。請不要將任何人從抄送
+列表中刪除,除非你有足夠的理由這麼做。也不要只回復到郵件列表。請習慣於同
+一封郵件接收兩次(一封來自發送者一封來自郵件列表),而不要試圖通過添加一
+些奇特的郵件頭來解決這個問題,人們不會喜歡的。
+
+記住保留你所回復內容的上下文和源頭。在你回覆郵件的頂部保留「某某某說到……」
+這幾行。將你的評論加在被引用的段落之間而不要放在郵件的頂部。
+
+如果你在郵件中附帶補丁,請確認它們是可以直接閱讀的純文本(如
+:ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+文檔中所述)。內核開發者們不希望遇到附件或者被壓縮了的補丁。只有這樣才能
+保證他們可以直接評論你的每行代碼。請確保你使用的郵件發送程序不會修改空格
+和制表符。一個防範性的測試方法是先將郵件發送給自己,然後自己嘗試是否可以
+順利地打上收到的補丁。如果測試不成功,請調整或者更換你的郵件發送程序直到
+它正確工作爲止。
+
+總而言之,請尊重其他的郵件列表訂閱者。
+
+
+同內核社區合作
+----------------
+
+內核社區的目標就是提供盡善盡美的內核。所以當你提交補丁期望被接受進內核的
+時候,它的技術價值以及其他方面都將被評審。那麼你可能會得到什麼呢?
+
+  - 批評
+  - 評論
+  - 要求修改
+  - 要求證明修改的必要性
+  - 沉默
+
+要記住,這些是把補丁放進內核的正常情況。你必須學會聽取對補丁的批評和評論,
+從技術層面評估它們,然後要麼重寫你的補丁要麼簡明扼要地論證修改是不必要
+的。如果你發的郵件沒有得到任何回應,請過幾天後再試一次,因爲有時信件會湮
+沒在茫茫信海中。
+
+你不應該做的事情:
+
+  - 期望自己的補丁不受任何質疑就直接被接受
+  - 翻臉
+  - 忽略別人的評論
+  - 沒有按照別人的要求做任何修改就重新提交
+
+在一個努力追尋最好技術方案的社區里,對於一個補丁有多少好處總會有不同的見
+解。你必須要抱著合作的態度,願意改變自己的觀點來適應內核的風格。或者至少
+願意去證明你的想法是有價值的。記住,犯錯誤是允許的,只要你願意朝著正確的
+方案去努力。
+
+如果你的第一個補丁換來的是一堆修改建議,這是很正常的。這並不代表你的補丁
+不會被接受,也不意味著有人和你作對。你只需要改正所有提出的問題然後重新發
+送你的補丁。
+
+內核社區和公司文化的差異
+------------------------
+
+內核社區的工作模式同大多數傳統公司開發隊伍的工作模式並不相同。下面這些例
+子,可以幫助你避免某些可能發生問題:
+用這些話介紹你的修改提案會有好處:
+
+    - 它同時解決了多個問題
+    - 它刪除了2000行代碼
+    - 這是補丁,它已經解釋了我想要說明的
+    - 我在5種不同的體系結構上測試過它……
+    - 這是一系列小補丁用來……
+    - 這個修改提高了普通機器的性能……
+
+應該避免如下的說法:
+
+    - 我們在AIX/ptx/Solaris就是這麼做的,所以這麼做肯定是好的……
+    - 我做這行已經20年了,所以……
+    - 爲了我們公司賺錢考慮必須這麼做
+    - 這是我們的企業產品線所需要的
+    - 這裡是描述我觀點的1000頁設計文檔
+    - 這是一個5000行的補丁用來……
+    - 我重寫了現在亂七八糟的代碼,這就是……
+    - 我被規定了最後期限,所以這個補丁需要立刻被接受
+
+另外一個內核社區與大部分傳統公司的軟體開發隊伍不同的地方是無法面對面地交
+流。使用電子郵件和IRC聊天工具做爲主要溝通工具的一個好處是性別和種族歧視
+將會更少。Linux內核的工作環境更能接受婦女和少數族羣,因爲每個人在別人眼
+里只是一個郵件地址。國際化也幫助了公平的實現,因爲你無法通過姓名來判斷人
+的性別。男人有可能叫李麗,女人也有可能叫王剛。大多數在Linux內核上工作過
+並表達過看法的女性對在linux上工作的經歷都給出了正面的評價。
+
+對於一些不習慣使用英語的人來說,語言可能是一個引起問題的障礙。在郵件列表
+中要正確地表達想法必需良好地掌握語言,所以建議你在發送郵件之前最好檢查一
+下英文寫得是否正確。
+
+
+拆分修改
+--------
+
+Linux內核社區並不喜歡一下接收大段的代碼。修改需要被恰當地介紹、討論並且
+拆分成獨立的小段。這幾乎完全和公司中的習慣背道而馳。你的想法應該在開發最
+開始的階段就讓大家知道,這樣你就可以及時獲得對你正在進行的開發的反饋。這
+樣也會讓社區覺得你是在和他們協作,而不是僅僅把他們當作傾銷新功能的對象。
+無論如何,你不要一次性地向郵件列表發送50封信,你的補丁序列應該永遠用不到
+這麼多。
+
+將補丁拆開的原因如下:
+
+1) 小的補丁更有可能被接受,因爲它們不需要太多的時間和精力去驗證其正確性。
+   一個5行的補丁,可能在維護者看了一眼以後就會被接受。而500行的補丁則
+   需要數個小時來審查其正確性(所需時間隨補丁大小增加大約呈指數級增長)。
+
+   當出了問題的時候,小的補丁也會讓調試變得非常容易。一個一個補丁地回溯
+   將會比仔細剖析一個被打上的大補丁(這個補丁破壞了其他東西)容易得多。
+
+2)不光發送小的補丁很重要,在提交之前重新編排、化簡(或者僅僅重新排列)
+   補丁也是很重要的。
+
+這裡有內核開發者Al Viro打的一個比方:
+	「想像一個老師正在給學生批改數學作業。老師並不希望看到學生爲了得
+	到正確解法所進行的嘗試和產生的錯誤。他希望看到的是最乾淨最優雅的
+	解答。好學生了解這點,絕不會把最終解決之前的中間方案提交上去。」
+
+	內核開發也是這樣。維護者和評審者不希望看到一個人在解決問題時的思
+	考過程。他們只希望看到簡單和優雅的解決方案。
+
+直接給出一流的解決方案,和社區一起協作討論尚未完成的工作,這兩者之間似乎
+很難找到一個平衡點。所以最好儘早開始收集有利於你進行改進的反饋;同時也要
+保證修改分成很多小塊,這樣在整個項目都準備好被包含進內核之前,其中的一部
+分可能會先被接收。
+
+必須了解這樣做是不可接受的:試圖將未完成的工作提交進內核,然後再找時間修
+復。
+
+
+證明修改的必要性
+----------------
+除了將補丁拆成小塊,很重要的一點是讓Linux社區了解他們爲什麼需要這樣修改。
+你必須證明新功能是有人需要的並且是有用的。
+
+
+記錄修改
+--------
+
+當你發送補丁的時候,需要特別留意郵件正文的內容。因爲這裡的信息將會做爲補
+丁的修改記錄(ChangeLog),會被一直保留以備大家查閱。它需要完全地描述補丁,
+包括:
+
+  - 爲什麼需要這個修改
+  - 補丁的總體設計
+  - 實現細節
+  - 測試結果
+
+想了解它具體應該看起來像什麼,請查閱以下文檔中的「ChangeLog」章節:
+  「The Perfect Patch」
+  	 https://www.ozlabs.org/~akpm/stuff/tpp.txt
+
+
+這些事情有時候做起來很難。要在任何方面都做到完美可能需要好幾年時間。這是
+一個持續提高的過程,它需要大量的耐心和決心。只要不放棄,你一定可以做到。
+很多人已經做到了,而他們都曾經和現在的你站在同樣的起點上。
+
+
+感謝
+----
+感謝Paolo Ciarrocchi允許「開發流程」部分基於他所寫的文章
+(http://www.kerneltravel.net/newbie/2.6-development_process),感謝Randy
+Dunlap和Gerrit Huizenga完善了應該說和不該說的列表。感謝Pat Mochel, Hanna
+Linder, Randy Dunlap, Kay Sievers, Vojtech Pavlik, Jan Kara, Josh Boyer,
+Kees Cook, Andrew Morton, Andi Kleen, Vadim Lobanov, Jesper Juhl, Adrian
+Bunk, Keri Harris, Frans Pop, David A. Wheeler, Junio Hamano, Michael
+Kerrisk和Alex Shepard的評審、建議和貢獻。沒有他們的幫助,這篇文檔是不可
+能完成的。
+
+
+
+英文版維護者: Greg Kroah-Hartman <greg@kroah.com>
+
diff --git a/Documentation/translations/zh_TW/process/index.rst b/Documentation/translations/zh_TW/process/index.rst
new file mode 100644
index 000000000000..2f6ecb6515f6
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/index.rst
@@ -0,0 +1,65 @@
+.. raw:: latex
+
+	\renewcommand\thesection*
+	\renewcommand\thesubsection*
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/index.rst <process_index>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+.. _tw_process_index:
+
+與Linux 內核社區一起工作
+========================
+
+你想成爲Linux內核開發人員嗎?歡迎之至!在學習許多關於內核的技術知識的同時,
+了解我們社區的工作方式也很重要。閱讀這些文檔可以讓您以更輕鬆的、麻煩更少的
+方式將更改合併到內核。
+
+以下是每位開發人員都應閱讀的基本指南:
+
+.. toctree::
+   :maxdepth: 1
+
+   howto
+   code-of-conduct
+   code-of-conduct-interpretation
+   submitting-patches
+   programming-language
+   coding-style
+   development-process
+   email-clients
+   license-rules
+   kernel-enforcement-statement
+   kernel-driver-statement
+
+其它大多數開發人員感興趣的社區指南:
+
+
+.. toctree::
+   :maxdepth: 1
+
+   submitting-drivers
+   submit-checklist
+   stable-api-nonsense
+   stable-kernel-rules
+   management-style
+   embargoed-hardware-issues
+
+這些是一些總體性技術指南,由於不大好分類而放在這裡:
+
+.. toctree::
+   :maxdepth: 1
+
+   magic-number
+   volatile-considered-harmful
+
+.. only::  subproject and html
+
+   目錄
+   ====
+
+   * :ref:`genindex`
+
diff --git a/Documentation/translations/zh_TW/process/kernel-driver-statement.rst b/Documentation/translations/zh_TW/process/kernel-driver-statement.rst
new file mode 100644
index 000000000000..f833c1bf81d2
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/kernel-driver-statement.rst
@@ -0,0 +1,201 @@
+.. _zh_process_statement_driver:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/kernel-driver-statement.rst <process_statement_driver>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+內核驅動聲明
+------------
+
+關於Linux內核模塊的立場聲明
+===========================
+
+我們,以下署名的Linux內核開發人員,認爲任何封閉源Linux內核模塊或驅動程序都是
+有害的和不可取的。我們已經一再發現它們對Linux用戶,企業和更大的Linux生態系統
+有害。這樣的模塊否定了Linux開發模型的開放性,穩定性,靈活性和可維護性,並使
+他們的用戶無法使用Linux社區的專業知識。提供閉源內核模塊的供應商迫使其客戶
+放棄Linux的主要優勢或選擇新的供應商。因此,爲了充分利用開源所提供的成本節省和
+共享支持優勢,我們敦促供應商採取措施,以開源內核代碼在Linux上爲其客戶提供支持。
+
+我們只爲自己說話,而不是我們今天可能會爲之工作,過去或將來會爲之工作的任何公司。
+
+ - Dave Airlie
+ - Nick Andrew
+ - Jens Axboe
+ - Ralf Baechle
+ - Felipe Balbi
+ - Ohad Ben-Cohen
+ - Muli Ben-Yehuda
+ - Jiri Benc
+ - Arnd Bergmann
+ - Thomas Bogendoerfer
+ - Vitaly Bordug
+ - James Bottomley
+ - Josh Boyer
+ - Neil Brown
+ - Mark Brown
+ - David Brownell
+ - Michael Buesch
+ - Franck Bui-Huu
+ - Adrian Bunk
+ - François Cami
+ - Ralph Campbell
+ - Luiz Fernando N. Capitulino
+ - Mauro Carvalho Chehab
+ - Denis Cheng
+ - Jonathan Corbet
+ - Glauber Costa
+ - Alan Cox
+ - Magnus Damm
+ - Ahmed S. Darwish
+ - Robert P. J. Day
+ - Hans de Goede
+ - Arnaldo Carvalho de Melo
+ - Helge Deller
+ - Jean Delvare
+ - Mathieu Desnoyers
+ - Sven-Thorsten Dietrich
+ - Alexey Dobriyan
+ - Daniel Drake
+ - Alex Dubov
+ - Randy Dunlap
+ - Michael Ellerman
+ - Pekka Enberg
+ - Jan Engelhardt
+ - Mark Fasheh
+ - J. Bruce Fields
+ - Larry Finger
+ - Jeremy Fitzhardinge
+ - Mike Frysinger
+ - Kumar Gala
+ - Robin Getz
+ - Liam Girdwood
+ - Jan-Benedict Glaw
+ - Thomas Gleixner
+ - Brice Goglin
+ - Cyrill Gorcunov
+ - Andy Gospodarek
+ - Thomas Graf
+ - Krzysztof Halasa
+ - Harvey Harrison
+ - Stephen Hemminger
+ - Michael Hennerich
+ - Tejun Heo
+ - Benjamin Herrenschmidt
+ - Kristian Høgsberg
+ - Henrique de Moraes Holschuh
+ - Marcel Holtmann
+ - Mike Isely
+ - Takashi Iwai
+ - Olof Johansson
+ - Dave Jones
+ - Jesper Juhl
+ - Matthias Kaehlcke
+ - Kenji Kaneshige
+ - Jan Kara
+ - Jeremy Kerr
+ - Russell King
+ - Olaf Kirch
+ - Roel Kluin
+ - Hans-Jürgen Koch
+ - Auke Kok
+ - Peter Korsgaard
+ - Jiri Kosina
+ - Aaro Koskinen
+ - Mariusz Kozlowski
+ - Greg Kroah-Hartman
+ - Michael Krufky
+ - Aneesh Kumar
+ - Clemens Ladisch
+ - Christoph Lameter
+ - Gunnar Larisch
+ - Anders Larsen
+ - Grant Likely
+ - John W. Linville
+ - Yinghai Lu
+ - Tony Luck
+ - Pavel Machek
+ - Matt Mackall
+ - Paul Mackerras
+ - Roland McGrath
+ - Patrick McHardy
+ - Kyle McMartin
+ - Paul Menage
+ - Thierry Merle
+ - Eric Miao
+ - Akinobu Mita
+ - Ingo Molnar
+ - James Morris
+ - Andrew Morton
+ - Paul Mundt
+ - Oleg Nesterov
+ - Luca Olivetti
+ - S.Çağlar Onur
+ - Pierre Ossman
+ - Keith Owens
+ - Venkatesh Pallipadi
+ - Nick Piggin
+ - Nicolas Pitre
+ - Evgeniy Polyakov
+ - Richard Purdie
+ - Mike Rapoport
+ - Sam Ravnborg
+ - Gerrit Renker
+ - Stefan Richter
+ - David Rientjes
+ - Luis R. Rodriguez
+ - Stefan Roese
+ - Francois Romieu
+ - Rami Rosen
+ - Stephen Rothwell
+ - Maciej W. Rozycki
+ - Mark Salyzyn
+ - Yoshinori Sato
+ - Deepak Saxena
+ - Holger Schurig
+ - Amit Shah
+ - Yoshihiro Shimoda
+ - Sergei Shtylyov
+ - Kay Sievers
+ - Sebastian Siewior
+ - Rik Snel
+ - Jes Sorensen
+ - Alexey Starikovskiy
+ - Alan Stern
+ - Timur Tabi
+ - Hirokazu Takata
+ - Eliezer Tamir
+ - Eugene Teo
+ - Doug Thompson
+ - FUJITA Tomonori
+ - Dmitry Torokhov
+ - Marcelo Tosatti
+ - Steven Toth
+ - Theodore Tso
+ - Matthias Urlichs
+ - Geert Uytterhoeven
+ - Arjan van de Ven
+ - Ivo van Doorn
+ - Rik van Riel
+ - Wim Van Sebroeck
+ - Hans Verkuil
+ - Horst H. von Brand
+ - Dmitri Vorobiev
+ - Anton Vorontsov
+ - Daniel Walker
+ - Johannes Weiner
+ - Harald Welte
+ - Matthew Wilcox
+ - Dan J. Williams
+ - Darrick J. Wong
+ - David Woodhouse
+ - Chris Wright
+ - Bryan Wu
+ - Rafael J. Wysocki
+ - Herbert Xu
+ - Vlad Yasevich
+ - Peter Zijlstra
+ - Bartlomiej Zolnierkiewicz
+
diff --git a/Documentation/translations/zh_TW/process/kernel-enforcement-statement.rst b/Documentation/translations/zh_TW/process/kernel-enforcement-statement.rst
new file mode 100644
index 000000000000..5e792edcd868
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/kernel-enforcement-statement.rst
@@ -0,0 +1,153 @@
+.. _tw_process_statement_kernel:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/kernel-enforcement-statement.rst <process_statement_kernel>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+Linux 內核執行聲明
+------------------
+
+作爲Linux內核的開發人員,我們對如何使用我們的軟體以及如何實施軟體許可證有著
+濃厚的興趣。遵守GPL-2.0的互惠共享義務對我們軟體和社區的長期可持續性至關重要。
+
+雖然有權強制執行對我們社區的貢獻中的單獨版權權益,但我們有共同的利益,即確保
+個人強制執行行動的方式有利於我們的社區,不會對我們軟體生態系統的健康和增長
+產生意外的負面影響。爲了阻止無益的執法行動,我們同意代表我們自己和我們版權
+利益的任何繼承人對Linux內核用戶作出以下符合我們開發社區最大利益的承諾:
+
+    儘管有GPL-2.0的終止條款,我們同意,採用以下GPL-3.0條款作爲我們許可證下的
+    附加許可,作爲任何對許可證下權利的非防禦性主張,這符合我們開發社區的最佳
+    利益。
+
+        但是,如果您停止所有違反本許可證的行爲,則您從特定版權持有人處獲得的
+        許可證將被恢復:(a)暫時恢復,除非版權持有人明確並最終終止您的許可證;
+        以及(b)永久恢復, 如果版權持有人未能在你終止違反後60天內以合理方式
+        通知您違反本許可證的行爲,則永久恢復您的許可證。
+
+        此外,如果版權所有者以某種合理的方式通知您違反了本許可,這是您第一次
+        從該版權所有者處收到違反本許可的通知(對於任何作品),並且您在收到通知
+        後的30天內糾正違規行爲。則您從特定版權所有者處獲得的許可將永久恢復.
+
+我們提供這些保證的目的是鼓勵更多地使用該軟體。我們希望公司和個人使用、修改和
+分發此軟體。我們希望以公開和透明的方式與用戶合作,以消除我們對法規遵從性或強制
+執行的任何不確定性,這些不確定性可能會限制我們軟體的採用。我們將法律行動視爲
+最後手段,只有在其他社區努力未能解決這一問題時才採取行動。
+
+最後,一旦一個不合規問題得到解決,我們希望用戶會感到歡迎,加入我們爲之努力的
+這個項目。共同努力,我們會更強大。
+
+除了下面提到的以外,我們只爲自己說話,而不是爲今天、過去或將來可能爲之工作的
+任何公司說話。
+
+  - Laura Abbott
+  - Bjorn Andersson (Linaro)
+  - Andrea Arcangeli
+  - Neil Armstrong
+  - Jens Axboe
+  - Pablo Neira Ayuso
+  - Khalid Aziz
+  - Ralf Baechle
+  - Felipe Balbi
+  - Arnd Bergmann
+  - Ard Biesheuvel
+  - Tim Bird
+  - Paolo Bonzini
+  - Christian Borntraeger
+  - Mark Brown (Linaro)
+  - Paul Burton
+  - Javier Martinez Canillas
+  - Rob Clark
+  - Kees Cook (Google)
+  - Jonathan Corbet
+  - Dennis Dalessandro
+  - Vivien Didelot (Savoir-faire Linux)
+  - Hans de Goede
+  - Mel Gorman (SUSE)
+  - Sven Eckelmann
+  - Alex Elder (Linaro)
+  - Fabio Estevam
+  - Larry Finger
+  - Bhumika Goyal
+  - Andy Gross
+  - Juergen Gross
+  - Shawn Guo
+  - Ulf Hansson
+  - Stephen Hemminger (Microsoft)
+  - Tejun Heo
+  - Rob Herring
+  - Masami Hiramatsu
+  - Michal Hocko
+  - Simon Horman
+  - Johan Hovold (Hovold Consulting AB)
+  - Christophe JAILLET
+  - Olof Johansson
+  - Lee Jones (Linaro)
+  - Heiner Kallweit
+  - Srinivas Kandagatla
+  - Jan Kara
+  - Shuah Khan (Samsung)
+  - David Kershner
+  - Jaegeuk Kim
+  - Namhyung Kim
+  - Colin Ian King
+  - Jeff Kirsher
+  - Greg Kroah-Hartman (Linux Foundation)
+  - Christian König
+  - Vinod Koul
+  - Krzysztof Kozlowski
+  - Viresh Kumar
+  - Aneesh Kumar K.V
+  - Julia Lawall
+  - Doug Ledford
+  - Chuck Lever (Oracle)
+  - Daniel Lezcano
+  - Shaohua Li
+  - Xin Long
+  - Tony Luck
+  - Catalin Marinas (Arm Ltd)
+  - Mike Marshall
+  - Chris Mason
+  - Paul E. McKenney
+  - Arnaldo Carvalho de Melo
+  - David S. Miller
+  - Ingo Molnar
+  - Kuninori Morimoto
+  - Trond Myklebust
+  - Martin K. Petersen (Oracle)
+  - Borislav Petkov
+  - Jiri Pirko
+  - Josh Poimboeuf
+  - Sebastian Reichel (Collabora)
+  - Guenter Roeck
+  - Joerg Roedel
+  - Leon Romanovsky
+  - Steven Rostedt (VMware)
+  - Frank Rowand
+  - Ivan Safonov
+  - Anna Schumaker
+  - Jes Sorensen
+  - K.Y. Srinivasan
+  - David Sterba (SUSE)
+  - Heiko Stuebner
+  - Jiri Kosina (SUSE)
+  - Willy Tarreau
+  - Dmitry Torokhov
+  - Linus Torvalds
+  - Thierry Reding
+  - Rik van Riel
+  - Luis R. Rodriguez
+  - Geert Uytterhoeven (Glider bvba)
+  - Eduardo Valentin (Amazon.com)
+  - Daniel Vetter
+  - Linus Walleij
+  - Richard Weinberger
+  - Dan Williams
+  - Rafael J. Wysocki
+  - Arvind Yadav
+  - Masahiro Yamada
+  - Wei Yongjun
+  - Lv Zheng
+  - Marc Zyngier (Arm Ltd)
+
diff --git a/Documentation/translations/zh_TW/process/license-rules.rst b/Documentation/translations/zh_TW/process/license-rules.rst
new file mode 100644
index 000000000000..d48f2f605068
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/license-rules.rst
@@ -0,0 +1,372 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/license-rules.rst <kernel_licensing>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+.. _tw_kernel_licensing:
+
+Linux內核許可規則
+=================
+
+Linux內核根據LICENSES/preferred/GPL-2.0中提供的GNU通用公共許可證版本2
+(GPL-2.0)的條款提供,並在LICENSES/exceptions/Linux-syscall-note中顯式
+描述了例外的系統調用,如COPYING文件中所述。
+
+此文檔文件提供了如何對每個源文件進行注釋以使其許可證清晰明確的說明。
+它不會取代內核的許可證。
+
+內核原始碼作爲一個整體適用於COPYING文件中描述的許可證,但是單個源文件可以
+具有不同的與GPL-20兼容的許可證::
+
+    GPL-1.0+ : GNU通用公共許可證v1.0或更高版本
+    GPL-2.0+ : GNU通用公共許可證v2.0或更高版本
+    LGPL-2.0 : 僅限GNU庫通用公共許可證v2
+    LGPL-2.0+: GNU 庫通用公共許可證v2或更高版本
+    LGPL-2.1 : 僅限GNU寬通用公共許可證v2.1
+    LGPL-2.1+: GNU寬通用公共許可證v2.1或更高版本
+
+除此之外,個人文件可以在雙重許可下提供,例如一個兼容的GPL變體,或者BSD,
+MIT等許可。
+
+用戶空間API(UAPI)頭文件描述了用戶空間程序與內核的接口,這是一種特殊情況。
+根據內核COPYING文件中的注釋,syscall接口是一個明確的邊界,它不會將GPL要求
+擴展到任何使用它與內核通信的軟體。由於UAPI頭文件必須包含在創建在Linux內核
+上運行的可執行文件的任何源文件中,因此此例外必須記錄在特別的許可證表述中。
+
+表達源文件許可證的常用方法是將匹配的樣板文本添加到文件的頂部注釋中。由於
+格式,拼寫錯誤等,這些「樣板」很難通過那些在上下文中使用的驗證許可證合規性
+的工具。
+
+樣板文本的替代方法是在每個源文件中使用軟體包數據交換(SPDX)許可證標識符。
+SPDX許可證標識符是機器可解析的,並且是用於提供文件內容的許可證的精確縮寫。
+SPDX許可證標識符由Linux 基金會的SPDX 工作組管理,並得到了整個行業,工具
+供應商和法律團隊的合作夥伴的一致同意。有關詳細信息,請參閱
+https://spdx.org/
+
+Linux內核需要所有源文件中的精確SPDX標識符。內核中使用的有效標識符在
+`許可標識符`_ 一節中進行了解釋,並且已可以在
+https://spdx.org/licenses/ 上的官方SPDX許可證列表中檢索,並附帶許可證
+文本。
+
+許可標識符語法
+--------------
+
+1.安置:
+
+   內核文件中的SPDX許可證標識符應添加到可包含注釋的文件中的第一行。對於大多
+   數文件,這是第一行,除了那些在第一行中需要'#!PATH_TO_INTERPRETER'的腳本。
+   對於這些腳本,SPDX標識符進入第二行。
+
+|
+
+2. 風格:
+
+   SPDX許可證標識符以注釋的形式添加。注釋樣式取決於文件類型::
+
+      C source:	// SPDX-License-Identifier: <SPDX License Expression>
+      C header:	/* SPDX-License-Identifier: <SPDX License Expression> */
+      ASM:	/* SPDX-License-Identifier: <SPDX License Expression> */
+      scripts:	# SPDX-License-Identifier: <SPDX License Expression>
+      .rst:	.. SPDX-License-Identifier: <SPDX License Expression>
+      .dts{i}:	// SPDX-License-Identifier: <SPDX License Expression>
+
+   如果特定工具無法處理標準注釋樣式,則應使用工具接受的相應注釋機制。這是在
+   C 頭文件中使用「/\*\*/」樣式注釋的原因。過去在使用生成的.lds文件中觀察到
+   構建被破壞,其中'ld'無法解析C++注釋。現在已經解決了這個問題,但仍然有較
+   舊的彙編程序工具無法處理C++樣式的注釋。
+
+|
+
+3. 句法:
+
+   <SPDX許可證表達式>是SPDX許可證列表中的SPDX短格式許可證標識符,或者在許可
+   證例外適用時由「WITH」分隔的兩個SPDX短格式許可證標識符的組合。當應用多個許
+   可證時,表達式由分隔子表達式的關鍵字「AND」,「OR」組成,並由「(」,「)」包圍。
+
+   帶有「或更高」選項的[L]GPL等許可證的許可證標識符通過使用「+」來表示「或更高」
+   選項來構建。::
+
+      // SPDX-License-Identifier: GPL-2.0+
+      // SPDX-License-Identifier: LGPL-2.1+
+
+   當需要修正的許可證時,應使用WITH。 例如,linux內核UAPI文件使用表達式::
+
+      // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
+      // SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note
+
+   其它在內核中使用WITH例外的事例如下::
+
+      // SPDX-License-Identifier: GPL-2.0 WITH mif-exception
+      // SPDX-License-Identifier: GPL-2.0+ WITH GCC-exception-2.0
+
+   例外只能與特定的許可證標識符一起使用。有效的許可證標識符列在異常文本文件
+   的標記中。有關詳細信息,請參閱 `許可標識符`_ 一章中的 `例外`_ 。
+
+   如果文件是雙重許可且只選擇一個許可證,則應使用OR。例如,一些dtsi文件在雙
+   許可下可用::
+
+      // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+
+   內核中雙許可文件中許可表達式的示例::
+
+      // SPDX-License-Identifier: GPL-2.0 OR MIT
+      // SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+      // SPDX-License-Identifier: GPL-2.0 OR Apache-2.0
+      // SPDX-License-Identifier: GPL-2.0 OR MPL-1.1
+      // SPDX-License-Identifier: (GPL-2.0 WITH Linux-syscall-note) OR MIT
+      // SPDX-License-Identifier: GPL-1.0+ OR BSD-3-Clause OR OpenSSL
+
+   如果文件具有多個許可證,其條款全部適用於使用該文件,則應使用AND。例如,
+   如果代碼是從另一個項目繼承的,並且已經授予了將其放入內核的權限,但原始
+   許可條款需要保持有效::
+
+      // SPDX-License-Identifier: (GPL-2.0 WITH Linux-syscall-note) AND MIT
+
+   另一個需要遵守兩套許可條款的例子是::
+
+      // SPDX-License-Identifier: GPL-1.0+ AND LGPL-2.1+
+
+許可標識符
+----------
+
+當前使用的許可證以及添加到內核的代碼許可證可以分解爲:
+
+1. _`優先許可`:
+
+   應儘可能使用這些許可證,因爲它們已知完全兼容並廣泛使用。這些許可證在內核
+   目錄::
+
+      LICENSES/preferred/
+
+   此目錄中的文件包含完整的許可證文本和 `元標記`_ 。文件名與SPDX許可證標識
+   符相同,後者應用於源文件中的許可證。
+
+   例如::
+
+      LICENSES/preferred/GPL-2.0
+
+   包含GPLv2許可證文本和所需的元標籤::
+
+      LICENSES/preferred/MIT
+
+   包含MIT許可證文本和所需的元標記
+
+   _`元標記`:
+
+   許可證文件中必須包含以下元標記:
+
+   - Valid-License-Identifier:
+
+     一行或多行, 聲明那些許可標識符在項目內有效, 以引用此特定許可的文本。通
+     常這是一個有效的標識符,但是例如對於帶有'或更高'選項的許可證,兩個標識
+     符都有效。
+
+   - SPDX-URL:
+
+     SPDX頁面的URL,其中包含與許可證相關的其他信息.
+
+   - Usage-Guidance:
+
+     使用建議的自由格式文本。該文本必須包含SPDX許可證標識符的正確示例,因爲
+     它們應根據 `許可標識符語法`_ 指南放入源文件中。
+
+   - License-Text:
+
+     此標記之後的所有文本都被視爲原始許可文本
+
+   文件格式示例::
+
+      Valid-License-Identifier: GPL-2.0
+      Valid-License-Identifier: GPL-2.0+
+      SPDX-URL: https://spdx.org/licenses/GPL-2.0.html
+      Usage-Guide:
+        To use this license in source code, put one of the following SPDX
+	tag/value pairs into a comment according to the placement
+	guidelines in the licensing rules documentation.
+	For 'GNU General Public License (GPL) version 2 only' use:
+	  SPDX-License-Identifier: GPL-2.0
+	For 'GNU General Public License (GPL) version 2 or any later version' use:
+	  SPDX-License-Identifier: GPL-2.0+
+      License-Text:
+        Full license text
+
+   ::
+
+      SPDX-License-Identifier: MIT
+      SPDX-URL: https://spdx.org/licenses/MIT.html
+      Usage-Guide:
+	To use this license in source code, put the following SPDX
+	tag/value pair into a comment according to the placement
+	guidelines in the licensing rules documentation.
+	  SPDX-License-Identifier: MIT
+      License-Text:
+        Full license text
+
+|
+
+2. 不推薦的許可證:
+
+   這些許可證只應用於現有代碼或從其他項目導入代碼。這些許可證在內核目錄::
+
+      LICENSES/other/
+
+   此目錄中的文件包含完整的許可證文本和 `元標記`_ 。文件名與SPDX許可證標識
+   符相同,後者應用於源文件中的許可證。
+
+   例如::
+
+      LICENSES/other/ISC
+
+   包含國際系統聯合許可文本和所需的元標籤::
+
+      LICENSES/other/ZLib
+
+   包含ZLIB許可文本和所需的元標籤.
+
+   元標籤:
+
+   「其他」許可證的元標籤要求與 `優先許可`_ 的要求相同。
+
+   文件格式示例::
+
+      Valid-License-Identifier: ISC
+      SPDX-URL: https://spdx.org/licenses/ISC.html
+      Usage-Guide:
+        Usage of this license in the kernel for new code is discouraged
+	and it should solely be used for importing code from an already
+	existing project.
+        To use this license in source code, put the following SPDX
+	tag/value pair into a comment according to the placement
+	guidelines in the licensing rules documentation.
+	  SPDX-License-Identifier: ISC
+      License-Text:
+        Full license text
+
+|
+
+3. _`例外`:
+
+   某些許可證可以修改,並允許原始許可證不具有的某些例外權利。這些例外在
+   內核目錄::
+
+      LICENSES/exceptions/
+
+   此目錄中的文件包含完整的例外文本和所需的 `例外元標記`_ 。
+
+   例如::
+
+      LICENSES/exceptions/Linux-syscall-note
+
+   包含Linux內核的COPYING文件中記錄的Linux系統調用例外,該文件用於UAPI
+   頭文件。例如::
+
+      LICENSES/exceptions/GCC-exception-2.0
+
+   包含GCC'連結例外',它允許獨立於其許可證的任何二進位文件與標記有此例外的
+   文件的編譯版本連結。這是從GPL不兼容原始碼創建可運行的可執行文件所必需的。
+
+   _`例外元標記`:
+
+   以下元標記必須在例外文件中可用:
+
+   - SPDX-Exception-Identifier:
+
+     一個可與SPDX許可證標識符一起使用的例外標識符。
+
+   - SPDX-URL:
+
+     SPDX頁面的URL,其中包含與例外相關的其他信息。
+
+   - SPDX-Licenses:
+
+     以逗號分隔的例外可用的SPDX許可證標識符列表。
+
+   - Usage-Guidance:
+
+     使用建議的自由格式文本。必須在文本後面加上SPDX許可證標識符的正確示例,
+     因爲它們應根據 `許可標識符語法`_ 指南放入源文件中。
+
+   - Exception-Text:
+
+     此標記之後的所有文本都被視爲原始異常文本
+
+   文件格式示例::
+
+      SPDX-Exception-Identifier: Linux-syscall-note
+      SPDX-URL: https://spdx.org/licenses/Linux-syscall-note.html
+      SPDX-Licenses: GPL-2.0, GPL-2.0+, GPL-1.0+, LGPL-2.0, LGPL-2.0+, LGPL-2.1, LGPL-2.1+
+      Usage-Guidance:
+        This exception is used together with one of the above SPDX-Licenses
+	to mark user-space API (uapi) header files so they can be included
+	into non GPL compliant user-space application code.
+        To use this exception add it with the keyword WITH to one of the
+	identifiers in the SPDX-Licenses tag:
+	  SPDX-License-Identifier: <SPDX-License> WITH Linux-syscall-note
+      Exception-Text:
+        Full exception text
+
+   ::
+
+      SPDX-Exception-Identifier: GCC-exception-2.0
+      SPDX-URL: https://spdx.org/licenses/GCC-exception-2.0.html
+      SPDX-Licenses: GPL-2.0, GPL-2.0+
+      Usage-Guidance:
+        The "GCC Runtime Library exception 2.0" is used together with one
+	of the above SPDX-Licenses for code imported from the GCC runtime
+	library.
+        To use this exception add it with the keyword WITH to one of the
+	identifiers in the SPDX-Licenses tag:
+	  SPDX-License-Identifier: <SPDX-License> WITH GCC-exception-2.0
+      Exception-Text:
+        Full exception text
+
+
+所有SPDX許可證標識符和例外都必須在LICENSES子目錄中具有相應的文件。這是允許
+工具驗證(例如checkpatch.pl)以及準備好從源讀取和提取許可證所必需的, 這是
+各種FOSS組織推薦的,例如 `FSFE REUSE initiative <https://reuse.software/>`_.
+
+_`模塊許可`
+-----------------
+
+   可加載內核模塊還需要MODULE_LICENSE()標記。此標記既不替代正確的原始碼
+   許可證信息(SPDX-License-Identifier),也不以任何方式表示或確定提供模塊
+   原始碼的確切許可證。
+
+   此標記的唯一目的是提供足夠的信息,該模塊是否是自由軟體或者是內核模塊加
+   載器和用戶空間工具的專有模塊。
+
+   MODULE_LICENSE()的有效許可證字符串是:
+
+    ============================= =============================================
+    "GPL"			  模塊是根據GPL版本2許可的。這並不表示僅限於
+                                  GPL-2.0或GPL-2.0或更高版本之間的任何區別。
+                                  最正確許可證信息只能通過相應源文件中的許可證
+                                  信息來確定
+
+    "GPL v2"			  和"GPL"相同,它的存在是因爲歷史原因。
+
+    "GPL and additional rights"   表示模塊源在GPL v2變體和MIT許可下雙重許可的
+                                  歷史變體。請不要在新代碼中使用。
+
+    "Dual MIT/GPL"		  表達該模塊在GPL v2變體或MIT許可證選擇下雙重
+                                  許可的正確方式。
+
+    "Dual BSD/GPL"		  該模塊根據GPL v2變體或BSD許可證選擇進行雙重
+                                  許可。 BSD許可證的確切變體只能通過相應源文件
+                                  中的許可證信息來確定。
+
+    "Dual MPL/GPL"		  該模塊根據GPL v2變體或Mozilla Public License
+                                  (MPL)選項進行雙重許可。 MPL許可證的確切變體
+                                  只能通過相應的源文件中的許可證信息來確定。
+
+    "Proprietary"		  該模塊屬於專有許可。此字符串僅用於專有的第三
+                                  方模塊,不能用於在內核樹中具有原始碼的模塊。
+                                  以這種方式標記的模塊在加載時會使用'P'標記汙
+                                  染內核,並且內核模塊加載器拒絕將這些模塊連結
+                                  到使用EXPORT_SYMBOL_GPL()導出的符號。
+    ============================= =============================================
+
+
diff --git a/Documentation/translations/zh_TW/process/magic-number.rst b/Documentation/translations/zh_TW/process/magic-number.rst
new file mode 100644
index 000000000000..491459ea792f
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/magic-number.rst
@@ -0,0 +1,146 @@
+.. _tw_magicnumbers:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/magic-number.rst <magicnumbers>`
+
+如果想評論或更新本文的內容,請直接發信到LKML。如果你使用英文交流有困難的話,也可
+以向中文版維護者求助。如果本翻譯更新不及時或者翻譯存在問題,請聯繫中文版維護者::
+
+        中文版維護者: 賈威威 Jia Wei Wei <harryxiyou@gmail.com>
+        中文版翻譯者: 賈威威 Jia Wei Wei <harryxiyou@gmail.com>
+        中文版校譯者: 賈威威 Jia Wei Wei <harryxiyou@gmail.com>
+                      胡皓文 Hu Haowen <src.res@email.cn>
+
+Linux 魔術數
+============
+
+這個文件是有關當前使用的魔術值註冊表。當你給一個結構添加了一個魔術值,你也應該把這個魔術值添加到這個文件,因爲我們最好把用於各種結構的魔術值統一起來。
+
+使用魔術值來保護內核數據結構是一個非常好的主意。這就允許你在運行期檢查(a)一個結構是否已經被攻擊,或者(b)你已經給一個例行程序通過了一個錯誤的結構。後一種情況特別地有用---特別是當你通過一個空指針指向結構體的時候。tty源碼,例如,經常通過特定驅動使用這種方法並且反覆地排列特定方面的結構。
+
+使用魔術值的方法是在結構的開始處聲明的,如下::
+
+        struct tty_ldisc {
+	        int	magic;
+        	...
+        };
+
+當你以後給內核添加增強功能的時候,請遵守這條規則!這樣就會節省數不清的調試時間,特別是一些古怪的情況,例如,數組超出範圍並且重新寫了超出部分。遵守這個規則,‪這些情況可以被快速地,安全地避免。
+
+		Theodore Ts'o
+		  31 Mar 94
+
+給當前的Linux 2.1.55添加魔術表。
+
+		Michael Chastain
+		<mailto:mec@shout.net>
+		22 Sep 1997
+
+現在應該最新的Linux 2.1.112.因爲在特性凍結期間,不能在2.2.x前改變任何東西。這些條目被數域所排序。
+
+		Krzysztof G.Baranowski
+	        <mailto: kgb@knm.org.pl>
+		29 Jul 1998
+
+更新魔術表到Linux 2.5.45。剛好越過特性凍結,但是有可能還會有一些新的魔術值在2.6.x之前融入到內核中。
+
+		Petr Baudis
+		<pasky@ucw.cz>
+		03 Nov 2002
+
+更新魔術表到Linux 2.5.74。
+
+		Fabian Frederick
+                <ffrederick@users.sourceforge.net>
+		09 Jul 2003
+
+===================== ================ ======================== ==========================================
+魔術數名              數字             結構                     文件
+===================== ================ ======================== ==========================================
+PG_MAGIC              'P'              pg_{read,write}_hdr      ``include/linux/pg.h``
+CMAGIC                0x0111           user                     ``include/linux/a.out.h``
+MKISS_DRIVER_MAGIC    0x04bf           mkiss_channel            ``drivers/net/mkiss.h``
+HDLC_MAGIC            0x239e           n_hdlc                   ``drivers/char/n_hdlc.c``
+APM_BIOS_MAGIC        0x4101           apm_user                 ``arch/x86/kernel/apm_32.c``
+DB_MAGIC              0x4442           fc_info                  ``drivers/net/iph5526_novram.c``
+DL_MAGIC              0x444d           fc_info                  ``drivers/net/iph5526_novram.c``
+FASYNC_MAGIC          0x4601           fasync_struct            ``include/linux/fs.h``
+FF_MAGIC              0x4646           fc_info                  ``drivers/net/iph5526_novram.c``
+PTY_MAGIC             0x5001                                    ``drivers/char/pty.c``
+PPP_MAGIC             0x5002           ppp                      ``include/linux/if_pppvar.h``
+SSTATE_MAGIC          0x5302           serial_state             ``include/linux/serial.h``
+SLIP_MAGIC            0x5302           slip                     ``drivers/net/slip.h``
+STRIP_MAGIC           0x5303           strip                    ``drivers/net/strip.c``
+SIXPACK_MAGIC         0x5304           sixpack                  ``drivers/net/hamradio/6pack.h``
+AX25_MAGIC            0x5316           ax_disp                  ``drivers/net/mkiss.h``
+TTY_MAGIC             0x5401           tty_struct               ``include/linux/tty.h``
+MGSL_MAGIC            0x5401           mgsl_info                ``drivers/char/synclink.c``
+TTY_DRIVER_MAGIC      0x5402           tty_driver               ``include/linux/tty_driver.h``
+MGSLPC_MAGIC          0x5402           mgslpc_info              ``drivers/char/pcmcia/synclink_cs.c``
+USB_SERIAL_MAGIC      0x6702           usb_serial               ``drivers/usb/serial/usb-serial.h``
+FULL_DUPLEX_MAGIC     0x6969                                    ``drivers/net/ethernet/dec/tulip/de2104x.c``
+USB_BLUETOOTH_MAGIC   0x6d02           usb_bluetooth            ``drivers/usb/class/bluetty.c``
+RFCOMM_TTY_MAGIC      0x6d02                                    ``net/bluetooth/rfcomm/tty.c``
+USB_SERIAL_PORT_MAGIC 0x7301           usb_serial_port          ``drivers/usb/serial/usb-serial.h``
+CG_MAGIC              0x00090255       ufs_cylinder_group       ``include/linux/ufs_fs.h``
+LSEMAGIC              0x05091998       lse                      ``drivers/fc4/fc.c``
+GDTIOCTL_MAGIC        0x06030f07       gdth_iowr_str            ``drivers/scsi/gdth_ioctl.h``
+RIEBL_MAGIC           0x09051990                                ``drivers/net/atarilance.c``
+NBD_REQUEST_MAGIC     0x12560953       nbd_request              ``include/linux/nbd.h``
+RED_MAGIC2            0x170fc2a5       (any)                    ``mm/slab.c``
+BAYCOM_MAGIC          0x19730510       baycom_state             ``drivers/net/baycom_epp.c``
+ISDN_X25IFACE_MAGIC   0x1e75a2b9       isdn_x25iface_proto_data ``drivers/isdn/isdn_x25iface.h``
+ECP_MAGIC             0x21504345       cdkecpsig                ``include/linux/cdk.h``
+LSOMAGIC              0x27091997       lso                      ``drivers/fc4/fc.c``
+LSMAGIC               0x2a3b4d2a       ls                       ``drivers/fc4/fc.c``
+WANPIPE_MAGIC         0x414C4453       sdla_{dump,exec}         ``include/linux/wanpipe.h``
+CS_CARD_MAGIC         0x43525553       cs_card                  ``sound/oss/cs46xx.c``
+LABELCL_MAGIC         0x4857434c       labelcl_info_s           ``include/asm/ia64/sn/labelcl.h``
+ISDN_ASYNC_MAGIC      0x49344C01       modem_info               ``include/linux/isdn.h``
+CTC_ASYNC_MAGIC       0x49344C01       ctc_tty_info             ``drivers/s390/net/ctctty.c``
+ISDN_NET_MAGIC        0x49344C02       isdn_net_local_s         ``drivers/isdn/i4l/isdn_net_lib.h``
+SAVEKMSG_MAGIC2       0x4B4D5347       savekmsg                 ``arch/*/amiga/config.c``
+CS_STATE_MAGIC        0x4c4f4749       cs_state                 ``sound/oss/cs46xx.c``
+SLAB_C_MAGIC          0x4f17a36d       kmem_cache               ``mm/slab.c``
+COW_MAGIC             0x4f4f4f4d       cow_header_v1            ``arch/um/drivers/ubd_user.c``
+I810_CARD_MAGIC       0x5072696E       i810_card                ``sound/oss/i810_audio.c``
+TRIDENT_CARD_MAGIC    0x5072696E       trident_card             ``sound/oss/trident.c``
+ROUTER_MAGIC          0x524d4157       wan_device               [in ``wanrouter.h`` pre 3.9]
+SAVEKMSG_MAGIC1       0x53415645       savekmsg                 ``arch/*/amiga/config.c``
+GDA_MAGIC             0x58464552       gda                      ``arch/mips/include/asm/sn/gda.h``
+RED_MAGIC1            0x5a2cf071       (any)                    ``mm/slab.c``
+EEPROM_MAGIC_VALUE    0x5ab478d2       lanai_dev                ``drivers/atm/lanai.c``
+HDLCDRV_MAGIC         0x5ac6e778       hdlcdrv_state            ``include/linux/hdlcdrv.h``
+PCXX_MAGIC            0x5c6df104       channel                  ``drivers/char/pcxx.h``
+KV_MAGIC              0x5f4b565f       kernel_vars_s            ``arch/mips/include/asm/sn/klkernvars.h``
+I810_STATE_MAGIC      0x63657373       i810_state               ``sound/oss/i810_audio.c``
+TRIDENT_STATE_MAGIC   0x63657373       trient_state             ``sound/oss/trident.c``
+M3_CARD_MAGIC         0x646e6f50       m3_card                  ``sound/oss/maestro3.c``
+FW_HEADER_MAGIC       0x65726F66       fw_header                ``drivers/atm/fore200e.h``
+SLOT_MAGIC            0x67267321       slot                     ``drivers/hotplug/cpqphp.h``
+SLOT_MAGIC            0x67267322       slot                     ``drivers/hotplug/acpiphp.h``
+LO_MAGIC              0x68797548       nbd_device               ``include/linux/nbd.h``
+M3_STATE_MAGIC        0x734d724d       m3_state                 ``sound/oss/maestro3.c``
+VMALLOC_MAGIC         0x87654320       snd_alloc_track          ``sound/core/memory.c``
+KMALLOC_MAGIC         0x87654321       snd_alloc_track          ``sound/core/memory.c``
+PWC_MAGIC             0x89DC10AB       pwc_device               ``drivers/usb/media/pwc.h``
+NBD_REPLY_MAGIC       0x96744668       nbd_reply                ``include/linux/nbd.h``
+ENI155_MAGIC          0xa54b872d       midway_eprom	        ``drivers/atm/eni.h``
+CODA_MAGIC            0xC0DAC0DA       coda_file_info           ``fs/coda/coda_fs_i.h``
+DPMEM_MAGIC           0xc0ffee11       gdt_pci_sram             ``drivers/scsi/gdth.h``
+YAM_MAGIC             0xF10A7654       yam_port                 ``drivers/net/hamradio/yam.c``
+CCB_MAGIC             0xf2691ad2       ccb                      ``drivers/scsi/ncr53c8xx.c``
+QUEUE_MAGIC_FREE      0xf7e1c9a3       queue_entry              ``drivers/scsi/arm/queue.c``
+QUEUE_MAGIC_USED      0xf7e1cc33       queue_entry              ``drivers/scsi/arm/queue.c``
+HTB_CMAGIC            0xFEFAFEF1       htb_class                ``net/sched/sch_htb.c``
+NMI_MAGIC             0x48414d4d455201 nmi_s                    ``arch/mips/include/asm/sn/nmi.h``
+===================== ================ ======================== ==========================================
+
+
+請注意,在聲音記憶管理中仍然有一些特殊的爲每個驅動定義的魔術值。查看include/sound/sndmagic.h來獲取他們完整的列表信息。很多OSS聲音驅動擁有自己從音效卡PCI ID構建的魔術值-他們也沒有被列在這裡。
+
+IrDA子系統也使用了大量的自己的魔術值,查看include/net/irda/irda.h來獲取他們完整的信息。
+
+HFS是另外一個比較大的使用魔術值的文件系統-你可以在fs/hfs/hfs.h中找到他們。
+
diff --git a/Documentation/translations/zh_TW/process/management-style.rst b/Documentation/translations/zh_TW/process/management-style.rst
new file mode 100644
index 000000000000..0fddb0115a4c
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/management-style.rst
@@ -0,0 +1,209 @@
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/management-style.rst <managementstyle>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+.. _tw_managementstyle:
+
+Linux內核管理風格
+=================
+
+這是一個簡短的文檔,描述了Linux內核首選的(或胡編的,取決於您問誰)管理風格。
+它的目的是在某種程度上參照 :ref:`process/coding-style.rst <codingstyle>`
+主要是爲了避免反覆回答 [#cnf1]_ 相同(或類似)的問題。
+
+管理風格是非常個人化的,比簡單的編碼風格規則更難以量化,因此本文檔可能與實
+際情況有關,也可能與實際情況無關。起初它是一個玩笑,但這並不意味著它可能不
+是真的。你得自己決定。
+
+順便說一句,在談到「核心管理者」時,主要是技術負責人,而不是在公司內部進行傳
+統管理的人。如果你簽署了採購訂單或者對你的團隊的預算有任何了解,你幾乎肯定
+不是一個核心管理者。這些建議可能適用於您,也可能不適用於您。
+
+首先,我建議你購買「高效人的七個習慣」,而不是閱讀它。燒了它,這是一個偉大的
+象徵性姿態。
+
+.. [#cnf1] 本文件並不是通過回答問題,而是通過讓提問者痛苦地明白,我們不知道
+   答案是什麼。
+
+不管怎樣,這裡是:
+
+.. _tw_decisions:
+
+1)決策
+-------
+
+每個人都認爲管理者做決定,而且決策很重要。決定越大越痛苦,管理者就必須越高級。
+這很明顯,但事實並非如此。
+
+遊戲的名字是 **避免** 做出決定。尤其是,如果有人告訴你「選擇(a)或(b),
+我們真的需要你來做決定」,你就是陷入麻煩的管理者。你管理的人比你更了解細節,
+所以如果他們來找你做技術決策,你完蛋了。你顯然沒有能力爲他們做這個決定。
+
+(推論:如果你管理的人不比你更了解細節,你也會被搞砸,儘管原因完全不同。
+也就是說,你的工作是錯的,他們應該管理你的才智)
+
+所以遊戲的名字是 **避免** 做出決定,至少是那些大而痛苦的決定。做一些小的
+和非結果性的決定是很好的,並且使您看起來好像知道自己在做什麼,所以內核管理者
+需要做的是將那些大的和痛苦的決定變成那些沒有人真正關心的小事情。
+
+這有助於認識到一個大的決定和一個小的決定之間的關鍵區別是你是否可以在事後修正
+你的決定。任何決定都可以通過始終確保如果你錯了(而且你一定會錯),你以後總是
+可以通過回溯來彌補損失。突然間,你就要做兩個無關緊要的決定,一個是錯誤的,另
+一個是正確的。
+
+人們甚至會認爲這是真正的領導能力(咳,胡說,咳)。
+
+因此,避免重大決策的關鍵在於避免做那些無法挽回的事情。不要被引導到一個你無法
+逃離的角落。走投無路的老鼠可能很危險——走投無路的管理者真可憐。
+
+事實證明,由於沒有人會愚蠢到讓內核管理者承擔巨大的財政責任,所以通常很容易
+回溯。既然你不可能浪費掉你無法償還的巨額資金,你唯一可以回溯的就是技術決策,
+而回溯很容易:只要告訴大家你是個不稱職的傻瓜,說對不起,然後撤銷你去年讓別
+人所做的毫無價值的工作。突然間,你一年前做的決定不在是一個重大的決定,因爲
+它很容易被推翻。
+
+事實證明,有些人對接受這種方法有困難,原因有兩個:
+
+ - 承認你是個白癡比看起來更難。我們都喜歡保持形象,在公共場合說你錯了有時
+   確實很難。
+ - 如果有人告訴你,你去年所做的工作終究是不值得的,那麼對那些可憐的低級工
+   程師來說也是很困難的,雖然實際的 **工作** 很容易刪除,但你可能已經不可
+   挽回地失去了工程師的信任。記住:「不可撤銷」是我們一開始就試圖避免的,
+   而你的決定終究是一個重大的決定。
+
+令人欣慰的是,這兩個原因都可以通過預先承認你沒有任何線索,提前告訴人們你的
+決定完全是初步的,而且可能是錯誤的事情來有效地緩解。你應該始終保留改變主意
+的權利,並讓人們 **意識** 到這一點。當你 **還沒有** 做過真正愚蠢的事情的時
+候,承認自己是愚蠢的要容易得多。
+
+然後,當它真的被證明是愚蠢的時候,人們就轉動他們的眼珠說「哎呀,下次不要了」。
+
+這種對不稱職的先發制人的承認,也可能使真正做這項工作的人也會三思是否值得做。
+畢竟,如果他們不確定這是否是一個好主意,你肯定不應該通過向他們保證他們所做
+的工作將會進入(內核)鼓勵他們。在他們開始一項巨大的努力之前,至少讓他們三
+思而後行。
+
+記住:他們最好比你更了解細節,而且他們通常認爲他們對每件事都有答案。作爲一
+個管理者,你能做的最好的事情不是灌輸自信,而是對他們所做的事情進行健康的批
+判性思考。
+
+順便說一句,另一種避免做出決定的方法是看起來很可憐的抱怨 「我們不能兩者兼
+得嗎?」 相信我,它是有效的。如果不清楚哪種方法更好,他們最終會弄清楚的。
+最終的答案可能是兩個團隊都會因爲這種情況而感到沮喪,以至於他們放棄了。
+
+這聽起來像是一個失敗,但這通常是一個跡象,表明兩個項目都有問題,而參與其中
+的人不能做決定的原因是他們都是錯誤的。你最終會聞到玫瑰的味道,你避免了另一
+個你本可以搞砸的決定。
+
+2)人
+-----
+
+大多數人都是白癡,做一名管理者意味著你必須處理好這件事,也許更重要的是,
+**他們** 必須處理好你。
+
+事實證明,雖然很容易糾正技術錯誤,但不容易糾正人格障礙。你只能和他們的和
+你的(人格障礙)共處。
+
+但是,爲了做好作爲內核管理者的準備,最好記住不要燒掉任何橋樑,不要轟炸任何
+無辜的村民,也不要疏遠太多的內核開發人員。事實證明,疏遠人是相當容易的,而
+親近一個疏遠的人是很難的。因此,「疏遠」立即屬於「不可逆」的範疇,並根據
+:ref:`tw_decisions` 成爲絕不可以做的事情。
+
+這裡只有幾個簡單的規則:
+
+ (1) 不要叫人笨蛋(至少不要在公共場合)
+ (2) 學習如何在忘記規則(1)時道歉
+
+問題在於 #1 很容易去做,因爲你可以用數百萬種不同的方式說「你是一個笨蛋」 [#cnf2]_
+有時甚至沒有意識到,而且幾乎總是帶著一種白熱化的信念,認爲你是對的。
+
+你越確信自己是對的(讓我們面對現實吧,你可以把幾乎所有人都稱爲壞人,而且你
+經常是對的),事後道歉就越難。
+
+要解決此問題,您實際上只有兩個選項:
+
+ - 非常擅長道歉
+ - 把「愛」均勻地散開,沒有人會真正感覺到自己被不公平地瞄準了。讓它有足夠的
+   創造性,他們甚至可能會覺得好笑。
+
+選擇永遠保持禮貌是不存在的。沒有人會相信一個如此明顯地隱藏了他們真實性格的人。
+
+.. [#cnf2] 保羅·西蒙演唱了「離開愛人的50種方法」,因爲坦率地說,「告訴開發者
+   他們是D*CKHEAD" 的100萬種方法都無法確認。但我確信他已經這麼想了。
+
+3)人2 - 好人
+-------------
+
+雖然大多數人都是白癡,但不幸的是,據此推論你也是白癡,儘管我們都自我感覺良
+好,我們比普通人更好(讓我們面對現實吧,沒有人相信他們是普通人或低於普通人),
+我們也應該承認我們不是最鋒利的刀,而且會有其他人比你更不像白癡。
+
+有些人對聰明人反應不好。其他人利用它們。
+
+作爲內核維護人員,確保您在第二組中。接受他們,因爲他們會讓你的工作更容易。
+特別是,他們能夠爲你做決定,這就是遊戲的全部內容。
+
+所以當你發現一個比你聰明的人時,就順其自然吧。你的管理職責在很大程度上變成
+了「聽起來像是個好主意——去嘗試吧」,或者「聽起來不錯,但是XXX呢?」「。第二個版
+本尤其是一個很好的方法,要麼學習一些關於「XXX」的新東西,要麼通過指出一些聰明
+人沒有想到的東西來顯得更具管理性。無論哪種情況,你都會贏。
+
+要注意的一件事是認識到一個領域的偉大不一定會轉化爲其他領域。所以你可能會向
+特定的方向刺激人們,但讓我們面對現實吧,他們可能擅長他們所做的事情,而且對
+其他事情都很差勁。好消息是,人們往往會自然而然地重拾他們擅長的東西,所以當
+你向某個方向刺激他們時,你並不是在做不可逆轉的事情,只是不要用力推。
+
+4)責備
+-------
+
+事情會出問題的,人們希望去責備人。貼標籤,你就是受責備的人。
+
+事實上,接受責備並不難,尤其是當人們意識到這不 **全是** 你的過錯時。這讓我
+們找到了承擔責任的最佳方式:爲別人承擔這件事。你會感覺很好,他們會感覺很好,
+沒有受到指責. 那誰,失去了他們的全部36GB色情收藏的人,因爲你的無能將勉強承
+認,你至少沒有試圖逃避責任。
+
+然後讓真正搞砸了的開發人員(如果你能找到他們)私下知道他們搞砸了。不僅是爲
+了將來可以避免,而且爲了讓他們知道他們欠你一個人情。而且,也許更重要的是,
+他們也可能是能夠解決問題的人。因爲,讓我們面對現實吧,肯定不是你。
+
+承擔責任也是你首先成爲管理者的原因。這是讓人們信任你,讓你獲得潛在的榮耀的
+一部分,因爲你就是那個會說「我搞砸了」的人。如果你已經遵循了以前的規則,你現
+在已經很擅長說了。
+
+5)應避免的事情
+---------------
+
+有一件事人們甚至比被稱爲「笨蛋」更討厭,那就是在一個神聖的聲音中被稱爲「笨蛋」。
+第一個你可以道歉,第二個你不會真正得到機會。即使你做得很好,他們也可能不再
+傾聽。
+
+我們都認爲自己比別人強,這意味著當別人裝腔作勢時,這會讓我們很惱火。你也許
+在道德和智力上比你周圍的每個人都優越,但不要試圖太明顯,除非你真的打算激怒
+某人 [#cnf3]_
+
+同樣,不要對事情太客氣或太微妙。禮貌很容易落得落花流水,把問題隱藏起來,
+正如他們所說,「在網際網路上,沒人能聽到你的含蓄。」用一個鈍器把這一點錘進去,
+因爲你不能真的依靠別人來獲得你的觀點。
+
+一些幽默可以幫助緩和直率和道德化。過度到荒謬的地步,可以灌輸一個觀點,而不
+會讓接受者感到痛苦,他們只是認爲你是愚蠢的。因此,它可以幫助我們擺脫對批評
+的個人心理障礙。
+
+.. [#cnf3] 提示:與你的工作沒有直接關係的網絡新聞組是消除你對他人不滿的好
+   方法。偶爾寫些侮辱性的帖子,打個噴嚏,讓你的情緒得到淨化。別把牢騷帶回家
+
+6)爲什麼是我?
+---------------
+
+既然你的主要責任似乎是爲別人的錯誤承擔責任,並且讓別人痛苦地明白你是不稱職
+的,那麼顯而易見的問題之一就變成了爲什麼首先要這樣做。
+
+首先,雖然你可能會或可能不會聽到十幾歲女孩(或男孩,讓我們不要在這裡評判或
+性別歧視)敲你的更衣室門,你會得到一個巨大的個人成就感爲「負責」。別介意你真
+的在領導別人,你要跟上別人,儘可能快地追趕他們。每個人都會認爲你是負責人。
+
+如果你可以做到這個, 這是個偉大的工作!
+
diff --git a/Documentation/translations/zh_TW/process/programming-language.rst b/Documentation/translations/zh_TW/process/programming-language.rst
new file mode 100644
index 000000000000..0e4081c58b98
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/programming-language.rst
@@ -0,0 +1,74 @@
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/programming-language.rst <programming_language>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+.. _tw_programming_language:
+
+程序設計語言
+============
+
+內核是用C語言 :ref:`c-language <tw_c-language>` 編寫的。更準確地說,內核通常是用 :ref:`gcc <tw_gcc>`
+在 ``-std=gnu89`` :ref:`gcc-c-dialect-options <tw_gcc-c-dialect-options>` 下編譯的:ISO C90的 GNU 方言(
+包括一些C99特性)
+
+這種方言包含對語言 :ref:`gnu-extensions <tw_gnu-extensions>` 的許多擴展,當然,它們許多都在內核中使用。
+
+對於一些體系結構,有一些使用 :ref:`clang <tw_clang>` 和 :ref:`icc <tw_icc>` 編譯內核
+的支持,儘管在編寫此文檔時還沒有完成,仍需要第三方補丁。
+
+屬性
+----
+
+在整個內核中使用的一個常見擴展是屬性(attributes) :ref:`gcc-attribute-syntax <tw_gcc-attribute-syntax>`
+屬性允許將實現定義的語義引入語言實體(如變量、函數或類型),而無需對語言進行
+重大的語法更改(例如添加新關鍵字) :ref:`n2049 <tw_n2049>`
+
+在某些情況下,屬性是可選的(即不支持這些屬性的編譯器仍然應該生成正確的代碼,
+即使其速度較慢或執行的編譯時檢查/診斷次數不夠)
+
+內核定義了僞關鍵字(例如, ``pure`` ),而不是直接使用GNU屬性語法(例如,
+``__attribute__((__pure__))`` ),以檢測可以使用哪些關鍵字和/或縮短代碼, 具體
+請參閱 ``include/linux/compiler_attributes.h``
+
+.. _tw_c-language:
+
+c-language
+   http://www.open-std.org/jtc1/sc22/wg14/www/standards
+
+.. _tw_gcc:
+
+gcc
+   https://gcc.gnu.org
+
+.. _tw_clang:
+
+clang
+   https://clang.llvm.org
+
+.. _tw_icc:
+
+icc
+   https://software.intel.com/en-us/c-compilers
+
+.. _tw_gcc-c-dialect-options:
+
+c-dialect-options
+   https://gcc.gnu.org/onlinedocs/gcc/C-Dialect-Options.html
+
+.. _tw_gnu-extensions:
+
+gnu-extensions
+   https://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html
+
+.. _tw_gcc-attribute-syntax:
+
+gcc-attribute-syntax
+   https://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html
+
+.. _tw_n2049:
+
+n2049
+   http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2049.pdf
+
diff --git a/Documentation/translations/zh_TW/process/stable-api-nonsense.rst b/Documentation/translations/zh_TW/process/stable-api-nonsense.rst
new file mode 100644
index 000000000000..344f3d3dc793
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/stable-api-nonsense.rst
@@ -0,0 +1,157 @@
+.. _tw_stable_api_nonsense:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/stable-api-nonsense.rst
+           <stable_api_nonsense>`
+
+譯者::
+
+        中文版維護者: 鍾宇  TripleX Chung <xxx.phy@gmail.com>
+        中文版翻譯者: 鍾宇  TripleX Chung <xxx.phy@gmail.com>
+        中文版校譯者: 李陽  Li Yang <leoyang.li@nxp.com>
+                      胡皓文 Hu Haowen <src.res@email.cn>
+
+Linux 內核驅動接口
+==================
+
+寫作本文檔的目的,是爲了解釋爲什麼Linux既沒有二進位內核接口,也沒有穩定
+的內核接口。這裡所說的內核接口,是指內核里的接口,而不是內核和用戶空間
+的接口。內核到用戶空間的接口,是提供給應用程式使用的系統調用,系統調用
+在歷史上幾乎沒有過變化,將來也不會有變化。我有一些老應用程式是在0.9版本
+或者更早版本的內核上編譯的,在使用2.6版本內核的Linux發布上依然用得很好
+。用戶和應用程式作者可以將這個接口看成是穩定的。
+
+
+執行綱要
+--------
+
+你也許以爲自己想要穩定的內核接口,但是你不清楚你要的實際上不是它。你需
+要的其實是穩定的驅動程序,而你只有將驅動程序放到公版內核的原始碼樹里,
+才有可能達到這個目的。而且這樣做還有很多其它好處,正是因爲這些好處使得
+Linux能成爲強壯,穩定,成熟的作業系統,這也是你最開始選擇Linux的原因。
+
+
+入門
+-----
+
+只有那些寫驅動程序的「怪人」才會擔心內核接口的改變,對廣大用戶來說,既
+看不到內核接口,也不需要去關心它。
+
+首先,我不打算討論關於任何非GPL許可的內核驅動的法律問題,這些非GPL許可
+的驅動程序包括不公開原始碼,隱藏原始碼,二進位或者是用原始碼包裝,或者
+是其它任何形式的不能以GPL許可公開原始碼的驅動程序。如果有法律問題,請咨
+詢律師,我只是一個程式設計師,所以我只打算探討技術問題(不是小看法律問題,
+法律問題很實際,並且需要一直關注)。
+
+既然只談技術問題,我們就有了下面兩個主題:二進位內核接口和穩定的內核源
+代碼接口。這兩個問題是互相關聯的,讓我們先解決掉二進位接口的問題。
+
+
+二進位內核接口
+--------------
+假如我們有一個穩定的內核原始碼接口,那麼自然而然的,我們就擁有了穩定的
+二進位接口,是這樣的嗎?錯。讓我們看看關於Linux內核的幾點事實:
+
+    - 取決於所用的C編譯器的版本,不同的內核數據結構里的結構體的對齊方
+      式會有差別,代碼中不同函數的表現形式也不一樣(函數是不是被inline
+      編譯取決於編譯器行爲)。不同的函數的表現形式並不重要,但是數據
+      結構內部的對齊方式很關鍵。
+
+    - 取決於內核的配置選項,不同的選項會讓內核的很多東西發生改變:
+
+      - 同一個結構體可能包含不同的成員變量
+      - 有的函數可能根本不會被實現(比如編譯的時候沒有選擇SMP支持
+        一些鎖函數就會被定義成空函數)。
+      - 內核使用的內存會以不同的方式對齊,這取決於不同的內核配置選
+        項。
+
+    - Linux可以在很多的不同體系結構的處理器上運行。在某個體系結構上編
+      譯好的二進位驅動程序,不可能在另外一個體系結構上正確的運行。
+
+對於一個特定的內核,滿足這些條件並不難,使用同一個C編譯器和同樣的內核配
+置選項來編譯驅動程序模塊就可以了。這對於給一個特定Linux發布的特定版本提
+供驅動程序,是完全可以滿足需求的。但是如果你要給不同發布的不同版本都發
+布一個驅動程序,就需要在每個發布上用不同的內核設置參數都編譯一次內核,
+這簡直跟噩夢一樣。而且還要注意到,每個Linux發布還提供不同的Linux內核,
+這些內核都針對不同的硬體類型進行了優化(有很多種不同的處理器,還有不同
+的內核設置選項)。所以每發布一次驅動程序,都需要提供很多不同版本的內核
+模塊。
+
+相信我,如果你真的要採取這種發布方式,一定會慢慢瘋掉,我很久以前就有過
+深刻的教訓...
+
+
+穩定的內核原始碼接口
+--------------------
+
+如果有人不將他的內核驅動程序,放入公版內核的原始碼樹,而又想讓驅動程序
+一直保持在最新的內核中可用,那麼這個話題將會變得沒完沒了。
+內核開發是持續而且快節奏的,從來都不會慢下來。內核開發人員在當前接口中
+找到bug,或者找到更好的實現方式。一旦發現這些,他們就很快會去修改當前的
+接口。修改接口意味著,函數名可能會改變,結構體可能被擴充或者刪減,函數
+的參數也可能發生改變。一旦接口被修改,內核中使用這些接口的地方需要同時
+修正,這樣才能保證所有的東西繼續工作。
+
+舉一個例子,內核的USB驅動程序接口在USB子系統的整個生命周期中,至少經歷
+了三次重寫。這些重寫解決以下問題:
+
+    - 把數據流從同步模式改成非同步模式,這個改動減少了一些驅動程序的
+      複雜度,提高了所有USB驅動程序的吞吐率,這樣幾乎所有的USB設備都
+      能以最大速率工作了。
+    - 修改了USB核心代碼中爲USB驅動分配數據包內存的方式,所有的驅動都
+      需要提供更多的參數給USB核心,以修正了很多已經被記錄在案的死鎖。
+
+這和一些封閉原始碼的作業系統形成鮮明的對比,在那些作業系統上,不得不額
+外的維護舊的USB接口。這導致了一個可能性,新的開發者依然會不小心使用舊的
+接口,以不恰當的方式編寫代碼,進而影響到作業系統的穩定性。
+在上面的例子中,所有的開發者都同意這些重要的改動,在這樣的情況下修改代
+價很低。如果Linux保持一個穩定的內核原始碼接口,那麼就得創建一個新的接口
+;舊的,有問題的接口必須一直維護,給Linux USB開發者帶來額外的工作。既然
+所有的Linux USB驅動的作者都是利用自己的時間工作,那麼要求他們去做毫無意
+義的免費額外工作,是不可能的。
+安全問題對Linux來說十分重要。一個安全問題被發現,就會在短時間內得到修
+正。在很多情況下,這將導致Linux內核中的一些接口被重寫,以從根本上避免安
+全問題。一旦接口被重寫,所有使用這些接口的驅動程序,必須同時得到修正,
+以確定安全問題已經得到修復並且不可能在未來還有同樣的安全問題。如果內核
+內部接口不允許改變,那麼就不可能修復這樣的安全問題,也不可能確認這樣的
+安全問題以後不會發生。
+開發者一直在清理內核接口。如果一個接口沒有人在使用了,它就會被刪除。這
+樣可以確保內核儘可能的小,而且所有潛在的接口都會得到儘可能完整的測試
+(沒有人使用的接口是不可能得到良好的測試的)。
+
+
+要做什麼
+--------
+
+如果你寫了一個Linux內核驅動,但是它還不在Linux原始碼樹里,作爲一個開發
+者,你應該怎麼做?爲每個發布的每個版本提供一個二進位驅動,那簡直是一個
+噩夢,要跟上永遠處於變化之中的內核接口,也是一件辛苦活。
+很簡單,讓你的驅動進入內核原始碼樹(要記得我們在談論的是以GPL許可發行
+的驅動,如果你的代碼不符合GPL,那麼祝你好運,你只能自己解決這個問題了,
+你這個吸血鬼<把Andrew和Linus對吸血鬼的定義連結到這裡>)。當你的代碼加入
+公版內核原始碼樹之後,如果一個內核接口改變,你的驅動會直接被修改接口的
+那個人修改。保證你的驅動永遠都可以編譯通過,並且一直工作,你幾乎不需要
+做什麼事情。
+
+把驅動放到內核原始碼樹里會有很多的好處:
+
+    - 驅動的質量會提升,而維護成本(對原始作者來說)會下降。
+    - 其他人會給驅動添加新特性。
+    - 其他人會找到驅動中的bug並修復。
+    - 其他人會在驅動中找到性能優化的機會。
+    - 當外部的接口的改變需要修改驅動程序的時候,其他人會修改驅動程序
+    - 不需要聯繫任何發行商,這個驅動會自動的隨著所有的Linux發布一起發
+      布。
+
+和別的作業系統相比,Linux爲更多不同的設備提供現成的驅動,而且能在更多不
+同體系結構的處理器上支持這些設備。這個經過考驗的開發模式,必然是錯不了
+的 :)
+
+感謝
+----
+感謝 Randy Dunlap, Andrew Morton, David Brownell, Hanna Linder,
+Robert Love, and Nishanth Aravamudan 對於本文檔早期版本的評審和建議。
+
+英文版維護者: Greg Kroah-Hartman <greg@kroah.com>
+
diff --git a/Documentation/translations/zh_TW/process/stable-kernel-rules.rst b/Documentation/translations/zh_TW/process/stable-kernel-rules.rst
new file mode 100644
index 000000000000..d66306fa6dc8
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/stable-kernel-rules.rst
@@ -0,0 +1,66 @@
+.. _tw_stable_kernel_rules:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/stable-kernel-rules.rst <stable_kernel_rules>`
+
+如果想評論或更新本文的內容,請直接聯繫原文檔的維護者。如果你使用英文
+交流有困難的話,也可以向中文版維護者求助。如果本翻譯更新不及時或者翻
+譯存在問題,請聯繫中文版維護者::
+
+        中文版維護者: 鍾宇  TripleX Chung <xxx.phy@gmail.com>
+        中文版翻譯者: 鍾宇  TripleX Chung <xxx.phy@gmail.com>
+        中文版校譯者:
+            - 李陽  Li Yang <leoyang.li@nxp.com>
+            - Kangkai Yin <e12051@motorola.com>
+            - 胡皓文 Hu Haowen <src.res@email.cn>
+
+所有你想知道的事情 - 關於linux穩定版發布
+========================================
+
+關於Linux 2.6穩定版發布,所有你想知道的事情。
+
+關於哪些類型的補丁可以被接收進入穩定版代碼樹,哪些不可以的規則:
+----------------------------------------------------------------
+
+  - 必須是顯而易見的正確,並且經過測試的。
+  - 連同上下文,不能大於100行。
+  - 必須只修正一件事情。
+  - 必須修正了一個給大家帶來麻煩的真正的bug(不是「這也許是一個問題...」
+    那樣的東西)。
+  - 必須修正帶來如下後果的問題:編譯錯誤(對被標記爲CONFIG_BROKEN的例外),
+    內核崩潰,掛起,數據損壞,真正的安全問題,或者一些類似「哦,這不
+    好」的問題。簡短的說,就是一些致命的問題。
+  - 沒有「理論上的競爭條件」,除非能給出競爭條件如何被利用的解釋。
+  - 不能存在任何的「瑣碎的」修正(拼寫修正,去掉多餘空格之類的)。
+  - 必須被相關子系統的維護者接受。
+  - 必須遵循Documentation/translations/zh_TW/process/submitting-patches.rst里的規則。
+
+向穩定版代碼樹提交補丁的過程:
+------------------------------
+
+  - 在確認了補丁符合以上的規則後,將補丁發送到stable@vger.kernel.org。
+  - 如果補丁被接受到隊列里,發送者會收到一個ACK回復,如果沒有被接受,收
+    到的是NAK回復。回復需要幾天的時間,這取決於開發者的時間安排。
+  - 被接受的補丁會被加到穩定版本隊列里,等待其他開發者的審查。
+  - 安全方面的補丁不要發到這個列表,應該發送到security@kernel.org。
+
+審查周期:
+----------
+
+  - 當穩定版的維護者決定開始一個審查周期,補丁將被發送到審查委員會,以
+    及被補丁影響的領域的維護者(除非提交者就是該領域的維護者)並且抄送
+    到linux-kernel郵件列表。
+  - 審查委員會有48小時的時間,用來決定給該補丁回復ACK還是NAK。
+  - 如果委員會中有成員拒絕這個補丁,或者linux-kernel列表上有人反對這個
+    補丁,並提出維護者和審查委員會之前沒有意識到的問題,補丁會從隊列中
+    丟棄。
+  - 在審查周期結束的時候,那些得到ACK回應的補丁將會被加入到最新的穩定版
+    發布中,一個新的穩定版發布就此產生。
+  - 安全性補丁將從內核安全小組那裡直接接收到穩定版代碼樹中,而不是通過
+    通常的審查周期。請聯繫內核安全小組以獲得關於這個過程的更多細節。
+
+審查委員會:
+------------
+  - 由一些自願承擔這項任務的內核開發者,和幾個非志願的組成。
+
diff --git a/Documentation/translations/zh_TW/process/submit-checklist.rst b/Documentation/translations/zh_TW/process/submit-checklist.rst
new file mode 100644
index 000000000000..52d435814da1
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/submit-checklist.rst
@@ -0,0 +1,107 @@
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/submit-checklist.rst <submitchecklist>`
+:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+             Hu Haowen <src.res@email.cn>
+
+.. _tw_submitchecklist:
+
+Linux內核補丁提交清單
+~~~~~~~~~~~~~~~~~~~~~
+
+如果開發人員希望看到他們的內核補丁提交更快地被接受,那麼他們應該做一些基本
+的事情。
+
+這些都是在
+:ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
+和其他有關提交Linux內核補丁的文檔中提供的。
+
+1) 如果使用工具,則包括定義/聲明該工具的文件。不要依賴於其他頭文件拉入您使用
+   的頭文件。
+
+2) 乾淨的編譯:
+
+   a) 使用適用或修改的 ``CONFIG`` 選項 ``=y``、``=m`` 和 ``=n`` 。沒有GCC
+      警告/錯誤,沒有連結器警告/錯誤。
+
+   b) 通過allnoconfig、allmodconfig
+
+   c) 使用 ``O=builddir`` 時可以成功編譯
+
+3) 通過使用本地交叉編譯工具或其他一些構建場在多個CPU體系結構上構建。
+
+4) PPC64是一種很好的交叉編譯檢查體系結構,因爲它傾向於對64位的數使用無符號
+   長整型。
+
+5) 如下所述 :ref:`Documentation/translations/zh_TW/process/coding-style.rst <tw_codingstyle>`.
+   檢查您的補丁是否爲常規樣式。在提交( ``scripts/check patch.pl`` )之前,
+   使用補丁樣式檢查器檢查是否有輕微的衝突。您應該能夠處理您的補丁中存在的所有
+   違規行爲。
+
+6) 任何新的或修改過的 ``CONFIG`` 選項都不會弄髒配置菜單,並默認爲關閉,除非
+   它們符合 ``Documentation/kbuild/kconfig-language.rst`` 中記錄的異常條件,
+   菜單屬性:默認值.
+
+7) 所有新的 ``kconfig`` 選項都有幫助文本。
+
+8) 已仔細審查了相關的 ``Kconfig`` 組合。這很難用測試來糾正——腦力在這裡是有
+   回報的。
+
+9) 用 sparse 檢查乾淨。
+
+10) 使用 ``make checkstack`` 和 ``make namespacecheck`` 並修復他們發現的任何
+    問題。
+
+    .. note::
+
+        ``checkstack`` 並沒有明確指出問題,但是任何一個在堆棧上使用超過512
+        字節的函數都可以進行更改。
+
+11) 包括 :ref:`kernel-doc <kernel_doc>` 內核文檔以記錄全局內核API。(靜態函數
+    不需要,但也可以。)使用 ``make htmldocs`` 或 ``make pdfdocs`` 檢查
+    :ref:`kernel-doc <kernel_doc>` 並修復任何問題。
+
+12) 通過以下選項同時啓用的測試 ``CONFIG_PREEMPT``, ``CONFIG_DEBUG_PREEMPT``,
+    ``CONFIG_DEBUG_SLAB``, ``CONFIG_DEBUG_PAGEALLOC``, ``CONFIG_DEBUG_MUTEXES``,
+    ``CONFIG_DEBUG_SPINLOCK``, ``CONFIG_DEBUG_ATOMIC_SLEEP``,
+    ``CONFIG_PROVE_RCU`` and ``CONFIG_DEBUG_OBJECTS_RCU_HEAD``
+
+13) 已經過構建和運行時測試,包括有或沒有 ``CONFIG_SMP``, ``CONFIG_PREEMPT``.
+
+14) 如果補丁程序影響IO/磁碟等:使用或不使用 ``CONFIG_LBDAF`` 進行測試。
+
+15) 所有代碼路徑都已在啓用所有lockdep功能的情況下運行。
+
+16) 所有新的/proc條目都記錄在 ``Documentation/``
+
+17) 所有新的內核引導參數都記錄在
+    Documentation/admin-guide/kernel-parameters.rst 中。
+
+18) 所有新的模塊參數都記錄在 ``MODULE_PARM_DESC()``
+
+19) 所有新的用戶空間接口都記錄在 ``Documentation/ABI/`` 中。有關詳細信息,
+    請參閱 ``Documentation/ABI/README`` 。更改用戶空間接口的補丁應該抄送
+    linux-api@vger.kernel.org。
+
+20) 已通過至少注入slab和page分配失敗進行檢查。請參閱 ``Documentation/fault-injection/``
+    如果新代碼是實質性的,那麼添加子系統特定的故障注入可能是合適的。
+
+21) 新添加的代碼已經用 ``gcc -W`` 編譯(使用 ``make EXTRA-CFLAGS=-W`` )。這
+    將產生大量噪聲,但對於查找諸如「警告:有符號和無符號之間的比較」之類的錯誤
+    很有用。
+
+22) 在它被合併到-mm補丁集中之後進行測試,以確保它仍然與所有其他排隊的補丁以
+    及VM、VFS和其他子系統中的各種更改一起工作。
+
+23) 所有內存屏障例如 ``barrier()``, ``rmb()``, ``wmb()`` 都需要原始碼中的注
+    釋來解釋它們正在執行的操作及其原因的邏輯。
+
+24) 如果補丁添加了任何ioctl,那麼也要更新 ``Documentation/userspace-api/ioctl/ioctl-number.rst``
+
+25) 如果修改後的原始碼依賴或使用與以下 ``Kconfig`` 符號相關的任何內核API或
+    功能,則在禁用相關 ``Kconfig`` 符號和/或 ``=m`` (如果該選項可用)的情況
+    下測試以下多個構建[並非所有這些都同時存在,只是它們的各種/隨機組合]:
+
+    ``CONFIG_SMP``, ``CONFIG_SYSFS``, ``CONFIG_PROC_FS``, ``CONFIG_INPUT``, ``CONFIG_PCI``, ``CONFIG_BLOCK``, ``CONFIG_PM``, ``CONFIG_MAGIC_SYSRQ``,
+    ``CONFIG_NET``, ``CONFIG_INET=n`` (但是後者伴隨 ``CONFIG_NET=y``).
+
diff --git a/Documentation/translations/zh_TW/process/submitting-drivers.rst b/Documentation/translations/zh_TW/process/submitting-drivers.rst
new file mode 100644
index 000000000000..9727d27c362b
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/submitting-drivers.rst
@@ -0,0 +1,162 @@
+.. _tw_submittingdrivers:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/submitting-drivers.rst
+           <submittingdrivers>`
+
+如果想評論或更新本文的內容,請直接聯繫原文檔的維護者。如果你使用英文
+交流有困難的話,也可以向中文版維護者求助。如果本翻譯更新不及時或者翻
+譯存在問題,請聯繫中文版維護者::
+
+        中文版維護者: 李陽  Li Yang <leoyang.li@nxp.com>
+        中文版翻譯者: 李陽  Li Yang <leoyang.li@nxp.com>
+        中文版校譯者: 陳琦 Maggie Chen <chenqi@beyondsoft.com>
+                       王聰 Wang Cong <xiyou.wangcong@gmail.com>
+                       張巍 Zhang Wei <wezhang@outlook.com>
+                       胡皓文 Hu Haowen <src.res@email.cn>
+
+如何向 Linux 內核提交驅動程序
+=============================
+
+這篇文檔將會解釋如何向不同的內核源碼樹提交設備驅動程序。請注意,如果你感
+興趣的是顯卡驅動程序,你也許應該訪問 XFree86 項目(https://www.xfree86.org/)
+和/或 X.org 項目 (https://x.org)。
+
+另請參閱 Documentation/translations/zh_TW/process/submitting-patches.rst 文檔。
+
+
+分配設備號
+----------
+
+塊設備和字符設備的主設備號與從設備號是由 Linux 命名編號分配權威 LANANA(
+現在是 Torben Mathiasen)負責分配。申請的網址是 https://www.lanana.org/。
+即使不準備提交到主流內核的設備驅動也需要在這裡分配設備號。有關詳細信息,
+請參閱 Documentation/admin-guide/devices.rst。
+
+如果你使用的不是已經分配的設備號,那麼當你提交設備驅動的時候,它將會被強
+制分配一個新的設備號,即便這個設備號和你之前發給客戶的截然不同。
+
+設備驅動的提交對象
+------------------
+
+Linux 2.0:
+	此內核源碼樹不接受新的驅動程序。
+
+Linux 2.2:
+	此內核源碼樹不接受新的驅動程序。
+
+Linux 2.4:
+	如果所屬的代碼領域在內核的 MAINTAINERS 文件中列有一個總維護者,
+	那麼請將驅動程序提交給他。如果此維護者沒有回應或者你找不到恰當的
+	維護者,那麼請聯繫 Willy Tarreau <w@1wt.eu>。
+
+Linux 2.6:
+	除了遵循和 2.4 版內核同樣的規則外,你還需要在 linux-kernel 郵件
+	列表上跟蹤最新的 API 變化。向 Linux 2.6 內核提交驅動的頂級聯繫人
+	是 Andrew Morton <akpm@linux-foundation.org>。
+
+決定設備驅動能否被接受的條件
+----------------------------
+
+許可:		代碼必須使用 GNU 通用公開許可證 (GPL) 提交給 Linux,但是
+		我們並不要求 GPL 是唯一的許可。你或許會希望同時使用多種
+		許可證發布,如果希望驅動程序可以被其他開源社區(比如BSD)
+		使用。請參考 include/linux/module.h 文件中所列出的可被
+		接受共存的許可。
+
+版權:		版權所有者必須同意使用 GPL 許可。最好提交者和版權所有者
+		是相同個人或實體。否則,必需列出授權使用 GPL 的版權所有
+		人或實體,以備驗證之需。
+
+接口:		如果你的驅動程序使用現成的接口並且和其他同類的驅動程序行
+		爲相似,而不是去發明無謂的新接口,那麼它將會更容易被接受。
+		如果你需要一個 Linux 和 NT 的通用驅動接口,那麼請在用
+		戶空間實現它。
+
+代碼:		請使用 Documentation/process/coding-style.rst 中所描述的 Linux 代碼風
+		格。如果你的某些代碼段(例如那些與 Windows 驅動程序包共
+		享的代碼段)需要使用其他格式,而你卻只希望維護一份代碼,
+		那麼請將它們很好地區分出來,並且註明原因。
+
+可移植性:	請注意,指針並不永遠是 32 位的,不是所有的計算機都使用小
+		尾模式 (little endian) 存儲數據,不是所有的人都擁有浮點
+		單元,不要隨便在你的驅動程序里嵌入 x86 彙編指令。只能在
+		x86 上運行的驅動程序一般是不受歡迎的。雖然你可能只有 x86
+		硬體,很難測試驅動程序在其他平台上是否可用,但是確保代碼
+		可以被輕鬆地移植卻是很簡單的。
+
+清晰度:	做到所有人都能修補這個驅動程序將會很有好處,因爲這樣你將
+		會直接收到修復的補丁而不是 bug 報告。如果你提交一個試圖
+		隱藏硬體工作機理的驅動程序,那麼它將會被扔進廢紙簍。
+
+電源管理:	因爲 Linux 正在被很多行動裝置和桌面系統使用,所以你的驅
+		動程序也很有可能被使用在這些設備上。它應該支持最基本的電
+		源管理,即在需要的情況下實現系統級休眠和喚醒要用到的
+		.suspend 和 .resume 函數。你應該檢查你的驅動程序是否能正
+		確地處理休眠與喚醒,如果實在無法確認,請至少把 .suspend
+		函數定義成返回 -ENOSYS(功能未實現)錯誤。你還應該嘗試確
+		保你的驅動在什麼都不乾的情況下將耗電降到最低。要獲得驅動
+		程序測試的指導,請參閱
+		Documentation/power/drivers-testing.rst。有關驅動程序電
+		源管理問題相對全面的概述,請參閱
+		Documentation/driver-api/pm/devices.rst。
+
+管理:		如果一個驅動程序的作者還在進行有效的維護,那麼通常除了那
+		些明顯正確且不需要任何檢查的補丁以外,其他所有的補丁都會
+		被轉發給作者。如果你希望成爲驅動程序的聯繫人和更新者,最
+		好在代碼注釋中寫明並且在 MAINTAINERS 文件中加入這個驅動
+		程序的條目。
+
+不影響設備驅動能否被接受的條件
+------------------------------
+
+供應商:	由硬體供應商來維護驅動程序通常是一件好事。不過,如果源碼
+		樹里已經有其他人提供了可穩定工作的驅動程序,那麼請不要期
+		望「我是供應商」會成爲內核改用你的驅動程序的理由。理想的情
+		況是:供應商與現有驅動程序的作者合作,構建一個統一完美的
+		驅動程序。
+
+作者:		驅動程序是由大的 Linux 公司研發還是由你個人編寫,並不影
+		響其是否能被內核接受。沒有人對內核源碼樹享有特權。只要你
+		充分了解內核社區,你就會發現這一點。
+
+
+資源列表
+--------
+
+Linux 內核主源碼樹:
+	ftp.??.kernel.org:/pub/linux/kernel/...
+	?? == 你的國家代碼,例如 "cn"、"us"、"uk"、"fr" 等等
+
+Linux 內核郵件列表:
+	linux-kernel@vger.kernel.org
+	[可通過向majordomo@vger.kernel.org發郵件來訂閱]
+
+Linux 設備驅動程序,第三版(探討 2.6.10 版內核):
+	https://lwn.net/Kernel/LDD3/ (免費版)
+
+LWN.net:
+	每周內核開發活動摘要 - https://lwn.net/
+
+	2.6 版中 API 的變更:
+
+		https://lwn.net/Articles/2.6-kernel-api/
+
+	將舊版內核的驅動程序移植到 2.6 版:
+
+		https://lwn.net/Articles/driver-porting/
+
+內核新手(KernelNewbies):
+	爲新的內核開發者提供文檔和幫助
+	https://kernelnewbies.org/
+
+Linux USB項目:
+	http://www.linux-usb.org/
+
+寫內核驅動的「不要」(Arjan van de Ven著):
+	http://www.fenrus.org/how-to-not-write-a-device-driver-paper.pdf
+
+內核清潔工 (Kernel Janitor):
+	https://kernelnewbies.org/KernelJanitors
+
diff --git a/Documentation/translations/zh_TW/process/submitting-patches.rst b/Documentation/translations/zh_TW/process/submitting-patches.rst
new file mode 100644
index 000000000000..3b7dd4c73e0b
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/submitting-patches.rst
@@ -0,0 +1,684 @@
+.. _tw_submittingpatches:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/submitting-patches.rst <submittingpatches>`
+
+譯者::
+
+        中文版維護者: 鍾宇 TripleX Chung <xxx.phy@gmail.com>
+        中文版翻譯者: 鍾宇 TripleX Chung <xxx.phy@gmail.com>
+                       時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+        中文版校譯者: 李陽 Li Yang <leoyang.li@nxp.com>
+                       王聰 Wang Cong <xiyou.wangcong@gmail.com>
+                       胡皓文 Hu Haowen <src.res@email.cn>
+
+
+如何讓你的改動進入內核
+======================
+
+對於想要將改動提交到 Linux 內核的個人或者公司來說,如果不熟悉「規矩」,
+提交的流程會讓人畏懼。本文檔收集了一系列建議,這些建議可以大大的提高你
+的改動被接受的機會.
+
+以下文檔含有大量簡潔的建議, 具體請見:
+:ref:`Documentation/process <development_process_main>`
+同樣,:ref:`Documentation/translations/zh_TW/process/submit-checklist.rst <tw_submitchecklist>`
+給出在提交代碼前需要檢查的項目的列表。如果你在提交一個驅動程序,那麼
+同時閱讀一下:
+:ref:`Documentation/process/submitting-drivers.rst <submittingdrivers>`
+
+其中許多步驟描述了Git版本控制系統的默認行爲;如果您使用Git來準備補丁,
+您將發現它爲您完成的大部分機械工作,儘管您仍然需要準備和記錄一組合理的
+補丁。一般來說,使用git將使您作爲內核開發人員的生活更輕鬆。
+
+
+0) 獲取當前源碼樹
+-----------------
+
+如果您沒有一個可以使用當前內核原始碼的存儲庫,請使用git獲取一個。您將要
+從主線存儲庫開始,它可以通過以下方式獲取::
+
+        git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
+
+但是,請注意,您可能不希望直接針對主線樹進行開發。大多數子系統維護人員運
+行自己的樹,並希望看到針對這些樹準備的補丁。請參見MAINTAINERS文件中子系
+統的 **T:** 項以查找該樹,或者簡單地詢問維護者該樹是否未在其中列出。
+
+仍然可以通過tarballs下載內核版本(如下一節所述),但這是進行內核開發的
+一種困難的方式。
+
+1) "diff -up"
+-------------
+
+使用 "diff -up" 或者 "diff -uprN" 來創建補丁。
+
+所有內核的改動,都是以補丁的形式呈現的,補丁由 diff(1) 生成。創建補丁的
+時候,要確認它是以 "unified diff" 格式創建的,這種格式由 diff(1) 的 '-u'
+參數生成。而且,請使用 '-p' 參數,那樣會顯示每個改動所在的C函數,使得
+產生的補丁容易讀得多。補丁應該基於內核原始碼樹的根目錄,而不是裡邊的任
+何子目錄。
+
+爲一個單獨的文件創建補丁,一般來說這樣做就夠了::
+
+        SRCTREE=linux
+        MYFILE=drivers/net/mydriver.c
+
+        cd $SRCTREE
+        cp $MYFILE $MYFILE.orig
+        vi $MYFILE      # make your change
+        cd ..
+        diff -up $SRCTREE/$MYFILE{.orig,} > /tmp/patch
+
+爲多個文件創建補丁,你可以解開一個沒有修改過的內核原始碼樹,然後和你自
+己的代碼樹之間做 diff 。例如::
+
+        MYSRC=/devel/linux
+
+        tar xvfz linux-3.19.tar.gz
+        mv linux-3.19 linux-3.19-vanilla
+        diff -uprN -X linux-3.19-vanilla/Documentation/dontdiff \
+                linux-3.19-vanilla $MYSRC > /tmp/patch
+
+"dontdiff" 是內核在編譯的時候產生的文件的列表,列表中的文件在 diff(1)
+產生的補丁里會被跳過。
+
+確定你的補丁里沒有包含任何不屬於這次補丁提交的額外文件。記得在用diff(1)
+生成補丁之後,審閱一次補丁,以確保準確。
+
+如果你的改動很散亂,你應該研究一下如何將補丁分割成獨立的部分,將改動分
+割成一系列合乎邏輯的步驟。這樣更容易讓其他內核開發者審核,如果你想你的
+補丁被接受,這是很重要的。請參閱:
+:ref:`tw_split_changes`
+
+如果你用 ``git`` , ``git rebase -i`` 可以幫助你這一點。如果你不用 ``git``,
+``quilt`` <https://savannah.nongnu.org/projects/quilt> 另外一個流行的選擇。
+
+.. _tw_describe_changes:
+
+2) 描述你的改動
+---------------
+
+描述你的問題。無論您的補丁是一行錯誤修復還是5000行新功能,都必須有一個潛在
+的問題激勵您完成這項工作。讓審稿人相信有一個問題值得解決,讓他們讀完第一段
+是有意義的。
+
+描述用戶可見的影響。直接崩潰和鎖定是相當有說服力的,但並不是所有的錯誤都那麼
+明目張胆。即使在代碼審查期間發現了這個問題,也要描述一下您認爲它可能對用戶產
+生的影響。請記住,大多數Linux安裝運行的內核來自二級穩定樹或特定於供應商/產品
+的樹,只從上游精選特定的補丁,因此請包含任何可以幫助您將更改定位到下游的內容:
+觸發的場景、DMESG的摘錄、崩潰描述、性能回歸、延遲尖峯、鎖定等。
+
+量化優化和權衡。如果您聲稱在性能、內存消耗、堆棧占用空間或二進位大小方面有所
+改進,請包括支持它們的數字。但也要描述不明顯的成本。優化通常不是免費的,而是
+在CPU、內存和可讀性之間進行權衡;或者,探索性的工作,在不同的工作負載之間進
+行權衡。請描述優化的預期缺點,以便審閱者可以權衡成本和收益。
+
+一旦問題建立起來,就要詳細地描述一下您實際在做什麼。對於審閱者來說,用簡單的
+英語描述代碼的變化是很重要的,以驗證代碼的行爲是否符合您的意願。
+
+如果您將補丁描述寫在一個表單中,這個表單可以很容易地作爲「提交日誌」放入Linux
+的原始碼管理系統git中,那麼維護人員將非常感謝您。見 :ref:`tw_explicit_in_reply_to`.
+
+每個補丁只解決一個問題。如果你的描述開始變長,這就表明你可能需要拆分你的補丁。
+請見 :ref:`tw_split_changes`
+
+提交或重新提交修補程序或修補程序系列時,請包括完整的修補程序說明和理由。不要
+只說這是補丁(系列)的第幾版。不要期望子系統維護人員引用更早的補丁版本或引用
+URL來查找補丁描述並將其放入補丁中。也就是說,補丁(系列)及其描述應該是獨立的。
+這對維護人員和審查人員都有好處。一些評審者可能甚至沒有收到補丁的早期版本。
+
+描述你在命令語氣中的變化,例如「make xyzzy do frotz」而不是「[這個補丁]make
+xyzzy do frotz」或「[我]changed xyzzy to do frotz」,就好像你在命令代碼庫改變
+它的行爲一樣。
+
+如果修補程序修復了一個記錄的bug條目,請按編號和URL引用該bug條目。如果補丁來
+自郵件列表討論,請給出郵件列表存檔的URL;使用帶有 ``Message-ID`` 的
+https://lkml.kernel.org/ 重定向,以確保連結不會過時。
+
+但是,在沒有外部資源的情況下,儘量讓你的解釋可理解。除了提供郵件列表存檔或
+bug的URL之外,還要總結需要提交補丁的相關討論要點。
+
+如果您想要引用一個特定的提交,不要只引用提交的 SHA-1 ID。還請包括提交的一行
+摘要,以便於審閱者了解它是關於什麼的。例如::
+
+        Commit e21d2170f36602ae2708 ("video: remove unnecessary
+        platform_set_drvdata()") removed the unnecessary
+        platform_set_drvdata(), but left the variable "dev" unused,
+        delete it.
+
+您還應該確保至少使用前12位 SHA-1 ID. 內核存儲庫包含*許多*對象,使與較短的ID
+發生衝突的可能性很大。記住,即使現在不會與您的六個字符ID發生衝突,這種情況
+可能五年後改變。
+
+如果修補程序修復了特定提交中的錯誤,例如,使用 ``git bisct`` ,請使用帶有前
+12個字符SHA-1 ID 的"Fixes:"標記和單行摘要。爲了簡化不要將標記拆分爲多個,
+行、標記不受分析腳本「75列換行」規則的限制。例如::
+
+        Fixes: 54a4f0239f2e ("KVM: MMU: make kvm_mmu_zap_page() return the number of pages it actually freed")
+
+下列 ``git config`` 設置可以添加讓 ``git log``, ``git show`` 漂亮的顯示格式::
+
+	[core]
+		abbrev = 12
+	[pretty]
+		fixes = Fixes: %h (\"%s\")
+
+.. _tw_split_changes:
+
+3) 拆分你的改動
+---------------
+
+將每個邏輯更改分隔成一個單獨的補丁。
+
+例如,如果你的改動里同時有bug修正和性能優化,那麼把這些改動拆分到兩個或
+者更多的補丁文件中。如果你的改動包含對API的修改,並且修改了驅動程序來適
+應這些新的API,那麼把這些修改分成兩個補丁。
+
+另一方面,如果你將一個單獨的改動做成多個補丁文件,那麼將它們合併成一個
+單獨的補丁文件。這樣一個邏輯上單獨的改動只被包含在一個補丁文件里。
+
+如果有一個補丁依賴另外一個補丁來完成它的改動,那沒問題。簡單的在你的補
+丁描述里指出「這個補丁依賴某補丁」就好了。
+
+在將您的更改劃分爲一系列補丁時,要特別注意確保內核在系列中的每個補丁之後
+都能正常構建和運行。使用 ``git bisect`` 來追蹤問題的開發者可能會在任何時
+候分割你的補丁系列;如果你在中間引入錯誤,他們不會感謝你。
+
+如果你不能將補丁濃縮成更少的文件,那麼每次大約發送出15個,然後等待審查
+和集成。
+
+4) 檢查你的更改風格
+-------------------
+
+檢查您的補丁是否存在基本樣式衝突,詳細信息可在
+:ref:`Documentation/translations/zh_TW/process/coding-style.rst <tw_codingstyle>`
+中找到。如果不這樣做,只會浪費審稿人的時間,並且會導致你的補丁被拒絕,甚至
+可能沒有被閱讀。
+
+一個重要的例外是在將代碼從一個文件移動到另一個文件時——在這種情況下,您不應
+該在移動代碼的同一個補丁中修改移動的代碼。這清楚地描述了移動代碼和您的更改
+的行爲。這大大有助於審查實際差異,並允許工具更好地跟蹤代碼本身的歷史。
+
+在提交之前,使用補丁樣式檢查程序檢查補丁(scripts/check patch.pl)。不過,
+請注意,樣式檢查程序應該被視爲一個指南,而不是作爲人類判斷的替代品。如果您
+的代碼看起來更好,但有違規行爲,那麼最好不要使用它。
+
+檢查者報告三個級別:
+
+ - ERROR:很可能出錯的事情
+ - WARNING:需要仔細審查的事項
+ - CHECK:需要思考的事情
+
+您應該能夠判斷您的補丁中存在的所有違規行爲。
+
+5) 選擇補丁收件人
+-----------------
+
+您應該總是在任何補丁上複製相應的子系統維護人員,以獲得他們維護的代碼;查看
+維護人員文件和原始碼修訂歷史記錄,以了解這些維護人員是誰。腳本
+scripts/get_Maintainer.pl在這個步驟中非常有用。如果您找不到正在工作的子系統
+的維護人員,那麼Andrew Morton(akpm@linux-foundation.org)將充當最後的維護
+人員。
+
+您通常還應該選擇至少一個郵件列表來接收補丁集的。linux-kernel@vger.kernel.org
+作爲最後一個解決辦法的列表,但是這個列表上的體積已經引起了許多開發人員的拒絕。
+在MAINTAINERS文件中查找子系統特定的列表;您的補丁可能會在那裡得到更多的關注。
+不過,請不要發送垃圾郵件到無關的列表。
+
+許多與內核相關的列表託管在vger.kernel.org上;您可以在
+http://vger.kernel.org/vger-lists.html 上找到它們的列表。不過,也有與內核相關
+的列表託管在其他地方。
+
+不要一次發送超過15個補丁到vger郵件列表!!!!
+
+Linus Torvalds 是決定改動能否進入 Linux 內核的最終裁決者。他的 e-mail
+地址是 <torvalds@linux-foundation.org> 。他收到的 e-mail 很多,所以一般
+的說,最好別給他發 e-mail。
+
+如果您有修復可利用安全漏洞的補丁,請將該補丁發送到 security@kernel.org。對於
+嚴重的bug,可以考慮短期暫停以允許分銷商向用戶發布補丁;在這種情況下,顯然不應
+將補丁發送到任何公共列表。
+
+修復已發布內核中嚴重錯誤的補丁程序應該指向穩定版維護人員,方法是放這樣的一行::
+
+        Cc: stable@vger.kernel.org
+
+進入補丁的簽准區(注意,不是電子郵件收件人)。除了這個文件之外,您還應該閱讀
+:ref:`Documentation/process/stable-kernel-rules.rst <stable_kernel_rules>`
+
+但是,請注意,一些子系統維護人員希望得出他們自己的結論,即哪些補丁應該被放到
+穩定的樹上。尤其是網絡維護人員,不希望看到單個開發人員在補丁中添加像上面這樣
+的行。
+
+如果更改影響到用戶和內核接口,請向手冊頁維護人員(如維護人員文件中所列)發送
+手冊頁補丁,或至少發送更改通知,以便一些信息進入手冊頁。還應將用戶空間API
+更改複製到 linux-api@vger.kernel.org。
+
+對於小的補丁,你也許會CC到搜集瑣碎補丁的郵件列表(Trivial Patch Monkey)
+trivial@kernel.org,那裡專門收集瑣碎的補丁。下面這樣的補丁會被看作「瑣碎的」
+補丁:
+
+ - 文檔的拼寫修正。
+ - 修正會影響到 grep(1) 的拼寫。
+ - 警告信息修正(頻繁的列印無用的警告是不好的。)
+ - 編譯錯誤修正(代碼邏輯的確是對的,只是編譯有問題。)
+ - 運行時修正(只要真的修正了錯誤。)
+ - 移除使用了被廢棄的函數/宏的代碼(例如 check_region。)
+ - 聯繫方式和文檔修正。
+ - 用可移植的代碼替換不可移植的代碼(即使在體系結構相關的代碼中,既然有
+ - 人拷貝,只要它是瑣碎的)
+ - 任何文件的作者/維護者對該文件的改動(例如 patch monkey 在重傳模式下)
+
+(譯註,關於「瑣碎補丁」的一些說明:因爲原文的這一部分寫得比較簡單,所以不得不
+違例寫一下譯註。"trivial"這個英文單詞的本意是「瑣碎的,不重要的。」但是在這裡
+有稍微有一些變化,例如對一些明顯的NULL指針的修正,屬於運行時修正,會被歸類
+到瑣碎補丁里。雖然NULL指針的修正很重要,但是這樣的修正往往很小而且很容易得到
+檢驗,所以也被歸入瑣碎補丁。瑣碎補丁更精確的歸類應該是
+「simple, localized & easy to verify」,也就是說簡單的,局部的和易於檢驗的。
+trivial@kernel.org郵件列表的目的是針對這樣的補丁,爲提交者提供一個中心,來
+降低提交的門檻。)
+
+6) 沒有 MIME 編碼,沒有連結,沒有壓縮,沒有附件,只有純文本
+-----------------------------------------------------------
+
+Linus 和其他的內核開發者需要閱讀和評論你提交的改動。對於內核開發者來說
+,可以「引用」你的改動很重要,使用一般的 e-mail 工具,他們就可以在你的
+代碼的任何位置添加評論。
+
+因爲這個原因,所有的提交的補丁都是 e-mail 中「內嵌」的。
+
+.. warning::
+   如果你使用剪切-粘貼你的補丁,小心你的編輯器的自動換行功能破壞你的補丁
+
+不要將補丁作爲 MIME 編碼的附件,不管是否壓縮。很多流行的 e-mail 軟體不
+是任何時候都將 MIME 編碼的附件當作純文本發送的,這會使得別人無法在你的
+代碼中加評論。另外,MIME 編碼的附件會讓 Linus 多花一點時間來處理,這就
+降低了你的改動被接受的可能性。
+
+例外:如果你的郵遞員弄壞了補丁,那麼有人可能會要求你使用mime重新發送補丁
+
+請參閱 :ref:`Documentation/translations/zh_TW/process/email-clients.rst <tw_email_clients>`
+以獲取有關配置電子郵件客戶端以使其不受影響地發送修補程序的提示。
+
+7) e-mail 的大小
+----------------
+
+大的改動對郵件列表不合適,對某些維護者也不合適。如果你的補丁,在不壓縮
+的情況下,超過了300kB,那麼你最好將補丁放在一個能通過 internet 訪問的服
+務器上,然後用指向你的補丁的 URL 替代。但是請注意,如果您的補丁超過了
+300kb,那麼它幾乎肯定需要被破壞。
+
+8)回複評審意見
+---------------
+
+你的補丁幾乎肯定會得到評審者對補丁改進方法的評論。您必須對這些評論作出
+回應;讓補丁被忽略的一個好辦法就是忽略審閱者的意見。不會導致代碼更改的
+意見或問題幾乎肯定會帶來注釋或變更日誌的改變,以便下一個評審者更好地了解
+正在發生的事情。
+
+一定要告訴審稿人你在做什麼改變,並感謝他們的時間。代碼審查是一個累人且
+耗時的過程,審查人員有時會變得暴躁。即使在這種情況下,也要禮貌地回應並
+解決他們指出的問題。
+
+9)不要洩氣或不耐煩
+-------------------
+
+提交更改後,請耐心等待。審閱者是忙碌的人,可能無法立即訪問您的修補程序。
+
+曾幾何時,補丁曾在沒有評論的情況下消失在空白中,但開發過程比現在更加順利。
+您應該在一周左右的時間內收到評論;如果沒有收到評論,請確保您已將補丁發送
+到正確的位置。在重新提交或聯繫審閱者之前至少等待一周-在諸如合併窗口之類的
+繁忙時間可能更長。
+
+10)主題中包含 PATCH
+--------------------
+
+由於到linus和linux內核的電子郵件流量很高,通常會在主題行前面加上[PATCH]
+前綴. 這使Linus和其他內核開發人員更容易將補丁與其他電子郵件討論區分開。
+
+11)簽署你的作品-開發者原始認證
+-------------------------------
+
+爲了加強對誰做了何事的追蹤,尤其是對那些透過好幾層的維護者的補丁,我們
+建議在發送出去的補丁上加一個 「sign-off」 的過程。
+
+"sign-off" 是在補丁的注釋的最後的簡單的一行文字,認證你編寫了它或者其他
+人有權力將它作爲開放原始碼的補丁傳遞。規則很簡單:如果你能認證如下信息:
+
+開發者來源證書 1.1
+^^^^^^^^^^^^^^^^^^
+
+對於本項目的貢獻,我認證如下信息:
+
+      (a)這些貢獻是完全或者部分的由我創建,我有權利以文件中指出
+           的開放原始碼許可證提交它;或者
+      (b)這些貢獻基於以前的工作,據我所知,這些以前的工作受恰當的開放
+           原始碼許可證保護,而且,根據許可證,我有權提交修改後的貢獻,
+           無論是完全還是部分由我創造,這些貢獻都使用同一個開放原始碼許可證
+           (除非我被允許用其它的許可證),正如文件中指出的;或者
+      (c)這些貢獻由認證(a),(b)或者(c)的人直接提供給我,而
+           且我沒有修改它。
+      (d)我理解並同意這個項目和貢獻是公開的,貢獻的記錄(包括我
+           一起提交的個人記錄,包括 sign-off )被永久維護並且可以和這個項目
+           或者開放原始碼的許可證同步地再發行。
+
+那麼加入這樣一行::
+
+       Signed-off-by: Random J Developer <random@developer.example.org>
+
+使用你的真名(抱歉,不能使用假名或者匿名。)
+
+有人在最後加上標籤。現在這些東西會被忽略,但是你可以這樣做,來標記公司
+內部的過程,或者只是指出關於 sign-off 的一些特殊細節。
+
+如果您是子系統或分支維護人員,有時需要稍微修改收到的補丁,以便合併它們,
+因爲樹和提交者中的代碼不完全相同。如果你嚴格遵守規則(c),你應該要求提交者
+重新發布,但這完全是在浪費時間和精力。規則(b)允許您調整代碼,但是更改一個
+提交者的代碼並讓他認可您的錯誤是非常不禮貌的。要解決此問題,建議在最後一個
+由簽名行和您的行之間添加一行,指示更改的性質。雖然這並不是強制性的,但似乎
+在描述前加上您的郵件和/或姓名(全部用方括號括起來),這足以讓人注意到您對最
+後一分鐘的更改負有責任。例如::
+
+	Signed-off-by: Random J Developer <random@developer.example.org>
+	[lucky@maintainer.example.org: struct foo moved from foo.c to foo.h]
+	Signed-off-by: Lucky K Maintainer <lucky@maintainer.example.org>
+
+如果您維護一個穩定的分支機構,同時希望對作者進行致謝、跟蹤更改、合併修復並
+保護提交者不受投訴,那麼這種做法尤其有用。請注意,在任何情況下都不能更改作者
+的ID(From 頭),因爲它是出現在更改日誌中的標識。
+
+對回合(back-porters)的特別說明:在提交消息的頂部(主題行之後)插入一個補丁
+的起源指示似乎是一種常見且有用的實踐,以便於跟蹤。例如,下面是我們在3.x穩定
+版本中看到的內容::
+
+  Date:   Tue Oct 7 07:26:38 2014 -0400
+
+    libata: Un-break ATA blacklist
+
+    commit 1c40279960bcd7d52dbdf1d466b20d24b99176c8 upstream.
+
+還有, 這裡是一個舊版內核中的一個回合補丁::
+
+    Date:   Tue May 13 22:12:27 2008 +0200
+
+        wireless, airo: waitbusy() won't delay
+
+        [backport of 2.6 commit b7acbdfbd1f277c1eb23f344f899cfa4cd0bf36a]
+
+12)何時使用Acked-by:,CC:,和Co-Developed by:
+----------------------------------------------
+
+Singed-off-by: 標記表示簽名者參與了補丁的開發,或者他/她在補丁的傳遞路徑中。
+
+如果一個人沒有直接參與補丁的準備或處理,但希望表示並記錄他們對補丁的批准,
+那麼他們可以要求在補丁的變更日誌中添加一個 Acked-by:
+
+Acked-by:通常由受影響代碼的維護者使用,當該維護者既沒有貢獻也沒有轉發補丁時。
+
+Acked-by: 不像簽字人那樣正式。這是一個記錄,確認人至少審查了補丁,並表示接受。
+因此,補丁合併有時會手動將Acker的「Yep,looks good to me」轉換爲 Acked-By:(但
+請注意,通常最好要求一個明確的Ack)。
+
+Acked-by:不一定表示對整個補丁的確認。例如,如果一個補丁影響多個子系統,並且
+有一個:來自一個子系統維護者,那麼這通常表示只確認影響維護者代碼的部分。這裡
+應該仔細判斷。如有疑問,應參考郵件列表檔案中的原始討論。
+
+如果某人有機會對補丁進行評論,但沒有提供此類評論,您可以選擇在補丁中添加 ``Cc:``
+這是唯一一個標籤,它可以在沒有被它命名的人顯式操作的情況下添加,但它應該表明
+這個人是在補丁上抄送的。討論中包含了潛在利益相關方。
+
+Co-developed-by: 聲明補丁是由多個開發人員共同創建的;當幾個人在一個補丁上工
+作時,它用於將屬性賦予共同作者(除了 From: 所賦予的作者之外)。因爲
+Co-developed-by: 表示作者身份,所以每個共同開發人:必須緊跟在相關合作作者的
+簽名之後。標準的簽核程序要求:標記的簽核順序應儘可能反映補丁的時間歷史,而不
+管作者是通過 From :還是由 Co-developed-by: 共同開發的。值得注意的是,最後一
+個簽字人:必須始終是提交補丁的開發人員。
+
+注意,當作者也是電子郵件標題「發件人:」行中列出的人時,「From: 」 標記是可選的。
+
+作者提交的補丁程序示例::
+
+	<changelog>
+
+	Co-developed-by: First Co-Author <first@coauthor.example.org>
+	Signed-off-by: First Co-Author <first@coauthor.example.org>
+	Co-developed-by: Second Co-Author <second@coauthor.example.org>
+	Signed-off-by: Second Co-Author <second@coauthor.example.org>
+	Signed-off-by: From Author <from@author.example.org>
+
+合作開發者提交的補丁示例::
+
+	From: From Author <from@author.example.org>
+
+	<changelog>
+
+	Co-developed-by: Random Co-Author <random@coauthor.example.org>
+	Signed-off-by: Random Co-Author <random@coauthor.example.org>
+	Signed-off-by: From Author <from@author.example.org>
+	Co-developed-by: Submitting Co-Author <sub@coauthor.example.org>
+	Signed-off-by: Submitting Co-Author <sub@coauthor.example.org>
+
+
+13)使用報告人:、測試人:、審核人:、建議人:、修復人:
+--------------------------------------------------------
+
+Reported-by: 給那些發現錯誤並報告錯誤的人致謝,它希望激勵他們在將來再次幫助
+我們。請注意,如果bug是以私有方式報告的,那麼在使用Reported-by標記之前,請
+先請求權限。
+
+Tested-by: 標記表示補丁已由指定的人(在某些環境中)成功測試。這個標籤通知
+維護人員已經執行了一些測試,爲將來的補丁提供了一種定位測試人員的方法,並確
+保測試人員的信譽。
+
+Reviewed-by:相反,根據審查人的聲明,表明該補丁已被審查並被認爲是可接受的:
+
+
+審查人的監督聲明
+^^^^^^^^^^^^^^^^
+
+通過提供我的 Reviewed-by,我聲明:
+
+        (a) 我已經對這個補丁進行了一次技術審查,以評估它是否適合被包含到
+            主線內核中。
+
+        (b) 與補丁相關的任何問題、顧慮或問題都已反饋給提交者。我對提交者對
+            我的評論的回應感到滿意。
+
+        (c) 雖然這一提交可能會改進一些東西,但我相信,此時,(1)對內核
+            進行了有價值的修改,(2)沒有包含爭論中涉及的已知問題。
+
+        (d) 雖然我已經審查了補丁並認爲它是健全的,但我不會(除非另有明確
+            說明)作出任何保證或保證它將在任何給定情況下實現其規定的目的
+            或正常運行。
+
+Reviewed-by 是一種觀點聲明,即補丁是對內核的適當修改,沒有任何遺留的嚴重技術
+問題。任何感興趣的審閱者(完成工作的人)都可以爲一個補丁提供一個 Review-by
+標籤。此標籤用於向審閱者提供致謝,並通知維護者已在修補程序上完成的審閱程度。
+Reviewed-by: 當由已知了解主題區域並執行徹底檢查的審閱者提供時,通常會增加
+補丁進入內核的可能性。
+
+Suggested-by: 表示補丁的想法是由指定的人提出的,並確保將此想法歸功於指定的
+人。請注意,未經許可,不得添加此標籤,特別是如果該想法未在公共論壇上發布。
+這就是說,如果我們勤快地致謝我們的創意者,他們很有希望在未來得到鼓舞,再次
+幫助我們。
+
+Fixes: 指示補丁在以前的提交中修復了一個問題。它可以很容易地確定錯誤的來源,
+這有助於檢查錯誤修復。這個標記還幫助穩定內核團隊確定應該接收修復的穩定內核
+版本。這是指示補丁修復的錯誤的首選方法。請參閱 :ref:`tw_describe_changes`
+描述您的更改以了解更多詳細信息。
+
+.. _tw_the_canonical_patch_format:
+
+12)標準補丁格式
+----------------
+
+本節描述如何格式化補丁本身。請注意,如果您的補丁存儲在 ``Git`` 存儲庫中,則
+可以使用 ``git format-patch`` 進行正確的補丁格式設置。但是,這些工具無法創建
+必要的文本,因此請務必閱讀下面的說明。
+
+標準的補丁,標題行是::
+
+    Subject: [PATCH 001/123] 子系統:一句話概述
+
+標準補丁的信體存在如下部分:
+
+  - 一個 "from" 行指出補丁作者。後跟空行(僅當發送修補程序的人不是作者時才需要)。
+
+  - 解釋的正文,行以75列包裝,這將被複製到永久變更日誌來描述這個補丁。
+
+  - 一個空行
+
+  - 上面描述的「Signed-off-by」 行,也將出現在更改日誌中。
+
+  - 只包含 ``---`` 的標記線。
+
+  - 任何其他不適合放在變更日誌的注釋。
+
+  - 實際補丁( ``diff`` 輸出)。
+
+標題行的格式,使得對標題行按字母序排序非常的容易 - 很多 e-mail 客戶端都
+可以支持 - 因爲序列號是用零填充的,所以按數字排序和按字母排序是一樣的。
+
+e-mail 標題中的「子系統」標識哪個內核子系統將被打補丁。
+
+e-mail 標題中的「一句話概述」扼要的描述 e-mail 中的補丁。「一句話概述」
+不應該是一個文件名。對於一個補丁系列(「補丁系列」指一系列的多個相關補
+丁),不要對每個補丁都使用同樣的「一句話概述」。
+
+記住 e-mail 的「一句話概述」會成爲該補丁的全局唯一標識。它會蔓延到 git
+的改動記錄里。然後「一句話概述」會被用在開發者的討論里,用來指代這個補
+丁。用戶將希望通過 google 來搜索"一句話概述"來找到那些討論這個補丁的文
+章。當人們在兩三個月後使用諸如 ``gitk`` 或 ``git log --oneline`` 之類
+的工具查看數千個補丁時,也會很快看到它。
+
+出於這些原因,概述必須不超過70-75個字符,並且必須描述補丁的更改以及爲
+什麼需要補丁。既要簡潔又要描述性很有挑戰性,但寫得好的概述應該這樣做。
+
+概述的前綴可以用方括號括起來:「Subject: [PATCH <tag>...] <概述>」。標記
+不被視爲概述的一部分,而是描述應該如何處理補丁。如果補丁的多個版本已發
+送出來以響應評審(即「v1,v2,v3」)或「rfc」,以指示評審請求,那麼通用標記
+可能包括版本描述符。如果一個補丁系列中有四個補丁,那麼各個補丁可以這樣
+編號:1/4、2/4、3/4、4/4。這可以確保開發人員了解補丁應用的順序,並且他們
+已經查看或應用了補丁系列中的所有補丁。
+
+一些標題的例子::
+
+    Subject: [patch 2/5] ext2: improve scalability of bitmap searching
+    Subject: [PATCHv2 001/207] x86: fix eflags tracking
+
+"From" 行是信體裡的最上面一行,具有如下格式:
+        From: Patch Author <author@example.com>
+
+"From" 行指明在永久改動日誌里,誰會被確認爲作者。如果沒有 "From" 行,那
+麼郵件頭裡的 "From: " 行會被用來決定改動日誌中的作者。
+
+說明的主題將會被提交到永久的原始碼改動日誌里,因此對那些早已經不記得和
+這個補丁相關的討論細節的有能力的讀者來說,是有意義的。包括補丁程序定位
+錯誤的(內核日誌消息、OOPS消息等)症狀,對於搜索提交日誌以尋找適用補丁的人
+尤其有用。如果一個補丁修復了一個編譯失敗,那麼可能不需要包含所有編譯失敗;
+只要足夠讓搜索補丁的人能夠找到它就行了。與概述一樣,既要簡潔又要描述性。
+
+"---" 標記行對於補丁處理工具要找到哪裡是改動日誌信息的結束,是不可缺少
+的。
+
+對於 "---" 標記之後的額外註解,一個好的用途就是用來寫 diffstat,用來顯
+示修改了什麼文件和每個文件都增加和刪除了多少行。diffstat 對於比較大的補
+丁特別有用。其餘那些只是和時刻或者開發者相關的註解,不合適放到永久的改
+動日誌里的,也應該放這裡。
+使用 diffstat的選項 "-p 1 -w 70" 這樣文件名就會從內核原始碼樹的目錄開始
+,不會占用太寬的空間(很容易適合80列的寬度,也許會有一些縮進。)
+
+在後面的參考資料中能看到適當的補丁格式的更多細節。
+
+.. _tw_explicit_in_reply_to:
+
+15) 明確回覆郵件頭(In-Reply-To)
+-------------------------------
+
+手動添加回復補丁的的標題頭(In-Reply_To:) 是有幫助的(例如,使用 ``git send-email`` )
+將補丁與以前的相關討論關聯起來,例如,將bug修復程序連結到電子郵件和bug報告。
+但是,對於多補丁系列,最好避免在回復時使用連結到該系列的舊版本。這樣,
+補丁的多個版本就不會成爲電子郵件客戶端中無法管理的引用序列。如果連結有用,
+可以使用 https://lkml.kernel.org/ 重定向器(例如,在封面電子郵件文本中)
+連結到補丁系列的早期版本。
+
+16) 發送git pull請求
+--------------------
+
+如果您有一系列補丁,那麼讓維護人員通過git pull操作將它們直接拉入子系統存儲
+庫可能是最方便的。但是,請注意,從開發人員那裡獲取補丁比從郵件列表中獲取補
+丁需要更高的信任度。因此,許多子系統維護人員不願意接受請求,特別是來自新的
+未知開發人員的請求。如果有疑問,您可以在封面郵件中使用pull 請求作爲補丁系列
+正常發布的一個選項,讓維護人員可以選擇使用其中之一。
+
+pull 請求的主題行中應該有[Git Pull]。請求本身應該在一行中包含存儲庫名稱和
+感興趣的分支;它應該看起來像::
+
+  Please pull from
+
+      git://jdelvare.pck.nerim.net/jdelvare-2.6 i2c-for-linus
+
+  to get these changes:
+
+
+pull 請求還應該包含一條整體消息,說明請求中將包含什麼,一個補丁本身的 ``Git shortlog``
+以及一個顯示補丁系列整體效果的 ``diffstat`` 。當然,將所有這些信息收集在一起
+的最簡單方法是讓 ``git`` 使用 ``git request-pull`` 命令爲您完成這些工作。
+
+一些維護人員(包括Linus)希望看到來自已簽名提交的請求;這增加了他們對你的
+請求信心。特別是,在沒有簽名標籤的情況下,Linus 不會從像 Github 這樣的公共
+託管站點拉請求。
+
+創建此類簽名的第一步是生成一個 GNRPG 密鑰,並由一個或多個核心內核開發人員對
+其進行簽名。這一步對新開發人員來說可能很困難,但沒有辦法繞過它。參加會議是
+找到可以簽署您的密鑰的開發人員的好方法。
+
+一旦您在Git 中準備了一個您希望有人拉的補丁系列,就用 ``git tag -s`` 創建一
+個簽名標記。這將創建一個新標記,標識該系列中的最後一次提交,並包含用您的私
+鑰創建的簽名。您還可以將changelog樣式的消息添加到標記中;這是一個描述拉請求
+整體效果的理想位置。
+
+如果維護人員將要從中提取的樹不是您正在使用的存儲庫,請不要忘記將已簽名的標記
+顯式推送到公共樹。
+
+生成拉請求時,請使用已簽名的標記作爲目標。這樣的命令可以實現::
+
+  git request-pull master git://my.public.tree/linux.git my-signed-tag
+
+參考文獻
+--------
+
+Andrew Morton, "The perfect patch" (tpp).
+  <https://www.ozlabs.org/~akpm/stuff/tpp.txt>
+
+Jeff Garzik, "Linux kernel patch submission format".
+  <https://web.archive.org/web/20180829112450/http://linux.yyz.us/patch-format.html>
+
+Greg Kroah-Hartman, "How to piss off a kernel subsystem maintainer".
+  <http://www.kroah.com/log/linux/maintainer.html>
+
+  <http://www.kroah.com/log/linux/maintainer-02.html>
+
+  <http://www.kroah.com/log/linux/maintainer-03.html>
+
+  <http://www.kroah.com/log/linux/maintainer-04.html>
+
+  <http://www.kroah.com/log/linux/maintainer-05.html>
+
+  <http://www.kroah.com/log/linux/maintainer-06.html>
+
+NO!!!! No more huge patch bombs to linux-kernel@vger.kernel.org people!
+  <https://lore.kernel.org/r/20050711.125305.08322243.davem@davemloft.net>
+
+Kernel Documentation/process/coding-style.rst:
+  :ref:`Documentation/translations/zh_TW/process/coding-style.rst <tw_codingstyle>`
+
+Linus Torvalds's mail on the canonical patch format:
+  <https://lore.kernel.org/r/Pine.LNX.4.58.0504071023190.28951@ppc970.osdl.org>
+
+Andi Kleen, "On submitting kernel patches"
+  Some strategies to get difficult or controversial changes in.
+
+  http://halobates.de/on-submitting-patches.pdf
+
diff --git a/Documentation/translations/zh_TW/process/volatile-considered-harmful.rst b/Documentation/translations/zh_TW/process/volatile-considered-harmful.rst
new file mode 100644
index 000000000000..5bf923489d05
--- /dev/null
+++ b/Documentation/translations/zh_TW/process/volatile-considered-harmful.rst
@@ -0,0 +1,108 @@
+.. _tw_volatile_considered_harmful:
+
+.. include:: ../disclaimer-zh_TW.rst
+
+:Original: :ref:`Documentation/process/volatile-considered-harmful.rst
+           <volatile_considered_harmful>`
+
+如果想評論或更新本文的內容,請直接聯繫原文檔的維護者。如果你使用英文
+交流有困難的話,也可以向中文版維護者求助。如果本翻譯更新不及時或者翻
+譯存在問題,請聯繫中文版維護者::
+
+        英文版維護者: Jonathan Corbet <corbet@lwn.net>
+        中文版維護者: 伍鵬  Bryan Wu <bryan.wu@analog.com>
+        中文版翻譯者: 伍鵬  Bryan Wu <bryan.wu@analog.com>
+        中文版校譯者: 張漢輝  Eugene Teo <eugeneteo@kernel.sg>
+                       楊瑞  Dave Young <hidave.darkstar@gmail.com>
+                       時奎亮 Alex Shi <alex.shi@linux.alibaba.com>
+                       胡皓文 Hu Haowen <src.res@email.cn>
+
+爲什麼不應該使用「volatile」類型
+================================
+
+C程式設計師通常認爲volatile表示某個變量可以在當前執行的線程之外被改變;因此,在內核
+中用到共享數據結構時,常常會有C程式設計師喜歡使用volatile這類變量。換句話說,他們經
+常會把volatile類型看成某種簡易的原子變量,當然它們不是。在內核中使用volatile幾
+乎總是錯誤的;本文檔將解釋爲什麼這樣。
+
+理解volatile的關鍵是知道它的目的是用來消除優化,實際上很少有人真正需要這樣的應
+用。在內核中,程式設計師必須防止意外的並發訪問破壞共享的數據結構,這其實是一個完全
+不同的任務。用來防止意外並發訪問的保護措施,可以更加高效的避免大多數優化相關的
+問題。
+
+像volatile一樣,內核提供了很多原語來保證並發訪問時的數據安全(自旋鎖, 互斥量,內
+存屏障等等),同樣可以防止意外的優化。如果可以正確使用這些內核原語,那麼就沒有
+必要再使用volatile。如果仍然必須使用volatile,那麼幾乎可以肯定在代碼的某處有一
+個bug。在正確設計的內核代碼中,volatile能帶來的僅僅是使事情變慢。
+
+思考一下這段典型的內核代碼::
+
+    spin_lock(&the_lock);
+    do_something_on(&shared_data);
+    do_something_else_with(&shared_data);
+    spin_unlock(&the_lock);
+
+如果所有的代碼都遵循加鎖規則,當持有the_lock的時候,不可能意外的改變shared_data的
+值。任何可能訪問該數據的其他代碼都會在這個鎖上等待。自旋鎖原語跟內存屏障一樣—— 它
+們顯式的用來書寫成這樣 —— 意味著數據訪問不會跨越它們而被優化。所以本來編譯器認爲
+它知道在shared_data裡面將有什麼,但是因爲spin_lock()調用跟內存屏障一樣,會強制編
+譯器忘記它所知道的一切。那麼在訪問這些數據時不會有優化的問題。
+
+如果shared_data被聲名爲volatile,鎖操作將仍然是必須的。就算我們知道沒有其他人正在
+使用它,編譯器也將被阻止優化對臨界區內shared_data的訪問。在鎖有效的同時,
+shared_data不是volatile的。在處理共享數據的時候,適當的鎖操作可以不再需要
+volatile —— 並且是有潛在危害的。
+
+volatile的存儲類型最初是爲那些內存映射的I/O寄存器而定義。在內核里,寄存器訪問也應
+該被鎖保護,但是人們也不希望編譯器「優化」臨界區內的寄存器訪問。內核里I/O的內存訪問
+是通過訪問函數完成的;不贊成通過指針對I/O內存的直接訪問,並且不是在所有體系架構上
+都能工作。那些訪問函數正是爲了防止意外優化而寫的,因此,再說一次,volatile類型不
+是必需的。
+
+另一種引起用戶可能使用volatile的情況是當處理器正忙著等待一個變量的值。正確執行一
+個忙等待的方法是::
+
+    while (my_variable != what_i_want)
+        cpu_relax();
+
+cpu_relax()調用會降低CPU的能量消耗或者讓位於超線程雙處理器;它也作爲內存屏障一樣出
+現,所以,再一次,volatile不是必需的。當然,忙等待一開始就是一種反常規的做法。
+
+在內核中,一些稀少的情況下volatile仍然是有意義的:
+
+  - 在一些體系架構的系統上,允許直接的I/0內存訪問,那麼前面提到的訪問函數可以使用
+    volatile。基本上,每一個訪問函數調用它自己都是一個小的臨界區域並且保證了按照
+    程式設計師期望的那樣發生訪問操作。
+
+  - 某些會改變內存的內聯彙編代碼雖然沒有什麼其他明顯的附作用,但是有被GCC刪除的可
+    能性。在彙編聲明中加上volatile關鍵字可以防止這種刪除操作。
+
+  - Jiffies變量是一種特殊情況,雖然每次引用它的時候都可以有不同的值,但讀jiffies
+    變量時不需要任何特殊的加鎖保護。所以jiffies變量可以使用volatile,但是不贊成
+    其他跟jiffies相同類型變量使用volatile。Jiffies被認爲是一種「愚蠢的遺留物"
+    (Linus的話)因爲解決這個問題比保持現狀要麻煩的多。
+
+  - 由於某些I/0設備可能會修改連續一致的內存,所以有時,指向連續一致內存的數據結構
+    的指針需要正確的使用volatile。網絡適配器使用的環狀緩存區正是這類情形的一個例
+    子,其中適配器用改變指針來表示哪些描述符已經處理過了。
+
+對於大多代碼,上述幾種可以使用volatile的情況都不適用。所以,使用volatile是一種
+bug並且需要對這樣的代碼額外仔細檢查。那些試圖使用volatile的開發人員需要退一步想想
+他們真正想實現的是什麼。
+
+非常歡迎刪除volatile變量的補丁 - 只要證明這些補丁完整的考慮了並發問題。
+
+注釋
+----
+
+[1] https://lwn.net/Articles/233481/
+[2] https://lwn.net/Articles/233482/
+
+致謝
+----
+
+最初由Randy Dunlap推動並作初步研究
+由Jonathan Corbet撰寫
+參考Satyam Sharma,Johannes Stezenbach,Jesper Juhl,Heikki Orsila,
+H. Peter Anvin,Philipp Hahn和Stefan Richter的意見改善了本檔。
+
-- 
2.25.1


^ permalink raw reply related	[relevance 1%]

* Linux 3.16.85
@ 2020-06-11 18:35  1% Ben Hutchings
  0 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-11 18:35 UTC (permalink / raw)
  To: linux-kernel, Andrew Morton, torvalds, Jiri Slaby, stable; +Cc: lwn


[-- Attachment #1.1: Type: text/plain, Size: 9012 bytes --]

I'm announcing the release of the 3.16.85 kernel.  This is probably
the last release in the 3.16 stable series, unless some critical fix
comes up later this month.

All users of the 3.16 kernel series should upgrade.

The updated 3.16.y git tree can be found at:
        https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git linux-3.16.y
and can be browsed at the normal kernel.org git web browser:
        https://git.kernel.org/?p=linux/kernel/git/stable/linux-stable.git

The diff from 3.16.84 is attached to this message.

Ben.

------------

 Documentation/ABI/testing/sysfs-devices-system-cpu |   1 +
 .../special-register-buffer-data-sampling.rst      | 149 ++++
 Documentation/kernel-parameters.txt                |  20 +
 Makefile                                           |   2 +-
 arch/x86/include/asm/acpi.h                        |   2 +-
 arch/x86/include/asm/cpu_device_id.h               |  27 +
 arch/x86/include/asm/cpufeatures.h                 |   2 +
 arch/x86/include/asm/processor.h                   |   2 +-
 arch/x86/include/uapi/asm/msr-index.h              |   4 +
 arch/x86/kernel/amd_nb.c                           |   2 +-
 arch/x86/kernel/asm-offsets_32.c                   |   2 +-
 arch/x86/kernel/cpu/amd.c                          |  28 +-
 arch/x86/kernel/cpu/bugs.c                         | 106 +++
 arch/x86/kernel/cpu/centaur.c                      |   4 +-
 arch/x86/kernel/cpu/common.c                       |  62 +-
 arch/x86/kernel/cpu/cpu.h                          |   1 +
 arch/x86/kernel/cpu/cyrix.c                        |   2 +-
 arch/x86/kernel/cpu/intel.c                        |  18 +-
 arch/x86/kernel/cpu/match.c                        |   7 +-
 arch/x86/kernel/cpu/microcode/intel.c              |   4 +-
 arch/x86/kernel/cpu/mtrr/generic.c                 |   2 +-
 arch/x86/kernel/cpu/mtrr/main.c                    |   4 +-
 arch/x86/kernel/cpu/perf_event_intel.c             |   2 +-
 arch/x86/kernel/cpu/perf_event_intel_lbr.c         |   2 +-
 arch/x86/kernel/cpu/perf_event_p6.c                |   2 +-
 arch/x86/kernel/cpu/proc.c                         |   4 +-
 arch/x86/kernel/head_32.S                          |   4 +-
 arch/x86/kernel/mpparse.c                          |   2 +-
 drivers/base/cpu.c                                 |   8 +
 drivers/char/hw_random/via-rng.c                   |   2 +-
 drivers/char/random.c                              |   3 -
 drivers/cpufreq/acpi-cpufreq.c                     |   2 +-
 drivers/cpufreq/longhaul.c                         |   6 +-
 drivers/cpufreq/p4-clockmod.c                      |   2 +-
 drivers/cpufreq/powernow-k7.c                      |   2 +-
 drivers/cpufreq/speedstep-centrino.c               |   4 +-
 drivers/cpufreq/speedstep-lib.c                    |   6 +-
 drivers/crypto/padlock-aes.c                       |   2 +-
 drivers/edac/amd64_edac.c                          |   2 +-
 drivers/edac/mce_amd.c                             |   2 +-
 drivers/hwmon/coretemp.c                           |   6 +-
 drivers/hwmon/hwmon-vid.c                          |   2 +-
 drivers/hwmon/k10temp.c                            |   2 +-
 drivers/hwmon/k8temp.c                             |   2 +-
 drivers/message/fusion/mptctl.c                    | 215 ++----
 drivers/net/can/slcan.c                            |   4 +
 drivers/net/slip/slip.c                            |   4 +
 drivers/net/wireless/mwifiex/scan.c                |   7 +
 drivers/net/wireless/mwifiex/wmm.c                 |   4 +
 drivers/scsi/sg.c                                  | 758 +++++++++++----------
 drivers/usb/core/message.c                         |  53 +-
 drivers/usb/gadget/configfs.c                      |   3 +
 drivers/video/fbdev/geode/video_gx.c               |   2 +-
 fs/binfmt_elf.c                                    |   2 +-
 fs/exec.c                                          |   2 +-
 fs/ext4/block_validity.c                           |  57 ++
 fs/ext4/ext4.h                                     |  19 +-
 fs/ext4/extents.c                                  |  13 +-
 fs/ext4/inode.c                                    |   5 +
 include/linux/mod_devicetable.h                    |   6 +
 include/linux/sched.h                              |   4 +-
 include/scsi/sg.h                                  |   1 -
 kernel/signal.c                                    |   2 +-
 net/core/net-sysfs.c                               |  39 +-
 security/selinux/hooks.c                           |  70 +-
 65 files changed, 1102 insertions(+), 688 deletions(-)

Akinobu Mita (1):
      sg: prevent integer overflow when converting from sectors to bytes

Alan Stern (1):
      USB: core: Fix free-while-in-use bug in the USB S-Glibrary

Alexander Potapenko (1):
      fs/binfmt_elf.c: allocate initialized memory in fill_thread_core_info()

Ben Hutchings (3):
      scsi: sg: Change next_cmd_len handling to mirror upstream
      scsi: sg: Re-fix off by one in sg_fill_request_table()
      Linux 3.16.85

Colin Ian King (1):
      ext4: unsigned int compared against zero

Dan Carpenter (3):
      scsi: mptfusion: Add bounds check in mptctl_hp_targetinfo()
      scsi: mptfusion: Fix double fetch bug in ioctl
      scsi: sg: off by one in sg_ioctl()

David Mosberger (2):
      drivers: usb: core: Don't disable irqs in usb_sg_wait() during URB submit.
      drivers: usb: core: Minimize irq disabling in usb_sg_cancel()

Douglas Gilbert (1):
      sg: O_EXCL and other lock handling

Eric Dumazet (1):
      net-sysfs: fix netdev_queue_add_kobject() breakage

Eric W. Biederman (1):
      signal: Extend exec_id to 64bits

Hannes Reinecke (8):
      scsi: sg: protect accesses to 'reserved' page array
      scsi: sg: reset 'res_in_use' after unlinking reserved array
      scsi: sg: remove 'save_scat_len'
      scsi: sg: use standard lists for sg_requests
      scsi: sg: factor out sg_fill_request_table()
      scsi: sg: fixup infoleak when using SG_GET_REQUEST_TABLE
      scsi: sg: disable SET_FORCE_LOW_DMA
      scsi: sg: close race condition in sg_remove_sfp_usercontext()

Jason A. Donenfeld (1):
      random: always use batched entropy for get_random_u{32,64}

Jia Zhang (1):
      x86/cpu: Rename cpu_data.x86_mask to cpu_data.x86_stepping

Johannes Thumshirn (5):
      scsi: sg: check for valid direction before starting the request
      scsi: sg: fix SG_DXFER_FROM_DEV transfers
      scsi: sg: fix static checker warning in sg_is_valid_dxfer
      scsi: sg: only check for dxfer_len greater than 256M
      scsi: sg: don't return bogus Sg_requests

Josh Poimboeuf (1):
      x86/speculation: Add Ivy Bridge to affected list

Jouni Hogander (7):
      slcan: Fix memory leak in error path
      can: slcan: Fix use-after-free Read in slcan_open
      slip: Fix memory leak in slip_open error path
      slip: Fix use-after-free Read in slip_open
      net-sysfs: Fix reference count leak in rx|netdev_queue_add_kobject
      net-sysfs: Call dev_hold always in netdev_queue_add_kobject
      net-sysfs: Call dev_hold always in rx_queue_add_kobject

Kyungtae Kim (1):
      USB: gadget: fix illegal array access in binding with UDC

Li Bin (1):
      scsi: sg: add sg_remove_request in sg_common_write

Marek Milkovic (1):
      selinux: Print 'sclass' as string when unrecognized netlink message occurs

Mark Gross (4):
      x86/cpu: Add a steppings field to struct x86_cpu_id
      x86/cpu: Add 'table' argument to cpu_matches()
      x86/speculation: Add Special Register Buffer Data Sampling (SRBDS) mitigation
      x86/speculation: Add SRBDS vulnerability and mitigation documentation

Oliver Hartkopp (1):
      slcan: not call free_netdev before rtnl_unlock in slcan_open

Paul Moore (1):
      selinux: properly handle multiple messages in selinux_netlink_send()

Qing Xu (2):
      mwifiex: Fix possible buffer overflows in mwifiex_cmd_append_vsie_tlv()
      mwifiex: Fix possible buffer overflows in mwifiex_ret_wmm_get_status()

Richard Guy Briggs (2):
      selinux: cleanup error reporting in selinux_nlmsg_perm()
      selinux: convert WARN_ONCE() to printk() in selinux_nlmsg_perm()

Shijie Luo (1):
      ext4: add cond_resched() to ext4_protect_reserved_inode

Tahsin Erdogan (1):
      ext4: Make checks for metadata_csum feature safer

Theodore Ts'o (3):
      ext4: protect journal inode's blocks using block_validity
      ext4: fix block validity checks for journal inodes using indirect blocks
      ext4: don't perform block validity checks on the journal inode

Todd Poynor (2):
      scsi: sg: protect against races between mmap() and SG_SET_RESERVED_SIZE
      scsi: sg: recheck MMAP_IO request length with lock held

Tony Battersby (1):
      scsi: sg: fix minor memory leak in error path

Vladis Dronov (1):
      selinux: rate-limit netlink message warnings in selinux_nlmsg_perm()

Wu Bo (1):
      scsi: sg: add sg_remove_request in sg_write

yangerkun (1):
      slip: not call free_netdev before rtnl_unlock in slip_open


[-- Attachment #1.2: linux-3.16.85.patch --]
[-- Type: text/x-diff, Size: 139671 bytes --]

diff --git a/Documentation/ABI/testing/sysfs-devices-system-cpu b/Documentation/ABI/testing/sysfs-devices-system-cpu
index 2fdfbf6337e7..19251577179b 100644
--- a/Documentation/ABI/testing/sysfs-devices-system-cpu
+++ b/Documentation/ABI/testing/sysfs-devices-system-cpu
@@ -232,6 +232,7 @@ What:		/sys/devices/system/cpu/vulnerabilities
 		/sys/devices/system/cpu/vulnerabilities/spec_store_bypass
 		/sys/devices/system/cpu/vulnerabilities/l1tf
 		/sys/devices/system/cpu/vulnerabilities/mds
+		/sys/devices/system/cpu/vulnerabilities/srbds
 		/sys/devices/system/cpu/vulnerabilities/tsx_async_abort
 		/sys/devices/system/cpu/vulnerabilities/itlb_multihit
 Date:		January 2018
diff --git a/Documentation/hw-vuln/special-register-buffer-data-sampling.rst b/Documentation/hw-vuln/special-register-buffer-data-sampling.rst
new file mode 100644
index 000000000000..47b1b3afac99
--- /dev/null
+++ b/Documentation/hw-vuln/special-register-buffer-data-sampling.rst
@@ -0,0 +1,149 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+SRBDS - Special Register Buffer Data Sampling
+=============================================
+
+SRBDS is a hardware vulnerability that allows MDS :doc:`mds` techniques to
+infer values returned from special register accesses.  Special register
+accesses are accesses to off core registers.  According to Intel's evaluation,
+the special register reads that have a security expectation of privacy are
+RDRAND, RDSEED and SGX EGETKEY.
+
+When RDRAND, RDSEED and EGETKEY instructions are used, the data is moved
+to the core through the special register mechanism that is susceptible
+to MDS attacks.
+
+Affected processors
+--------------------
+Core models (desktop, mobile, Xeon-E3) that implement RDRAND and/or RDSEED may
+be affected.
+
+A processor is affected by SRBDS if its Family_Model and stepping is
+in the following list, with the exception of the listed processors
+exporting MDS_NO while Intel TSX is available yet not enabled. The
+latter class of processors are only affected when Intel TSX is enabled
+by software using TSX_CTRL_MSR otherwise they are not affected.
+
+  =============  ============  ========
+  common name    Family_Model  Stepping
+  =============  ============  ========
+  IvyBridge      06_3AH        All
+
+  Haswell        06_3CH        All
+  Haswell_L      06_45H        All
+  Haswell_G      06_46H        All
+
+  Broadwell_G    06_47H        All
+  Broadwell      06_3DH        All
+
+  Skylake_L      06_4EH        All
+  Skylake        06_5EH        All
+
+  Kabylake_L     06_8EH        <= 0xC
+  Kabylake       06_9EH        <= 0xD
+  =============  ============  ========
+
+Related CVEs
+------------
+
+The following CVE entry is related to this SRBDS issue:
+
+    ==============  =====  =====================================
+    CVE-2020-0543   SRBDS  Special Register Buffer Data Sampling
+    ==============  =====  =====================================
+
+Attack scenarios
+----------------
+An unprivileged user can extract values returned from RDRAND and RDSEED
+executed on another core or sibling thread using MDS techniques.
+
+
+Mitigation mechanism
+-------------------
+Intel will release microcode updates that modify the RDRAND, RDSEED, and
+EGETKEY instructions to overwrite secret special register data in the shared
+staging buffer before the secret data can be accessed by another logical
+processor.
+
+During execution of the RDRAND, RDSEED, or EGETKEY instructions, off-core
+accesses from other logical processors will be delayed until the special
+register read is complete and the secret data in the shared staging buffer is
+overwritten.
+
+This has three effects on performance:
+
+#. RDRAND, RDSEED, or EGETKEY instructions have higher latency.
+
+#. Executing RDRAND at the same time on multiple logical processors will be
+   serialized, resulting in an overall reduction in the maximum RDRAND
+   bandwidth.
+
+#. Executing RDRAND, RDSEED or EGETKEY will delay memory accesses from other
+   logical processors that miss their core caches, with an impact similar to
+   legacy locked cache-line-split accesses.
+
+The microcode updates provide an opt-out mechanism (RNGDS_MITG_DIS) to disable
+the mitigation for RDRAND and RDSEED instructions executed outside of Intel
+Software Guard Extensions (Intel SGX) enclaves. On logical processors that
+disable the mitigation using this opt-out mechanism, RDRAND and RDSEED do not
+take longer to execute and do not impact performance of sibling logical
+processors memory accesses. The opt-out mechanism does not affect Intel SGX
+enclaves (including execution of RDRAND or RDSEED inside an enclave, as well
+as EGETKEY execution).
+
+IA32_MCU_OPT_CTRL MSR Definition
+--------------------------------
+Along with the mitigation for this issue, Intel added a new thread-scope
+IA32_MCU_OPT_CTRL MSR, (address 0x123). The presence of this MSR and
+RNGDS_MITG_DIS (bit 0) is enumerated by CPUID.(EAX=07H,ECX=0).EDX[SRBDS_CTRL =
+9]==1. This MSR is introduced through the microcode update.
+
+Setting IA32_MCU_OPT_CTRL[0] (RNGDS_MITG_DIS) to 1 for a logical processor
+disables the mitigation for RDRAND and RDSEED executed outside of an Intel SGX
+enclave on that logical processor. Opting out of the mitigation for a
+particular logical processor does not affect the RDRAND and RDSEED mitigations
+for other logical processors.
+
+Note that inside of an Intel SGX enclave, the mitigation is applied regardless
+of the value of RNGDS_MITG_DS.
+
+Mitigation control on the kernel command line
+---------------------------------------------
+The kernel command line allows control over the SRBDS mitigation at boot time
+with the option "srbds=".  The option for this is:
+
+  ============= =============================================================
+  off           This option disables SRBDS mitigation for RDRAND and RDSEED on
+                affected platforms.
+  ============= =============================================================
+
+SRBDS System Information
+-----------------------
+The Linux kernel provides vulnerability status information through sysfs.  For
+SRBDS this can be accessed by the following sysfs file:
+/sys/devices/system/cpu/vulnerabilities/srbds
+
+The possible values contained in this file are:
+
+ ============================== =============================================
+ Not affected                   Processor not vulnerable
+ Vulnerable                     Processor vulnerable and mitigation disabled
+ Vulnerable: No microcode       Processor vulnerable and microcode is missing
+                                mitigation
+ Mitigation: Microcode          Processor is vulnerable and mitigation is in
+                                effect.
+ Mitigation: TSX disabled       Processor is only vulnerable when TSX is
+                                enabled while this system was booted with TSX
+                                disabled.
+ Unknown: Dependent on
+ hypervisor status              Running on virtual guest processor that is
+                                affected but with no way to know if host
+                                processor is mitigated or vulnerable.
+ ============================== =============================================
+
+SRBDS Default mitigation
+------------------------
+This new microcode serializes processor access during execution of RDRAND,
+RDSEED ensures that the shared buffer is overwritten before it is released for
+reuse.  Use the "srbds=off" kernel command line to disable the mitigation for
+RDRAND and RDSEED.
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 01eb7cab0419..b12d696ba116 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -3356,6 +3356,26 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 	spia_pedr=
 	spia_peddr=
 
+	srbds=		[X86,INTEL]
+			Control the Special Register Buffer Data Sampling
+			(SRBDS) mitigation.
+
+			Certain CPUs are vulnerable to an MDS-like
+			exploit which can leak bits from the random
+			number generator.
+
+			By default, this issue is mitigated by
+			microcode.  However, the microcode fix can cause
+			the RDRAND and RDSEED instructions to become
+			much slower.  Among other effects, this will
+			result in reduced throughput from /dev/urandom.
+
+			The microcode mitigation can be disabled with
+			the following option:
+
+			off:    Disable mitigation and remove
+				performance impact to RDRAND and RDSEED
+
 	stack_guard_gap=	[MM]
 			override the default stack gap protection. The value
 			is in page units and it defines how many pages prior
diff --git a/Makefile b/Makefile
index e1c91ead7918..ed944e74529c 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 3
 PATCHLEVEL = 16
-SUBLEVEL = 84
+SUBLEVEL = 85
 EXTRAVERSION =
 NAME = Museum of Fishiegoodies
 
diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h
index e06225eda635..28a11324052f 100644
--- a/arch/x86/include/asm/acpi.h
+++ b/arch/x86/include/asm/acpi.h
@@ -87,7 +87,7 @@ static inline unsigned int acpi_processor_cstate_check(unsigned int max_cstate)
 	if (boot_cpu_data.x86 == 0x0F &&
 	    boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
 	    boot_cpu_data.x86_model <= 0x05 &&
-	    boot_cpu_data.x86_mask < 0x0A)
+	    boot_cpu_data.x86_stepping < 0x0A)
 		return 1;
 	else if (amd_e400_c1e_detected)
 		return 1;
diff --git a/arch/x86/include/asm/cpu_device_id.h b/arch/x86/include/asm/cpu_device_id.h
index ff501e511d91..b9473858c6b6 100644
--- a/arch/x86/include/asm/cpu_device_id.h
+++ b/arch/x86/include/asm/cpu_device_id.h
@@ -8,6 +8,33 @@
 
 #include <linux/mod_devicetable.h>
 
+#define X86_STEPPINGS(mins, maxs)    GENMASK(maxs, mins)
+
+/**
+ * X86_MATCH_VENDOR_FAM_MODEL_STEPPINGS_FEATURE - Base macro for CPU matching
+ * @_vendor:	The vendor name, e.g. INTEL, AMD, HYGON, ..., ANY
+ *		The name is expanded to X86_VENDOR_@_vendor
+ * @_family:	The family number or X86_FAMILY_ANY
+ * @_model:	The model number, model constant or X86_MODEL_ANY
+ * @_steppings:	Bitmask for steppings, stepping constant or X86_STEPPING_ANY
+ * @_feature:	A X86_FEATURE bit or X86_FEATURE_ANY
+ * @_data:	Driver specific data or NULL. The internal storage
+ *		format is unsigned long. The supplied value, pointer
+ *		etc. is casted to unsigned long internally.
+ *
+ * Backport version to keep the SRBDS pile consistant. No shorter variants
+ * required for this.
+ */
+#define X86_MATCH_VENDOR_FAM_MODEL_STEPPINGS_FEATURE(_vendor, _family, _model, \
+						    _steppings, _feature, _data) { \
+	.vendor		= X86_VENDOR_##_vendor,				\
+	.family		= _family,					\
+	.model		= _model,					\
+	.steppings	= _steppings,					\
+	.feature	= _feature,					\
+	.driver_data	= (unsigned long) _data				\
+}
+
 extern const struct x86_cpu_id *x86_match_cpu(const struct x86_cpu_id *match);
 
 #endif
diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
index 4ad4e3bfee4e..47aed45d0514 100644
--- a/arch/x86/include/asm/cpufeatures.h
+++ b/arch/x86/include/asm/cpufeatures.h
@@ -247,6 +247,7 @@
 #define X86_FEATURE_AVX512CD	( 9*32+28) /* AVX-512 Conflict Detection */
 
 /* Intel-defined CPU features, CPUID level 0x00000007:0 (EDX), word 10 */
+#define X86_FEATURE_SRBDS_CTRL		(10*32+ 9) /* "" SRBDS mitigation MSR available */
 #define X86_FEATURE_MD_CLEAR		(10*32+10) /* VERW clears CPU buffers */
 #define X86_FEATURE_SPEC_CTRL		(10*32+26) /* "" Speculation Control (IBRS + IBPB) */
 #define X86_FEATURE_INTEL_STIBP		(10*32+27) /* "" Single Thread Indirect Branch Predictors */
@@ -281,5 +282,6 @@
 #define X86_BUG_SWAPGS		X86_BUG(12) /* CPU is affected by speculation through SWAPGS */
 #define X86_BUG_TAA		X86_BUG(13) /* CPU is affected by TSX Async Abort(TAA) */
 #define X86_BUG_ITLB_MULTIHIT	X86_BUG(14) /* CPU may incur MCE during certain page attribute changes */
+#define X86_BUG_SRBDS		X86_BUG(15) /* CPU may leak RNG bits if not mitigated */
 
 #endif /* _ASM_X86_CPUFEATURES_H */
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 9ea2413fc16d..0cd633ecef64 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -82,7 +82,7 @@ struct cpuinfo_x86 {
 	__u8			x86;		/* CPU family */
 	__u8			x86_vendor;	/* CPU vendor */
 	__u8			x86_model;
-	__u8			x86_mask;
+	__u8			x86_stepping;
 #ifdef CONFIG_X86_32
 	char			wp_works_ok;	/* It doesn't on 386's */
 
diff --git a/arch/x86/include/uapi/asm/msr-index.h b/arch/x86/include/uapi/asm/msr-index.h
index e376e780e380..a22e63c5abb6 100644
--- a/arch/x86/include/uapi/asm/msr-index.h
+++ b/arch/x86/include/uapi/asm/msr-index.h
@@ -90,6 +90,10 @@
 #define TSX_CTRL_RTM_DISABLE		(1UL << 0) /* Disable RTM feature */
 #define TSX_CTRL_CPUID_CLEAR		(1UL << 1) /* Disable TSX enumeration */
 
+/* SRBDS support */
+#define MSR_IA32_MCU_OPT_CTRL		0x00000123
+#define RNGDS_MITG_DIS			BIT(0)
+
 #define MSR_IA32_SYSENTER_CS		0x00000174
 #define MSR_IA32_SYSENTER_ESP		0x00000175
 #define MSR_IA32_SYSENTER_EIP		0x00000176
diff --git a/arch/x86/kernel/amd_nb.c b/arch/x86/kernel/amd_nb.c
index 3c9d268939af..3a7e04cad598 100644
--- a/arch/x86/kernel/amd_nb.c
+++ b/arch/x86/kernel/amd_nb.c
@@ -116,7 +116,7 @@ int amd_cache_northbridges(void)
 	if (boot_cpu_data.x86 == 0x10 &&
 	    boot_cpu_data.x86_model >= 0x8 &&
 	    (boot_cpu_data.x86_model > 0x9 ||
-	     boot_cpu_data.x86_mask >= 0x1))
+	     boot_cpu_data.x86_stepping >= 0x1))
 		amd_northbridges.flags |= AMD_NB_L3_INDEX_DISABLE;
 
 	if (boot_cpu_data.x86 == 0x15)
diff --git a/arch/x86/kernel/asm-offsets_32.c b/arch/x86/kernel/asm-offsets_32.c
index d67c4be3e8b1..45768892add5 100644
--- a/arch/x86/kernel/asm-offsets_32.c
+++ b/arch/x86/kernel/asm-offsets_32.c
@@ -27,7 +27,7 @@ void foo(void)
 	OFFSET(CPUINFO_x86, cpuinfo_x86, x86);
 	OFFSET(CPUINFO_x86_vendor, cpuinfo_x86, x86_vendor);
 	OFFSET(CPUINFO_x86_model, cpuinfo_x86, x86_model);
-	OFFSET(CPUINFO_x86_mask, cpuinfo_x86, x86_mask);
+	OFFSET(CPUINFO_x86_stepping, cpuinfo_x86, x86_stepping);
 	OFFSET(CPUINFO_cpuid_level, cpuinfo_x86, cpuid_level);
 	OFFSET(CPUINFO_x86_capability, cpuinfo_x86, x86_capability);
 	OFFSET(CPUINFO_x86_vendor_id, cpuinfo_x86, x86_vendor_id);
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index ccfb36b455a4..878dc10b7db3 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -101,7 +101,7 @@ static void init_amd_k6(struct cpuinfo_x86 *c)
 		return;
 	}
 
-	if (c->x86_model == 6 && c->x86_mask == 1) {
+	if (c->x86_model == 6 && c->x86_stepping == 1) {
 		const int K6_BUG_LOOP = 1000000;
 		int n;
 		void (*f_vide)(void);
@@ -131,7 +131,7 @@ static void init_amd_k6(struct cpuinfo_x86 *c)
 
 	/* K6 with old style WHCR */
 	if (c->x86_model < 8 ||
-	   (c->x86_model == 8 && c->x86_mask < 8)) {
+	   (c->x86_model == 8 && c->x86_stepping < 8)) {
 		/* We can only write allocate on the low 508Mb */
 		if (mbytes > 508)
 			mbytes = 508;
@@ -150,7 +150,7 @@ static void init_amd_k6(struct cpuinfo_x86 *c)
 		return;
 	}
 
-	if ((c->x86_model == 8 && c->x86_mask > 7) ||
+	if ((c->x86_model == 8 && c->x86_stepping > 7) ||
 	     c->x86_model == 9 || c->x86_model == 13) {
 		/* The more serious chips .. */
 
@@ -190,12 +190,12 @@ static void amd_k7_smp_check(struct cpuinfo_x86 *c)
 	 * but they are not certified as MP capable.
 	 */
 	/* Athlon 660/661 is valid. */
-	if ((c->x86_model == 6) && ((c->x86_mask == 0) ||
-	    (c->x86_mask == 1)))
+	if ((c->x86_model == 6) && ((c->x86_stepping == 0) ||
+	    (c->x86_stepping == 1)))
 		return;
 
 	/* Duron 670 is valid */
-	if ((c->x86_model == 7) && (c->x86_mask == 0))
+	if ((c->x86_model == 7) && (c->x86_stepping == 0))
 		return;
 
 	/*
@@ -205,8 +205,8 @@ static void amd_k7_smp_check(struct cpuinfo_x86 *c)
 	 * See http://www.heise.de/newsticker/data/jow-18.10.01-000 for
 	 * more.
 	 */
-	if (((c->x86_model == 6) && (c->x86_mask >= 2)) ||
-	    ((c->x86_model == 7) && (c->x86_mask >= 1)) ||
+	if (((c->x86_model == 6) && (c->x86_stepping >= 2)) ||
+	    ((c->x86_model == 7) && (c->x86_stepping >= 1)) ||
 	     (c->x86_model > 7))
 		if (cpu_has_mp)
 			return;
@@ -244,7 +244,7 @@ static void init_amd_k7(struct cpuinfo_x86 *c)
 	 * are more robust with CLK_CTL set to 200xxxxx instead of 600xxxxx
 	 * As per AMD technical note 27212 0.2
 	 */
-	if ((c->x86_model == 8 && c->x86_mask >= 1) || (c->x86_model > 8)) {
+	if ((c->x86_model == 8 && c->x86_stepping >= 1) || (c->x86_model > 8)) {
 		rdmsr(MSR_K7_CLK_CTL, l, h);
 		if ((l & 0xfff00000) != 0x20000000) {
 			printk(KERN_INFO
@@ -514,7 +514,7 @@ static void early_init_amd(struct cpuinfo_x86 *c)
 	/*  Set MTRR capability flag if appropriate */
 	if (c->x86 == 5)
 		if (c->x86_model == 13 || c->x86_model == 9 ||
-		    (c->x86_model == 8 && c->x86_mask >= 8))
+		    (c->x86_model == 8 && c->x86_stepping >= 8))
 			set_cpu_cap(c, X86_FEATURE_K6_MTRR);
 #endif
 #if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_PCI)
@@ -561,7 +561,7 @@ static void init_amd_zn(struct cpuinfo_x86 *c)
 	 * Fix erratum 1076: CPB feature bit not being set in CPUID. It affects
 	 * all up to and including B1.
 	 */
-	if (c->x86_model <= 1 && c->x86_mask <= 1)
+	if (c->x86_model <= 1 && c->x86_stepping <= 1)
 		set_cpu_cap(c, X86_FEATURE_CPB);
 }
 
@@ -810,11 +810,11 @@ static unsigned int amd_size_cache(struct cpuinfo_x86 *c, unsigned int size)
 	/* AMD errata T13 (order #21922) */
 	if ((c->x86 == 6)) {
 		/* Duron Rev A0 */
-		if (c->x86_model == 3 && c->x86_mask == 0)
+		if (c->x86_model == 3 && c->x86_stepping == 0)
 			size = 64;
 		/* Tbird rev A1/A2 */
 		if (c->x86_model == 4 &&
-			(c->x86_mask == 0 || c->x86_mask == 1))
+			(c->x86_stepping == 0 || c->x86_stepping == 1))
 			size = 256;
 	}
 	return size;
@@ -951,7 +951,7 @@ static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum)
 	}
 
 	/* OSVW unavailable or ID unknown, match family-model-stepping range */
-	ms = (cpu->x86_model << 4) | cpu->x86_mask;
+	ms = (cpu->x86_model << 4) | cpu->x86_stepping;
 	while ((range = *erratum++))
 		if ((cpu->x86 == AMD_MODEL_RANGE_FAMILY(range)) &&
 		    (ms >= AMD_MODEL_RANGE_START(range)) &&
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index 9739e4436e79..f1367b95b8d3 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -38,6 +38,7 @@ static void __init ssb_select_mitigation(void);
 static void __init l1tf_select_mitigation(void);
 static void __init mds_select_mitigation(void);
 static void __init taa_select_mitigation(void);
+static void __init srbds_select_mitigation(void);
 
 /* The base value of the SPEC_CTRL MSR that always has to be preserved. */
 u64 x86_spec_ctrl_base;
@@ -159,6 +160,7 @@ void __init check_bugs(void)
 	l1tf_select_mitigation();
 	mds_select_mitigation();
 	taa_select_mitigation();
+	srbds_select_mitigation();
 
 	arch_smt_update();
 
@@ -416,6 +418,97 @@ static int __init tsx_async_abort_parse_cmdline(char *str)
 }
 early_param("tsx_async_abort", tsx_async_abort_parse_cmdline);
 
+#undef pr_fmt
+#define pr_fmt(fmt)	"SRBDS: " fmt
+
+enum srbds_mitigations {
+	SRBDS_MITIGATION_OFF,
+	SRBDS_MITIGATION_UCODE_NEEDED,
+	SRBDS_MITIGATION_FULL,
+	SRBDS_MITIGATION_TSX_OFF,
+	SRBDS_MITIGATION_HYPERVISOR,
+};
+
+static enum srbds_mitigations srbds_mitigation = SRBDS_MITIGATION_FULL;
+
+static const char * const srbds_strings[] = {
+	[SRBDS_MITIGATION_OFF]		= "Vulnerable",
+	[SRBDS_MITIGATION_UCODE_NEEDED]	= "Vulnerable: No microcode",
+	[SRBDS_MITIGATION_FULL]		= "Mitigation: Microcode",
+	[SRBDS_MITIGATION_TSX_OFF]	= "Mitigation: TSX disabled",
+	[SRBDS_MITIGATION_HYPERVISOR]	= "Unknown: Dependent on hypervisor status",
+};
+
+static bool srbds_off;
+
+void update_srbds_msr(void)
+{
+	u64 mcu_ctrl;
+
+	if (!boot_cpu_has_bug(X86_BUG_SRBDS))
+		return;
+
+	if (boot_cpu_has(X86_FEATURE_HYPERVISOR))
+		return;
+
+	if (srbds_mitigation == SRBDS_MITIGATION_UCODE_NEEDED)
+		return;
+
+	rdmsrl(MSR_IA32_MCU_OPT_CTRL, mcu_ctrl);
+
+	switch (srbds_mitigation) {
+	case SRBDS_MITIGATION_OFF:
+	case SRBDS_MITIGATION_TSX_OFF:
+		mcu_ctrl |= RNGDS_MITG_DIS;
+		break;
+	case SRBDS_MITIGATION_FULL:
+		mcu_ctrl &= ~RNGDS_MITG_DIS;
+		break;
+	default:
+		break;
+	}
+
+	wrmsrl(MSR_IA32_MCU_OPT_CTRL, mcu_ctrl);
+}
+
+static void __init srbds_select_mitigation(void)
+{
+	u64 ia32_cap;
+
+	if (!boot_cpu_has_bug(X86_BUG_SRBDS))
+		return;
+
+	/*
+	 * Check to see if this is one of the MDS_NO systems supporting
+	 * TSX that are only exposed to SRBDS when TSX is enabled.
+	 */
+	ia32_cap = x86_read_arch_cap_msr();
+	if ((ia32_cap & ARCH_CAP_MDS_NO) && !boot_cpu_has(X86_FEATURE_RTM))
+		srbds_mitigation = SRBDS_MITIGATION_TSX_OFF;
+	else if (boot_cpu_has(X86_FEATURE_HYPERVISOR))
+		srbds_mitigation = SRBDS_MITIGATION_HYPERVISOR;
+	else if (!boot_cpu_has(X86_FEATURE_SRBDS_CTRL))
+		srbds_mitigation = SRBDS_MITIGATION_UCODE_NEEDED;
+	else if (cpu_mitigations_off() || srbds_off)
+		srbds_mitigation = SRBDS_MITIGATION_OFF;
+
+	update_srbds_msr();
+	pr_info("%s\n", srbds_strings[srbds_mitigation]);
+}
+
+static int __init srbds_parse_cmdline(char *str)
+{
+	if (!str)
+		return -EINVAL;
+
+	if (!boot_cpu_has_bug(X86_BUG_SRBDS))
+		return 0;
+
+	srbds_off = !strcmp(str, "off");
+	return 0;
+}
+early_param("srbds", srbds_parse_cmdline);
+
 #undef pr_fmt
 #define pr_fmt(fmt)     "Spectre V1 : " fmt
 
@@ -1422,6 +1515,11 @@ static char *ibpb_state(void)
 	return "";
 }
 
+static ssize_t srbds_show_state(char *buf)
+{
+	return sprintf(buf, "%s\n", srbds_strings[srbds_mitigation]);
+}
+
 static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr,
 			       char *buf, unsigned int bug)
 {
@@ -1463,6 +1561,9 @@ static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr
 	case X86_BUG_ITLB_MULTIHIT:
 		return itlb_multihit_show_state(buf);
 
+	case X86_BUG_SRBDS:
+		return srbds_show_state(buf);
+
 	default:
 		break;
 	}
@@ -1509,4 +1610,9 @@ ssize_t cpu_show_itlb_multihit(struct device *dev, struct device_attribute *attr
 {
 	return cpu_show_common(dev, attr, buf, X86_BUG_ITLB_MULTIHIT);
 }
+
+ssize_t cpu_show_srbds(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	return cpu_show_common(dev, attr, buf, X86_BUG_SRBDS);
+}
 #endif
diff --git a/arch/x86/kernel/cpu/centaur.c b/arch/x86/kernel/cpu/centaur.c
index 5468a6067588..4ff55c676a13 100644
--- a/arch/x86/kernel/cpu/centaur.c
+++ b/arch/x86/kernel/cpu/centaur.c
@@ -134,7 +134,7 @@ static void init_centaur(struct cpuinfo_x86 *c)
 			clear_cpu_cap(c, X86_FEATURE_TSC);
 			break;
 		case 8:
-			switch (c->x86_mask) {
+			switch (c->x86_stepping) {
 			default:
 			name = "2";
 				break;
@@ -209,7 +209,7 @@ centaur_size_cache(struct cpuinfo_x86 *c, unsigned int size)
 	 *  - Note, it seems this may only be in engineering samples.
 	 */
 	if ((c->x86 == 6) && (c->x86_model == 9) &&
-				(c->x86_mask == 1) && (size == 65))
+				(c->x86_stepping == 1) && (size == 65))
 		size -= 1;
 	return size;
 }
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index e6d410f83bab..95f06271fdec 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -659,7 +659,7 @@ void cpu_detect(struct cpuinfo_x86 *c)
 		cpuid(0x00000001, &tfms, &misc, &junk, &cap0);
 		c->x86 = (tfms >> 8) & 0xf;
 		c->x86_model = (tfms >> 4) & 0xf;
-		c->x86_mask = tfms & 0xf;
+		c->x86_stepping = tfms & 0xf;
 
 		if (c->x86 == 0xf)
 			c->x86 += (tfms >> 20) & 0xff;
@@ -872,9 +872,30 @@ static const __initconst struct x86_cpu_id cpu_vuln_whitelist[] = {
 	{}
 };
 
-static bool __init cpu_matches(unsigned long which)
+#define VULNBL_INTEL_STEPPINGS(model, steppings, issues)		   \
+	X86_MATCH_VENDOR_FAM_MODEL_STEPPINGS_FEATURE(INTEL, 6,		   \
+					    INTEL_FAM6_##model, steppings, \
+					    X86_FEATURE_ANY, issues)
+
+#define SRBDS		BIT(0)
+
+static const struct x86_cpu_id cpu_vuln_blacklist[] __initconst = {
+	VULNBL_INTEL_STEPPINGS(IVYBRIDGE,	X86_STEPPING_ANY,		SRBDS),
+	VULNBL_INTEL_STEPPINGS(HASWELL_CORE,	X86_STEPPING_ANY,		SRBDS),
+	VULNBL_INTEL_STEPPINGS(HASWELL_ULT,	X86_STEPPING_ANY,		SRBDS),
+	VULNBL_INTEL_STEPPINGS(HASWELL_GT3E,	X86_STEPPING_ANY,		SRBDS),
+	VULNBL_INTEL_STEPPINGS(BROADWELL_GT3E,	X86_STEPPING_ANY,		SRBDS),
+	VULNBL_INTEL_STEPPINGS(BROADWELL_CORE,	X86_STEPPING_ANY,		SRBDS),
+	VULNBL_INTEL_STEPPINGS(SKYLAKE_MOBILE,	X86_STEPPING_ANY,		SRBDS),
+	VULNBL_INTEL_STEPPINGS(SKYLAKE_DESKTOP,	X86_STEPPING_ANY,		SRBDS),
+	VULNBL_INTEL_STEPPINGS(KABYLAKE_MOBILE,	X86_STEPPINGS(0x0, 0xC),	SRBDS),
+	VULNBL_INTEL_STEPPINGS(KABYLAKE_DESKTOP,X86_STEPPINGS(0x0, 0xD),	SRBDS),
+	{}
+};
+
+static bool __init cpu_matches(const struct x86_cpu_id *table, unsigned long which)
 {
-	const struct x86_cpu_id *m = x86_match_cpu(cpu_vuln_whitelist);
+	const struct x86_cpu_id *m = x86_match_cpu(table);
 
 	return m && !!(m->driver_data & which);
 }
@@ -894,29 +915,32 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
 	u64 ia32_cap = x86_read_arch_cap_msr();
 
 	/* Set ITLB_MULTIHIT bug if cpu is not in the whitelist and not mitigated */
-	if (!cpu_matches(NO_ITLB_MULTIHIT) && !(ia32_cap & ARCH_CAP_PSCHANGE_MC_NO))
+	if (!cpu_matches(cpu_vuln_whitelist, NO_ITLB_MULTIHIT) &&
+	    !(ia32_cap & ARCH_CAP_PSCHANGE_MC_NO))
 		setup_force_cpu_bug(X86_BUG_ITLB_MULTIHIT);
 
-	if (cpu_matches(NO_SPECULATION))
+	if (cpu_matches(cpu_vuln_whitelist, NO_SPECULATION))
 		return;
 
 	setup_force_cpu_bug(X86_BUG_SPECTRE_V1);
 	setup_force_cpu_bug(X86_BUG_SPECTRE_V2);
 
-	if (!cpu_matches(NO_SSB) && !(ia32_cap & ARCH_CAP_SSB_NO) &&
+	if (!cpu_matches(cpu_vuln_whitelist, NO_SSB) &&
+	    !(ia32_cap & ARCH_CAP_SSB_NO) &&
 	   !cpu_has(c, X86_FEATURE_AMD_SSB_NO))
 		setup_force_cpu_bug(X86_BUG_SPEC_STORE_BYPASS);
 
 	if (ia32_cap & ARCH_CAP_IBRS_ALL)
 		setup_force_cpu_cap(X86_FEATURE_IBRS_ENHANCED);
 
-	if (!cpu_matches(NO_MDS) && !(ia32_cap & ARCH_CAP_MDS_NO)) {
+	if (!cpu_matches(cpu_vuln_whitelist, NO_MDS) &&
+	    !(ia32_cap & ARCH_CAP_MDS_NO)) {
 		setup_force_cpu_bug(X86_BUG_MDS);
-		if (cpu_matches(MSBDS_ONLY))
+		if (cpu_matches(cpu_vuln_whitelist, MSBDS_ONLY))
 			setup_force_cpu_bug(X86_BUG_MSBDS_ONLY);
 	}
 
-	if (!cpu_matches(NO_SWAPGS))
+	if (!cpu_matches(cpu_vuln_whitelist, NO_SWAPGS))
 		setup_force_cpu_bug(X86_BUG_SWAPGS);
 
 	/*
@@ -934,7 +958,16 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
 	     (ia32_cap & ARCH_CAP_TSX_CTRL_MSR)))
 		setup_force_cpu_bug(X86_BUG_TAA);
 
-	if (cpu_matches(NO_MELTDOWN))
+	/*
+	 * SRBDS affects CPUs which support RDRAND or RDSEED and are listed
+	 * in the vulnerability blacklist.
+	 */
+	if ((cpu_has(c, X86_FEATURE_RDRAND) ||
+	     cpu_has(c, X86_FEATURE_RDSEED)) &&
+	    cpu_matches(cpu_vuln_blacklist, SRBDS))
+		    setup_force_cpu_bug(X86_BUG_SRBDS);
+
+	if (cpu_matches(cpu_vuln_whitelist, NO_MELTDOWN))
 		return;
 
 	/* Rogue Data Cache Load? No! */
@@ -943,7 +976,7 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
 
 	setup_force_cpu_bug(X86_BUG_CPU_MELTDOWN);
 
-	if (cpu_matches(NO_L1TF))
+	if (cpu_matches(cpu_vuln_whitelist, NO_L1TF))
 		return;
 
 	setup_force_cpu_bug(X86_BUG_L1TF);
@@ -1095,7 +1128,7 @@ static void identify_cpu(struct cpuinfo_x86 *c)
 	c->loops_per_jiffy = loops_per_jiffy;
 	c->x86_cache_size = 0;
 	c->x86_vendor = X86_VENDOR_UNKNOWN;
-	c->x86_model = c->x86_mask = 0;	/* So far unknown... */
+	c->x86_model = c->x86_stepping = 0;	/* So far unknown... */
 	c->x86_vendor_id[0] = '\0'; /* Unset */
 	c->x86_model_id[0] = '\0';  /* Unset */
 	c->x86_max_cores = 1;
@@ -1280,6 +1313,7 @@ void identify_secondary_cpu(struct cpuinfo_x86 *c)
 #endif
 	mtrr_ap_init();
 	x86_spec_ctrl_setup_ap();
+	update_srbds_msr();
 }
 
 struct msr_range {
@@ -1356,8 +1390,8 @@ void print_cpu_info(struct cpuinfo_x86 *c)
 
 	printk(KERN_CONT " (fam: %02x, model: %02x", c->x86, c->x86_model);
 
-	if (c->x86_mask || c->cpuid_level >= 0)
-		printk(KERN_CONT ", stepping: %02x)\n", c->x86_mask);
+	if (c->x86_stepping || c->cpuid_level >= 0)
+		printk(KERN_CONT ", stepping: %02x)\n", c->x86_stepping);
 	else
 		printk(KERN_CONT ")\n");
 
diff --git a/arch/x86/kernel/cpu/cpu.h b/arch/x86/kernel/cpu/cpu.h
index 6c81eb018ce9..71c2b191fb5c 100644
--- a/arch/x86/kernel/cpu/cpu.h
+++ b/arch/x86/kernel/cpu/cpu.h
@@ -63,6 +63,7 @@ extern void get_cpu_cap(struct cpuinfo_x86 *c);
 extern void cpu_detect_cache_sizes(struct cpuinfo_x86 *c);
  
 extern void x86_spec_ctrl_setup_ap(void);
+extern void update_srbds_msr(void);
 
 extern u64 x86_read_arch_cap_msr(void);
 
diff --git a/arch/x86/kernel/cpu/cyrix.c b/arch/x86/kernel/cpu/cyrix.c
index 15e47c1cd412..e297ef0cfffb 100644
--- a/arch/x86/kernel/cpu/cyrix.c
+++ b/arch/x86/kernel/cpu/cyrix.c
@@ -212,7 +212,7 @@ static void init_cyrix(struct cpuinfo_x86 *c)
 
 	/* common case step number/rev -- exceptions handled below */
 	c->x86_model = (dir1 >> 4) + 1;
-	c->x86_mask = dir1 & 0xf;
+	c->x86_stepping = dir1 & 0xf;
 
 	/* Now cook; the original recipe is by Channing Corn, from Cyrix.
 	 * We do the same thing for each generation: we work out
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index 224957084d38..8f119fef01e3 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -81,7 +81,7 @@ static bool bad_spectre_microcode(struct cpuinfo_x86 *c)
 
 	for (i = 0; i < ARRAY_SIZE(spectre_bad_microcodes); i++) {
 		if (c->x86_model == spectre_bad_microcodes[i].model &&
-		    c->x86_mask == spectre_bad_microcodes[i].stepping)
+		    c->x86_stepping == spectre_bad_microcodes[i].stepping)
 			return (c->microcode <= spectre_bad_microcodes[i].microcode);
 	}
 	return false;
@@ -131,7 +131,7 @@ static void early_init_intel(struct cpuinfo_x86 *c)
 	 * need the microcode to have already been loaded... so if it is
 	 * not, recommend a BIOS update and disable large pages.
 	 */
-	if (c->x86 == 6 && c->x86_model == 0x1c && c->x86_mask <= 2 &&
+	if (c->x86 == 6 && c->x86_model == 0x1c && c->x86_stepping <= 2 &&
 	    c->microcode < 0x20e) {
 		printk(KERN_WARNING "Atom PSE erratum detected, BIOS microcode update recommended\n");
 		clear_cpu_cap(c, X86_FEATURE_PSE);
@@ -147,7 +147,7 @@ static void early_init_intel(struct cpuinfo_x86 *c)
 
 	/* CPUID workaround for 0F33/0F34 CPU */
 	if (c->x86 == 0xF && c->x86_model == 0x3
-	    && (c->x86_mask == 0x3 || c->x86_mask == 0x4))
+	    && (c->x86_stepping == 0x3 || c->x86_stepping == 0x4))
 		c->x86_phys_bits = 36;
 
 	/*
@@ -246,7 +246,7 @@ int ppro_with_ram_bug(void)
 	if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
 	    boot_cpu_data.x86 == 6 &&
 	    boot_cpu_data.x86_model == 1 &&
-	    boot_cpu_data.x86_mask < 8) {
+	    boot_cpu_data.x86_stepping < 8) {
 		printk(KERN_INFO "Pentium Pro with Errata#50 detected. Taking evasive action.\n");
 		return 1;
 	}
@@ -263,7 +263,7 @@ static void intel_smp_check(struct cpuinfo_x86 *c)
 	 * Mask B, Pentium, but not Pentium MMX
 	 */
 	if (c->x86 == 5 &&
-	    c->x86_mask >= 1 && c->x86_mask <= 4 &&
+	    c->x86_stepping >= 1 && c->x86_stepping <= 4 &&
 	    c->x86_model <= 3) {
 		/*
 		 * Remember we have B step Pentia with bugs
@@ -305,7 +305,7 @@ static void intel_workarounds(struct cpuinfo_x86 *c)
 	 * SEP CPUID bug: Pentium Pro reports SEP but doesn't have it until
 	 * model 3 mask 3
 	 */
-	if ((c->x86<<8 | c->x86_model<<4 | c->x86_mask) < 0x633)
+	if ((c->x86<<8 | c->x86_model<<4 | c->x86_stepping) < 0x633)
 		clear_cpu_cap(c, X86_FEATURE_SEP);
 
 	/*
@@ -323,7 +323,7 @@ static void intel_workarounds(struct cpuinfo_x86 *c)
 	 * P4 Xeon errata 037 workaround.
 	 * Hardware prefetcher may cause stale data to be loaded into the cache.
 	 */
-	if ((c->x86 == 15) && (c->x86_model == 1) && (c->x86_mask == 1)) {
+	if ((c->x86 == 15) && (c->x86_model == 1) && (c->x86_stepping == 1)) {
 		if (msr_set_bit(MSR_IA32_MISC_ENABLE,
 				MSR_IA32_MISC_ENABLE_PREFETCH_DISABLE_BIT)
 		    > 0) {
@@ -339,7 +339,7 @@ static void intel_workarounds(struct cpuinfo_x86 *c)
 	 * Specification Update").
 	 */
 	if (cpu_has_apic && (c->x86<<8 | c->x86_model<<4) == 0x520 &&
-	    (c->x86_mask < 0x6 || c->x86_mask == 0xb))
+	    (c->x86_stepping < 0x6 || c->x86_stepping == 0xb))
 		set_cpu_cap(c, X86_FEATURE_11AP);
 
 
@@ -523,7 +523,7 @@ static void init_intel(struct cpuinfo_x86 *c)
 		case 6:
 			if (l2 == 128)
 				p = "Celeron (Mendocino)";
-			else if (c->x86_mask == 0 || c->x86_mask == 5)
+			else if (c->x86_stepping == 0 || c->x86_stepping == 5)
 				p = "Celeron-A";
 			break;
 
diff --git a/arch/x86/kernel/cpu/match.c b/arch/x86/kernel/cpu/match.c
index fbb5e90557a5..a207aaaf78db 100644
--- a/arch/x86/kernel/cpu/match.c
+++ b/arch/x86/kernel/cpu/match.c
@@ -33,13 +33,18 @@ const struct x86_cpu_id *x86_match_cpu(const struct x86_cpu_id *match)
 	const struct x86_cpu_id *m;
 	struct cpuinfo_x86 *c = &boot_cpu_data;
 
-	for (m = match; m->vendor | m->family | m->model | m->feature; m++) {
+	for (m = match;
+	     m->vendor | m->family | m->model | m->steppings | m->feature;
+	     m++) {
 		if (m->vendor != X86_VENDOR_ANY && c->x86_vendor != m->vendor)
 			continue;
 		if (m->family != X86_FAMILY_ANY && c->x86 != m->family)
 			continue;
 		if (m->model != X86_MODEL_ANY && c->x86_model != m->model)
 			continue;
+		if (m->steppings != X86_STEPPING_ANY &&
+		    !(BIT(c->x86_stepping) & m->steppings))
+			continue;
 		if (m->feature != X86_FEATURE_ANY && !cpu_has(c, m->feature))
 			continue;
 		return m;
diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c
index 96fc70c033a2..6f0d056b47bf 100644
--- a/arch/x86/kernel/cpu/microcode/intel.c
+++ b/arch/x86/kernel/cpu/microcode/intel.c
@@ -291,7 +291,7 @@ static bool is_blacklisted(unsigned int cpu)
 	 */
 	if (c->x86 == 6 &&
 	    c->x86_model == 0x4F &&
-	    c->x86_mask == 0x01 &&
+	    c->x86_stepping == 0x01 &&
 	    llc_size_per_core > 2621440 &&
 	    c->microcode < 0x0b000021) {
 		pr_err_once("Erratum BDF90: late loading with revision < 0x0b000021 (0x%x) disabled.\n", c->microcode);
@@ -314,7 +314,7 @@ static enum ucode_state request_microcode_fw(int cpu, struct device *device,
 		return UCODE_NFOUND;
 
 	sprintf(name, "intel-ucode/%02x-%02x-%02x",
-		c->x86, c->x86_model, c->x86_mask);
+		c->x86, c->x86_model, c->x86_stepping);
 
 	if (request_firmware_direct(&firmware, name, device)) {
 		pr_debug("data file %s load failed\n", name);
diff --git a/arch/x86/kernel/cpu/mtrr/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c
index 0e25a1bc5ab5..cf0ef3412903 100644
--- a/arch/x86/kernel/cpu/mtrr/generic.c
+++ b/arch/x86/kernel/cpu/mtrr/generic.c
@@ -791,7 +791,7 @@ int generic_validate_add_page(unsigned long base, unsigned long size,
 	 */
 	if (is_cpu(INTEL) && boot_cpu_data.x86 == 6 &&
 	    boot_cpu_data.x86_model == 1 &&
-	    boot_cpu_data.x86_mask <= 7) {
+	    boot_cpu_data.x86_stepping <= 7) {
 		if (base & ((1 << (22 - PAGE_SHIFT)) - 1)) {
 			pr_warning("mtrr: base(0x%lx000) is not 4 MiB aligned\n", base);
 			return -EINVAL;
diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c
index 44668915fa07..cb717ed27188 100644
--- a/arch/x86/kernel/cpu/mtrr/main.c
+++ b/arch/x86/kernel/cpu/mtrr/main.c
@@ -688,8 +688,8 @@ void __init mtrr_bp_init(void)
 			if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
 			    boot_cpu_data.x86 == 0xF &&
 			    boot_cpu_data.x86_model == 0x3 &&
-			    (boot_cpu_data.x86_mask == 0x3 ||
-			     boot_cpu_data.x86_mask == 0x4))
+			    (boot_cpu_data.x86_stepping == 0x3 ||
+			     boot_cpu_data.x86_stepping == 0x4))
 				phys_addr = 36;
 
 			size_or_mask = SIZE_OR_MASK_BITS(phys_addr);
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c
index 6cb22df3a92e..e91d9891a82a 100644
--- a/arch/x86/kernel/cpu/perf_event_intel.c
+++ b/arch/x86/kernel/cpu/perf_event_intel.c
@@ -2192,7 +2192,7 @@ static int intel_snb_pebs_broken(int cpu)
 		break;
 
 	case 45: /* SNB-EP */
-		switch (cpu_data(cpu).x86_mask) {
+		switch (cpu_data(cpu).x86_stepping) {
 		case 6: rev = 0x618; break;
 		case 7: rev = 0x70c; break;
 		}
diff --git a/arch/x86/kernel/cpu/perf_event_intel_lbr.c b/arch/x86/kernel/cpu/perf_event_intel_lbr.c
index 32a14fe2a65c..222b47f20847 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_lbr.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_lbr.c
@@ -763,7 +763,7 @@ void intel_pmu_lbr_init_atom(void)
 	 * on PMU interrupt
 	 */
 	if (boot_cpu_data.x86_model == 28
-	    && boot_cpu_data.x86_mask < 10) {
+	    && boot_cpu_data.x86_stepping < 10) {
 		pr_cont("LBR disabled due to erratum");
 		return;
 	}
diff --git a/arch/x86/kernel/cpu/perf_event_p6.c b/arch/x86/kernel/cpu/perf_event_p6.c
index 7c1a0c07b607..507e2e319f52 100644
--- a/arch/x86/kernel/cpu/perf_event_p6.c
+++ b/arch/x86/kernel/cpu/perf_event_p6.c
@@ -233,7 +233,7 @@ static __initconst const struct x86_pmu p6_pmu = {
 
 static __init void p6_pmu_rdpmc_quirk(void)
 {
-	if (boot_cpu_data.x86_mask < 9) {
+	if (boot_cpu_data.x86_stepping < 9) {
 		/*
 		 * PPro erratum 26; fixed in stepping 9 and above.
 		 */
diff --git a/arch/x86/kernel/cpu/proc.c b/arch/x86/kernel/cpu/proc.c
index 4af9be1c07eb..b8d40e046d0b 100644
--- a/arch/x86/kernel/cpu/proc.c
+++ b/arch/x86/kernel/cpu/proc.c
@@ -69,8 +69,8 @@ static int show_cpuinfo(struct seq_file *m, void *v)
 		   c->x86_model,
 		   c->x86_model_id[0] ? c->x86_model_id : "unknown");
 
-	if (c->x86_mask || c->cpuid_level >= 0)
-		seq_printf(m, "stepping\t: %d\n", c->x86_mask);
+	if (c->x86_stepping || c->cpuid_level >= 0)
+		seq_printf(m, "stepping\t: %d\n", c->x86_stepping);
 	else
 		seq_printf(m, "stepping\t: unknown\n");
 	if (c->microcode)
diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S
index 736330f96d93..302969718d54 100644
--- a/arch/x86/kernel/head_32.S
+++ b/arch/x86/kernel/head_32.S
@@ -33,7 +33,7 @@
 #define X86		new_cpu_data+CPUINFO_x86
 #define X86_VENDOR	new_cpu_data+CPUINFO_x86_vendor
 #define X86_MODEL	new_cpu_data+CPUINFO_x86_model
-#define X86_MASK	new_cpu_data+CPUINFO_x86_mask
+#define X86_STEPPING	new_cpu_data+CPUINFO_x86_stepping
 #define X86_HARD_MATH	new_cpu_data+CPUINFO_hard_math
 #define X86_CPUID	new_cpu_data+CPUINFO_cpuid_level
 #define X86_CAPABILITY	new_cpu_data+CPUINFO_x86_capability
@@ -433,7 +433,7 @@ ENTRY(startup_32_smp)
 	shrb $4,%al
 	movb %al,X86_MODEL
 	andb $0x0f,%cl		# mask mask revision
-	movb %cl,X86_MASK
+	movb %cl,X86_STEPPING
 	movl %edx,X86_CAPABILITY
 
 is486:
diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c
index d2b56489d70f..ea6715138021 100644
--- a/arch/x86/kernel/mpparse.c
+++ b/arch/x86/kernel/mpparse.c
@@ -409,7 +409,7 @@ static inline void __init construct_default_ISA_mptable(int mpc_default_type)
 	processor.apicver = mpc_default_type > 4 ? 0x10 : 0x01;
 	processor.cpuflag = CPU_ENABLED;
 	processor.cpufeature = (boot_cpu_data.x86 << 8) |
-	    (boot_cpu_data.x86_model << 4) | boot_cpu_data.x86_mask;
+	    (boot_cpu_data.x86_model << 4) | boot_cpu_data.x86_stepping;
 	processor.featureflag = boot_cpu_data.x86_capability[0];
 	processor.reserved[0] = 0;
 	processor.reserved[1] = 0;
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index 9f7d6b1b1eb2..0c8289d5aae8 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -469,6 +469,12 @@ ssize_t __weak cpu_show_itlb_multihit(struct device *dev,
 	return sprintf(buf, "Not affected\n");
 }
 
+ssize_t __weak cpu_show_srbds(struct device *dev,
+			      struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "Not affected\n");
+}
+
 static DEVICE_ATTR(meltdown, 0444, cpu_show_meltdown, NULL);
 static DEVICE_ATTR(spectre_v1, 0444, cpu_show_spectre_v1, NULL);
 static DEVICE_ATTR(spectre_v2, 0444, cpu_show_spectre_v2, NULL);
@@ -477,6 +483,7 @@ static DEVICE_ATTR(l1tf, 0444, cpu_show_l1tf, NULL);
 static DEVICE_ATTR(mds, 0444, cpu_show_mds, NULL);
 static DEVICE_ATTR(tsx_async_abort, 0444, cpu_show_tsx_async_abort, NULL);
 static DEVICE_ATTR(itlb_multihit, 0444, cpu_show_itlb_multihit, NULL);
+static DEVICE_ATTR(srbds, 0444, cpu_show_srbds, NULL);
 
 static struct attribute *cpu_root_vulnerabilities_attrs[] = {
 	&dev_attr_meltdown.attr,
@@ -487,6 +494,7 @@ static struct attribute *cpu_root_vulnerabilities_attrs[] = {
 	&dev_attr_mds.attr,
 	&dev_attr_tsx_async_abort.attr,
 	&dev_attr_itlb_multihit.attr,
+	&dev_attr_srbds.attr,
 	NULL
 };
 
diff --git a/drivers/char/hw_random/via-rng.c b/drivers/char/hw_random/via-rng.c
index de5a6dcfb3e2..64313dbdecba 100644
--- a/drivers/char/hw_random/via-rng.c
+++ b/drivers/char/hw_random/via-rng.c
@@ -166,7 +166,7 @@ static int via_rng_init(struct hwrng *rng)
 	/* Enable secondary noise source on CPUs where it is present. */
 
 	/* Nehemiah stepping 8 and higher */
-	if ((c->x86_model == 9) && (c->x86_mask > 7))
+	if ((c->x86_model == 9) && (c->x86_stepping > 7))
 		lo |= VIA_NOISESRC2;
 
 	/* Esther */
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 0787fa2bdf27..4fd33598ce0a 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1700,9 +1700,6 @@ unsigned int get_random_int(void)
 	__u32 *hash;
 	unsigned int ret;
 
-	if (arch_get_random_int(&ret))
-		return ret;
-
 	hash = get_cpu_var(get_random_int_hash);
 
 	hash[0] += current->pid + jiffies + random_get_entropy();
diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c
index b0c18ed8d83f..ec3c0afb1bb2 100644
--- a/drivers/cpufreq/acpi-cpufreq.c
+++ b/drivers/cpufreq/acpi-cpufreq.c
@@ -628,7 +628,7 @@ static int acpi_cpufreq_blacklist(struct cpuinfo_x86 *c)
 	if (c->x86_vendor == X86_VENDOR_INTEL) {
 		if ((c->x86 == 15) &&
 		    (c->x86_model == 6) &&
-		    (c->x86_mask == 8)) {
+		    (c->x86_stepping == 8)) {
 			printk(KERN_INFO "acpi-cpufreq: Intel(R) "
 			    "Xeon(R) 7100 Errata AL30, processors may "
 			    "lock up on frequency changes: disabling "
diff --git a/drivers/cpufreq/longhaul.c b/drivers/cpufreq/longhaul.c
index c913906a719e..74ff01e77b95 100644
--- a/drivers/cpufreq/longhaul.c
+++ b/drivers/cpufreq/longhaul.c
@@ -786,7 +786,7 @@ static int longhaul_cpu_init(struct cpufreq_policy *policy)
 		break;
 
 	case 7:
-		switch (c->x86_mask) {
+		switch (c->x86_stepping) {
 		case 0:
 			longhaul_version = TYPE_LONGHAUL_V1;
 			cpu_model = CPU_SAMUEL2;
@@ -798,7 +798,7 @@ static int longhaul_cpu_init(struct cpufreq_policy *policy)
 			break;
 		case 1 ... 15:
 			longhaul_version = TYPE_LONGHAUL_V2;
-			if (c->x86_mask < 8) {
+			if (c->x86_stepping < 8) {
 				cpu_model = CPU_SAMUEL2;
 				cpuname = "C3 'Samuel 2' [C5B]";
 			} else {
@@ -825,7 +825,7 @@ static int longhaul_cpu_init(struct cpufreq_policy *policy)
 		numscales = 32;
 		memcpy(mults, nehemiah_mults, sizeof(nehemiah_mults));
 		memcpy(eblcr, nehemiah_eblcr, sizeof(nehemiah_eblcr));
-		switch (c->x86_mask) {
+		switch (c->x86_stepping) {
 		case 0 ... 1:
 			cpu_model = CPU_NEHEMIAH;
 			cpuname = "C3 'Nehemiah A' [C5XLOE]";
diff --git a/drivers/cpufreq/p4-clockmod.c b/drivers/cpufreq/p4-clockmod.c
index 529cfd92158f..3ab037775c04 100644
--- a/drivers/cpufreq/p4-clockmod.c
+++ b/drivers/cpufreq/p4-clockmod.c
@@ -176,7 +176,7 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy)
 #endif
 
 	/* Errata workaround */
-	cpuid = (c->x86 << 8) | (c->x86_model << 4) | c->x86_mask;
+	cpuid = (c->x86 << 8) | (c->x86_model << 4) | c->x86_stepping;
 	switch (cpuid) {
 	case 0x0f07:
 	case 0x0f0a:
diff --git a/drivers/cpufreq/powernow-k7.c b/drivers/cpufreq/powernow-k7.c
index e61e224475ad..d8f4ef994c73 100644
--- a/drivers/cpufreq/powernow-k7.c
+++ b/drivers/cpufreq/powernow-k7.c
@@ -133,7 +133,7 @@ static int check_powernow(void)
 		return 0;
 	}
 
-	if ((c->x86_model == 6) && (c->x86_mask == 0)) {
+	if ((c->x86_model == 6) && (c->x86_stepping == 0)) {
 		printk(KERN_INFO PFX "K7 660[A0] core detected, "
 				"enabling errata workarounds\n");
 		have_a0 = 1;
diff --git a/drivers/cpufreq/speedstep-centrino.c b/drivers/cpufreq/speedstep-centrino.c
index 7d4a31571608..a7e72a51806a 100644
--- a/drivers/cpufreq/speedstep-centrino.c
+++ b/drivers/cpufreq/speedstep-centrino.c
@@ -36,7 +36,7 @@ struct cpu_id
 {
 	__u8	x86;            /* CPU family */
 	__u8	x86_model;	/* model */
-	__u8	x86_mask;	/* stepping */
+	__u8	x86_stepping;	/* stepping */
 };
 
 enum {
@@ -276,7 +276,7 @@ static int centrino_verify_cpu_id(const struct cpuinfo_x86 *c,
 {
 	if ((c->x86 == x->x86) &&
 	    (c->x86_model == x->x86_model) &&
-	    (c->x86_mask == x->x86_mask))
+	    (c->x86_stepping == x->x86_stepping))
 		return 1;
 	return 0;
 }
diff --git a/drivers/cpufreq/speedstep-lib.c b/drivers/cpufreq/speedstep-lib.c
index 4ab7a2156672..ee4a8f2def34 100644
--- a/drivers/cpufreq/speedstep-lib.c
+++ b/drivers/cpufreq/speedstep-lib.c
@@ -270,9 +270,9 @@ unsigned int speedstep_detect_processor(void)
 		ebx = cpuid_ebx(0x00000001);
 		ebx &= 0x000000FF;
 
-		pr_debug("ebx value is %x, x86_mask is %x\n", ebx, c->x86_mask);
+		pr_debug("ebx value is %x, x86_stepping is %x\n", ebx, c->x86_stepping);
 
-		switch (c->x86_mask) {
+		switch (c->x86_stepping) {
 		case 4:
 			/*
 			 * B-stepping [M-P4-M]
@@ -359,7 +359,7 @@ unsigned int speedstep_detect_processor(void)
 				msr_lo, msr_hi);
 		if ((msr_hi & (1<<18)) &&
 		    (relaxed_check ? 1 : (msr_hi & (3<<24)))) {
-			if (c->x86_mask == 0x01) {
+			if (c->x86_stepping == 0x01) {
 				pr_debug("early PIII version\n");
 				return SPEEDSTEP_CPU_PIII_C_EARLY;
 			} else
diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c
index 2250db026198..6b706544b279 100644
--- a/drivers/crypto/padlock-aes.c
+++ b/drivers/crypto/padlock-aes.c
@@ -535,7 +535,7 @@ static int __init padlock_init(void)
 
 	printk(KERN_NOTICE PFX "Using VIA PadLock ACE for AES algorithm.\n");
 
-	if (c->x86 == 6 && c->x86_model == 15 && c->x86_mask == 2) {
+	if (c->x86 == 6 && c->x86_model == 15 && c->x86_stepping == 2) {
 		ecb_fetch_blocks = MAX_ECB_FETCH_BLOCKS;
 		cbc_fetch_blocks = MAX_CBC_FETCH_BLOCKS;
 		printk(KERN_NOTICE PFX "VIA Nano stepping 2 detected: enabling workaround.\n");
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
index 5fde910aeb62..0b612d240202 100644
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -2576,7 +2576,7 @@ static struct amd64_family_type *per_family_init(struct amd64_pvt *pvt)
 	struct amd64_family_type *fam_type = NULL;
 
 	pvt->ext_model  = boot_cpu_data.x86_model >> 4;
-	pvt->stepping	= boot_cpu_data.x86_mask;
+	pvt->stepping	= boot_cpu_data.x86_stepping;
 	pvt->model	= boot_cpu_data.x86_model;
 	pvt->fam	= boot_cpu_data.x86;
 
diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c
index 5f43620d580a..064ef95f9aad 100644
--- a/drivers/edac/mce_amd.c
+++ b/drivers/edac/mce_amd.c
@@ -744,7 +744,7 @@ int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data)
 
 	pr_emerg(HW_ERR "CPU:%d (%x:%x:%x) MC%d_STATUS[%s|%s|%s|%s|%s",
 		m->extcpu,
-		c->x86, c->x86_model, c->x86_mask,
+		c->x86, c->x86_model, c->x86_stepping,
 		m->bank,
 		((m->status & MCI_STATUS_OVER)	? "Over"  : "-"),
 		((m->status & MCI_STATUS_UC)	? "UE"	  : "CE"),
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c
index d76f0b70c6e0..4cf3b791e88e 100644
--- a/drivers/hwmon/coretemp.c
+++ b/drivers/hwmon/coretemp.c
@@ -268,13 +268,13 @@ static int adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev)
 	for (i = 0; i < ARRAY_SIZE(tjmax_model_table); i++) {
 		const struct tjmax_model *tm = &tjmax_model_table[i];
 		if (c->x86_model == tm->model &&
-		    (tm->mask == ANY || c->x86_mask == tm->mask))
+		    (tm->mask == ANY || c->x86_stepping == tm->mask))
 			return tm->tjmax;
 	}
 
 	/* Early chips have no MSR for TjMax */
 
-	if (c->x86_model == 0xf && c->x86_mask < 4)
+	if (c->x86_model == 0xf && c->x86_stepping < 4)
 		usemsr_ee = 0;
 
 	if (c->x86_model > 0xe && usemsr_ee) {
@@ -426,7 +426,7 @@ static int chk_ucode_version(unsigned int cpu)
 	 * Readings might stop update when processor visited too deep sleep,
 	 * fixed for stepping D0 (6EC).
 	 */
-	if (c->x86_model == 0xe && c->x86_mask < 0xc && c->microcode < 0x39) {
+	if (c->x86_model == 0xe && c->x86_stepping < 0xc && c->microcode < 0x39) {
 		pr_err("Errata AE18 not fixed, update BIOS or microcode of the CPU!\n");
 		return -ENODEV;
 	}
diff --git a/drivers/hwmon/hwmon-vid.c b/drivers/hwmon/hwmon-vid.c
index ef91b8a67549..84e91286fc4f 100644
--- a/drivers/hwmon/hwmon-vid.c
+++ b/drivers/hwmon/hwmon-vid.c
@@ -293,7 +293,7 @@ u8 vid_which_vrm(void)
 	if (c->x86 < 6)		/* Any CPU with family lower than 6 */
 		return 0;	/* doesn't have VID */
 
-	vrm_ret = find_vrm(c->x86, c->x86_model, c->x86_mask, c->x86_vendor);
+	vrm_ret = find_vrm(c->x86, c->x86_model, c->x86_stepping, c->x86_vendor);
 	if (vrm_ret == 134)
 		vrm_ret = get_via_model_d_vrm();
 	if (vrm_ret == 0)
diff --git a/drivers/hwmon/k10temp.c b/drivers/hwmon/k10temp.c
index f7b46f68ef43..91f22a0e72b3 100644
--- a/drivers/hwmon/k10temp.c
+++ b/drivers/hwmon/k10temp.c
@@ -126,7 +126,7 @@ static bool has_erratum_319(struct pci_dev *pdev)
 	 * and AM3 formats, but that's the best we can do.
 	 */
 	return boot_cpu_data.x86_model < 4 ||
-	       (boot_cpu_data.x86_model == 4 && boot_cpu_data.x86_mask <= 2);
+	       (boot_cpu_data.x86_model == 4 && boot_cpu_data.x86_stepping <= 2);
 }
 
 static int k10temp_probe(struct pci_dev *pdev,
diff --git a/drivers/hwmon/k8temp.c b/drivers/hwmon/k8temp.c
index 734d55d48cc8..486502798fc5 100644
--- a/drivers/hwmon/k8temp.c
+++ b/drivers/hwmon/k8temp.c
@@ -187,7 +187,7 @@ static int k8temp_probe(struct pci_dev *pdev,
 		return -ENOMEM;
 
 	model = boot_cpu_data.x86_model;
-	stepping = boot_cpu_data.x86_mask;
+	stepping = boot_cpu_data.x86_stepping;
 
 	/* feature available since SH-C0, exclude older revisions */
 	if ((model == 4 && stepping == 0) ||
diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c
index 8a050e885688..03a5db0da480 100644
--- a/drivers/message/fusion/mptctl.c
+++ b/drivers/message/fusion/mptctl.c
@@ -100,19 +100,19 @@ struct buflist {
  * Function prototypes. Called from OS entry point mptctl_ioctl.
  * arg contents specific to function.
  */
-static int mptctl_fw_download(unsigned long arg);
-static int mptctl_getiocinfo(unsigned long arg, unsigned int cmd);
-static int mptctl_gettargetinfo(unsigned long arg);
-static int mptctl_readtest(unsigned long arg);
-static int mptctl_mpt_command(unsigned long arg);
-static int mptctl_eventquery(unsigned long arg);
-static int mptctl_eventenable(unsigned long arg);
-static int mptctl_eventreport(unsigned long arg);
-static int mptctl_replace_fw(unsigned long arg);
-
-static int mptctl_do_reset(unsigned long arg);
-static int mptctl_hp_hostinfo(unsigned long arg, unsigned int cmd);
-static int mptctl_hp_targetinfo(unsigned long arg);
+static int mptctl_fw_download(MPT_ADAPTER *iocp, unsigned long arg);
+static int mptctl_getiocinfo(MPT_ADAPTER *iocp, unsigned long arg, unsigned int cmd);
+static int mptctl_gettargetinfo(MPT_ADAPTER *iocp, unsigned long arg);
+static int mptctl_readtest(MPT_ADAPTER *iocp, unsigned long arg);
+static int mptctl_mpt_command(MPT_ADAPTER *iocp, unsigned long arg);
+static int mptctl_eventquery(MPT_ADAPTER *iocp, unsigned long arg);
+static int mptctl_eventenable(MPT_ADAPTER *iocp, unsigned long arg);
+static int mptctl_eventreport(MPT_ADAPTER *iocp, unsigned long arg);
+static int mptctl_replace_fw(MPT_ADAPTER *iocp, unsigned long arg);
+
+static int mptctl_do_reset(MPT_ADAPTER *iocp, unsigned long arg);
+static int mptctl_hp_hostinfo(MPT_ADAPTER *iocp, unsigned long arg, unsigned int cmd);
+static int mptctl_hp_targetinfo(MPT_ADAPTER *iocp, unsigned long arg);
 
 static int  mptctl_probe(struct pci_dev *, const struct pci_device_id *);
 static void mptctl_remove(struct pci_dev *);
@@ -123,8 +123,8 @@ static long compat_mpctl_ioctl(struct file *f, unsigned cmd, unsigned long arg);
 /*
  * Private function calls.
  */
-static int mptctl_do_mpt_command(struct mpt_ioctl_command karg, void __user *mfPtr);
-static int mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen);
+static int mptctl_do_mpt_command(MPT_ADAPTER *iocp, struct mpt_ioctl_command karg, void __user *mfPtr);
+static int mptctl_do_fw_download(MPT_ADAPTER *iocp, char __user *ufwbuf, size_t fwlen);
 static MptSge_t *kbuf_alloc_2_sgl(int bytes, u32 dir, int sge_offset, int *frags,
 		struct buflist **blp, dma_addr_t *sglbuf_dma, MPT_ADAPTER *ioc);
 static void kfree_sgl(MptSge_t *sgl, dma_addr_t sgl_dma,
@@ -656,19 +656,19 @@ __mptctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 	 * by TM and FW reloads.
 	 */
 	if ((cmd & ~IOCSIZE_MASK) == (MPTIOCINFO & ~IOCSIZE_MASK)) {
-		return mptctl_getiocinfo(arg, _IOC_SIZE(cmd));
+		return mptctl_getiocinfo(iocp, arg, _IOC_SIZE(cmd));
 	} else if (cmd == MPTTARGETINFO) {
-		return mptctl_gettargetinfo(arg);
+		return mptctl_gettargetinfo(iocp, arg);
 	} else if (cmd == MPTTEST) {
-		return mptctl_readtest(arg);
+		return mptctl_readtest(iocp, arg);
 	} else if (cmd == MPTEVENTQUERY) {
-		return mptctl_eventquery(arg);
+		return mptctl_eventquery(iocp, arg);
 	} else if (cmd == MPTEVENTENABLE) {
-		return mptctl_eventenable(arg);
+		return mptctl_eventenable(iocp, arg);
 	} else if (cmd == MPTEVENTREPORT) {
-		return mptctl_eventreport(arg);
+		return mptctl_eventreport(iocp, arg);
 	} else if (cmd == MPTFWREPLACE) {
-		return mptctl_replace_fw(arg);
+		return mptctl_replace_fw(iocp, arg);
 	}
 
 	/* All of these commands require an interrupt or
@@ -678,15 +678,15 @@ __mptctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 		return ret;
 
 	if (cmd == MPTFWDOWNLOAD)
-		ret = mptctl_fw_download(arg);
+		ret = mptctl_fw_download(iocp, arg);
 	else if (cmd == MPTCOMMAND)
-		ret = mptctl_mpt_command(arg);
+		ret = mptctl_mpt_command(iocp, arg);
 	else if (cmd == MPTHARDRESET)
-		ret = mptctl_do_reset(arg);
+		ret = mptctl_do_reset(iocp, arg);
 	else if ((cmd & ~IOCSIZE_MASK) == (HP_GETHOSTINFO & ~IOCSIZE_MASK))
-		ret = mptctl_hp_hostinfo(arg, _IOC_SIZE(cmd));
+		ret = mptctl_hp_hostinfo(iocp, arg, _IOC_SIZE(cmd));
 	else if (cmd == HP_GETTARGETINFO)
-		ret = mptctl_hp_targetinfo(arg);
+		ret = mptctl_hp_targetinfo(iocp, arg);
 	else
 		ret = -EINVAL;
 
@@ -705,11 +705,10 @@ mptctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 	return ret;
 }
 
-static int mptctl_do_reset(unsigned long arg)
+static int mptctl_do_reset(MPT_ADAPTER *iocp, unsigned long arg)
 {
 	struct mpt_ioctl_diag_reset __user *urinfo = (void __user *) arg;
 	struct mpt_ioctl_diag_reset krinfo;
-	MPT_ADAPTER		*iocp;
 
 	if (copy_from_user(&krinfo, urinfo, sizeof(struct mpt_ioctl_diag_reset))) {
 		printk(KERN_ERR MYNAM "%s@%d::mptctl_do_reset - "
@@ -718,12 +717,6 @@ static int mptctl_do_reset(unsigned long arg)
 		return -EFAULT;
 	}
 
-	if (mpt_verify_adapter(krinfo.hdr.iocnum, &iocp) < 0) {
-		printk(KERN_DEBUG MYNAM "%s@%d::mptctl_do_reset - ioc%d not found!\n",
-				__FILE__, __LINE__, krinfo.hdr.iocnum);
-		return -ENODEV; /* (-6) No such device or address */
-	}
-
 	dctlprintk(iocp, printk(MYIOC_s_DEBUG_FMT "mptctl_do_reset called.\n",
 	    iocp->name));
 
@@ -754,7 +747,7 @@ static int mptctl_do_reset(unsigned long arg)
  *		-ENOMSG if FW upload returned bad status
  */
 static int
-mptctl_fw_download(unsigned long arg)
+mptctl_fw_download(MPT_ADAPTER *iocp, unsigned long arg)
 {
 	struct mpt_fw_xfer __user *ufwdl = (void __user *) arg;
 	struct mpt_fw_xfer	 kfwdl;
@@ -766,7 +759,7 @@ mptctl_fw_download(unsigned long arg)
 		return -EFAULT;
 	}
 
-	return mptctl_do_fw_download(kfwdl.iocnum, kfwdl.bufp, kfwdl.fwlen);
+	return mptctl_do_fw_download(iocp, kfwdl.bufp, kfwdl.fwlen);
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -784,11 +777,10 @@ mptctl_fw_download(unsigned long arg)
  *		-ENOMSG if FW upload returned bad status
  */
 static int
-mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen)
+mptctl_do_fw_download(MPT_ADAPTER *iocp, char __user *ufwbuf, size_t fwlen)
 {
 	FWDownload_t		*dlmsg;
 	MPT_FRAME_HDR		*mf;
-	MPT_ADAPTER		*iocp;
 	FWDownloadTCSGE_t	*ptsge;
 	MptSge_t		*sgl, *sgIn;
 	char			*sgOut;
@@ -808,17 +800,10 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen)
 	pFWDownloadReply_t	 ReplyMsg = NULL;
 	unsigned long		 timeleft;
 
-	if (mpt_verify_adapter(ioc, &iocp) < 0) {
-		printk(KERN_DEBUG MYNAM "ioctl_fwdl - ioc%d not found!\n",
-				 ioc);
-		return -ENODEV; /* (-6) No such device or address */
-	} else {
-
-		/*  Valid device. Get a message frame and construct the FW download message.
-	 	*/
-		if ((mf = mpt_get_msg_frame(mptctl_id, iocp)) == NULL)
-			return -EAGAIN;
-	}
+	/*  Valid device. Get a message frame and construct the FW download message.
+	*/
+	if ((mf = mpt_get_msg_frame(mptctl_id, iocp)) == NULL)
+		return -EAGAIN;
 
 	dctlprintk(iocp, printk(MYIOC_s_DEBUG_FMT
 	    "mptctl_do_fwdl called. mptctl_id = %xh.\n", iocp->name, mptctl_id));
@@ -826,8 +811,6 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen)
 	    iocp->name, ufwbuf));
 	dctlprintk(iocp, printk(MYIOC_s_DEBUG_FMT "DbG: kfwdl.fwlen = %d\n",
 	    iocp->name, (int)fwlen));
-	dctlprintk(iocp, printk(MYIOC_s_DEBUG_FMT "DbG: kfwdl.ioc   = %04xh\n",
-	    iocp->name, ioc));
 
 	dlmsg = (FWDownload_t*) mf;
 	ptsge = (FWDownloadTCSGE_t *) &dlmsg->SGL;
@@ -1234,13 +1217,11 @@ kfree_sgl(MptSge_t *sgl, dma_addr_t sgl_dma, struct buflist *buflist, MPT_ADAPTE
  *		-ENODEV  if no such device/adapter
  */
 static int
-mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
+mptctl_getiocinfo (MPT_ADAPTER *ioc, unsigned long arg, unsigned int data_size)
 {
 	struct mpt_ioctl_iocinfo __user *uarg = (void __user *) arg;
 	struct mpt_ioctl_iocinfo *karg;
-	MPT_ADAPTER		*ioc;
 	struct pci_dev		*pdev;
-	int			iocnum;
 	unsigned int		port;
 	int			cim_rev;
 	struct scsi_device 	*sdev;
@@ -1276,14 +1257,6 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
 		return -EFAULT;
 	}
 
-	if (((iocnum = mpt_verify_adapter(karg->hdr.iocnum, &ioc)) < 0) ||
-	    (ioc == NULL)) {
-		printk(KERN_DEBUG MYNAM "%s::mptctl_getiocinfo() @%d - ioc%d not found!\n",
-				__FILE__, __LINE__, iocnum);
-		kfree(karg);
-		return -ENODEV;
-	}
-
 	/* Verify the data transfer size is correct. */
 	if (karg->hdr.maxDataSize != data_size) {
 		printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_getiocinfo - "
@@ -1389,15 +1362,13 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
  *		-ENODEV  if no such device/adapter
  */
 static int
-mptctl_gettargetinfo (unsigned long arg)
+mptctl_gettargetinfo (MPT_ADAPTER *ioc, unsigned long arg)
 {
 	struct mpt_ioctl_targetinfo __user *uarg = (void __user *) arg;
 	struct mpt_ioctl_targetinfo karg;
-	MPT_ADAPTER		*ioc;
 	VirtDevice		*vdevice;
 	char			*pmem;
 	int			*pdata;
-	int			iocnum;
 	int			numDevices = 0;
 	int			lun;
 	int			maxWordsLeft;
@@ -1412,13 +1383,6 @@ mptctl_gettargetinfo (unsigned long arg)
 		return -EFAULT;
 	}
 
-	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
-	    (ioc == NULL)) {
-		printk(KERN_DEBUG MYNAM "%s::mptctl_gettargetinfo() @%d - ioc%d not found!\n",
-				__FILE__, __LINE__, iocnum);
-		return -ENODEV;
-	}
-
 	dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_gettargetinfo called.\n",
 	    ioc->name));
 	/* Get the port number and set the maximum number of bytes
@@ -1514,12 +1478,10 @@ mptctl_gettargetinfo (unsigned long arg)
  *		-ENODEV  if no such device/adapter
  */
 static int
-mptctl_readtest (unsigned long arg)
+mptctl_readtest (MPT_ADAPTER *ioc, unsigned long arg)
 {
 	struct mpt_ioctl_test __user *uarg = (void __user *) arg;
 	struct mpt_ioctl_test	 karg;
-	MPT_ADAPTER *ioc;
-	int iocnum;
 
 	if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_test))) {
 		printk(KERN_ERR MYNAM "%s@%d::mptctl_readtest - "
@@ -1528,13 +1490,6 @@ mptctl_readtest (unsigned long arg)
 		return -EFAULT;
 	}
 
-	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
-	    (ioc == NULL)) {
-		printk(KERN_DEBUG MYNAM "%s::mptctl_readtest() @%d - ioc%d not found!\n",
-				__FILE__, __LINE__, iocnum);
-		return -ENODEV;
-	}
-
 	dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_readtest called.\n",
 	    ioc->name));
 	/* Fill in the data and return the structure to the calling
@@ -1575,12 +1530,10 @@ mptctl_readtest (unsigned long arg)
  *		-ENODEV  if no such device/adapter
  */
 static int
-mptctl_eventquery (unsigned long arg)
+mptctl_eventquery (MPT_ADAPTER *ioc, unsigned long arg)
 {
 	struct mpt_ioctl_eventquery __user *uarg = (void __user *) arg;
 	struct mpt_ioctl_eventquery	 karg;
-	MPT_ADAPTER *ioc;
-	int iocnum;
 
 	if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventquery))) {
 		printk(KERN_ERR MYNAM "%s@%d::mptctl_eventquery - "
@@ -1589,13 +1542,6 @@ mptctl_eventquery (unsigned long arg)
 		return -EFAULT;
 	}
 
-	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
-	    (ioc == NULL)) {
-		printk(KERN_DEBUG MYNAM "%s::mptctl_eventquery() @%d - ioc%d not found!\n",
-				__FILE__, __LINE__, iocnum);
-		return -ENODEV;
-	}
-
 	dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_eventquery called.\n",
 	    ioc->name));
 	karg.eventEntries = MPTCTL_EVENT_LOG_SIZE;
@@ -1614,12 +1560,10 @@ mptctl_eventquery (unsigned long arg)
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 static int
-mptctl_eventenable (unsigned long arg)
+mptctl_eventenable (MPT_ADAPTER *ioc, unsigned long arg)
 {
 	struct mpt_ioctl_eventenable __user *uarg = (void __user *) arg;
 	struct mpt_ioctl_eventenable	 karg;
-	MPT_ADAPTER *ioc;
-	int iocnum;
 
 	if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventenable))) {
 		printk(KERN_ERR MYNAM "%s@%d::mptctl_eventenable - "
@@ -1628,13 +1572,6 @@ mptctl_eventenable (unsigned long arg)
 		return -EFAULT;
 	}
 
-	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
-	    (ioc == NULL)) {
-		printk(KERN_DEBUG MYNAM "%s::mptctl_eventenable() @%d - ioc%d not found!\n",
-				__FILE__, __LINE__, iocnum);
-		return -ENODEV;
-	}
-
 	dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_eventenable called.\n",
 	    ioc->name));
 	if (ioc->events == NULL) {
@@ -1662,12 +1599,10 @@ mptctl_eventenable (unsigned long arg)
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 static int
-mptctl_eventreport (unsigned long arg)
+mptctl_eventreport (MPT_ADAPTER *ioc, unsigned long arg)
 {
 	struct mpt_ioctl_eventreport __user *uarg = (void __user *) arg;
 	struct mpt_ioctl_eventreport	 karg;
-	MPT_ADAPTER		 *ioc;
-	int			 iocnum;
 	int			 numBytes, maxEvents, max;
 
 	if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventreport))) {
@@ -1677,12 +1612,6 @@ mptctl_eventreport (unsigned long arg)
 		return -EFAULT;
 	}
 
-	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
-	    (ioc == NULL)) {
-		printk(KERN_DEBUG MYNAM "%s::mptctl_eventreport() @%d - ioc%d not found!\n",
-				__FILE__, __LINE__, iocnum);
-		return -ENODEV;
-	}
 	dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_eventreport called.\n",
 	    ioc->name));
 
@@ -1716,12 +1645,10 @@ mptctl_eventreport (unsigned long arg)
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 static int
-mptctl_replace_fw (unsigned long arg)
+mptctl_replace_fw (MPT_ADAPTER *ioc, unsigned long arg)
 {
 	struct mpt_ioctl_replace_fw __user *uarg = (void __user *) arg;
 	struct mpt_ioctl_replace_fw	 karg;
-	MPT_ADAPTER		 *ioc;
-	int			 iocnum;
 	int			 newFwSize;
 
 	if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_replace_fw))) {
@@ -1731,13 +1658,6 @@ mptctl_replace_fw (unsigned long arg)
 		return -EFAULT;
 	}
 
-	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
-	    (ioc == NULL)) {
-		printk(KERN_DEBUG MYNAM "%s::mptctl_replace_fw() @%d - ioc%d not found!\n",
-				__FILE__, __LINE__, iocnum);
-		return -ENODEV;
-	}
-
 	dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_replace_fw called.\n",
 	    ioc->name));
 	/* If caching FW, Free the old FW image
@@ -1789,12 +1709,10 @@ mptctl_replace_fw (unsigned long arg)
  *		-ENOMEM if memory allocation error
  */
 static int
-mptctl_mpt_command (unsigned long arg)
+mptctl_mpt_command (MPT_ADAPTER *ioc, unsigned long arg)
 {
 	struct mpt_ioctl_command __user *uarg = (void __user *) arg;
 	struct mpt_ioctl_command  karg;
-	MPT_ADAPTER	*ioc;
-	int		iocnum;
 	int		rc;
 
 
@@ -1805,14 +1723,7 @@ mptctl_mpt_command (unsigned long arg)
 		return -EFAULT;
 	}
 
-	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
-	    (ioc == NULL)) {
-		printk(KERN_DEBUG MYNAM "%s::mptctl_mpt_command() @%d - ioc%d not found!\n",
-				__FILE__, __LINE__, iocnum);
-		return -ENODEV;
-	}
-
-	rc = mptctl_do_mpt_command (karg, &uarg->MF);
+	rc = mptctl_do_mpt_command (ioc, karg, &uarg->MF);
 
 	return rc;
 }
@@ -1830,9 +1741,8 @@ mptctl_mpt_command (unsigned long arg)
  *		-EPERM if SCSI I/O and target is untagged
  */
 static int
-mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
+mptctl_do_mpt_command (MPT_ADAPTER *ioc, struct mpt_ioctl_command karg, void __user *mfPtr)
 {
-	MPT_ADAPTER	*ioc;
 	MPT_FRAME_HDR	*mf = NULL;
 	MPIHeader_t	*hdr;
 	char		*psge;
@@ -1841,7 +1751,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
 	dma_addr_t	dma_addr_in;
 	dma_addr_t	dma_addr_out;
 	int		sgSize = 0;	/* Num SG elements */
-	int		iocnum, flagsLength;
+	int		flagsLength;
 	int		sz, rc = 0;
 	int		msgContext;
 	u16		req_idx;
@@ -1856,13 +1766,6 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
 	bufIn.kptr = bufOut.kptr = NULL;
 	bufIn.len = bufOut.len = 0;
 
-	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
-	    (ioc == NULL)) {
-		printk(KERN_DEBUG MYNAM "%s::mptctl_do_mpt_command() @%d - ioc%d not found!\n",
-				__FILE__, __LINE__, iocnum);
-		return -ENODEV;
-	}
-
 	spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
 	if (ioc->ioc_reset_in_progress) {
 		spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
@@ -2418,17 +2321,15 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
  *		-ENOMEM if memory allocation error
  */
 static int
-mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
+mptctl_hp_hostinfo(MPT_ADAPTER *ioc, unsigned long arg, unsigned int data_size)
 {
 	hp_host_info_t	__user *uarg = (void __user *) arg;
-	MPT_ADAPTER		*ioc;
 	struct pci_dev		*pdev;
 	char                    *pbuf=NULL;
 	dma_addr_t		buf_dma;
 	hp_host_info_t		karg;
 	CONFIGPARMS		cfg;
 	ConfigPageHeader_t	hdr;
-	int			iocnum;
 	int			rc, cim_rev;
 	ToolboxIstwiReadWriteRequest_t	*IstwiRWRequest;
 	MPT_FRAME_HDR		*mf = NULL;
@@ -2452,12 +2353,6 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
 		return -EFAULT;
 	}
 
-	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
-	    (ioc == NULL)) {
-		printk(KERN_DEBUG MYNAM "%s::mptctl_hp_hostinfo() @%d - ioc%d not found!\n",
-				__FILE__, __LINE__, iocnum);
-		return -ENODEV;
-	}
 	dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": mptctl_hp_hostinfo called.\n",
 	    ioc->name));
 
@@ -2670,15 +2565,13 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
  *		-ENOMEM if memory allocation error
  */
 static int
-mptctl_hp_targetinfo(unsigned long arg)
+mptctl_hp_targetinfo(MPT_ADAPTER *ioc, unsigned long arg)
 {
 	hp_target_info_t __user *uarg = (void __user *) arg;
 	SCSIDevicePage0_t	*pg0_alloc;
 	SCSIDevicePage3_t	*pg3_alloc;
-	MPT_ADAPTER		*ioc;
 	MPT_SCSI_HOST 		*hd = NULL;
 	hp_target_info_t	karg;
-	int			iocnum;
 	int			data_sz;
 	dma_addr_t		page_dma;
 	CONFIGPARMS	 	cfg;
@@ -2692,12 +2585,8 @@ mptctl_hp_targetinfo(unsigned long arg)
 		return -EFAULT;
 	}
 
-	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
-		(ioc == NULL)) {
-		printk(KERN_DEBUG MYNAM "%s::mptctl_hp_targetinfo() @%d - ioc%d not found!\n",
-				__FILE__, __LINE__, iocnum);
-		return -ENODEV;
-	}
+	if (karg.hdr.id >= MPT_MAX_FC_DEVICES)
+		return -EINVAL;
 	dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_hp_targetinfo called.\n",
 	    ioc->name));
 
@@ -2863,7 +2752,7 @@ compat_mptfwxfer_ioctl(struct file *filp, unsigned int cmd,
 	kfw.fwlen = kfw32.fwlen;
 	kfw.bufp = compat_ptr(kfw32.bufp);
 
-	ret = mptctl_do_fw_download(kfw.iocnum, kfw.bufp, kfw.fwlen);
+	ret = mptctl_do_fw_download(iocp, kfw.bufp, kfw.fwlen);
 
 	mutex_unlock(&iocp->ioctl_cmds.mutex);
 
@@ -2917,7 +2806,7 @@ compat_mpt_command(struct file *filp, unsigned int cmd,
 
 	/* Pass new structure to do_mpt_command
 	 */
-	ret = mptctl_do_mpt_command (karg, &uarg->MF);
+	ret = mptctl_do_mpt_command (iocp, karg, &uarg->MF);
 
 	mutex_unlock(&iocp->ioctl_cmds.mutex);
 
diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c
index f0769ce11c4b..772fe3bfc348 100644
--- a/drivers/net/can/slcan.c
+++ b/drivers/net/can/slcan.c
@@ -620,6 +620,10 @@ static int slcan_open(struct tty_struct *tty)
 	sl->tty = NULL;
 	tty->disc_data = NULL;
 	clear_bit(SLF_INUSE, &sl->flags);
+	/* do not call free_netdev before rtnl_unlock */
+	rtnl_unlock();
+	slc_free_netdev(sl->dev);
+	return err;
 
 err_exit:
 	rtnl_unlock();
diff --git a/drivers/net/slip/slip.c b/drivers/net/slip/slip.c
index 65df455c056e..812fe19986e2 100644
--- a/drivers/net/slip/slip.c
+++ b/drivers/net/slip/slip.c
@@ -867,6 +867,10 @@ static int slip_open(struct tty_struct *tty)
 	sl->tty = NULL;
 	tty->disc_data = NULL;
 	clear_bit(SLF_INUSE, &sl->flags);
+	/* do not call free_netdev before rtnl_unlock */
+	rtnl_unlock();
+	sl_free_netdev(sl->dev);
+	return err;
 
 err_exit:
 	rtnl_unlock();
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c
index b73af01c84d5..362b49c8b878 100644
--- a/drivers/net/wireless/mwifiex/scan.c
+++ b/drivers/net/wireless/mwifiex/scan.c
@@ -2267,6 +2267,13 @@ mwifiex_cmd_append_vsie_tlv(struct mwifiex_private *priv,
 			vs_param_set->header.len =
 				cpu_to_le16((((u16) priv->vs_ie[id].ie[1])
 				& 0x00FF) + 2);
+			if (le16_to_cpu(vs_param_set->header.len) >
+				MWIFIEX_MAX_VSIE_LEN) {
+				dev_info(priv->adapter->dev,
+					 "Invalid param length!\n");
+				break;
+			}
+
 			memcpy(vs_param_set->ie, priv->vs_ie[id].ie,
 			       le16_to_cpu(vs_param_set->header.len));
 			*buffer += le16_to_cpu(vs_param_set->header.len) +
diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c
index 67cefd06b7b0..00b2cb7eb60b 100644
--- a/drivers/net/wireless/mwifiex/wmm.c
+++ b/drivers/net/wireless/mwifiex/wmm.c
@@ -791,6 +791,10 @@ int mwifiex_ret_wmm_get_status(struct mwifiex_private *priv,
 				wmm_param_ie->qos_info_bitmap &
 				IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK);
 
+			if (wmm_param_ie->vend_hdr.len + 2 >
+				sizeof(struct ieee_types_wmm_parameter))
+				break;
+
 			memcpy((u8 *) &priv->curr_bss_params.bss_descriptor.
 			       wmm_ie, wmm_param_ie,
 			       wmm_param_ie->vend_hdr.len + 2);
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 2cb688ba1d2b..d8d81515789d 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -51,8 +51,10 @@ static int sg_version_num = 30534;	/* 2 digits for each component */
 #include <linux/delay.h>
 #include <linux/blktrace_api.h>
 #include <linux/mutex.h>
+#include <linux/atomic.h>
 #include <linux/ratelimit.h>
 #include <linux/cred.h> /* for sg_check_file_access() */
+#include <linux/sizes.h>
 
 #include "scsi.h"
 #include <scsi/scsi_dbg.h>
@@ -103,18 +105,16 @@ static int scatter_elem_sz_prev = SG_SCATTER_SZ;
 
 #define SG_SECTOR_SZ 512
 
-static int sg_add(struct device *, struct class_interface *);
-static void sg_remove(struct device *, struct class_interface *);
-
-static DEFINE_SPINLOCK(sg_open_exclusive_lock);
+static int sg_add_device(struct device *, struct class_interface *);
+static void sg_remove_device(struct device *, struct class_interface *);
 
 static DEFINE_IDR(sg_index_idr);
 static DEFINE_RWLOCK(sg_index_lock);	/* Also used to lock
 							   file descriptor list for device */
 
 static struct class_interface sg_interface = {
-	.add_dev	= sg_add,
-	.remove_dev	= sg_remove,
+	.add_dev        = sg_add_device,
+	.remove_dev     = sg_remove_device,
 };
 
 typedef struct sg_scatter_hold { /* holding area for scsi scatter gather info */
@@ -131,7 +131,7 @@ struct sg_device;		/* forward declarations */
 struct sg_fd;
 
 typedef struct sg_request {	/* SG_MAX_QUEUE requests outstanding per file */
-	struct sg_request *nextrp;	/* NULL -> tail request (slist) */
+	struct list_head entry;	/* list entry */
 	struct sg_fd *parentfp;	/* NULL -> not in use */
 	Sg_scatter_hold data;	/* hold buffer, perhaps scatter list */
 	sg_io_hdr_t header;	/* scsi command+info, see <scsi/sg.h> */
@@ -147,38 +147,38 @@ typedef struct sg_request {	/* SG_MAX_QUEUE requests outstanding per file */
 } Sg_request;
 
 typedef struct sg_fd {		/* holds the state of a file descriptor */
-	/* sfd_siblings is protected by sg_index_lock */
-	struct list_head sfd_siblings;
+	struct list_head sfd_siblings;  /* protected by device's sfd_lock */
 	struct sg_device *parentdp;	/* owning device */
 	wait_queue_head_t read_wait;	/* queue read until command done */
 	rwlock_t rq_list_lock;	/* protect access to list in req_arr */
+	struct mutex f_mutex;	/* protect against changes in this fd */
 	int timeout;		/* defaults to SG_DEFAULT_TIMEOUT      */
 	int timeout_user;	/* defaults to SG_DEFAULT_TIMEOUT_USER */
 	Sg_scatter_hold reserve;	/* buffer held for this file descriptor */
-	unsigned save_scat_len;	/* original length of trunc. scat. element */
-	Sg_request *headrp;	/* head of request slist, NULL->empty */
+	struct list_head rq_list; /* head of request list */
 	struct fasync_struct *async_qp;	/* used by asynchronous notification */
 	Sg_request req_arr[SG_MAX_QUEUE];	/* used as singly-linked list */
-	char low_dma;		/* as in parent but possibly overridden to 1 */
 	char force_packid;	/* 1 -> pack_id input to read(), 0 -> ignored */
 	char cmd_q;		/* 1 -> allow command queuing, 0 -> don't */
-	char next_cmd_len;	/* 0 -> automatic (def), >0 -> use on next write() */
+	unsigned char next_cmd_len; /* 0: automatic, >0: use on next write() */
 	char keep_orphan;	/* 0 -> drop orphan (def), 1 -> keep for read() */
 	char mmap_called;	/* 0 -> mmap() never called on this fd */
+	char res_in_use;	/* 1 -> 'reserve' array in use */
 	struct kref f_ref;
 	struct execute_work ew;
 } Sg_fd;
 
 typedef struct sg_device { /* holds the state of each scsi generic device */
 	struct scsi_device *device;
-	wait_queue_head_t o_excl_wait;	/* queue open() when O_EXCL in use */
+	wait_queue_head_t open_wait;    /* queue open() when O_EXCL present */
+	struct mutex open_rel_lock;     /* held when in open() or release() */
 	int sg_tablesize;	/* adapter's max scatter-gather table size */
 	u32 index;		/* device index number */
-	/* sfds is protected by sg_index_lock */
 	struct list_head sfds;
-	volatile char detached;	/* 0->attached, 1->detached pending removal */
-	/* exclude protected by sg_open_exclusive_lock */
-	char exclude;		/* opened for exclusive access */
+	rwlock_t sfd_lock;      /* protect access to sfd list */
+	atomic_t detaching;     /* 0->device usable, 1->device detaching */
+	bool exclude;		/* 1->open(O_EXCL) succeeded and is active */
+	int open_cnt;		/* count of opens (perhaps < num(sfds) ) */
 	char sgdebug;		/* 0->off, 1->sense, 9->dump dev, 10-> all devs */
 	struct gendisk *disk;
 	struct cdev * cdev;	/* char_dev [sysfs: /sys/cdev/major/sg<n>] */
@@ -207,9 +207,8 @@ static void sg_remove_sfp(struct kref *);
 static Sg_request *sg_get_rq_mark(Sg_fd * sfp, int pack_id);
 static Sg_request *sg_add_request(Sg_fd * sfp);
 static int sg_remove_request(Sg_fd * sfp, Sg_request * srp);
-static int sg_res_in_use(Sg_fd * sfp);
 static Sg_device *sg_get_dev(int dev);
-static void sg_put_dev(Sg_device *sdp);
+static void sg_device_destroy(struct kref *kref);
 
 #define SZ_SG_HEADER sizeof(struct sg_header)
 #define SZ_SG_IO_HDR sizeof(sg_io_hdr_t)
@@ -253,38 +252,43 @@ static int sg_allow_access(struct file *filp, unsigned char *cmd)
 	return blk_verify_command(cmd, filp->f_mode & FMODE_WRITE);
 }
 
-static int get_exclude(Sg_device *sdp)
-{
-	unsigned long flags;
-	int ret;
-
-	spin_lock_irqsave(&sg_open_exclusive_lock, flags);
-	ret = sdp->exclude;
-	spin_unlock_irqrestore(&sg_open_exclusive_lock, flags);
-	return ret;
-}
-
-static int set_exclude(Sg_device *sdp, char val)
+static int
+open_wait(Sg_device *sdp, int flags)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&sg_open_exclusive_lock, flags);
-	sdp->exclude = val;
-	spin_unlock_irqrestore(&sg_open_exclusive_lock, flags);
-	return val;
-}
+	int retval = 0;
 
-static int sfds_list_empty(Sg_device *sdp)
-{
-	unsigned long flags;
-	int ret;
+	if (flags & O_EXCL) {
+		while (sdp->open_cnt > 0) {
+			mutex_unlock(&sdp->open_rel_lock);
+			retval = wait_event_interruptible(sdp->open_wait,
+					(atomic_read(&sdp->detaching) ||
+					 !sdp->open_cnt));
+			mutex_lock(&sdp->open_rel_lock);
+
+			if (retval) /* -ERESTARTSYS */
+				return retval;
+			if (atomic_read(&sdp->detaching))
+				return -ENODEV;
+		}
+	} else {
+		while (sdp->exclude) {
+			mutex_unlock(&sdp->open_rel_lock);
+			retval = wait_event_interruptible(sdp->open_wait,
+					(atomic_read(&sdp->detaching) ||
+					 !sdp->exclude));
+			mutex_lock(&sdp->open_rel_lock);
+
+			if (retval) /* -ERESTARTSYS */
+				return retval;
+			if (atomic_read(&sdp->detaching))
+				return -ENODEV;
+		}
+	}
 
-	read_lock_irqsave(&sg_index_lock, flags);
-	ret = list_empty(&sdp->sfds);
-	read_unlock_irqrestore(&sg_index_lock, flags);
-	return ret;
+	return retval;
 }
 
+/* Returns 0 on success, else a negated errno value */
 static int
 sg_open(struct inode *inode, struct file *filp)
 {
@@ -293,17 +297,15 @@ sg_open(struct inode *inode, struct file *filp)
 	struct request_queue *q;
 	Sg_device *sdp;
 	Sg_fd *sfp;
-	int res;
 	int retval;
 
 	nonseekable_open(inode, filp);
 	SCSI_LOG_TIMEOUT(3, printk("sg_open: dev=%d, flags=0x%x\n", dev, flags));
+	if ((flags & O_EXCL) && (O_RDONLY == (flags & O_ACCMODE)))
+		return -EPERM; /* Can't lock it with read only access */
 	sdp = sg_get_dev(dev);
-	if (IS_ERR(sdp)) {
-		retval = PTR_ERR(sdp);
-		sdp = NULL;
-		goto sg_put;
-	}
+	if (IS_ERR(sdp))
+		return PTR_ERR(sdp);
 
 	/* This driver's module count bumped by fops_get in <linux/fs.h> */
 	/* Prevent the device driver from vanishing while we sleep */
@@ -315,6 +317,9 @@ sg_open(struct inode *inode, struct file *filp)
 	if (retval)
 		goto sdp_put;
 
+	/* scsi_block_when_processing_errors() may block so bypass
+	 * check if O_NONBLOCK. Permits SCSI commands to be issued
+	 * during error recovery. Tread carefully. */
 	if (!((flags & O_NONBLOCK) ||
 	      scsi_block_when_processing_errors(sdp->device))) {
 		retval = -ENXIO;
@@ -322,65 +327,65 @@ sg_open(struct inode *inode, struct file *filp)
 		goto error_out;
 	}
 
-	if (flags & O_EXCL) {
-		if (O_RDONLY == (flags & O_ACCMODE)) {
-			retval = -EPERM; /* Can't lock it with read only access */
-			goto error_out;
-		}
-		if (!sfds_list_empty(sdp) && (flags & O_NONBLOCK)) {
-			retval = -EBUSY;
-			goto error_out;
-		}
-		res = wait_event_interruptible(sdp->o_excl_wait,
-					   ((!sfds_list_empty(sdp) || get_exclude(sdp)) ? 0 : set_exclude(sdp, 1)));
-		if (res) {
-			retval = res;	/* -ERESTARTSYS because signal hit process */
-			goto error_out;
-		}
-	} else if (get_exclude(sdp)) {	/* some other fd has an exclusive lock on dev */
-		if (flags & O_NONBLOCK) {
-			retval = -EBUSY;
-			goto error_out;
-		}
-		res = wait_event_interruptible(sdp->o_excl_wait, !get_exclude(sdp));
-		if (res) {
-			retval = res;	/* -ERESTARTSYS because signal hit process */
-			goto error_out;
+	mutex_lock(&sdp->open_rel_lock);
+	if (flags & O_NONBLOCK) {
+		if (flags & O_EXCL) {
+			if (sdp->open_cnt > 0) {
+				retval = -EBUSY;
+				goto error_mutex_locked;
+			}
+		} else {
+			if (sdp->exclude) {
+				retval = -EBUSY;
+				goto error_mutex_locked;
+			}
 		}
+	} else {
+		retval = open_wait(sdp, flags);
+		if (retval) /* -ERESTARTSYS or -ENODEV */
+			goto error_mutex_locked;
 	}
-	if (sdp->detached) {
-		retval = -ENODEV;
-		goto error_out;
-	}
-	if (sfds_list_empty(sdp)) {	/* no existing opens on this device */
+
+	/* N.B. at this point we are holding the open_rel_lock */
+	if (flags & O_EXCL)
+		sdp->exclude = true;
+
+	if (sdp->open_cnt < 1) {  /* no existing opens */
 		sdp->sgdebug = 0;
 		q = sdp->device->request_queue;
 		sdp->sg_tablesize = queue_max_segments(q);
 	}
-	if ((sfp = sg_add_sfp(sdp, dev)))
-		filp->private_data = sfp;
-	else {
-		if (flags & O_EXCL) {
-			set_exclude(sdp, 0);	/* undo if error */
-			wake_up_interruptible(&sdp->o_excl_wait);
-		}
-		retval = -ENOMEM;
-		goto error_out;
+	sfp = sg_add_sfp(sdp, dev);
+	if (IS_ERR(sfp)) {
+		retval = PTR_ERR(sfp);
+		goto out_undo;
 	}
+
+	filp->private_data = sfp;
+	sdp->open_cnt++;
+	mutex_unlock(&sdp->open_rel_lock);
+
 	retval = 0;
-error_out:
-	if (retval) {
-		scsi_autopm_put_device(sdp->device);
-sdp_put:
-		scsi_device_put(sdp->device);
-	}
 sg_put:
-	if (sdp)
-		sg_put_dev(sdp);
+	kref_put(&sdp->d_ref, sg_device_destroy);
 	return retval;
+
+out_undo:
+	if (flags & O_EXCL) {
+		sdp->exclude = false;   /* undo if error */
+		wake_up_interruptible(&sdp->open_wait);
+	}
+error_mutex_locked:
+	mutex_unlock(&sdp->open_rel_lock);
+error_out:
+	scsi_autopm_put_device(sdp->device);
+sdp_put:
+	scsi_device_put(sdp->device);
+	goto sg_put;
 }
 
-/* Following function was formerly called 'sg_close' */
+/* Release resources associated with a successful sg_open()
+ * Returns 0 on success, else a negated errno value */
 static int
 sg_release(struct inode *inode, struct file *filp)
 {
@@ -391,11 +396,20 @@ sg_release(struct inode *inode, struct file *filp)
 		return -ENXIO;
 	SCSI_LOG_TIMEOUT(3, printk("sg_release: %s\n", sdp->disk->disk_name));
 
-	set_exclude(sdp, 0);
-	wake_up_interruptible(&sdp->o_excl_wait);
-
+	mutex_lock(&sdp->open_rel_lock);
 	scsi_autopm_put_device(sdp->device);
 	kref_put(&sfp->f_ref, sg_remove_sfp);
+	sdp->open_cnt--;
+
+	/* possibly many open()s waiting on exlude clearing, start many;
+	 * only open(O_EXCL)s wait on 0==open_cnt so only start one */
+	if (sdp->exclude) {
+		sdp->exclude = false;
+		wake_up_interruptible_all(&sdp->open_wait);
+	} else if (0 == sdp->open_cnt) {
+		wake_up_interruptible(&sdp->open_wait);
+	}
+	mutex_unlock(&sdp->open_rel_lock);
 	return 0;
 }
 
@@ -455,7 +469,7 @@ sg_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos)
 	}
 	srp = sg_get_rq_mark(sfp, req_pack_id);
 	if (!srp) {		/* now wait on packet to arrive */
-		if (sdp->detached) {
+		if (atomic_read(&sdp->detaching)) {
 			retval = -ENODEV;
 			goto free_old_hdr;
 		}
@@ -464,9 +478,9 @@ sg_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos)
 			goto free_old_hdr;
 		}
 		retval = wait_event_interruptible(sfp->read_wait,
-			(sdp->detached ||
+			(atomic_read(&sdp->detaching) ||
 			(srp = sg_get_rq_mark(sfp, req_pack_id))));
-		if (sdp->detached) {
+		if (atomic_read(&sdp->detaching)) {
 			retval = -ENODEV;
 			goto free_old_hdr;
 		}
@@ -548,6 +562,7 @@ sg_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos)
 	} else
 		count = (old_hdr->result == 0) ? 0 : -EIO;
 	sg_finish_rem_req(srp);
+	sg_remove_request(sfp, srp);
 	retval = count;
 free_old_hdr:
 	kfree(old_hdr);
@@ -588,6 +603,7 @@ sg_new_read(Sg_fd * sfp, char __user *buf, size_t count, Sg_request * srp)
 	}
 err_out:
 	err2 = sg_finish_rem_req(srp);
+	sg_remove_request(sfp, srp);
 	return err ? : err2 ? : count;
 }
 
@@ -613,7 +629,7 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
 		return -ENXIO;
 	SCSI_LOG_TIMEOUT(3, printk("sg_write: %s, count=%d\n",
 				   sdp->disk->disk_name, (int) count));
-	if (sdp->detached)
+	if (atomic_read(&sdp->detaching))
 		return -ENODEV;
 	if (!((filp->f_flags & O_NONBLOCK) ||
 	      scsi_block_when_processing_errors(sdp->device)))
@@ -638,13 +654,8 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
 	}
 	buf += SZ_SG_HEADER;
 	__get_user(opcode, buf);
+	mutex_lock(&sfp->f_mutex);
 	if (sfp->next_cmd_len > 0) {
-		if (sfp->next_cmd_len > MAX_COMMAND_SIZE) {
-			SCSI_LOG_TIMEOUT(1, printk("sg_write: command length too long\n"));
-			sfp->next_cmd_len = 0;
-			sg_remove_request(sfp, srp);
-			return -EIO;
-		}
 		cmd_size = sfp->next_cmd_len;
 		sfp->next_cmd_len = 0;	/* reset so only this write() effected */
 	} else {
@@ -652,6 +663,7 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
 		if ((opcode >= 0xc0) && old_hdr.twelve_byte)
 			cmd_size = 12;
 	}
+	mutex_unlock(&sfp->f_mutex);
 	SCSI_LOG_TIMEOUT(4, printk(
 		"sg_write:   scsi opcode=0x%02x, cmd_size=%d\n", (int) opcode, cmd_size));
 /* Determine buffer size.  */
@@ -684,26 +696,24 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
 	hp->flags = input_size;	/* structure abuse ... */
 	hp->pack_id = old_hdr.pack_id;
 	hp->usr_ptr = NULL;
-	if (__copy_from_user(cmnd, buf, cmd_size))
+	if (__copy_from_user(cmnd, buf, cmd_size)) {
+		sg_remove_request(sfp, srp);
 		return -EFAULT;
+	}
 	/*
 	 * SG_DXFER_TO_FROM_DEV is functionally equivalent to SG_DXFER_FROM_DEV,
 	 * but is is possible that the app intended SG_DXFER_TO_DEV, because there
 	 * is a non-zero input_size, so emit a warning.
 	 */
 	if (hp->dxfer_direction == SG_DXFER_TO_FROM_DEV) {
-		static char cmd[TASK_COMM_LEN];
-		if (strcmp(current->comm, cmd)) {
-			printk_ratelimited(KERN_WARNING
-					   "sg_write: data in/out %d/%d bytes "
-					   "for SCSI command 0x%x-- guessing "
-					   "data in;\n   program %s not setting "
-					   "count and/or reply_len properly\n",
-					   old_hdr.reply_len - (int)SZ_SG_HEADER,
-					   input_size, (unsigned int) cmnd[0],
-					   current->comm);
-			strcpy(cmd, current->comm);
-		}
+		printk_ratelimited(KERN_WARNING
+				   "sg_write: data in/out %d/%d bytes "
+				   "for SCSI command 0x%x-- guessing "
+				   "data in;\n   program %s not setting "
+				   "count and/or reply_len properly\n",
+				   old_hdr.reply_len - (int)SZ_SG_HEADER,
+				   input_size, (unsigned int) cmnd[0],
+				   current->comm);
 	}
 	k = sg_common_write(sfp, srp, cmnd, sfp->timeout, blocking);
 	return (k < 0) ? k : count;
@@ -750,7 +760,7 @@ sg_new_write(Sg_fd *sfp, struct file *file, const char __user *buf,
 			sg_remove_request(sfp, srp);
 			return -EINVAL;	/* either MMAP_IO or DIRECT_IO (not both) */
 		}
-		if (sg_res_in_use(sfp)) {
+		if (sfp->res_in_use) {
 			sg_remove_request(sfp, srp);
 			return -EBUSY;	/* reserve buffer already being used */
 		}
@@ -800,19 +810,26 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp,
 	SCSI_LOG_TIMEOUT(4, printk("sg_common_write:  scsi opcode=0x%02x, cmd_size=%d\n",
 			  (int) cmnd[0], (int) hp->cmd_len));
 
+	if (hp->dxfer_len >= SZ_256M) {
+		sg_remove_request(sfp, srp);
+		return -EINVAL;
+	}
+
 	k = sg_start_req(srp, cmnd);
 	if (k) {
 		SCSI_LOG_TIMEOUT(1, printk("sg_common_write: start_req err=%d\n", k));
 		sg_finish_rem_req(srp);
+		sg_remove_request(sfp, srp);
 		return k;	/* probably out of space --> ENOMEM */
 	}
-	if (sdp->detached) {
+	if (atomic_read(&sdp->detaching)) {
 		if (srp->bio) {
 			blk_end_request_all(srp->rq, -EIO);
 			srp->rq = NULL;
 		}
 
 		sg_finish_rem_req(srp);
+		sg_remove_request(sfp, srp);
 		return -ENODEV;
 	}
 
@@ -851,6 +868,48 @@ static int srp_done(Sg_fd *sfp, Sg_request *srp)
 	return ret;
 }
 
+static int max_sectors_bytes(struct request_queue *q)
+{
+	unsigned int max_sectors = queue_max_sectors(q);
+
+	max_sectors = min_t(unsigned int, max_sectors, INT_MAX >> 9);
+
+	return max_sectors << 9;
+}
+
+static void
+sg_fill_request_table(Sg_fd *sfp, sg_req_info_t *rinfo)
+{
+	Sg_request *srp;
+	int val;
+	unsigned int ms;
+
+	val = 0;
+	list_for_each_entry(srp, &sfp->rq_list, entry) {
+		if (val >= SG_MAX_QUEUE)
+			break;
+		rinfo[val].req_state = srp->done + 1;
+		rinfo[val].problem =
+			srp->header.masked_status &
+			srp->header.host_status &
+			srp->header.driver_status;
+		if (srp->done)
+			rinfo[val].duration =
+				srp->header.duration;
+		else {
+			ms = jiffies_to_msecs(jiffies);
+			rinfo[val].duration =
+				(ms > srp->header.duration) ?
+				(ms - srp->header.duration) : 0;
+		}
+		rinfo[val].orphan = srp->orphan;
+		rinfo[val].sg_io_owned = srp->sg_io_owned;
+		rinfo[val].pack_id = srp->header.pack_id;
+		rinfo[val].usr_ptr = srp->header.usr_ptr;
+		val++;
+	}
+}
+
 static long
 sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
 {
@@ -871,7 +930,7 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
 
 	switch (cmd_in) {
 	case SG_IO:
-		if (sdp->detached)
+		if (atomic_read(&sdp->detaching))
 			return -ENODEV;
 		if (!scsi_block_when_processing_errors(sdp->device))
 			return -ENXIO;
@@ -882,8 +941,8 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
 		if (result < 0)
 			return result;
 		result = wait_event_interruptible(sfp->read_wait,
-			(srp_done(sfp, srp) || sdp->detached));
-		if (sdp->detached)
+			(srp_done(sfp, srp) || atomic_read(&sdp->detaching)));
+		if (atomic_read(&sdp->detaching))
 			return -ENODEV;
 		write_lock_irq(&sfp->rq_list_lock);
 		if (srp->done) {
@@ -911,31 +970,21 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
 				/* strange ..., for backward compatibility */
 		return sfp->timeout_user;
 	case SG_SET_FORCE_LOW_DMA:
-		result = get_user(val, ip);
-		if (result)
-			return result;
-		if (val) {
-			sfp->low_dma = 1;
-			if ((0 == sfp->low_dma) && (0 == sg_res_in_use(sfp))) {
-				val = (int) sfp->reserve.bufflen;
-				sg_remove_scat(&sfp->reserve);
-				sg_build_reserve(sfp, val);
-			}
-		} else {
-			if (sdp->detached)
-				return -ENODEV;
-			sfp->low_dma = sdp->device->host->unchecked_isa_dma;
-		}
+		/*
+		 * N.B. This ioctl never worked properly, but failed to
+		 * return an error value. So returning '0' to keep compability
+		 * with legacy applications.
+		 */
 		return 0;
 	case SG_GET_LOW_DMA:
-		return put_user((int) sfp->low_dma, ip);
+		return put_user((int) sdp->device->host->unchecked_isa_dma, ip);
 	case SG_GET_SCSI_ID:
 		if (!access_ok(VERIFY_WRITE, p, sizeof (sg_scsi_id_t)))
 			return -EFAULT;
 		else {
 			sg_scsi_id_t __user *sg_idp = p;
 
-			if (sdp->detached)
+			if (atomic_read(&sdp->detaching))
 				return -ENODEV;
 			__put_user((int) sdp->device->host->host_no,
 				   &sg_idp->host_no);
@@ -962,7 +1011,7 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
 		if (!access_ok(VERIFY_WRITE, ip, sizeof (int)))
 			return -EFAULT;
 		read_lock_irqsave(&sfp->rq_list_lock, iflags);
-		for (srp = sfp->headrp; srp; srp = srp->nextrp) {
+		list_for_each_entry(srp, &sfp->rq_list, entry) {
 			if ((1 == srp->done) && (!srp->sg_io_owned)) {
 				read_unlock_irqrestore(&sfp->rq_list_lock,
 						       iflags);
@@ -975,7 +1024,8 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
 		return 0;
 	case SG_GET_NUM_WAITING:
 		read_lock_irqsave(&sfp->rq_list_lock, iflags);
-		for (val = 0, srp = sfp->headrp; srp; srp = srp->nextrp) {
+		val = 0;
+		list_for_each_entry(srp, &sfp->rq_list, entry) {
 			if ((1 == srp->done) && (!srp->sg_io_owned))
 				++val;
 		}
@@ -990,17 +1040,23 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
                 if (val < 0)
                         return -EINVAL;
 		val = min_t(int, val,
-			    queue_max_sectors(sdp->device->request_queue) * 512);
+			    max_sectors_bytes(sdp->device->request_queue));
+		mutex_lock(&sfp->f_mutex);
 		if (val != sfp->reserve.bufflen) {
-			if (sg_res_in_use(sfp) || sfp->mmap_called)
+			if (sfp->mmap_called ||
+			    sfp->res_in_use) {
+				mutex_unlock(&sfp->f_mutex);
 				return -EBUSY;
+			}
+
 			sg_remove_scat(&sfp->reserve);
 			sg_build_reserve(sfp, val);
 		}
+		mutex_unlock(&sfp->f_mutex);
 		return 0;
 	case SG_GET_RESERVED_SIZE:
 		val = min_t(int, sfp->reserve.bufflen,
-			    queue_max_sectors(sdp->device->request_queue) * 512);
+			    max_sectors_bytes(sdp->device->request_queue));
 		return put_user(val, ip);
 	case SG_SET_COMMAND_Q:
 		result = get_user(val, ip);
@@ -1022,6 +1078,8 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
 		result = get_user(val, ip);
 		if (result)
 			return result;
+		if (val > MAX_COMMAND_SIZE)
+			return -ENOMEM;
 		sfp->next_cmd_len = (val > 0) ? val : 0;
 		return 0;
 	case SG_GET_VERSION_NUM:
@@ -1035,53 +1093,26 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
 			return -EFAULT;
 		else {
 			sg_req_info_t *rinfo;
-			unsigned int ms;
 
-			rinfo = kmalloc(SZ_SG_REQ_INFO * SG_MAX_QUEUE,
-								GFP_KERNEL);
+			rinfo = kzalloc(SZ_SG_REQ_INFO * SG_MAX_QUEUE,
+					GFP_KERNEL);
 			if (!rinfo)
 				return -ENOMEM;
 			read_lock_irqsave(&sfp->rq_list_lock, iflags);
-			for (srp = sfp->headrp, val = 0; val < SG_MAX_QUEUE;
-			     ++val, srp = srp ? srp->nextrp : srp) {
-				memset(&rinfo[val], 0, SZ_SG_REQ_INFO);
-				if (srp) {
-					rinfo[val].req_state = srp->done + 1;
-					rinfo[val].problem =
-					    srp->header.masked_status & 
-					    srp->header.host_status & 
-					    srp->header.driver_status;
-					if (srp->done)
-						rinfo[val].duration =
-							srp->header.duration;
-					else {
-						ms = jiffies_to_msecs(jiffies);
-						rinfo[val].duration =
-						    (ms > srp->header.duration) ?
-						    (ms - srp->header.duration) : 0;
-					}
-					rinfo[val].orphan = srp->orphan;
-					rinfo[val].sg_io_owned =
-							srp->sg_io_owned;
-					rinfo[val].pack_id =
-							srp->header.pack_id;
-					rinfo[val].usr_ptr =
-							srp->header.usr_ptr;
-				}
-			}
+			sg_fill_request_table(sfp, rinfo);
 			read_unlock_irqrestore(&sfp->rq_list_lock, iflags);
-			result = __copy_to_user(p, rinfo, 
+			result = __copy_to_user(p, rinfo,
 						SZ_SG_REQ_INFO * SG_MAX_QUEUE);
 			result = result ? -EFAULT : 0;
 			kfree(rinfo);
 			return result;
 		}
 	case SG_EMULATED_HOST:
-		if (sdp->detached)
+		if (atomic_read(&sdp->detaching))
 			return -ENODEV;
 		return put_user(sdp->device->host->hostt->emulated, ip);
 	case SG_SCSI_RESET:
-		if (sdp->detached)
+		if (atomic_read(&sdp->detaching))
 			return -ENODEV;
 		if (filp->f_flags & O_NONBLOCK) {
 			if (scsi_host_in_recovery(sdp->device->host))
@@ -1114,7 +1145,7 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
 		return (scsi_reset_provider(sdp->device, val) ==
 			SUCCESS) ? 0 : -EIO;
 	case SCSI_IOCTL_SEND_COMMAND:
-		if (sdp->detached)
+		if (atomic_read(&sdp->detaching))
 			return -ENODEV;
 		if (read_only) {
 			unsigned char opcode = WRITE_6;
@@ -1136,11 +1167,11 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
 	case SCSI_IOCTL_GET_BUS_NUMBER:
 	case SCSI_IOCTL_PROBE_HOST:
 	case SG_GET_TRANSFORM:
-		if (sdp->detached)
+		if (atomic_read(&sdp->detaching))
 			return -ENODEV;
 		return scsi_ioctl(sdp->device, cmd_in, p);
 	case BLKSECTGET:
-		return put_user(queue_max_sectors(sdp->device->request_queue) * 512,
+		return put_user(max_sectors_bytes(sdp->device->request_queue),
 				ip);
 	case BLKTRACESETUP:
 		return blk_trace_setup(sdp->device->request_queue,
@@ -1202,7 +1233,7 @@ sg_poll(struct file *filp, poll_table * wait)
 		return POLLERR;
 	poll_wait(filp, &sfp->read_wait, wait);
 	read_lock_irqsave(&sfp->rq_list_lock, iflags);
-	for (srp = sfp->headrp; srp; srp = srp->nextrp) {
+	list_for_each_entry(srp, &sfp->rq_list, entry) {
 		/* if any read waiting, flag it */
 		if ((0 == res) && (1 == srp->done) && (!srp->sg_io_owned))
 			res = POLLIN | POLLRDNORM;
@@ -1210,7 +1241,7 @@ sg_poll(struct file *filp, poll_table * wait)
 	}
 	read_unlock_irqrestore(&sfp->rq_list_lock, iflags);
 
-	if (sdp->detached)
+	if (atomic_read(&sdp->detaching))
 		res |= POLLHUP;
 	else if (!sfp->cmd_q) {
 		if (0 == count)
@@ -1282,6 +1313,7 @@ sg_mmap(struct file *filp, struct vm_area_struct *vma)
 	unsigned long req_sz, len, sa;
 	Sg_scatter_hold *rsv_schp;
 	int k, length;
+	int ret = 0;
 
 	if ((!filp) || (!vma) || (!(sfp = (Sg_fd *) filp->private_data)))
 		return -ENXIO;
@@ -1291,8 +1323,11 @@ sg_mmap(struct file *filp, struct vm_area_struct *vma)
 	if (vma->vm_pgoff)
 		return -EINVAL;	/* want no offset */
 	rsv_schp = &sfp->reserve;
-	if (req_sz > rsv_schp->bufflen)
-		return -ENOMEM;	/* cannot map more than reserved buffer */
+	mutex_lock(&sfp->f_mutex);
+	if (req_sz > rsv_schp->bufflen) {
+		ret = -ENOMEM;	/* cannot map more than reserved buffer */
+		goto out;
+	}
 
 	sa = vma->vm_start;
 	length = 1 << (PAGE_SHIFT + rsv_schp->page_order);
@@ -1306,15 +1341,19 @@ sg_mmap(struct file *filp, struct vm_area_struct *vma)
 	vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP;
 	vma->vm_private_data = sfp;
 	vma->vm_ops = &sg_mmap_vm_ops;
-	return 0;
+out:
+	mutex_unlock(&sfp->f_mutex);
+	return ret;
 }
 
-static void sg_rq_end_io_usercontext(struct work_struct *work)
+static void
+sg_rq_end_io_usercontext(struct work_struct *work)
 {
 	struct sg_request *srp = container_of(work, struct sg_request, ew.work);
 	struct sg_fd *sfp = srp->parentfp;
 
 	sg_finish_rem_req(srp);
+	sg_remove_request(sfp, srp);
 	kref_put(&sfp->f_ref, sg_remove_sfp);
 }
 
@@ -1322,7 +1361,8 @@ static void sg_rq_end_io_usercontext(struct work_struct *work)
  * This function is a "bottom half" handler that is called by the mid
  * level when a command is completed (or has failed).
  */
-static void sg_rq_end_io(struct request *rq, int uptodate)
+static void
+sg_rq_end_io(struct request *rq, int uptodate)
 {
 	struct sg_request *srp = rq->end_io_data;
 	Sg_device *sdp;
@@ -1340,8 +1380,8 @@ static void sg_rq_end_io(struct request *rq, int uptodate)
 		return;
 
 	sdp = sfp->parentdp;
-	if (unlikely(sdp->detached))
-		printk(KERN_INFO "sg_rq_end_io: device detached\n");
+	if (unlikely(atomic_read(&sdp->detaching)))
+		pr_info("%s: device detaching\n", __func__);
 
 	sense = rq->sense;
 	result = rq->errors;
@@ -1364,7 +1404,7 @@ static void sg_rq_end_io(struct request *rq, int uptodate)
 		if ((sdp->sgdebug > 0) &&
 		    ((CHECK_CONDITION == srp->header.masked_status) ||
 		     (COMMAND_TERMINATED == srp->header.masked_status)))
-			__scsi_print_sense("sg_cmd_done", sense,
+			__scsi_print_sense(__func__, sense,
 					   SCSI_SENSE_BUFFERSIZE);
 
 		/* Following if statement is a patch supplied by Eric Youngdale */
@@ -1423,7 +1463,8 @@ static struct class *sg_sysfs_class;
 
 static int sg_sysfs_valid = 0;
 
-static Sg_device *sg_alloc(struct gendisk *disk, struct scsi_device *scsidp)
+static Sg_device *
+sg_alloc(struct gendisk *disk, struct scsi_device *scsidp)
 {
 	struct request_queue *q = scsidp->request_queue;
 	Sg_device *sdp;
@@ -1433,7 +1474,8 @@ static Sg_device *sg_alloc(struct gendisk *disk, struct scsi_device *scsidp)
 
 	sdp = kzalloc(sizeof(Sg_device), GFP_KERNEL);
 	if (!sdp) {
-		printk(KERN_WARNING "kmalloc Sg_device failure\n");
+		sdev_printk(KERN_WARNING, scsidp, "%s: kmalloc Sg_device "
+			    "failure\n", __func__);
 		return ERR_PTR(-ENOMEM);
 	}
 
@@ -1448,8 +1490,9 @@ static Sg_device *sg_alloc(struct gendisk *disk, struct scsi_device *scsidp)
 				    scsidp->type, SG_MAX_DEVS - 1);
 			error = -ENODEV;
 		} else {
-			printk(KERN_WARNING
-			       "idr allocation Sg_device failure: %d\n", error);
+			sdev_printk(KERN_WARNING, scsidp, "%s: idr "
+				    "allocation Sg_device failure: %d\n",
+				    __func__, error);
 		}
 		goto out_unlock;
 	}
@@ -1460,8 +1503,11 @@ static Sg_device *sg_alloc(struct gendisk *disk, struct scsi_device *scsidp)
 	disk->first_minor = k;
 	sdp->disk = disk;
 	sdp->device = scsidp;
+	mutex_init(&sdp->open_rel_lock);
 	INIT_LIST_HEAD(&sdp->sfds);
-	init_waitqueue_head(&sdp->o_excl_wait);
+	init_waitqueue_head(&sdp->open_wait);
+	atomic_set(&sdp->detaching, 0);
+	rwlock_init(&sdp->sfd_lock);
 	sdp->sg_tablesize = queue_max_segments(q);
 	sdp->index = k;
 	kref_init(&sdp->d_ref);
@@ -1479,7 +1525,7 @@ static Sg_device *sg_alloc(struct gendisk *disk, struct scsi_device *scsidp)
 }
 
 static int
-sg_add(struct device *cl_dev, struct class_interface *cl_intf)
+sg_add_device(struct device *cl_dev, struct class_interface *cl_intf)
 {
 	struct scsi_device *scsidp = to_scsi_device(cl_dev->parent);
 	struct gendisk *disk;
@@ -1490,7 +1536,7 @@ sg_add(struct device *cl_dev, struct class_interface *cl_intf)
 
 	disk = alloc_disk(1);
 	if (!disk) {
-		printk(KERN_WARNING "alloc_disk failed\n");
+		pr_warn("%s: alloc_disk failed\n", __func__);
 		return -ENOMEM;
 	}
 	disk->major = SCSI_GENERIC_MAJOR;
@@ -1498,7 +1544,7 @@ sg_add(struct device *cl_dev, struct class_interface *cl_intf)
 	error = -ENOMEM;
 	cdev = cdev_alloc();
 	if (!cdev) {
-		printk(KERN_WARNING "cdev_alloc failed\n");
+		pr_warn("%s: cdev_alloc failed\n", __func__);
 		goto out;
 	}
 	cdev->owner = THIS_MODULE;
@@ -1506,7 +1552,7 @@ sg_add(struct device *cl_dev, struct class_interface *cl_intf)
 
 	sdp = sg_alloc(disk, scsidp);
 	if (IS_ERR(sdp)) {
-		printk(KERN_WARNING "sg_alloc failed\n");
+		pr_warn("%s: sg_alloc failed\n", __func__);
 		error = PTR_ERR(sdp);
 		goto out;
 	}
@@ -1524,22 +1570,20 @@ sg_add(struct device *cl_dev, struct class_interface *cl_intf)
 						      sdp->index),
 						sdp, "%s", disk->disk_name);
 		if (IS_ERR(sg_class_member)) {
-			printk(KERN_ERR "sg_add: "
-			       "device_create failed\n");
+			pr_err("%s: device_create failed\n", __func__);
 			error = PTR_ERR(sg_class_member);
 			goto cdev_add_err;
 		}
 		error = sysfs_create_link(&scsidp->sdev_gendev.kobj,
 					  &sg_class_member->kobj, "generic");
 		if (error)
-			printk(KERN_ERR "sg_add: unable to make symlink "
-					"'generic' back to sg%d\n", sdp->index);
+			pr_err("%s: unable to make symlink 'generic' back "
+			       "to sg%d\n", __func__, sdp->index);
 	} else
-		printk(KERN_WARNING "sg_add: sg_sys Invalid\n");
+		pr_warn("%s: sg_sys Invalid\n", __func__);
 
-	sdev_printk(KERN_NOTICE, scsidp,
-		    "Attached scsi generic sg%d type %d\n", sdp->index,
-		    scsidp->type);
+	sdev_printk(KERN_NOTICE, scsidp, "Attached scsi generic sg%d "
+		    "type %d\n", sdp->index, scsidp->type);
 
 	dev_set_drvdata(cl_dev, sdp);
 
@@ -1558,7 +1602,8 @@ sg_add(struct device *cl_dev, struct class_interface *cl_intf)
 	return error;
 }
 
-static void sg_device_destroy(struct kref *kref)
+static void
+sg_device_destroy(struct kref *kref)
 {
 	struct sg_device *sdp = container_of(kref, struct sg_device, d_ref);
 	unsigned long flags;
@@ -1580,33 +1625,39 @@ static void sg_device_destroy(struct kref *kref)
 	kfree(sdp);
 }
 
-static void sg_remove(struct device *cl_dev, struct class_interface *cl_intf)
+static void
+sg_remove_device(struct device *cl_dev, struct class_interface *cl_intf)
 {
 	struct scsi_device *scsidp = to_scsi_device(cl_dev->parent);
 	Sg_device *sdp = dev_get_drvdata(cl_dev);
 	unsigned long iflags;
 	Sg_fd *sfp;
+	int val;
 
-	if (!sdp || sdp->detached)
+	if (!sdp)
 		return;
+	/* want sdp->detaching non-zero as soon as possible */
+	val = atomic_inc_return(&sdp->detaching);
+	if (val > 1)
+		return; /* only want to do following once per device */
 
-	SCSI_LOG_TIMEOUT(3, printk("sg_remove: %s\n", sdp->disk->disk_name));
+	SCSI_LOG_TIMEOUT(3, printk("%s: %s\n", __func__,
+			 sdp->disk->disk_name));
 
-	/* Need a write lock to set sdp->detached. */
-	write_lock_irqsave(&sg_index_lock, iflags);
-	sdp->detached = 1;
+	read_lock_irqsave(&sdp->sfd_lock, iflags);
 	list_for_each_entry(sfp, &sdp->sfds, sfd_siblings) {
-		wake_up_interruptible(&sfp->read_wait);
+		wake_up_interruptible_all(&sfp->read_wait);
 		kill_fasync(&sfp->async_qp, SIGPOLL, POLL_HUP);
 	}
-	write_unlock_irqrestore(&sg_index_lock, iflags);
+	wake_up_interruptible_all(&sdp->open_wait);
+	read_unlock_irqrestore(&sdp->sfd_lock, iflags);
 
 	sysfs_remove_link(&scsidp->sdev_gendev.kobj, "generic");
 	device_destroy(sg_sysfs_class, MKDEV(SCSI_GENERIC_MAJOR, sdp->index));
 	cdev_del(sdp->cdev);
 	sdp->cdev = NULL;
 
-	sg_put_dev(sdp);
+	kref_put(&sdp->d_ref, sg_device_destroy);
 }
 
 module_param_named(scatter_elem_sz, scatter_elem_sz, int, S_IRUGO | S_IWUSR);
@@ -1676,7 +1727,8 @@ exit_sg(void)
 	idr_destroy(&sg_index_idr);
 }
 
-static int sg_start_req(Sg_request *srp, unsigned char *cmd)
+static int
+sg_start_req(Sg_request *srp, unsigned char *cmd)
 {
 	int res;
 	struct request *rq;
@@ -1719,13 +1771,25 @@ static int sg_start_req(Sg_request *srp, unsigned char *cmd)
 		md = &map_data;
 
 	if (md) {
-		if (!sg_res_in_use(sfp) && dxfer_len <= rsv_schp->bufflen)
+		mutex_lock(&sfp->f_mutex);
+		if (dxfer_len <= rsv_schp->bufflen &&
+		    !sfp->res_in_use) {
+			sfp->res_in_use = 1;
 			sg_link_reserve(sfp, srp, dxfer_len);
-		else {
+		} else if (hp->flags & SG_FLAG_MMAP_IO) {
+			res = -EBUSY; /* sfp->res_in_use == 1 */
+			if (dxfer_len > rsv_schp->bufflen)
+				res = -ENOMEM;
+			mutex_unlock(&sfp->f_mutex);
+			return res;
+		} else {
 			res = sg_build_indirect(req_schp, sfp, dxfer_len);
-			if (res)
+			if (res) {
+				mutex_unlock(&sfp->f_mutex);
 				return res;
+			}
 		}
+		mutex_unlock(&sfp->f_mutex);
 
 		md->pages = req_schp->pages;
 		md->page_order = req_schp->page_order;
@@ -1778,7 +1842,8 @@ static int sg_start_req(Sg_request *srp, unsigned char *cmd)
 	return res;
 }
 
-static int sg_finish_rem_req(Sg_request * srp)
+static int
+sg_finish_rem_req(Sg_request *srp)
 {
 	int ret = 0;
 
@@ -1798,8 +1863,6 @@ static int sg_finish_rem_req(Sg_request * srp)
 	else
 		sg_remove_scat(req_schp);
 
-	sg_remove_request(sfp, srp);
-
 	return ret;
 }
 
@@ -1823,6 +1886,7 @@ sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size)
 	int sg_tablesize = sfp->parentdp->sg_tablesize;
 	int blk_size = buff_size, order;
 	gfp_t gfp_mask = GFP_ATOMIC | __GFP_COMP | __GFP_NOWARN;
+	struct sg_device *sdp = sfp->parentdp;
 
 	if (blk_size < 0)
 		return -EFAULT;
@@ -1847,7 +1911,7 @@ sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size)
 			scatter_elem_sz_prev = num;
 	}
 
-	if (sfp->low_dma)
+	if (sdp->device->host->unchecked_isa_dma)
 		gfp_mask |= GFP_DMA;
 
 	if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
@@ -2008,8 +2072,9 @@ sg_unlink_reserve(Sg_fd * sfp, Sg_request * srp)
 	req_schp->pages = NULL;
 	req_schp->page_order = 0;
 	req_schp->sglist_len = 0;
-	sfp->save_scat_len = 0;
 	srp->res_used = 0;
+	/* Called without mutex lock to avoid deadlock */
+	sfp->res_in_use = 0;
 }
 
 static Sg_request *
@@ -2019,16 +2084,17 @@ sg_get_rq_mark(Sg_fd * sfp, int pack_id)
 	unsigned long iflags;
 
 	write_lock_irqsave(&sfp->rq_list_lock, iflags);
-	for (resp = sfp->headrp; resp; resp = resp->nextrp) {
+	list_for_each_entry(resp, &sfp->rq_list, entry) {
 		/* look for requests that are ready + not SG_IO owned */
 		if ((1 == resp->done) && (!resp->sg_io_owned) &&
 		    ((-1 == pack_id) || (resp->header.pack_id == pack_id))) {
 			resp->done = 2;	/* guard against other readers */
-			break;
+			write_unlock_irqrestore(&sfp->rq_list_lock, iflags);
+			return resp;
 		}
 	}
 	write_unlock_irqrestore(&sfp->rq_list_lock, iflags);
-	return resp;
+	return NULL;
 }
 
 /* always adds to end of list */
@@ -2037,70 +2103,45 @@ sg_add_request(Sg_fd * sfp)
 {
 	int k;
 	unsigned long iflags;
-	Sg_request *resp;
 	Sg_request *rp = sfp->req_arr;
 
 	write_lock_irqsave(&sfp->rq_list_lock, iflags);
-	resp = sfp->headrp;
-	if (!resp) {
-		memset(rp, 0, sizeof (Sg_request));
-		rp->parentfp = sfp;
-		resp = rp;
-		sfp->headrp = resp;
-	} else {
-		if (0 == sfp->cmd_q)
-			resp = NULL;	/* command queuing disallowed */
-		else {
-			for (k = 0; k < SG_MAX_QUEUE; ++k, ++rp) {
-				if (!rp->parentfp)
-					break;
-			}
-			if (k < SG_MAX_QUEUE) {
-				memset(rp, 0, sizeof (Sg_request));
-				rp->parentfp = sfp;
-				while (resp->nextrp)
-					resp = resp->nextrp;
-				resp->nextrp = rp;
-				resp = rp;
-			} else
-				resp = NULL;
+	if (!list_empty(&sfp->rq_list)) {
+		if (!sfp->cmd_q)
+			goto out_unlock;
+
+		for (k = 0; k < SG_MAX_QUEUE; ++k, ++rp) {
+			if (!rp->parentfp)
+				break;
 		}
+		if (k >= SG_MAX_QUEUE)
+			goto out_unlock;
 	}
-	if (resp) {
-		resp->nextrp = NULL;
-		resp->header.duration = jiffies_to_msecs(jiffies);
-	}
+	memset(rp, 0, sizeof (Sg_request));
+	rp->parentfp = sfp;
+	rp->header.duration = jiffies_to_msecs(jiffies);
+	list_add_tail(&rp->entry, &sfp->rq_list);
 	write_unlock_irqrestore(&sfp->rq_list_lock, iflags);
-	return resp;
+	return rp;
+out_unlock:
+	write_unlock_irqrestore(&sfp->rq_list_lock, iflags);
+	return NULL;
 }
 
 /* Return of 1 for found; 0 for not found */
 static int
 sg_remove_request(Sg_fd * sfp, Sg_request * srp)
 {
-	Sg_request *prev_rp;
-	Sg_request *rp;
 	unsigned long iflags;
 	int res = 0;
 
-	if ((!sfp) || (!srp) || (!sfp->headrp))
+	if (!sfp || !srp || list_empty(&sfp->rq_list))
 		return res;
 	write_lock_irqsave(&sfp->rq_list_lock, iflags);
-	prev_rp = sfp->headrp;
-	if (srp == prev_rp) {
-		sfp->headrp = prev_rp->nextrp;
-		prev_rp->parentfp = NULL;
+	if (!list_empty(&srp->entry)) {
+		list_del(&srp->entry);
+		srp->parentfp = NULL;
 		res = 1;
-	} else {
-		while ((rp = prev_rp->nextrp)) {
-			if (srp == rp) {
-				prev_rp->nextrp = rp->nextrp;
-				rp->parentfp = NULL;
-				res = 1;
-				break;
-			}
-			prev_rp = rp;
-		}
 	}
 	write_unlock_irqrestore(&sfp->rq_list_lock, iflags);
 	return res;
@@ -2115,29 +2156,33 @@ sg_add_sfp(Sg_device * sdp, int dev)
 
 	sfp = kzalloc(sizeof(*sfp), GFP_ATOMIC | __GFP_NOWARN);
 	if (!sfp)
-		return NULL;
+		return ERR_PTR(-ENOMEM);
 
 	init_waitqueue_head(&sfp->read_wait);
 	rwlock_init(&sfp->rq_list_lock);
-
+	INIT_LIST_HEAD(&sfp->rq_list);
 	kref_init(&sfp->f_ref);
+	mutex_init(&sfp->f_mutex);
 	sfp->timeout = SG_DEFAULT_TIMEOUT;
 	sfp->timeout_user = SG_DEFAULT_TIMEOUT_USER;
 	sfp->force_packid = SG_DEF_FORCE_PACK_ID;
-	sfp->low_dma = (SG_DEF_FORCE_LOW_DMA == 0) ?
-	    sdp->device->host->unchecked_isa_dma : 1;
 	sfp->cmd_q = SG_DEF_COMMAND_Q;
 	sfp->keep_orphan = SG_DEF_KEEP_ORPHAN;
 	sfp->parentdp = sdp;
-	write_lock_irqsave(&sg_index_lock, iflags);
+	write_lock_irqsave(&sdp->sfd_lock, iflags);
+	if (atomic_read(&sdp->detaching)) {
+		write_unlock_irqrestore(&sdp->sfd_lock, iflags);
+		kfree(sfp);
+		return ERR_PTR(-ENODEV);
+	}
 	list_add_tail(&sfp->sfd_siblings, &sdp->sfds);
-	write_unlock_irqrestore(&sg_index_lock, iflags);
+	write_unlock_irqrestore(&sdp->sfd_lock, iflags);
 	SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp: sfp=0x%p\n", sfp));
 	if (unlikely(sg_big_buff != def_reserved_size))
 		sg_big_buff = def_reserved_size;
 
 	bufflen = min_t(int, sg_big_buff,
-			queue_max_sectors(sdp->device->request_queue) * 512);
+			max_sectors_bytes(sdp->device->request_queue));
 	sg_build_reserve(sfp, bufflen);
 	SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp:   bufflen=%d, k_use_sg=%d\n",
 			   sfp->reserve.bufflen, sfp->reserve.k_use_sg));
@@ -2147,14 +2192,23 @@ sg_add_sfp(Sg_device * sdp, int dev)
 	return sfp;
 }
 
-static void sg_remove_sfp_usercontext(struct work_struct *work)
+static void
+sg_remove_sfp_usercontext(struct work_struct *work)
 {
 	struct sg_fd *sfp = container_of(work, struct sg_fd, ew.work);
 	struct sg_device *sdp = sfp->parentdp;
+	Sg_request *srp;
+	unsigned long iflags;
 
 	/* Cleanup any responses which were never read(). */
-	while (sfp->headrp)
-		sg_finish_rem_req(sfp->headrp);
+	write_lock_irqsave(&sfp->rq_list_lock, iflags);
+	while (!list_empty(&sfp->rq_list)) {
+		srp = list_first_entry(&sfp->rq_list, Sg_request, entry);
+		sg_finish_rem_req(srp);
+		list_del(&srp->entry);
+		srp->parentfp = NULL;
+	}
+	write_unlock_irqrestore(&sfp->rq_list_lock, iflags);
 
 	if (sfp->reserve.bufflen > 0) {
 		SCSI_LOG_TIMEOUT(6,
@@ -2171,39 +2225,25 @@ static void sg_remove_sfp_usercontext(struct work_struct *work)
 	kfree(sfp);
 
 	scsi_device_put(sdp->device);
-	sg_put_dev(sdp);
+	kref_put(&sdp->d_ref, sg_device_destroy);
 	module_put(THIS_MODULE);
 }
 
-static void sg_remove_sfp(struct kref *kref)
+static void
+sg_remove_sfp(struct kref *kref)
 {
 	struct sg_fd *sfp = container_of(kref, struct sg_fd, f_ref);
 	struct sg_device *sdp = sfp->parentdp;
 	unsigned long iflags;
 
-	write_lock_irqsave(&sg_index_lock, iflags);
+	write_lock_irqsave(&sdp->sfd_lock, iflags);
 	list_del(&sfp->sfd_siblings);
-	write_unlock_irqrestore(&sg_index_lock, iflags);
-	wake_up_interruptible(&sdp->o_excl_wait);
+	write_unlock_irqrestore(&sdp->sfd_lock, iflags);
 
 	INIT_WORK(&sfp->ew.work, sg_remove_sfp_usercontext);
 	schedule_work(&sfp->ew.work);
 }
 
-static int
-sg_res_in_use(Sg_fd * sfp)
-{
-	const Sg_request *srp;
-	unsigned long iflags;
-
-	read_lock_irqsave(&sfp->rq_list_lock, iflags);
-	for (srp = sfp->headrp; srp; srp = srp->nextrp)
-		if (srp->res_used)
-			break;
-	read_unlock_irqrestore(&sfp->rq_list_lock, iflags);
-	return srp ? 1 : 0;
-}
-
 #ifdef CONFIG_SCSI_PROC_FS
 static int
 sg_idr_max_id(int id, void *p, void *data)
@@ -2235,7 +2275,8 @@ static Sg_device *sg_lookup_dev(int dev)
 	return idr_find(&sg_index_idr, dev);
 }
 
-static Sg_device *sg_get_dev(int dev)
+static Sg_device *
+sg_get_dev(int dev)
 {
 	struct sg_device *sdp;
 	unsigned long flags;
@@ -2244,8 +2285,8 @@ static Sg_device *sg_get_dev(int dev)
 	sdp = sg_lookup_dev(dev);
 	if (!sdp)
 		sdp = ERR_PTR(-ENXIO);
-	else if (sdp->detached) {
-		/* If sdp->detached, then the refcount may already be 0, in
+	else if (atomic_read(&sdp->detaching)) {
+		/* If sdp->detaching, then the refcount may already be 0, in
 		 * which case it would be a bug to do kref_get().
 		 */
 		sdp = ERR_PTR(-ENODEV);
@@ -2256,11 +2297,6 @@ static Sg_device *sg_get_dev(int dev)
 	return sdp;
 }
 
-static void sg_put_dev(struct sg_device *sdp)
-{
-	kref_put(&sdp->d_ref, sg_device_destroy);
-}
-
 #ifdef CONFIG_SCSI_PROC_FS
 
 static struct proc_dir_entry *sg_proc_sgp = NULL;
@@ -2477,8 +2513,7 @@ static int sg_proc_single_open_version(struct inode *inode, struct file *file)
 
 static int sg_proc_seq_show_devhdr(struct seq_file *s, void *v)
 {
-	seq_printf(s, "host\tchan\tid\tlun\ttype\topens\tqdepth\tbusy\t"
-		   "online\n");
+	seq_puts(s, "host\tchan\tid\tlun\ttype\topens\tqdepth\tbusy\tonline\n");
 	return 0;
 }
 
@@ -2534,7 +2569,11 @@ static int sg_proc_seq_show_dev(struct seq_file *s, void *v)
 
 	read_lock_irqsave(&sg_index_lock, iflags);
 	sdp = it ? sg_lookup_dev(it->index) : NULL;
-	if (sdp && (scsidp = sdp->device) && (!sdp->detached))
+	if ((NULL == sdp) || (NULL == sdp->device) ||
+	    (atomic_read(&sdp->detaching)))
+		seq_puts(s, "-1\t-1\t-1\t-1\t-1\t-1\t-1\t-1\t-1\n");
+	else {
+		scsidp = sdp->device;
 		seq_printf(s, "%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n",
 			      scsidp->host->host_no, scsidp->channel,
 			      scsidp->id, scsidp->lun, (int) scsidp->type,
@@ -2542,8 +2581,7 @@ static int sg_proc_seq_show_dev(struct seq_file *s, void *v)
 			      (int) scsidp->queue_depth,
 			      (int) scsidp->device_busy,
 			      (int) scsi_device_online(scsidp));
-	else
-		seq_printf(s, "-1\t-1\t-1\t-1\t-1\t-1\t-1\t-1\t-1\n");
+	}
 	read_unlock_irqrestore(&sg_index_lock, iflags);
 	return 0;
 }
@@ -2562,11 +2600,12 @@ static int sg_proc_seq_show_devstrs(struct seq_file *s, void *v)
 
 	read_lock_irqsave(&sg_index_lock, iflags);
 	sdp = it ? sg_lookup_dev(it->index) : NULL;
-	if (sdp && (scsidp = sdp->device) && (!sdp->detached))
+	scsidp = sdp ? sdp->device : NULL;
+	if (sdp && scsidp && (!atomic_read(&sdp->detaching)))
 		seq_printf(s, "%8.8s\t%16.16s\t%4.4s\n",
 			   scsidp->vendor, scsidp->model, scsidp->rev);
 	else
-		seq_printf(s, "<no active device>\n");
+		seq_puts(s, "<no active device>\n");
 	read_unlock_irqrestore(&sg_index_lock, iflags);
 	return 0;
 }
@@ -2574,7 +2613,7 @@ static int sg_proc_seq_show_devstrs(struct seq_file *s, void *v)
 /* must be called while holding sg_index_lock */
 static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp)
 {
-	int k, m, new_interface, blen, usg;
+	int k, new_interface, blen, usg;
 	Sg_request *srp;
 	Sg_fd *fp;
 	const sg_io_hdr_t *hp;
@@ -2590,17 +2629,15 @@ static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp)
 			   jiffies_to_msecs(fp->timeout),
 			   fp->reserve.bufflen,
 			   (int) fp->reserve.k_use_sg,
-			   (int) fp->low_dma);
+			   (int) sdp->device->host->unchecked_isa_dma);
 		seq_printf(s, "   cmd_q=%d f_packid=%d k_orphan=%d closed=0\n",
 			   (int) fp->cmd_q, (int) fp->force_packid,
 			   (int) fp->keep_orphan);
-		for (m = 0, srp = fp->headrp;
-				srp != NULL;
-				++m, srp = srp->nextrp) {
+		list_for_each_entry(srp, &fp->rq_list, entry) {
 			hp = &srp->header;
 			new_interface = (hp->interface_id == '\0') ? 0 : 1;
 			if (srp->res_used) {
-				if (new_interface && 
+				if (new_interface &&
 				    (SG_FLAG_MMAP_IO & hp->flags))
 					cp = "     mmap>> ";
 				else
@@ -2611,12 +2648,12 @@ static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp)
 				else
 					cp = "     ";
 			}
-			seq_printf(s, cp);
+			seq_puts(s, cp);
 			blen = srp->data.bufflen;
 			usg = srp->data.k_use_sg;
-			seq_printf(s, srp->done ? 
-				   ((1 == srp->done) ?  "rcv:" : "fin:")
-				   : "act:");
+			seq_puts(s, srp->done ?
+				 ((1 == srp->done) ?  "rcv:" : "fin:")
+				  : "act:");
 			seq_printf(s, " id=%d blen=%d",
 				   srp->header.pack_id, blen);
 			if (srp->done)
@@ -2631,8 +2668,8 @@ static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp)
 			seq_printf(s, "ms sgat=%d op=0x%02x\n", usg,
 				   (int) srp->data.cmd_opcode);
 		}
-		if (0 == m)
-			seq_printf(s, "     No requests active\n");
+		if (list_empty(&fp->rq_list))
+			seq_puts(s, "     No requests active\n");
 		read_unlock(&fp->rq_list_lock);
 	}
 }
@@ -2648,31 +2685,34 @@ static int sg_proc_seq_show_debug(struct seq_file *s, void *v)
 	Sg_device *sdp;
 	unsigned long iflags;
 
-	if (it && (0 == it->index)) {
-		seq_printf(s, "max_active_device=%d(origin 1)\n",
-			   (int)it->max);
-		seq_printf(s, " def_reserved_size=%d\n", sg_big_buff);
-	}
+	if (it && (0 == it->index))
+		seq_printf(s, "max_active_device=%d  def_reserved_size=%d\n",
+			   (int)it->max, sg_big_buff);
 
 	read_lock_irqsave(&sg_index_lock, iflags);
 	sdp = it ? sg_lookup_dev(it->index) : NULL;
-	if (sdp && !list_empty(&sdp->sfds)) {
-		struct scsi_device *scsidp = sdp->device;
-
+	if (NULL == sdp)
+		goto skip;
+	read_lock(&sdp->sfd_lock);
+	if (!list_empty(&sdp->sfds)) {
 		seq_printf(s, " >>> device=%s ", sdp->disk->disk_name);
-		if (sdp->detached)
-			seq_printf(s, "detached pending close ");
-		else
-			seq_printf
-			    (s, "scsi%d chan=%d id=%d lun=%d   em=%d",
-			     scsidp->host->host_no,
-			     scsidp->channel, scsidp->id,
-			     scsidp->lun,
-			     scsidp->host->hostt->emulated);
-		seq_printf(s, " sg_tablesize=%d excl=%d\n",
-			   sdp->sg_tablesize, get_exclude(sdp));
+		if (atomic_read(&sdp->detaching))
+			seq_puts(s, "detaching pending close ");
+		else if (sdp->device) {
+			struct scsi_device *scsidp = sdp->device;
+
+			seq_printf(s, "%d:%d:%d:%d   em=%d",
+				   scsidp->host->host_no,
+				   scsidp->channel, scsidp->id,
+				   scsidp->lun,
+				   scsidp->host->hostt->emulated);
+		}
+		seq_printf(s, " sg_tablesize=%d excl=%d open_cnt=%d\n",
+			   sdp->sg_tablesize, sdp->exclude, sdp->open_cnt);
 		sg_proc_debug_helper(s, sdp);
 	}
+	read_unlock(&sdp->sfd_lock);
+skip:
 	read_unlock_irqrestore(&sg_index_lock, iflags);
 	return 0;
 }
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index f7019c7e9bc5..da693eceff9a 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -306,9 +306,10 @@ static void sg_complete(struct urb *urb)
 		 */
 		spin_unlock(&io->lock);
 		for (i = 0, found = 0; i < io->entries; i++) {
-			if (!io->urbs[i] || !io->urbs[i]->dev)
+			if (!io->urbs[i])
 				continue;
 			if (found) {
+				usb_block_urb(io->urbs[i]);
 				retval = usb_unlink_urb(io->urbs[i]);
 				if (retval != -EINPROGRESS &&
 				    retval != -ENODEV &&
@@ -519,12 +520,10 @@ void usb_sg_wait(struct usb_sg_request *io)
 		int retval;
 
 		io->urbs[i]->dev = io->dev;
-		retval = usb_submit_urb(io->urbs[i], GFP_ATOMIC);
-
-		/* after we submit, let completions or cancellations fire;
-		 * we handshake using io->status.
-		 */
 		spin_unlock_irq(&io->lock);
+
+		retval = usb_submit_urb(io->urbs[i], GFP_NOIO);
+
 		switch (retval) {
 			/* maybe we retrying will recover */
 		case -ENXIO:	/* hc didn't queue this one */
@@ -582,30 +581,34 @@ EXPORT_SYMBOL_GPL(usb_sg_wait);
 void usb_sg_cancel(struct usb_sg_request *io)
 {
 	unsigned long flags;
+	int i, retval;
 
 	spin_lock_irqsave(&io->lock, flags);
+	if (io->status || io->count == 0) {
+		spin_unlock_irqrestore(&io->lock, flags);
+		return;
+	}
+	/* shut everything down */
+	io->status = -ECONNRESET;
+	io->count++;		/* Keep the request alive until we're done */
+	spin_unlock_irqrestore(&io->lock, flags);
 
-	/* shut everything down, if it didn't already */
-	if (!io->status) {
-		int i;
-
-		io->status = -ECONNRESET;
-		spin_unlock(&io->lock);
-		for (i = 0; i < io->entries; i++) {
-			int retval;
+	for (i = io->entries - 1; i >= 0; --i) {
+		usb_block_urb(io->urbs[i]);
 
-			if (!io->urbs[i]->dev)
-				continue;
-			retval = usb_unlink_urb(io->urbs[i]);
-			if (retval != -EINPROGRESS
-					&& retval != -ENODEV
-					&& retval != -EBUSY
-					&& retval != -EIDRM)
-				dev_warn(&io->dev->dev, "%s, unlink --> %d\n",
-					__func__, retval);
-		}
-		spin_lock(&io->lock);
+		retval = usb_unlink_urb(io->urbs[i]);
+		if (retval != -EINPROGRESS
+		    && retval != -ENODEV
+		    && retval != -EBUSY
+		    && retval != -EIDRM)
+			dev_warn(&io->dev->dev, "%s, unlink --> %d\n",
+				 __func__, retval);
 	}
+
+	spin_lock_irqsave(&io->lock, flags);
+	io->count--;
+	if (!io->count)
+		complete(&io->complete);
 	spin_unlock_irqrestore(&io->lock, flags);
 }
 EXPORT_SYMBOL_GPL(usb_sg_cancel);
diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c
index 3589be72f598..05b9adde1a17 100644
--- a/drivers/usb/gadget/configfs.c
+++ b/drivers/usb/gadget/configfs.c
@@ -254,6 +254,9 @@ static ssize_t gadget_dev_desc_UDC_store(struct gadget_info *gi,
 	char *name;
 	int ret;
 
+	if (strlen(page) < len)
+		return -EOVERFLOW;
+
 	name = kstrdup(page, GFP_KERNEL);
 	if (!name)
 		return -ENOMEM;
diff --git a/drivers/video/fbdev/geode/video_gx.c b/drivers/video/fbdev/geode/video_gx.c
index 6082f653c68a..67773e8bbb95 100644
--- a/drivers/video/fbdev/geode/video_gx.c
+++ b/drivers/video/fbdev/geode/video_gx.c
@@ -127,7 +127,7 @@ void gx_set_dclk_frequency(struct fb_info *info)
 	int timeout = 1000;
 
 	/* Rev. 1 Geode GXs use a 14 MHz reference clock instead of 48 MHz. */
-	if (cpu_data(0).x86_mask == 1) {
+	if (cpu_data(0).x86_stepping == 1) {
 		pll_table = gx_pll_table_14MHz;
 		pll_table_len = ARRAY_SIZE(gx_pll_table_14MHz);
 	} else {
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 2df8642c3ac1..563b42f3f3ba 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -1575,7 +1575,7 @@ static int fill_thread_core_info(struct elf_thread_core_info *t,
 		    (!regset->active || regset->active(t->task, regset) > 0)) {
 			int ret;
 			size_t size = regset->n * regset->size;
-			void *data = kmalloc(size, GFP_KERNEL);
+			void *data = kzalloc(size, GFP_KERNEL);
 			if (unlikely(!data))
 				return 0;
 			ret = regset->get(t->task, regset,
diff --git a/fs/exec.c b/fs/exec.c
index 077f85439264..680d1dbcf564 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1182,7 +1182,7 @@ void setup_new_exec(struct linux_binprm * bprm)
 
 	/* An exec changes our domain. We are no longer part of the thread
 	   group */
-	current->self_exec_id++;
+	ACCESS_ONCE(current->self_exec_id) = current->self_exec_id + 1;
 	flush_signal_handlers(current, 0);
 }
 EXPORT_SYMBOL(setup_new_exec);
diff --git a/fs/ext4/block_validity.c b/fs/ext4/block_validity.c
index 41eb9dcfac7e..c6836e6726ae 100644
--- a/fs/ext4/block_validity.c
+++ b/fs/ext4/block_validity.c
@@ -137,6 +137,50 @@ static void debug_print_tree(struct ext4_sb_info *sbi)
 	printk("\n");
 }
 
+static int ext4_protect_reserved_inode(struct super_block *sb, u32 ino)
+{
+	struct inode *inode;
+	struct ext4_sb_info *sbi = EXT4_SB(sb);
+	struct ext4_map_blocks map;
+	u32 i = 0, num;
+	int err = 0, n;
+
+	if ((ino < EXT4_ROOT_INO) ||
+	    (ino > le32_to_cpu(sbi->s_es->s_inodes_count)))
+		return -EINVAL;
+	inode = ext4_iget(sb, ino, EXT4_IGET_SPECIAL);
+	if (IS_ERR(inode))
+		return PTR_ERR(inode);
+	num = (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
+	while (i < num) {
+		cond_resched();
+		map.m_lblk = i;
+		map.m_len = num - i;
+		n = ext4_map_blocks(NULL, inode, &map, 0);
+		if (n < 0) {
+			err = n;
+			break;
+		}
+		if (n == 0) {
+			i++;
+		} else {
+			if (!ext4_data_block_valid(sbi, map.m_pblk, n)) {
+				ext4_error(sb, "blocks %llu-%llu from inode %u "
+					   "overlap system zone", map.m_pblk,
+					   map.m_pblk + map.m_len - 1, ino);
+				err = -EIO;
+				break;
+			}
+			err = add_system_zone(sbi, map.m_pblk, n);
+			if (err < 0)
+				break;
+			i += n;
+		}
+	}
+	iput(inode);
+	return err;
+}
+
 int ext4_setup_system_zone(struct super_block *sb)
 {
 	ext4_group_t ngroups = ext4_get_groups_count(sb);
@@ -171,6 +215,13 @@ int ext4_setup_system_zone(struct super_block *sb)
 		if (ret)
 			return ret;
 	}
+	if (EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL) &&
+	    sbi->s_es->s_journal_inum) {
+		ret = ext4_protect_reserved_inode(sb,
+				le32_to_cpu(sbi->s_es->s_journal_inum));
+		if (ret)
+			return ret;
+	}
 
 	if (test_opt(sb, DEBUG))
 		debug_print_tree(EXT4_SB(sb));
@@ -227,6 +278,12 @@ int ext4_check_blockref(const char *function, unsigned int line,
 	__le32 *bref = p;
 	unsigned int blk;
 
+	if (EXT4_HAS_COMPAT_FEATURE(inode->i_sb,
+				    EXT4_FEATURE_COMPAT_HAS_JOURNAL) &&
+	    (inode->i_ino ==
+	     le32_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_journal_inum)))
+		return 0;
+
 	while (bref < p+max) {
 		blk = le32_to_cpu(*bref++);
 		if (blk &&
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 09e978818474..929834c9a85c 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -2411,21 +2411,24 @@ extern void ext4_group_desc_csum_set(struct super_block *sb, __u32 group,
 extern int ext4_register_li_request(struct super_block *sb,
 				    ext4_group_t first_not_zeroed);
 
-static inline int ext4_has_group_desc_csum(struct super_block *sb)
-{
-	return EXT4_HAS_RO_COMPAT_FEATURE(sb,
-					  EXT4_FEATURE_RO_COMPAT_GDT_CSUM) ||
-	       (EXT4_SB(sb)->s_chksum_driver != NULL);
-}
-
 static inline int ext4_has_metadata_csum(struct super_block *sb)
 {
 	WARN_ON_ONCE(EXT4_HAS_RO_COMPAT_FEATURE(sb,
 			EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) &&
 		     !EXT4_SB(sb)->s_chksum_driver);
 
-	return (EXT4_SB(sb)->s_chksum_driver != NULL);
+	return EXT4_HAS_RO_COMPAT_FEATURE(sb,
+			EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) &&
+	       (EXT4_SB(sb)->s_chksum_driver != NULL);
+}
+
+static inline int ext4_has_group_desc_csum(struct super_block *sb)
+{
+	return EXT4_HAS_RO_COMPAT_FEATURE(sb,
+					  EXT4_FEATURE_RO_COMPAT_GDT_CSUM) ||
+		ext4_has_metadata_csum(sb);
 }
+
 static inline ext4_fsblk_t ext4_blocks_count(struct ext4_super_block *es)
 {
 	return ((ext4_fsblk_t)le32_to_cpu(es->s_blocks_count_hi) << 32) |
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 02dca6c43316..43602f4b0ae5 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -503,10 +503,15 @@ __read_extent_tree_block(const char *function, unsigned int line,
 	}
 	if (buffer_verified(bh) && !(flags & EXT4_EX_FORCE_CACHE))
 		return bh;
-	err = __ext4_ext_check(function, line, inode,
-			       ext_block_hdr(bh), depth, pblk);
-	if (err)
-		goto errout;
+	if (!EXT4_HAS_COMPAT_FEATURE(inode->i_sb,
+				     EXT4_FEATURE_COMPAT_HAS_JOURNAL) ||
+	    (inode->i_ino !=
+	     le32_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_journal_inum))) {
+		err = __ext4_ext_check(function, line, inode,
+				       ext_block_hdr(bh), depth, pblk);
+		if (err)
+			goto errout;
+	}
 	set_buffer_verified(bh);
 	/*
 	 * If this is a leaf block, cache all of its entries
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 66aed5f01784..67d8c6a7b182 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -411,6 +411,11 @@ static int __check_block_validity(struct inode *inode, const char *func,
 				unsigned int line,
 				struct ext4_map_blocks *map)
 {
+	if (EXT4_HAS_COMPAT_FEATURE(inode->i_sb,
+				    EXT4_FEATURE_COMPAT_HAS_JOURNAL) &&
+	    (inode->i_ino ==
+	     le32_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_journal_inum)))
+		return 0;
 	if (!ext4_data_block_valid(EXT4_SB(inode->i_sb), map->m_pblk,
 				   map->m_len)) {
 		ext4_error_inode(inode, func, line, map->m_pblk,
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
index 4c546028b035..db45b2a21d2f 100644
--- a/include/linux/mod_devicetable.h
+++ b/include/linux/mod_devicetable.h
@@ -559,6 +559,10 @@ struct amba_id {
 /*
  * MODULE_DEVICE_TABLE expects this struct to be called x86cpu_device_id.
  * Although gcc seems to ignore this error, clang fails without this define.
+ *
+ * Note: The ordering of the struct is different from upstream because the
+ * static initializers in kernels < 5.7 still use C89 style while upstream
+ * has been converted to proper C99 initializers.
  */
 #define x86cpu_device_id x86_cpu_id
 struct x86_cpu_id {
@@ -567,6 +571,7 @@ struct x86_cpu_id {
 	__u16 model;
 	__u16 feature;	/* bit index */
 	kernel_ulong_t driver_data;
+	__u16 steppings;
 };
 
 #define X86_FEATURE_MATCH(x) \
@@ -575,6 +580,7 @@ struct x86_cpu_id {
 #define X86_VENDOR_ANY 0xffff
 #define X86_FAMILY_ANY 0
 #define X86_MODEL_ANY  0
+#define X86_STEPPING_ANY 0
 #define X86_FEATURE_ANY 0	/* Same as FPU, you can't test for that */
 
 /*
diff --git a/include/linux/sched.h b/include/linux/sched.h
index bcd8b1664301..182f15430cb0 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1427,8 +1427,8 @@ struct task_struct {
 	struct seccomp seccomp;
 
 /* Thread group tracking */
-   	u32 parent_exec_id;
-   	u32 self_exec_id;
+	u64 parent_exec_id;
+	u64 self_exec_id;
 /* Protection of (de-)allocation: mm, files, fs, tty, keyrings, mems_allowed,
  * mempolicy */
 	spinlock_t alloc_lock;
diff --git a/include/scsi/sg.h b/include/scsi/sg.h
index a9f3c6fc3f57..034cf63c1342 100644
--- a/include/scsi/sg.h
+++ b/include/scsi/sg.h
@@ -234,7 +234,6 @@ typedef struct sg_req_info { /* used by SG_GET_REQUEST_TABLE ioctl() */
 #define SG_DEFAULT_RETRIES 0
 
 /* Defaults, commented if they differ from original sg driver */
-#define SG_DEF_FORCE_LOW_DMA 0  /* was 1 -> memory below 16MB on i386 */
 #define SG_DEF_FORCE_PACK_ID 0
 #define SG_DEF_KEEP_ORPHAN 0
 #define SG_DEF_RESERVED_SIZE SG_SCATTER_SZ /* load time option */
diff --git a/kernel/signal.c b/kernel/signal.c
index 6816d3ae6f46..d7b33730a2a4 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1679,7 +1679,7 @@ bool do_notify_parent(struct task_struct *tsk, int sig)
 		 * This is only possible if parent == real_parent.
 		 * Check if it has changed security domain.
 		 */
-		if (tsk->parent_exec_id != tsk->parent->self_exec_id)
+		if (tsk->parent_exec_id != ACCESS_ONCE(tsk->parent->self_exec_id))
 			sig = SIGCHLD;
 	}
 
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index 7550d098e3b7..ada029c4af3a 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -782,25 +782,30 @@ static int rx_queue_add_kobject(struct net_device *net, int index)
 	struct kobject *kobj = &queue->kobj;
 	int error = 0;
 
+	/* Kobject_put later will trigger rx_queue_release call which
+	 * decreases dev refcount: Take that reference here
+	 */
+	dev_hold(queue->dev);
+
 	kobj->kset = net->queues_kset;
 	error = kobject_init_and_add(kobj, &rx_queue_ktype, NULL,
 	    "rx-%u", index);
 	if (error)
-		return error;
-
-	dev_hold(queue->dev);
+		goto err;
 
 	if (net->sysfs_rx_queue_group) {
 		error = sysfs_create_group(kobj, net->sysfs_rx_queue_group);
-		if (error) {
-			kobject_put(kobj);
-			return error;
-		}
+		if (error)
+			goto err;
 	}
 
 	kobject_uevent(kobj, KOBJ_ADD);
 
 	return error;
+
+err:
+	kobject_put(kobj);
+	return error;
 }
 #endif /* CONFIG_SYSFS */
 
@@ -1141,25 +1146,29 @@ static int netdev_queue_add_kobject(struct net_device *net, int index)
 	struct kobject *kobj = &queue->kobj;
 	int error = 0;
 
+	/* Kobject_put later will trigger netdev_queue_release call
+	 * which decreases dev refcount: Take that reference here
+	 */
+	dev_hold(queue->dev);
+
 	kobj->kset = net->queues_kset;
 	error = kobject_init_and_add(kobj, &netdev_queue_ktype, NULL,
 	    "tx-%u", index);
 	if (error)
-		return error;
-
-	dev_hold(queue->dev);
+		goto err;
 
 #ifdef CONFIG_BQL
 	error = sysfs_create_group(kobj, &dql_group);
-	if (error) {
-		kobject_put(kobj);
-		return error;
-	}
+	if (error)
+		goto err;
 #endif
 
 	kobject_uevent(kobj, KOBJ_ADD);
-
 	return 0;
+
+err:
+	kobject_put(kobj);
+	return error;
 }
 #endif /* CONFIG_SYSFS */
 
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 60d50812900f..84f4a4e9e2ba 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -4669,37 +4669,59 @@ static int selinux_tun_dev_open(void *security)
 
 static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
 {
-	int err = 0;
-	u32 perm;
+	int rc = 0;
+	unsigned int msg_len;
+	unsigned int data_len = skb->len;
+	unsigned char *data = skb->data;
 	struct nlmsghdr *nlh;
 	struct sk_security_struct *sksec = sk->sk_security;
+	u16 sclass = sksec->sclass;
+	u32 perm;
 
-	if (skb->len < NLMSG_HDRLEN) {
-		err = -EINVAL;
-		goto out;
-	}
-	nlh = nlmsg_hdr(skb);
-
-	err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm);
-	if (err) {
-		if (err == -EINVAL) {
-			audit_log(current->audit_context, GFP_KERNEL, AUDIT_SELINUX_ERR,
-				  "SELinux:  unrecognized netlink message"
-				  " type=%hu for sclass=%hu\n",
-				  nlh->nlmsg_type, sksec->sclass);
-			if (!selinux_enforcing || security_get_allow_unknown())
-				err = 0;
+	while (data_len >= nlmsg_total_size(0)) {
+		nlh = (struct nlmsghdr *)data;
+
+		/* NOTE: the nlmsg_len field isn't reliably set by some netlink
+		 *       users which means we can't reject skb's with bogus
+		 *       length fields; our solution is to follow what
+		 *       netlink_rcv_skb() does and simply skip processing at
+		 *       messages with length fields that are clearly junk
+		 */
+		if (nlh->nlmsg_len < NLMSG_HDRLEN || nlh->nlmsg_len > data_len)
+			return 0;
+
+		rc = selinux_nlmsg_lookup(sclass, nlh->nlmsg_type, &perm);
+		if (rc == 0) {
+			rc = sock_has_perm(current, sk, perm);
+			if (rc)
+				return rc;
+		} else if (rc == -EINVAL) {
+			/* -EINVAL is a missing msg/perm mapping */
+			pr_warn_ratelimited("SELinux: unrecognized netlink"
+				" message: protocol=%hu nlmsg_type=%hu sclass=%s"
+				" pid=%d comm=%s\n",
+				sk->sk_protocol, nlh->nlmsg_type,
+				secclass_map[sclass - 1].name,
+				task_pid_nr(current), current->comm);
+			if (selinux_enforcing && !security_get_allow_unknown())
+				return rc;
+			rc = 0;
+		} else if (rc == -ENOENT) {
+			/* -ENOENT is a missing socket/class mapping, ignore */
+			rc = 0;
+		} else {
+			return rc;
 		}
 
-		/* Ignore */
-		if (err == -ENOENT)
-			err = 0;
-		goto out;
+		/* move to the next message after applying netlink padding */
+		msg_len = NLMSG_ALIGN(nlh->nlmsg_len);
+		if (msg_len >= data_len)
+			return 0;
+		data_len -= msg_len;
+		data += msg_len;
 	}
 
-	err = sock_has_perm(current, sk, perm);
-out:
-	return err;
+	return rc;
 }
 
 #ifdef CONFIG_NETFILTER

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply related	[relevance 1%]

* Re: [PATCH 3.16 00/61] 3.16.85-rc1 review
  2020-06-10 19:08  6% ` [PATCH 3.16 00/61] 3.16.85-rc1 review Guenter Roeck
@ 2020-06-10 21:25  9%   ` Ben Hutchings
  0 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-10 21:25 UTC (permalink / raw)
  To: Guenter Roeck; +Cc: linux-kernel, stable, torvalds, akpm, Denis Kirjanov

[-- Attachment #1: Type: text/plain, Size: 736 bytes --]

On Wed, 2020-06-10 at 12:08 -0700, Guenter Roeck wrote:
> On Tue, Jun 09, 2020 at 07:03:51PM +0100, Ben Hutchings wrote:
> > This is the start of the stable review cycle for the 3.16.85 release.
> > There are 61 patches in this series, which will be posted as responses
> > to this one.  If anyone has any issues with these being applied, please
> > let me know.
> > 
> > Responses should be made by Thu Jun 11 18:03:51 UTC 2020.
> > Anything received after that time might be too late.
> > 
> 
> Build results:
> 	total: 135 pass: 135 fail: 0
> Qemu test results:
> 	total: 229 pass: 229 fail: 0

Thanks for testing,

Ben.

-- 
Ben Hutchings
Life would be so much easier if we could look at the source code.



[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[relevance 9%]

* Re: [PATCH 3.16 00/61] 3.16.85-rc1 review
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (60 preceding siblings ...)
  2020-06-09 18:04 12% ` [PATCH 3.16 61/61] fs/binfmt_elf.c: allocate initialized memory in fill_thread_core_info() Ben Hutchings
@ 2020-06-10 19:08  6% ` Guenter Roeck
  2020-06-10 21:25  9%   ` Ben Hutchings
  61 siblings, 1 reply; 200+ results
From: Guenter Roeck @ 2020-06-10 19:08 UTC (permalink / raw)
  To: Ben Hutchings; +Cc: linux-kernel, stable, torvalds, akpm, Denis Kirjanov

On Tue, Jun 09, 2020 at 07:03:51PM +0100, Ben Hutchings wrote:
> This is the start of the stable review cycle for the 3.16.85 release.
> There are 61 patches in this series, which will be posted as responses
> to this one.  If anyone has any issues with these being applied, please
> let me know.
> 
> Responses should be made by Thu Jun 11 18:03:51 UTC 2020.
> Anything received after that time might be too late.
> 

Build results:
	total: 135 pass: 135 fail: 0
Qemu test results:
	total: 229 pass: 229 fail: 0

Guenter

^ permalink raw reply	[relevance 6%]

* Re: [PATCH 3.16 42/61] scsi: sg: don't return bogus Sg_requests
  2020-06-09 18:28  6%   ` Tony Battersby
@ 2020-06-09 19:03 13%     ` Ben Hutchings
  0 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 19:03 UTC (permalink / raw)
  To: Tony Battersby, linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Martin K. Petersen, Johannes Thumshirn,
	Andrey Konovalov, Christoph Hellwig, Hannes Reinecke,
	Greg Kroah-Hartman, Doug Gilbert

[-- Attachment #1: Type: text/plain, Size: 3373 bytes --]

On Tue, 2020-06-09 at 14:28 -0400, Tony Battersby wrote:
> On 6/9/20 2:04 PM, Ben Hutchings wrote:
> > 3.16.85-rc1 review patch.  If anyone has any objections, please let me know.
> > 
> > ------------------
> > 
> > From: Johannes Thumshirn <jthumshirn@suse.de>
> > 
> > commit 48ae8484e9fc324b4968d33c585e54bc98e44d61 upstream.
> > 
> > If the list search in sg_get_rq_mark() fails to find a valid request, we
> > return a bogus element. This then can later lead to a GPF in
> > sg_remove_scat().
> > 
> > So don't return bogus Sg_requests in sg_get_rq_mark() but NULL in case
> > the list search doesn't find a valid request.
> > 
> > Signed-off-by: Johannes Thumshirn <jthumshirn@suse.de>
> > Reported-by: Andrey Konovalov <andreyknvl@google.com>
> > Cc: Hannes Reinecke <hare@suse.de>
> > Cc: Christoph Hellwig <hch@lst.de>
> > Cc: Doug Gilbert <dgilbert@interlog.com>
> > Reviewed-by: Hannes Reinecke <hare@suse.de>
> > Acked-by: Doug Gilbert <dgilbert@interlog.com>
> > Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
> > Cc: Tony Battersby <tonyb@cybernetics.com>
> > Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> > Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
> > ---
> >  drivers/scsi/sg.c | 5 +++--
> >  1 file changed, 3 insertions(+), 2 deletions(-)
> > 
> > --- a/drivers/scsi/sg.c
> > +++ b/drivers/scsi/sg.c
> > @@ -2085,11 +2085,12 @@ sg_get_rq_mark(Sg_fd * sfp, int pack_id)
> >  		if ((1 == resp->done) && (!resp->sg_io_owned) &&
> >  		    ((-1 == pack_id) || (resp->header.pack_id == pack_id))) {
> >  			resp->done = 2;	/* guard against other readers */
> > -			break;
> > +			write_unlock_irqrestore(&sfp->rq_list_lock, iflags);
> > +			return resp;
> >  		}
> >  	}
> >  	write_unlock_irqrestore(&sfp->rq_list_lock, iflags);
> > -	return resp;
> > +	return NULL;
> >  }
> >  
> >  /* always adds to end of list */
> > 
> The following "cleanup" commit to the sg driver introduced a number of bugs:
> 
> 109bade9c625 ("scsi: sg: use standard lists for sg_requests") (v4.12-rc1)
> 
> This one bad commit requires all of the following fixes:
> 
> 48ae8484e9fc ("scsi: sg: don't return bogus Sg_requests") (v4.12-rc1)
> bd46fc406b30 ("scsi: sg: off by one in sg_ioctl()") (v4.13-rc7)
> 4759df905a47 ("scsi: sg: factor out sg_fill_request_table()") (v4.14-rc1)
> 3e0097499839 ("scsi: sg: fixup infoleak when using SG_GET_REQUEST_TABLE") (v4.14-rc1)
> 587c3c9f286c ("scsi: sg: Re-fix off by one in sg_fill_request_table()") (v4.14-rc6)
> 
> AFAIK, there is no reason to backport any of these changes to -stable,
> but if for some reason you do need to backport any one of these patches,
> then make sure you get all of them.

I couldn't see how to backport some of the more recent fixes without
applying this change first.  For this review cycle I've picked all of
the bug fixes that were on the 4.4-stable and 4.9-stable branches and
not yet in 3.16-stable, so I do have all the fixes you identified
above.

Ben.

> My guess is that the initial buggy patch was backported to other -stable
> trees because the fixes for it looked important, and of course the fixes
> depended on the patch that introduced all of the problems to begin with.

-- 
Ben Hutchings
The two most common things in the universe are hydrogen and stupidity.



[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[relevance 13%]

* Re: [PATCH 3.16 42/61] scsi: sg: don't return bogus Sg_requests
  2020-06-09 18:04  9% ` [PATCH 3.16 42/61] scsi: sg: don't return bogus Sg_requests Ben Hutchings
@ 2020-06-09 18:28  6%   ` Tony Battersby
  2020-06-09 19:03 13%     ` Ben Hutchings
  0 siblings, 1 reply; 200+ results
From: Tony Battersby @ 2020-06-09 18:28 UTC (permalink / raw)
  To: Ben Hutchings, linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Martin K. Petersen, Johannes Thumshirn,
	Andrey Konovalov, Christoph Hellwig, Hannes Reinecke,
	Greg Kroah-Hartman, Doug Gilbert

On 6/9/20 2:04 PM, Ben Hutchings wrote:
> 3.16.85-rc1 review patch.  If anyone has any objections, please let me know.
>
> ------------------
>
> From: Johannes Thumshirn <jthumshirn@suse.de>
>
> commit 48ae8484e9fc324b4968d33c585e54bc98e44d61 upstream.
>
> If the list search in sg_get_rq_mark() fails to find a valid request, we
> return a bogus element. This then can later lead to a GPF in
> sg_remove_scat().
>
> So don't return bogus Sg_requests in sg_get_rq_mark() but NULL in case
> the list search doesn't find a valid request.
>
> Signed-off-by: Johannes Thumshirn <jthumshirn@suse.de>
> Reported-by: Andrey Konovalov <andreyknvl@google.com>
> Cc: Hannes Reinecke <hare@suse.de>
> Cc: Christoph Hellwig <hch@lst.de>
> Cc: Doug Gilbert <dgilbert@interlog.com>
> Reviewed-by: Hannes Reinecke <hare@suse.de>
> Acked-by: Doug Gilbert <dgilbert@interlog.com>
> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
> Cc: Tony Battersby <tonyb@cybernetics.com>
> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
> ---
>  drivers/scsi/sg.c | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
>
> --- a/drivers/scsi/sg.c
> +++ b/drivers/scsi/sg.c
> @@ -2085,11 +2085,12 @@ sg_get_rq_mark(Sg_fd * sfp, int pack_id)
>  		if ((1 == resp->done) && (!resp->sg_io_owned) &&
>  		    ((-1 == pack_id) || (resp->header.pack_id == pack_id))) {
>  			resp->done = 2;	/* guard against other readers */
> -			break;
> +			write_unlock_irqrestore(&sfp->rq_list_lock, iflags);
> +			return resp;
>  		}
>  	}
>  	write_unlock_irqrestore(&sfp->rq_list_lock, iflags);
> -	return resp;
> +	return NULL;
>  }
>  
>  /* always adds to end of list */
>
The following "cleanup" commit to the sg driver introduced a number of bugs:

109bade9c625 ("scsi: sg: use standard lists for sg_requests") (v4.12-rc1)

This one bad commit requires all of the following fixes:

48ae8484e9fc ("scsi: sg: don't return bogus Sg_requests") (v4.12-rc1)
bd46fc406b30 ("scsi: sg: off by one in sg_ioctl()") (v4.13-rc7)
4759df905a47 ("scsi: sg: factor out sg_fill_request_table()") (v4.14-rc1)
3e0097499839 ("scsi: sg: fixup infoleak when using SG_GET_REQUEST_TABLE") (v4.14-rc1)
587c3c9f286c ("scsi: sg: Re-fix off by one in sg_fill_request_table()") (v4.14-rc6)

AFAIK, there is no reason to backport any of these changes to -stable,
but if for some reason you do need to backport any one of these patches,
then make sure you get all of them.

My guess is that the initial buggy patch was backported to other -stable
trees because the fixes for it looked important, and of course the fixes
depended on the patch that introduced all of the problems to begin with.

Tony Battersby
Cybernetics

^ permalink raw reply	[relevance 6%]

* [PATCH 3.16 11/61] selinux: cleanup error reporting in selinux_nlmsg_perm()
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (9 preceding siblings ...)
  2020-06-09 18:04 12% ` [PATCH 3.16 10/61] net-sysfs: Call dev_hold always in rx_queue_add_kobject Ben Hutchings
@ 2020-06-09 18:04  9% ` Ben Hutchings
  2020-06-09 18:04  9% ` [PATCH 3.16 12/61] selinux: convert WARN_ONCE() to printk() " Ben Hutchings
                   ` (50 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable; +Cc: akpm, Denis Kirjanov, Paul Moore, Richard Guy Briggs

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Richard Guy Briggs <rgb@redhat.com>

commit e173fb2646a832b424c80904c306b816760ce477 upstream.

Convert audit_log() call to WARN_ONCE().

Rename "type=" to nlmsg_type=" to avoid confusion with the audit record
type.

Added "protocol=" to help track down which protocol (NETLINK_AUDIT?) was used
within the netlink protocol family.

Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
[Rewrote the patch subject line]
Signed-off-by: Paul Moore <pmoore@redhat.com>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 security/selinux/hooks.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -4683,10 +4683,9 @@ static int selinux_nlmsg_perm(struct soc
 	err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm);
 	if (err) {
 		if (err == -EINVAL) {
-			audit_log(current->audit_context, GFP_KERNEL, AUDIT_SELINUX_ERR,
-				  "SELinux:  unrecognized netlink message"
-				  " type=%hu for sclass=%hu\n",
-				  nlh->nlmsg_type, sksec->sclass);
+			WARN_ONCE(1, "selinux_nlmsg_perm: unrecognized netlink message:"
+				  " protocol=%hu nlmsg_type=%hu sclass=%hu\n",
+				  sk->sk_protocol, nlh->nlmsg_type, sksec->sclass);
 			if (!selinux_enforcing || security_get_allow_unknown())
 				err = 0;
 		}


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 01/61] slcan: Fix memory leak in error path
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
@ 2020-06-09 18:03  9% ` Ben Hutchings
  2020-06-09 18:03 11% ` [PATCH 3.16 02/61] can: slcan: Fix use-after-free Read in slcan_open Ben Hutchings
                   ` (60 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:03 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Lukas Bulwahn, Jouni Hogander,
	Marc Kleine-Budde, Wolfgang Grandegger

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Jouni Hogander <jouni.hogander@unikie.com>

commit ed50e1600b4483c049ce76e6bd3b665a6a9300ed upstream.

This patch is fixing memory leak reported by Syzkaller:

BUG: memory leak unreferenced object 0xffff888067f65500 (size 4096):
  comm "syz-executor043", pid 454, jiffies 4294759719 (age 11.930s)
  hex dump (first 32 bytes):
    73 6c 63 61 6e 30 00 00 00 00 00 00 00 00 00 00 slcan0..........
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
  backtrace:
    [<00000000a06eec0d>] __kmalloc+0x18b/0x2c0
    [<0000000083306e66>] kvmalloc_node+0x3a/0xc0
    [<000000006ac27f87>] alloc_netdev_mqs+0x17a/0x1080
    [<0000000061a996c9>] slcan_open+0x3ae/0x9a0
    [<000000001226f0f9>] tty_ldisc_open.isra.1+0x76/0xc0
    [<0000000019289631>] tty_set_ldisc+0x28c/0x5f0
    [<000000004de5a617>] tty_ioctl+0x48d/0x1590
    [<00000000daef496f>] do_vfs_ioctl+0x1c7/0x1510
    [<0000000059068dbc>] ksys_ioctl+0x99/0xb0
    [<000000009a6eb334>] __x64_sys_ioctl+0x78/0xb0
    [<0000000053d0332e>] do_syscall_64+0x16f/0x580
    [<0000000021b83b99>] entry_SYSCALL_64_after_hwframe+0x44/0xa9
    [<000000008ea75434>] 0xffffffffffffffff

Cc: Wolfgang Grandegger <wg@grandegger.com>
Cc: Marc Kleine-Budde <mkl@pengutronix.de>
Cc: Lukas Bulwahn <lukas.bulwahn@gmail.com>
Signed-off-by: Jouni Hogander <jouni.hogander@unikie.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/net/can/slcan.c | 1 +
 1 file changed, 1 insertion(+)

--- a/drivers/net/can/slcan.c
+++ b/drivers/net/can/slcan.c
@@ -620,6 +620,7 @@ err_free_chan:
 	sl->tty = NULL;
 	tty->disc_data = NULL;
 	clear_bit(SLF_INUSE, &sl->flags);
+	free_netdev(sl->dev);
 
 err_exit:
 	rtnl_unlock();


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 12/61] selinux: convert WARN_ONCE() to printk() in selinux_nlmsg_perm()
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (10 preceding siblings ...)
  2020-06-09 18:04  9% ` [PATCH 3.16 11/61] selinux: cleanup error reporting in selinux_nlmsg_perm() Ben Hutchings
@ 2020-06-09 18:04  9% ` Ben Hutchings
  2020-06-09 18:04  9% ` [PATCH 3.16 13/61] selinux: Print 'sclass' as string when unrecognized netlink message occurs Ben Hutchings
                   ` (49 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable; +Cc: akpm, Denis Kirjanov, Paul Moore, Richard Guy Briggs

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Richard Guy Briggs <rgb@redhat.com>

commit d950f84c1c6658faec2ecbf5b09f7e7191953394 upstream.

Convert WARN_ONCE() to printk() in selinux_nlmsg_perm().

After conversion from audit_log() in commit e173fb26, WARN_ONCE() was
deemed too alarmist, so switch it to printk().

Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
[PM: Changed to printk(WARNING) so we catch all of the different
 invalid netlink messages.  In Richard's defense, he brought this
 point up earlier, but I didn't understand his point at the time.]
Signed-off-by: Paul Moore <pmoore@redhat.com>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 security/selinux/hooks.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -4683,9 +4683,10 @@ static int selinux_nlmsg_perm(struct soc
 	err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm);
 	if (err) {
 		if (err == -EINVAL) {
-			WARN_ONCE(1, "selinux_nlmsg_perm: unrecognized netlink message:"
-				  " protocol=%hu nlmsg_type=%hu sclass=%hu\n",
-				  sk->sk_protocol, nlh->nlmsg_type, sksec->sclass);
+			printk(KERN_WARNING
+			       "SELinux: unrecognized netlink message:"
+			       " protocol=%hu nlmsg_type=%hu sclass=%hu\n",
+			       sk->sk_protocol, nlh->nlmsg_type, sksec->sclass);
 			if (!selinux_enforcing || security_get_allow_unknown())
 				err = 0;
 		}


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 06/61] slip: not call free_netdev before rtnl_unlock in slip_open
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (4 preceding siblings ...)
  2020-06-09 18:03 11% ` [PATCH 3.16 05/61] slip: Fix use-after-free Read in slip_open Ben Hutchings
@ 2020-06-09 18:03 13% ` Ben Hutchings
  2020-06-09 18:03 12% ` [PATCH 3.16 07/61] net-sysfs: Fix reference count leak in rx|netdev_queue_add_kobject Ben Hutchings
                   ` (55 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:03 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Oliver Hartkopp, David S. Miller, yangerkun

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: yangerkun <yangerkun@huawei.com>

commit f596c87005f7b1baeb7d62d9a9e25d68c3dfae10 upstream.

As the description before netdev_run_todo, we cannot call free_netdev
before rtnl_unlock, fix it by reorder the code.

Signed-off-by: yangerkun <yangerkun@huawei.com>
Reviewed-by: Oliver Hartkopp <socketcan@hartkopp.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/net/slip/slip.c | 3 +++
 1 file changed, 3 insertions(+)

--- a/drivers/net/slip/slip.c
+++ b/drivers/net/slip/slip.c
@@ -867,7 +867,10 @@ err_free_chan:
 	sl->tty = NULL;
 	tty->disc_data = NULL;
 	clear_bit(SLF_INUSE, &sl->flags);
+	/* do not call free_netdev before rtnl_unlock */
+	rtnl_unlock();
 	sl_free_netdev(sl->dev);
+	return err;
 
 err_exit:
 	rtnl_unlock();


^ permalink raw reply	[relevance 13%]

* [PATCH 3.16 04/61] slip: Fix memory leak in slip_open error path
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (2 preceding siblings ...)
  2020-06-09 18:03 13% ` [PATCH 3.16 03/61] slcan: not call free_netdev before rtnl_unlock " Ben Hutchings
@ 2020-06-09 18:03  9% ` Ben Hutchings
  2020-06-09 18:03 11% ` [PATCH 3.16 05/61] slip: Fix use-after-free Read in slip_open Ben Hutchings
                   ` (57 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:03 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Oliver Hartkopp, Lukas Bulwahn,
	David S. Miller, Jouni Hogander

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Jouni Hogander <jouni.hogander@unikie.com>

commit 3b5a39979dafea9d0cd69c7ae06088f7a84cdafa upstream.

Driver/net/can/slcan.c is derived from slip.c. Memory leak was detected
by Syzkaller in slcan. Same issue exists in slip.c and this patch is
addressing the leak in slip.c.

Here is the slcan memory leak trace reported by Syzkaller:

BUG: memory leak unreferenced object 0xffff888067f65500 (size 4096):
  comm "syz-executor043", pid 454, jiffies 4294759719 (age 11.930s)
  hex dump (first 32 bytes):
    73 6c 63 61 6e 30 00 00 00 00 00 00 00 00 00 00 slcan0..........
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
  backtrace:
    [<00000000a06eec0d>] __kmalloc+0x18b/0x2c0
    [<0000000083306e66>] kvmalloc_node+0x3a/0xc0
    [<000000006ac27f87>] alloc_netdev_mqs+0x17a/0x1080
    [<0000000061a996c9>] slcan_open+0x3ae/0x9a0
    [<000000001226f0f9>] tty_ldisc_open.isra.1+0x76/0xc0
    [<0000000019289631>] tty_set_ldisc+0x28c/0x5f0
    [<000000004de5a617>] tty_ioctl+0x48d/0x1590
    [<00000000daef496f>] do_vfs_ioctl+0x1c7/0x1510
    [<0000000059068dbc>] ksys_ioctl+0x99/0xb0
    [<000000009a6eb334>] __x64_sys_ioctl+0x78/0xb0
    [<0000000053d0332e>] do_syscall_64+0x16f/0x580
    [<0000000021b83b99>] entry_SYSCALL_64_after_hwframe+0x44/0xa9
    [<000000008ea75434>] 0xfffffffffffffff

Cc: "David S. Miller" <davem@davemloft.net>
Cc: Oliver Hartkopp <socketcan@hartkopp.net>
Cc: Lukas Bulwahn <lukas.bulwahn@gmail.com>
Signed-off-by: Jouni Hogander <jouni.hogander@unikie.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/net/slip/slip.c | 1 +
 1 file changed, 1 insertion(+)

--- a/drivers/net/slip/slip.c
+++ b/drivers/net/slip/slip.c
@@ -867,6 +867,7 @@ err_free_chan:
 	sl->tty = NULL;
 	tty->disc_data = NULL;
 	clear_bit(SLF_INUSE, &sl->flags);
+	free_netdev(sl->dev);
 
 err_exit:
 	rtnl_unlock();


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 17/61] drivers: usb: core: Minimize irq disabling in usb_sg_cancel()
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (15 preceding siblings ...)
  2020-06-09 18:04  8% ` [PATCH 3.16 16/61] drivers: usb: core: Don't disable irqs in usb_sg_wait() during URB submit Ben Hutchings
@ 2020-06-09 18:04  9% ` Ben Hutchings
  2020-06-09 18:04  7% ` [PATCH 3.16 18/61] USB: core: Fix free-while-in-use bug in the USB S-Glibrary Ben Hutchings
                   ` (44 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Alan Stern, David Mosberger, Greg Kroah-Hartman

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: David Mosberger <davidm@egauge.net>

commit 5f2e5fb873e269fcb806165715d237f0de4ecf1d upstream.

Restructure usb_sg_cancel() so we don't have to disable interrupts
while cancelling the URBs.

Suggested-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: David Mosberger <davidm@egauge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/usb/core/message.c | 37 +++++++++++++++++--------------------
 1 file changed, 17 insertions(+), 20 deletions(-)

--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -581,31 +581,28 @@ EXPORT_SYMBOL_GPL(usb_sg_wait);
 void usb_sg_cancel(struct usb_sg_request *io)
 {
 	unsigned long flags;
+	int i, retval;
 
 	spin_lock_irqsave(&io->lock, flags);
+	if (io->status) {
+		spin_unlock_irqrestore(&io->lock, flags);
+		return;
+	}
+	/* shut everything down */
+	io->status = -ECONNRESET;
+	spin_unlock_irqrestore(&io->lock, flags);
 
-	/* shut everything down, if it didn't already */
-	if (!io->status) {
-		int i;
-
-		io->status = -ECONNRESET;
-		spin_unlock(&io->lock);
-		for (i = 0; i < io->entries; i++) {
-			int retval;
-
-			usb_block_urb(io->urbs[i]);
+	for (i = io->entries - 1; i >= 0; --i) {
+		usb_block_urb(io->urbs[i]);
 
-			retval = usb_unlink_urb(io->urbs[i]);
-			if (retval != -EINPROGRESS
-					&& retval != -ENODEV
-					&& retval != -EBUSY
-					&& retval != -EIDRM)
-				dev_warn(&io->dev->dev, "%s, unlink --> %d\n",
-					__func__, retval);
-		}
-		spin_lock(&io->lock);
+		retval = usb_unlink_urb(io->urbs[i]);
+		if (retval != -EINPROGRESS
+		    && retval != -ENODEV
+		    && retval != -EBUSY
+		    && retval != -EIDRM)
+			dev_warn(&io->dev->dev, "%s, unlink --> %d\n",
+				 __func__, retval);
 	}
-	spin_unlock_irqrestore(&io->lock, flags);
 }
 EXPORT_SYMBOL_GPL(usb_sg_cancel);
 


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 07/61] net-sysfs: Fix reference count leak in rx|netdev_queue_add_kobject
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (5 preceding siblings ...)
  2020-06-09 18:03 13% ` [PATCH 3.16 06/61] slip: not call free_netdev before rtnl_unlock " Ben Hutchings
@ 2020-06-09 18:03 12% ` Ben Hutchings
  2020-06-09 18:03  9% ` [PATCH 3.16 08/61] net-sysfs: fix netdev_queue_add_kobject() breakage Ben Hutchings
                   ` (54 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:03 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Lukas Bulwahn, David Miller, Jouni Hogander

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Jouni Hogander <jouni.hogander@unikie.com>

commit b8eb718348b8fb30b5a7d0a8fce26fb3f4ac741b upstream.

kobject_init_and_add takes reference even when it fails. This has
to be given up by the caller in error handling. Otherwise memory
allocated by kobject_init_and_add is never freed. Originally found
by Syzkaller:

BUG: memory leak
unreferenced object 0xffff8880679f8b08 (size 8):
  comm "netdev_register", pid 269, jiffies 4294693094 (age 12.132s)
  hex dump (first 8 bytes):
    72 78 2d 30 00 36 20 d4                          rx-0.6 .
  backtrace:
    [<000000008c93818e>] __kmalloc_track_caller+0x16e/0x290
    [<000000001f2e4e49>] kvasprintf+0xb1/0x140
    [<000000007f313394>] kvasprintf_const+0x56/0x160
    [<00000000aeca11c8>] kobject_set_name_vargs+0x5b/0x140
    [<0000000073a0367c>] kobject_init_and_add+0xd8/0x170
    [<0000000088838e4b>] net_rx_queue_update_kobjects+0x152/0x560
    [<000000006be5f104>] netdev_register_kobject+0x210/0x380
    [<00000000e31dab9d>] register_netdevice+0xa1b/0xf00
    [<00000000f68b2465>] __tun_chr_ioctl+0x20d5/0x3dd0
    [<000000004c50599f>] tun_chr_ioctl+0x2f/0x40
    [<00000000bbd4c317>] do_vfs_ioctl+0x1c7/0x1510
    [<00000000d4c59e8f>] ksys_ioctl+0x99/0xb0
    [<00000000946aea81>] __x64_sys_ioctl+0x78/0xb0
    [<0000000038d946e5>] do_syscall_64+0x16f/0x580
    [<00000000e0aa5d8f>] entry_SYSCALL_64_after_hwframe+0x44/0xa9
    [<00000000285b3d1a>] 0xffffffffffffffff

Cc: David Miller <davem@davemloft.net>
Cc: Lukas Bulwahn <lukas.bulwahn@gmail.com>
Signed-off-by: Jouni Hogander <jouni.hogander@unikie.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 net/core/net-sysfs.c | 24 +++++++++++++-----------
 1 file changed, 13 insertions(+), 11 deletions(-)

--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -786,21 +786,23 @@ static int rx_queue_add_kobject(struct n
 	error = kobject_init_and_add(kobj, &rx_queue_ktype, NULL,
 	    "rx-%u", index);
 	if (error)
-		return error;
+		goto err;
 
 	dev_hold(queue->dev);
 
 	if (net->sysfs_rx_queue_group) {
 		error = sysfs_create_group(kobj, net->sysfs_rx_queue_group);
-		if (error) {
-			kobject_put(kobj);
-			return error;
-		}
+		if (error)
+			goto err;
 	}
 
 	kobject_uevent(kobj, KOBJ_ADD);
 
 	return error;
+
+err:
+	kobject_put(kobj);
+	return error;
 }
 #endif /* CONFIG_SYSFS */
 
@@ -1145,21 +1147,21 @@ static int netdev_queue_add_kobject(stru
 	error = kobject_init_and_add(kobj, &netdev_queue_ktype, NULL,
 	    "tx-%u", index);
 	if (error)
-		return error;
+		goto err;
 
 	dev_hold(queue->dev);
 
 #ifdef CONFIG_BQL
 	error = sysfs_create_group(kobj, &dql_group);
-	if (error) {
-		kobject_put(kobj);
-		return error;
-	}
+	if (error)
+		goto err;
 #endif
 
 	kobject_uevent(kobj, KOBJ_ADD);
 
-	return 0;
+err:
+	kobject_put(kobj);
+	return error;
 }
 #endif /* CONFIG_SYSFS */
 


^ permalink raw reply	[relevance 12%]

* [PATCH 3.16 05/61] slip: Fix use-after-free Read in slip_open
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (3 preceding siblings ...)
  2020-06-09 18:03  9% ` [PATCH 3.16 04/61] slip: Fix memory leak in slip_open error path Ben Hutchings
@ 2020-06-09 18:03 11% ` Ben Hutchings
  2020-06-09 18:03 13% ` [PATCH 3.16 06/61] slip: not call free_netdev before rtnl_unlock " Ben Hutchings
                   ` (56 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:03 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Jouni Hogander, Lukas Bulwahn,
	David Miller, Oliver Hartkopp, syzbot+4d5170758f3762109542

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Jouni Hogander <jouni.hogander@unikie.com>

commit e58c1912418980f57ba2060017583067f5f71e52 upstream.

Slip_open doesn't clean-up device which registration failed from the
slip_devs device list. On next open after failure this list is iterated
and freed device is accessed. Fix this by calling sl_free_netdev in error
path.

Here is the trace from the Syzbot:

__dump_stack lib/dump_stack.c:77 [inline]
dump_stack+0x197/0x210 lib/dump_stack.c:118
print_address_description.constprop.0.cold+0xd4/0x30b mm/kasan/report.c:374
__kasan_report.cold+0x1b/0x41 mm/kasan/report.c:506
kasan_report+0x12/0x20 mm/kasan/common.c:634
__asan_report_load8_noabort+0x14/0x20 mm/kasan/generic_report.c:132
sl_sync drivers/net/slip/slip.c:725 [inline]
slip_open+0xecd/0x11b7 drivers/net/slip/slip.c:801
tty_ldisc_open.isra.0+0xa3/0x110 drivers/tty/tty_ldisc.c:469
tty_set_ldisc+0x30e/0x6b0 drivers/tty/tty_ldisc.c:596
tiocsetd drivers/tty/tty_io.c:2334 [inline]
tty_ioctl+0xe8d/0x14f0 drivers/tty/tty_io.c:2594
vfs_ioctl fs/ioctl.c:46 [inline]
file_ioctl fs/ioctl.c:509 [inline]
do_vfs_ioctl+0xdb6/0x13e0 fs/ioctl.c:696
ksys_ioctl+0xab/0xd0 fs/ioctl.c:713
__do_sys_ioctl fs/ioctl.c:720 [inline]
__se_sys_ioctl fs/ioctl.c:718 [inline]
__x64_sys_ioctl+0x73/0xb0 fs/ioctl.c:718
do_syscall_64+0xfa/0x760 arch/x86/entry/common.c:290
entry_SYSCALL_64_after_hwframe+0x49/0xbe

Fixes: 3b5a39979daf ("slip: Fix memory leak in slip_open error path")
Reported-by: syzbot+4d5170758f3762109542@syzkaller.appspotmail.com
Cc: David Miller <davem@davemloft.net>
Cc: Oliver Hartkopp <socketcan@hartkopp.net>
Cc: Lukas Bulwahn <lukas.bulwahn@gmail.com>
Signed-off-by: Jouni Hogander <jouni.hogander@unikie.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
[bwh: Backported to 3.16: sl_free_netdev() calls free_netdev() here, so
 delete the direct call to free_netdev()]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
--- a/drivers/net/slip/slip.c
+++ b/drivers/net/slip/slip.c
@@ -867,7 +867,7 @@ err_free_chan:
 	sl->tty = NULL;
 	tty->disc_data = NULL;
 	clear_bit(SLF_INUSE, &sl->flags);
-	free_netdev(sl->dev);
+	sl_free_netdev(sl->dev);
 
 err_exit:
 	rtnl_unlock();


^ permalink raw reply	[relevance 11%]

* [PATCH 3.16 02/61] can: slcan: Fix use-after-free Read in slcan_open
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
  2020-06-09 18:03  9% ` [PATCH 3.16 01/61] slcan: Fix memory leak in error path Ben Hutchings
@ 2020-06-09 18:03 11% ` Ben Hutchings
  2020-06-09 18:03 13% ` [PATCH 3.16 03/61] slcan: not call free_netdev before rtnl_unlock " Ben Hutchings
                   ` (59 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:03 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Jouni Hogander, David Miller,
	Lukas Bulwahn, Oliver Hartkopp, Wolfgang Grandegger,
	Marc Kleine-Budde

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Jouni Hogander <jouni.hogander@unikie.com>

commit 9ebd796e24008f33f06ebea5a5e6aceb68b51794 upstream.

Slcan_open doesn't clean-up device which registration failed from the
slcan_devs device list. On next open this list is iterated and freed
device is accessed. Fix this by calling slc_free_netdev in error path.

Driver/net/can/slcan.c is derived from slip.c. Use-after-free error was
identified in slip_open by syzboz. Same bug is in slcan.c. Here is the
trace from the Syzbot slip report:

__dump_stack lib/dump_stack.c:77 [inline]
dump_stack+0x197/0x210 lib/dump_stack.c:118
print_address_description.constprop.0.cold+0xd4/0x30b mm/kasan/report.c:374
__kasan_report.cold+0x1b/0x41 mm/kasan/report.c:506
kasan_report+0x12/0x20 mm/kasan/common.c:634
__asan_report_load8_noabort+0x14/0x20 mm/kasan/generic_report.c:132
sl_sync drivers/net/slip/slip.c:725 [inline]
slip_open+0xecd/0x11b7 drivers/net/slip/slip.c:801
tty_ldisc_open.isra.0+0xa3/0x110 drivers/tty/tty_ldisc.c:469
tty_set_ldisc+0x30e/0x6b0 drivers/tty/tty_ldisc.c:596
tiocsetd drivers/tty/tty_io.c:2334 [inline]
tty_ioctl+0xe8d/0x14f0 drivers/tty/tty_io.c:2594
vfs_ioctl fs/ioctl.c:46 [inline]
file_ioctl fs/ioctl.c:509 [inline]
do_vfs_ioctl+0xdb6/0x13e0 fs/ioctl.c:696
ksys_ioctl+0xab/0xd0 fs/ioctl.c:713
__do_sys_ioctl fs/ioctl.c:720 [inline]
__se_sys_ioctl fs/ioctl.c:718 [inline]
__x64_sys_ioctl+0x73/0xb0 fs/ioctl.c:718
do_syscall_64+0xfa/0x760 arch/x86/entry/common.c:290
entry_SYSCALL_64_after_hwframe+0x49/0xbe

Fixes: ed50e1600b44 ("slcan: Fix memory leak in error path")
Cc: Wolfgang Grandegger <wg@grandegger.com>
Cc: Marc Kleine-Budde <mkl@pengutronix.de>
Cc: David Miller <davem@davemloft.net>
Cc: Oliver Hartkopp <socketcan@hartkopp.net>
Cc: Lukas Bulwahn <lukas.bulwahn@gmail.com>
Signed-off-by: Jouni Hogander <jouni.hogander@unikie.com>
Acked-by: Oliver Hartkopp <socketcan@hartkopp.net>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
[bwh: Backported to 3.16: slc_free_netdev() calls free_netdev() here, so
 delete the direct call to free_netdev()]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
--- a/drivers/net/can/slcan.c
+++ b/drivers/net/can/slcan.c
@@ -620,7 +620,7 @@ err_free_chan:
 	sl->tty = NULL;
 	tty->disc_data = NULL;
 	clear_bit(SLF_INUSE, &sl->flags);
-	free_netdev(sl->dev);
+	slc_free_netdev(sl->dev);
 
 err_exit:
 	rtnl_unlock();


^ permalink raw reply	[relevance 11%]

* [PATCH 3.16 03/61] slcan: not call free_netdev before rtnl_unlock in slcan_open
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
  2020-06-09 18:03  9% ` [PATCH 3.16 01/61] slcan: Fix memory leak in error path Ben Hutchings
  2020-06-09 18:03 11% ` [PATCH 3.16 02/61] can: slcan: Fix use-after-free Read in slcan_open Ben Hutchings
@ 2020-06-09 18:03 13% ` Ben Hutchings
  2020-06-09 18:03  9% ` [PATCH 3.16 04/61] slip: Fix memory leak in slip_open error path Ben Hutchings
                   ` (58 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:03 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, David S. Miller, Oliver Hartkopp, yangerkun

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Oliver Hartkopp <socketcan@hartkopp.net>

commit 2091a3d42b4f339eaeed11228e0cbe9d4f92f558 upstream.

As the description before netdev_run_todo, we cannot call free_netdev
before rtnl_unlock, fix it by reorder the code.

This patch is a 1:1 copy of upstream slip.c commit f596c87005f7
("slip: not call free_netdev before rtnl_unlock in slip_open").

Reported-by: yangerkun <yangerkun@huawei.com>
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/net/can/slcan.c | 3 +++
 1 file changed, 3 insertions(+)

--- a/drivers/net/can/slcan.c
+++ b/drivers/net/can/slcan.c
@@ -620,7 +620,10 @@ err_free_chan:
 	sl->tty = NULL;
 	tty->disc_data = NULL;
 	clear_bit(SLF_INUSE, &sl->flags);
+	/* do not call free_netdev before rtnl_unlock */
+	rtnl_unlock();
 	slc_free_netdev(sl->dev);
+	return err;
 
 err_exit:
 	rtnl_unlock();


^ permalink raw reply	[relevance 13%]

* [PATCH 3.16 19/61] scsi: mptfusion: Add bounds check in mptctl_hp_targetinfo()
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (17 preceding siblings ...)
  2020-06-09 18:04  7% ` [PATCH 3.16 18/61] USB: core: Fix free-while-in-use bug in the USB S-Glibrary Ben Hutchings
@ 2020-06-09 18:04  9% ` Ben Hutchings
  2020-06-09 18:04  4% ` [PATCH 3.16 20/61] scsi: mptfusion: Fix double fetch bug in ioctl Ben Hutchings
                   ` (42 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Dan Carpenter, Johannes Thumshirn,
	Martin K. Petersen

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Dan Carpenter <dan.carpenter@oracle.com>

commit a7043e9529f3c367cc4d82997e00be034cbe57ca upstream.

My static checker complains about an out of bounds read:

    drivers/message/fusion/mptctl.c:2786 mptctl_hp_targetinfo()
    error: buffer overflow 'hd->sel_timeout' 255 <= u32max.

It's true that we probably should have a bounds check here.

Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/message/fusion/mptctl.c | 2 ++
 1 file changed, 2 insertions(+)

--- a/drivers/message/fusion/mptctl.c
+++ b/drivers/message/fusion/mptctl.c
@@ -2698,6 +2698,8 @@ mptctl_hp_targetinfo(unsigned long arg)
 				__FILE__, __LINE__, iocnum);
 		return -ENODEV;
 	}
+	if (karg.hdr.id >= MPT_MAX_FC_DEVICES)
+		return -EINVAL;
 	dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_hp_targetinfo called.\n",
 	    ioc->name));
 


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 21/61] mwifiex: Fix possible buffer overflows in mwifiex_cmd_append_vsie_tlv()
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (19 preceding siblings ...)
  2020-06-09 18:04  4% ` [PATCH 3.16 20/61] scsi: mptfusion: Fix double fetch bug in ioctl Ben Hutchings
@ 2020-06-09 18:04 13% ` Ben Hutchings
  2020-06-09 18:04 13% ` [PATCH 3.16 22/61] mwifiex: Fix possible buffer overflows in mwifiex_ret_wmm_get_status() Ben Hutchings
                   ` (40 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable; +Cc: akpm, Denis Kirjanov, Kalle Valo, Qing Xu

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Qing Xu <m1s5p6688@gmail.com>

commit b70261a288ea4d2f4ac7cd04be08a9f0f2de4f4d upstream.

mwifiex_cmd_append_vsie_tlv() calls memcpy() without checking
the destination size may trigger a buffer overflower,
which a local user could use to cause denial of service
or the execution of arbitrary code.
Fix it by putting the length check before calling memcpy().

Signed-off-by: Qing Xu <m1s5p6688@gmail.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
[bwh: Backported to 3.16:
 - Use dev_info() instead of mwifiex_dbg()
 - Adjust filename]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/net/wireless/mwifiex/scan.c | 7 +++++++
 1 file changed, 7 insertions(+)

--- a/drivers/net/wireless/mwifiex/scan.c
+++ b/drivers/net/wireless/mwifiex/scan.c
@@ -2267,6 +2267,13 @@ mwifiex_cmd_append_vsie_tlv(struct mwifi
 			vs_param_set->header.len =
 				cpu_to_le16((((u16) priv->vs_ie[id].ie[1])
 				& 0x00FF) + 2);
+			if (le16_to_cpu(vs_param_set->header.len) >
+				MWIFIEX_MAX_VSIE_LEN) {
+				dev_info(priv->adapter->dev,
+					 "Invalid param length!\n");
+				break;
+			}
+
 			memcpy(vs_param_set->ie, priv->vs_ie[id].ie,
 			       le16_to_cpu(vs_param_set->header.len));
 			*buffer += le16_to_cpu(vs_param_set->header.len) +


^ permalink raw reply	[relevance 13%]

* [PATCH 3.16 08/61] net-sysfs: fix netdev_queue_add_kobject() breakage
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (6 preceding siblings ...)
  2020-06-09 18:03 12% ` [PATCH 3.16 07/61] net-sysfs: Fix reference count leak in rx|netdev_queue_add_kobject Ben Hutchings
@ 2020-06-09 18:03  9% ` Ben Hutchings
  2020-06-09 18:04 12% ` [PATCH 3.16 09/61] net-sysfs: Call dev_hold always in netdev_queue_add_kobject Ben Hutchings
                   ` (53 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:03 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, David S. Miller, Eric Dumazet, Jouni Hogander

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Eric Dumazet <edumazet@google.com>

commit 48a322b6f9965b2f1e4ce81af972f0e287b07ed0 upstream.

kobject_put() should only be called in error path.

Fixes: b8eb718348b8 ("net-sysfs: Fix reference count leak in rx|netdev_queue_add_kobject")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Jouni Hogander <jouni.hogander@unikie.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 net/core/net-sysfs.c | 1 +
 1 file changed, 1 insertion(+)

--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -1158,6 +1158,7 @@ static int netdev_queue_add_kobject(stru
 #endif
 
 	kobject_uevent(kobj, KOBJ_ADD);
+	return 0;
 
 err:
 	kobject_put(kobj);


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 15/61] selinux: properly handle multiple messages in selinux_netlink_send()
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (13 preceding siblings ...)
  2020-06-09 18:04  9% ` [PATCH 3.16 14/61] selinux: rate-limit netlink message warnings in selinux_nlmsg_perm() Ben Hutchings
@ 2020-06-09 18:04 11% ` Ben Hutchings
  2020-06-09 18:04  8% ` [PATCH 3.16 16/61] drivers: usb: core: Don't disable irqs in usb_sg_wait() during URB submit Ben Hutchings
                   ` (46 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Dmitry Vyukov, stable, Paul Moore, Stephen Smalley

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Paul Moore <paul@paul-moore.com>

commit fb73974172ffaaf57a7c42f35424d9aece1a5af6 upstream.

Fix the SELinux netlink_send hook to properly handle multiple netlink
messages in a single sk_buff; each message is parsed and subject to
SELinux access control.  Prior to this patch, SELinux only inspected
the first message in the sk_buff.

Cc: stable@vger.kernel.org
Reported-by: Dmitry Vyukov <dvyukov@google.com>
Reviewed-by: Stephen Smalley <stephen.smalley.work@gmail.com>
Signed-off-by: Paul Moore <paul@paul-moore.com>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -4669,39 +4669,59 @@ static int selinux_tun_dev_open(void *se
 
 static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
 {
-	int err = 0;
-	u32 perm;
+	int rc = 0;
+	unsigned int msg_len;
+	unsigned int data_len = skb->len;
+	unsigned char *data = skb->data;
 	struct nlmsghdr *nlh;
 	struct sk_security_struct *sksec = sk->sk_security;
+	u16 sclass = sksec->sclass;
+	u32 perm;
 
-	if (skb->len < NLMSG_HDRLEN) {
-		err = -EINVAL;
-		goto out;
-	}
-	nlh = nlmsg_hdr(skb);
+	while (data_len >= nlmsg_total_size(0)) {
+		nlh = (struct nlmsghdr *)data;
 
-	err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm);
-	if (err) {
-		if (err == -EINVAL) {
+		/* NOTE: the nlmsg_len field isn't reliably set by some netlink
+		 *       users which means we can't reject skb's with bogus
+		 *       length fields; our solution is to follow what
+		 *       netlink_rcv_skb() does and simply skip processing at
+		 *       messages with length fields that are clearly junk
+		 */
+		if (nlh->nlmsg_len < NLMSG_HDRLEN || nlh->nlmsg_len > data_len)
+			return 0;
+
+		rc = selinux_nlmsg_lookup(sclass, nlh->nlmsg_type, &perm);
+		if (rc == 0) {
+			rc = sock_has_perm(current, sk, perm);
+			if (rc)
+				return rc;
+		} else if (rc == -EINVAL) {
+			/* -EINVAL is a missing msg/perm mapping */
 			pr_warn_ratelimited("SELinux: unrecognized netlink"
-			       " message: protocol=%hu nlmsg_type=%hu sclass=%s"
-			       " pig=%d comm=%s\n",
-			       sk->sk_protocol, nlh->nlmsg_type,
-			       secclass_map[sksec->sclass - 1].name,
-			       task_pid_nr(current), current->comm);
-			if (!selinux_enforcing || security_get_allow_unknown())
-				err = 0;
+				" message: protocol=%hu nlmsg_type=%hu sclass=%s"
+				" pid=%d comm=%s\n",
+				sk->sk_protocol, nlh->nlmsg_type,
+				secclass_map[sclass - 1].name,
+				task_pid_nr(current), current->comm);
+			if (selinux_enforcing && !security_get_allow_unknown())
+				return rc;
+			rc = 0;
+		} else if (rc == -ENOENT) {
+			/* -ENOENT is a missing socket/class mapping, ignore */
+			rc = 0;
+		} else {
+			return rc;
 		}
 
-		/* Ignore */
-		if (err == -ENOENT)
-			err = 0;
-		goto out;
+		/* move to the next message after applying netlink padding */
+		msg_len = NLMSG_ALIGN(nlh->nlmsg_len);
+		if (msg_len >= data_len)
+			return 0;
+		data_len -= msg_len;
+		data += msg_len;
 	}
 
-	err = sock_has_perm(current, sk, perm);
-out:
-	return err;
+	return rc;
 }
 
 #ifdef CONFIG_NETFILTER


^ permalink raw reply	[relevance 11%]

* [PATCH 3.16 22/61] mwifiex: Fix possible buffer overflows in mwifiex_ret_wmm_get_status()
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (20 preceding siblings ...)
  2020-06-09 18:04 13% ` [PATCH 3.16 21/61] mwifiex: Fix possible buffer overflows in mwifiex_cmd_append_vsie_tlv() Ben Hutchings
@ 2020-06-09 18:04 13% ` Ben Hutchings
  2020-06-09 18:04  3% ` [PATCH 3.16 23/61] sg: O_EXCL and other lock handling Ben Hutchings
                   ` (39 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable; +Cc: akpm, Denis Kirjanov, Kalle Valo, Qing Xu

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Qing Xu <m1s5p6688@gmail.com>

commit 3a9b153c5591548612c3955c9600a98150c81875 upstream.

mwifiex_ret_wmm_get_status() calls memcpy() without checking the
destination size.Since the source is given from remote AP which
contains illegal wmm elements , this may trigger a heap buffer
overflow.
Fix it by putting the length check before calling memcpy().

Signed-off-by: Qing Xu <m1s5p6688@gmail.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
[bwh: Backported to 3.16: adjust filename]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/net/wireless/mwifiex/wmm.c | 4 ++++
 1 file changed, 4 insertions(+)

--- a/drivers/net/wireless/mwifiex/wmm.c
+++ b/drivers/net/wireless/mwifiex/wmm.c
@@ -791,6 +791,10 @@ int mwifiex_ret_wmm_get_status(struct mw
 				wmm_param_ie->qos_info_bitmap &
 				IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK);
 
+			if (wmm_param_ie->vend_hdr.len + 2 >
+				sizeof(struct ieee_types_wmm_parameter))
+				break;
+
 			memcpy((u8 *) &priv->curr_bss_params.bss_descriptor.
 			       wmm_ie, wmm_param_ie,
 			       wmm_param_ie->vend_hdr.len + 2);


^ permalink raw reply	[relevance 13%]

* [PATCH 3.16 20/61] scsi: mptfusion: Fix double fetch bug in ioctl
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (18 preceding siblings ...)
  2020-06-09 18:04  9% ` [PATCH 3.16 19/61] scsi: mptfusion: Add bounds check in mptctl_hp_targetinfo() Ben Hutchings
@ 2020-06-09 18:04  4% ` Ben Hutchings
  2020-06-09 18:04 13% ` [PATCH 3.16 21/61] mwifiex: Fix possible buffer overflows in mwifiex_cmd_append_vsie_tlv() Ben Hutchings
                   ` (41 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Dan Carpenter, Martin K. Petersen,
	Greg Kroah-Hartman, Tom Hatskevich

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Dan Carpenter <dan.carpenter@oracle.com>

commit 28d76df18f0ad5bcf5fa48510b225f0ed262a99b upstream.

Tom Hatskevich reported that we look up "iocp" then, in the called
functions we do a second copy_from_user() and look it up again.
The problem that could cause is:

drivers/message/fusion/mptctl.c
   674          /* All of these commands require an interrupt or
   675           * are unknown/illegal.
   676           */
   677          if ((ret = mptctl_syscall_down(iocp, nonblock)) != 0)
                                               ^^^^
We take this lock.

   678                  return ret;
   679
   680          if (cmd == MPTFWDOWNLOAD)
   681                  ret = mptctl_fw_download(arg);
                                                 ^^^
Then the user memory changes and we look up "iocp" again but a different
one so now we are holding the incorrect lock and have a race condition.

   682          else if (cmd == MPTCOMMAND)
   683                  ret = mptctl_mpt_command(arg);

The security impact of this bug is not as bad as it could have been
because these operations are all privileged and root already has
enormous destructive power.  But it's still worth fixing.

This patch passes the "iocp" pointer to the functions to avoid the
second lookup.  That deletes 100 lines of code from the driver so
it's a nice clean up as well.

Link: https://lore.kernel.org/r/20200114123414.GA7957@kadam
Reported-by: Tom Hatskevich <tom2001tom.23@gmail.com>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/message/fusion/mptctl.c | 213 ++++++++------------------------
 1 file changed, 50 insertions(+), 163 deletions(-)

--- a/drivers/message/fusion/mptctl.c
+++ b/drivers/message/fusion/mptctl.c
@@ -100,19 +100,19 @@ struct buflist {
  * Function prototypes. Called from OS entry point mptctl_ioctl.
  * arg contents specific to function.
  */
-static int mptctl_fw_download(unsigned long arg);
-static int mptctl_getiocinfo(unsigned long arg, unsigned int cmd);
-static int mptctl_gettargetinfo(unsigned long arg);
-static int mptctl_readtest(unsigned long arg);
-static int mptctl_mpt_command(unsigned long arg);
-static int mptctl_eventquery(unsigned long arg);
-static int mptctl_eventenable(unsigned long arg);
-static int mptctl_eventreport(unsigned long arg);
-static int mptctl_replace_fw(unsigned long arg);
-
-static int mptctl_do_reset(unsigned long arg);
-static int mptctl_hp_hostinfo(unsigned long arg, unsigned int cmd);
-static int mptctl_hp_targetinfo(unsigned long arg);
+static int mptctl_fw_download(MPT_ADAPTER *iocp, unsigned long arg);
+static int mptctl_getiocinfo(MPT_ADAPTER *iocp, unsigned long arg, unsigned int cmd);
+static int mptctl_gettargetinfo(MPT_ADAPTER *iocp, unsigned long arg);
+static int mptctl_readtest(MPT_ADAPTER *iocp, unsigned long arg);
+static int mptctl_mpt_command(MPT_ADAPTER *iocp, unsigned long arg);
+static int mptctl_eventquery(MPT_ADAPTER *iocp, unsigned long arg);
+static int mptctl_eventenable(MPT_ADAPTER *iocp, unsigned long arg);
+static int mptctl_eventreport(MPT_ADAPTER *iocp, unsigned long arg);
+static int mptctl_replace_fw(MPT_ADAPTER *iocp, unsigned long arg);
+
+static int mptctl_do_reset(MPT_ADAPTER *iocp, unsigned long arg);
+static int mptctl_hp_hostinfo(MPT_ADAPTER *iocp, unsigned long arg, unsigned int cmd);
+static int mptctl_hp_targetinfo(MPT_ADAPTER *iocp, unsigned long arg);
 
 static int  mptctl_probe(struct pci_dev *, const struct pci_device_id *);
 static void mptctl_remove(struct pci_dev *);
@@ -123,8 +123,8 @@ static long compat_mpctl_ioctl(struct fi
 /*
  * Private function calls.
  */
-static int mptctl_do_mpt_command(struct mpt_ioctl_command karg, void __user *mfPtr);
-static int mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen);
+static int mptctl_do_mpt_command(MPT_ADAPTER *iocp, struct mpt_ioctl_command karg, void __user *mfPtr);
+static int mptctl_do_fw_download(MPT_ADAPTER *iocp, char __user *ufwbuf, size_t fwlen);
 static MptSge_t *kbuf_alloc_2_sgl(int bytes, u32 dir, int sge_offset, int *frags,
 		struct buflist **blp, dma_addr_t *sglbuf_dma, MPT_ADAPTER *ioc);
 static void kfree_sgl(MptSge_t *sgl, dma_addr_t sgl_dma,
@@ -656,19 +656,19 @@ __mptctl_ioctl(struct file *file, unsign
 	 * by TM and FW reloads.
 	 */
 	if ((cmd & ~IOCSIZE_MASK) == (MPTIOCINFO & ~IOCSIZE_MASK)) {
-		return mptctl_getiocinfo(arg, _IOC_SIZE(cmd));
+		return mptctl_getiocinfo(iocp, arg, _IOC_SIZE(cmd));
 	} else if (cmd == MPTTARGETINFO) {
-		return mptctl_gettargetinfo(arg);
+		return mptctl_gettargetinfo(iocp, arg);
 	} else if (cmd == MPTTEST) {
-		return mptctl_readtest(arg);
+		return mptctl_readtest(iocp, arg);
 	} else if (cmd == MPTEVENTQUERY) {
-		return mptctl_eventquery(arg);
+		return mptctl_eventquery(iocp, arg);
 	} else if (cmd == MPTEVENTENABLE) {
-		return mptctl_eventenable(arg);
+		return mptctl_eventenable(iocp, arg);
 	} else if (cmd == MPTEVENTREPORT) {
-		return mptctl_eventreport(arg);
+		return mptctl_eventreport(iocp, arg);
 	} else if (cmd == MPTFWREPLACE) {
-		return mptctl_replace_fw(arg);
+		return mptctl_replace_fw(iocp, arg);
 	}
 
 	/* All of these commands require an interrupt or
@@ -678,15 +678,15 @@ __mptctl_ioctl(struct file *file, unsign
 		return ret;
 
 	if (cmd == MPTFWDOWNLOAD)
-		ret = mptctl_fw_download(arg);
+		ret = mptctl_fw_download(iocp, arg);
 	else if (cmd == MPTCOMMAND)
-		ret = mptctl_mpt_command(arg);
+		ret = mptctl_mpt_command(iocp, arg);
 	else if (cmd == MPTHARDRESET)
-		ret = mptctl_do_reset(arg);
+		ret = mptctl_do_reset(iocp, arg);
 	else if ((cmd & ~IOCSIZE_MASK) == (HP_GETHOSTINFO & ~IOCSIZE_MASK))
-		ret = mptctl_hp_hostinfo(arg, _IOC_SIZE(cmd));
+		ret = mptctl_hp_hostinfo(iocp, arg, _IOC_SIZE(cmd));
 	else if (cmd == HP_GETTARGETINFO)
-		ret = mptctl_hp_targetinfo(arg);
+		ret = mptctl_hp_targetinfo(iocp, arg);
 	else
 		ret = -EINVAL;
 
@@ -705,11 +705,10 @@ mptctl_ioctl(struct file *file, unsigned
 	return ret;
 }
 
-static int mptctl_do_reset(unsigned long arg)
+static int mptctl_do_reset(MPT_ADAPTER *iocp, unsigned long arg)
 {
 	struct mpt_ioctl_diag_reset __user *urinfo = (void __user *) arg;
 	struct mpt_ioctl_diag_reset krinfo;
-	MPT_ADAPTER		*iocp;
 
 	if (copy_from_user(&krinfo, urinfo, sizeof(struct mpt_ioctl_diag_reset))) {
 		printk(KERN_ERR MYNAM "%s@%d::mptctl_do_reset - "
@@ -718,12 +717,6 @@ static int mptctl_do_reset(unsigned long
 		return -EFAULT;
 	}
 
-	if (mpt_verify_adapter(krinfo.hdr.iocnum, &iocp) < 0) {
-		printk(KERN_DEBUG MYNAM "%s@%d::mptctl_do_reset - ioc%d not found!\n",
-				__FILE__, __LINE__, krinfo.hdr.iocnum);
-		return -ENODEV; /* (-6) No such device or address */
-	}
-
 	dctlprintk(iocp, printk(MYIOC_s_DEBUG_FMT "mptctl_do_reset called.\n",
 	    iocp->name));
 
@@ -754,7 +747,7 @@ static int mptctl_do_reset(unsigned long
  *		-ENOMSG if FW upload returned bad status
  */
 static int
-mptctl_fw_download(unsigned long arg)
+mptctl_fw_download(MPT_ADAPTER *iocp, unsigned long arg)
 {
 	struct mpt_fw_xfer __user *ufwdl = (void __user *) arg;
 	struct mpt_fw_xfer	 kfwdl;
@@ -766,7 +759,7 @@ mptctl_fw_download(unsigned long arg)
 		return -EFAULT;
 	}
 
-	return mptctl_do_fw_download(kfwdl.iocnum, kfwdl.bufp, kfwdl.fwlen);
+	return mptctl_do_fw_download(iocp, kfwdl.bufp, kfwdl.fwlen);
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -784,11 +777,10 @@ mptctl_fw_download(unsigned long arg)
  *		-ENOMSG if FW upload returned bad status
  */
 static int
-mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen)
+mptctl_do_fw_download(MPT_ADAPTER *iocp, char __user *ufwbuf, size_t fwlen)
 {
 	FWDownload_t		*dlmsg;
 	MPT_FRAME_HDR		*mf;
-	MPT_ADAPTER		*iocp;
 	FWDownloadTCSGE_t	*ptsge;
 	MptSge_t		*sgl, *sgIn;
 	char			*sgOut;
@@ -808,17 +800,10 @@ mptctl_do_fw_download(int ioc, char __us
 	pFWDownloadReply_t	 ReplyMsg = NULL;
 	unsigned long		 timeleft;
 
-	if (mpt_verify_adapter(ioc, &iocp) < 0) {
-		printk(KERN_DEBUG MYNAM "ioctl_fwdl - ioc%d not found!\n",
-				 ioc);
-		return -ENODEV; /* (-6) No such device or address */
-	} else {
-
-		/*  Valid device. Get a message frame and construct the FW download message.
-	 	*/
-		if ((mf = mpt_get_msg_frame(mptctl_id, iocp)) == NULL)
-			return -EAGAIN;
-	}
+	/*  Valid device. Get a message frame and construct the FW download message.
+	*/
+	if ((mf = mpt_get_msg_frame(mptctl_id, iocp)) == NULL)
+		return -EAGAIN;
 
 	dctlprintk(iocp, printk(MYIOC_s_DEBUG_FMT
 	    "mptctl_do_fwdl called. mptctl_id = %xh.\n", iocp->name, mptctl_id));
@@ -826,8 +811,6 @@ mptctl_do_fw_download(int ioc, char __us
 	    iocp->name, ufwbuf));
 	dctlprintk(iocp, printk(MYIOC_s_DEBUG_FMT "DbG: kfwdl.fwlen = %d\n",
 	    iocp->name, (int)fwlen));
-	dctlprintk(iocp, printk(MYIOC_s_DEBUG_FMT "DbG: kfwdl.ioc   = %04xh\n",
-	    iocp->name, ioc));
 
 	dlmsg = (FWDownload_t*) mf;
 	ptsge = (FWDownloadTCSGE_t *) &dlmsg->SGL;
@@ -1234,13 +1217,11 @@ kfree_sgl(MptSge_t *sgl, dma_addr_t sgl_
  *		-ENODEV  if no such device/adapter
  */
 static int
-mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
+mptctl_getiocinfo (MPT_ADAPTER *ioc, unsigned long arg, unsigned int data_size)
 {
 	struct mpt_ioctl_iocinfo __user *uarg = (void __user *) arg;
 	struct mpt_ioctl_iocinfo *karg;
-	MPT_ADAPTER		*ioc;
 	struct pci_dev		*pdev;
-	int			iocnum;
 	unsigned int		port;
 	int			cim_rev;
 	struct scsi_device 	*sdev;
@@ -1276,14 +1257,6 @@ mptctl_getiocinfo (unsigned long arg, un
 		return -EFAULT;
 	}
 
-	if (((iocnum = mpt_verify_adapter(karg->hdr.iocnum, &ioc)) < 0) ||
-	    (ioc == NULL)) {
-		printk(KERN_DEBUG MYNAM "%s::mptctl_getiocinfo() @%d - ioc%d not found!\n",
-				__FILE__, __LINE__, iocnum);
-		kfree(karg);
-		return -ENODEV;
-	}
-
 	/* Verify the data transfer size is correct. */
 	if (karg->hdr.maxDataSize != data_size) {
 		printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_getiocinfo - "
@@ -1389,15 +1362,13 @@ mptctl_getiocinfo (unsigned long arg, un
  *		-ENODEV  if no such device/adapter
  */
 static int
-mptctl_gettargetinfo (unsigned long arg)
+mptctl_gettargetinfo (MPT_ADAPTER *ioc, unsigned long arg)
 {
 	struct mpt_ioctl_targetinfo __user *uarg = (void __user *) arg;
 	struct mpt_ioctl_targetinfo karg;
-	MPT_ADAPTER		*ioc;
 	VirtDevice		*vdevice;
 	char			*pmem;
 	int			*pdata;
-	int			iocnum;
 	int			numDevices = 0;
 	int			lun;
 	int			maxWordsLeft;
@@ -1412,13 +1383,6 @@ mptctl_gettargetinfo (unsigned long arg)
 		return -EFAULT;
 	}
 
-	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
-	    (ioc == NULL)) {
-		printk(KERN_DEBUG MYNAM "%s::mptctl_gettargetinfo() @%d - ioc%d not found!\n",
-				__FILE__, __LINE__, iocnum);
-		return -ENODEV;
-	}
-
 	dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_gettargetinfo called.\n",
 	    ioc->name));
 	/* Get the port number and set the maximum number of bytes
@@ -1514,12 +1478,10 @@ mptctl_gettargetinfo (unsigned long arg)
  *		-ENODEV  if no such device/adapter
  */
 static int
-mptctl_readtest (unsigned long arg)
+mptctl_readtest (MPT_ADAPTER *ioc, unsigned long arg)
 {
 	struct mpt_ioctl_test __user *uarg = (void __user *) arg;
 	struct mpt_ioctl_test	 karg;
-	MPT_ADAPTER *ioc;
-	int iocnum;
 
 	if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_test))) {
 		printk(KERN_ERR MYNAM "%s@%d::mptctl_readtest - "
@@ -1528,13 +1490,6 @@ mptctl_readtest (unsigned long arg)
 		return -EFAULT;
 	}
 
-	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
-	    (ioc == NULL)) {
-		printk(KERN_DEBUG MYNAM "%s::mptctl_readtest() @%d - ioc%d not found!\n",
-				__FILE__, __LINE__, iocnum);
-		return -ENODEV;
-	}
-
 	dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_readtest called.\n",
 	    ioc->name));
 	/* Fill in the data and return the structure to the calling
@@ -1575,12 +1530,10 @@ mptctl_readtest (unsigned long arg)
  *		-ENODEV  if no such device/adapter
  */
 static int
-mptctl_eventquery (unsigned long arg)
+mptctl_eventquery (MPT_ADAPTER *ioc, unsigned long arg)
 {
 	struct mpt_ioctl_eventquery __user *uarg = (void __user *) arg;
 	struct mpt_ioctl_eventquery	 karg;
-	MPT_ADAPTER *ioc;
-	int iocnum;
 
 	if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventquery))) {
 		printk(KERN_ERR MYNAM "%s@%d::mptctl_eventquery - "
@@ -1589,13 +1542,6 @@ mptctl_eventquery (unsigned long arg)
 		return -EFAULT;
 	}
 
-	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
-	    (ioc == NULL)) {
-		printk(KERN_DEBUG MYNAM "%s::mptctl_eventquery() @%d - ioc%d not found!\n",
-				__FILE__, __LINE__, iocnum);
-		return -ENODEV;
-	}
-
 	dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_eventquery called.\n",
 	    ioc->name));
 	karg.eventEntries = MPTCTL_EVENT_LOG_SIZE;
@@ -1614,12 +1560,10 @@ mptctl_eventquery (unsigned long arg)
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 static int
-mptctl_eventenable (unsigned long arg)
+mptctl_eventenable (MPT_ADAPTER *ioc, unsigned long arg)
 {
 	struct mpt_ioctl_eventenable __user *uarg = (void __user *) arg;
 	struct mpt_ioctl_eventenable	 karg;
-	MPT_ADAPTER *ioc;
-	int iocnum;
 
 	if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventenable))) {
 		printk(KERN_ERR MYNAM "%s@%d::mptctl_eventenable - "
@@ -1628,13 +1572,6 @@ mptctl_eventenable (unsigned long arg)
 		return -EFAULT;
 	}
 
-	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
-	    (ioc == NULL)) {
-		printk(KERN_DEBUG MYNAM "%s::mptctl_eventenable() @%d - ioc%d not found!\n",
-				__FILE__, __LINE__, iocnum);
-		return -ENODEV;
-	}
-
 	dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_eventenable called.\n",
 	    ioc->name));
 	if (ioc->events == NULL) {
@@ -1662,12 +1599,10 @@ mptctl_eventenable (unsigned long arg)
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 static int
-mptctl_eventreport (unsigned long arg)
+mptctl_eventreport (MPT_ADAPTER *ioc, unsigned long arg)
 {
 	struct mpt_ioctl_eventreport __user *uarg = (void __user *) arg;
 	struct mpt_ioctl_eventreport	 karg;
-	MPT_ADAPTER		 *ioc;
-	int			 iocnum;
 	int			 numBytes, maxEvents, max;
 
 	if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventreport))) {
@@ -1677,12 +1612,6 @@ mptctl_eventreport (unsigned long arg)
 		return -EFAULT;
 	}
 
-	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
-	    (ioc == NULL)) {
-		printk(KERN_DEBUG MYNAM "%s::mptctl_eventreport() @%d - ioc%d not found!\n",
-				__FILE__, __LINE__, iocnum);
-		return -ENODEV;
-	}
 	dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_eventreport called.\n",
 	    ioc->name));
 
@@ -1716,12 +1645,10 @@ mptctl_eventreport (unsigned long arg)
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 static int
-mptctl_replace_fw (unsigned long arg)
+mptctl_replace_fw (MPT_ADAPTER *ioc, unsigned long arg)
 {
 	struct mpt_ioctl_replace_fw __user *uarg = (void __user *) arg;
 	struct mpt_ioctl_replace_fw	 karg;
-	MPT_ADAPTER		 *ioc;
-	int			 iocnum;
 	int			 newFwSize;
 
 	if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_replace_fw))) {
@@ -1731,13 +1658,6 @@ mptctl_replace_fw (unsigned long arg)
 		return -EFAULT;
 	}
 
-	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
-	    (ioc == NULL)) {
-		printk(KERN_DEBUG MYNAM "%s::mptctl_replace_fw() @%d - ioc%d not found!\n",
-				__FILE__, __LINE__, iocnum);
-		return -ENODEV;
-	}
-
 	dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_replace_fw called.\n",
 	    ioc->name));
 	/* If caching FW, Free the old FW image
@@ -1789,12 +1709,10 @@ mptctl_replace_fw (unsigned long arg)
  *		-ENOMEM if memory allocation error
  */
 static int
-mptctl_mpt_command (unsigned long arg)
+mptctl_mpt_command (MPT_ADAPTER *ioc, unsigned long arg)
 {
 	struct mpt_ioctl_command __user *uarg = (void __user *) arg;
 	struct mpt_ioctl_command  karg;
-	MPT_ADAPTER	*ioc;
-	int		iocnum;
 	int		rc;
 
 
@@ -1805,14 +1723,7 @@ mptctl_mpt_command (unsigned long arg)
 		return -EFAULT;
 	}
 
-	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
-	    (ioc == NULL)) {
-		printk(KERN_DEBUG MYNAM "%s::mptctl_mpt_command() @%d - ioc%d not found!\n",
-				__FILE__, __LINE__, iocnum);
-		return -ENODEV;
-	}
-
-	rc = mptctl_do_mpt_command (karg, &uarg->MF);
+	rc = mptctl_do_mpt_command (ioc, karg, &uarg->MF);
 
 	return rc;
 }
@@ -1830,9 +1741,8 @@ mptctl_mpt_command (unsigned long arg)
  *		-EPERM if SCSI I/O and target is untagged
  */
 static int
-mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
+mptctl_do_mpt_command (MPT_ADAPTER *ioc, struct mpt_ioctl_command karg, void __user *mfPtr)
 {
-	MPT_ADAPTER	*ioc;
 	MPT_FRAME_HDR	*mf = NULL;
 	MPIHeader_t	*hdr;
 	char		*psge;
@@ -1841,7 +1751,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_
 	dma_addr_t	dma_addr_in;
 	dma_addr_t	dma_addr_out;
 	int		sgSize = 0;	/* Num SG elements */
-	int		iocnum, flagsLength;
+	int		flagsLength;
 	int		sz, rc = 0;
 	int		msgContext;
 	u16		req_idx;
@@ -1856,13 +1766,6 @@ mptctl_do_mpt_command (struct mpt_ioctl_
 	bufIn.kptr = bufOut.kptr = NULL;
 	bufIn.len = bufOut.len = 0;
 
-	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
-	    (ioc == NULL)) {
-		printk(KERN_DEBUG MYNAM "%s::mptctl_do_mpt_command() @%d - ioc%d not found!\n",
-				__FILE__, __LINE__, iocnum);
-		return -ENODEV;
-	}
-
 	spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
 	if (ioc->ioc_reset_in_progress) {
 		spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
@@ -2418,17 +2321,15 @@ done_free_mem:
  *		-ENOMEM if memory allocation error
  */
 static int
-mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
+mptctl_hp_hostinfo(MPT_ADAPTER *ioc, unsigned long arg, unsigned int data_size)
 {
 	hp_host_info_t	__user *uarg = (void __user *) arg;
-	MPT_ADAPTER		*ioc;
 	struct pci_dev		*pdev;
 	char                    *pbuf=NULL;
 	dma_addr_t		buf_dma;
 	hp_host_info_t		karg;
 	CONFIGPARMS		cfg;
 	ConfigPageHeader_t	hdr;
-	int			iocnum;
 	int			rc, cim_rev;
 	ToolboxIstwiReadWriteRequest_t	*IstwiRWRequest;
 	MPT_FRAME_HDR		*mf = NULL;
@@ -2452,12 +2353,6 @@ mptctl_hp_hostinfo(unsigned long arg, un
 		return -EFAULT;
 	}
 
-	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
-	    (ioc == NULL)) {
-		printk(KERN_DEBUG MYNAM "%s::mptctl_hp_hostinfo() @%d - ioc%d not found!\n",
-				__FILE__, __LINE__, iocnum);
-		return -ENODEV;
-	}
 	dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": mptctl_hp_hostinfo called.\n",
 	    ioc->name));
 
@@ -2670,15 +2565,13 @@ retry_wait:
  *		-ENOMEM if memory allocation error
  */
 static int
-mptctl_hp_targetinfo(unsigned long arg)
+mptctl_hp_targetinfo(MPT_ADAPTER *ioc, unsigned long arg)
 {
 	hp_target_info_t __user *uarg = (void __user *) arg;
 	SCSIDevicePage0_t	*pg0_alloc;
 	SCSIDevicePage3_t	*pg3_alloc;
-	MPT_ADAPTER		*ioc;
 	MPT_SCSI_HOST 		*hd = NULL;
 	hp_target_info_t	karg;
-	int			iocnum;
 	int			data_sz;
 	dma_addr_t		page_dma;
 	CONFIGPARMS	 	cfg;
@@ -2692,12 +2585,6 @@ mptctl_hp_targetinfo(unsigned long arg)
 		return -EFAULT;
 	}
 
-	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
-		(ioc == NULL)) {
-		printk(KERN_DEBUG MYNAM "%s::mptctl_hp_targetinfo() @%d - ioc%d not found!\n",
-				__FILE__, __LINE__, iocnum);
-		return -ENODEV;
-	}
 	if (karg.hdr.id >= MPT_MAX_FC_DEVICES)
 		return -EINVAL;
 	dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_hp_targetinfo called.\n",
@@ -2865,7 +2752,7 @@ compat_mptfwxfer_ioctl(struct file *filp
 	kfw.fwlen = kfw32.fwlen;
 	kfw.bufp = compat_ptr(kfw32.bufp);
 
-	ret = mptctl_do_fw_download(kfw.iocnum, kfw.bufp, kfw.fwlen);
+	ret = mptctl_do_fw_download(iocp, kfw.bufp, kfw.fwlen);
 
 	mutex_unlock(&iocp->ioctl_cmds.mutex);
 
@@ -2919,7 +2806,7 @@ compat_mpt_command(struct file *filp, un
 
 	/* Pass new structure to do_mpt_command
 	 */
-	ret = mptctl_do_mpt_command (karg, &uarg->MF);
+	ret = mptctl_do_mpt_command (iocp, karg, &uarg->MF);
 
 	mutex_unlock(&iocp->ioctl_cmds.mutex);
 


^ permalink raw reply	[relevance 4%]

* [PATCH 3.16 24/61] sg: prevent integer overflow when converting from sectors to bytes
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (22 preceding siblings ...)
  2020-06-09 18:04  3% ` [PATCH 3.16 23/61] sg: O_EXCL and other lock handling Ben Hutchings
@ 2020-06-09 18:04  8% ` Ben Hutchings
  2020-06-09 18:04 10% ` [PATCH 3.16 25/61] scsi: sg: Change next_cmd_len handling to mirror upstream Ben Hutchings
                   ` (37 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Akinobu Mita, Christoph Hellwig

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Akinobu Mita <akinobu.mita@gmail.com>

commit 46f69e6a6bbbf3858617c8729e31895846c15a79 upstream.

This prevents integer overflow when converting the request queue's
max_sectors from sectors to bytes.  However, this is a preparation for
extending the data type of max_sectors in struct Scsi_Host and
scsi_host_template.  So, it is impossible to happen this integer
overflow for now, because SCSI low-level drivers can not specify
max_sectors greater than 0xffff due to the data type limitation.

Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com>
Acked by: Douglas Gilbert <dgilbert@interlog.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/scsi/sg.c | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -865,6 +865,15 @@ static int srp_done(Sg_fd *sfp, Sg_reque
 	return ret;
 }
 
+static int max_sectors_bytes(struct request_queue *q)
+{
+	unsigned int max_sectors = queue_max_sectors(q);
+
+	max_sectors = min_t(unsigned int, max_sectors, INT_MAX >> 9);
+
+	return max_sectors << 9;
+}
+
 static long
 sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
 {
@@ -1004,7 +1013,7 @@ sg_ioctl(struct file *filp, unsigned int
                 if (val < 0)
                         return -EINVAL;
 		val = min_t(int, val,
-			    queue_max_sectors(sdp->device->request_queue) * 512);
+			    max_sectors_bytes(sdp->device->request_queue));
 		if (val != sfp->reserve.bufflen) {
 			if (sg_res_in_use(sfp) || sfp->mmap_called)
 				return -EBUSY;
@@ -1014,7 +1023,7 @@ sg_ioctl(struct file *filp, unsigned int
 		return 0;
 	case SG_GET_RESERVED_SIZE:
 		val = min_t(int, sfp->reserve.bufflen,
-			    queue_max_sectors(sdp->device->request_queue) * 512);
+			    max_sectors_bytes(sdp->device->request_queue));
 		return put_user(val, ip);
 	case SG_SET_COMMAND_Q:
 		result = get_user(val, ip);
@@ -1154,7 +1163,7 @@ sg_ioctl(struct file *filp, unsigned int
 			return -ENODEV;
 		return scsi_ioctl(sdp->device, cmd_in, p);
 	case BLKSECTGET:
-		return put_user(queue_max_sectors(sdp->device->request_queue) * 512,
+		return put_user(max_sectors_bytes(sdp->device->request_queue),
 				ip);
 	case BLKTRACESETUP:
 		return blk_trace_setup(sdp->device->request_queue,
@@ -2170,7 +2179,7 @@ sg_add_sfp(Sg_device * sdp, int dev)
 		sg_big_buff = def_reserved_size;
 
 	bufflen = min_t(int, sg_big_buff,
-			queue_max_sectors(sdp->device->request_queue) * 512);
+			max_sectors_bytes(sdp->device->request_queue));
 	sg_build_reserve(sfp, bufflen);
 	SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp:   bufflen=%d, k_use_sg=%d\n",
 			   sfp->reserve.bufflen, sfp->reserve.k_use_sg));


^ permalink raw reply	[relevance 8%]

* [PATCH 3.16 32/61] scsi: sg: off by one in sg_ioctl()
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (30 preceding siblings ...)
  2020-06-09 18:04  6% ` [PATCH 3.16 31/61] scsi: sg: use standard lists for sg_requests Ben Hutchings
@ 2020-06-09 18:04  9% ` Ben Hutchings
  2020-06-09 18:04  8% ` [PATCH 3.16 33/61] scsi: sg: factor out sg_fill_request_table() Ben Hutchings
                   ` (29 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Douglas Gilbert, Greg Kroah-Hartman,
	Martin K. Petersen, Dan Carpenter

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Dan Carpenter <dan.carpenter@oracle.com>

commit bd46fc406b30d1db1aff8dabaff8d18bb423fdcf upstream.

If "val" is SG_MAX_QUEUE then we are one element beyond the end of the
"rinfo" array so the > should be >=.

Fixes: 109bade9c625 ("scsi: sg: use standard lists for sg_requests")
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Acked-by: Douglas Gilbert <dgilbert@interlog.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/scsi/sg.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -1072,7 +1072,7 @@ sg_ioctl(struct file *filp, unsigned int
 			read_lock_irqsave(&sfp->rq_list_lock, iflags);
 			val = 0;
 			list_for_each_entry(srp, &sfp->rq_list, entry) {
-				if (val > SG_MAX_QUEUE)
+				if (val >= SG_MAX_QUEUE)
 					break;
 				memset(&rinfo[val], 0, SZ_SG_REQ_INFO);
 				rinfo[val].req_state = srp->done + 1;


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 29/61] scsi: sg: recheck MMAP_IO request length with lock held
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (27 preceding siblings ...)
  2020-06-09 18:04  9% ` [PATCH 3.16 28/61] scsi: sg: protect against races between mmap() and SG_SET_RESERVED_SIZE Ben Hutchings
@ 2020-06-09 18:04  9% ` Ben Hutchings
  2020-06-09 18:04  9% ` [PATCH 3.16 30/61] scsi: sg: remove 'save_scat_len' Ben Hutchings
                   ` (32 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Douglas Gilbert, Greg Kroah-Hartman,
	Martin K. Petersen, Todd Poynor

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Todd Poynor <toddpoynor@google.com>

commit 8d26f491116feaa0b16de370b6a7ba40a40fa0b4 upstream.

Commit 1bc0eb044615 ("scsi: sg: protect accesses to 'reserved' page
array") adds needed concurrency protection for the "reserve" buffer.
Some checks that are initially made outside the lock are replicated once
the lock is taken to ensure the checks and resulting decisions are made
using consistent state.

The check that a request with flag SG_FLAG_MMAP_IO set fits in the
reserve buffer also needs to be performed again under the lock to ensure
the reserve buffer length compared against matches the value in effect
when the request is linked to the reserve buffer.  An -ENOMEM should be
returned in this case, instead of switching over to an indirect buffer
as for non-MMAP_IO requests.

Signed-off-by: Todd Poynor <toddpoynor@google.com>
Acked-by: Douglas Gilbert <dgilbert@interlog.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/scsi/sg.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -1772,9 +1772,12 @@ sg_start_req(Sg_request *srp, unsigned c
 		    !sfp->res_in_use) {
 			sfp->res_in_use = 1;
 			sg_link_reserve(sfp, srp, dxfer_len);
-		} else if ((hp->flags & SG_FLAG_MMAP_IO) && sfp->res_in_use) {
+		} else if (hp->flags & SG_FLAG_MMAP_IO) {
+			res = -EBUSY; /* sfp->res_in_use == 1 */
+			if (dxfer_len > rsv_schp->bufflen)
+				res = -ENOMEM;
 			mutex_unlock(&sfp->f_mutex);
-			return -EBUSY;
+			return res;
 		} else {
 			res = sg_build_indirect(req_schp, sfp, dxfer_len);
 			if (res) {


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 45/61] scsi: sg: add sg_remove_request in sg_write
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (43 preceding siblings ...)
  2020-06-09 18:04  9% ` [PATCH 3.16 44/61] scsi: sg: add sg_remove_request in sg_common_write Ben Hutchings
@ 2020-06-09 18:04  9% ` Ben Hutchings
  2020-06-09 18:04 11% ` [PATCH 3.16 46/61] signal: Extend exec_id to 64bits Ben Hutchings
                   ` (16 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Martin K. Petersen, Wu Bo, Guenter Roeck,
	Sasha Levin, Douglas Gilbert, Greg Kroah-Hartman

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Wu Bo <wubo40@huawei.com>

commit 83c6f2390040f188cc25b270b4befeb5628c1aee upstream.

If the __copy_from_user function failed we need to call sg_remove_request
in sg_write.

Link: https://lore.kernel.org/r/610618d9-e983-fd56-ed0f-639428343af7@huawei.com
Acked-by: Douglas Gilbert <dgilbert@interlog.com>
Signed-off-by: Wu Bo <wubo40@huawei.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
[groeck: Backport to v5.4.y and older kernels]
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/scsi/sg.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -696,8 +696,10 @@ sg_write(struct file *filp, const char _
 	hp->flags = input_size;	/* structure abuse ... */
 	hp->pack_id = old_hdr.pack_id;
 	hp->usr_ptr = NULL;
-	if (__copy_from_user(cmnd, buf, cmd_size))
+	if (__copy_from_user(cmnd, buf, cmd_size)) {
+		sg_remove_request(sfp, srp);
 		return -EFAULT;
+	}
 	/*
 	 * SG_DXFER_TO_FROM_DEV is functionally equivalent to SG_DXFER_FROM_DEV,
 	 * but is is possible that the app intended SG_DXFER_TO_DEV, because there


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 59/61] x86/speculation: Add Ivy Bridge to affected list
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (57 preceding siblings ...)
  2020-06-09 18:04  6% ` [PATCH 3.16 58/61] x86/speculation: Add SRBDS vulnerability and mitigation documentation Ben Hutchings
@ 2020-06-09 18:04  9% ` Ben Hutchings
  2020-06-09 18:04 11% ` [PATCH 3.16 60/61] random: always use batched entropy for get_random_u{32,64} Ben Hutchings
                   ` (2 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Thomas Gleixner, Josh Poimboeuf

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Josh Poimboeuf <jpoimboe@redhat.com>

commit 3798cc4d106e91382bfe016caa2edada27c2bb3f upstream.

Make the docs match the code.

Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 .../hw-vuln/special-register-buffer-data-sampling.rst      | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

--- a/Documentation/hw-vuln/special-register-buffer-data-sampling.rst
+++ b/Documentation/hw-vuln/special-register-buffer-data-sampling.rst
@@ -27,6 +27,8 @@ by software using TSX_CTRL_MSR otherwise
   =============  ============  ========
   common name    Family_Model  Stepping
   =============  ============  ========
+  IvyBridge      06_3AH        All
+
   Haswell        06_3CH        All
   Haswell_L      06_45H        All
   Haswell_G      06_46H        All
@@ -37,9 +39,8 @@ by software using TSX_CTRL_MSR otherwise
   Skylake_L      06_4EH        All
   Skylake        06_5EH        All
 
-  Kabylake_L     06_8EH        <=0xC
-
-  Kabylake       06_9EH        <=0xD
+  Kabylake_L     06_8EH        <= 0xC
+  Kabylake       06_9EH        <= 0xD
   =============  ============  ========
 
 Related CVEs


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 25/61] scsi: sg: Change next_cmd_len handling to mirror upstream
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (23 preceding siblings ...)
  2020-06-09 18:04  8% ` [PATCH 3.16 24/61] sg: prevent integer overflow when converting from sectors to bytes Ben Hutchings
@ 2020-06-09 18:04 10% ` Ben Hutchings
  2020-06-09 18:04  7% ` [PATCH 3.16 26/61] scsi: sg: protect accesses to 'reserved' page array Ben Hutchings
                   ` (36 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable; +Cc: akpm, Denis Kirjanov

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Ben Hutchings <ben@decadent.org.uk>

Change the type of next_cmd_len to unsigned char, done in upstream
commit 65c26a0f3969 "sg: relax 16 byte cdb restriction".

Move the range check from sg_write() to sg_ioctl(), which was done by
that commit and commit bf33f87dd04c "scsi: sg: check length passed to
SG_NEXT_CMD_LEN".  Continue limiting the command length to
MAX_COMMAND_SIZE (16).

Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -160,7 +160,7 @@ typedef struct sg_fd {		/* holds the sta
 	char low_dma;		/* as in parent but possibly overridden to 1 */
 	char force_packid;	/* 1 -> pack_id input to read(), 0 -> ignored */
 	char cmd_q;		/* 1 -> allow command queuing, 0 -> don't */
-	char next_cmd_len;	/* 0 -> automatic (def), >0 -> use on next write() */
+	unsigned char next_cmd_len; /* 0: automatic, >0: use on next write() */
 	char keep_orphan;	/* 0 -> drop orphan (def), 1 -> keep for read() */
 	char mmap_called;	/* 0 -> mmap() never called on this fd */
 	struct kref f_ref;
@@ -653,12 +653,6 @@ sg_write(struct file *filp, const char _
 	buf += SZ_SG_HEADER;
 	__get_user(opcode, buf);
 	if (sfp->next_cmd_len > 0) {
-		if (sfp->next_cmd_len > MAX_COMMAND_SIZE) {
-			SCSI_LOG_TIMEOUT(1, printk("sg_write: command length too long\n"));
-			sfp->next_cmd_len = 0;
-			sg_remove_request(sfp, srp);
-			return -EIO;
-		}
 		cmd_size = sfp->next_cmd_len;
 		sfp->next_cmd_len = 0;	/* reset so only this write() effected */
 	} else {
@@ -1045,6 +1039,8 @@ sg_ioctl(struct file *filp, unsigned int
 		result = get_user(val, ip);
 		if (result)
 			return result;
+		if (val > MAX_COMMAND_SIZE)
+			return -ENOMEM;
 		sfp->next_cmd_len = (val > 0) ? val : 0;
 		return 0;
 	case SG_GET_VERSION_NUM:


^ permalink raw reply	[relevance 10%]

* [PATCH 3.16 48/61] ext4: Make checks for metadata_csum feature safer
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (46 preceding siblings ...)
  2020-06-09 18:04  8% ` [PATCH 3.16 47/61] USB: gadget: fix illegal array access in binding with UDC Ben Hutchings
@ 2020-06-09 18:04 13% ` Ben Hutchings
  2020-06-09 18:04 11% ` [PATCH 3.16 49/61] ext4: protect journal inode's blocks using block_validity Ben Hutchings
                   ` (13 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable; +Cc: akpm, Denis Kirjanov, Tahsin Erdogan, Jan Kara

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Tahsin Erdogan <tahsin@google.com>

This is just a small part of commit dec214d00e0d7 "ext4: xattr inode
deduplication" that makes checks for metadata_csum feature safer and is
actually needed by following fixes.

Signed-off-by: Tahsin Erdogan <tahsin@google.com>
Acked-by: Jan Kara <jack@suse.cz>
[bwh: Ported to 3.16: Use EXT4_HAS_RO_COMPAT_FEATURE()]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -2411,21 +2411,24 @@ extern void ext4_group_desc_csum_set(str
 extern int ext4_register_li_request(struct super_block *sb,
 				    ext4_group_t first_not_zeroed);
 
-static inline int ext4_has_group_desc_csum(struct super_block *sb)
-{
-	return EXT4_HAS_RO_COMPAT_FEATURE(sb,
-					  EXT4_FEATURE_RO_COMPAT_GDT_CSUM) ||
-	       (EXT4_SB(sb)->s_chksum_driver != NULL);
-}
-
 static inline int ext4_has_metadata_csum(struct super_block *sb)
 {
 	WARN_ON_ONCE(EXT4_HAS_RO_COMPAT_FEATURE(sb,
 			EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) &&
 		     !EXT4_SB(sb)->s_chksum_driver);
 
-	return (EXT4_SB(sb)->s_chksum_driver != NULL);
+	return EXT4_HAS_RO_COMPAT_FEATURE(sb,
+			EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) &&
+	       (EXT4_SB(sb)->s_chksum_driver != NULL);
+}
+
+static inline int ext4_has_group_desc_csum(struct super_block *sb)
+{
+	return EXT4_HAS_RO_COMPAT_FEATURE(sb,
+					  EXT4_FEATURE_RO_COMPAT_GDT_CSUM) ||
+		ext4_has_metadata_csum(sb);
 }
+
 static inline ext4_fsblk_t ext4_blocks_count(struct ext4_super_block *es)
 {
 	return ((ext4_fsblk_t)le32_to_cpu(es->s_blocks_count_hi) << 32) |


^ permalink raw reply	[relevance 13%]

* [PATCH 3.16 28/61] scsi: sg: protect against races between mmap() and SG_SET_RESERVED_SIZE
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (26 preceding siblings ...)
  2020-06-09 18:04  9% ` [PATCH 3.16 27/61] scsi: sg: reset 'res_in_use' after unlinking reserved array Ben Hutchings
@ 2020-06-09 18:04  9% ` Ben Hutchings
  2020-06-09 18:04  9% ` [PATCH 3.16 29/61] scsi: sg: recheck MMAP_IO request length with lock held Ben Hutchings
                   ` (33 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Greg Kroah-Hartman, Douglas Gilbert,
	Todd Poynor, Martin K. Petersen

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Todd Poynor <toddpoynor@google.com>

commit 6a8dadcca81fceff9976e8828cceb072873b7bd5 upstream.

Take f_mutex around mmap() processing to protect against races with the
SG_SET_RESERVED_SIZE ioctl.  Ensure the reserve buffer length remains
consistent during the mapping operation, and set the "mmap called" flag
to prevent further changes to the reserved buffer size as an atomic
operation with the mapping.

[mkp: fixed whitespace]

Signed-off-by: Todd Poynor <toddpoynor@google.com>
Acked-by: Douglas Gilbert <dgilbert@interlog.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/scsi/sg.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -1310,6 +1310,7 @@ sg_mmap(struct file *filp, struct vm_are
 	unsigned long req_sz, len, sa;
 	Sg_scatter_hold *rsv_schp;
 	int k, length;
+	int ret = 0;
 
 	if ((!filp) || (!vma) || (!(sfp = (Sg_fd *) filp->private_data)))
 		return -ENXIO;
@@ -1319,8 +1320,11 @@ sg_mmap(struct file *filp, struct vm_are
 	if (vma->vm_pgoff)
 		return -EINVAL;	/* want no offset */
 	rsv_schp = &sfp->reserve;
-	if (req_sz > rsv_schp->bufflen)
-		return -ENOMEM;	/* cannot map more than reserved buffer */
+	mutex_lock(&sfp->f_mutex);
+	if (req_sz > rsv_schp->bufflen) {
+		ret = -ENOMEM;	/* cannot map more than reserved buffer */
+		goto out;
+	}
 
 	sa = vma->vm_start;
 	length = 1 << (PAGE_SHIFT + rsv_schp->page_order);
@@ -1334,7 +1338,9 @@ sg_mmap(struct file *filp, struct vm_are
 	vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP;
 	vma->vm_private_data = sfp;
 	vma->vm_ops = &sg_mmap_vm_ops;
-	return 0;
+out:
+	mutex_unlock(&sfp->f_mutex);
+	return ret;
 }
 
 static void


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 40/61] scsi: sg: fix static checker warning in sg_is_valid_dxfer
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (38 preceding siblings ...)
  2020-06-09 18:04  9% ` [PATCH 3.16 39/61] scsi: sg: fix SG_DXFER_FROM_DEV transfers Ben Hutchings
@ 2020-06-09 18:04  9% ` Ben Hutchings
  2020-06-09 18:04 11% ` [PATCH 3.16 41/61] scsi: sg: only check for dxfer_len greater than 256M Ben Hutchings
                   ` (21 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Johannes Thumshirn, Martin K. Petersen,
	Dan Carpenter, Colin Ian King, Greg Kroah-Hartman,
	Douglas Gilbert

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Johannes Thumshirn <jthumshirn@suse.de>

commit 14074aba4bcda3764c9a702b276308b89901d5b6 upstream.

dxfer_len is an unsigned int and we always assign a value > 0 to it, so
it doesn't make any sense to check if it is < 0. We can't really check
dxferp as well as we have both NULL and not NULL cases in the possible
call paths.

So just return true for SG_DXFER_FROM_DEV transfer in
sg_is_valid_dxfer().

Signed-off-by: Johannes Thumshirn <jthumshirn@suse.de>
Reported-by: Colin Ian King <colin.king@canonical.com>
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Cc: Douglas Gilbert <dgilbert@interlog.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/scsi/sg.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -796,8 +796,11 @@ static bool sg_is_valid_dxfer(sg_io_hdr_
 			return false;
 		return true;
 	case SG_DXFER_FROM_DEV:
-		if (hp->dxfer_len < 0)
-			return false;
+		/*
+		 * for SG_DXFER_FROM_DEV we always set dxfer_len to > 0. dxferp
+		 * can either be NULL or != NULL so there's no point in checking
+		 * it either. So just return true.
+		 */
 		return true;
 	case SG_DXFER_TO_DEV:
 	case SG_DXFER_TO_FROM_DEV:


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 53/61] ext4: add cond_resched() to ext4_protect_reserved_inode
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (51 preceding siblings ...)
  2020-06-09 18:04 12% ` [PATCH 3.16 52/61] ext4: don't perform block validity checks on the journal inode Ben Hutchings
@ 2020-06-09 18:04  9% ` Ben Hutchings
  2020-06-09 18:04  5% ` [PATCH 3.16 54/61] x86/cpu: Rename cpu_data.x86_mask to cpu_data.x86_stepping Ben Hutchings
                   ` (8 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, stable, Theodore Ts'o, Jan Kara, Shijie Luo

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Shijie Luo <luoshijie1@huawei.com>

commit af133ade9a40794a37104ecbcc2827c0ea373a3c upstream.

When journal size is set too big by "mkfs.ext4 -J size=", or when
we mount a crafted image to make journal inode->i_size too big,
the loop, "while (i < num)", holds cpu too long. This could cause
soft lockup.

[  529.357541] Call trace:
[  529.357551]  dump_backtrace+0x0/0x198
[  529.357555]  show_stack+0x24/0x30
[  529.357562]  dump_stack+0xa4/0xcc
[  529.357568]  watchdog_timer_fn+0x300/0x3e8
[  529.357574]  __hrtimer_run_queues+0x114/0x358
[  529.357576]  hrtimer_interrupt+0x104/0x2d8
[  529.357580]  arch_timer_handler_virt+0x38/0x58
[  529.357584]  handle_percpu_devid_irq+0x90/0x248
[  529.357588]  generic_handle_irq+0x34/0x50
[  529.357590]  __handle_domain_irq+0x68/0xc0
[  529.357593]  gic_handle_irq+0x6c/0x150
[  529.357595]  el1_irq+0xb8/0x140
[  529.357599]  __ll_sc_atomic_add_return_acquire+0x14/0x20
[  529.357668]  ext4_map_blocks+0x64/0x5c0 [ext4]
[  529.357693]  ext4_setup_system_zone+0x330/0x458 [ext4]
[  529.357717]  ext4_fill_super+0x2170/0x2ba8 [ext4]
[  529.357722]  mount_bdev+0x1a8/0x1e8
[  529.357746]  ext4_mount+0x44/0x58 [ext4]
[  529.357748]  mount_fs+0x50/0x170
[  529.357752]  vfs_kern_mount.part.9+0x54/0x188
[  529.357755]  do_mount+0x5ac/0xd78
[  529.357758]  ksys_mount+0x9c/0x118
[  529.357760]  __arm64_sys_mount+0x28/0x38
[  529.357764]  el0_svc_common+0x78/0x130
[  529.357766]  el0_svc_handler+0x38/0x78
[  529.357769]  el0_svc+0x8/0xc
[  541.356516] watchdog: BUG: soft lockup - CPU#0 stuck for 23s! [mount:18674]

Link: https://lore.kernel.org/r/20200211011752.29242-1-luoshijie1@huawei.com
Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Shijie Luo <luoshijie1@huawei.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Cc: stable@kernel.org
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 fs/ext4/block_validity.c | 1 +
 1 file changed, 1 insertion(+)

--- a/fs/ext4/block_validity.c
+++ b/fs/ext4/block_validity.c
@@ -153,6 +153,7 @@ static int ext4_protect_reserved_inode(s
 		return PTR_ERR(inode);
 	num = (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
 	while (i < num) {
+		cond_resched();
 		map.m_lblk = i;
 		map.m_len = num - i;
 		n = ext4_map_blocks(NULL, inode, &map, 0);


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 52/61] ext4: don't perform block validity checks on the journal inode
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (50 preceding siblings ...)
  2020-06-09 18:04 12% ` [PATCH 3.16 51/61] ext4: fix block validity checks for journal inodes using indirect blocks Ben Hutchings
@ 2020-06-09 18:04 12% ` Ben Hutchings
  2020-06-09 18:04  9% ` [PATCH 3.16 53/61] ext4: add cond_resched() to ext4_protect_reserved_inode Ben Hutchings
                   ` (9 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Theodore Ts'o, Naresh Kamboju, Dan Rue

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Theodore Ts'o <tytso@mit.edu>

commit 0a944e8a6c66ca04c7afbaa17e22bf208a8b37f0 upstream.

Since the journal inode is already checked when we added it to the
block validity's system zone, if we check it again, we'll just trigger
a failure.

This was causing failures like this:

[   53.897001] EXT4-fs error (device sda): ext4_find_extent:909: inode
#8: comm jbd2/sda-8: pblk 121667583 bad header/extent: invalid extent entries - magic f30a, entries 8, max 340(340), depth 0(0)
[   53.931430] jbd2_journal_bmap: journal block not found at offset 49 on sda-8
[   53.938480] Aborting journal on device sda-8.

... but only if the system was under enough memory pressure that
logical->physical mapping for the journal inode gets pushed out of the
extent cache.  (This is why it wasn't noticed earlier.)

Fixes: 345c0dbf3a30 ("ext4: protect journal inode's blocks using block_validity")
Reported-by: Dan Rue <dan.rue@linaro.org>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Tested-by: Naresh Kamboju <naresh.kamboju@linaro.org>
[bwh: Backported to 3.16: Use EXT4_HAS_COMPAT_FEATURE()]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -503,10 +503,15 @@ __read_extent_tree_block(const char *fun
 	}
 	if (buffer_verified(bh) && !(flags & EXT4_EX_FORCE_CACHE))
 		return bh;
-	err = __ext4_ext_check(function, line, inode,
-			       ext_block_hdr(bh), depth, pblk);
-	if (err)
-		goto errout;
+	if (!EXT4_HAS_COMPAT_FEATURE(inode->i_sb,
+				     EXT4_FEATURE_COMPAT_HAS_JOURNAL) ||
+	    (inode->i_ino !=
+	     le32_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_journal_inum))) {
+		err = __ext4_ext_check(function, line, inode,
+				       ext_block_hdr(bh), depth, pblk);
+		if (err)
+			goto errout;
+	}
 	set_buffer_verified(bh);
 	/*
 	 * If this is a leaf block, cache all of its entries


^ permalink raw reply	[relevance 12%]

* [PATCH 3.16 55/61] x86/cpu: Add a steppings field to struct x86_cpu_id
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (53 preceding siblings ...)
  2020-06-09 18:04  5% ` [PATCH 3.16 54/61] x86/cpu: Rename cpu_data.x86_mask to cpu_data.x86_stepping Ben Hutchings
@ 2020-06-09 18:04  7% ` Ben Hutchings
  2020-06-09 18:04  8% ` [PATCH 3.16 56/61] x86/cpu: Add 'table' argument to cpu_matches() Ben Hutchings
                   ` (6 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Thomas Gleixner, Josh Poimboeuf,
	Borislav Petkov, Tony Luck, Mark Gross

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Mark Gross <mgross@linux.intel.com>

commit e9d7144597b10ff13ff2264c059f7d4a7fbc89ac upstream.

Intel uses the same family/model for several CPUs. Sometimes the
stepping must be checked to tell them apart.

On x86 there can be at most 16 steppings. Add a steppings bitmask to
x86_cpu_id and a X86_MATCH_VENDOR_FAMILY_MODEL_STEPPING_FEATURE macro
and support for matching against family/model/stepping.

 [ bp: Massage.
   tglx: Lightweight variant for backporting ]

Signed-off-by: Mark Gross <mgross@linux.intel.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Tony Luck <tony.luck@intel.com>
Reviewed-by: Josh Poimboeuf <jpoimboe@redhat.com>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 arch/x86/include/asm/cpu_device_id.h | 27 +++++++++++++++++++++++++++
 arch/x86/kernel/cpu/match.c          |  7 ++++++-
 include/linux/mod_devicetable.h      |  6 ++++++
 3 files changed, 39 insertions(+), 1 deletion(-)

--- a/arch/x86/include/asm/cpu_device_id.h
+++ b/arch/x86/include/asm/cpu_device_id.h
@@ -8,6 +8,33 @@
 
 #include <linux/mod_devicetable.h>
 
+#define X86_STEPPINGS(mins, maxs)    GENMASK(maxs, mins)
+
+/**
+ * X86_MATCH_VENDOR_FAM_MODEL_STEPPINGS_FEATURE - Base macro for CPU matching
+ * @_vendor:	The vendor name, e.g. INTEL, AMD, HYGON, ..., ANY
+ *		The name is expanded to X86_VENDOR_@_vendor
+ * @_family:	The family number or X86_FAMILY_ANY
+ * @_model:	The model number, model constant or X86_MODEL_ANY
+ * @_steppings:	Bitmask for steppings, stepping constant or X86_STEPPING_ANY
+ * @_feature:	A X86_FEATURE bit or X86_FEATURE_ANY
+ * @_data:	Driver specific data or NULL. The internal storage
+ *		format is unsigned long. The supplied value, pointer
+ *		etc. is casted to unsigned long internally.
+ *
+ * Backport version to keep the SRBDS pile consistant. No shorter variants
+ * required for this.
+ */
+#define X86_MATCH_VENDOR_FAM_MODEL_STEPPINGS_FEATURE(_vendor, _family, _model, \
+						    _steppings, _feature, _data) { \
+	.vendor		= X86_VENDOR_##_vendor,				\
+	.family		= _family,					\
+	.model		= _model,					\
+	.steppings	= _steppings,					\
+	.feature	= _feature,					\
+	.driver_data	= (unsigned long) _data				\
+}
+
 extern const struct x86_cpu_id *x86_match_cpu(const struct x86_cpu_id *match);
 
 #endif
--- a/arch/x86/kernel/cpu/match.c
+++ b/arch/x86/kernel/cpu/match.c
@@ -33,13 +33,18 @@ const struct x86_cpu_id *x86_match_cpu(c
 	const struct x86_cpu_id *m;
 	struct cpuinfo_x86 *c = &boot_cpu_data;
 
-	for (m = match; m->vendor | m->family | m->model | m->feature; m++) {
+	for (m = match;
+	     m->vendor | m->family | m->model | m->steppings | m->feature;
+	     m++) {
 		if (m->vendor != X86_VENDOR_ANY && c->x86_vendor != m->vendor)
 			continue;
 		if (m->family != X86_FAMILY_ANY && c->x86 != m->family)
 			continue;
 		if (m->model != X86_MODEL_ANY && c->x86_model != m->model)
 			continue;
+		if (m->steppings != X86_STEPPING_ANY &&
+		    !(BIT(c->x86_stepping) & m->steppings))
+			continue;
 		if (m->feature != X86_FEATURE_ANY && !cpu_has(c, m->feature))
 			continue;
 		return m;
--- a/include/linux/mod_devicetable.h
+++ b/include/linux/mod_devicetable.h
@@ -559,6 +559,10 @@ struct amba_id {
 /*
  * MODULE_DEVICE_TABLE expects this struct to be called x86cpu_device_id.
  * Although gcc seems to ignore this error, clang fails without this define.
+ *
+ * Note: The ordering of the struct is different from upstream because the
+ * static initializers in kernels < 5.7 still use C89 style while upstream
+ * has been converted to proper C99 initializers.
  */
 #define x86cpu_device_id x86_cpu_id
 struct x86_cpu_id {
@@ -567,6 +571,7 @@ struct x86_cpu_id {
 	__u16 model;
 	__u16 feature;	/* bit index */
 	kernel_ulong_t driver_data;
+	__u16 steppings;
 };
 
 #define X86_FEATURE_MATCH(x) \
@@ -575,6 +580,7 @@ struct x86_cpu_id {
 #define X86_VENDOR_ANY 0xffff
 #define X86_FAMILY_ANY 0
 #define X86_MODEL_ANY  0
+#define X86_STEPPING_ANY 0
 #define X86_FEATURE_ANY 0	/* Same as FPU, you can't test for that */
 
 /*


^ permalink raw reply	[relevance 7%]

* [PATCH 3.16 42/61] scsi: sg: don't return bogus Sg_requests
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (40 preceding siblings ...)
  2020-06-09 18:04 11% ` [PATCH 3.16 41/61] scsi: sg: only check for dxfer_len greater than 256M Ben Hutchings
@ 2020-06-09 18:04  9% ` Ben Hutchings
  2020-06-09 18:28  6%   ` Tony Battersby
  2020-06-09 18:04  9% ` [PATCH 3.16 43/61] scsi: sg: fix minor memory leak in error path Ben Hutchings
                   ` (19 subsequent siblings)
  61 siblings, 1 reply; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Martin K. Petersen, Johannes Thumshirn,
	Andrey Konovalov, Christoph Hellwig, Tony Battersby,
	Hannes Reinecke, Greg Kroah-Hartman, Doug Gilbert

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Johannes Thumshirn <jthumshirn@suse.de>

commit 48ae8484e9fc324b4968d33c585e54bc98e44d61 upstream.

If the list search in sg_get_rq_mark() fails to find a valid request, we
return a bogus element. This then can later lead to a GPF in
sg_remove_scat().

So don't return bogus Sg_requests in sg_get_rq_mark() but NULL in case
the list search doesn't find a valid request.

Signed-off-by: Johannes Thumshirn <jthumshirn@suse.de>
Reported-by: Andrey Konovalov <andreyknvl@google.com>
Cc: Hannes Reinecke <hare@suse.de>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Doug Gilbert <dgilbert@interlog.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Acked-by: Doug Gilbert <dgilbert@interlog.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Cc: Tony Battersby <tonyb@cybernetics.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/scsi/sg.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -2085,11 +2085,12 @@ sg_get_rq_mark(Sg_fd * sfp, int pack_id)
 		if ((1 == resp->done) && (!resp->sg_io_owned) &&
 		    ((-1 == pack_id) || (resp->header.pack_id == pack_id))) {
 			resp->done = 2;	/* guard against other readers */
-			break;
+			write_unlock_irqrestore(&sfp->rq_list_lock, iflags);
+			return resp;
 		}
 	}
 	write_unlock_irqrestore(&sfp->rq_list_lock, iflags);
-	return resp;
+	return NULL;
 }
 
 /* always adds to end of list */


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 36/61] scsi: sg: disable SET_FORCE_LOW_DMA
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (34 preceding siblings ...)
  2020-06-09 18:04 11% ` [PATCH 3.16 35/61] scsi: sg: Re-fix off by one in sg_fill_request_table() Ben Hutchings
@ 2020-06-09 18:04 10% ` Ben Hutchings
  2020-06-09 18:04  8% ` [PATCH 3.16 37/61] scsi: sg: check for valid direction before starting the request Ben Hutchings
                   ` (25 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Martin K. Petersen, Johannes Thumshirn,
	Christoph Hellwig, Hannes Reinecke, Hannes Reinecke,
	Greg Kroah-Hartman

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Hannes Reinecke <hare@suse.de>

commit 745dfa0d8ec26b24f3304459ff6e9eacc5c8351b upstream.

The ioctl SET_FORCE_LOW_DMA has never worked since the initial git
check-in, and the respective setting is nowadays handled correctly. So
disable it entirely.

Signed-off-by: Hannes Reinecke <hare@suse.com>
Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Tested-by: Johannes Thumshirn <jthumshirn@suse.de>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/scsi/sg.c | 30 +++++++++---------------------
 include/scsi/sg.h |  1 -
 2 files changed, 9 insertions(+), 22 deletions(-)

--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -157,7 +157,6 @@ typedef struct sg_fd {		/* holds the sta
 	struct list_head rq_list; /* head of request list */
 	struct fasync_struct *async_qp;	/* used by asynchronous notification */
 	Sg_request req_arr[SG_MAX_QUEUE];	/* used as singly-linked list */
-	char low_dma;		/* as in parent but possibly overridden to 1 */
 	char force_packid;	/* 1 -> pack_id input to read(), 0 -> ignored */
 	char cmd_q;		/* 1 -> allow command queuing, 0 -> don't */
 	unsigned char next_cmd_len; /* 0: automatic, >0: use on next write() */
@@ -963,24 +962,14 @@ sg_ioctl(struct file *filp, unsigned int
 				/* strange ..., for backward compatibility */
 		return sfp->timeout_user;
 	case SG_SET_FORCE_LOW_DMA:
-		result = get_user(val, ip);
-		if (result)
-			return result;
-		if (val) {
-			sfp->low_dma = 1;
-			if ((0 == sfp->low_dma) && !sfp->res_in_use) {
-				val = (int) sfp->reserve.bufflen;
-				sg_remove_scat(&sfp->reserve);
-				sg_build_reserve(sfp, val);
-			}
-		} else {
-			if (atomic_read(&sdp->detaching))
-				return -ENODEV;
-			sfp->low_dma = sdp->device->host->unchecked_isa_dma;
-		}
+		/*
+		 * N.B. This ioctl never worked properly, but failed to
+		 * return an error value. So returning '0' to keep compability
+		 * with legacy applications.
+		 */
 		return 0;
 	case SG_GET_LOW_DMA:
-		return put_user((int) sfp->low_dma, ip);
+		return put_user((int) sdp->device->host->unchecked_isa_dma, ip);
 	case SG_GET_SCSI_ID:
 		if (!access_ok(VERIFY_WRITE, p, sizeof (sg_scsi_id_t)))
 			return -EFAULT;
@@ -1890,6 +1879,7 @@ sg_build_indirect(Sg_scatter_hold * schp
 	int sg_tablesize = sfp->parentdp->sg_tablesize;
 	int blk_size = buff_size, order;
 	gfp_t gfp_mask = GFP_ATOMIC | __GFP_COMP | __GFP_NOWARN;
+	struct sg_device *sdp = sfp->parentdp;
 
 	if (blk_size < 0)
 		return -EFAULT;
@@ -1914,7 +1904,7 @@ sg_build_indirect(Sg_scatter_hold * schp
 			scatter_elem_sz_prev = num;
 	}
 
-	if (sfp->low_dma)
+	if (sdp->device->host->unchecked_isa_dma)
 		gfp_mask |= GFP_DMA;
 
 	if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
@@ -2168,8 +2158,6 @@ sg_add_sfp(Sg_device * sdp, int dev)
 	sfp->timeout = SG_DEFAULT_TIMEOUT;
 	sfp->timeout_user = SG_DEFAULT_TIMEOUT_USER;
 	sfp->force_packid = SG_DEF_FORCE_PACK_ID;
-	sfp->low_dma = (SG_DEF_FORCE_LOW_DMA == 0) ?
-	    sdp->device->host->unchecked_isa_dma : 1;
 	sfp->cmd_q = SG_DEF_COMMAND_Q;
 	sfp->keep_orphan = SG_DEF_KEEP_ORPHAN;
 	sfp->parentdp = sdp;
@@ -2627,7 +2615,7 @@ static void sg_proc_debug_helper(struct
 			   jiffies_to_msecs(fp->timeout),
 			   fp->reserve.bufflen,
 			   (int) fp->reserve.k_use_sg,
-			   (int) fp->low_dma);
+			   (int) sdp->device->host->unchecked_isa_dma);
 		seq_printf(s, "   cmd_q=%d f_packid=%d k_orphan=%d closed=0\n",
 			   (int) fp->cmd_q, (int) fp->force_packid,
 			   (int) fp->keep_orphan);
--- a/include/scsi/sg.h
+++ b/include/scsi/sg.h
@@ -234,7 +234,6 @@ typedef struct sg_req_info { /* used by
 #define SG_DEFAULT_RETRIES 0
 
 /* Defaults, commented if they differ from original sg driver */
-#define SG_DEF_FORCE_LOW_DMA 0  /* was 1 -> memory below 16MB on i386 */
 #define SG_DEF_FORCE_PACK_ID 0
 #define SG_DEF_KEEP_ORPHAN 0
 #define SG_DEF_RESERVED_SIZE SG_SCATTER_SZ /* load time option */


^ permalink raw reply	[relevance 10%]

* [PATCH 3.16 10/61] net-sysfs: Call dev_hold always in rx_queue_add_kobject
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (8 preceding siblings ...)
  2020-06-09 18:04 12% ` [PATCH 3.16 09/61] net-sysfs: Call dev_hold always in netdev_queue_add_kobject Ben Hutchings
@ 2020-06-09 18:04 12% ` Ben Hutchings
  2020-06-09 18:04  9% ` [PATCH 3.16 11/61] selinux: cleanup error reporting in selinux_nlmsg_perm() Ben Hutchings
                   ` (51 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Tetsuo Handa, Lukas Bulwahn, David Miller,
	Jouni Hogander, syzbot

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Jouni Hogander <jouni.hogander@unikie.com>

commit ddd9b5e3e765d8ed5a35786a6cb00111713fe161 upstream.

Dev_hold has to be called always in rx_queue_add_kobject.
Otherwise usage count drops below 0 in case of failure in
kobject_init_and_add.

Fixes: b8eb718348b8 ("net-sysfs: Fix reference count leak in rx|netdev_queue_add_kobject")
Reported-by: syzbot <syzbot+30209ea299c09d8785c9@syzkaller.appspotmail.com>
Cc: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Cc: David Miller <davem@davemloft.net>
Cc: Lukas Bulwahn <lukas.bulwahn@gmail.com>
Signed-off-by: Jouni Hogander <jouni.hogander@unikie.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 net/core/net-sysfs.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -782,14 +782,17 @@ static int rx_queue_add_kobject(struct n
 	struct kobject *kobj = &queue->kobj;
 	int error = 0;
 
+	/* Kobject_put later will trigger rx_queue_release call which
+	 * decreases dev refcount: Take that reference here
+	 */
+	dev_hold(queue->dev);
+
 	kobj->kset = net->queues_kset;
 	error = kobject_init_and_add(kobj, &rx_queue_ktype, NULL,
 	    "rx-%u", index);
 	if (error)
 		goto err;
 
-	dev_hold(queue->dev);
-
 	if (net->sysfs_rx_queue_group) {
 		error = sysfs_create_group(kobj, net->sysfs_rx_queue_group);
 		if (error)


^ permalink raw reply	[relevance 12%]

* [PATCH 3.16 50/61] ext4: unsigned int compared against zero
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (48 preceding siblings ...)
  2020-06-09 18:04 11% ` [PATCH 3.16 49/61] ext4: protect journal inode's blocks using block_validity Ben Hutchings
@ 2020-06-09 18:04  9% ` Ben Hutchings
  2020-06-09 18:04 12% ` [PATCH 3.16 51/61] ext4: fix block validity checks for journal inodes using indirect blocks Ben Hutchings
                   ` (11 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Colin Ian King, Theodore Ts'o

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Colin Ian King <colin.king@canonical.com>

commit fbbbbd2f28aec991f3fbc248df211550fbdfd58c upstream.

There are two cases where u32 variables n and err are being checked
for less than zero error values, the checks is always false because
the variables are not signed. Fix this by making the variables ints.

Addresses-Coverity: ("Unsigned compared against 0")
Fixes: 345c0dbf3a30 ("ext4: protect journal inode's blocks using block_validity")
Signed-off-by: Colin Ian King <colin.king@canonical.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 fs/ext4/block_validity.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

--- a/fs/ext4/block_validity.c
+++ b/fs/ext4/block_validity.c
@@ -142,7 +142,8 @@ static int ext4_protect_reserved_inode(s
 	struct inode *inode;
 	struct ext4_sb_info *sbi = EXT4_SB(sb);
 	struct ext4_map_blocks map;
-	u32 i = 0, err = 0, num, n;
+	u32 i = 0, num;
+	int err = 0, n;
 
 	if ((ino < EXT4_ROOT_INO) ||
 	    (ino > le32_to_cpu(sbi->s_es->s_inodes_count)))


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 56/61] x86/cpu: Add 'table' argument to cpu_matches()
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (54 preceding siblings ...)
  2020-06-09 18:04  7% ` [PATCH 3.16 55/61] x86/cpu: Add a steppings field to struct x86_cpu_id Ben Hutchings
@ 2020-06-09 18:04  8% ` Ben Hutchings
  2020-06-09 18:04  7% ` [PATCH 3.16 57/61] x86/speculation: Add Special Register Buffer Data Sampling (SRBDS) mitigation Ben Hutchings
                   ` (5 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Josh Poimboeuf, Thomas Gleixner,
	Mark Gross, Borislav Petkov

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Mark Gross <mgross@linux.intel.com>

commit 93920f61c2ad7edb01e63323832585796af75fc9 upstream.

To make cpu_matches() reusable for other matching tables, have it take a
pointer to a x86_cpu_id table as an argument.

 [ bp: Flip arguments order. ]

Signed-off-by: Mark Gross <mgross@linux.intel.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Josh Poimboeuf <jpoimboe@redhat.com>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 arch/x86/kernel/cpu/common.c | 23 +++++++++++++----------
 1 file changed, 13 insertions(+), 10 deletions(-)

--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -872,9 +872,9 @@ static const __initconst struct x86_cpu_
 	{}
 };
 
-static bool __init cpu_matches(unsigned long which)
+static bool __init cpu_matches(const struct x86_cpu_id *table, unsigned long which)
 {
-	const struct x86_cpu_id *m = x86_match_cpu(cpu_vuln_whitelist);
+	const struct x86_cpu_id *m = x86_match_cpu(table);
 
 	return m && !!(m->driver_data & which);
 }
@@ -894,29 +894,32 @@ static void __init cpu_set_bug_bits(stru
 	u64 ia32_cap = x86_read_arch_cap_msr();
 
 	/* Set ITLB_MULTIHIT bug if cpu is not in the whitelist and not mitigated */
-	if (!cpu_matches(NO_ITLB_MULTIHIT) && !(ia32_cap & ARCH_CAP_PSCHANGE_MC_NO))
+	if (!cpu_matches(cpu_vuln_whitelist, NO_ITLB_MULTIHIT) &&
+	    !(ia32_cap & ARCH_CAP_PSCHANGE_MC_NO))
 		setup_force_cpu_bug(X86_BUG_ITLB_MULTIHIT);
 
-	if (cpu_matches(NO_SPECULATION))
+	if (cpu_matches(cpu_vuln_whitelist, NO_SPECULATION))
 		return;
 
 	setup_force_cpu_bug(X86_BUG_SPECTRE_V1);
 	setup_force_cpu_bug(X86_BUG_SPECTRE_V2);
 
-	if (!cpu_matches(NO_SSB) && !(ia32_cap & ARCH_CAP_SSB_NO) &&
+	if (!cpu_matches(cpu_vuln_whitelist, NO_SSB) &&
+	    !(ia32_cap & ARCH_CAP_SSB_NO) &&
 	   !cpu_has(c, X86_FEATURE_AMD_SSB_NO))
 		setup_force_cpu_bug(X86_BUG_SPEC_STORE_BYPASS);
 
 	if (ia32_cap & ARCH_CAP_IBRS_ALL)
 		setup_force_cpu_cap(X86_FEATURE_IBRS_ENHANCED);
 
-	if (!cpu_matches(NO_MDS) && !(ia32_cap & ARCH_CAP_MDS_NO)) {
+	if (!cpu_matches(cpu_vuln_whitelist, NO_MDS) &&
+	    !(ia32_cap & ARCH_CAP_MDS_NO)) {
 		setup_force_cpu_bug(X86_BUG_MDS);
-		if (cpu_matches(MSBDS_ONLY))
+		if (cpu_matches(cpu_vuln_whitelist, MSBDS_ONLY))
 			setup_force_cpu_bug(X86_BUG_MSBDS_ONLY);
 	}
 
-	if (!cpu_matches(NO_SWAPGS))
+	if (!cpu_matches(cpu_vuln_whitelist, NO_SWAPGS))
 		setup_force_cpu_bug(X86_BUG_SWAPGS);
 
 	/*
@@ -934,7 +937,7 @@ static void __init cpu_set_bug_bits(stru
 	     (ia32_cap & ARCH_CAP_TSX_CTRL_MSR)))
 		setup_force_cpu_bug(X86_BUG_TAA);
 
-	if (cpu_matches(NO_MELTDOWN))
+	if (cpu_matches(cpu_vuln_whitelist, NO_MELTDOWN))
 		return;
 
 	/* Rogue Data Cache Load? No! */
@@ -943,7 +946,7 @@ static void __init cpu_set_bug_bits(stru
 
 	setup_force_cpu_bug(X86_BUG_CPU_MELTDOWN);
 
-	if (cpu_matches(NO_L1TF))
+	if (cpu_matches(cpu_vuln_whitelist, NO_L1TF))
 		return;
 
 	setup_force_cpu_bug(X86_BUG_L1TF);


^ permalink raw reply	[relevance 8%]

* [PATCH 3.16 23/61] sg: O_EXCL and other lock handling
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (21 preceding siblings ...)
  2020-06-09 18:04 13% ` [PATCH 3.16 22/61] mwifiex: Fix possible buffer overflows in mwifiex_ret_wmm_get_status() Ben Hutchings
@ 2020-06-09 18:04  3% ` Ben Hutchings
  2020-06-09 18:04  8% ` [PATCH 3.16 24/61] sg: prevent integer overflow when converting from sectors to bytes Ben Hutchings
                   ` (38 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Douglas Gilbert, Hannes Reinecke

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Douglas Gilbert <dgilbert@interlog.com>

commit cc833acbee9db5ca8c6162b015b4c93863c6f821 upstream.

This addresses a problem reported by Vaughan Cao concerning
the correctness of the O_EXCL logic in the sg driver. POSIX
doesn't defined O_EXCL semantics on devices but "allow only
one open file descriptor at a time per sg device" is a rough
definition. The sg driver's semantics have been to wait
on an open() when O_NONBLOCK is not given and there are
O_EXCL headwinds. Nasty things can happen during that wait
such as the device being detached (removed). So multiple
locks are reworked in this patch making it large and hard
to break down into digestible bits.

This patch is against Linus's current git repository which
doesn't include any sg patches sent in the last few weeks.
Hence this patch touches as little as possible that it
doesn't need to and strips out most SCSI_LOG_TIMEOUT()
changes in v3 because Hannes said he was going to rework all
that stuff.

The sg3_utils package has several test programs written to
test this patch. See examples/sg_tst_excl*.cpp .

Not all the locks and flags in sg have been re-worked in
this patch, notably sg_request::done . That can wait for
a follow-up patch if this one meets with approval.

Signed-off-by: Douglas Gilbert <dgilbert@interlog.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/scsi/sg.c | 424 +++++++++++++++++++++++++---------------------
 1 file changed, 230 insertions(+), 194 deletions(-)

--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -51,6 +51,7 @@ static int sg_version_num = 30534;	/* 2
 #include <linux/delay.h>
 #include <linux/blktrace_api.h>
 #include <linux/mutex.h>
+#include <linux/atomic.h>
 #include <linux/ratelimit.h>
 #include <linux/cred.h> /* for sg_check_file_access() */
 
@@ -103,18 +104,16 @@ static int scatter_elem_sz_prev = SG_SCA
 
 #define SG_SECTOR_SZ 512
 
-static int sg_add(struct device *, struct class_interface *);
-static void sg_remove(struct device *, struct class_interface *);
-
-static DEFINE_SPINLOCK(sg_open_exclusive_lock);
+static int sg_add_device(struct device *, struct class_interface *);
+static void sg_remove_device(struct device *, struct class_interface *);
 
 static DEFINE_IDR(sg_index_idr);
 static DEFINE_RWLOCK(sg_index_lock);	/* Also used to lock
 							   file descriptor list for device */
 
 static struct class_interface sg_interface = {
-	.add_dev	= sg_add,
-	.remove_dev	= sg_remove,
+	.add_dev        = sg_add_device,
+	.remove_dev     = sg_remove_device,
 };
 
 typedef struct sg_scatter_hold { /* holding area for scsi scatter gather info */
@@ -147,8 +146,7 @@ typedef struct sg_request {	/* SG_MAX_QU
 } Sg_request;
 
 typedef struct sg_fd {		/* holds the state of a file descriptor */
-	/* sfd_siblings is protected by sg_index_lock */
-	struct list_head sfd_siblings;
+	struct list_head sfd_siblings;  /* protected by device's sfd_lock */
 	struct sg_device *parentdp;	/* owning device */
 	wait_queue_head_t read_wait;	/* queue read until command done */
 	rwlock_t rq_list_lock;	/* protect access to list in req_arr */
@@ -171,14 +169,15 @@ typedef struct sg_fd {		/* holds the sta
 
 typedef struct sg_device { /* holds the state of each scsi generic device */
 	struct scsi_device *device;
-	wait_queue_head_t o_excl_wait;	/* queue open() when O_EXCL in use */
+	wait_queue_head_t open_wait;    /* queue open() when O_EXCL present */
+	struct mutex open_rel_lock;     /* held when in open() or release() */
 	int sg_tablesize;	/* adapter's max scatter-gather table size */
 	u32 index;		/* device index number */
-	/* sfds is protected by sg_index_lock */
 	struct list_head sfds;
-	volatile char detached;	/* 0->attached, 1->detached pending removal */
-	/* exclude protected by sg_open_exclusive_lock */
-	char exclude;		/* opened for exclusive access */
+	rwlock_t sfd_lock;      /* protect access to sfd list */
+	atomic_t detaching;     /* 0->device usable, 1->device detaching */
+	bool exclude;		/* 1->open(O_EXCL) succeeded and is active */
+	int open_cnt;		/* count of opens (perhaps < num(sfds) ) */
 	char sgdebug;		/* 0->off, 1->sense, 9->dump dev, 10-> all devs */
 	struct gendisk *disk;
 	struct cdev * cdev;	/* char_dev [sysfs: /sys/cdev/major/sg<n>] */
@@ -209,7 +208,7 @@ static Sg_request *sg_add_request(Sg_fd
 static int sg_remove_request(Sg_fd * sfp, Sg_request * srp);
 static int sg_res_in_use(Sg_fd * sfp);
 static Sg_device *sg_get_dev(int dev);
-static void sg_put_dev(Sg_device *sdp);
+static void sg_device_destroy(struct kref *kref);
 
 #define SZ_SG_HEADER sizeof(struct sg_header)
 #define SZ_SG_IO_HDR sizeof(sg_io_hdr_t)
@@ -253,38 +252,43 @@ static int sg_allow_access(struct file *
 	return blk_verify_command(cmd, filp->f_mode & FMODE_WRITE);
 }
 
-static int get_exclude(Sg_device *sdp)
-{
-	unsigned long flags;
-	int ret;
-
-	spin_lock_irqsave(&sg_open_exclusive_lock, flags);
-	ret = sdp->exclude;
-	spin_unlock_irqrestore(&sg_open_exclusive_lock, flags);
-	return ret;
-}
-
-static int set_exclude(Sg_device *sdp, char val)
+static int
+open_wait(Sg_device *sdp, int flags)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&sg_open_exclusive_lock, flags);
-	sdp->exclude = val;
-	spin_unlock_irqrestore(&sg_open_exclusive_lock, flags);
-	return val;
-}
+	int retval = 0;
 
-static int sfds_list_empty(Sg_device *sdp)
-{
-	unsigned long flags;
-	int ret;
+	if (flags & O_EXCL) {
+		while (sdp->open_cnt > 0) {
+			mutex_unlock(&sdp->open_rel_lock);
+			retval = wait_event_interruptible(sdp->open_wait,
+					(atomic_read(&sdp->detaching) ||
+					 !sdp->open_cnt));
+			mutex_lock(&sdp->open_rel_lock);
+
+			if (retval) /* -ERESTARTSYS */
+				return retval;
+			if (atomic_read(&sdp->detaching))
+				return -ENODEV;
+		}
+	} else {
+		while (sdp->exclude) {
+			mutex_unlock(&sdp->open_rel_lock);
+			retval = wait_event_interruptible(sdp->open_wait,
+					(atomic_read(&sdp->detaching) ||
+					 !sdp->exclude));
+			mutex_lock(&sdp->open_rel_lock);
+
+			if (retval) /* -ERESTARTSYS */
+				return retval;
+			if (atomic_read(&sdp->detaching))
+				return -ENODEV;
+		}
+	}
 
-	read_lock_irqsave(&sg_index_lock, flags);
-	ret = list_empty(&sdp->sfds);
-	read_unlock_irqrestore(&sg_index_lock, flags);
-	return ret;
+	return retval;
 }
 
+/* Returns 0 on success, else a negated errno value */
 static int
 sg_open(struct inode *inode, struct file *filp)
 {
@@ -293,17 +297,15 @@ sg_open(struct inode *inode, struct file
 	struct request_queue *q;
 	Sg_device *sdp;
 	Sg_fd *sfp;
-	int res;
 	int retval;
 
 	nonseekable_open(inode, filp);
 	SCSI_LOG_TIMEOUT(3, printk("sg_open: dev=%d, flags=0x%x\n", dev, flags));
+	if ((flags & O_EXCL) && (O_RDONLY == (flags & O_ACCMODE)))
+		return -EPERM; /* Can't lock it with read only access */
 	sdp = sg_get_dev(dev);
-	if (IS_ERR(sdp)) {
-		retval = PTR_ERR(sdp);
-		sdp = NULL;
-		goto sg_put;
-	}
+	if (IS_ERR(sdp))
+		return PTR_ERR(sdp);
 
 	/* This driver's module count bumped by fops_get in <linux/fs.h> */
 	/* Prevent the device driver from vanishing while we sleep */
@@ -315,6 +317,9 @@ sg_open(struct inode *inode, struct file
 	if (retval)
 		goto sdp_put;
 
+	/* scsi_block_when_processing_errors() may block so bypass
+	 * check if O_NONBLOCK. Permits SCSI commands to be issued
+	 * during error recovery. Tread carefully. */
 	if (!((flags & O_NONBLOCK) ||
 	      scsi_block_when_processing_errors(sdp->device))) {
 		retval = -ENXIO;
@@ -322,65 +327,65 @@ sg_open(struct inode *inode, struct file
 		goto error_out;
 	}
 
-	if (flags & O_EXCL) {
-		if (O_RDONLY == (flags & O_ACCMODE)) {
-			retval = -EPERM; /* Can't lock it with read only access */
-			goto error_out;
-		}
-		if (!sfds_list_empty(sdp) && (flags & O_NONBLOCK)) {
-			retval = -EBUSY;
-			goto error_out;
-		}
-		res = wait_event_interruptible(sdp->o_excl_wait,
-					   ((!sfds_list_empty(sdp) || get_exclude(sdp)) ? 0 : set_exclude(sdp, 1)));
-		if (res) {
-			retval = res;	/* -ERESTARTSYS because signal hit process */
-			goto error_out;
-		}
-	} else if (get_exclude(sdp)) {	/* some other fd has an exclusive lock on dev */
-		if (flags & O_NONBLOCK) {
-			retval = -EBUSY;
-			goto error_out;
-		}
-		res = wait_event_interruptible(sdp->o_excl_wait, !get_exclude(sdp));
-		if (res) {
-			retval = res;	/* -ERESTARTSYS because signal hit process */
-			goto error_out;
+	mutex_lock(&sdp->open_rel_lock);
+	if (flags & O_NONBLOCK) {
+		if (flags & O_EXCL) {
+			if (sdp->open_cnt > 0) {
+				retval = -EBUSY;
+				goto error_mutex_locked;
+			}
+		} else {
+			if (sdp->exclude) {
+				retval = -EBUSY;
+				goto error_mutex_locked;
+			}
 		}
+	} else {
+		retval = open_wait(sdp, flags);
+		if (retval) /* -ERESTARTSYS or -ENODEV */
+			goto error_mutex_locked;
 	}
-	if (sdp->detached) {
-		retval = -ENODEV;
-		goto error_out;
-	}
-	if (sfds_list_empty(sdp)) {	/* no existing opens on this device */
+
+	/* N.B. at this point we are holding the open_rel_lock */
+	if (flags & O_EXCL)
+		sdp->exclude = true;
+
+	if (sdp->open_cnt < 1) {  /* no existing opens */
 		sdp->sgdebug = 0;
 		q = sdp->device->request_queue;
 		sdp->sg_tablesize = queue_max_segments(q);
 	}
-	if ((sfp = sg_add_sfp(sdp, dev)))
-		filp->private_data = sfp;
-	else {
-		if (flags & O_EXCL) {
-			set_exclude(sdp, 0);	/* undo if error */
-			wake_up_interruptible(&sdp->o_excl_wait);
-		}
-		retval = -ENOMEM;
-		goto error_out;
+	sfp = sg_add_sfp(sdp, dev);
+	if (IS_ERR(sfp)) {
+		retval = PTR_ERR(sfp);
+		goto out_undo;
 	}
+
+	filp->private_data = sfp;
+	sdp->open_cnt++;
+	mutex_unlock(&sdp->open_rel_lock);
+
 	retval = 0;
-error_out:
-	if (retval) {
-		scsi_autopm_put_device(sdp->device);
-sdp_put:
-		scsi_device_put(sdp->device);
-	}
 sg_put:
-	if (sdp)
-		sg_put_dev(sdp);
+	kref_put(&sdp->d_ref, sg_device_destroy);
 	return retval;
+
+out_undo:
+	if (flags & O_EXCL) {
+		sdp->exclude = false;   /* undo if error */
+		wake_up_interruptible(&sdp->open_wait);
+	}
+error_mutex_locked:
+	mutex_unlock(&sdp->open_rel_lock);
+error_out:
+	scsi_autopm_put_device(sdp->device);
+sdp_put:
+	scsi_device_put(sdp->device);
+	goto sg_put;
 }
 
-/* Following function was formerly called 'sg_close' */
+/* Release resources associated with a successful sg_open()
+ * Returns 0 on success, else a negated errno value */
 static int
 sg_release(struct inode *inode, struct file *filp)
 {
@@ -391,11 +396,20 @@ sg_release(struct inode *inode, struct f
 		return -ENXIO;
 	SCSI_LOG_TIMEOUT(3, printk("sg_release: %s\n", sdp->disk->disk_name));
 
-	set_exclude(sdp, 0);
-	wake_up_interruptible(&sdp->o_excl_wait);
-
+	mutex_lock(&sdp->open_rel_lock);
 	scsi_autopm_put_device(sdp->device);
 	kref_put(&sfp->f_ref, sg_remove_sfp);
+	sdp->open_cnt--;
+
+	/* possibly many open()s waiting on exlude clearing, start many;
+	 * only open(O_EXCL)s wait on 0==open_cnt so only start one */
+	if (sdp->exclude) {
+		sdp->exclude = false;
+		wake_up_interruptible_all(&sdp->open_wait);
+	} else if (0 == sdp->open_cnt) {
+		wake_up_interruptible(&sdp->open_wait);
+	}
+	mutex_unlock(&sdp->open_rel_lock);
 	return 0;
 }
 
@@ -455,7 +469,7 @@ sg_read(struct file *filp, char __user *
 	}
 	srp = sg_get_rq_mark(sfp, req_pack_id);
 	if (!srp) {		/* now wait on packet to arrive */
-		if (sdp->detached) {
+		if (atomic_read(&sdp->detaching)) {
 			retval = -ENODEV;
 			goto free_old_hdr;
 		}
@@ -464,9 +478,9 @@ sg_read(struct file *filp, char __user *
 			goto free_old_hdr;
 		}
 		retval = wait_event_interruptible(sfp->read_wait,
-			(sdp->detached ||
+			(atomic_read(&sdp->detaching) ||
 			(srp = sg_get_rq_mark(sfp, req_pack_id))));
-		if (sdp->detached) {
+		if (atomic_read(&sdp->detaching)) {
 			retval = -ENODEV;
 			goto free_old_hdr;
 		}
@@ -613,7 +627,7 @@ sg_write(struct file *filp, const char _
 		return -ENXIO;
 	SCSI_LOG_TIMEOUT(3, printk("sg_write: %s, count=%d\n",
 				   sdp->disk->disk_name, (int) count));
-	if (sdp->detached)
+	if (atomic_read(&sdp->detaching))
 		return -ENODEV;
 	if (!((filp->f_flags & O_NONBLOCK) ||
 	      scsi_block_when_processing_errors(sdp->device)))
@@ -806,7 +820,7 @@ sg_common_write(Sg_fd * sfp, Sg_request
 		sg_finish_rem_req(srp);
 		return k;	/* probably out of space --> ENOMEM */
 	}
-	if (sdp->detached) {
+	if (atomic_read(&sdp->detaching)) {
 		if (srp->bio) {
 			blk_end_request_all(srp->rq, -EIO);
 			srp->rq = NULL;
@@ -871,7 +885,7 @@ sg_ioctl(struct file *filp, unsigned int
 
 	switch (cmd_in) {
 	case SG_IO:
-		if (sdp->detached)
+		if (atomic_read(&sdp->detaching))
 			return -ENODEV;
 		if (!scsi_block_when_processing_errors(sdp->device))
 			return -ENXIO;
@@ -882,8 +896,8 @@ sg_ioctl(struct file *filp, unsigned int
 		if (result < 0)
 			return result;
 		result = wait_event_interruptible(sfp->read_wait,
-			(srp_done(sfp, srp) || sdp->detached));
-		if (sdp->detached)
+			(srp_done(sfp, srp) || atomic_read(&sdp->detaching)));
+		if (atomic_read(&sdp->detaching))
 			return -ENODEV;
 		write_lock_irq(&sfp->rq_list_lock);
 		if (srp->done) {
@@ -922,7 +936,7 @@ sg_ioctl(struct file *filp, unsigned int
 				sg_build_reserve(sfp, val);
 			}
 		} else {
-			if (sdp->detached)
+			if (atomic_read(&sdp->detaching))
 				return -ENODEV;
 			sfp->low_dma = sdp->device->host->unchecked_isa_dma;
 		}
@@ -935,7 +949,7 @@ sg_ioctl(struct file *filp, unsigned int
 		else {
 			sg_scsi_id_t __user *sg_idp = p;
 
-			if (sdp->detached)
+			if (atomic_read(&sdp->detaching))
 				return -ENODEV;
 			__put_user((int) sdp->device->host->host_no,
 				   &sg_idp->host_no);
@@ -1077,11 +1091,11 @@ sg_ioctl(struct file *filp, unsigned int
 			return result;
 		}
 	case SG_EMULATED_HOST:
-		if (sdp->detached)
+		if (atomic_read(&sdp->detaching))
 			return -ENODEV;
 		return put_user(sdp->device->host->hostt->emulated, ip);
 	case SG_SCSI_RESET:
-		if (sdp->detached)
+		if (atomic_read(&sdp->detaching))
 			return -ENODEV;
 		if (filp->f_flags & O_NONBLOCK) {
 			if (scsi_host_in_recovery(sdp->device->host))
@@ -1114,7 +1128,7 @@ sg_ioctl(struct file *filp, unsigned int
 		return (scsi_reset_provider(sdp->device, val) ==
 			SUCCESS) ? 0 : -EIO;
 	case SCSI_IOCTL_SEND_COMMAND:
-		if (sdp->detached)
+		if (atomic_read(&sdp->detaching))
 			return -ENODEV;
 		if (read_only) {
 			unsigned char opcode = WRITE_6;
@@ -1136,7 +1150,7 @@ sg_ioctl(struct file *filp, unsigned int
 	case SCSI_IOCTL_GET_BUS_NUMBER:
 	case SCSI_IOCTL_PROBE_HOST:
 	case SG_GET_TRANSFORM:
-		if (sdp->detached)
+		if (atomic_read(&sdp->detaching))
 			return -ENODEV;
 		return scsi_ioctl(sdp->device, cmd_in, p);
 	case BLKSECTGET:
@@ -1210,7 +1224,7 @@ sg_poll(struct file *filp, poll_table *
 	}
 	read_unlock_irqrestore(&sfp->rq_list_lock, iflags);
 
-	if (sdp->detached)
+	if (atomic_read(&sdp->detaching))
 		res |= POLLHUP;
 	else if (!sfp->cmd_q) {
 		if (0 == count)
@@ -1309,7 +1323,8 @@ sg_mmap(struct file *filp, struct vm_are
 	return 0;
 }
 
-static void sg_rq_end_io_usercontext(struct work_struct *work)
+static void
+sg_rq_end_io_usercontext(struct work_struct *work)
 {
 	struct sg_request *srp = container_of(work, struct sg_request, ew.work);
 	struct sg_fd *sfp = srp->parentfp;
@@ -1322,7 +1337,8 @@ static void sg_rq_end_io_usercontext(str
  * This function is a "bottom half" handler that is called by the mid
  * level when a command is completed (or has failed).
  */
-static void sg_rq_end_io(struct request *rq, int uptodate)
+static void
+sg_rq_end_io(struct request *rq, int uptodate)
 {
 	struct sg_request *srp = rq->end_io_data;
 	Sg_device *sdp;
@@ -1340,8 +1356,8 @@ static void sg_rq_end_io(struct request
 		return;
 
 	sdp = sfp->parentdp;
-	if (unlikely(sdp->detached))
-		printk(KERN_INFO "sg_rq_end_io: device detached\n");
+	if (unlikely(atomic_read(&sdp->detaching)))
+		pr_info("%s: device detaching\n", __func__);
 
 	sense = rq->sense;
 	result = rq->errors;
@@ -1364,7 +1380,7 @@ static void sg_rq_end_io(struct request
 		if ((sdp->sgdebug > 0) &&
 		    ((CHECK_CONDITION == srp->header.masked_status) ||
 		     (COMMAND_TERMINATED == srp->header.masked_status)))
-			__scsi_print_sense("sg_cmd_done", sense,
+			__scsi_print_sense(__func__, sense,
 					   SCSI_SENSE_BUFFERSIZE);
 
 		/* Following if statement is a patch supplied by Eric Youngdale */
@@ -1423,7 +1439,8 @@ static struct class *sg_sysfs_class;
 
 static int sg_sysfs_valid = 0;
 
-static Sg_device *sg_alloc(struct gendisk *disk, struct scsi_device *scsidp)
+static Sg_device *
+sg_alloc(struct gendisk *disk, struct scsi_device *scsidp)
 {
 	struct request_queue *q = scsidp->request_queue;
 	Sg_device *sdp;
@@ -1433,7 +1450,8 @@ static Sg_device *sg_alloc(struct gendis
 
 	sdp = kzalloc(sizeof(Sg_device), GFP_KERNEL);
 	if (!sdp) {
-		printk(KERN_WARNING "kmalloc Sg_device failure\n");
+		sdev_printk(KERN_WARNING, scsidp, "%s: kmalloc Sg_device "
+			    "failure\n", __func__);
 		return ERR_PTR(-ENOMEM);
 	}
 
@@ -1448,8 +1466,9 @@ static Sg_device *sg_alloc(struct gendis
 				    scsidp->type, SG_MAX_DEVS - 1);
 			error = -ENODEV;
 		} else {
-			printk(KERN_WARNING
-			       "idr allocation Sg_device failure: %d\n", error);
+			sdev_printk(KERN_WARNING, scsidp, "%s: idr "
+				    "allocation Sg_device failure: %d\n",
+				    __func__, error);
 		}
 		goto out_unlock;
 	}
@@ -1460,8 +1479,11 @@ static Sg_device *sg_alloc(struct gendis
 	disk->first_minor = k;
 	sdp->disk = disk;
 	sdp->device = scsidp;
+	mutex_init(&sdp->open_rel_lock);
 	INIT_LIST_HEAD(&sdp->sfds);
-	init_waitqueue_head(&sdp->o_excl_wait);
+	init_waitqueue_head(&sdp->open_wait);
+	atomic_set(&sdp->detaching, 0);
+	rwlock_init(&sdp->sfd_lock);
 	sdp->sg_tablesize = queue_max_segments(q);
 	sdp->index = k;
 	kref_init(&sdp->d_ref);
@@ -1479,7 +1501,7 @@ out_unlock:
 }
 
 static int
-sg_add(struct device *cl_dev, struct class_interface *cl_intf)
+sg_add_device(struct device *cl_dev, struct class_interface *cl_intf)
 {
 	struct scsi_device *scsidp = to_scsi_device(cl_dev->parent);
 	struct gendisk *disk;
@@ -1490,7 +1512,7 @@ sg_add(struct device *cl_dev, struct cla
 
 	disk = alloc_disk(1);
 	if (!disk) {
-		printk(KERN_WARNING "alloc_disk failed\n");
+		pr_warn("%s: alloc_disk failed\n", __func__);
 		return -ENOMEM;
 	}
 	disk->major = SCSI_GENERIC_MAJOR;
@@ -1498,7 +1520,7 @@ sg_add(struct device *cl_dev, struct cla
 	error = -ENOMEM;
 	cdev = cdev_alloc();
 	if (!cdev) {
-		printk(KERN_WARNING "cdev_alloc failed\n");
+		pr_warn("%s: cdev_alloc failed\n", __func__);
 		goto out;
 	}
 	cdev->owner = THIS_MODULE;
@@ -1506,7 +1528,7 @@ sg_add(struct device *cl_dev, struct cla
 
 	sdp = sg_alloc(disk, scsidp);
 	if (IS_ERR(sdp)) {
-		printk(KERN_WARNING "sg_alloc failed\n");
+		pr_warn("%s: sg_alloc failed\n", __func__);
 		error = PTR_ERR(sdp);
 		goto out;
 	}
@@ -1524,22 +1546,20 @@ sg_add(struct device *cl_dev, struct cla
 						      sdp->index),
 						sdp, "%s", disk->disk_name);
 		if (IS_ERR(sg_class_member)) {
-			printk(KERN_ERR "sg_add: "
-			       "device_create failed\n");
+			pr_err("%s: device_create failed\n", __func__);
 			error = PTR_ERR(sg_class_member);
 			goto cdev_add_err;
 		}
 		error = sysfs_create_link(&scsidp->sdev_gendev.kobj,
 					  &sg_class_member->kobj, "generic");
 		if (error)
-			printk(KERN_ERR "sg_add: unable to make symlink "
-					"'generic' back to sg%d\n", sdp->index);
+			pr_err("%s: unable to make symlink 'generic' back "
+			       "to sg%d\n", __func__, sdp->index);
 	} else
-		printk(KERN_WARNING "sg_add: sg_sys Invalid\n");
+		pr_warn("%s: sg_sys Invalid\n", __func__);
 
-	sdev_printk(KERN_NOTICE, scsidp,
-		    "Attached scsi generic sg%d type %d\n", sdp->index,
-		    scsidp->type);
+	sdev_printk(KERN_NOTICE, scsidp, "Attached scsi generic sg%d "
+		    "type %d\n", sdp->index, scsidp->type);
 
 	dev_set_drvdata(cl_dev, sdp);
 
@@ -1558,7 +1578,8 @@ out:
 	return error;
 }
 
-static void sg_device_destroy(struct kref *kref)
+static void
+sg_device_destroy(struct kref *kref)
 {
 	struct sg_device *sdp = container_of(kref, struct sg_device, d_ref);
 	unsigned long flags;
@@ -1580,33 +1601,39 @@ static void sg_device_destroy(struct kre
 	kfree(sdp);
 }
 
-static void sg_remove(struct device *cl_dev, struct class_interface *cl_intf)
+static void
+sg_remove_device(struct device *cl_dev, struct class_interface *cl_intf)
 {
 	struct scsi_device *scsidp = to_scsi_device(cl_dev->parent);
 	Sg_device *sdp = dev_get_drvdata(cl_dev);
 	unsigned long iflags;
 	Sg_fd *sfp;
+	int val;
 
-	if (!sdp || sdp->detached)
+	if (!sdp)
 		return;
+	/* want sdp->detaching non-zero as soon as possible */
+	val = atomic_inc_return(&sdp->detaching);
+	if (val > 1)
+		return; /* only want to do following once per device */
 
-	SCSI_LOG_TIMEOUT(3, printk("sg_remove: %s\n", sdp->disk->disk_name));
+	SCSI_LOG_TIMEOUT(3, printk("%s: %s\n", __func__,
+			 sdp->disk->disk_name));
 
-	/* Need a write lock to set sdp->detached. */
-	write_lock_irqsave(&sg_index_lock, iflags);
-	sdp->detached = 1;
+	read_lock_irqsave(&sdp->sfd_lock, iflags);
 	list_for_each_entry(sfp, &sdp->sfds, sfd_siblings) {
-		wake_up_interruptible(&sfp->read_wait);
+		wake_up_interruptible_all(&sfp->read_wait);
 		kill_fasync(&sfp->async_qp, SIGPOLL, POLL_HUP);
 	}
-	write_unlock_irqrestore(&sg_index_lock, iflags);
+	wake_up_interruptible_all(&sdp->open_wait);
+	read_unlock_irqrestore(&sdp->sfd_lock, iflags);
 
 	sysfs_remove_link(&scsidp->sdev_gendev.kobj, "generic");
 	device_destroy(sg_sysfs_class, MKDEV(SCSI_GENERIC_MAJOR, sdp->index));
 	cdev_del(sdp->cdev);
 	sdp->cdev = NULL;
 
-	sg_put_dev(sdp);
+	kref_put(&sdp->d_ref, sg_device_destroy);
 }
 
 module_param_named(scatter_elem_sz, scatter_elem_sz, int, S_IRUGO | S_IWUSR);
@@ -1676,7 +1703,8 @@ exit_sg(void)
 	idr_destroy(&sg_index_idr);
 }
 
-static int sg_start_req(Sg_request *srp, unsigned char *cmd)
+static int
+sg_start_req(Sg_request *srp, unsigned char *cmd)
 {
 	int res;
 	struct request *rq;
@@ -1778,7 +1806,8 @@ static int sg_start_req(Sg_request *srp,
 	return res;
 }
 
-static int sg_finish_rem_req(Sg_request * srp)
+static int
+sg_finish_rem_req(Sg_request *srp)
 {
 	int ret = 0;
 
@@ -2115,7 +2144,7 @@ sg_add_sfp(Sg_device * sdp, int dev)
 
 	sfp = kzalloc(sizeof(*sfp), GFP_ATOMIC | __GFP_NOWARN);
 	if (!sfp)
-		return NULL;
+		return ERR_PTR(-ENOMEM);
 
 	init_waitqueue_head(&sfp->read_wait);
 	rwlock_init(&sfp->rq_list_lock);
@@ -2129,9 +2158,13 @@ sg_add_sfp(Sg_device * sdp, int dev)
 	sfp->cmd_q = SG_DEF_COMMAND_Q;
 	sfp->keep_orphan = SG_DEF_KEEP_ORPHAN;
 	sfp->parentdp = sdp;
-	write_lock_irqsave(&sg_index_lock, iflags);
+	write_lock_irqsave(&sdp->sfd_lock, iflags);
+	if (atomic_read(&sdp->detaching)) {
+		write_unlock_irqrestore(&sdp->sfd_lock, iflags);
+		return ERR_PTR(-ENODEV);
+	}
 	list_add_tail(&sfp->sfd_siblings, &sdp->sfds);
-	write_unlock_irqrestore(&sg_index_lock, iflags);
+	write_unlock_irqrestore(&sdp->sfd_lock, iflags);
 	SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp: sfp=0x%p\n", sfp));
 	if (unlikely(sg_big_buff != def_reserved_size))
 		sg_big_buff = def_reserved_size;
@@ -2147,7 +2180,8 @@ sg_add_sfp(Sg_device * sdp, int dev)
 	return sfp;
 }
 
-static void sg_remove_sfp_usercontext(struct work_struct *work)
+static void
+sg_remove_sfp_usercontext(struct work_struct *work)
 {
 	struct sg_fd *sfp = container_of(work, struct sg_fd, ew.work);
 	struct sg_device *sdp = sfp->parentdp;
@@ -2171,20 +2205,20 @@ static void sg_remove_sfp_usercontext(st
 	kfree(sfp);
 
 	scsi_device_put(sdp->device);
-	sg_put_dev(sdp);
+	kref_put(&sdp->d_ref, sg_device_destroy);
 	module_put(THIS_MODULE);
 }
 
-static void sg_remove_sfp(struct kref *kref)
+static void
+sg_remove_sfp(struct kref *kref)
 {
 	struct sg_fd *sfp = container_of(kref, struct sg_fd, f_ref);
 	struct sg_device *sdp = sfp->parentdp;
 	unsigned long iflags;
 
-	write_lock_irqsave(&sg_index_lock, iflags);
+	write_lock_irqsave(&sdp->sfd_lock, iflags);
 	list_del(&sfp->sfd_siblings);
-	write_unlock_irqrestore(&sg_index_lock, iflags);
-	wake_up_interruptible(&sdp->o_excl_wait);
+	write_unlock_irqrestore(&sdp->sfd_lock, iflags);
 
 	INIT_WORK(&sfp->ew.work, sg_remove_sfp_usercontext);
 	schedule_work(&sfp->ew.work);
@@ -2235,7 +2269,8 @@ static Sg_device *sg_lookup_dev(int dev)
 	return idr_find(&sg_index_idr, dev);
 }
 
-static Sg_device *sg_get_dev(int dev)
+static Sg_device *
+sg_get_dev(int dev)
 {
 	struct sg_device *sdp;
 	unsigned long flags;
@@ -2244,8 +2279,8 @@ static Sg_device *sg_get_dev(int dev)
 	sdp = sg_lookup_dev(dev);
 	if (!sdp)
 		sdp = ERR_PTR(-ENXIO);
-	else if (sdp->detached) {
-		/* If sdp->detached, then the refcount may already be 0, in
+	else if (atomic_read(&sdp->detaching)) {
+		/* If sdp->detaching, then the refcount may already be 0, in
 		 * which case it would be a bug to do kref_get().
 		 */
 		sdp = ERR_PTR(-ENODEV);
@@ -2256,11 +2291,6 @@ static Sg_device *sg_get_dev(int dev)
 	return sdp;
 }
 
-static void sg_put_dev(struct sg_device *sdp)
-{
-	kref_put(&sdp->d_ref, sg_device_destroy);
-}
-
 #ifdef CONFIG_SCSI_PROC_FS
 
 static struct proc_dir_entry *sg_proc_sgp = NULL;
@@ -2477,8 +2507,7 @@ static int sg_proc_single_open_version(s
 
 static int sg_proc_seq_show_devhdr(struct seq_file *s, void *v)
 {
-	seq_printf(s, "host\tchan\tid\tlun\ttype\topens\tqdepth\tbusy\t"
-		   "online\n");
+	seq_puts(s, "host\tchan\tid\tlun\ttype\topens\tqdepth\tbusy\tonline\n");
 	return 0;
 }
 
@@ -2534,7 +2563,11 @@ static int sg_proc_seq_show_dev(struct s
 
 	read_lock_irqsave(&sg_index_lock, iflags);
 	sdp = it ? sg_lookup_dev(it->index) : NULL;
-	if (sdp && (scsidp = sdp->device) && (!sdp->detached))
+	if ((NULL == sdp) || (NULL == sdp->device) ||
+	    (atomic_read(&sdp->detaching)))
+		seq_puts(s, "-1\t-1\t-1\t-1\t-1\t-1\t-1\t-1\t-1\n");
+	else {
+		scsidp = sdp->device;
 		seq_printf(s, "%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n",
 			      scsidp->host->host_no, scsidp->channel,
 			      scsidp->id, scsidp->lun, (int) scsidp->type,
@@ -2542,8 +2575,7 @@ static int sg_proc_seq_show_dev(struct s
 			      (int) scsidp->queue_depth,
 			      (int) scsidp->device_busy,
 			      (int) scsi_device_online(scsidp));
-	else
-		seq_printf(s, "-1\t-1\t-1\t-1\t-1\t-1\t-1\t-1\t-1\n");
+	}
 	read_unlock_irqrestore(&sg_index_lock, iflags);
 	return 0;
 }
@@ -2562,11 +2594,12 @@ static int sg_proc_seq_show_devstrs(stru
 
 	read_lock_irqsave(&sg_index_lock, iflags);
 	sdp = it ? sg_lookup_dev(it->index) : NULL;
-	if (sdp && (scsidp = sdp->device) && (!sdp->detached))
+	scsidp = sdp ? sdp->device : NULL;
+	if (sdp && scsidp && (!atomic_read(&sdp->detaching)))
 		seq_printf(s, "%8.8s\t%16.16s\t%4.4s\n",
 			   scsidp->vendor, scsidp->model, scsidp->rev);
 	else
-		seq_printf(s, "<no active device>\n");
+		seq_puts(s, "<no active device>\n");
 	read_unlock_irqrestore(&sg_index_lock, iflags);
 	return 0;
 }
@@ -2611,12 +2644,12 @@ static void sg_proc_debug_helper(struct
 				else
 					cp = "     ";
 			}
-			seq_printf(s, cp);
+			seq_puts(s, cp);
 			blen = srp->data.bufflen;
 			usg = srp->data.k_use_sg;
-			seq_printf(s, srp->done ? 
-				   ((1 == srp->done) ?  "rcv:" : "fin:")
-				   : "act:");
+			seq_puts(s, srp->done ?
+				 ((1 == srp->done) ?  "rcv:" : "fin:")
+				  : "act:");
 			seq_printf(s, " id=%d blen=%d",
 				   srp->header.pack_id, blen);
 			if (srp->done)
@@ -2632,7 +2665,7 @@ static void sg_proc_debug_helper(struct
 				   (int) srp->data.cmd_opcode);
 		}
 		if (0 == m)
-			seq_printf(s, "     No requests active\n");
+			seq_puts(s, "     No requests active\n");
 		read_unlock(&fp->rq_list_lock);
 	}
 }
@@ -2648,31 +2681,34 @@ static int sg_proc_seq_show_debug(struct
 	Sg_device *sdp;
 	unsigned long iflags;
 
-	if (it && (0 == it->index)) {
-		seq_printf(s, "max_active_device=%d(origin 1)\n",
-			   (int)it->max);
-		seq_printf(s, " def_reserved_size=%d\n", sg_big_buff);
-	}
+	if (it && (0 == it->index))
+		seq_printf(s, "max_active_device=%d  def_reserved_size=%d\n",
+			   (int)it->max, sg_big_buff);
 
 	read_lock_irqsave(&sg_index_lock, iflags);
 	sdp = it ? sg_lookup_dev(it->index) : NULL;
-	if (sdp && !list_empty(&sdp->sfds)) {
-		struct scsi_device *scsidp = sdp->device;
-
+	if (NULL == sdp)
+		goto skip;
+	read_lock(&sdp->sfd_lock);
+	if (!list_empty(&sdp->sfds)) {
 		seq_printf(s, " >>> device=%s ", sdp->disk->disk_name);
-		if (sdp->detached)
-			seq_printf(s, "detached pending close ");
-		else
-			seq_printf
-			    (s, "scsi%d chan=%d id=%d lun=%d   em=%d",
-			     scsidp->host->host_no,
-			     scsidp->channel, scsidp->id,
-			     scsidp->lun,
-			     scsidp->host->hostt->emulated);
-		seq_printf(s, " sg_tablesize=%d excl=%d\n",
-			   sdp->sg_tablesize, get_exclude(sdp));
+		if (atomic_read(&sdp->detaching))
+			seq_puts(s, "detaching pending close ");
+		else if (sdp->device) {
+			struct scsi_device *scsidp = sdp->device;
+
+			seq_printf(s, "%d:%d:%d:%d   em=%d",
+				   scsidp->host->host_no,
+				   scsidp->channel, scsidp->id,
+				   scsidp->lun,
+				   scsidp->host->hostt->emulated);
+		}
+		seq_printf(s, " sg_tablesize=%d excl=%d open_cnt=%d\n",
+			   sdp->sg_tablesize, sdp->exclude, sdp->open_cnt);
 		sg_proc_debug_helper(s, sdp);
 	}
+	read_unlock(&sdp->sfd_lock);
+skip:
 	read_unlock_irqrestore(&sg_index_lock, iflags);
 	return 0;
 }


^ permalink raw reply	[relevance 3%]

* [PATCH 3.16 09/61] net-sysfs: Call dev_hold always in netdev_queue_add_kobject
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (7 preceding siblings ...)
  2020-06-09 18:03  9% ` [PATCH 3.16 08/61] net-sysfs: fix netdev_queue_add_kobject() breakage Ben Hutchings
@ 2020-06-09 18:04 12% ` Ben Hutchings
  2020-06-09 18:04 12% ` [PATCH 3.16 10/61] net-sysfs: Call dev_hold always in rx_queue_add_kobject Ben Hutchings
                   ` (52 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Tetsuo Handa, Lukas Bulwahn, David Miller,
	Hulk Robot, Jouni Hogander

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Jouni Hogander <jouni.hogander@unikie.com>

commit e0b60903b434a7ee21ba8d8659f207ed84101e89 upstream.

Dev_hold has to be called always in netdev_queue_add_kobject.
Otherwise usage count drops below 0 in case of failure in
kobject_init_and_add.

Fixes: b8eb718348b8 ("net-sysfs: Fix reference count leak in rx|netdev_queue_add_kobject")
Reported-by: Hulk Robot <hulkci@huawei.com>
Cc: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Cc: David Miller <davem@davemloft.net>
Cc: Lukas Bulwahn <lukas.bulwahn@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 net/core/net-sysfs.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -1143,14 +1143,17 @@ static int netdev_queue_add_kobject(stru
 	struct kobject *kobj = &queue->kobj;
 	int error = 0;
 
+	/* Kobject_put later will trigger netdev_queue_release call
+	 * which decreases dev refcount: Take that reference here
+	 */
+	dev_hold(queue->dev);
+
 	kobj->kset = net->queues_kset;
 	error = kobject_init_and_add(kobj, &netdev_queue_ktype, NULL,
 	    "tx-%u", index);
 	if (error)
 		goto err;
 
-	dev_hold(queue->dev);
-
 #ifdef CONFIG_BQL
 	error = sysfs_create_group(kobj, &dql_group);
 	if (error)


^ permalink raw reply	[relevance 12%]

* [PATCH 3.16 47/61] USB: gadget: fix illegal array access in binding with UDC
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (45 preceding siblings ...)
  2020-06-09 18:04 11% ` [PATCH 3.16 46/61] signal: Extend exec_id to 64bits Ben Hutchings
@ 2020-06-09 18:04  8% ` Ben Hutchings
  2020-06-09 18:04 13% ` [PATCH 3.16 48/61] ext4: Make checks for metadata_csum feature safer Ben Hutchings
                   ` (14 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, stable, Felipe Balbi, Kyungtae Kim,
	Greg Kroah-Hartman

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Kyungtae Kim <kt0755@gmail.com>

commit 15753588bcd4bbffae1cca33c8ced5722477fe1f upstream.

FuzzUSB (a variant of syzkaller) found an illegal array access
using an incorrect index while binding a gadget with UDC.

Reference: https://www.spinics.net/lists/linux-usb/msg194331.html

This bug occurs when a size variable used for a buffer
is misused to access its strcpy-ed buffer.
Given a buffer along with its size variable (taken from user input),
from which, a new buffer is created using kstrdup().
Due to the original buffer containing 0 value in the middle,
the size of the kstrdup-ed buffer becomes smaller than that of the original.
So accessing the kstrdup-ed buffer with the same size variable
triggers memory access violation.

The fix makes sure no zero value in the buffer,
by comparing the strlen() of the orignal buffer with the size variable,
so that the access to the kstrdup-ed buffer is safe.

BUG: KASAN: slab-out-of-bounds in gadget_dev_desc_UDC_store+0x1ba/0x200
drivers/usb/gadget/configfs.c:266
Read of size 1 at addr ffff88806a55dd7e by task syz-executor.0/17208

CPU: 2 PID: 17208 Comm: syz-executor.0 Not tainted 5.6.8 #1
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
Call Trace:
 __dump_stack lib/dump_stack.c:77 [inline]
 dump_stack+0xce/0x128 lib/dump_stack.c:118
 print_address_description.constprop.4+0x21/0x3c0 mm/kasan/report.c:374
 __kasan_report+0x131/0x1b0 mm/kasan/report.c:506
 kasan_report+0x12/0x20 mm/kasan/common.c:641
 __asan_report_load1_noabort+0x14/0x20 mm/kasan/generic_report.c:132
 gadget_dev_desc_UDC_store+0x1ba/0x200 drivers/usb/gadget/configfs.c:266
 flush_write_buffer fs/configfs/file.c:251 [inline]
 configfs_write_file+0x2f1/0x4c0 fs/configfs/file.c:283
 __vfs_write+0x85/0x110 fs/read_write.c:494
 vfs_write+0x1cd/0x510 fs/read_write.c:558
 ksys_write+0x18a/0x220 fs/read_write.c:611
 __do_sys_write fs/read_write.c:623 [inline]
 __se_sys_write fs/read_write.c:620 [inline]
 __x64_sys_write+0x73/0xb0 fs/read_write.c:620
 do_syscall_64+0x9e/0x510 arch/x86/entry/common.c:294
 entry_SYSCALL_64_after_hwframe+0x49/0xbe

Signed-off-by: Kyungtae Kim <kt0755@gmail.com>
Reported-and-tested-by: Kyungtae Kim <kt0755@gmail.com>
Cc: Felipe Balbi <balbi@kernel.org>
Cc: stable <stable@vger.kernel.org>
Link: https://lore.kernel.org/r/20200510054326.GA19198@pizza01
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/usb/gadget/configfs.c | 3 +++
 1 file changed, 3 insertions(+)

--- a/drivers/usb/gadget/configfs.c
+++ b/drivers/usb/gadget/configfs.c
@@ -254,6 +254,9 @@ static ssize_t gadget_dev_desc_UDC_store
 	char *name;
 	int ret;
 
+	if (strlen(page) < len)
+		return -EOVERFLOW;
+
 	name = kstrdup(page, GFP_KERNEL);
 	if (!name)
 		return -ENOMEM;


^ permalink raw reply	[relevance 8%]

* [PATCH 3.16 35/61] scsi: sg: Re-fix off by one in sg_fill_request_table()
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (33 preceding siblings ...)
  2020-06-09 18:04  9% ` [PATCH 3.16 34/61] scsi: sg: fixup infoleak when using SG_GET_REQUEST_TABLE Ben Hutchings
@ 2020-06-09 18:04 11% ` Ben Hutchings
  2020-06-09 18:04 10% ` [PATCH 3.16 36/61] scsi: sg: disable SET_FORCE_LOW_DMA Ben Hutchings
                   ` (26 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Ben Hutchings, Douglas Gilbert,
	Greg Kroah-Hartman, Martin K. Petersen

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Ben Hutchings <ben.hutchings@codethink.co.uk>

commit 587c3c9f286cee5c9cac38d28c8ae1875f4ec85b upstream.

Commit 109bade9c625 ("scsi: sg: use standard lists for sg_requests")
introduced an off-by-one error in sg_ioctl(), which was fixed by commit
bd46fc406b30 ("scsi: sg: off by one in sg_ioctl()").

Unfortunately commit 4759df905a47 ("scsi: sg: factor out
sg_fill_request_table()") moved that code, and reintroduced the
bug (perhaps due to a botched rebase).  Fix it again.

Fixes: 4759df905a47 ("scsi: sg: factor out sg_fill_request_table()")
Signed-off-by: Ben Hutchings <ben.hutchings@codethink.co.uk>
Acked-by: Douglas Gilbert <dgilbert@interlog.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/scsi/sg.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -879,7 +879,7 @@ sg_fill_request_table(Sg_fd *sfp, sg_req
 
 	val = 0;
 	list_for_each_entry(srp, &sfp->rq_list, entry) {
-		if (val > SG_MAX_QUEUE)
+		if (val >= SG_MAX_QUEUE)
 			break;
 		rinfo[val].req_state = srp->done + 1;
 		rinfo[val].problem =


^ permalink raw reply	[relevance 11%]

* [PATCH 3.16 27/61] scsi: sg: reset 'res_in_use' after unlinking reserved array
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (25 preceding siblings ...)
  2020-06-09 18:04  7% ` [PATCH 3.16 26/61] scsi: sg: protect accesses to 'reserved' page array Ben Hutchings
@ 2020-06-09 18:04  9% ` Ben Hutchings
  2020-06-09 18:04  9% ` [PATCH 3.16 28/61] scsi: sg: protect against races between mmap() and SG_SET_RESERVED_SIZE Ben Hutchings
                   ` (34 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Hannes Reinecke, Greg Kroah-Hartman,
	Hannes Reinecke, Todd Poynor, Christoph Hellwig,
	Martin K. Petersen, Johannes Thumshirn

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Hannes Reinecke <hare@suse.de>

commit e791ce27c3f6a1d3c746fd6a8f8e36c9540ec6f9 upstream.

Once the reserved page array is unused we can reset the 'res_in_use'
state; here we can do a lazy update without holding the mutex as we only
need to check against concurrent access, not concurrent release.

[mkp: checkpatch]

Fixes: 1bc0eb044615 ("scsi: sg: protect accesses to 'reserved' page array")
Signed-off-by: Hannes Reinecke <hare@suse.com>
Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Cc: Todd Poynor <toddpoynor@google.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/scsi/sg.c | 2 ++
 1 file changed, 2 insertions(+)

--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -2062,6 +2062,8 @@ sg_unlink_reserve(Sg_fd * sfp, Sg_reques
 	req_schp->sglist_len = 0;
 	sfp->save_scat_len = 0;
 	srp->res_used = 0;
+	/* Called without mutex lock to avoid deadlock */
+	sfp->res_in_use = 0;
 }
 
 static Sg_request *


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 51/61] ext4: fix block validity checks for journal inodes using indirect blocks
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (49 preceding siblings ...)
  2020-06-09 18:04  9% ` [PATCH 3.16 50/61] ext4: unsigned int compared against zero Ben Hutchings
@ 2020-06-09 18:04 12% ` Ben Hutchings
  2020-06-09 18:04 12% ` [PATCH 3.16 52/61] ext4: don't perform block validity checks on the journal inode Ben Hutchings
                   ` (10 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Theodore Ts'o, Arthur Marsh

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Theodore Ts'o <tytso@mit.edu>

commit 170417c8c7bb2cbbdd949bf5c443c0c8f24a203b upstream.

Commit 345c0dbf3a30 ("ext4: protect journal inode's blocks using
block_validity") failed to add an exception for the journal inode in
ext4_check_blockref(), which is the function used by ext4_get_branch()
for indirect blocks.  This caused attempts to read from the ext3-style
journals to fail with:

[  848.968550] EXT4-fs error (device sdb7): ext4_get_branch:171: inode #8: block 30343695: comm jbd2/sdb7-8: invalid block

Fix this by adding the missing exception check.

Fixes: 345c0dbf3a30 ("ext4: protect journal inode's blocks using block_validity")
Reported-by: Arthur Marsh <arthur.marsh@internode.on.net>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
[bwh: Backported to 3.16: Use EXT4_HAS_COMPAT_FEATURE]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
--- a/fs/ext4/block_validity.c
+++ b/fs/ext4/block_validity.c
@@ -277,6 +277,12 @@ int ext4_check_blockref(const char *func
 	__le32 *bref = p;
 	unsigned int blk;
 
+	if (EXT4_HAS_COMPAT_FEATURE(inode->i_sb,
+				    EXT4_FEATURE_COMPAT_HAS_JOURNAL) &&
+	    (inode->i_ino ==
+	     le32_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_journal_inum)))
+		return 0;
+
 	while (bref < p+max) {
 		blk = le32_to_cpu(*bref++);
 		if (blk &&


^ permalink raw reply	[relevance 12%]

* [PATCH 3.16 33/61] scsi: sg: factor out sg_fill_request_table()
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (31 preceding siblings ...)
  2020-06-09 18:04  9% ` [PATCH 3.16 32/61] scsi: sg: off by one in sg_ioctl() Ben Hutchings
@ 2020-06-09 18:04  8% ` Ben Hutchings
  2020-06-09 18:04  9% ` [PATCH 3.16 34/61] scsi: sg: fixup infoleak when using SG_GET_REQUEST_TABLE Ben Hutchings
                   ` (28 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Hannes Reinecke, Bart Van Assche,
	Greg Kroah-Hartman, Hannes Reinecke, Martin K. Petersen,
	Christoph Hellwig

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Hannes Reinecke <hare@suse.de>

commit 4759df905a474d245752c9dc94288e779b8734dd upstream.

Factor out sg_fill_request_table() for better readability.

[mkp: typos, applied by hand]

Signed-off-by: Hannes Reinecke <hare@suse.com>
Reviewed-by: Bart Van Assche <bart.vanassche@wdc.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/scsi/sg.c | 61 +++++++++++++++++++++++++++--------------------
 1 file changed, 35 insertions(+), 26 deletions(-)

--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -870,6 +870,40 @@ static int max_sectors_bytes(struct requ
 	return max_sectors << 9;
 }
 
+static void
+sg_fill_request_table(Sg_fd *sfp, sg_req_info_t *rinfo)
+{
+	Sg_request *srp;
+	int val;
+	unsigned int ms;
+
+	val = 0;
+	list_for_each_entry(srp, &sfp->rq_list, entry) {
+		if (val > SG_MAX_QUEUE)
+			break;
+		memset(&rinfo[val], 0, SZ_SG_REQ_INFO);
+		rinfo[val].req_state = srp->done + 1;
+		rinfo[val].problem =
+			srp->header.masked_status &
+			srp->header.host_status &
+			srp->header.driver_status;
+		if (srp->done)
+			rinfo[val].duration =
+				srp->header.duration;
+		else {
+			ms = jiffies_to_msecs(jiffies);
+			rinfo[val].duration =
+				(ms > srp->header.duration) ?
+				(ms - srp->header.duration) : 0;
+		}
+		rinfo[val].orphan = srp->orphan;
+		rinfo[val].sg_io_owned = srp->sg_io_owned;
+		rinfo[val].pack_id = srp->header.pack_id;
+		rinfo[val].usr_ptr = srp->header.usr_ptr;
+		val++;
+	}
+}
+
 static long
 sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
 {
@@ -1063,38 +1097,13 @@ sg_ioctl(struct file *filp, unsigned int
 			return -EFAULT;
 		else {
 			sg_req_info_t *rinfo;
-			unsigned int ms;
 
 			rinfo = kmalloc(SZ_SG_REQ_INFO * SG_MAX_QUEUE,
 								GFP_KERNEL);
 			if (!rinfo)
 				return -ENOMEM;
 			read_lock_irqsave(&sfp->rq_list_lock, iflags);
-			val = 0;
-			list_for_each_entry(srp, &sfp->rq_list, entry) {
-				if (val >= SG_MAX_QUEUE)
-					break;
-				memset(&rinfo[val], 0, SZ_SG_REQ_INFO);
-				rinfo[val].req_state = srp->done + 1;
-				rinfo[val].problem =
-					srp->header.masked_status &
-					srp->header.host_status &
-					srp->header.driver_status;
-				if (srp->done)
-					rinfo[val].duration =
-						srp->header.duration;
-				else {
-					ms = jiffies_to_msecs(jiffies);
-					rinfo[val].duration =
-						(ms > srp->header.duration) ?
-						(ms - srp->header.duration) : 0;
-				}
-				rinfo[val].orphan = srp->orphan;
-				rinfo[val].sg_io_owned = srp->sg_io_owned;
-				rinfo[val].pack_id = srp->header.pack_id;
-				rinfo[val].usr_ptr = srp->header.usr_ptr;
-				val++;
-			}
+			sg_fill_request_table(sfp, rinfo);
 			read_unlock_irqrestore(&sfp->rq_list_lock, iflags);
 			result = __copy_to_user(p, rinfo,
 						SZ_SG_REQ_INFO * SG_MAX_QUEUE);


^ permalink raw reply	[relevance 8%]

* [PATCH 3.16 58/61] x86/speculation: Add SRBDS vulnerability and mitigation documentation
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (56 preceding siblings ...)
  2020-06-09 18:04  7% ` [PATCH 3.16 57/61] x86/speculation: Add Special Register Buffer Data Sampling (SRBDS) mitigation Ben Hutchings
@ 2020-06-09 18:04  6% ` Ben Hutchings
  2020-06-09 18:04  9% ` [PATCH 3.16 59/61] x86/speculation: Add Ivy Bridge to affected list Ben Hutchings
                   ` (3 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Mark Gross, Tony Luck, Borislav Petkov,
	Josh Poimboeuf

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Mark Gross <mgross@linux.intel.com>

commit 7222a1b5b87417f22265c92deea76a6aecd0fb0f upstream.

Add documentation for the SRBDS vulnerability and its mitigation.

 [ bp: Massage.
   jpoimboe: sysfs table strings. ]

Signed-off-by: Mark Gross <mgross@linux.intel.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
Reviewed-by: Tony Luck <tony.luck@intel.com>
Reviewed-by: Josh Poimboeuf <jpoimboe@redhat.com>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 .../special-register-buffer-data-sampling.rst | 148 ++++++++++++++++++
 1 file changed, 148 insertions(+)
 create mode 100644 Documentation/hw-vuln/special-register-buffer-data-sampling.rst

--- /dev/null
+++ b/Documentation/hw-vuln/special-register-buffer-data-sampling.rst
@@ -0,0 +1,148 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+SRBDS - Special Register Buffer Data Sampling
+=============================================
+
+SRBDS is a hardware vulnerability that allows MDS :doc:`mds` techniques to
+infer values returned from special register accesses.  Special register
+accesses are accesses to off core registers.  According to Intel's evaluation,
+the special register reads that have a security expectation of privacy are
+RDRAND, RDSEED and SGX EGETKEY.
+
+When RDRAND, RDSEED and EGETKEY instructions are used, the data is moved
+to the core through the special register mechanism that is susceptible
+to MDS attacks.
+
+Affected processors
+--------------------
+Core models (desktop, mobile, Xeon-E3) that implement RDRAND and/or RDSEED may
+be affected.
+
+A processor is affected by SRBDS if its Family_Model and stepping is
+in the following list, with the exception of the listed processors
+exporting MDS_NO while Intel TSX is available yet not enabled. The
+latter class of processors are only affected when Intel TSX is enabled
+by software using TSX_CTRL_MSR otherwise they are not affected.
+
+  =============  ============  ========
+  common name    Family_Model  Stepping
+  =============  ============  ========
+  Haswell        06_3CH        All
+  Haswell_L      06_45H        All
+  Haswell_G      06_46H        All
+
+  Broadwell_G    06_47H        All
+  Broadwell      06_3DH        All
+
+  Skylake_L      06_4EH        All
+  Skylake        06_5EH        All
+
+  Kabylake_L     06_8EH        <=0xC
+
+  Kabylake       06_9EH        <=0xD
+  =============  ============  ========
+
+Related CVEs
+------------
+
+The following CVE entry is related to this SRBDS issue:
+
+    ==============  =====  =====================================
+    CVE-2020-0543   SRBDS  Special Register Buffer Data Sampling
+    ==============  =====  =====================================
+
+Attack scenarios
+----------------
+An unprivileged user can extract values returned from RDRAND and RDSEED
+executed on another core or sibling thread using MDS techniques.
+
+
+Mitigation mechanism
+-------------------
+Intel will release microcode updates that modify the RDRAND, RDSEED, and
+EGETKEY instructions to overwrite secret special register data in the shared
+staging buffer before the secret data can be accessed by another logical
+processor.
+
+During execution of the RDRAND, RDSEED, or EGETKEY instructions, off-core
+accesses from other logical processors will be delayed until the special
+register read is complete and the secret data in the shared staging buffer is
+overwritten.
+
+This has three effects on performance:
+
+#. RDRAND, RDSEED, or EGETKEY instructions have higher latency.
+
+#. Executing RDRAND at the same time on multiple logical processors will be
+   serialized, resulting in an overall reduction in the maximum RDRAND
+   bandwidth.
+
+#. Executing RDRAND, RDSEED or EGETKEY will delay memory accesses from other
+   logical processors that miss their core caches, with an impact similar to
+   legacy locked cache-line-split accesses.
+
+The microcode updates provide an opt-out mechanism (RNGDS_MITG_DIS) to disable
+the mitigation for RDRAND and RDSEED instructions executed outside of Intel
+Software Guard Extensions (Intel SGX) enclaves. On logical processors that
+disable the mitigation using this opt-out mechanism, RDRAND and RDSEED do not
+take longer to execute and do not impact performance of sibling logical
+processors memory accesses. The opt-out mechanism does not affect Intel SGX
+enclaves (including execution of RDRAND or RDSEED inside an enclave, as well
+as EGETKEY execution).
+
+IA32_MCU_OPT_CTRL MSR Definition
+--------------------------------
+Along with the mitigation for this issue, Intel added a new thread-scope
+IA32_MCU_OPT_CTRL MSR, (address 0x123). The presence of this MSR and
+RNGDS_MITG_DIS (bit 0) is enumerated by CPUID.(EAX=07H,ECX=0).EDX[SRBDS_CTRL =
+9]==1. This MSR is introduced through the microcode update.
+
+Setting IA32_MCU_OPT_CTRL[0] (RNGDS_MITG_DIS) to 1 for a logical processor
+disables the mitigation for RDRAND and RDSEED executed outside of an Intel SGX
+enclave on that logical processor. Opting out of the mitigation for a
+particular logical processor does not affect the RDRAND and RDSEED mitigations
+for other logical processors.
+
+Note that inside of an Intel SGX enclave, the mitigation is applied regardless
+of the value of RNGDS_MITG_DS.
+
+Mitigation control on the kernel command line
+---------------------------------------------
+The kernel command line allows control over the SRBDS mitigation at boot time
+with the option "srbds=".  The option for this is:
+
+  ============= =============================================================
+  off           This option disables SRBDS mitigation for RDRAND and RDSEED on
+                affected platforms.
+  ============= =============================================================
+
+SRBDS System Information
+-----------------------
+The Linux kernel provides vulnerability status information through sysfs.  For
+SRBDS this can be accessed by the following sysfs file:
+/sys/devices/system/cpu/vulnerabilities/srbds
+
+The possible values contained in this file are:
+
+ ============================== =============================================
+ Not affected                   Processor not vulnerable
+ Vulnerable                     Processor vulnerable and mitigation disabled
+ Vulnerable: No microcode       Processor vulnerable and microcode is missing
+                                mitigation
+ Mitigation: Microcode          Processor is vulnerable and mitigation is in
+                                effect.
+ Mitigation: TSX disabled       Processor is only vulnerable when TSX is
+                                enabled while this system was booted with TSX
+                                disabled.
+ Unknown: Dependent on
+ hypervisor status              Running on virtual guest processor that is
+                                affected but with no way to know if host
+                                processor is mitigated or vulnerable.
+ ============================== =============================================
+
+SRBDS Default mitigation
+------------------------
+This new microcode serializes processor access during execution of RDRAND,
+RDSEED ensures that the shared buffer is overwritten before it is released for
+reuse.  Use the "srbds=off" kernel command line to disable the mitigation for
+RDRAND and RDSEED.


^ permalink raw reply	[relevance 6%]

* [PATCH 3.16 44/61] scsi: sg: add sg_remove_request in sg_common_write
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (42 preceding siblings ...)
  2020-06-09 18:04  9% ` [PATCH 3.16 43/61] scsi: sg: fix minor memory leak in error path Ben Hutchings
@ 2020-06-09 18:04  9% ` Ben Hutchings
  2020-06-09 18:04  9% ` [PATCH 3.16 45/61] scsi: sg: add sg_remove_request in sg_write Ben Hutchings
                   ` (17 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Greg Kroah-Hartman, Douglas Gilbert,
	Li Bin, Martin K. Petersen

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Li Bin <huawei.libin@huawei.com>

commit 849f8583e955dbe3a1806e03ecacd5e71cce0a08 upstream.

If the dxfer_len is greater than 256M then the request is invalid and we
need to call sg_remove_request in sg_common_write.

Link: https://lore.kernel.org/r/1586777361-17339-1-git-send-email-huawei.libin@huawei.com
Fixes: f930c7043663 ("scsi: sg: only check for dxfer_len greater than 256M")
Acked-by: Douglas Gilbert <dgilbert@interlog.com>
Signed-off-by: Li Bin <huawei.libin@huawei.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/scsi/sg.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -808,8 +808,10 @@ sg_common_write(Sg_fd * sfp, Sg_request
 	SCSI_LOG_TIMEOUT(4, printk("sg_common_write:  scsi opcode=0x%02x, cmd_size=%d\n",
 			  (int) cmnd[0], (int) hp->cmd_len));
 
-	if (hp->dxfer_len >= SZ_256M)
+	if (hp->dxfer_len >= SZ_256M) {
+		sg_remove_request(sfp, srp);
 		return -EINVAL;
+	}
 
 	k = sg_start_req(srp, cmnd);
 	if (k) {


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 46/61] signal: Extend exec_id to 64bits
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (44 preceding siblings ...)
  2020-06-09 18:04  9% ` [PATCH 3.16 45/61] scsi: sg: add sg_remove_request in sg_write Ben Hutchings
@ 2020-06-09 18:04 11% ` Ben Hutchings
  2020-06-09 18:04  8% ` [PATCH 3.16 47/61] USB: gadget: fix illegal array access in binding with UDC Ben Hutchings
                   ` (15 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable; +Cc: akpm, Denis Kirjanov, Eric W. Biederman, stable

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: "Eric W. Biederman" <ebiederm@xmission.com>

commit d1e7fd6462ca9fc76650fbe6ca800e35b24267da upstream.

Replace the 32bit exec_id with a 64bit exec_id to make it impossible
to wrap the exec_id counter.  With care an attacker can cause exec_id
wrap and send arbitrary signals to a newly exec'd parent.  This
bypasses the signal sending checks if the parent changes their
credentials during exec.

The severity of this problem can been seen that in my limited testing
of a 32bit exec_id it can take as little as 19s to exec 65536 times.
Which means that it can take as little as 14 days to wrap a 32bit
exec_id.  Adam Zabrocki has succeeded wrapping the self_exe_id in 7
days.  Even my slower timing is in the uptime of a typical server.
Which means self_exec_id is simply a speed bump today, and if exec
gets noticably faster self_exec_id won't even be a speed bump.

Extending self_exec_id to 64bits introduces a problem on 32bit
architectures where reading self_exec_id is no longer atomic and can
take two read instructions.  Which means that is is possible to hit
a window where the read value of exec_id does not match the written
value.  So with very lucky timing after this change this still
remains expoiltable.

I have updated the update of exec_id on exec to use WRITE_ONCE
and the read of exec_id in do_notify_parent to use READ_ONCE
to make it clear that there is no locking between these two
locations.

Link: https://lore.kernel.org/kernel-hardening/20200324215049.GA3710@pi3.com.pl
Fixes: 2.3.23pre2
Cc: stable@vger.kernel.org
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
[bwh: Backported to 3.16:
 - Use ACCESS_ONCE()
 - Adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 fs/exec.c             | 2 +-
 include/linux/sched.h | 4 ++--
 kernel/signal.c       | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1182,7 +1182,7 @@ void setup_new_exec(struct linux_binprm
 
 	/* An exec changes our domain. We are no longer part of the thread
 	   group */
-	current->self_exec_id++;
+	ACCESS_ONCE(current->self_exec_id) = current->self_exec_id + 1;
 	flush_signal_handlers(current, 0);
 }
 EXPORT_SYMBOL(setup_new_exec);
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1427,8 +1427,8 @@ struct task_struct {
 	struct seccomp seccomp;
 
 /* Thread group tracking */
-   	u32 parent_exec_id;
-   	u32 self_exec_id;
+	u64 parent_exec_id;
+	u64 self_exec_id;
 /* Protection of (de-)allocation: mm, files, fs, tty, keyrings, mems_allowed,
  * mempolicy */
 	spinlock_t alloc_lock;
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1679,7 +1679,7 @@ bool do_notify_parent(struct task_struct
 		 * This is only possible if parent == real_parent.
 		 * Check if it has changed security domain.
 		 */
-		if (tsk->parent_exec_id != tsk->parent->self_exec_id)
+		if (tsk->parent_exec_id != ACCESS_ONCE(tsk->parent->self_exec_id))
 			sig = SIGCHLD;
 	}
 


^ permalink raw reply	[relevance 11%]

* [PATCH 3.16 61/61] fs/binfmt_elf.c: allocate initialized memory in fill_thread_core_info()
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (59 preceding siblings ...)
  2020-06-09 18:04 11% ` [PATCH 3.16 60/61] random: always use batched entropy for get_random_u{32,64} Ben Hutchings
@ 2020-06-09 18:04 12% ` Ben Hutchings
  2020-06-10 19:08  6% ` [PATCH 3.16 00/61] 3.16.85-rc1 review Guenter Roeck
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Al Viro, Linus Torvalds, Alexey Dobriyan,
	Kees Cook, Alexander Potapenko, sam

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Alexander Potapenko <glider@google.com>

commit 1d605416fb7175e1adf094251466caa52093b413 upstream.

KMSAN reported uninitialized data being written to disk when dumping
core.  As a result, several kilobytes of kmalloc memory may be written
to the core file and then read by a non-privileged user.

Reported-by: sam <sunhaoyl@outlook.com>
Signed-off-by: Alexander Potapenko <glider@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Acked-by: Kees Cook <keescook@chromium.org>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Alexey Dobriyan <adobriyan@gmail.com>
Link: http://lkml.kernel.org/r/20200419100848.63472-1-glider@google.com
Link: https://github.com/google/kmsan/issues/76
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 fs/binfmt_elf.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -1575,7 +1575,7 @@ static int fill_thread_core_info(struct
 		    (!regset->active || regset->active(t->task, regset) > 0)) {
 			int ret;
 			size_t size = regset->n * regset->size;
-			void *data = kmalloc(size, GFP_KERNEL);
+			void *data = kzalloc(size, GFP_KERNEL);
 			if (unlikely(!data))
 				return 0;
 			ret = regset->get(t->task, regset,


^ permalink raw reply	[relevance 12%]

* [PATCH 3.16 49/61] ext4: protect journal inode's blocks using block_validity
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (47 preceding siblings ...)
  2020-06-09 18:04 13% ` [PATCH 3.16 48/61] ext4: Make checks for metadata_csum feature safer Ben Hutchings
@ 2020-06-09 18:04 11% ` Ben Hutchings
  2020-06-09 18:04  9% ` [PATCH 3.16 50/61] ext4: unsigned int compared against zero Ben Hutchings
                   ` (12 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable; +Cc: akpm, Denis Kirjanov, Theodore Ts'o, stable

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Theodore Ts'o <tytso@mit.edu>

commit 345c0dbf3a30872d9b204db96b5857cd00808cae upstream.

Add the blocks which belong to the journal inode to block_validity's
system zone so attempts to deallocate or overwrite the journal due a
corrupted file system where the journal blocks are also claimed by
another inode.

Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=202879
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Cc: stable@kernel.org
[bwh: Backported to 3.16:
 - Use EXT4_HAS_COMPAT_FEATURE()
 - Use EIO instead of EFSCORRUPTED]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
--- a/fs/ext4/block_validity.c
+++ b/fs/ext4/block_validity.c
@@ -137,6 +137,48 @@ static void debug_print_tree(struct ext4
 	printk("\n");
 }
 
+static int ext4_protect_reserved_inode(struct super_block *sb, u32 ino)
+{
+	struct inode *inode;
+	struct ext4_sb_info *sbi = EXT4_SB(sb);
+	struct ext4_map_blocks map;
+	u32 i = 0, err = 0, num, n;
+
+	if ((ino < EXT4_ROOT_INO) ||
+	    (ino > le32_to_cpu(sbi->s_es->s_inodes_count)))
+		return -EINVAL;
+	inode = ext4_iget(sb, ino, EXT4_IGET_SPECIAL);
+	if (IS_ERR(inode))
+		return PTR_ERR(inode);
+	num = (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
+	while (i < num) {
+		map.m_lblk = i;
+		map.m_len = num - i;
+		n = ext4_map_blocks(NULL, inode, &map, 0);
+		if (n < 0) {
+			err = n;
+			break;
+		}
+		if (n == 0) {
+			i++;
+		} else {
+			if (!ext4_data_block_valid(sbi, map.m_pblk, n)) {
+				ext4_error(sb, "blocks %llu-%llu from inode %u "
+					   "overlap system zone", map.m_pblk,
+					   map.m_pblk + map.m_len - 1, ino);
+				err = -EIO;
+				break;
+			}
+			err = add_system_zone(sbi, map.m_pblk, n);
+			if (err < 0)
+				break;
+			i += n;
+		}
+	}
+	iput(inode);
+	return err;
+}
+
 int ext4_setup_system_zone(struct super_block *sb)
 {
 	ext4_group_t ngroups = ext4_get_groups_count(sb);
@@ -171,6 +213,13 @@ int ext4_setup_system_zone(struct super_
 		if (ret)
 			return ret;
 	}
+	if (EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL) &&
+	    sbi->s_es->s_journal_inum) {
+		ret = ext4_protect_reserved_inode(sb,
+				le32_to_cpu(sbi->s_es->s_journal_inum));
+		if (ret)
+			return ret;
+	}
 
 	if (test_opt(sb, DEBUG))
 		debug_print_tree(EXT4_SB(sb));
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -411,6 +411,11 @@ static int __check_block_validity(struct
 				unsigned int line,
 				struct ext4_map_blocks *map)
 {
+	if (EXT4_HAS_COMPAT_FEATURE(inode->i_sb,
+				    EXT4_FEATURE_COMPAT_HAS_JOURNAL) &&
+	    (inode->i_ino ==
+	     le32_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_journal_inum)))
+		return 0;
 	if (!ext4_data_block_valid(EXT4_SB(inode->i_sb), map->m_pblk,
 				   map->m_len)) {
 		ext4_error_inode(inode, func, line, map->m_pblk,


^ permalink raw reply	[relevance 11%]

* [PATCH 3.16 60/61] random: always use batched entropy for get_random_u{32,64}
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (58 preceding siblings ...)
  2020-06-09 18:04  9% ` [PATCH 3.16 59/61] x86/speculation: Add Ivy Bridge to affected list Ben Hutchings
@ 2020-06-09 18:04 11% ` Ben Hutchings
  2020-06-09 18:04 12% ` [PATCH 3.16 61/61] fs/binfmt_elf.c: allocate initialized memory in fill_thread_core_info() Ben Hutchings
  2020-06-10 19:08  6% ` [PATCH 3.16 00/61] 3.16.85-rc1 review Guenter Roeck
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Greg Kroah-Hartman, Theodore Ts'o,
	Jason A. Donenfeld

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: "Jason A. Donenfeld" <Jason@zx2c4.com>

commit 69efea712f5b0489e67d07565aad5c94e09a3e52 upstream.

It turns out that RDRAND is pretty slow. Comparing these two
constructions:

  for (i = 0; i < CHACHA_BLOCK_SIZE; i += sizeof(ret))
    arch_get_random_long(&ret);

and

  long buf[CHACHA_BLOCK_SIZE / sizeof(long)];
  extract_crng((u8 *)buf);

it amortizes out to 352 cycles per long for the top one and 107 cycles
per long for the bottom one, on Coffee Lake Refresh, Intel Core i9-9880H.

And importantly, the top one has the drawback of not benefiting from the
real rng, whereas the bottom one has all the nice benefits of using our
own chacha rng. As get_random_u{32,64} gets used in more places (perhaps
beyond what it was originally intended for when it was introduced as
get_random_{int,long} back in the md5 monstrosity era), it seems like it
might be a good thing to strengthen its posture a tiny bit. Doing this
should only be stronger and not any weaker because that pool is already
initialized with a bunch of rdrand data (when available). This way, we
get the benefits of the hardware rng as well as our own rng.

Another benefit of this is that we no longer hit pitfalls of the recent
stream of AMD bugs in RDRAND. One often used code pattern for various
things is:

  do {
  	val = get_random_u32();
  } while (hash_table_contains_key(val));

That recent AMD bug rendered that pattern useless, whereas we're really
very certain that chacha20 output will give pretty distributed numbers,
no matter what.

So, this simplification seems better both from a security perspective
and from a performance perspective.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Link: https://lore.kernel.org/r/20200221201037.30231-1-Jason@zx2c4.com
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
[bwh: Backported to 3.16: Only get_random_int() exists here]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/char/random.c | 6 ------
 1 file changed, 6 deletions(-)

--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1700,9 +1700,6 @@ unsigned int get_random_int(void)
 	__u32 *hash;
 	unsigned int ret;
 
-	if (arch_get_random_int(&ret))
-		return ret;
-
 	hash = get_cpu_var(get_random_int_hash);
 
 	hash[0] += current->pid + jiffies + random_get_entropy();


^ permalink raw reply	[relevance 11%]

* [PATCH 3.16 38/61] scsi: sg: close race condition in sg_remove_sfp_usercontext()
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (36 preceding siblings ...)
  2020-06-09 18:04  8% ` [PATCH 3.16 37/61] scsi: sg: check for valid direction before starting the request Ben Hutchings
@ 2020-06-09 18:04  8% ` Ben Hutchings
  2020-06-09 18:04  9% ` [PATCH 3.16 39/61] scsi: sg: fix SG_DXFER_FROM_DEV transfers Ben Hutchings
                   ` (23 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Christoph Hellwig, Johannes Thumshirn,
	Martin K. Petersen, Greg Kroah-Hartman, Sasha Levin,
	Hannes Reinecke, Hannes Reinecke

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Hannes Reinecke <hare@suse.de>

commit 97d27b0dd015e980ade63fda111fd1353276e28b upstream.

sg_remove_sfp_usercontext() is clearing any sg requests, but needs to
take 'rq_list_lock' when modifying the list.

Reported-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Hannes Reinecke <hare@suse.com>
Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Tested-by: Johannes Thumshirn <jthumshirn@suse.de>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Sasha Levin <alexander.levin@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/scsi/sg.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -561,6 +561,7 @@ sg_read(struct file *filp, char __user *
 	} else
 		count = (old_hdr->result == 0) ? 0 : -EIO;
 	sg_finish_rem_req(srp);
+	sg_remove_request(sfp, srp);
 	retval = count;
 free_old_hdr:
 	kfree(old_hdr);
@@ -601,6 +602,7 @@ sg_new_read(Sg_fd * sfp, char __user *bu
 	}
 err_out:
 	err2 = sg_finish_rem_req(srp);
+	sg_remove_request(sfp, srp);
 	return err ? : err2 ? : count;
 }
 
@@ -835,6 +837,7 @@ sg_common_write(Sg_fd * sfp, Sg_request
 	if (k) {
 		SCSI_LOG_TIMEOUT(1, printk("sg_common_write: start_req err=%d\n", k));
 		sg_finish_rem_req(srp);
+		sg_remove_request(sfp, srp);
 		return k;	/* probably out of space --> ENOMEM */
 	}
 	if (atomic_read(&sdp->detaching)) {
@@ -844,6 +847,7 @@ sg_common_write(Sg_fd * sfp, Sg_request
 		}
 
 		sg_finish_rem_req(srp);
+		sg_remove_request(sfp, srp);
 		return -ENODEV;
 	}
 
@@ -1367,6 +1371,7 @@ sg_rq_end_io_usercontext(struct work_str
 	struct sg_fd *sfp = srp->parentfp;
 
 	sg_finish_rem_req(srp);
+	sg_remove_request(sfp, srp);
 	kref_put(&sfp->f_ref, sg_remove_sfp);
 }
 
@@ -1876,8 +1881,6 @@ sg_finish_rem_req(Sg_request *srp)
 	else
 		sg_remove_scat(req_schp);
 
-	sg_remove_request(sfp, srp);
-
 	return ret;
 }
 
@@ -2211,12 +2214,17 @@ sg_remove_sfp_usercontext(struct work_st
 	struct sg_fd *sfp = container_of(work, struct sg_fd, ew.work);
 	struct sg_device *sdp = sfp->parentdp;
 	Sg_request *srp;
+	unsigned long iflags;
 
 	/* Cleanup any responses which were never read(). */
+	write_lock_irqsave(&sfp->rq_list_lock, iflags);
 	while (!list_empty(&sfp->rq_list)) {
 		srp = list_first_entry(&sfp->rq_list, Sg_request, entry);
 		sg_finish_rem_req(srp);
+		list_del(&srp->entry);
+		srp->parentfp = NULL;
 	}
+	write_unlock_irqrestore(&sfp->rq_list_lock, iflags);
 
 	if (sfp->reserve.bufflen > 0) {
 		SCSI_LOG_TIMEOUT(6,


^ permalink raw reply	[relevance 8%]

* [PATCH 3.16 57/61] x86/speculation: Add Special Register Buffer Data Sampling (SRBDS) mitigation
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (55 preceding siblings ...)
  2020-06-09 18:04  8% ` [PATCH 3.16 56/61] x86/cpu: Add 'table' argument to cpu_matches() Ben Hutchings
@ 2020-06-09 18:04  7% ` Ben Hutchings
  2020-06-09 18:04  6% ` [PATCH 3.16 58/61] x86/speculation: Add SRBDS vulnerability and mitigation documentation Ben Hutchings
                   ` (4 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Josh Poimboeuf, Neelima Krishnan,
	Thomas Gleixner, Mark Gross, Pawan Gupta, Tony Luck,
	Borislav Petkov

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Mark Gross <mgross@linux.intel.com>

commit 7e5b3c267d256822407a22fdce6afdf9cd13f9fb upstream.

SRBDS is an MDS-like speculative side channel that can leak bits from the
random number generator (RNG) across cores and threads. New microcode
serializes the processor access during the execution of RDRAND and
RDSEED. This ensures that the shared buffer is overwritten before it is
released for reuse.

While it is present on all affected CPU models, the microcode mitigation
is not needed on models that enumerate ARCH_CAPABILITIES[MDS_NO] in the
cases where TSX is not supported or has been disabled with TSX_CTRL.

The mitigation is activated by default on affected processors and it
increases latency for RDRAND and RDSEED instructions. Among other
effects this will reduce throughput from /dev/urandom.

* Enable administrator to configure the mitigation off when desired using
  either mitigations=off or srbds=off.

* Export vulnerability status via sysfs

* Rename file-scoped macros to apply for non-whitelist table initializations.

 [ bp: Massage,
   - s/VULNBL_INTEL_STEPPING/VULNBL_INTEL_STEPPINGS/g,
   - do not read arch cap MSR a second time in tsx_fused_off() - just pass it in,
   - flip check in cpu_set_bug_bits() to save an indentation level,
   - reflow comments.
   jpoimboe: s/Mitigated/Mitigation/ in user-visible strings
   tglx: Dropped the fused off magic for now
 ]

Signed-off-by: Mark Gross <mgross@linux.intel.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Tony Luck <tony.luck@intel.com>
Reviewed-by: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
Reviewed-by: Josh Poimboeuf <jpoimboe@redhat.com>
Tested-by: Neelima Krishnan <neelima.krishnan@intel.com>
[bwh: Backported to 3.16:
 - CPU feature words and bugs are numbered differently
 - Adjust filename for <asm/msr-index.h>]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 .../ABI/testing/sysfs-devices-system-cpu      |   1 +
 Documentation/kernel-parameters.txt           |  20 ++++
 arch/x86/include/asm/cpufeatures.h            |   2 +
 arch/x86/include/uapi/asm/msr-index.h         |   4 +
 arch/x86/kernel/cpu/bugs.c                    | 106 ++++++++++++++++++
 arch/x86/kernel/cpu/common.c                  |  31 +++++
 arch/x86/kernel/cpu/cpu.h                     |   1 +
 drivers/base/cpu.c                            |   8 ++
 8 files changed, 173 insertions(+)

--- a/Documentation/ABI/testing/sysfs-devices-system-cpu
+++ b/Documentation/ABI/testing/sysfs-devices-system-cpu
@@ -232,6 +232,7 @@ What:		/sys/devices/system/cpu/vulnerabi
 		/sys/devices/system/cpu/vulnerabilities/spec_store_bypass
 		/sys/devices/system/cpu/vulnerabilities/l1tf
 		/sys/devices/system/cpu/vulnerabilities/mds
+		/sys/devices/system/cpu/vulnerabilities/srbds
 		/sys/devices/system/cpu/vulnerabilities/tsx_async_abort
 		/sys/devices/system/cpu/vulnerabilities/itlb_multihit
 Date:		January 2018
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -3356,6 +3356,26 @@ bytes respectively. Such letter suffixes
 	spia_pedr=
 	spia_peddr=
 
+	srbds=		[X86,INTEL]
+			Control the Special Register Buffer Data Sampling
+			(SRBDS) mitigation.
+
+			Certain CPUs are vulnerable to an MDS-like
+			exploit which can leak bits from the random
+			number generator.
+
+			By default, this issue is mitigated by
+			microcode.  However, the microcode fix can cause
+			the RDRAND and RDSEED instructions to become
+			much slower.  Among other effects, this will
+			result in reduced throughput from /dev/urandom.
+
+			The microcode mitigation can be disabled with
+			the following option:
+
+			off:    Disable mitigation and remove
+				performance impact to RDRAND and RDSEED
+
 	stack_guard_gap=	[MM]
 			override the default stack gap protection. The value
 			is in page units and it defines how many pages prior
--- a/arch/x86/include/asm/cpufeatures.h
+++ b/arch/x86/include/asm/cpufeatures.h
@@ -247,6 +247,7 @@
 #define X86_FEATURE_AVX512CD	( 9*32+28) /* AVX-512 Conflict Detection */
 
 /* Intel-defined CPU features, CPUID level 0x00000007:0 (EDX), word 10 */
+#define X86_FEATURE_SRBDS_CTRL		(10*32+ 9) /* "" SRBDS mitigation MSR available */
 #define X86_FEATURE_MD_CLEAR		(10*32+10) /* VERW clears CPU buffers */
 #define X86_FEATURE_SPEC_CTRL		(10*32+26) /* "" Speculation Control (IBRS + IBPB) */
 #define X86_FEATURE_INTEL_STIBP		(10*32+27) /* "" Single Thread Indirect Branch Predictors */
@@ -281,5 +282,6 @@
 #define X86_BUG_SWAPGS		X86_BUG(12) /* CPU is affected by speculation through SWAPGS */
 #define X86_BUG_TAA		X86_BUG(13) /* CPU is affected by TSX Async Abort(TAA) */
 #define X86_BUG_ITLB_MULTIHIT	X86_BUG(14) /* CPU may incur MCE during certain page attribute changes */
+#define X86_BUG_SRBDS		X86_BUG(15) /* CPU may leak RNG bits if not mitigated */
 
 #endif /* _ASM_X86_CPUFEATURES_H */
--- a/arch/x86/include/uapi/asm/msr-index.h
+++ b/arch/x86/include/uapi/asm/msr-index.h
@@ -90,6 +90,10 @@
 #define TSX_CTRL_RTM_DISABLE		(1UL << 0) /* Disable RTM feature */
 #define TSX_CTRL_CPUID_CLEAR		(1UL << 1) /* Disable TSX enumeration */
 
+/* SRBDS support */
+#define MSR_IA32_MCU_OPT_CTRL		0x00000123
+#define RNGDS_MITG_DIS			BIT(0)
+
 #define MSR_IA32_SYSENTER_CS		0x00000174
 #define MSR_IA32_SYSENTER_ESP		0x00000175
 #define MSR_IA32_SYSENTER_EIP		0x00000176
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -38,6 +38,7 @@ static void __init ssb_select_mitigation
 static void __init l1tf_select_mitigation(void);
 static void __init mds_select_mitigation(void);
 static void __init taa_select_mitigation(void);
+static void __init srbds_select_mitigation(void);
 
 /* The base value of the SPEC_CTRL MSR that always has to be preserved. */
 u64 x86_spec_ctrl_base;
@@ -159,6 +160,7 @@ void __init check_bugs(void)
 	l1tf_select_mitigation();
 	mds_select_mitigation();
 	taa_select_mitigation();
+	srbds_select_mitigation();
 
 	arch_smt_update();
 
@@ -417,6 +419,97 @@ static int __init tsx_async_abort_parse_
 early_param("tsx_async_abort", tsx_async_abort_parse_cmdline);
 
 #undef pr_fmt
+#define pr_fmt(fmt)	"SRBDS: " fmt
+
+enum srbds_mitigations {
+	SRBDS_MITIGATION_OFF,
+	SRBDS_MITIGATION_UCODE_NEEDED,
+	SRBDS_MITIGATION_FULL,
+	SRBDS_MITIGATION_TSX_OFF,
+	SRBDS_MITIGATION_HYPERVISOR,
+};
+
+static enum srbds_mitigations srbds_mitigation = SRBDS_MITIGATION_FULL;
+
+static const char * const srbds_strings[] = {
+	[SRBDS_MITIGATION_OFF]		= "Vulnerable",
+	[SRBDS_MITIGATION_UCODE_NEEDED]	= "Vulnerable: No microcode",
+	[SRBDS_MITIGATION_FULL]		= "Mitigation: Microcode",
+	[SRBDS_MITIGATION_TSX_OFF]	= "Mitigation: TSX disabled",
+	[SRBDS_MITIGATION_HYPERVISOR]	= "Unknown: Dependent on hypervisor status",
+};
+
+static bool srbds_off;
+
+void update_srbds_msr(void)
+{
+	u64 mcu_ctrl;
+
+	if (!boot_cpu_has_bug(X86_BUG_SRBDS))
+		return;
+
+	if (boot_cpu_has(X86_FEATURE_HYPERVISOR))
+		return;
+
+	if (srbds_mitigation == SRBDS_MITIGATION_UCODE_NEEDED)
+		return;
+
+	rdmsrl(MSR_IA32_MCU_OPT_CTRL, mcu_ctrl);
+
+	switch (srbds_mitigation) {
+	case SRBDS_MITIGATION_OFF:
+	case SRBDS_MITIGATION_TSX_OFF:
+		mcu_ctrl |= RNGDS_MITG_DIS;
+		break;
+	case SRBDS_MITIGATION_FULL:
+		mcu_ctrl &= ~RNGDS_MITG_DIS;
+		break;
+	default:
+		break;
+	}
+
+	wrmsrl(MSR_IA32_MCU_OPT_CTRL, mcu_ctrl);
+}
+
+static void __init srbds_select_mitigation(void)
+{
+	u64 ia32_cap;
+
+	if (!boot_cpu_has_bug(X86_BUG_SRBDS))
+		return;
+
+	/*
+	 * Check to see if this is one of the MDS_NO systems supporting
+	 * TSX that are only exposed to SRBDS when TSX is enabled.
+	 */
+	ia32_cap = x86_read_arch_cap_msr();
+	if ((ia32_cap & ARCH_CAP_MDS_NO) && !boot_cpu_has(X86_FEATURE_RTM))
+		srbds_mitigation = SRBDS_MITIGATION_TSX_OFF;
+	else if (boot_cpu_has(X86_FEATURE_HYPERVISOR))
+		srbds_mitigation = SRBDS_MITIGATION_HYPERVISOR;
+	else if (!boot_cpu_has(X86_FEATURE_SRBDS_CTRL))
+		srbds_mitigation = SRBDS_MITIGATION_UCODE_NEEDED;
+	else if (cpu_mitigations_off() || srbds_off)
+		srbds_mitigation = SRBDS_MITIGATION_OFF;
+
+	update_srbds_msr();
+	pr_info("%s\n", srbds_strings[srbds_mitigation]);
+}
+
+static int __init srbds_parse_cmdline(char *str)
+{
+	if (!str)
+		return -EINVAL;
+
+	if (!boot_cpu_has_bug(X86_BUG_SRBDS))
+		return 0;
+
+	srbds_off = !strcmp(str, "off");
+	return 0;
+}
+early_param("srbds", srbds_parse_cmdline);
+
+#undef pr_fmt
 #define pr_fmt(fmt)     "Spectre V1 : " fmt
 
 enum spectre_v1_mitigation {
@@ -1422,6 +1515,11 @@ static char *ibpb_state(void)
 	return "";
 }
 
+static ssize_t srbds_show_state(char *buf)
+{
+	return sprintf(buf, "%s\n", srbds_strings[srbds_mitigation]);
+}
+
 static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr,
 			       char *buf, unsigned int bug)
 {
@@ -1463,6 +1561,9 @@ static ssize_t cpu_show_common(struct de
 	case X86_BUG_ITLB_MULTIHIT:
 		return itlb_multihit_show_state(buf);
 
+	case X86_BUG_SRBDS:
+		return srbds_show_state(buf);
+
 	default:
 		break;
 	}
@@ -1509,4 +1610,9 @@ ssize_t cpu_show_itlb_multihit(struct de
 {
 	return cpu_show_common(dev, attr, buf, X86_BUG_ITLB_MULTIHIT);
 }
+
+ssize_t cpu_show_srbds(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	return cpu_show_common(dev, attr, buf, X86_BUG_SRBDS);
+}
 #endif
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -872,6 +872,27 @@ static const __initconst struct x86_cpu_
 	{}
 };
 
+#define VULNBL_INTEL_STEPPINGS(model, steppings, issues)		   \
+	X86_MATCH_VENDOR_FAM_MODEL_STEPPINGS_FEATURE(INTEL, 6,		   \
+					    INTEL_FAM6_##model, steppings, \
+					    X86_FEATURE_ANY, issues)
+
+#define SRBDS		BIT(0)
+
+static const struct x86_cpu_id cpu_vuln_blacklist[] __initconst = {
+	VULNBL_INTEL_STEPPINGS(IVYBRIDGE,	X86_STEPPING_ANY,		SRBDS),
+	VULNBL_INTEL_STEPPINGS(HASWELL_CORE,	X86_STEPPING_ANY,		SRBDS),
+	VULNBL_INTEL_STEPPINGS(HASWELL_ULT,	X86_STEPPING_ANY,		SRBDS),
+	VULNBL_INTEL_STEPPINGS(HASWELL_GT3E,	X86_STEPPING_ANY,		SRBDS),
+	VULNBL_INTEL_STEPPINGS(BROADWELL_GT3E,	X86_STEPPING_ANY,		SRBDS),
+	VULNBL_INTEL_STEPPINGS(BROADWELL_CORE,	X86_STEPPING_ANY,		SRBDS),
+	VULNBL_INTEL_STEPPINGS(SKYLAKE_MOBILE,	X86_STEPPING_ANY,		SRBDS),
+	VULNBL_INTEL_STEPPINGS(SKYLAKE_DESKTOP,	X86_STEPPING_ANY,		SRBDS),
+	VULNBL_INTEL_STEPPINGS(KABYLAKE_MOBILE,	X86_STEPPINGS(0x0, 0xC),	SRBDS),
+	VULNBL_INTEL_STEPPINGS(KABYLAKE_DESKTOP,X86_STEPPINGS(0x0, 0xD),	SRBDS),
+	{}
+};
+
 static bool __init cpu_matches(const struct x86_cpu_id *table, unsigned long which)
 {
 	const struct x86_cpu_id *m = x86_match_cpu(table);
@@ -937,6 +958,15 @@ static void __init cpu_set_bug_bits(stru
 	     (ia32_cap & ARCH_CAP_TSX_CTRL_MSR)))
 		setup_force_cpu_bug(X86_BUG_TAA);
 
+	/*
+	 * SRBDS affects CPUs which support RDRAND or RDSEED and are listed
+	 * in the vulnerability blacklist.
+	 */
+	if ((cpu_has(c, X86_FEATURE_RDRAND) ||
+	     cpu_has(c, X86_FEATURE_RDSEED)) &&
+	    cpu_matches(cpu_vuln_blacklist, SRBDS))
+		    setup_force_cpu_bug(X86_BUG_SRBDS);
+
 	if (cpu_matches(cpu_vuln_whitelist, NO_MELTDOWN))
 		return;
 
@@ -1283,6 +1313,7 @@ void identify_secondary_cpu(struct cpuin
 #endif
 	mtrr_ap_init();
 	x86_spec_ctrl_setup_ap();
+	update_srbds_msr();
 }
 
 struct msr_range {
--- a/arch/x86/kernel/cpu/cpu.h
+++ b/arch/x86/kernel/cpu/cpu.h
@@ -63,6 +63,7 @@ extern void get_cpu_cap(struct cpuinfo_x
 extern void cpu_detect_cache_sizes(struct cpuinfo_x86 *c);
  
 extern void x86_spec_ctrl_setup_ap(void);
+extern void update_srbds_msr(void);
 
 extern u64 x86_read_arch_cap_msr(void);
 
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -469,6 +469,12 @@ ssize_t __weak cpu_show_itlb_multihit(st
 	return sprintf(buf, "Not affected\n");
 }
 
+ssize_t __weak cpu_show_srbds(struct device *dev,
+			      struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "Not affected\n");
+}
+
 static DEVICE_ATTR(meltdown, 0444, cpu_show_meltdown, NULL);
 static DEVICE_ATTR(spectre_v1, 0444, cpu_show_spectre_v1, NULL);
 static DEVICE_ATTR(spectre_v2, 0444, cpu_show_spectre_v2, NULL);
@@ -477,6 +483,7 @@ static DEVICE_ATTR(l1tf, 0444, cpu_show_
 static DEVICE_ATTR(mds, 0444, cpu_show_mds, NULL);
 static DEVICE_ATTR(tsx_async_abort, 0444, cpu_show_tsx_async_abort, NULL);
 static DEVICE_ATTR(itlb_multihit, 0444, cpu_show_itlb_multihit, NULL);
+static DEVICE_ATTR(srbds, 0444, cpu_show_srbds, NULL);
 
 static struct attribute *cpu_root_vulnerabilities_attrs[] = {
 	&dev_attr_meltdown.attr,
@@ -487,6 +494,7 @@ static struct attribute *cpu_root_vulner
 	&dev_attr_mds.attr,
 	&dev_attr_tsx_async_abort.attr,
 	&dev_attr_itlb_multihit.attr,
+	&dev_attr_srbds.attr,
 	NULL
 };
 


^ permalink raw reply	[relevance 7%]

* [PATCH 3.16 26/61] scsi: sg: protect accesses to 'reserved' page array
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (24 preceding siblings ...)
  2020-06-09 18:04 10% ` [PATCH 3.16 25/61] scsi: sg: Change next_cmd_len handling to mirror upstream Ben Hutchings
@ 2020-06-09 18:04  7% ` Ben Hutchings
  2020-06-09 18:04  9% ` [PATCH 3.16 27/61] scsi: sg: reset 'res_in_use' after unlinking reserved array Ben Hutchings
                   ` (35 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Christoph Hellwig, Todd Poynor,
	Martin K. Petersen, Johannes Thumshirn, Hannes Reinecke,
	Greg Kroah-Hartman, Hannes Reinecke

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Hannes Reinecke <hare@suse.de>

commit 1bc0eb0446158cc76562176b80623aa119afee5b upstream.

The 'reserved' page array is used as a short-cut for mapping data,
saving us to allocate pages per request. However, the 'reserved' array
is only capable of holding one request, so this patch introduces a mutex
for protect 'sg_fd' against concurrent accesses.

Signed-off-by: Hannes Reinecke <hare@suse.com>
Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Tested-by: Johannes Thumshirn <jthumshirn@suse.de>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

[toddpoynor@google.com: backport to 3.18-4.9,  fixup for bad ioctl
SG_SET_FORCE_LOW_DMA code removed in later versions and not modified by
the original patch.]

Signed-off-by: Hannes Reinecke <hare@suse.com>
Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Tested-by: Johannes Thumshirn <jthumshirn@suse.de>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Todd Poynor <toddpoynor@google.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/scsi/sg.c | 47 ++++++++++++++++++++++++++---------------------
 1 file changed, 26 insertions(+), 21 deletions(-)

--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -150,6 +150,7 @@ typedef struct sg_fd {		/* holds the sta
 	struct sg_device *parentdp;	/* owning device */
 	wait_queue_head_t read_wait;	/* queue read until command done */
 	rwlock_t rq_list_lock;	/* protect access to list in req_arr */
+	struct mutex f_mutex;	/* protect against changes in this fd */
 	int timeout;		/* defaults to SG_DEFAULT_TIMEOUT      */
 	int timeout_user;	/* defaults to SG_DEFAULT_TIMEOUT_USER */
 	Sg_scatter_hold reserve;	/* buffer held for this file descriptor */
@@ -163,6 +164,7 @@ typedef struct sg_fd {		/* holds the sta
 	unsigned char next_cmd_len; /* 0: automatic, >0: use on next write() */
 	char keep_orphan;	/* 0 -> drop orphan (def), 1 -> keep for read() */
 	char mmap_called;	/* 0 -> mmap() never called on this fd */
+	char res_in_use;	/* 1 -> 'reserve' array in use */
 	struct kref f_ref;
 	struct execute_work ew;
 } Sg_fd;
@@ -206,7 +208,6 @@ static void sg_remove_sfp(struct kref *)
 static Sg_request *sg_get_rq_mark(Sg_fd * sfp, int pack_id);
 static Sg_request *sg_add_request(Sg_fd * sfp);
 static int sg_remove_request(Sg_fd * sfp, Sg_request * srp);
-static int sg_res_in_use(Sg_fd * sfp);
 static Sg_device *sg_get_dev(int dev);
 static void sg_device_destroy(struct kref *kref);
 
@@ -652,6 +653,7 @@ sg_write(struct file *filp, const char _
 	}
 	buf += SZ_SG_HEADER;
 	__get_user(opcode, buf);
+	mutex_lock(&sfp->f_mutex);
 	if (sfp->next_cmd_len > 0) {
 		cmd_size = sfp->next_cmd_len;
 		sfp->next_cmd_len = 0;	/* reset so only this write() effected */
@@ -660,6 +662,7 @@ sg_write(struct file *filp, const char _
 		if ((opcode >= 0xc0) && old_hdr.twelve_byte)
 			cmd_size = 12;
 	}
+	mutex_unlock(&sfp->f_mutex);
 	SCSI_LOG_TIMEOUT(4, printk(
 		"sg_write:   scsi opcode=0x%02x, cmd_size=%d\n", (int) opcode, cmd_size));
 /* Determine buffer size.  */
@@ -758,7 +761,7 @@ sg_new_write(Sg_fd *sfp, struct file *fi
 			sg_remove_request(sfp, srp);
 			return -EINVAL;	/* either MMAP_IO or DIRECT_IO (not both) */
 		}
-		if (sg_res_in_use(sfp)) {
+		if (sfp->res_in_use) {
 			sg_remove_request(sfp, srp);
 			return -EBUSY;	/* reserve buffer already being used */
 		}
@@ -933,7 +936,7 @@ sg_ioctl(struct file *filp, unsigned int
 			return result;
 		if (val) {
 			sfp->low_dma = 1;
-			if ((0 == sfp->low_dma) && (0 == sg_res_in_use(sfp))) {
+			if ((0 == sfp->low_dma) && !sfp->res_in_use) {
 				val = (int) sfp->reserve.bufflen;
 				sg_remove_scat(&sfp->reserve);
 				sg_build_reserve(sfp, val);
@@ -1008,12 +1011,18 @@ sg_ioctl(struct file *filp, unsigned int
                         return -EINVAL;
 		val = min_t(int, val,
 			    max_sectors_bytes(sdp->device->request_queue));
+		mutex_lock(&sfp->f_mutex);
 		if (val != sfp->reserve.bufflen) {
-			if (sg_res_in_use(sfp) || sfp->mmap_called)
+			if (sfp->mmap_called ||
+			    sfp->res_in_use) {
+				mutex_unlock(&sfp->f_mutex);
 				return -EBUSY;
+			}
+
 			sg_remove_scat(&sfp->reserve);
 			sg_build_reserve(sfp, val);
 		}
+		mutex_unlock(&sfp->f_mutex);
 		return 0;
 	case SG_GET_RESERVED_SIZE:
 		val = min_t(int, sfp->reserve.bufflen,
@@ -1752,13 +1761,22 @@ sg_start_req(Sg_request *srp, unsigned c
 		md = &map_data;
 
 	if (md) {
-		if (!sg_res_in_use(sfp) && dxfer_len <= rsv_schp->bufflen)
+		mutex_lock(&sfp->f_mutex);
+		if (dxfer_len <= rsv_schp->bufflen &&
+		    !sfp->res_in_use) {
+			sfp->res_in_use = 1;
 			sg_link_reserve(sfp, srp, dxfer_len);
-		else {
+		} else if ((hp->flags & SG_FLAG_MMAP_IO) && sfp->res_in_use) {
+			mutex_unlock(&sfp->f_mutex);
+			return -EBUSY;
+		} else {
 			res = sg_build_indirect(req_schp, sfp, dxfer_len);
-			if (res)
+			if (res) {
+				mutex_unlock(&sfp->f_mutex);
 				return res;
+			}
 		}
+		mutex_unlock(&sfp->f_mutex);
 
 		md->pages = req_schp->pages;
 		md->page_order = req_schp->page_order;
@@ -2155,6 +2173,7 @@ sg_add_sfp(Sg_device * sdp, int dev)
 	rwlock_init(&sfp->rq_list_lock);
 
 	kref_init(&sfp->f_ref);
+	mutex_init(&sfp->f_mutex);
 	sfp->timeout = SG_DEFAULT_TIMEOUT;
 	sfp->timeout_user = SG_DEFAULT_TIMEOUT_USER;
 	sfp->force_packid = SG_DEF_FORCE_PACK_ID;
@@ -2229,20 +2248,6 @@ sg_remove_sfp(struct kref *kref)
 	schedule_work(&sfp->ew.work);
 }
 
-static int
-sg_res_in_use(Sg_fd * sfp)
-{
-	const Sg_request *srp;
-	unsigned long iflags;
-
-	read_lock_irqsave(&sfp->rq_list_lock, iflags);
-	for (srp = sfp->headrp; srp; srp = srp->nextrp)
-		if (srp->res_used)
-			break;
-	read_unlock_irqrestore(&sfp->rq_list_lock, iflags);
-	return srp ? 1 : 0;
-}
-
 #ifdef CONFIG_SCSI_PROC_FS
 static int
 sg_idr_max_id(int id, void *p, void *data)


^ permalink raw reply	[relevance 7%]

* [PATCH 3.16 39/61] scsi: sg: fix SG_DXFER_FROM_DEV transfers
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (37 preceding siblings ...)
  2020-06-09 18:04  8% ` [PATCH 3.16 38/61] scsi: sg: close race condition in sg_remove_sfp_usercontext() Ben Hutchings
@ 2020-06-09 18:04  9% ` Ben Hutchings
  2020-06-09 18:04  9% ` [PATCH 3.16 40/61] scsi: sg: fix static checker warning in sg_is_valid_dxfer Ben Hutchings
                   ` (22 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Hannes Reinecke, Greg Kroah-Hartman,
	Douglas Gilbert, Cristian Crinteanu, Chris Clayton,
	Martin K. Petersen, Johannes Thumshirn

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Johannes Thumshirn <jthumshirn@suse.de>

commit 68c59fcea1f2c6a54c62aa896cc623c1b5bc9b47 upstream.

SG_DXFER_FROM_DEV transfers do not necessarily have a dxferp as we set
it to NULL for the old sg_io read/write interface, but must have a
length bigger than 0. This fixes a regression introduced by commit
28676d869bbb ("scsi: sg: check for valid direction before starting the
request")

Signed-off-by: Johannes Thumshirn <jthumshirn@suse.de>
Fixes: 28676d869bbb ("scsi: sg: check for valid direction before starting the request")
Reported-by: Chris Clayton <chris2553@googlemail.com>
Tested-by: Chris Clayton <chris2553@googlemail.com>
Cc: Douglas Gilbert <dgilbert@interlog.com>
Reviewed-by: Hannes Reinecke <hare@suse.com>
Tested-by: Chris Clayton <chris2553@googlemail.com>
Acked-by: Douglas Gilbert <dgilbert@interlog.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Cc: Cristian Crinteanu <crinteanu.cristian@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/scsi/sg.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -795,8 +795,11 @@ static bool sg_is_valid_dxfer(sg_io_hdr_
 		if (hp->dxferp || hp->dxfer_len > 0)
 			return false;
 		return true;
-	case SG_DXFER_TO_DEV:
 	case SG_DXFER_FROM_DEV:
+		if (hp->dxfer_len < 0)
+			return false;
+		return true;
+	case SG_DXFER_TO_DEV:
 	case SG_DXFER_TO_FROM_DEV:
 		if (!hp->dxferp || hp->dxfer_len == 0)
 			return false;


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 37/61] scsi: sg: check for valid direction before starting the request
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (35 preceding siblings ...)
  2020-06-09 18:04 10% ` [PATCH 3.16 36/61] scsi: sg: disable SET_FORCE_LOW_DMA Ben Hutchings
@ 2020-06-09 18:04  8% ` Ben Hutchings
  2020-06-09 18:04  8% ` [PATCH 3.16 38/61] scsi: sg: close race condition in sg_remove_sfp_usercontext() Ben Hutchings
                   ` (24 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Hannes Reinecke, Greg Kroah-Hartman,
	Sasha Levin, Martin K. Petersen, Dmitry Vyukov,
	Johannes Thumshirn, Christoph Hellwig

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Johannes Thumshirn <jthumshirn@suse.de>

commit 28676d869bbb5257b5f14c0c95ad3af3a7019dd5 upstream.

Check for a valid direction before starting the request, otherwise we
risk running into an assertion in the scsi midlayer checking for valid
requests.

[mkp: fixed typo]

Signed-off-by: Johannes Thumshirn <jthumshirn@suse.de>
Link: http://www.spinics.net/lists/linux-scsi/msg104400.html
Reported-by: Dmitry Vyukov <dvyukov@google.com>
Signed-off-by: Hannes Reinecke <hare@suse.com>
Tested-by: Johannes Thumshirn <jthumshirn@suse.de>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Sasha Levin <alexander.levin@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/scsi/sg.c | 46 ++++++++++++++++++++++++++++++++++------------
 1 file changed, 34 insertions(+), 12 deletions(-)

--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -701,18 +701,14 @@ sg_write(struct file *filp, const char _
 	 * is a non-zero input_size, so emit a warning.
 	 */
 	if (hp->dxfer_direction == SG_DXFER_TO_FROM_DEV) {
-		static char cmd[TASK_COMM_LEN];
-		if (strcmp(current->comm, cmd)) {
-			printk_ratelimited(KERN_WARNING
-					   "sg_write: data in/out %d/%d bytes "
-					   "for SCSI command 0x%x-- guessing "
-					   "data in;\n   program %s not setting "
-					   "count and/or reply_len properly\n",
-					   old_hdr.reply_len - (int)SZ_SG_HEADER,
-					   input_size, (unsigned int) cmnd[0],
-					   current->comm);
-			strcpy(cmd, current->comm);
-		}
+		printk_ratelimited(KERN_WARNING
+				   "sg_write: data in/out %d/%d bytes "
+				   "for SCSI command 0x%x-- guessing "
+				   "data in;\n   program %s not setting "
+				   "count and/or reply_len properly\n",
+				   old_hdr.reply_len - (int)SZ_SG_HEADER,
+				   input_size, (unsigned int) cmnd[0],
+				   current->comm);
 	}
 	k = sg_common_write(sfp, srp, cmnd, sfp->timeout, blocking);
 	return (k < 0) ? k : count;
@@ -790,6 +786,29 @@ sg_new_write(Sg_fd *sfp, struct file *fi
 	return count;
 }
 
+static bool sg_is_valid_dxfer(sg_io_hdr_t *hp)
+{
+	switch (hp->dxfer_direction) {
+	case SG_DXFER_NONE:
+		if (hp->dxferp || hp->dxfer_len > 0)
+			return false;
+		return true;
+	case SG_DXFER_TO_DEV:
+	case SG_DXFER_FROM_DEV:
+	case SG_DXFER_TO_FROM_DEV:
+		if (!hp->dxferp || hp->dxfer_len == 0)
+			return false;
+		return true;
+	case SG_DXFER_UNKNOWN:
+		if ((!hp->dxferp && hp->dxfer_len) ||
+		    (hp->dxferp && hp->dxfer_len == 0))
+			return false;
+		return true;
+	default:
+		return false;
+	}
+}
+
 static int
 sg_common_write(Sg_fd * sfp, Sg_request * srp,
 		unsigned char *cmnd, int timeout, int blocking)
@@ -809,6 +828,9 @@ sg_common_write(Sg_fd * sfp, Sg_request
 	SCSI_LOG_TIMEOUT(4, printk("sg_common_write:  scsi opcode=0x%02x, cmd_size=%d\n",
 			  (int) cmnd[0], (int) hp->cmd_len));
 
+	if (!sg_is_valid_dxfer(hp))
+		return -EINVAL;
+
 	k = sg_start_req(srp, cmnd);
 	if (k) {
 		SCSI_LOG_TIMEOUT(1, printk("sg_common_write: start_req err=%d\n", k));


^ permalink raw reply	[relevance 8%]

* [PATCH 3.16 30/61] scsi: sg: remove 'save_scat_len'
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (28 preceding siblings ...)
  2020-06-09 18:04  9% ` [PATCH 3.16 29/61] scsi: sg: recheck MMAP_IO request length with lock held Ben Hutchings
@ 2020-06-09 18:04  9% ` Ben Hutchings
  2020-06-09 18:04  6% ` [PATCH 3.16 31/61] scsi: sg: use standard lists for sg_requests Ben Hutchings
                   ` (31 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Hannes Reinecke, Greg Kroah-Hartman,
	Hannes Reinecke, Johannes Thumshirn, Martin K. Petersen,
	Christoph Hellwig

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Hannes Reinecke <hare@suse.de>

commit 136e57bf43dc4babbfb8783abbf707d483cacbe3 upstream.

Unused.

Signed-off-by: Hannes Reinecke <hare@suse.com>
Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Tested-by: Johannes Thumshirn <jthumshirn@suse.de>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/scsi/sg.c | 2 --
 1 file changed, 2 deletions(-)

--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -154,7 +154,6 @@ typedef struct sg_fd {		/* holds the sta
 	int timeout;		/* defaults to SG_DEFAULT_TIMEOUT      */
 	int timeout_user;	/* defaults to SG_DEFAULT_TIMEOUT_USER */
 	Sg_scatter_hold reserve;	/* buffer held for this file descriptor */
-	unsigned save_scat_len;	/* original length of trunc. scat. element */
 	Sg_request *headrp;	/* head of request slist, NULL->empty */
 	struct fasync_struct *async_qp;	/* used by asynchronous notification */
 	Sg_request req_arr[SG_MAX_QUEUE];	/* used as singly-linked list */
@@ -2069,7 +2068,6 @@ sg_unlink_reserve(Sg_fd * sfp, Sg_reques
 	req_schp->pages = NULL;
 	req_schp->page_order = 0;
 	req_schp->sglist_len = 0;
-	sfp->save_scat_len = 0;
 	srp->res_used = 0;
 	/* Called without mutex lock to avoid deadlock */
 	sfp->res_in_use = 0;


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 31/61] scsi: sg: use standard lists for sg_requests
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (29 preceding siblings ...)
  2020-06-09 18:04  9% ` [PATCH 3.16 30/61] scsi: sg: remove 'save_scat_len' Ben Hutchings
@ 2020-06-09 18:04  6% ` Ben Hutchings
  2020-06-09 18:04  9% ` [PATCH 3.16 32/61] scsi: sg: off by one in sg_ioctl() Ben Hutchings
                   ` (30 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Christoph Hellwig, Martin K. Petersen,
	Johannes Thumshirn, Hannes Reinecke, Greg Kroah-Hartman,
	Hannes Reinecke

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Hannes Reinecke <hare@suse.de>

commit 109bade9c625c89bb5ea753aaa1a0a97e6fbb548 upstream.

'Sg_request' is using a private list implementation; convert it to
standard lists.

Signed-off-by: Hannes Reinecke <hare@suse.com>
Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Tested-by: Johannes Thumshirn <jthumshirn@suse.de>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/scsi/sg.c | 147 +++++++++++++++++++---------------------------
 1 file changed, 61 insertions(+), 86 deletions(-)

--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -130,7 +130,7 @@ struct sg_device;		/* forward declaratio
 struct sg_fd;
 
 typedef struct sg_request {	/* SG_MAX_QUEUE requests outstanding per file */
-	struct sg_request *nextrp;	/* NULL -> tail request (slist) */
+	struct list_head entry;	/* list entry */
 	struct sg_fd *parentfp;	/* NULL -> not in use */
 	Sg_scatter_hold data;	/* hold buffer, perhaps scatter list */
 	sg_io_hdr_t header;	/* scsi command+info, see <scsi/sg.h> */
@@ -154,7 +154,7 @@ typedef struct sg_fd {		/* holds the sta
 	int timeout;		/* defaults to SG_DEFAULT_TIMEOUT      */
 	int timeout_user;	/* defaults to SG_DEFAULT_TIMEOUT_USER */
 	Sg_scatter_hold reserve;	/* buffer held for this file descriptor */
-	Sg_request *headrp;	/* head of request slist, NULL->empty */
+	struct list_head rq_list; /* head of request list */
 	struct fasync_struct *async_qp;	/* used by asynchronous notification */
 	Sg_request req_arr[SG_MAX_QUEUE];	/* used as singly-linked list */
 	char low_dma;		/* as in parent but possibly overridden to 1 */
@@ -981,7 +981,7 @@ sg_ioctl(struct file *filp, unsigned int
 		if (!access_ok(VERIFY_WRITE, ip, sizeof (int)))
 			return -EFAULT;
 		read_lock_irqsave(&sfp->rq_list_lock, iflags);
-		for (srp = sfp->headrp; srp; srp = srp->nextrp) {
+		list_for_each_entry(srp, &sfp->rq_list, entry) {
 			if ((1 == srp->done) && (!srp->sg_io_owned)) {
 				read_unlock_irqrestore(&sfp->rq_list_lock,
 						       iflags);
@@ -994,7 +994,8 @@ sg_ioctl(struct file *filp, unsigned int
 		return 0;
 	case SG_GET_NUM_WAITING:
 		read_lock_irqsave(&sfp->rq_list_lock, iflags);
-		for (val = 0, srp = sfp->headrp; srp; srp = srp->nextrp) {
+		val = 0;
+		list_for_each_entry(srp, &sfp->rq_list, entry) {
 			if ((1 == srp->done) && (!srp->sg_io_owned))
 				++val;
 		}
@@ -1069,35 +1070,33 @@ sg_ioctl(struct file *filp, unsigned int
 			if (!rinfo)
 				return -ENOMEM;
 			read_lock_irqsave(&sfp->rq_list_lock, iflags);
-			for (srp = sfp->headrp, val = 0; val < SG_MAX_QUEUE;
-			     ++val, srp = srp ? srp->nextrp : srp) {
+			val = 0;
+			list_for_each_entry(srp, &sfp->rq_list, entry) {
+				if (val > SG_MAX_QUEUE)
+					break;
 				memset(&rinfo[val], 0, SZ_SG_REQ_INFO);
-				if (srp) {
-					rinfo[val].req_state = srp->done + 1;
-					rinfo[val].problem =
-					    srp->header.masked_status & 
-					    srp->header.host_status & 
-					    srp->header.driver_status;
-					if (srp->done)
-						rinfo[val].duration =
-							srp->header.duration;
-					else {
-						ms = jiffies_to_msecs(jiffies);
-						rinfo[val].duration =
-						    (ms > srp->header.duration) ?
-						    (ms - srp->header.duration) : 0;
-					}
-					rinfo[val].orphan = srp->orphan;
-					rinfo[val].sg_io_owned =
-							srp->sg_io_owned;
-					rinfo[val].pack_id =
-							srp->header.pack_id;
-					rinfo[val].usr_ptr =
-							srp->header.usr_ptr;
+				rinfo[val].req_state = srp->done + 1;
+				rinfo[val].problem =
+					srp->header.masked_status &
+					srp->header.host_status &
+					srp->header.driver_status;
+				if (srp->done)
+					rinfo[val].duration =
+						srp->header.duration;
+				else {
+					ms = jiffies_to_msecs(jiffies);
+					rinfo[val].duration =
+						(ms > srp->header.duration) ?
+						(ms - srp->header.duration) : 0;
 				}
+				rinfo[val].orphan = srp->orphan;
+				rinfo[val].sg_io_owned = srp->sg_io_owned;
+				rinfo[val].pack_id = srp->header.pack_id;
+				rinfo[val].usr_ptr = srp->header.usr_ptr;
+				val++;
 			}
 			read_unlock_irqrestore(&sfp->rq_list_lock, iflags);
-			result = __copy_to_user(p, rinfo, 
+			result = __copy_to_user(p, rinfo,
 						SZ_SG_REQ_INFO * SG_MAX_QUEUE);
 			result = result ? -EFAULT : 0;
 			kfree(rinfo);
@@ -1229,7 +1228,7 @@ sg_poll(struct file *filp, poll_table *
 		return POLLERR;
 	poll_wait(filp, &sfp->read_wait, wait);
 	read_lock_irqsave(&sfp->rq_list_lock, iflags);
-	for (srp = sfp->headrp; srp; srp = srp->nextrp) {
+	list_for_each_entry(srp, &sfp->rq_list, entry) {
 		/* if any read waiting, flag it */
 		if ((0 == res) && (1 == srp->done) && (!srp->sg_io_owned))
 			res = POLLIN | POLLRDNORM;
@@ -2080,7 +2079,7 @@ sg_get_rq_mark(Sg_fd * sfp, int pack_id)
 	unsigned long iflags;
 
 	write_lock_irqsave(&sfp->rq_list_lock, iflags);
-	for (resp = sfp->headrp; resp; resp = resp->nextrp) {
+	list_for_each_entry(resp, &sfp->rq_list, entry) {
 		/* look for requests that are ready + not SG_IO owned */
 		if ((1 == resp->done) && (!resp->sg_io_owned) &&
 		    ((-1 == pack_id) || (resp->header.pack_id == pack_id))) {
@@ -2098,70 +2097,45 @@ sg_add_request(Sg_fd * sfp)
 {
 	int k;
 	unsigned long iflags;
-	Sg_request *resp;
 	Sg_request *rp = sfp->req_arr;
 
 	write_lock_irqsave(&sfp->rq_list_lock, iflags);
-	resp = sfp->headrp;
-	if (!resp) {
-		memset(rp, 0, sizeof (Sg_request));
-		rp->parentfp = sfp;
-		resp = rp;
-		sfp->headrp = resp;
-	} else {
-		if (0 == sfp->cmd_q)
-			resp = NULL;	/* command queuing disallowed */
-		else {
-			for (k = 0; k < SG_MAX_QUEUE; ++k, ++rp) {
-				if (!rp->parentfp)
-					break;
-			}
-			if (k < SG_MAX_QUEUE) {
-				memset(rp, 0, sizeof (Sg_request));
-				rp->parentfp = sfp;
-				while (resp->nextrp)
-					resp = resp->nextrp;
-				resp->nextrp = rp;
-				resp = rp;
-			} else
-				resp = NULL;
+	if (!list_empty(&sfp->rq_list)) {
+		if (!sfp->cmd_q)
+			goto out_unlock;
+
+		for (k = 0; k < SG_MAX_QUEUE; ++k, ++rp) {
+			if (!rp->parentfp)
+				break;
 		}
+		if (k >= SG_MAX_QUEUE)
+			goto out_unlock;
 	}
-	if (resp) {
-		resp->nextrp = NULL;
-		resp->header.duration = jiffies_to_msecs(jiffies);
-	}
+	memset(rp, 0, sizeof (Sg_request));
+	rp->parentfp = sfp;
+	rp->header.duration = jiffies_to_msecs(jiffies);
+	list_add_tail(&rp->entry, &sfp->rq_list);
 	write_unlock_irqrestore(&sfp->rq_list_lock, iflags);
-	return resp;
+	return rp;
+out_unlock:
+	write_unlock_irqrestore(&sfp->rq_list_lock, iflags);
+	return NULL;
 }
 
 /* Return of 1 for found; 0 for not found */
 static int
 sg_remove_request(Sg_fd * sfp, Sg_request * srp)
 {
-	Sg_request *prev_rp;
-	Sg_request *rp;
 	unsigned long iflags;
 	int res = 0;
 
-	if ((!sfp) || (!srp) || (!sfp->headrp))
+	if (!sfp || !srp || list_empty(&sfp->rq_list))
 		return res;
 	write_lock_irqsave(&sfp->rq_list_lock, iflags);
-	prev_rp = sfp->headrp;
-	if (srp == prev_rp) {
-		sfp->headrp = prev_rp->nextrp;
-		prev_rp->parentfp = NULL;
+	if (!list_empty(&srp->entry)) {
+		list_del(&srp->entry);
+		srp->parentfp = NULL;
 		res = 1;
-	} else {
-		while ((rp = prev_rp->nextrp)) {
-			if (srp == rp) {
-				prev_rp->nextrp = rp->nextrp;
-				rp->parentfp = NULL;
-				res = 1;
-				break;
-			}
-			prev_rp = rp;
-		}
 	}
 	write_unlock_irqrestore(&sfp->rq_list_lock, iflags);
 	return res;
@@ -2180,7 +2154,7 @@ sg_add_sfp(Sg_device * sdp, int dev)
 
 	init_waitqueue_head(&sfp->read_wait);
 	rwlock_init(&sfp->rq_list_lock);
-
+	INIT_LIST_HEAD(&sfp->rq_list);
 	kref_init(&sfp->f_ref);
 	mutex_init(&sfp->f_mutex);
 	sfp->timeout = SG_DEFAULT_TIMEOUT;
@@ -2218,10 +2192,13 @@ sg_remove_sfp_usercontext(struct work_st
 {
 	struct sg_fd *sfp = container_of(work, struct sg_fd, ew.work);
 	struct sg_device *sdp = sfp->parentdp;
+	Sg_request *srp;
 
 	/* Cleanup any responses which were never read(). */
-	while (sfp->headrp)
-		sg_finish_rem_req(sfp->headrp);
+	while (!list_empty(&sfp->rq_list)) {
+		srp = list_first_entry(&sfp->rq_list, Sg_request, entry);
+		sg_finish_rem_req(srp);
+	}
 
 	if (sfp->reserve.bufflen > 0) {
 		SCSI_LOG_TIMEOUT(6,
@@ -2626,7 +2603,7 @@ static int sg_proc_seq_show_devstrs(stru
 /* must be called while holding sg_index_lock */
 static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp)
 {
-	int k, m, new_interface, blen, usg;
+	int k, new_interface, blen, usg;
 	Sg_request *srp;
 	Sg_fd *fp;
 	const sg_io_hdr_t *hp;
@@ -2646,13 +2623,11 @@ static void sg_proc_debug_helper(struct
 		seq_printf(s, "   cmd_q=%d f_packid=%d k_orphan=%d closed=0\n",
 			   (int) fp->cmd_q, (int) fp->force_packid,
 			   (int) fp->keep_orphan);
-		for (m = 0, srp = fp->headrp;
-				srp != NULL;
-				++m, srp = srp->nextrp) {
+		list_for_each_entry(srp, &fp->rq_list, entry) {
 			hp = &srp->header;
 			new_interface = (hp->interface_id == '\0') ? 0 : 1;
 			if (srp->res_used) {
-				if (new_interface && 
+				if (new_interface &&
 				    (SG_FLAG_MMAP_IO & hp->flags))
 					cp = "     mmap>> ";
 				else
@@ -2683,7 +2658,7 @@ static void sg_proc_debug_helper(struct
 			seq_printf(s, "ms sgat=%d op=0x%02x\n", usg,
 				   (int) srp->data.cmd_opcode);
 		}
-		if (0 == m)
+		if (list_empty(&fp->rq_list))
 			seq_puts(s, "     No requests active\n");
 		read_unlock(&fp->rq_list_lock);
 	}


^ permalink raw reply	[relevance 6%]

* [PATCH 3.16 54/61] x86/cpu: Rename cpu_data.x86_mask to cpu_data.x86_stepping
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (52 preceding siblings ...)
  2020-06-09 18:04  9% ` [PATCH 3.16 53/61] ext4: add cond_resched() to ext4_protect_reserved_inode Ben Hutchings
@ 2020-06-09 18:04  5% ` Ben Hutchings
  2020-06-09 18:04  7% ` [PATCH 3.16 55/61] x86/cpu: Add a steppings field to struct x86_cpu_id Ben Hutchings
                   ` (7 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, tony.luck, bp, Linus Torvalds,
	Greg Kroah-Hartman, Jia Zhang, Peter Zijlstra, Ingo Molnar,
	Thomas Gleixner

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Jia Zhang <qianyue.zj@alibaba-inc.com>

commit b399151cb48db30ad1e0e93dd40d68c6d007b637 upstream.

x86_mask is a confusing name which is hard to associate with the
processor's stepping.

Additionally, correct an indent issue in lib/cpu.c.

Signed-off-by: Jia Zhang <qianyue.zj@alibaba-inc.com>
[ Updated it to more recent kernels. ]
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: bp@alien8.de
Cc: tony.luck@intel.com
Link: http://lkml.kernel.org/r/1514771530-70829-1-git-send-email-qianyue.zj@alibaba-inc.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
[bwh: Backported to 3.16:
 - Drop changes in arch/x86/lib/cpu.c
 - Adjust filenames, context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 arch/x86/include/asm/acpi.h                |  2 +-
 arch/x86/include/asm/processor.h           |  2 +-
 arch/x86/kernel/amd_nb.c                   |  2 +-
 arch/x86/kernel/asm-offsets_32.c           |  2 +-
 arch/x86/kernel/cpu/amd.c                  | 28 +++++++++++-----------
 arch/x86/kernel/cpu/centaur.c              |  4 ++--
 arch/x86/kernel/cpu/common.c               |  8 +++----
 arch/x86/kernel/cpu/cyrix.c                |  2 +-
 arch/x86/kernel/cpu/intel.c                | 18 +++++++-------
 arch/x86/kernel/cpu/microcode/intel.c      |  4 ++--
 arch/x86/kernel/cpu/mtrr/generic.c         |  2 +-
 arch/x86/kernel/cpu/mtrr/main.c            |  4 ++--
 arch/x86/kernel/cpu/perf_event_intel.c     |  2 +-
 arch/x86/kernel/cpu/perf_event_intel_lbr.c |  2 +-
 arch/x86/kernel/cpu/perf_event_p6.c        |  2 +-
 arch/x86/kernel/cpu/proc.c                 |  4 ++--
 arch/x86/kernel/head_32.S                  |  4 ++--
 arch/x86/kernel/mpparse.c                  |  2 +-
 drivers/char/hw_random/via-rng.c           |  2 +-
 drivers/cpufreq/acpi-cpufreq.c             |  2 +-
 drivers/cpufreq/longhaul.c                 |  6 ++---
 drivers/cpufreq/p4-clockmod.c              |  2 +-
 drivers/cpufreq/powernow-k7.c              |  2 +-
 drivers/cpufreq/speedstep-centrino.c       |  4 ++--
 drivers/cpufreq/speedstep-lib.c            |  6 ++---
 drivers/crypto/padlock-aes.c               |  2 +-
 drivers/edac/amd64_edac.c                  |  2 +-
 drivers/edac/mce_amd.c                     |  2 +-
 drivers/hwmon/coretemp.c                   |  6 ++---
 drivers/hwmon/hwmon-vid.c                  |  2 +-
 drivers/hwmon/k10temp.c                    |  2 +-
 drivers/hwmon/k8temp.c                     |  2 +-
 drivers/video/fbdev/geode/video_gx.c       |  2 +-
 33 files changed, 69 insertions(+), 69 deletions(-)

--- a/arch/x86/include/asm/acpi.h
+++ b/arch/x86/include/asm/acpi.h
@@ -87,7 +87,7 @@ static inline unsigned int acpi_processo
 	if (boot_cpu_data.x86 == 0x0F &&
 	    boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
 	    boot_cpu_data.x86_model <= 0x05 &&
-	    boot_cpu_data.x86_mask < 0x0A)
+	    boot_cpu_data.x86_stepping < 0x0A)
 		return 1;
 	else if (amd_e400_c1e_detected)
 		return 1;
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -82,7 +82,7 @@ struct cpuinfo_x86 {
 	__u8			x86;		/* CPU family */
 	__u8			x86_vendor;	/* CPU vendor */
 	__u8			x86_model;
-	__u8			x86_mask;
+	__u8			x86_stepping;
 #ifdef CONFIG_X86_32
 	char			wp_works_ok;	/* It doesn't on 386's */
 
--- a/arch/x86/kernel/amd_nb.c
+++ b/arch/x86/kernel/amd_nb.c
@@ -116,7 +116,7 @@ int amd_cache_northbridges(void)
 	if (boot_cpu_data.x86 == 0x10 &&
 	    boot_cpu_data.x86_model >= 0x8 &&
 	    (boot_cpu_data.x86_model > 0x9 ||
-	     boot_cpu_data.x86_mask >= 0x1))
+	     boot_cpu_data.x86_stepping >= 0x1))
 		amd_northbridges.flags |= AMD_NB_L3_INDEX_DISABLE;
 
 	if (boot_cpu_data.x86 == 0x15)
--- a/arch/x86/kernel/asm-offsets_32.c
+++ b/arch/x86/kernel/asm-offsets_32.c
@@ -27,7 +27,7 @@ void foo(void)
 	OFFSET(CPUINFO_x86, cpuinfo_x86, x86);
 	OFFSET(CPUINFO_x86_vendor, cpuinfo_x86, x86_vendor);
 	OFFSET(CPUINFO_x86_model, cpuinfo_x86, x86_model);
-	OFFSET(CPUINFO_x86_mask, cpuinfo_x86, x86_mask);
+	OFFSET(CPUINFO_x86_stepping, cpuinfo_x86, x86_stepping);
 	OFFSET(CPUINFO_cpuid_level, cpuinfo_x86, cpuid_level);
 	OFFSET(CPUINFO_x86_capability, cpuinfo_x86, x86_capability);
 	OFFSET(CPUINFO_x86_vendor_id, cpuinfo_x86, x86_vendor_id);
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -101,7 +101,7 @@ static void init_amd_k6(struct cpuinfo_x
 		return;
 	}
 
-	if (c->x86_model == 6 && c->x86_mask == 1) {
+	if (c->x86_model == 6 && c->x86_stepping == 1) {
 		const int K6_BUG_LOOP = 1000000;
 		int n;
 		void (*f_vide)(void);
@@ -131,7 +131,7 @@ static void init_amd_k6(struct cpuinfo_x
 
 	/* K6 with old style WHCR */
 	if (c->x86_model < 8 ||
-	   (c->x86_model == 8 && c->x86_mask < 8)) {
+	   (c->x86_model == 8 && c->x86_stepping < 8)) {
 		/* We can only write allocate on the low 508Mb */
 		if (mbytes > 508)
 			mbytes = 508;
@@ -150,7 +150,7 @@ static void init_amd_k6(struct cpuinfo_x
 		return;
 	}
 
-	if ((c->x86_model == 8 && c->x86_mask > 7) ||
+	if ((c->x86_model == 8 && c->x86_stepping > 7) ||
 	     c->x86_model == 9 || c->x86_model == 13) {
 		/* The more serious chips .. */
 
@@ -190,12 +190,12 @@ static void amd_k7_smp_check(struct cpui
 	 * but they are not certified as MP capable.
 	 */
 	/* Athlon 660/661 is valid. */
-	if ((c->x86_model == 6) && ((c->x86_mask == 0) ||
-	    (c->x86_mask == 1)))
+	if ((c->x86_model == 6) && ((c->x86_stepping == 0) ||
+	    (c->x86_stepping == 1)))
 		return;
 
 	/* Duron 670 is valid */
-	if ((c->x86_model == 7) && (c->x86_mask == 0))
+	if ((c->x86_model == 7) && (c->x86_stepping == 0))
 		return;
 
 	/*
@@ -205,8 +205,8 @@ static void amd_k7_smp_check(struct cpui
 	 * See http://www.heise.de/newsticker/data/jow-18.10.01-000 for
 	 * more.
 	 */
-	if (((c->x86_model == 6) && (c->x86_mask >= 2)) ||
-	    ((c->x86_model == 7) && (c->x86_mask >= 1)) ||
+	if (((c->x86_model == 6) && (c->x86_stepping >= 2)) ||
+	    ((c->x86_model == 7) && (c->x86_stepping >= 1)) ||
 	     (c->x86_model > 7))
 		if (cpu_has_mp)
 			return;
@@ -244,7 +244,7 @@ static void init_amd_k7(struct cpuinfo_x
 	 * are more robust with CLK_CTL set to 200xxxxx instead of 600xxxxx
 	 * As per AMD technical note 27212 0.2
 	 */
-	if ((c->x86_model == 8 && c->x86_mask >= 1) || (c->x86_model > 8)) {
+	if ((c->x86_model == 8 && c->x86_stepping >= 1) || (c->x86_model > 8)) {
 		rdmsr(MSR_K7_CLK_CTL, l, h);
 		if ((l & 0xfff00000) != 0x20000000) {
 			printk(KERN_INFO
@@ -514,7 +514,7 @@ static void early_init_amd(struct cpuinf
 	/*  Set MTRR capability flag if appropriate */
 	if (c->x86 == 5)
 		if (c->x86_model == 13 || c->x86_model == 9 ||
-		    (c->x86_model == 8 && c->x86_mask >= 8))
+		    (c->x86_model == 8 && c->x86_stepping >= 8))
 			set_cpu_cap(c, X86_FEATURE_K6_MTRR);
 #endif
 #if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_PCI)
@@ -561,7 +561,7 @@ static void init_amd_zn(struct cpuinfo_x
 	 * Fix erratum 1076: CPB feature bit not being set in CPUID. It affects
 	 * all up to and including B1.
 	 */
-	if (c->x86_model <= 1 && c->x86_mask <= 1)
+	if (c->x86_model <= 1 && c->x86_stepping <= 1)
 		set_cpu_cap(c, X86_FEATURE_CPB);
 }
 
@@ -810,11 +810,11 @@ static unsigned int amd_size_cache(struc
 	/* AMD errata T13 (order #21922) */
 	if ((c->x86 == 6)) {
 		/* Duron Rev A0 */
-		if (c->x86_model == 3 && c->x86_mask == 0)
+		if (c->x86_model == 3 && c->x86_stepping == 0)
 			size = 64;
 		/* Tbird rev A1/A2 */
 		if (c->x86_model == 4 &&
-			(c->x86_mask == 0 || c->x86_mask == 1))
+			(c->x86_stepping == 0 || c->x86_stepping == 1))
 			size = 256;
 	}
 	return size;
@@ -951,7 +951,7 @@ static bool cpu_has_amd_erratum(struct c
 	}
 
 	/* OSVW unavailable or ID unknown, match family-model-stepping range */
-	ms = (cpu->x86_model << 4) | cpu->x86_mask;
+	ms = (cpu->x86_model << 4) | cpu->x86_stepping;
 	while ((range = *erratum++))
 		if ((cpu->x86 == AMD_MODEL_RANGE_FAMILY(range)) &&
 		    (ms >= AMD_MODEL_RANGE_START(range)) &&
--- a/arch/x86/kernel/cpu/centaur.c
+++ b/arch/x86/kernel/cpu/centaur.c
@@ -134,7 +134,7 @@ static void init_centaur(struct cpuinfo_
 			clear_cpu_cap(c, X86_FEATURE_TSC);
 			break;
 		case 8:
-			switch (c->x86_mask) {
+			switch (c->x86_stepping) {
 			default:
 			name = "2";
 				break;
@@ -209,7 +209,7 @@ centaur_size_cache(struct cpuinfo_x86 *c
 	 *  - Note, it seems this may only be in engineering samples.
 	 */
 	if ((c->x86 == 6) && (c->x86_model == 9) &&
-				(c->x86_mask == 1) && (size == 65))
+				(c->x86_stepping == 1) && (size == 65))
 		size -= 1;
 	return size;
 }
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -659,7 +659,7 @@ void cpu_detect(struct cpuinfo_x86 *c)
 		cpuid(0x00000001, &tfms, &misc, &junk, &cap0);
 		c->x86 = (tfms >> 8) & 0xf;
 		c->x86_model = (tfms >> 4) & 0xf;
-		c->x86_mask = tfms & 0xf;
+		c->x86_stepping = tfms & 0xf;
 
 		if (c->x86 == 0xf)
 			c->x86 += (tfms >> 20) & 0xff;
@@ -1095,7 +1095,7 @@ static void identify_cpu(struct cpuinfo_
 	c->loops_per_jiffy = loops_per_jiffy;
 	c->x86_cache_size = 0;
 	c->x86_vendor = X86_VENDOR_UNKNOWN;
-	c->x86_model = c->x86_mask = 0;	/* So far unknown... */
+	c->x86_model = c->x86_stepping = 0;	/* So far unknown... */
 	c->x86_vendor_id[0] = '\0'; /* Unset */
 	c->x86_model_id[0] = '\0';  /* Unset */
 	c->x86_max_cores = 1;
@@ -1356,8 +1356,8 @@ void print_cpu_info(struct cpuinfo_x86 *
 
 	printk(KERN_CONT " (fam: %02x, model: %02x", c->x86, c->x86_model);
 
-	if (c->x86_mask || c->cpuid_level >= 0)
-		printk(KERN_CONT ", stepping: %02x)\n", c->x86_mask);
+	if (c->x86_stepping || c->cpuid_level >= 0)
+		printk(KERN_CONT ", stepping: %02x)\n", c->x86_stepping);
 	else
 		printk(KERN_CONT ")\n");
 
--- a/arch/x86/kernel/cpu/cyrix.c
+++ b/arch/x86/kernel/cpu/cyrix.c
@@ -212,7 +212,7 @@ static void init_cyrix(struct cpuinfo_x8
 
 	/* common case step number/rev -- exceptions handled below */
 	c->x86_model = (dir1 >> 4) + 1;
-	c->x86_mask = dir1 & 0xf;
+	c->x86_stepping = dir1 & 0xf;
 
 	/* Now cook; the original recipe is by Channing Corn, from Cyrix.
 	 * We do the same thing for each generation: we work out
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -81,7 +81,7 @@ static bool bad_spectre_microcode(struct
 
 	for (i = 0; i < ARRAY_SIZE(spectre_bad_microcodes); i++) {
 		if (c->x86_model == spectre_bad_microcodes[i].model &&
-		    c->x86_mask == spectre_bad_microcodes[i].stepping)
+		    c->x86_stepping == spectre_bad_microcodes[i].stepping)
 			return (c->microcode <= spectre_bad_microcodes[i].microcode);
 	}
 	return false;
@@ -131,7 +131,7 @@ static void early_init_intel(struct cpui
 	 * need the microcode to have already been loaded... so if it is
 	 * not, recommend a BIOS update and disable large pages.
 	 */
-	if (c->x86 == 6 && c->x86_model == 0x1c && c->x86_mask <= 2 &&
+	if (c->x86 == 6 && c->x86_model == 0x1c && c->x86_stepping <= 2 &&
 	    c->microcode < 0x20e) {
 		printk(KERN_WARNING "Atom PSE erratum detected, BIOS microcode update recommended\n");
 		clear_cpu_cap(c, X86_FEATURE_PSE);
@@ -147,7 +147,7 @@ static void early_init_intel(struct cpui
 
 	/* CPUID workaround for 0F33/0F34 CPU */
 	if (c->x86 == 0xF && c->x86_model == 0x3
-	    && (c->x86_mask == 0x3 || c->x86_mask == 0x4))
+	    && (c->x86_stepping == 0x3 || c->x86_stepping == 0x4))
 		c->x86_phys_bits = 36;
 
 	/*
@@ -246,7 +246,7 @@ int ppro_with_ram_bug(void)
 	if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
 	    boot_cpu_data.x86 == 6 &&
 	    boot_cpu_data.x86_model == 1 &&
-	    boot_cpu_data.x86_mask < 8) {
+	    boot_cpu_data.x86_stepping < 8) {
 		printk(KERN_INFO "Pentium Pro with Errata#50 detected. Taking evasive action.\n");
 		return 1;
 	}
@@ -263,7 +263,7 @@ static void intel_smp_check(struct cpuin
 	 * Mask B, Pentium, but not Pentium MMX
 	 */
 	if (c->x86 == 5 &&
-	    c->x86_mask >= 1 && c->x86_mask <= 4 &&
+	    c->x86_stepping >= 1 && c->x86_stepping <= 4 &&
 	    c->x86_model <= 3) {
 		/*
 		 * Remember we have B step Pentia with bugs
@@ -305,7 +305,7 @@ static void intel_workarounds(struct cpu
 	 * SEP CPUID bug: Pentium Pro reports SEP but doesn't have it until
 	 * model 3 mask 3
 	 */
-	if ((c->x86<<8 | c->x86_model<<4 | c->x86_mask) < 0x633)
+	if ((c->x86<<8 | c->x86_model<<4 | c->x86_stepping) < 0x633)
 		clear_cpu_cap(c, X86_FEATURE_SEP);
 
 	/*
@@ -323,7 +323,7 @@ static void intel_workarounds(struct cpu
 	 * P4 Xeon errata 037 workaround.
 	 * Hardware prefetcher may cause stale data to be loaded into the cache.
 	 */
-	if ((c->x86 == 15) && (c->x86_model == 1) && (c->x86_mask == 1)) {
+	if ((c->x86 == 15) && (c->x86_model == 1) && (c->x86_stepping == 1)) {
 		if (msr_set_bit(MSR_IA32_MISC_ENABLE,
 				MSR_IA32_MISC_ENABLE_PREFETCH_DISABLE_BIT)
 		    > 0) {
@@ -339,7 +339,7 @@ static void intel_workarounds(struct cpu
 	 * Specification Update").
 	 */
 	if (cpu_has_apic && (c->x86<<8 | c->x86_model<<4) == 0x520 &&
-	    (c->x86_mask < 0x6 || c->x86_mask == 0xb))
+	    (c->x86_stepping < 0x6 || c->x86_stepping == 0xb))
 		set_cpu_cap(c, X86_FEATURE_11AP);
 
 
@@ -523,7 +523,7 @@ static void init_intel(struct cpuinfo_x8
 		case 6:
 			if (l2 == 128)
 				p = "Celeron (Mendocino)";
-			else if (c->x86_mask == 0 || c->x86_mask == 5)
+			else if (c->x86_stepping == 0 || c->x86_stepping == 5)
 				p = "Celeron-A";
 			break;
 
--- a/arch/x86/kernel/cpu/microcode/intel.c
+++ b/arch/x86/kernel/cpu/microcode/intel.c
@@ -291,7 +291,7 @@ static bool is_blacklisted(unsigned int
 	 */
 	if (c->x86 == 6 &&
 	    c->x86_model == 0x4F &&
-	    c->x86_mask == 0x01 &&
+	    c->x86_stepping == 0x01 &&
 	    llc_size_per_core > 2621440 &&
 	    c->microcode < 0x0b000021) {
 		pr_err_once("Erratum BDF90: late loading with revision < 0x0b000021 (0x%x) disabled.\n", c->microcode);
@@ -314,7 +314,7 @@ static enum ucode_state request_microcod
 		return UCODE_NFOUND;
 
 	sprintf(name, "intel-ucode/%02x-%02x-%02x",
-		c->x86, c->x86_model, c->x86_mask);
+		c->x86, c->x86_model, c->x86_stepping);
 
 	if (request_firmware_direct(&firmware, name, device)) {
 		pr_debug("data file %s load failed\n", name);
--- a/arch/x86/kernel/cpu/mtrr/generic.c
+++ b/arch/x86/kernel/cpu/mtrr/generic.c
@@ -791,7 +791,7 @@ int generic_validate_add_page(unsigned l
 	 */
 	if (is_cpu(INTEL) && boot_cpu_data.x86 == 6 &&
 	    boot_cpu_data.x86_model == 1 &&
-	    boot_cpu_data.x86_mask <= 7) {
+	    boot_cpu_data.x86_stepping <= 7) {
 		if (base & ((1 << (22 - PAGE_SHIFT)) - 1)) {
 			pr_warning("mtrr: base(0x%lx000) is not 4 MiB aligned\n", base);
 			return -EINVAL;
--- a/arch/x86/kernel/cpu/mtrr/main.c
+++ b/arch/x86/kernel/cpu/mtrr/main.c
@@ -688,8 +688,8 @@ void __init mtrr_bp_init(void)
 			if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
 			    boot_cpu_data.x86 == 0xF &&
 			    boot_cpu_data.x86_model == 0x3 &&
-			    (boot_cpu_data.x86_mask == 0x3 ||
-			     boot_cpu_data.x86_mask == 0x4))
+			    (boot_cpu_data.x86_stepping == 0x3 ||
+			     boot_cpu_data.x86_stepping == 0x4))
 				phys_addr = 36;
 
 			size_or_mask = SIZE_OR_MASK_BITS(phys_addr);
--- a/arch/x86/kernel/cpu/perf_event_intel.c
+++ b/arch/x86/kernel/cpu/perf_event_intel.c
@@ -2192,7 +2192,7 @@ static int intel_snb_pebs_broken(int cpu
 		break;
 
 	case 45: /* SNB-EP */
-		switch (cpu_data(cpu).x86_mask) {
+		switch (cpu_data(cpu).x86_stepping) {
 		case 6: rev = 0x618; break;
 		case 7: rev = 0x70c; break;
 		}
--- a/arch/x86/kernel/cpu/perf_event_intel_lbr.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_lbr.c
@@ -763,7 +763,7 @@ void intel_pmu_lbr_init_atom(void)
 	 * on PMU interrupt
 	 */
 	if (boot_cpu_data.x86_model == 28
-	    && boot_cpu_data.x86_mask < 10) {
+	    && boot_cpu_data.x86_stepping < 10) {
 		pr_cont("LBR disabled due to erratum");
 		return;
 	}
--- a/arch/x86/kernel/cpu/perf_event_p6.c
+++ b/arch/x86/kernel/cpu/perf_event_p6.c
@@ -233,7 +233,7 @@ static __initconst const struct x86_pmu
 
 static __init void p6_pmu_rdpmc_quirk(void)
 {
-	if (boot_cpu_data.x86_mask < 9) {
+	if (boot_cpu_data.x86_stepping < 9) {
 		/*
 		 * PPro erratum 26; fixed in stepping 9 and above.
 		 */
--- a/arch/x86/kernel/cpu/proc.c
+++ b/arch/x86/kernel/cpu/proc.c
@@ -69,8 +69,8 @@ static int show_cpuinfo(struct seq_file
 		   c->x86_model,
 		   c->x86_model_id[0] ? c->x86_model_id : "unknown");
 
-	if (c->x86_mask || c->cpuid_level >= 0)
-		seq_printf(m, "stepping\t: %d\n", c->x86_mask);
+	if (c->x86_stepping || c->cpuid_level >= 0)
+		seq_printf(m, "stepping\t: %d\n", c->x86_stepping);
 	else
 		seq_printf(m, "stepping\t: unknown\n");
 	if (c->microcode)
--- a/arch/x86/kernel/head_32.S
+++ b/arch/x86/kernel/head_32.S
@@ -33,7 +33,7 @@
 #define X86		new_cpu_data+CPUINFO_x86
 #define X86_VENDOR	new_cpu_data+CPUINFO_x86_vendor
 #define X86_MODEL	new_cpu_data+CPUINFO_x86_model
-#define X86_MASK	new_cpu_data+CPUINFO_x86_mask
+#define X86_STEPPING	new_cpu_data+CPUINFO_x86_stepping
 #define X86_HARD_MATH	new_cpu_data+CPUINFO_hard_math
 #define X86_CPUID	new_cpu_data+CPUINFO_cpuid_level
 #define X86_CAPABILITY	new_cpu_data+CPUINFO_x86_capability
@@ -433,7 +433,7 @@ enable_paging:
 	shrb $4,%al
 	movb %al,X86_MODEL
 	andb $0x0f,%cl		# mask mask revision
-	movb %cl,X86_MASK
+	movb %cl,X86_STEPPING
 	movl %edx,X86_CAPABILITY
 
 is486:
--- a/arch/x86/kernel/mpparse.c
+++ b/arch/x86/kernel/mpparse.c
@@ -409,7 +409,7 @@ static inline void __init construct_defa
 	processor.apicver = mpc_default_type > 4 ? 0x10 : 0x01;
 	processor.cpuflag = CPU_ENABLED;
 	processor.cpufeature = (boot_cpu_data.x86 << 8) |
-	    (boot_cpu_data.x86_model << 4) | boot_cpu_data.x86_mask;
+	    (boot_cpu_data.x86_model << 4) | boot_cpu_data.x86_stepping;
 	processor.featureflag = boot_cpu_data.x86_capability[0];
 	processor.reserved[0] = 0;
 	processor.reserved[1] = 0;
--- a/drivers/char/hw_random/via-rng.c
+++ b/drivers/char/hw_random/via-rng.c
@@ -166,7 +166,7 @@ static int via_rng_init(struct hwrng *rn
 	/* Enable secondary noise source on CPUs where it is present. */
 
 	/* Nehemiah stepping 8 and higher */
-	if ((c->x86_model == 9) && (c->x86_mask > 7))
+	if ((c->x86_model == 9) && (c->x86_stepping > 7))
 		lo |= VIA_NOISESRC2;
 
 	/* Esther */
--- a/drivers/cpufreq/acpi-cpufreq.c
+++ b/drivers/cpufreq/acpi-cpufreq.c
@@ -628,7 +628,7 @@ static int acpi_cpufreq_blacklist(struct
 	if (c->x86_vendor == X86_VENDOR_INTEL) {
 		if ((c->x86 == 15) &&
 		    (c->x86_model == 6) &&
-		    (c->x86_mask == 8)) {
+		    (c->x86_stepping == 8)) {
 			printk(KERN_INFO "acpi-cpufreq: Intel(R) "
 			    "Xeon(R) 7100 Errata AL30, processors may "
 			    "lock up on frequency changes: disabling "
--- a/drivers/cpufreq/longhaul.c
+++ b/drivers/cpufreq/longhaul.c
@@ -786,7 +786,7 @@ static int longhaul_cpu_init(struct cpuf
 		break;
 
 	case 7:
-		switch (c->x86_mask) {
+		switch (c->x86_stepping) {
 		case 0:
 			longhaul_version = TYPE_LONGHAUL_V1;
 			cpu_model = CPU_SAMUEL2;
@@ -798,7 +798,7 @@ static int longhaul_cpu_init(struct cpuf
 			break;
 		case 1 ... 15:
 			longhaul_version = TYPE_LONGHAUL_V2;
-			if (c->x86_mask < 8) {
+			if (c->x86_stepping < 8) {
 				cpu_model = CPU_SAMUEL2;
 				cpuname = "C3 'Samuel 2' [C5B]";
 			} else {
@@ -825,7 +825,7 @@ static int longhaul_cpu_init(struct cpuf
 		numscales = 32;
 		memcpy(mults, nehemiah_mults, sizeof(nehemiah_mults));
 		memcpy(eblcr, nehemiah_eblcr, sizeof(nehemiah_eblcr));
-		switch (c->x86_mask) {
+		switch (c->x86_stepping) {
 		case 0 ... 1:
 			cpu_model = CPU_NEHEMIAH;
 			cpuname = "C3 'Nehemiah A' [C5XLOE]";
--- a/drivers/cpufreq/p4-clockmod.c
+++ b/drivers/cpufreq/p4-clockmod.c
@@ -176,7 +176,7 @@ static int cpufreq_p4_cpu_init(struct cp
 #endif
 
 	/* Errata workaround */
-	cpuid = (c->x86 << 8) | (c->x86_model << 4) | c->x86_mask;
+	cpuid = (c->x86 << 8) | (c->x86_model << 4) | c->x86_stepping;
 	switch (cpuid) {
 	case 0x0f07:
 	case 0x0f0a:
--- a/drivers/cpufreq/powernow-k7.c
+++ b/drivers/cpufreq/powernow-k7.c
@@ -133,7 +133,7 @@ static int check_powernow(void)
 		return 0;
 	}
 
-	if ((c->x86_model == 6) && (c->x86_mask == 0)) {
+	if ((c->x86_model == 6) && (c->x86_stepping == 0)) {
 		printk(KERN_INFO PFX "K7 660[A0] core detected, "
 				"enabling errata workarounds\n");
 		have_a0 = 1;
--- a/drivers/cpufreq/speedstep-centrino.c
+++ b/drivers/cpufreq/speedstep-centrino.c
@@ -36,7 +36,7 @@ struct cpu_id
 {
 	__u8	x86;            /* CPU family */
 	__u8	x86_model;	/* model */
-	__u8	x86_mask;	/* stepping */
+	__u8	x86_stepping;	/* stepping */
 };
 
 enum {
@@ -276,7 +276,7 @@ static int centrino_verify_cpu_id(const
 {
 	if ((c->x86 == x->x86) &&
 	    (c->x86_model == x->x86_model) &&
-	    (c->x86_mask == x->x86_mask))
+	    (c->x86_stepping == x->x86_stepping))
 		return 1;
 	return 0;
 }
--- a/drivers/cpufreq/speedstep-lib.c
+++ b/drivers/cpufreq/speedstep-lib.c
@@ -270,9 +270,9 @@ unsigned int speedstep_detect_processor(
 		ebx = cpuid_ebx(0x00000001);
 		ebx &= 0x000000FF;
 
-		pr_debug("ebx value is %x, x86_mask is %x\n", ebx, c->x86_mask);
+		pr_debug("ebx value is %x, x86_stepping is %x\n", ebx, c->x86_stepping);
 
-		switch (c->x86_mask) {
+		switch (c->x86_stepping) {
 		case 4:
 			/*
 			 * B-stepping [M-P4-M]
@@ -359,7 +359,7 @@ unsigned int speedstep_detect_processor(
 				msr_lo, msr_hi);
 		if ((msr_hi & (1<<18)) &&
 		    (relaxed_check ? 1 : (msr_hi & (3<<24)))) {
-			if (c->x86_mask == 0x01) {
+			if (c->x86_stepping == 0x01) {
 				pr_debug("early PIII version\n");
 				return SPEEDSTEP_CPU_PIII_C_EARLY;
 			} else
--- a/drivers/crypto/padlock-aes.c
+++ b/drivers/crypto/padlock-aes.c
@@ -535,7 +535,7 @@ static int __init padlock_init(void)
 
 	printk(KERN_NOTICE PFX "Using VIA PadLock ACE for AES algorithm.\n");
 
-	if (c->x86 == 6 && c->x86_model == 15 && c->x86_mask == 2) {
+	if (c->x86 == 6 && c->x86_model == 15 && c->x86_stepping == 2) {
 		ecb_fetch_blocks = MAX_ECB_FETCH_BLOCKS;
 		cbc_fetch_blocks = MAX_CBC_FETCH_BLOCKS;
 		printk(KERN_NOTICE PFX "VIA Nano stepping 2 detected: enabling workaround.\n");
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -2576,7 +2576,7 @@ static struct amd64_family_type *per_fam
 	struct amd64_family_type *fam_type = NULL;
 
 	pvt->ext_model  = boot_cpu_data.x86_model >> 4;
-	pvt->stepping	= boot_cpu_data.x86_mask;
+	pvt->stepping	= boot_cpu_data.x86_stepping;
 	pvt->model	= boot_cpu_data.x86_model;
 	pvt->fam	= boot_cpu_data.x86;
 
--- a/drivers/edac/mce_amd.c
+++ b/drivers/edac/mce_amd.c
@@ -744,7 +744,7 @@ int amd_decode_mce(struct notifier_block
 
 	pr_emerg(HW_ERR "CPU:%d (%x:%x:%x) MC%d_STATUS[%s|%s|%s|%s|%s",
 		m->extcpu,
-		c->x86, c->x86_model, c->x86_mask,
+		c->x86, c->x86_model, c->x86_stepping,
 		m->bank,
 		((m->status & MCI_STATUS_OVER)	? "Over"  : "-"),
 		((m->status & MCI_STATUS_UC)	? "UE"	  : "CE"),
--- a/drivers/hwmon/coretemp.c
+++ b/drivers/hwmon/coretemp.c
@@ -268,13 +268,13 @@ static int adjust_tjmax(struct cpuinfo_x
 	for (i = 0; i < ARRAY_SIZE(tjmax_model_table); i++) {
 		const struct tjmax_model *tm = &tjmax_model_table[i];
 		if (c->x86_model == tm->model &&
-		    (tm->mask == ANY || c->x86_mask == tm->mask))
+		    (tm->mask == ANY || c->x86_stepping == tm->mask))
 			return tm->tjmax;
 	}
 
 	/* Early chips have no MSR for TjMax */
 
-	if (c->x86_model == 0xf && c->x86_mask < 4)
+	if (c->x86_model == 0xf && c->x86_stepping < 4)
 		usemsr_ee = 0;
 
 	if (c->x86_model > 0xe && usemsr_ee) {
@@ -426,7 +426,7 @@ static int chk_ucode_version(unsigned in
 	 * Readings might stop update when processor visited too deep sleep,
 	 * fixed for stepping D0 (6EC).
 	 */
-	if (c->x86_model == 0xe && c->x86_mask < 0xc && c->microcode < 0x39) {
+	if (c->x86_model == 0xe && c->x86_stepping < 0xc && c->microcode < 0x39) {
 		pr_err("Errata AE18 not fixed, update BIOS or microcode of the CPU!\n");
 		return -ENODEV;
 	}
--- a/drivers/hwmon/hwmon-vid.c
+++ b/drivers/hwmon/hwmon-vid.c
@@ -293,7 +293,7 @@ u8 vid_which_vrm(void)
 	if (c->x86 < 6)		/* Any CPU with family lower than 6 */
 		return 0;	/* doesn't have VID */
 
-	vrm_ret = find_vrm(c->x86, c->x86_model, c->x86_mask, c->x86_vendor);
+	vrm_ret = find_vrm(c->x86, c->x86_model, c->x86_stepping, c->x86_vendor);
 	if (vrm_ret == 134)
 		vrm_ret = get_via_model_d_vrm();
 	if (vrm_ret == 0)
--- a/drivers/hwmon/k10temp.c
+++ b/drivers/hwmon/k10temp.c
@@ -126,7 +126,7 @@ static bool has_erratum_319(struct pci_d
 	 * and AM3 formats, but that's the best we can do.
 	 */
 	return boot_cpu_data.x86_model < 4 ||
-	       (boot_cpu_data.x86_model == 4 && boot_cpu_data.x86_mask <= 2);
+	       (boot_cpu_data.x86_model == 4 && boot_cpu_data.x86_stepping <= 2);
 }
 
 static int k10temp_probe(struct pci_dev *pdev,
--- a/drivers/hwmon/k8temp.c
+++ b/drivers/hwmon/k8temp.c
@@ -187,7 +187,7 @@ static int k8temp_probe(struct pci_dev *
 		return -ENOMEM;
 
 	model = boot_cpu_data.x86_model;
-	stepping = boot_cpu_data.x86_mask;
+	stepping = boot_cpu_data.x86_stepping;
 
 	/* feature available since SH-C0, exclude older revisions */
 	if ((model == 4 && stepping == 0) ||
--- a/drivers/video/fbdev/geode/video_gx.c
+++ b/drivers/video/fbdev/geode/video_gx.c
@@ -127,7 +127,7 @@ void gx_set_dclk_frequency(struct fb_inf
 	int timeout = 1000;
 
 	/* Rev. 1 Geode GXs use a 14 MHz reference clock instead of 48 MHz. */
-	if (cpu_data(0).x86_mask == 1) {
+	if (cpu_data(0).x86_stepping == 1) {
 		pll_table = gx_pll_table_14MHz;
 		pll_table_len = ARRAY_SIZE(gx_pll_table_14MHz);
 	} else {


^ permalink raw reply	[relevance 5%]

* [PATCH 3.16 34/61] scsi: sg: fixup infoleak when using SG_GET_REQUEST_TABLE
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (32 preceding siblings ...)
  2020-06-09 18:04  8% ` [PATCH 3.16 33/61] scsi: sg: factor out sg_fill_request_table() Ben Hutchings
@ 2020-06-09 18:04  9% ` Ben Hutchings
  2020-06-09 18:04 11% ` [PATCH 3.16 35/61] scsi: sg: Re-fix off by one in sg_fill_request_table() Ben Hutchings
                   ` (27 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Christoph Hellwig, Eric Dumazet,
	Martin K. Petersen, Greg Kroah-Hartman, Hannes Reinecke,
	Hannes Reinecke, Bart Van Assche

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Hannes Reinecke <hare@suse.de>

commit 3e0097499839e0fe3af380410eababe5a47c4cf9 upstream.

When calling SG_GET_REQUEST_TABLE ioctl only a half-filled table is
returned; the remaining part will then contain stale kernel memory
information.  This patch zeroes out the entire table to avoid this
issue.

Signed-off-by: Hannes Reinecke <hare@suse.com>
Reviewed-by: Bart Van Assche <bart.vanassche@wdc.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/scsi/sg.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -881,7 +881,6 @@ sg_fill_request_table(Sg_fd *sfp, sg_req
 	list_for_each_entry(srp, &sfp->rq_list, entry) {
 		if (val > SG_MAX_QUEUE)
 			break;
-		memset(&rinfo[val], 0, SZ_SG_REQ_INFO);
 		rinfo[val].req_state = srp->done + 1;
 		rinfo[val].problem =
 			srp->header.masked_status &
@@ -1098,8 +1097,8 @@ sg_ioctl(struct file *filp, unsigned int
 		else {
 			sg_req_info_t *rinfo;
 
-			rinfo = kmalloc(SZ_SG_REQ_INFO * SG_MAX_QUEUE,
-								GFP_KERNEL);
+			rinfo = kzalloc(SZ_SG_REQ_INFO * SG_MAX_QUEUE,
+					GFP_KERNEL);
 			if (!rinfo)
 				return -ENOMEM;
 			read_lock_irqsave(&sfp->rq_list_lock, iflags);


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 18/61] USB: core: Fix free-while-in-use bug in the USB S-Glibrary
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (16 preceding siblings ...)
  2020-06-09 18:04  9% ` [PATCH 3.16 17/61] drivers: usb: core: Minimize irq disabling in usb_sg_cancel() Ben Hutchings
@ 2020-06-09 18:04  7% ` Ben Hutchings
  2020-06-09 18:04  9% ` [PATCH 3.16 19/61] scsi: mptfusion: Add bounds check in mptctl_hp_targetinfo() Ben Hutchings
                   ` (43 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Alan Stern, Greg Kroah-Hartman, stable

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Alan Stern <stern@rowland.harvard.edu>

commit 056ad39ee9253873522f6469c3364964a322912b upstream.

FuzzUSB (a variant of syzkaller) found a free-while-still-in-use bug
in the USB scatter-gather library:

BUG: KASAN: use-after-free in atomic_read
include/asm-generic/atomic-instrumented.h:26 [inline]
BUG: KASAN: use-after-free in usb_hcd_unlink_urb+0x5f/0x170
drivers/usb/core/hcd.c:1607
Read of size 4 at addr ffff888065379610 by task kworker/u4:1/27

CPU: 1 PID: 27 Comm: kworker/u4:1 Not tainted 5.5.11 #2
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS
1.10.2-1ubuntu1 04/01/2014
Workqueue: scsi_tmf_2 scmd_eh_abort_handler
Call Trace:
 __dump_stack lib/dump_stack.c:77 [inline]
 dump_stack+0xce/0x128 lib/dump_stack.c:118
 print_address_description.constprop.4+0x21/0x3c0 mm/kasan/report.c:374
 __kasan_report+0x153/0x1cb mm/kasan/report.c:506
 kasan_report+0x12/0x20 mm/kasan/common.c:639
 check_memory_region_inline mm/kasan/generic.c:185 [inline]
 check_memory_region+0x152/0x1b0 mm/kasan/generic.c:192
 __kasan_check_read+0x11/0x20 mm/kasan/common.c:95
 atomic_read include/asm-generic/atomic-instrumented.h:26 [inline]
 usb_hcd_unlink_urb+0x5f/0x170 drivers/usb/core/hcd.c:1607
 usb_unlink_urb+0x72/0xb0 drivers/usb/core/urb.c:657
 usb_sg_cancel+0x14e/0x290 drivers/usb/core/message.c:602
 usb_stor_stop_transport+0x5e/0xa0 drivers/usb/storage/transport.c:937

This bug occurs when cancellation of the S-G transfer races with
transfer completion.  When that happens, usb_sg_cancel() may continue
to access the transfer's URBs after usb_sg_wait() has freed them.

The bug is caused by the fact that usb_sg_cancel() does not take any
sort of reference to the transfer, and so there is nothing to prevent
the URBs from being deallocated while the routine is trying to use
them.  The fix is to take such a reference by incrementing the
transfer's io->count field while the cancellation is in progres and
decrementing it afterward.  The transfer's URBs are not deallocated
until io->complete is triggered, which happens when io->count reaches
zero.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Reported-and-tested-by: Kyungtae Kim <kt0755@gmail.com>
CC: <stable@vger.kernel.org>

Link: https://lore.kernel.org/r/Pine.LNX.4.44L0.2003281615140.14837-100000@netrider.rowland.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/usb/core/message.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -584,12 +584,13 @@ void usb_sg_cancel(struct usb_sg_request
 	int i, retval;
 
 	spin_lock_irqsave(&io->lock, flags);
-	if (io->status) {
+	if (io->status || io->count == 0) {
 		spin_unlock_irqrestore(&io->lock, flags);
 		return;
 	}
 	/* shut everything down */
 	io->status = -ECONNRESET;
+	io->count++;		/* Keep the request alive until we're done */
 	spin_unlock_irqrestore(&io->lock, flags);
 
 	for (i = io->entries - 1; i >= 0; --i) {
@@ -603,6 +604,12 @@ void usb_sg_cancel(struct usb_sg_request
 			dev_warn(&io->dev->dev, "%s, unlink --> %d\n",
 				 __func__, retval);
 	}
+
+	spin_lock_irqsave(&io->lock, flags);
+	io->count--;
+	if (!io->count)
+		complete(&io->complete);
+	spin_unlock_irqrestore(&io->lock, flags);
 }
 EXPORT_SYMBOL_GPL(usb_sg_cancel);
 


^ permalink raw reply	[relevance 7%]

* [PATCH 3.16 41/61] scsi: sg: only check for dxfer_len greater than 256M
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (39 preceding siblings ...)
  2020-06-09 18:04  9% ` [PATCH 3.16 40/61] scsi: sg: fix static checker warning in sg_is_valid_dxfer Ben Hutchings
@ 2020-06-09 18:04 11% ` Ben Hutchings
  2020-06-09 18:04  9% ` [PATCH 3.16 42/61] scsi: sg: don't return bogus Sg_requests Ben Hutchings
                   ` (20 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Martin K. Petersen, stable,
	Johannes Thumshirn, Jason L Tibbitts III, Hannes Reinecke,
	Greg Kroah-Hartman, Doug Gilbert

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Johannes Thumshirn <jthumshirn@suse.de>

commit f930c7043663188429cd9b254e9d761edfc101ce upstream.

Don't make any assumptions on the sg_io_hdr_t::dxfer_direction or the
sg_io_hdr_t::dxferp in order to determine if it is a valid request. The
only way we can check for bad requests is by checking if the length
exceeds 256M.

Signed-off-by: Johannes Thumshirn <jthumshirn@suse.de>
Fixes: 28676d869bbb (scsi: sg: check for valid direction before starting the request)
Reported-by: Jason L Tibbitts III <tibbs@math.uh.edu>
Tested-by: Jason L Tibbitts III <tibbs@math.uh.edu>
Suggested-by: Doug Gilbert <dgilbert@interlog.com>
Cc: Doug Gilbert <dgilbert@interlog.com>
Cc: <stable@vger.kernel.org>
Reviewed-by: Hannes Reinecke <hare@suse.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
[bwh: Backported to 3.16: Include <linux/sizes.h>]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/scsi/sg.c | 31 +------------------------------
 1 file changed, 1 insertion(+), 30 deletions(-)

--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -54,6 +54,7 @@ static int sg_version_num = 30534;	/* 2
 #include <linux/atomic.h>
 #include <linux/ratelimit.h>
 #include <linux/cred.h> /* for sg_check_file_access() */
+#include <linux/sizes.h>
 
 #include "scsi.h"
 #include <scsi/scsi_dbg.h>
@@ -788,35 +789,6 @@ sg_new_write(Sg_fd *sfp, struct file *fi
 	return count;
 }
 
-static bool sg_is_valid_dxfer(sg_io_hdr_t *hp)
-{
-	switch (hp->dxfer_direction) {
-	case SG_DXFER_NONE:
-		if (hp->dxferp || hp->dxfer_len > 0)
-			return false;
-		return true;
-	case SG_DXFER_FROM_DEV:
-		/*
-		 * for SG_DXFER_FROM_DEV we always set dxfer_len to > 0. dxferp
-		 * can either be NULL or != NULL so there's no point in checking
-		 * it either. So just return true.
-		 */
-		return true;
-	case SG_DXFER_TO_DEV:
-	case SG_DXFER_TO_FROM_DEV:
-		if (!hp->dxferp || hp->dxfer_len == 0)
-			return false;
-		return true;
-	case SG_DXFER_UNKNOWN:
-		if ((!hp->dxferp && hp->dxfer_len) ||
-		    (hp->dxferp && hp->dxfer_len == 0))
-			return false;
-		return true;
-	default:
-		return false;
-	}
-}
-
 static int
 sg_common_write(Sg_fd * sfp, Sg_request * srp,
 		unsigned char *cmnd, int timeout, int blocking)
@@ -836,7 +808,7 @@ sg_common_write(Sg_fd * sfp, Sg_request
 	SCSI_LOG_TIMEOUT(4, printk("sg_common_write:  scsi opcode=0x%02x, cmd_size=%d\n",
 			  (int) cmnd[0], (int) hp->cmd_len));
 
-	if (!sg_is_valid_dxfer(hp))
+	if (hp->dxfer_len >= SZ_256M)
 		return -EINVAL;
 
 	k = sg_start_req(srp, cmnd);


^ permalink raw reply	[relevance 11%]

* [PATCH 3.16 00/61] 3.16.85-rc1 review
@ 2020-06-09 18:03  9% Ben Hutchings
  2020-06-09 18:03  9% ` [PATCH 3.16 01/61] slcan: Fix memory leak in error path Ben Hutchings
                   ` (61 more replies)
  0 siblings, 62 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:03 UTC (permalink / raw)
  To: linux-kernel, stable; +Cc: torvalds, Guenter Roeck, akpm, Denis Kirjanov

This is the start of the stable review cycle for the 3.16.85 release.
There are 61 patches in this series, which will be posted as responses
to this one.  If anyone has any issues with these being applied, please
let me know.

Responses should be made by Thu Jun 11 18:03:51 UTC 2020.
Anything received after that time might be too late.

All the patches have also been committed to the linux-3.16.y-rc branch of
https://git.kernel.org/pub/scm/linux/kernel/git/bwh/linux-stable-rc.git .
A shortlog and diffstat can be found below.

Ben.

-------------

Akinobu Mita (1):
      sg: prevent integer overflow when converting from sectors to bytes
         [46f69e6a6bbbf3858617c8729e31895846c15a79]

Alan Stern (1):
      USB: core: Fix free-while-in-use bug in the USB S-Glibrary
         [056ad39ee9253873522f6469c3364964a322912b]

Alexander Potapenko (1):
      fs/binfmt_elf.c: allocate initialized memory in fill_thread_core_info()
         [1d605416fb7175e1adf094251466caa52093b413]

Ben Hutchings (2):
      scsi: sg: Change next_cmd_len handling to mirror upstream
         [65c26a0f39695ba01d9693754f27ca76cc8a3ab5,
          bf33f87dd04c371ea33feb821b60d63d754e3124]
      scsi: sg: Re-fix off by one in sg_fill_request_table()
         [587c3c9f286cee5c9cac38d28c8ae1875f4ec85b]

Colin Ian King (1):
      ext4: unsigned int compared against zero
         [fbbbbd2f28aec991f3fbc248df211550fbdfd58c]

Dan Carpenter (3):
      scsi: mptfusion: Add bounds check in mptctl_hp_targetinfo()
         [a7043e9529f3c367cc4d82997e00be034cbe57ca]
      scsi: mptfusion: Fix double fetch bug in ioctl
         [28d76df18f0ad5bcf5fa48510b225f0ed262a99b]
      scsi: sg: off by one in sg_ioctl()
         [bd46fc406b30d1db1aff8dabaff8d18bb423fdcf]

David Mosberger (2):
      drivers: usb: core: Don't disable irqs in usb_sg_wait() during URB submit.
         [98b74b0ee57af1bcb6e8b2e76e707a71c5ef8ec9]
      drivers: usb: core: Minimize irq disabling in usb_sg_cancel()
         [5f2e5fb873e269fcb806165715d237f0de4ecf1d]

Douglas Gilbert (1):
      sg: O_EXCL and other lock handling
         [cc833acbee9db5ca8c6162b015b4c93863c6f821]

Eric Dumazet (1):
      net-sysfs: fix netdev_queue_add_kobject() breakage
         [48a322b6f9965b2f1e4ce81af972f0e287b07ed0]

Eric W. Biederman (1):
      signal: Extend exec_id to 64bits
         [d1e7fd6462ca9fc76650fbe6ca800e35b24267da]

Hannes Reinecke (8):
      scsi: sg: close race condition in sg_remove_sfp_usercontext()
         [97d27b0dd015e980ade63fda111fd1353276e28b]
      scsi: sg: disable SET_FORCE_LOW_DMA
         [745dfa0d8ec26b24f3304459ff6e9eacc5c8351b]
      scsi: sg: factor out sg_fill_request_table()
         [4759df905a474d245752c9dc94288e779b8734dd]
      scsi: sg: fixup infoleak when using SG_GET_REQUEST_TABLE
         [3e0097499839e0fe3af380410eababe5a47c4cf9]
      scsi: sg: protect accesses to 'reserved' page array
         [1bc0eb0446158cc76562176b80623aa119afee5b]
      scsi: sg: remove 'save_scat_len'
         [136e57bf43dc4babbfb8783abbf707d483cacbe3]
      scsi: sg: reset 'res_in_use' after unlinking reserved array
         [e791ce27c3f6a1d3c746fd6a8f8e36c9540ec6f9]
      scsi: sg: use standard lists for sg_requests
         [109bade9c625c89bb5ea753aaa1a0a97e6fbb548]

Jason A. Donenfeld (1):
      random: always use batched entropy for get_random_u{32,64}
         [69efea712f5b0489e67d07565aad5c94e09a3e52]

Jia Zhang (1):
      x86/cpu: Rename cpu_data.x86_mask to cpu_data.x86_stepping
         [b399151cb48db30ad1e0e93dd40d68c6d007b637]

Johannes Thumshirn (5):
      scsi: sg: check for valid direction before starting the request
         [28676d869bbb5257b5f14c0c95ad3af3a7019dd5]
      scsi: sg: don't return bogus Sg_requests
         [48ae8484e9fc324b4968d33c585e54bc98e44d61]
      scsi: sg: fix SG_DXFER_FROM_DEV transfers
         [68c59fcea1f2c6a54c62aa896cc623c1b5bc9b47]
      scsi: sg: fix static checker warning in sg_is_valid_dxfer
         [14074aba4bcda3764c9a702b276308b89901d5b6]
      scsi: sg: only check for dxfer_len greater than 256M
         [f930c7043663188429cd9b254e9d761edfc101ce]

Josh Poimboeuf (1):
      x86/speculation: Add Ivy Bridge to affected list
         [3798cc4d106e91382bfe016caa2edada27c2bb3f]

Jouni Hogander (7):
      can: slcan: Fix use-after-free Read in slcan_open
         [9ebd796e24008f33f06ebea5a5e6aceb68b51794]
      net-sysfs: Call dev_hold always in netdev_queue_add_kobject
         [e0b60903b434a7ee21ba8d8659f207ed84101e89]
      net-sysfs: Call dev_hold always in rx_queue_add_kobject
         [ddd9b5e3e765d8ed5a35786a6cb00111713fe161]
      net-sysfs: Fix reference count leak in rx|netdev_queue_add_kobject
         [b8eb718348b8fb30b5a7d0a8fce26fb3f4ac741b]
      slcan: Fix memory leak in error path
         [ed50e1600b4483c049ce76e6bd3b665a6a9300ed]
      slip: Fix memory leak in slip_open error path
         [3b5a39979dafea9d0cd69c7ae06088f7a84cdafa]
      slip: Fix use-after-free Read in slip_open
         [e58c1912418980f57ba2060017583067f5f71e52]

Kyungtae Kim (1):
      USB: gadget: fix illegal array access in binding with UDC
         [15753588bcd4bbffae1cca33c8ced5722477fe1f]

Li Bin (1):
      scsi: sg: add sg_remove_request in sg_common_write
         [849f8583e955dbe3a1806e03ecacd5e71cce0a08]

Marek Milkovic (1):
      selinux: Print 'sclass' as string when unrecognized netlink message occurs
         [cded3fffbeab777e6ad2ec05d4a3b62c5caca0f3]

Mark Gross (4):
      x86/cpu: Add 'table' argument to cpu_matches()
         [93920f61c2ad7edb01e63323832585796af75fc9]
      x86/cpu: Add a steppings field to struct x86_cpu_id
         [e9d7144597b10ff13ff2264c059f7d4a7fbc89ac]
      x86/speculation: Add SRBDS vulnerability and mitigation documentation
         [7222a1b5b87417f22265c92deea76a6aecd0fb0f]
      x86/speculation: Add Special Register Buffer Data Sampling (SRBDS) mitigation
         [7e5b3c267d256822407a22fdce6afdf9cd13f9fb]

Oliver Hartkopp (1):
      slcan: not call free_netdev before rtnl_unlock in slcan_open
         [2091a3d42b4f339eaeed11228e0cbe9d4f92f558]

Paul Moore (1):
      selinux: properly handle multiple messages in selinux_netlink_send()
         [fb73974172ffaaf57a7c42f35424d9aece1a5af6]

Qing Xu (2):
      mwifiex: Fix possible buffer overflows in mwifiex_cmd_append_vsie_tlv()
         [b70261a288ea4d2f4ac7cd04be08a9f0f2de4f4d]
      mwifiex: Fix possible buffer overflows in mwifiex_ret_wmm_get_status()
         [3a9b153c5591548612c3955c9600a98150c81875]

Richard Guy Briggs (2):
      selinux: cleanup error reporting in selinux_nlmsg_perm()
         [e173fb2646a832b424c80904c306b816760ce477]
      selinux: convert WARN_ONCE() to printk() in selinux_nlmsg_perm()
         [d950f84c1c6658faec2ecbf5b09f7e7191953394]

Shijie Luo (1):
      ext4: add cond_resched() to ext4_protect_reserved_inode
         [af133ade9a40794a37104ecbcc2827c0ea373a3c]

Tahsin Erdogan (1):
      ext4: Make checks for metadata_csum feature safer
         [dec214d00e0d78a08b947d7dccdfdb84407a9f4d]

Theodore Ts'o (3):
      ext4: don't perform block validity checks on the journal inode
         [0a944e8a6c66ca04c7afbaa17e22bf208a8b37f0]
      ext4: fix block validity checks for journal inodes using indirect blocks
         [170417c8c7bb2cbbdd949bf5c443c0c8f24a203b]
      ext4: protect journal inode's blocks using block_validity
         [345c0dbf3a30872d9b204db96b5857cd00808cae]

Todd Poynor (2):
      scsi: sg: protect against races between mmap() and SG_SET_RESERVED_SIZE
         [6a8dadcca81fceff9976e8828cceb072873b7bd5]
      scsi: sg: recheck MMAP_IO request length with lock held
         [8d26f491116feaa0b16de370b6a7ba40a40fa0b4]

Tony Battersby (1):
      scsi: sg: fix minor memory leak in error path
         [c170e5a8d222537e98aa8d4fddb667ff7a2ee114]

Vladis Dronov (1):
      selinux: rate-limit netlink message warnings in selinux_nlmsg_perm()
         [76319946f321e30872dd72af7de867cb26e7a373]

Wu Bo (1):
      scsi: sg: add sg_remove_request in sg_write
         [83c6f2390040f188cc25b270b4befeb5628c1aee]

Yangerkun (1):
      slip: not call free_netdev before rtnl_unlock in slip_open
         [f596c87005f7b1baeb7d62d9a9e25d68c3dfae10]

 Documentation/ABI/testing/sysfs-devices-system-cpu |   1 +
 .../special-register-buffer-data-sampling.rst      | 149 ++++
 Documentation/kernel-parameters.txt                |  20 +
 Makefile                                           |   4 +-
 arch/x86/include/asm/acpi.h                        |   2 +-
 arch/x86/include/asm/cpu_device_id.h               |  27 +
 arch/x86/include/asm/cpufeatures.h                 |   2 +
 arch/x86/include/asm/processor.h                   |   2 +-
 arch/x86/include/uapi/asm/msr-index.h              |   4 +
 arch/x86/kernel/amd_nb.c                           |   2 +-
 arch/x86/kernel/asm-offsets_32.c                   |   2 +-
 arch/x86/kernel/cpu/amd.c                          |  28 +-
 arch/x86/kernel/cpu/bugs.c                         | 106 +++
 arch/x86/kernel/cpu/centaur.c                      |   4 +-
 arch/x86/kernel/cpu/common.c                       |  62 +-
 arch/x86/kernel/cpu/cpu.h                          |   1 +
 arch/x86/kernel/cpu/cyrix.c                        |   2 +-
 arch/x86/kernel/cpu/intel.c                        |  18 +-
 arch/x86/kernel/cpu/match.c                        |   7 +-
 arch/x86/kernel/cpu/microcode/intel.c              |   4 +-
 arch/x86/kernel/cpu/mtrr/generic.c                 |   2 +-
 arch/x86/kernel/cpu/mtrr/main.c                    |   4 +-
 arch/x86/kernel/cpu/perf_event_intel.c             |   2 +-
 arch/x86/kernel/cpu/perf_event_intel_lbr.c         |   2 +-
 arch/x86/kernel/cpu/perf_event_p6.c                |   2 +-
 arch/x86/kernel/cpu/proc.c                         |   4 +-
 arch/x86/kernel/head_32.S                          |   4 +-
 arch/x86/kernel/mpparse.c                          |   2 +-
 drivers/base/cpu.c                                 |   8 +
 drivers/char/hw_random/via-rng.c                   |   2 +-
 drivers/char/random.c                              |   3 -
 drivers/cpufreq/acpi-cpufreq.c                     |   2 +-
 drivers/cpufreq/longhaul.c                         |   6 +-
 drivers/cpufreq/p4-clockmod.c                      |   2 +-
 drivers/cpufreq/powernow-k7.c                      |   2 +-
 drivers/cpufreq/speedstep-centrino.c               |   4 +-
 drivers/cpufreq/speedstep-lib.c                    |   6 +-
 drivers/crypto/padlock-aes.c                       |   2 +-
 drivers/edac/amd64_edac.c                          |   2 +-
 drivers/edac/mce_amd.c                             |   2 +-
 drivers/hwmon/coretemp.c                           |   6 +-
 drivers/hwmon/hwmon-vid.c                          |   2 +-
 drivers/hwmon/k10temp.c                            |   2 +-
 drivers/hwmon/k8temp.c                             |   2 +-
 drivers/message/fusion/mptctl.c                    | 215 ++----
 drivers/net/can/slcan.c                            |   4 +
 drivers/net/slip/slip.c                            |   4 +
 drivers/net/wireless/mwifiex/scan.c                |   7 +
 drivers/net/wireless/mwifiex/wmm.c                 |   4 +
 drivers/scsi/sg.c                                  | 758 +++++++++++----------
 drivers/usb/core/message.c                         |  53 +-
 drivers/usb/gadget/configfs.c                      |   3 +
 drivers/video/fbdev/geode/video_gx.c               |   2 +-
 fs/binfmt_elf.c                                    |   2 +-
 fs/exec.c                                          |   2 +-
 fs/ext4/block_validity.c                           |  57 ++
 fs/ext4/ext4.h                                     |  19 +-
 fs/ext4/extents.c                                  |  13 +-
 fs/ext4/inode.c                                    |   5 +
 include/linux/mod_devicetable.h                    |   6 +
 include/linux/sched.h                              |   4 +-
 include/scsi/sg.h                                  |   1 -
 kernel/signal.c                                    |   2 +-
 net/core/net-sysfs.c                               |  39 +-
 security/selinux/hooks.c                           |  70 +-
 65 files changed, 1103 insertions(+), 689 deletions(-)

-- 
Ben Hutchings
The two most common things in the universe are hydrogen and stupidity.


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 16/61] drivers: usb: core: Don't disable irqs in usb_sg_wait() during URB submit.
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (14 preceding siblings ...)
  2020-06-09 18:04 11% ` [PATCH 3.16 15/61] selinux: properly handle multiple messages in selinux_netlink_send() Ben Hutchings
@ 2020-06-09 18:04  8% ` Ben Hutchings
  2020-06-09 18:04  9% ` [PATCH 3.16 17/61] drivers: usb: core: Minimize irq disabling in usb_sg_cancel() Ben Hutchings
                   ` (45 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, David Mosberger, Greg Kroah-Hartman

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: David Mosberger <davidm@egauge.net>

commit 98b74b0ee57af1bcb6e8b2e76e707a71c5ef8ec9 upstream.

usb_submit_urb() may take quite long to execute.  For example, a
single sg list may have 30 or more entries, possibly leading to that
many calls to DMA-map pages.  This can cause interrupt latency of
several hundred micro-seconds.

Avoid the problem by releasing the io->lock spinlock and re-enabling
interrupts before calling usb_submit_urb().  This opens races with
usb_sg_cancel() and sg_complete().  Handle those races by using
usb_block_urb() to stop URBs from being submitted after
usb_sg_cancel() or sg_complete() with error.

Note that usb_unlink_urb() is guaranteed to return -ENODEV if
!io->urbs[i]->dev and since the -ENODEV case is already handled,
we don't have to check for !io->urbs[i]->dev explicitly.

Before this change, reading 512MB from an ext3 filesystem on a USB
memory stick showed a throughput of 12 MB/s with about 500 missed
deadlines.

With this change, reading the same file gave the same throughput but
only one or two missed deadlines.

Signed-off-by: David Mosberger <davidm@egauge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/usb/core/message.c | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)

--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -306,9 +306,10 @@ static void sg_complete(struct urb *urb)
 		 */
 		spin_unlock(&io->lock);
 		for (i = 0, found = 0; i < io->entries; i++) {
-			if (!io->urbs[i] || !io->urbs[i]->dev)
+			if (!io->urbs[i])
 				continue;
 			if (found) {
+				usb_block_urb(io->urbs[i]);
 				retval = usb_unlink_urb(io->urbs[i]);
 				if (retval != -EINPROGRESS &&
 				    retval != -ENODEV &&
@@ -519,12 +520,10 @@ void usb_sg_wait(struct usb_sg_request *
 		int retval;
 
 		io->urbs[i]->dev = io->dev;
-		retval = usb_submit_urb(io->urbs[i], GFP_ATOMIC);
-
-		/* after we submit, let completions or cancellations fire;
-		 * we handshake using io->status.
-		 */
 		spin_unlock_irq(&io->lock);
+
+		retval = usb_submit_urb(io->urbs[i], GFP_NOIO);
+
 		switch (retval) {
 			/* maybe we retrying will recover */
 		case -ENXIO:	/* hc didn't queue this one */
@@ -594,8 +593,8 @@ void usb_sg_cancel(struct usb_sg_request
 		for (i = 0; i < io->entries; i++) {
 			int retval;
 
-			if (!io->urbs[i]->dev)
-				continue;
+			usb_block_urb(io->urbs[i]);
+
 			retval = usb_unlink_urb(io->urbs[i]);
 			if (retval != -EINPROGRESS
 					&& retval != -ENODEV


^ permalink raw reply	[relevance 8%]

* [PATCH 3.16 13/61] selinux: Print 'sclass' as string when unrecognized netlink message occurs
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (11 preceding siblings ...)
  2020-06-09 18:04  9% ` [PATCH 3.16 12/61] selinux: convert WARN_ONCE() to printk() " Ben Hutchings
@ 2020-06-09 18:04  9% ` Ben Hutchings
  2020-06-09 18:04  9% ` [PATCH 3.16 14/61] selinux: rate-limit netlink message warnings in selinux_nlmsg_perm() Ben Hutchings
                   ` (48 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Stephen Smalley, Marek Milkovic, Paul Moore

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Marek Milkovic <mmilkovi@redhat.com>

commit cded3fffbeab777e6ad2ec05d4a3b62c5caca0f3 upstream.

This prints the 'sclass' field as string instead of index in unrecognized netlink message.
The textual representation makes it easier to distinguish the right class.

Signed-off-by: Marek Milkovic <mmilkovi@redhat.com>
Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
[PM: 80-char width fixes]
Signed-off-by: Paul Moore <pmoore@redhat.com>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 security/selinux/hooks.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -4685,8 +4685,9 @@ static int selinux_nlmsg_perm(struct soc
 		if (err == -EINVAL) {
 			printk(KERN_WARNING
 			       "SELinux: unrecognized netlink message:"
-			       " protocol=%hu nlmsg_type=%hu sclass=%hu\n",
-			       sk->sk_protocol, nlh->nlmsg_type, sksec->sclass);
+			       " protocol=%hu nlmsg_type=%hu sclass=%s\n",
+			       sk->sk_protocol, nlh->nlmsg_type,
+			       secclass_map[sksec->sclass - 1].name);
 			if (!selinux_enforcing || security_get_allow_unknown())
 				err = 0;
 		}


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 43/61] scsi: sg: fix minor memory leak in error path
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (41 preceding siblings ...)
  2020-06-09 18:04  9% ` [PATCH 3.16 42/61] scsi: sg: don't return bogus Sg_requests Ben Hutchings
@ 2020-06-09 18:04  9% ` Ben Hutchings
  2020-06-09 18:04  9% ` [PATCH 3.16 44/61] scsi: sg: add sg_remove_request in sg_common_write Ben Hutchings
                   ` (18 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Greg Kroah-Hartman, Bart Van Assche,
	Tony Battersby, Ewan D. Milne, Martin K. Petersen, stable

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Tony Battersby <tonyb@cybernetics.com>

commit c170e5a8d222537e98aa8d4fddb667ff7a2ee114 upstream.

Fix a minor memory leak when there is an error opening a /dev/sg device.

Fixes: cc833acbee9d ("sg: O_EXCL and other lock handling")
Cc: <stable@vger.kernel.org>
Reviewed-by: Ewan D. Milne <emilne@redhat.com>
Signed-off-by: Tony Battersby <tonyb@cybernetics.com>
Reviewed-by: Bart Van Assche <bart.vanassche@wdc.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/scsi/sg.c | 1 +
 1 file changed, 1 insertion(+)

--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -2168,6 +2168,7 @@ sg_add_sfp(Sg_device * sdp, int dev)
 	write_lock_irqsave(&sdp->sfd_lock, iflags);
 	if (atomic_read(&sdp->detaching)) {
 		write_unlock_irqrestore(&sdp->sfd_lock, iflags);
+		kfree(sfp);
 		return ERR_PTR(-ENODEV);
 	}
 	list_add_tail(&sfp->sfd_siblings, &sdp->sfds);


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 14/61] selinux: rate-limit netlink message warnings in selinux_nlmsg_perm()
  2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
                   ` (12 preceding siblings ...)
  2020-06-09 18:04  9% ` [PATCH 3.16 13/61] selinux: Print 'sclass' as string when unrecognized netlink message occurs Ben Hutchings
@ 2020-06-09 18:04  9% ` Ben Hutchings
  2020-06-09 18:04 11% ` [PATCH 3.16 15/61] selinux: properly handle multiple messages in selinux_netlink_send() Ben Hutchings
                   ` (47 subsequent siblings)
  61 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-06-09 18:04 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Paul Moore, Vladis Dronov, Florian Weimer

3.16.85-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Vladis Dronov <vdronov@redhat.com>

commit 76319946f321e30872dd72af7de867cb26e7a373 upstream.

Any process is able to send netlink messages with invalid types.
Make the warning rate-limited to prevent too much log spam.

The warning is supposed to help to find misbehaving programs, so
print the triggering command name and pid.

Reported-by: Florian Weimer <fweimer@redhat.com>
Signed-off-by: Vladis Dronov <vdronov@redhat.com>
[PM: subject line tweak to make checkpatch.pl happy]
Signed-off-by: Paul Moore <pmoore@redhat.com>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 security/selinux/hooks.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -4683,11 +4683,12 @@ static int selinux_nlmsg_perm(struct soc
 	err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm);
 	if (err) {
 		if (err == -EINVAL) {
-			printk(KERN_WARNING
-			       "SELinux: unrecognized netlink message:"
-			       " protocol=%hu nlmsg_type=%hu sclass=%s\n",
+			pr_warn_ratelimited("SELinux: unrecognized netlink"
+			       " message: protocol=%hu nlmsg_type=%hu sclass=%s"
+			       " pig=%d comm=%s\n",
 			       sk->sk_protocol, nlh->nlmsg_type,
-			       secclass_map[sksec->sclass - 1].name);
+			       secclass_map[sksec->sclass - 1].name,
+			       task_pid_nr(current), current->comm);
 			if (!selinux_enforcing || security_get_allow_unknown())
 				err = 0;
 		}


^ permalink raw reply	[relevance 9%]

* Linux 3.16.84
@ 2020-05-23 12:15  1% Ben Hutchings
  0 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-23 12:15 UTC (permalink / raw)
  To: linux-kernel, Andrew Morton, torvalds, Jiri Slaby, stable; +Cc: lwn


[-- Attachment #1.1: Type: text/plain, Size: 13681 bytes --]

I'm announcing the release of the 3.16.84 kernel.

All users of the 3.16 kernel series should upgrade.

The updated 3.16.y git tree can be found at:
        https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git linux-3.16.y
and can be browsed at the normal kernel.org git web browser:
        https://git.kernel.org/?p=linux/kernel/git/stable/linux-stable.git

The diff from 3.16.83 is attached to this message.

Ben.

------------

 Makefile                                           |   2 +-
 arch/arm/boot/dts/sama5d3.dtsi                     |  26 ++--
 arch/arm/boot/dts/sama5d3_can.dtsi                 |   4 +-
 arch/arm/boot/dts/sama5d3_tcb1.dtsi                |   1 +
 arch/arm/boot/dts/sama5d3_uart.dtsi                |   4 +-
 arch/arm/include/asm/kvm_emulate.h                 |   5 +
 arch/arm/include/asm/kvm_mmio.h                    |   2 +
 arch/arm/kvm/mmio.c                                |   6 +
 arch/arm/mach-tegra/sleep-tegra30.S                |  11 ++
 arch/arm64/include/asm/kvm_emulate.h               |   5 +
 arch/arm64/include/asm/kvm_mmio.h                  |   6 +-
 arch/ia64/include/asm/io.h                         |   1 +
 arch/powerpc/Kconfig                               |   1 +
 arch/powerpc/kvm/book3s_hv.c                       |   4 +-
 arch/powerpc/kvm/book3s_pr.c                       |   4 +-
 arch/sparc/include/uapi/asm/ipcbuf.h               |  22 ++--
 arch/x86/kernel/cpu/tsx.c                          |  13 +-
 arch/x86/kvm/emulate.c                             |  12 +-
 arch/x86/kvm/i8259.c                               |   4 +-
 arch/x86/kvm/lapic.c                               |  14 +-
 arch/x86/kvm/vmx.c                                 |   4 +-
 arch/x86/kvm/x86.c                                 |  57 +++++++--
 arch/x86/platform/efi/efi.c                        |  37 +++---
 crypto/af_alg.c                                    |   6 +-
 crypto/algapi.c                                    |  22 +---
 crypto/api.c                                       |   3 +-
 crypto/internal.h                                  |   1 -
 crypto/pcrypt.c                                    |   4 +-
 drivers/crypto/picoxcell_crypto.c                  |  15 ++-
 drivers/firmware/efi/efi.c                         |   4 +-
 drivers/md/persistent-data/dm-space-map-common.c   |  27 ++++
 drivers/md/persistent-data/dm-space-map-common.h   |   2 +
 drivers/md/persistent-data/dm-space-map-disk.c     |   6 +-
 drivers/md/persistent-data/dm-space-map-metadata.c |   5 +-
 drivers/media/rc/iguanair.c                        |  15 +--
 drivers/media/usb/uvc/uvc_driver.c                 |  12 ++
 drivers/media/v4l2-core/videobuf-dma-sg.c          |   5 +-
 drivers/mmc/host/mmc_spi.c                         |  11 +-
 drivers/net/bonding/bond_alb.c                     |  44 +++++--
 drivers/net/ethernet/freescale/gianfar.c           |  10 +-
 drivers/net/wireless/ath/ath9k/hif_usb.c           |   2 +-
 drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c |   3 +
 drivers/net/wireless/brcm80211/brcmfmac/usb.c      |   3 +-
 drivers/net/wireless/iwlegacy/common.c             |   2 +-
 drivers/net/wireless/orinoco/orinoco_usb.c         |   4 +-
 drivers/net/wireless/rsi/rsi_91x_usb.c             |  12 +-
 drivers/net/wireless/zd1211rw/zd_usb.c             |   2 +-
 drivers/of/Kconfig                                 |   4 +
 drivers/of/address.c                               |   6 +-
 drivers/pci/setup-bus.c                            |  20 ++-
 drivers/power/sbs-battery.c                        |   2 +-
 drivers/rtc/rtc-hym8563.c                          |   2 +-
 drivers/scsi/qla2xxx/qla_mbx.c                     |   3 +-
 drivers/spi/spi-dw.c                               |  14 +-
 drivers/spi/spi-dw.h                               |   1 +
 drivers/staging/wlan-ng/prism2mgmt.c               |   2 +-
 drivers/usb/dwc3/core.c                            |   3 +
 drivers/usb/gadget/f_ecm.c                         |  16 ++-
 drivers/usb/gadget/f_ncm.c                         |  17 ++-
 drivers/usb/serial/ir-usb.c                        | 136 +++++++++++++++-----
 drivers/video/fbdev/pxa168fb.c                     |   6 +-
 fs/btrfs/ctree.c                                   |   8 +-
 fs/btrfs/ctree.h                                   |   6 +-
 fs/btrfs/delayed-ref.c                             |   8 +-
 fs/btrfs/disk-io.c                                 |   1 -
 fs/btrfs/tests/btrfs-tests.c                       |   1 -
 fs/cifs/cifsglob.h                                 |   1 +
 fs/cifs/smb2pdu.c                                  |  10 +-
 fs/cifs/smb2transport.c                            |   2 +
 fs/cifs/transport.c                                |   4 +
 fs/jbd2/checkpoint.c                               |   2 +-
 fs/jbd2/commit.c                                   |   4 +-
 fs/jbd2/journal.c                                  |  21 ++-
 fs/namespace.c                                     |   2 +-
 fs/nfs/Kconfig                                     |   2 +-
 fs/nfs/dir.c                                       | 104 ++++++---------
 fs/pnode.c                                         |   9 +-
 fs/reiserfs/super.c                                |   4 +-
 fs/ubifs/file.c                                    |   5 +-
 include/linux/padata.h                             |  13 +-
 include/linux/usb/irda.h                           |  13 +-
 kernel/padata.c                                    | 142 ++++++++-------------
 kernel/time/clocksource.c                          |  11 +-
 kernel/trace/trace_stat.c                          |  31 +++--
 mm/mempolicy.c                                     |   6 +-
 net/ipv4/tcp.c                                     |   1 +
 net/sched/cls_rsvp.h                               |   6 +-
 net/sched/ematch.c                                 |   3 +
 net/sunrpc/auth_gss/svcauth_gss.c                  |   4 +
 scripts/kconfig/confdata.c                         |   2 +-
 sound/drivers/dummy.c                              |   2 +-
 sound/sh/aica.c                                    |   4 +-
 virt/kvm/ioapic.c                                  |  15 ++-
 virt/kvm/kvm_main.c                                |  12 +-
 94 files changed, 713 insertions(+), 443 deletions(-)

Al Viro (1):
      propagate_one(): mnt_set_mountpoint() needs mount_lock

Alexandre Belloni (2):
      ARM: dts: at91: sama5d3: fix maximum peripheral clock rates
      ARM: dts: at91: sama5d3: define clock rate range for tcb1

Ard Biesheuvel (1):
      efi/x86: Map the entire EFI vendor string before copying it

Arnd Bergmann (2):
      sparc32: fix struct ipc64_perm type definition
      x86: kvm: avoid unused variable warning

Ben Hutchings (1):
      Linux 3.16.84

Bin Liu (1):
      usb: dwc3: turn off VBUS when leaving host mode

Bryan O'Donoghue (2):
      usb: gadget: f_ncm: Use atomic_t to track in-flight request
      usb: gadget: f_ecm: Use atomic_t to track in-flight request

Chen Yucong (1):
      kvm: x86: use macros to compute bank MSRs

Christoffer Dall (1):
      KVM: arm64: Only sign-extend MMIO up to register width

Christophe JAILLET (1):
      pxa168fb: Fix the function used to release some memory in an error handling path

Chuhong Yuan (1):
      crypto: picoxcell - adjust the position of tasklet_init and fix missed tasklet_kill

Colin Ian King (2):
      staging: wlan-ng: ensure error return is actually returned
      iwlegacy: ensure loop counter addr does not wrap and cause an infinite loop

Dan Carpenter (3):
      brcmfmac: Fix use after free in brcmf_sdio_readframes()
      power: supply: sbs-battery: Fix a signedness bug in sbs_get_battery_capacity()
      mm/mempolicy.c: fix out of bounds write in mpol_parse_str()

Daniel Jordan (3):
      padata: initialize pd->cpu with effective cpumask
      padata: purge get_cpu and reorder_via_wq from padata_do_serial
      padata: always acquire cpu_hotplug_lock before pinst->lock

Daniel Kiper (2):
      arch/ia64: Define early_memunmap()
      efi: Use early_mem*() instead of early_io*()

Eric Dumazet (4):
      net_sched: ematch: reject invalid TCF_EM_SIMPLE
      tcp: clear tp->total_retrans in tcp_disconnect()
      cls_rsvp: fix rsvp_policy
      bonding/alb: properly access headers in bond_alb_xmit()

Fabian Frederick (1):
      nfs: use kmap/kunmap directly

Filipe Manana (1):
      Btrfs: fix race between adding and putting tree mod seq elements and nodes

Geert Uytterhoeven (1):
      nfs: NFS_SWAP should depend on SWAP

Guenter Roeck (1):
      brcmfmac: abort and release host after error

Herbert Xu (7):
      padata: Replace delayed timer with immediate workqueue in padata_reorder
      padata: Remove broken queue flushing
      crypto: pcrypt - Fix user-after-free on module unload
      crypto: pcrypt - Do not clear MAY_SLEEP flag in original request
      crypto: af_alg - Use bh_lock_sock in sk_destruct
      crypto: api - Check spawn->alg under lock in crypto_drop_spawn
      crypto: api - Fix race condition in crypto_spawn_alg

Jan Kara (2):
      reiserfs: Fix memory leak of journal device string
      reiserfs: Fix spurious unlock in reiserfs_fill_super() error handling

Jason A. Donenfeld (2):
      padata: avoid race in reordering
      padata: get_next is never NULL

Joe Thornber (1):
      dm space map common: fix to ensure new block isn't already in use

Johan Hovold (10):
      ath9k: fix storage endpoint lookup
      rsi: fix use-after-free on failed probe and unbind
      brcmfmac: fix interface sanity check
      orinoco_usb: fix interface sanity check
      rsi_91x_usb: fix interface sanity check
      zd1211rw: fix storage endpoint lookup
      media: iguanair: fix endpoint sanity check
      USB: serial: ir-usb: add missing endpoint sanity check
      USB: serial: ir-usb: fix link-speed handling
      USB: serial: ir-usb: fix IrLAP framing

John Hubbard (1):
      media/v4l2-core: set pages dirty upon releasing DMA buffers

Kai Li (1):
      jbd2: clear JBD2_ABORT flag before journal_reset to update log tail info when load journal

Konstantin Khlebnikov (1):
      clocksource: Prevent double add_timer_on() for watchdog_timer

Linus Walleij (1):
      mmc: spi: Toggle SPI polarity, do not hardcode it

Logan Gunthorpe (1):
      PCI: Don't disable bridge BARs when assigning bus resources

Luis Henriques (1):
      tracing: Fix tracing_stat return values in error handling paths

Marios Pomonis (7):
      KVM: x86: Protect x86_decode_insn from Spectre-v1/L1TF attacks
      KVM: x86: Refactor picdev_write() to prevent Spectre-v1/L1TF attacks
      KVM: x86: Protect ioapic_read_indirect() from Spectre-v1/L1TF attacks
      KVM: x86: Protect ioapic_write_indirect() from Spectre-v1/L1TF attacks
      KVM: x86: Protect kvm_lapic_reg_write() from Spectre-v1/L1TF attacks
      KVM: x86: Protect MSR-based index computations from Spectre-v1/L1TF attacks in x86.c
      KVM: x86: Protect DR-based index computations from Spectre-v1/L1TF attacks

Masahiro Yamada (1):
      kconfig: fix broken dependency in randconfig-generated .config

Mathias Krause (3):
      padata: set cpu_index of unused CPUs to -1
      padata: ensure the reorder timer callback runs on the correct CPU
      padata: ensure padata_do_serial() runs on the correct CPU

Miaohe Lin (1):
      KVM: nVMX: vmread should not set rflags to specify success in case of #PF

Michael Ellerman (1):
      of: Add OF_DMA_DEFAULT_COHERENT & select it on powerpc

Navid Emamdoost (1):
      brcmfmac: Fix memory leak in brcmf_usbdev_qinit

Oliver Neukum (1):
      media: iguanair: add sanity checks

Paul Kocialkowski (1):
      rtc: hym8563: Return -EINVAL if the time is known to be invalid

Pawan Gupta (1):
      x86/cpu: Update cached HLE state on write to TSX_CTRL_CPUID_CLEAR

Piotr Krysiuk (1):
      fs/namespace.c: fix mountpoint reference counter race

Quinn Tran (1):
      scsi: qla2xxx: Fix mtcp dump collection failure

Roberto Bergantinos Corpas (1):
      sunrpc: expiry_time should be seconds not timeval

Ronnie Sahlberg (1):
      cifs: fail i/o on soft mounts if sessionsetup errors out

Sean Christopherson (6):
      KVM: x86: Don't let userspace set host-reserved cr4 bits
      KVM: x86/mmu: Apply max PA check for MMIO sptes to 32-bit KVM
      KVM: PPC: Book3S HV: Uninit vCPU if vcore creation fails
      KVM: PPC: Book3S PR: Free shared page if mmu initialization fails
      KVM: x86: Free wbinvd_dirty_mask if vCPU creation fails
      KVM: Check for a bad hva before dropping into the ghc slow path

Stephen Warren (1):
      ARM: tegra: Enable PLLP bypass during Tegra124 LP1

Steven Rostedt (VMware) (1):
      tracing: Fix very unlikely race of registering two stat tracers

Takashi Iwai (2):
      ALSA: sh: Fix compile warning wrt const
      ALSA: dummy: Fix PCM format loop in proc output

Tobias Klauser (1):
      padata: Remove unused but set variables

Trond Myklebust (2):
      NFS: Fix memory leaks and corruption in readdir
      NFS: Directory page cache pages need to be locked when read

Vincent Whitchurch (1):
      CIFS: Fix task struct use-after-free on reconnect

Vladimir Oltean (1):
      gianfar: Fix TX timestamping with a stacked DSA driver

Will Deacon (1):
      media: uvcvideo: Avoid cyclic entity chains due to malformed USB descriptors

Zhihao Cheng (1):
      ubifs: Fix deadlock in concurrent bulk-read and writepage

wuxu.wu (1):
      spi: spi-dw: Add lock protect dw_spi rx/tx to prevent concurrent calls

zhangyi (F) (2):
      jbd2: switch to use jbd2_journal_abort() when failed to submit the commit record
      ext4, jbd2: ensure panic when aborting with zero errno


[-- Attachment #1.2: linux-3.16.84.patch --]
[-- Type: text/x-diff, Size: 112399 bytes --]

diff --git a/Makefile b/Makefile
index 99500d145fab..e1c91ead7918 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 3
 PATCHLEVEL = 16
-SUBLEVEL = 83
+SUBLEVEL = 84
 EXTRAVERSION =
 NAME = Museum of Fishiegoodies
 
diff --git a/arch/arm/boot/dts/sama5d3.dtsi b/arch/arm/boot/dts/sama5d3.dtsi
index e0b15a6e8897..d6fea619a0b5 100644
--- a/arch/arm/boot/dts/sama5d3.dtsi
+++ b/arch/arm/boot/dts/sama5d3.dtsi
@@ -1031,43 +1031,43 @@
 					usart0_clk: usart0_clk {
 						#clock-cells = <0>;
 						reg = <12>;
-						atmel,clk-output-range = <0 66000000>;
+						atmel,clk-output-range = <0 83000000>;
 					};
 
 					usart1_clk: usart1_clk {
 						#clock-cells = <0>;
 						reg = <13>;
-						atmel,clk-output-range = <0 66000000>;
+						atmel,clk-output-range = <0 83000000>;
 					};
 
 					usart2_clk: usart2_clk {
 						#clock-cells = <0>;
 						reg = <14>;
-						atmel,clk-output-range = <0 66000000>;
+						atmel,clk-output-range = <0 83000000>;
 					};
 
 					usart3_clk: usart3_clk {
 						#clock-cells = <0>;
 						reg = <15>;
-						atmel,clk-output-range = <0 66000000>;
+						atmel,clk-output-range = <0 83000000>;
 					};
 
 					twi0_clk: twi0_clk {
 						reg = <18>;
 						#clock-cells = <0>;
-						atmel,clk-output-range = <0 16625000>;
+						atmel,clk-output-range = <0 41500000>;
 					};
 
 					twi1_clk: twi1_clk {
 						#clock-cells = <0>;
 						reg = <19>;
-						atmel,clk-output-range = <0 16625000>;
+						atmel,clk-output-range = <0 41500000>;
 					};
 
 					twi2_clk: twi2_clk {
 						#clock-cells = <0>;
 						reg = <20>;
-						atmel,clk-output-range = <0 16625000>;
+						atmel,clk-output-range = <0 41500000>;
 					};
 
 					mci0_clk: mci0_clk {
@@ -1083,19 +1083,19 @@
 					spi0_clk: spi0_clk {
 						#clock-cells = <0>;
 						reg = <24>;
-						atmel,clk-output-range = <0 133000000>;
+						atmel,clk-output-range = <0 166000000>;
 					};
 
 					spi1_clk: spi1_clk {
 						#clock-cells = <0>;
 						reg = <25>;
-						atmel,clk-output-range = <0 133000000>;
+						atmel,clk-output-range = <0 166000000>;
 					};
 
 					tcb0_clk: tcb0_clk {
 						#clock-cells = <0>;
 						reg = <26>;
-						atmel,clk-output-range = <0 133000000>;
+						atmel,clk-output-range = <0 166000000>;
 					};
 
 					pwm_clk: pwm_clk {
@@ -1106,7 +1106,7 @@
 					adc_clk: adc_clk {
 						#clock-cells = <0>;
 						reg = <29>;
-						atmel,clk-output-range = <0 66000000>;
+						atmel,clk-output-range = <0 83000000>;
 					};
 
 					dma0_clk: dma0_clk {
@@ -1137,13 +1137,13 @@
 					ssc0_clk: ssc0_clk {
 						#clock-cells = <0>;
 						reg = <38>;
-						atmel,clk-output-range = <0 66000000>;
+						atmel,clk-output-range = <0 83000000>;
 					};
 
 					ssc1_clk: ssc1_clk {
 						#clock-cells = <0>;
 						reg = <39>;
-						atmel,clk-output-range = <0 66000000>;
+						atmel,clk-output-range = <0 83000000>;
 					};
 
 					sha_clk: sha_clk {
diff --git a/arch/arm/boot/dts/sama5d3_can.dtsi b/arch/arm/boot/dts/sama5d3_can.dtsi
index eaf41451ad0c..d1660f5945c3 100644
--- a/arch/arm/boot/dts/sama5d3_can.dtsi
+++ b/arch/arm/boot/dts/sama5d3_can.dtsi
@@ -37,13 +37,13 @@
 					can0_clk: can0_clk {
 						#clock-cells = <0>;
 						reg = <40>;
-						atmel,clk-output-range = <0 66000000>;
+						atmel,clk-output-range = <0 83000000>;
 					};
 
 					can1_clk: can1_clk {
 						#clock-cells = <0>;
 						reg = <41>;
-						atmel,clk-output-range = <0 66000000>;
+						atmel,clk-output-range = <0 83000000>;
 					};
 				};
 			};
diff --git a/arch/arm/boot/dts/sama5d3_tcb1.dtsi b/arch/arm/boot/dts/sama5d3_tcb1.dtsi
index 02848453ca0c..80b623c8898d 100644
--- a/arch/arm/boot/dts/sama5d3_tcb1.dtsi
+++ b/arch/arm/boot/dts/sama5d3_tcb1.dtsi
@@ -23,6 +23,7 @@
 					tcb1_clk: tcb1_clk {
 						#clock-cells = <0>;
 						reg = <27>;
+						atmel,clk-output-range = <0 166000000>;
 					};
 				};
 			};
diff --git a/arch/arm/boot/dts/sama5d3_uart.dtsi b/arch/arm/boot/dts/sama5d3_uart.dtsi
index 7a8d4c6115f7..8070ed629178 100644
--- a/arch/arm/boot/dts/sama5d3_uart.dtsi
+++ b/arch/arm/boot/dts/sama5d3_uart.dtsi
@@ -42,13 +42,13 @@
 					uart0_clk: uart0_clk {
 						#clock-cells = <0>;
 						reg = <16>;
-						atmel,clk-output-range = <0 66000000>;
+						atmel,clk-output-range = <0 83000000>;
 					};
 
 					uart1_clk: uart1_clk {
 						#clock-cells = <0>;
 						reg = <17>;
-						atmel,clk-output-range = <0 66000000>;
+						atmel,clk-output-range = <0 83000000>;
 					};
 				};
 			};
diff --git a/arch/arm/include/asm/kvm_emulate.h b/arch/arm/include/asm/kvm_emulate.h
index 853e2becad18..8d704db1ce96 100644
--- a/arch/arm/include/asm/kvm_emulate.h
+++ b/arch/arm/include/asm/kvm_emulate.h
@@ -105,6 +105,11 @@ static inline bool kvm_vcpu_dabt_issext(struct kvm_vcpu *vcpu)
 	return kvm_vcpu_get_hsr(vcpu) & HSR_SSE;
 }
 
+static inline bool kvm_vcpu_dabt_issf(const struct kvm_vcpu *vcpu)
+{
+	return false;
+}
+
 static inline int kvm_vcpu_dabt_get_rd(struct kvm_vcpu *vcpu)
 {
 	return (kvm_vcpu_get_hsr(vcpu) & HSR_SRT_MASK) >> HSR_SRT_SHIFT;
diff --git a/arch/arm/include/asm/kvm_mmio.h b/arch/arm/include/asm/kvm_mmio.h
index adcc0d7d3175..e28cef4beae8 100644
--- a/arch/arm/include/asm/kvm_mmio.h
+++ b/arch/arm/include/asm/kvm_mmio.h
@@ -26,6 +26,8 @@
 struct kvm_decode {
 	unsigned long rt;
 	bool sign_extend;
+	/* Not used on 32-bit arm */
+	bool sixty_four;
 };
 
 /*
diff --git a/arch/arm/kvm/mmio.c b/arch/arm/kvm/mmio.c
index c47f108c2b8a..c480bd438fd0 100644
--- a/arch/arm/kvm/mmio.c
+++ b/arch/arm/kvm/mmio.c
@@ -112,6 +112,9 @@ int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run)
 			data = (data ^ mask) - mask;
 		}
 
+		if (!vcpu->arch.mmio_decode.sixty_four)
+			data = data & 0xffffffff;
+
 		trace_kvm_mmio(KVM_TRACE_MMIO_READ, len, run->mmio.phys_addr,
 			       &data);
 		data = vcpu_data_host_to_guest(vcpu, data, len);
@@ -127,6 +130,7 @@ static int decode_hsr(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
 	unsigned long rt;
 	int len;
 	bool is_write, sign_extend;
+	bool sixty_four;
 
 	if (kvm_vcpu_dabt_isextabt(vcpu)) {
 		/* cache operation on I/O addr, tell guest unsupported */
@@ -146,6 +150,7 @@ static int decode_hsr(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
 
 	is_write = kvm_vcpu_dabt_iswrite(vcpu);
 	sign_extend = kvm_vcpu_dabt_issext(vcpu);
+	sixty_four = kvm_vcpu_dabt_issf(vcpu);
 	rt = kvm_vcpu_dabt_get_rd(vcpu);
 
 	mmio->is_write = is_write;
@@ -153,6 +158,7 @@ static int decode_hsr(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
 	mmio->len = len;
 	vcpu->arch.mmio_decode.sign_extend = sign_extend;
 	vcpu->arch.mmio_decode.rt = rt;
+	vcpu->arch.mmio_decode.sixty_four = sixty_four;
 
 	/*
 	 * The MMIO instruction is emulated and should not be re-executed
diff --git a/arch/arm/mach-tegra/sleep-tegra30.S b/arch/arm/mach-tegra/sleep-tegra30.S
index b16d4a57fa59..ab9a46178367 100644
--- a/arch/arm/mach-tegra/sleep-tegra30.S
+++ b/arch/arm/mach-tegra/sleep-tegra30.S
@@ -378,6 +378,14 @@ ENTRY(tegra30_lp1_reset)
 	pll_locked r1, r0, CLK_RESET_PLLC_BASE
 	pll_locked r1, r0, CLK_RESET_PLLX_BASE
 
+	tegra_get_soc_id TEGRA_APB_MISC_BASE, r1
+	cmp	r1, #TEGRA30
+	beq	1f
+	ldr	r1, [r0, #CLK_RESET_PLLP_BASE]
+	bic	r1, r1, #(1<<31)	@ disable PllP bypass
+	str	r1, [r0, #CLK_RESET_PLLP_BASE]
+1:
+
 	mov32	r7, TEGRA_TMRUS_BASE
 	ldr	r1, [r7]
 	add	r1, r1, #LOCK_DELAY
@@ -637,7 +645,10 @@ ENDPROC(tegra30_lp1_reset)
 	str	r0, [r4, #PMC_PLLP_WB0_OVERRIDE]
 
 	/* disable PLLP, PLLA, PLLC and PLLX */
+	tegra_get_soc_id TEGRA_APB_MISC_BASE, r1
+	cmp	r1, #TEGRA30
 	ldr	r0, [r5, #CLK_RESET_PLLP_BASE]
+	orrne	r0, r0, #(1 << 31)	@ enable PllP bypass on fast cluster
 	bic	r0, r0, #(1 << 30)
 	str	r0, [r5, #CLK_RESET_PLLP_BASE]
 	ldr	r0, [r5, #CLK_RESET_PLLA_BASE]
diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h
index ef490a55cdf1..9e1f3250bd73 100644
--- a/arch/arm64/include/asm/kvm_emulate.h
+++ b/arch/arm64/include/asm/kvm_emulate.h
@@ -140,6 +140,11 @@ static inline bool kvm_vcpu_dabt_issext(const struct kvm_vcpu *vcpu)
 	return !!(kvm_vcpu_get_hsr(vcpu) & ESR_EL2_SSE);
 }
 
+static inline bool kvm_vcpu_dabt_issf(const struct kvm_vcpu *vcpu)
+{
+	return !!(kvm_vcpu_get_hsr(vcpu) & ESR_EL2_SF);
+}
+
 static inline int kvm_vcpu_dabt_get_rd(const struct kvm_vcpu *vcpu)
 {
 	return (kvm_vcpu_get_hsr(vcpu) & ESR_EL2_SRT_MASK) >> ESR_EL2_SRT_SHIFT;
diff --git a/arch/arm64/include/asm/kvm_mmio.h b/arch/arm64/include/asm/kvm_mmio.h
index fc2f689c0694..09923122c4c9 100644
--- a/arch/arm64/include/asm/kvm_mmio.h
+++ b/arch/arm64/include/asm/kvm_mmio.h
@@ -22,13 +22,11 @@
 #include <asm/kvm_asm.h>
 #include <asm/kvm_arm.h>
 
-/*
- * This is annoying. The mmio code requires this, even if we don't
- * need any decoding. To be fixed.
- */
 struct kvm_decode {
 	unsigned long rt;
 	bool sign_extend;
+	/* Witdth of the register accessed by the faulting instruction is 64-bits */
+	bool sixty_four;
 };
 
 /*
diff --git a/arch/ia64/include/asm/io.h b/arch/ia64/include/asm/io.h
index 0d2bcb37ec35..bee0acd52f7e 100644
--- a/arch/ia64/include/asm/io.h
+++ b/arch/ia64/include/asm/io.h
@@ -426,6 +426,7 @@ extern void iounmap (volatile void __iomem *addr);
 extern void __iomem * early_ioremap (unsigned long phys_addr, unsigned long size);
 #define early_memremap(phys_addr, size)        early_ioremap(phys_addr, size)
 extern void early_iounmap (volatile void __iomem *addr, unsigned long size);
+#define early_memunmap(addr, size)             early_iounmap(addr, size)
 static inline void __iomem * ioremap_cache (unsigned long phys_addr, unsigned long size)
 {
 	return ioremap(phys_addr, size);
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 5ff5ab0411b3..d05ea43f24e0 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -89,6 +89,7 @@ config PPC
 	select ARCH_MIGHT_HAVE_PC_SERIO
 	select BINFMT_ELF
 	select OF
+	select OF_DMA_DEFAULT_COHERENT		if !NOT_COHERENT_CACHE
 	select OF_EARLY_FLATTREE
 	select OF_RESERVED_MEM
 	select HAVE_FTRACE_MCOUNT_RECORD
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index eaac0cb57717..5e5ba4a2b11a 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -1316,7 +1316,7 @@ static struct kvm_vcpu *kvmppc_core_vcpu_create_hv(struct kvm *kvm,
 	mutex_unlock(&kvm->lock);
 
 	if (!vcore)
-		goto free_vcpu;
+		goto uninit_vcpu;
 
 	spin_lock(&vcore->lock);
 	++vcore->num_threads;
@@ -1329,6 +1329,8 @@ static struct kvm_vcpu *kvmppc_core_vcpu_create_hv(struct kvm *kvm,
 
 	return vcpu;
 
+uninit_vcpu:
+	kvm_vcpu_uninit(vcpu);
 free_vcpu:
 	kmem_cache_free(kvm_vcpu_cache, vcpu);
 out:
diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c
index 1d9c536e6b16..b484895d4c78 100644
--- a/arch/powerpc/kvm/book3s_pr.c
+++ b/arch/powerpc/kvm/book3s_pr.c
@@ -1346,10 +1346,12 @@ static struct kvm_vcpu *kvmppc_core_vcpu_create_pr(struct kvm *kvm,
 
 	err = kvmppc_mmu_init(vcpu);
 	if (err < 0)
-		goto uninit_vcpu;
+		goto free_shared_page;
 
 	return vcpu;
 
+free_shared_page:
+	free_page((unsigned long)vcpu->arch.shared);
 uninit_vcpu:
 	kvm_vcpu_uninit(vcpu);
 free_shadow_vcpu:
diff --git a/arch/sparc/include/uapi/asm/ipcbuf.h b/arch/sparc/include/uapi/asm/ipcbuf.h
index 66013b4fe10d..58da9c4addb2 100644
--- a/arch/sparc/include/uapi/asm/ipcbuf.h
+++ b/arch/sparc/include/uapi/asm/ipcbuf.h
@@ -14,19 +14,19 @@
 
 struct ipc64_perm
 {
-	__kernel_key_t	key;
-	__kernel_uid_t	uid;
-	__kernel_gid_t	gid;
-	__kernel_uid_t	cuid;
-	__kernel_gid_t	cgid;
+	__kernel_key_t		key;
+	__kernel_uid32_t	uid;
+	__kernel_gid32_t	gid;
+	__kernel_uid32_t	cuid;
+	__kernel_gid32_t	cgid;
 #ifndef __arch64__
-	unsigned short	__pad0;
+	unsigned short		__pad0;
 #endif
-	__kernel_mode_t	mode;
-	unsigned short	__pad1;
-	unsigned short	seq;
-	unsigned long long __unused1;
-	unsigned long long __unused2;
+	__kernel_mode_t		mode;
+	unsigned short		__pad1;
+	unsigned short		seq;
+	unsigned long long	__unused1;
+	unsigned long long	__unused2;
 };
 
 #endif /* __SPARC_IPCBUF_H */
diff --git a/arch/x86/kernel/cpu/tsx.c b/arch/x86/kernel/cpu/tsx.c
index c2a9dd816c5c..9a7983968ba8 100644
--- a/arch/x86/kernel/cpu/tsx.c
+++ b/arch/x86/kernel/cpu/tsx.c
@@ -115,11 +115,12 @@ void __init tsx_init(void)
 		tsx_disable();
 
 		/*
-		 * tsx_disable() will change the state of the
-		 * RTM CPUID bit.  Clear it here since it is now
-		 * expected to be not set.
+		 * tsx_disable() will change the state of the RTM and HLE CPUID
+		 * bits. Clear them here since they are now expected to be not
+		 * set.
 		 */
 		setup_clear_cpu_cap(X86_FEATURE_RTM);
+		setup_clear_cpu_cap(X86_FEATURE_HLE);
 	} else if (tsx_ctrl_state == TSX_CTRL_ENABLE) {
 
 		/*
@@ -131,10 +132,10 @@ void __init tsx_init(void)
 		tsx_enable();
 
 		/*
-		 * tsx_enable() will change the state of the
-		 * RTM CPUID bit.  Force it here since it is now
-		 * expected to be set.
+		 * tsx_enable() will change the state of the RTM and HLE CPUID
+		 * bits. Force them here since they are now expected to be set.
 		 */
 		setup_force_cpu_cap(X86_FEATURE_RTM);
+		setup_force_cpu_cap(X86_FEATURE_HLE);
 	}
 }
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index ede6797ee203..16c267510d28 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -26,6 +26,7 @@
 #include <asm/kvm_emulate.h>
 #include <linux/stringify.h>
 #include <asm/nospec-branch.h>
+#include <linux/nospec.h>
 
 #include "x86.h"
 #include "tss.h"
@@ -4487,10 +4488,15 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
 			}
 			break;
 		case Escape:
-			if (ctxt->modrm > 0xbf)
-				opcode = opcode.u.esc->high[ctxt->modrm - 0xc0];
-			else
+			if (ctxt->modrm > 0xbf) {
+				size_t size = ARRAY_SIZE(opcode.u.esc->high);
+				u32 index = array_index_nospec(
+					ctxt->modrm - 0xc0, size);
+
+				opcode = opcode.u.esc->high[index];
+			} else {
 				opcode = opcode.u.esc->op[(ctxt->modrm >> 3) & 7];
+			}
 			break;
 		default:
 			return EMULATION_FAILED;
diff --git a/arch/x86/kvm/i8259.c b/arch/x86/kvm/i8259.c
index cc31f7c06d3d..08b2ad1df9f8 100644
--- a/arch/x86/kvm/i8259.c
+++ b/arch/x86/kvm/i8259.c
@@ -486,9 +486,11 @@ static int picdev_write(struct kvm_pic *s,
 	switch (addr) {
 	case 0x20:
 	case 0x21:
+		pic_ioport_write(&s->pics[0], addr, data);
+		break;
 	case 0xa0:
 	case 0xa1:
-		pic_ioport_write(&s->pics[addr >> 7], addr, data);
+		pic_ioport_write(&s->pics[1], addr, data);
 		break;
 	case 0x4d0:
 	case 0x4d1:
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index d03a88cb3129..e38d6a7dfbd6 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -35,6 +35,7 @@
 #include <asm/apicdef.h>
 #include <linux/atomic.h>
 #include <linux/jump_label.h>
+#include <linux/nospec.h>
 #include "kvm_cache_regs.h"
 #include "irq.h"
 #include "trace.h"
@@ -1196,15 +1197,20 @@ static int apic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val)
 	case APIC_LVTTHMR:
 	case APIC_LVTPC:
 	case APIC_LVT1:
-	case APIC_LVTERR:
+	case APIC_LVTERR: {
 		/* TODO: Check vector */
+		size_t size;
+		u32 index;
+
 		if (!kvm_apic_sw_enabled(apic))
 			val |= APIC_LVT_MASKED;
-
-		val &= apic_lvt_mask[(reg - APIC_LVTT) >> 4];
+		size = ARRAY_SIZE(apic_lvt_mask);
+		index = array_index_nospec(
+				(reg - APIC_LVTT) >> 4, size);
+		val &= apic_lvt_mask[index];
 		apic_set_reg(apic, reg, val);
-
 		break;
+	}
 
 	case APIC_LVTT:
 		if ((kvm_apic_get_reg(apic, APIC_LVTT) &
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 1faaa78505f4..0566fd97b58e 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -6455,8 +6455,10 @@ static int handle_vmread(struct kvm_vcpu *vcpu)
 		/* _system ok, as nested_vmx_check_permission verified cpl=0 */
 		if (kvm_write_guest_virt_system(vcpu, gva, &field_value,
 						(is_long_mode(vcpu) ? 8 : 4),
-						&e))
+						&e)) {
 			kvm_inject_page_fault(vcpu, &e);
+			return 1;
+		}
 	}
 
 	nested_vmx_succeed(vcpu);
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 9d4d3e0eaa6b..730b3beeda6a 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -48,6 +48,7 @@
 #include <linux/pci.h>
 #include <linux/timekeeper_internal.h>
 #include <linux/pvclock_gtod.h>
+#include <linux/nospec.h>
 #include <trace/events/kvm.h>
 
 #define CREATE_TRACE_POINTS
@@ -82,6 +83,8 @@ u64 __read_mostly efer_reserved_bits = ~((u64)(EFER_SCE | EFER_LME | EFER_LMA));
 static u64 __read_mostly efer_reserved_bits = ~((u64)EFER_SCE);
 #endif
 
+static u64 __read_mostly cr4_reserved_bits = CR4_RESERVED_BITS;
+
 #define VM_STAT(x) offsetof(struct kvm, stat.x), KVM_STAT_VM
 #define VCPU_STAT(x) offsetof(struct kvm_vcpu, stat.x), KVM_STAT_VCPU
 
@@ -660,13 +663,32 @@ int kvm_set_xcr(struct kvm_vcpu *vcpu, u32 index, u64 xcr)
 }
 EXPORT_SYMBOL_GPL(kvm_set_xcr);
 
+static u64 kvm_host_cr4_reserved_bits(struct cpuinfo_x86 *c)
+{
+	u64 reserved_bits = CR4_RESERVED_BITS;
+
+	if (!cpu_has(c, X86_FEATURE_XSAVE))
+		reserved_bits |= X86_CR4_OSXSAVE;
+
+	if (!cpu_has(c, X86_FEATURE_SMEP))
+		reserved_bits |= X86_CR4_SMEP;
+
+	if (!cpu_has(c, X86_FEATURE_SMAP))
+		reserved_bits |= X86_CR4_SMAP;
+
+	if (!cpu_has(c, X86_FEATURE_FSGSBASE))
+		reserved_bits |= X86_CR4_FSGSBASE;
+
+	return reserved_bits;
+}
+
 int kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
 {
 	unsigned long old_cr4 = kvm_read_cr4(vcpu);
 	unsigned long pdptr_bits = X86_CR4_PGE | X86_CR4_PSE | X86_CR4_PAE |
 				   X86_CR4_SMEP | X86_CR4_SMAP;
 
-	if (cr4 & CR4_RESERVED_BITS)
+	if (cr4 & cr4_reserved_bits)
 		return 1;
 
 	if (!guest_cpuid_has_xsave(vcpu) && (cr4 & X86_CR4_OSXSAVE))
@@ -779,9 +801,11 @@ static void kvm_update_dr7(struct kvm_vcpu *vcpu)
 
 static int __kvm_set_dr(struct kvm_vcpu *vcpu, int dr, unsigned long val)
 {
+	size_t size = ARRAY_SIZE(vcpu->arch.db);
+
 	switch (dr) {
 	case 0 ... 3:
-		vcpu->arch.db[dr] = val;
+		vcpu->arch.db[array_index_nospec(dr, size)] = val;
 		if (!(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP))
 			vcpu->arch.eff_db[dr] = val;
 		break;
@@ -826,9 +850,11 @@ EXPORT_SYMBOL_GPL(kvm_set_dr);
 
 static int _kvm_get_dr(struct kvm_vcpu *vcpu, int dr, unsigned long *val)
 {
+	size_t size = ARRAY_SIZE(vcpu->arch.db);
+
 	switch (dr) {
 	case 0 ... 3:
-		*val = vcpu->arch.db[dr];
+		*val = vcpu->arch.db[array_index_nospec(dr, size)];
 		break;
 	case 4:
 		if (kvm_read_cr4_bits(vcpu, X86_CR4_DE))
@@ -1894,8 +1920,11 @@ static int set_msr_mce(struct kvm_vcpu *vcpu, u32 msr, u64 data)
 		break;
 	default:
 		if (msr >= MSR_IA32_MC0_CTL &&
-		    msr < MSR_IA32_MC0_CTL + 4 * bank_num) {
-			u32 offset = msr - MSR_IA32_MC0_CTL;
+		    msr < MSR_IA32_MCx_CTL(bank_num)) {
+			u32 offset = array_index_nospec(
+				msr - MSR_IA32_MC0_CTL,
+				MSR_IA32_MCx_CTL(bank_num) - MSR_IA32_MC0_CTL);
+
 			/* only 0 or all 1s can be written to IA32_MCi_CTL
 			 * some Linux kernels though clear bit 10 in bank 4 to
 			 * workaround a BIOS/GART TBL issue on AMD K8s, ignore
@@ -2255,7 +2284,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 
 	case MSR_IA32_MCG_CTL:
 	case MSR_IA32_MCG_STATUS:
-	case MSR_IA32_MC0_CTL ... MSR_IA32_MC0_CTL + 4 * KVM_MAX_MCE_BANKS - 1:
+	case MSR_IA32_MC0_CTL ... MSR_IA32_MCx_CTL(KVM_MAX_MCE_BANKS) - 1:
 		return set_msr_mce(vcpu, msr, data);
 
 	/* Performance counters are not protected by a CPUID bit,
@@ -2421,8 +2450,11 @@ static int get_msr_mce(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
 		break;
 	default:
 		if (msr >= MSR_IA32_MC0_CTL &&
-		    msr < MSR_IA32_MC0_CTL + 4 * bank_num) {
-			u32 offset = msr - MSR_IA32_MC0_CTL;
+		    msr < MSR_IA32_MCx_CTL(bank_num)) {
+			u32 offset = array_index_nospec(
+				msr - MSR_IA32_MC0_CTL,
+				MSR_IA32_MCx_CTL(bank_num) - MSR_IA32_MC0_CTL);
+
 			data = vcpu->arch.mce_banks[offset];
 			break;
 		}
@@ -2607,7 +2639,7 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 	case MSR_IA32_MCG_CAP:
 	case MSR_IA32_MCG_CTL:
 	case MSR_IA32_MCG_STATUS:
-	case MSR_IA32_MC0_CTL ... MSR_IA32_MC0_CTL + 4 * KVM_MAX_MCE_BANKS - 1:
+	case MSR_IA32_MC0_CTL ... MSR_IA32_MCx_CTL(KVM_MAX_MCE_BANKS) - 1:
 		return get_msr_mce(vcpu, msr_info->index, &msr_info->data);
 	case MSR_K7_CLK_CTL:
 		/*
@@ -5709,14 +5741,12 @@ static void kvm_set_mmio_spte_mask(void)
 	/* Set the present bit. */
 	mask |= 1ull;
 
-#ifdef CONFIG_X86_64
 	/*
 	 * If reserved bit is not supported, clear the present bit to disable
 	 * mmio page fault.
 	 */
 	if (maxphyaddr == 52)
 		mask &= ~1ull;
-#endif
 
 	kvm_mmu_set_mmio_spte_mask(mask);
 }
@@ -7068,8 +7098,7 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
 	kvm_mmu_unload(vcpu);
 	vcpu_put(vcpu);
 
-	fx_free(vcpu);
-	kvm_x86_ops->vcpu_free(vcpu);
+	kvm_arch_vcpu_free(vcpu);
 }
 
 void kvm_vcpu_reset(struct kvm_vcpu *vcpu)
@@ -7220,6 +7249,8 @@ int kvm_arch_hardware_setup(void)
 	if (r != 0)
 		return r;
 
+	cr4_reserved_bits = kvm_host_cr4_reserved_bits(&boot_cpu_data);
+
 	kvm_init_msr_list();
 	return 0;
 }
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 09c8ac286cd5..f7e3bcb01c8c 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -435,7 +435,7 @@ void __init efi_unmap_memmap(void)
 {
 	clear_bit(EFI_MEMMAP, &efi.flags);
 	if (memmap.map) {
-		early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size);
+		early_memunmap(memmap.map, memmap.nr_map * memmap.desc_size);
 		memmap.map = NULL;
 	}
 }
@@ -475,12 +475,12 @@ static int __init efi_systab_init(void *phys)
 			if (!data)
 				return -ENOMEM;
 		}
-		systab64 = early_ioremap((unsigned long)phys,
+		systab64 = early_memremap((unsigned long)phys,
 					 sizeof(*systab64));
 		if (systab64 == NULL) {
 			pr_err("Couldn't map the system table!\n");
 			if (data)
-				early_iounmap(data, sizeof(*data));
+				early_memunmap(data, sizeof(*data));
 			return -ENOMEM;
 		}
 
@@ -512,9 +512,9 @@ static int __init efi_systab_init(void *phys)
 					   systab64->tables;
 		tmp |= data ? data->tables : systab64->tables;
 
-		early_iounmap(systab64, sizeof(*systab64));
+		early_memunmap(systab64, sizeof(*systab64));
 		if (data)
-			early_iounmap(data, sizeof(*data));
+			early_memunmap(data, sizeof(*data));
 #ifdef CONFIG_X86_32
 		if (tmp >> 32) {
 			pr_err("EFI data located above 4GB, disabling EFI.\n");
@@ -524,7 +524,7 @@ static int __init efi_systab_init(void *phys)
 	} else {
 		efi_system_table_32_t *systab32;
 
-		systab32 = early_ioremap((unsigned long)phys,
+		systab32 = early_memremap((unsigned long)phys,
 					 sizeof(*systab32));
 		if (systab32 == NULL) {
 			pr_err("Couldn't map the system table!\n");
@@ -545,7 +545,7 @@ static int __init efi_systab_init(void *phys)
 		efi_systab.nr_tables = systab32->nr_tables;
 		efi_systab.tables = systab32->tables;
 
-		early_iounmap(systab32, sizeof(*systab32));
+		early_memunmap(systab32, sizeof(*systab32));
 	}
 
 	efi.systab = &efi_systab;
@@ -571,7 +571,7 @@ static int __init efi_runtime_init32(void)
 {
 	efi_runtime_services_32_t *runtime;
 
-	runtime = early_ioremap((unsigned long)efi.systab->runtime,
+	runtime = early_memremap((unsigned long)efi.systab->runtime,
 			sizeof(efi_runtime_services_32_t));
 	if (!runtime) {
 		pr_err("Could not map the runtime service table!\n");
@@ -586,7 +586,7 @@ static int __init efi_runtime_init32(void)
 	efi_phys.set_virtual_address_map =
 			(efi_set_virtual_address_map_t *)
 			(unsigned long)runtime->set_virtual_address_map;
-	early_iounmap(runtime, sizeof(efi_runtime_services_32_t));
+	early_memunmap(runtime, sizeof(efi_runtime_services_32_t));
 
 	return 0;
 }
@@ -595,7 +595,7 @@ static int __init efi_runtime_init64(void)
 {
 	efi_runtime_services_64_t *runtime;
 
-	runtime = early_ioremap((unsigned long)efi.systab->runtime,
+	runtime = early_memremap((unsigned long)efi.systab->runtime,
 			sizeof(efi_runtime_services_64_t));
 	if (!runtime) {
 		pr_err("Could not map the runtime service table!\n");
@@ -610,7 +610,7 @@ static int __init efi_runtime_init64(void)
 	efi_phys.set_virtual_address_map =
 			(efi_set_virtual_address_map_t *)
 			(unsigned long)runtime->set_virtual_address_map;
-	early_iounmap(runtime, sizeof(efi_runtime_services_64_t));
+	early_memunmap(runtime, sizeof(efi_runtime_services_64_t));
 
 	return 0;
 }
@@ -641,7 +641,7 @@ static int __init efi_runtime_init(void)
 static int __init efi_memmap_init(void)
 {
 	/* Map the EFI memory map */
-	memmap.map = early_ioremap((unsigned long)memmap.phys_map,
+	memmap.map = early_memremap((unsigned long)memmap.phys_map,
 				   memmap.nr_map * memmap.desc_size);
 	if (memmap.map == NULL) {
 		pr_err("Could not map the memory map!\n");
@@ -718,7 +718,6 @@ void __init efi_init(void)
 	efi_char16_t *c16;
 	char vendor[100] = "unknown";
 	int i = 0;
-	void *tmp;
 
 #ifdef CONFIG_X86_32
 	if (boot_params.efi_info.efi_systab_hi ||
@@ -745,14 +744,16 @@ void __init efi_init(void)
 	/*
 	 * Show what we know for posterity
 	 */
-	c16 = tmp = early_ioremap(efi.systab->fw_vendor, 2);
+	c16 = early_memremap(efi.systab->fw_vendor,
+			     sizeof(vendor) * sizeof(efi_char16_t));
 	if (c16) {
-		for (i = 0; i < sizeof(vendor) - 1 && *c16; ++i)
-			vendor[i] = *c16++;
+		for (i = 0; i < sizeof(vendor) - 1 && c16[i]; ++i)
+			vendor[i] = c16[i];
 		vendor[i] = '\0';
-	} else
+		early_memunmap(c16, sizeof(vendor) * sizeof(efi_char16_t));
+	} else {
 		pr_err("Could not map the firmware vendor!\n");
-	early_iounmap(tmp, 2);
+	}
 
 	pr_info("EFI v%u.%.02u by %s\n",
 		efi.systab->hdr.revision >> 16,
diff --git a/crypto/af_alg.c b/crypto/af_alg.c
index 7f06df512f24..ae17aeb86130 100644
--- a/crypto/af_alg.c
+++ b/crypto/af_alg.c
@@ -136,11 +136,13 @@ void af_alg_release_parent(struct sock *sk)
 	sk = ask->parent;
 	ask = alg_sk(sk);
 
-	lock_sock(sk);
+	local_bh_disable();
+	bh_lock_sock(sk);
 	ask->nokey_refcnt -= nokey;
 	if (!last)
 		last = !--ask->refcnt;
-	release_sock(sk);
+	bh_unlock_sock(sk);
+	local_bh_enable();
 
 	if (last)
 		sock_put(sk);
diff --git a/crypto/algapi.c b/crypto/algapi.c
index 300cafd2228d..ede3aec4ff7c 100644
--- a/crypto/algapi.c
+++ b/crypto/algapi.c
@@ -618,11 +618,9 @@ EXPORT_SYMBOL_GPL(crypto_init_spawn2);
 
 void crypto_drop_spawn(struct crypto_spawn *spawn)
 {
-	if (!spawn->alg)
-		return;
-
 	down_write(&crypto_alg_sem);
-	list_del(&spawn->list);
+	if (spawn->alg)
+		list_del(&spawn->list);
 	up_write(&crypto_alg_sem);
 }
 EXPORT_SYMBOL_GPL(crypto_drop_spawn);
@@ -630,22 +628,16 @@ EXPORT_SYMBOL_GPL(crypto_drop_spawn);
 static struct crypto_alg *crypto_spawn_alg(struct crypto_spawn *spawn)
 {
 	struct crypto_alg *alg;
-	struct crypto_alg *alg2;
 
 	down_read(&crypto_alg_sem);
 	alg = spawn->alg;
-	alg2 = alg;
-	if (alg2)
-		alg2 = crypto_mod_get(alg2);
-	up_read(&crypto_alg_sem);
-
-	if (!alg2) {
-		if (alg)
-			crypto_shoot_alg(alg);
-		return ERR_PTR(-EAGAIN);
+	if (alg && !crypto_mod_get(alg)) {
+		alg->cra_flags |= CRYPTO_ALG_DYING;
+		alg = NULL;
 	}
+	up_read(&crypto_alg_sem);
 
-	return alg;
+	return alg ?: ERR_PTR(-EAGAIN);
 }
 
 struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn, u32 type,
diff --git a/crypto/api.c b/crypto/api.c
index 7db2e89a3114..b16cedc5731a 100644
--- a/crypto/api.c
+++ b/crypto/api.c
@@ -345,13 +345,12 @@ static unsigned int crypto_ctxsize(struct crypto_alg *alg, u32 type, u32 mask)
 	return len;
 }
 
-void crypto_shoot_alg(struct crypto_alg *alg)
+static void crypto_shoot_alg(struct crypto_alg *alg)
 {
 	down_write(&crypto_alg_sem);
 	alg->cra_flags |= CRYPTO_ALG_DYING;
 	up_write(&crypto_alg_sem);
 }
-EXPORT_SYMBOL_GPL(crypto_shoot_alg);
 
 struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type,
 				      u32 mask)
diff --git a/crypto/internal.h b/crypto/internal.h
index bd39bfc92eab..3c15f2b25c99 100644
--- a/crypto/internal.h
+++ b/crypto/internal.h
@@ -88,7 +88,6 @@ void crypto_alg_tested(const char *name, int err);
 void crypto_remove_spawns(struct crypto_alg *alg, struct list_head *list,
 			  struct crypto_alg *nalg);
 void crypto_remove_final(struct list_head *list);
-void crypto_shoot_alg(struct crypto_alg *alg);
 struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type,
 				      u32 mask);
 void *crypto_create_tfm(struct crypto_alg *alg,
diff --git a/crypto/pcrypt.c b/crypto/pcrypt.c
index a96de79498ee..a615ab6e3966 100644
--- a/crypto/pcrypt.c
+++ b/crypto/pcrypt.c
@@ -137,7 +137,6 @@ static void pcrypt_aead_done(struct crypto_async_request *areq, int err)
 	struct padata_priv *padata = pcrypt_request_padata(preq);
 
 	padata->info = err;
-	req->base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
 
 	padata_do_serial(padata);
 }
@@ -552,11 +551,12 @@ static int __init pcrypt_init(void)
 
 static void __exit pcrypt_exit(void)
 {
+	crypto_unregister_template(&pcrypt_tmpl);
+
 	pcrypt_fini_padata(&pencrypt);
 	pcrypt_fini_padata(&pdecrypt);
 
 	kset_unregister(pcrypt_kset);
-	crypto_unregister_template(&pcrypt_tmpl);
 }
 
 module_init(pcrypt_init);
diff --git a/drivers/crypto/picoxcell_crypto.c b/drivers/crypto/picoxcell_crypto.c
index 5da5b98b8f29..8bdd1e641914 100644
--- a/drivers/crypto/picoxcell_crypto.c
+++ b/drivers/crypto/picoxcell_crypto.c
@@ -1690,6 +1690,11 @@ static bool spacc_is_compatible(struct platform_device *pdev,
 	return false;
 }
 
+static void spacc_tasklet_kill(void *data)
+{
+	tasklet_kill(data);
+}
+
 static int spacc_probe(struct platform_device *pdev)
 {
 	int i, err, ret = -EINVAL;
@@ -1730,6 +1735,14 @@ static int spacc_probe(struct platform_device *pdev)
 		return -ENXIO;
 	}
 
+	tasklet_init(&engine->complete, spacc_spacc_complete,
+		     (unsigned long)engine);
+
+	ret = devm_add_action(&pdev->dev, spacc_tasklet_kill,
+			      &engine->complete);
+	if (ret)
+		return ret;
+
 	if (devm_request_irq(&pdev->dev, irq->start, spacc_spacc_irq, 0,
 			     engine->name, engine)) {
 		dev_err(engine->dev, "failed to request IRQ\n");
@@ -1792,8 +1805,6 @@ static int spacc_probe(struct platform_device *pdev)
 	INIT_LIST_HEAD(&engine->completed);
 	INIT_LIST_HEAD(&engine->in_progress);
 	engine->in_flight = 0;
-	tasklet_init(&engine->complete, spacc_spacc_complete,
-		     (unsigned long)engine);
 
 	platform_set_drvdata(pdev, engine);
 
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index d1296babcc18..ad558dda449a 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -295,7 +295,7 @@ int __init efi_config_init(efi_config_table_type_t *arch_tables)
 			if (table64 >> 32) {
 				pr_cont("\n");
 				pr_err("Table located above 4GB, disabling EFI.\n");
-				early_iounmap(config_tables,
+				early_memunmap(config_tables,
 					       efi.systab->nr_tables * sz);
 				return -EINVAL;
 			}
@@ -311,7 +311,7 @@ int __init efi_config_init(efi_config_table_type_t *arch_tables)
 		tablep += sz;
 	}
 	pr_cont("\n");
-	early_iounmap(config_tables, efi.systab->nr_tables * sz);
+	early_memunmap(config_tables, efi.systab->nr_tables * sz);
 
 	set_bit(EFI_CONFIG_TABLES, &efi.flags);
 
diff --git a/drivers/md/persistent-data/dm-space-map-common.c b/drivers/md/persistent-data/dm-space-map-common.c
index aacbe70c2c2e..6ade82751181 100644
--- a/drivers/md/persistent-data/dm-space-map-common.c
+++ b/drivers/md/persistent-data/dm-space-map-common.c
@@ -384,6 +384,33 @@ int sm_ll_find_free_block(struct ll_disk *ll, dm_block_t begin,
 	return -ENOSPC;
 }
 
+int sm_ll_find_common_free_block(struct ll_disk *old_ll, struct ll_disk *new_ll,
+	                         dm_block_t begin, dm_block_t end, dm_block_t *b)
+{
+	int r;
+	uint32_t count;
+
+	do {
+		r = sm_ll_find_free_block(new_ll, begin, new_ll->nr_blocks, b);
+		if (r)
+			break;
+
+		/* double check this block wasn't used in the old transaction */
+		if (*b >= old_ll->nr_blocks)
+			count = 0;
+		else {
+			r = sm_ll_lookup(old_ll, *b, &count);
+			if (r)
+				break;
+
+			if (count)
+				begin = *b + 1;
+		}
+	} while (count);
+
+	return r;
+}
+
 static int sm_ll_mutate(struct ll_disk *ll, dm_block_t b,
 			int (*mutator)(void *context, uint32_t old, uint32_t *new),
 			void *context, enum allocation_event *ev)
diff --git a/drivers/md/persistent-data/dm-space-map-common.h b/drivers/md/persistent-data/dm-space-map-common.h
index b3078d5eda0c..8de63ce39bdd 100644
--- a/drivers/md/persistent-data/dm-space-map-common.h
+++ b/drivers/md/persistent-data/dm-space-map-common.h
@@ -109,6 +109,8 @@ int sm_ll_lookup_bitmap(struct ll_disk *ll, dm_block_t b, uint32_t *result);
 int sm_ll_lookup(struct ll_disk *ll, dm_block_t b, uint32_t *result);
 int sm_ll_find_free_block(struct ll_disk *ll, dm_block_t begin,
 			  dm_block_t end, dm_block_t *result);
+int sm_ll_find_common_free_block(struct ll_disk *old_ll, struct ll_disk *new_ll,
+	                         dm_block_t begin, dm_block_t end, dm_block_t *result);
 int sm_ll_insert(struct ll_disk *ll, dm_block_t b, uint32_t ref_count, enum allocation_event *ev);
 int sm_ll_inc(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev);
 int sm_ll_dec(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev);
diff --git a/drivers/md/persistent-data/dm-space-map-disk.c b/drivers/md/persistent-data/dm-space-map-disk.c
index 8d0a6a23438b..d2487a6efc79 100644
--- a/drivers/md/persistent-data/dm-space-map-disk.c
+++ b/drivers/md/persistent-data/dm-space-map-disk.c
@@ -165,8 +165,10 @@ static int sm_disk_new_block(struct dm_space_map *sm, dm_block_t *b)
 	enum allocation_event ev;
 	struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
 
-	/* FIXME: we should loop round a couple of times */
-	r = sm_ll_find_free_block(&smd->old_ll, smd->begin, smd->old_ll.nr_blocks, b);
+	/*
+	 * Any block we allocate has to be free in both the old and current ll.
+	 */
+	r = sm_ll_find_common_free_block(&smd->old_ll, &smd->ll, smd->begin, smd->ll.nr_blocks, b);
 	if (r)
 		return r;
 
diff --git a/drivers/md/persistent-data/dm-space-map-metadata.c b/drivers/md/persistent-data/dm-space-map-metadata.c
index 35a7ac8499c3..0aed7ec50a95 100644
--- a/drivers/md/persistent-data/dm-space-map-metadata.c
+++ b/drivers/md/persistent-data/dm-space-map-metadata.c
@@ -447,7 +447,10 @@ static int sm_metadata_new_block_(struct dm_space_map *sm, dm_block_t *b)
 	enum allocation_event ev;
 	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
 
-	r = sm_ll_find_free_block(&smm->old_ll, smm->begin, smm->old_ll.nr_blocks, b);
+	/*
+	 * Any block we allocate has to be free in both the old and current ll.
+	 */
+	r = sm_ll_find_common_free_block(&smm->old_ll, &smm->ll, smm->begin, smm->ll.nr_blocks, b);
 	if (r)
 		return r;
 
diff --git a/drivers/media/rc/iguanair.c b/drivers/media/rc/iguanair.c
index 627ddfd61980..611d539ad925 100644
--- a/drivers/media/rc/iguanair.c
+++ b/drivers/media/rc/iguanair.c
@@ -430,6 +430,10 @@ static int iguanair_probe(struct usb_interface *intf,
 	int ret, pipein, pipeout;
 	struct usb_host_interface *idesc;
 
+	idesc = intf->cur_altsetting;
+	if (idesc->desc.bNumEndpoints < 2)
+		return -ENODEV;
+
 	ir = kzalloc(sizeof(*ir), GFP_KERNEL);
 	rc = rc_allocate_device();
 	if (!ir || !rc) {
@@ -444,18 +448,13 @@ static int iguanair_probe(struct usb_interface *intf,
 	ir->urb_in = usb_alloc_urb(0, GFP_KERNEL);
 	ir->urb_out = usb_alloc_urb(0, GFP_KERNEL);
 
-	if (!ir->buf_in || !ir->packet || !ir->urb_in || !ir->urb_out) {
+	if (!ir->buf_in || !ir->packet || !ir->urb_in || !ir->urb_out ||
+	    !usb_endpoint_is_int_in(&idesc->endpoint[0].desc) ||
+	    !usb_endpoint_is_int_out(&idesc->endpoint[1].desc)) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
-	idesc = intf->altsetting;
-
-	if (idesc->desc.bNumEndpoints < 2) {
-		ret = -ENODEV;
-		goto out;
-	}
-
 	ir->rc = rc;
 	ir->dev = &intf->dev;
 	ir->udev = udev;
diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
index 9da63b6ff167..37da5b650523 100644
--- a/drivers/media/usb/uvc/uvc_driver.c
+++ b/drivers/media/usb/uvc/uvc_driver.c
@@ -1369,6 +1369,11 @@ static int uvc_scan_chain_forward(struct uvc_video_chain *chain,
 			break;
 		if (forward == prev)
 			continue;
+		if (forward->chain.next || forward->chain.prev) {
+			uvc_trace(UVC_TRACE_DESCR, "Found reference to "
+				"entity %d already in chain.\n", forward->id);
+			return -EINVAL;
+		}
 
 		switch (UVC_ENTITY_TYPE(forward)) {
 		case UVC_VC_EXTENSION_UNIT:
@@ -1450,6 +1455,13 @@ static int uvc_scan_chain_backward(struct uvc_video_chain *chain,
 				return -1;
 			}
 
+			if (term->chain.next || term->chain.prev) {
+				uvc_trace(UVC_TRACE_DESCR, "Found reference to "
+					"entity %d already in chain.\n",
+					term->id);
+				return -EINVAL;
+			}
+
 			if (uvc_trace_param & UVC_TRACE_PROBE)
 				printk(" %d", term->id);
 
diff --git a/drivers/media/v4l2-core/videobuf-dma-sg.c b/drivers/media/v4l2-core/videobuf-dma-sg.c
index 828e7c10bd70..05410a8d2c8b 100644
--- a/drivers/media/v4l2-core/videobuf-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf-dma-sg.c
@@ -316,8 +316,11 @@ int videobuf_dma_free(struct videobuf_dmabuf *dma)
 	BUG_ON(dma->sglen);
 
 	if (dma->pages) {
-		for (i = 0; i < dma->nr_pages; i++)
+		for (i = 0; i < dma->nr_pages; i++) {
+			if (dma->direction == DMA_FROM_DEVICE)
+				set_page_dirty_lock(dma->pages[i]);
 			page_cache_release(dma->pages[i]);
+		}
 		kfree(dma->pages);
 		dma->pages = NULL;
 	}
diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c
index a55c4fb42b00..cf1e58b73560 100644
--- a/drivers/mmc/host/mmc_spi.c
+++ b/drivers/mmc/host/mmc_spi.c
@@ -1149,17 +1149,22 @@ static void mmc_spi_initsequence(struct mmc_spi_host *host)
 	 * SPI protocol.  Another is that when chipselect is released while
 	 * the card returns BUSY status, the clock must issue several cycles
 	 * with chipselect high before the card will stop driving its output.
+	 *
+	 * SPI_CS_HIGH means "asserted" here. In some cases like when using
+	 * GPIOs for chip select, SPI_CS_HIGH is set but this will be logically
+	 * inverted by gpiolib, so if we want to ascertain to drive it high
+	 * we should toggle the default with an XOR as we do here.
 	 */
-	host->spi->mode |= SPI_CS_HIGH;
+	host->spi->mode ^= SPI_CS_HIGH;
 	if (spi_setup(host->spi) != 0) {
 		/* Just warn; most cards work without it. */
 		dev_warn(&host->spi->dev,
 				"can't change chip-select polarity\n");
-		host->spi->mode &= ~SPI_CS_HIGH;
+		host->spi->mode ^= SPI_CS_HIGH;
 	} else {
 		mmc_spi_readbytes(host, 18);
 
-		host->spi->mode &= ~SPI_CS_HIGH;
+		host->spi->mode ^= SPI_CS_HIGH;
 		if (spi_setup(host->spi) != 0) {
 			/* Wot, we can't get the same setup we had before? */
 			dev_err(&host->spi->dev,
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index cd440dfffad1..16ea3787a02b 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -1450,26 +1450,31 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev)
 	bool do_tx_balance = true;
 	u32 hash_index = 0;
 	const u8 *hash_start = NULL;
-	struct ipv6hdr *ip6hdr;
 
 	skb_reset_mac_header(skb);
 	eth_data = eth_hdr(skb);
 
 	switch (ntohs(skb->protocol)) {
 	case ETH_P_IP: {
-		const struct iphdr *iph = ip_hdr(skb);
+		const struct iphdr *iph;
 
 		if (ether_addr_equal_64bits(eth_data->h_dest, mac_bcast) ||
-		    (iph->daddr == ip_bcast) ||
-		    (iph->protocol == IPPROTO_IGMP)) {
+		    !pskb_network_may_pull(skb, sizeof(*iph))) {
+			do_tx_balance = false;
+			break;
+		}
+		iph = ip_hdr(skb);
+		if (iph->daddr == ip_bcast || iph->protocol == IPPROTO_IGMP) {
 			do_tx_balance = false;
 			break;
 		}
 		hash_start = (char *)&(iph->daddr);
 		hash_size = sizeof(iph->daddr);
-	}
 		break;
-	case ETH_P_IPV6:
+	}
+	case ETH_P_IPV6: {
+		const struct ipv6hdr *ip6hdr;
+
 		/* IPv6 doesn't really use broadcast mac address, but leave
 		 * that here just in case.
 		 */
@@ -1486,7 +1491,11 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev)
 			break;
 		}
 
-		/* Additianally, DAD probes should not be tx-balanced as that
+		if (!pskb_network_may_pull(skb, sizeof(*ip6hdr))) {
+			do_tx_balance = false;
+			break;
+		}
+		/* Additionally, DAD probes should not be tx-balanced as that
 		 * will lead to false positives for duplicate addresses and
 		 * prevent address configuration from working.
 		 */
@@ -1496,17 +1505,26 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev)
 			break;
 		}
 
-		hash_start = (char *)&(ipv6_hdr(skb)->daddr);
-		hash_size = sizeof(ipv6_hdr(skb)->daddr);
+		hash_start = (char *)&ip6hdr->daddr;
+		hash_size = sizeof(ip6hdr->daddr);
 		break;
-	case ETH_P_IPX:
-		if (ipx_hdr(skb)->ipx_checksum != IPX_NO_CHECKSUM) {
+	}
+	case ETH_P_IPX: {
+		const struct ipxhdr *ipxhdr;
+
+		if (pskb_network_may_pull(skb, sizeof(*ipxhdr))) {
+			do_tx_balance = false;
+			break;
+		}
+		ipxhdr = (struct ipxhdr *)skb_network_header(skb);
+
+		if (ipxhdr->ipx_checksum != IPX_NO_CHECKSUM) {
 			/* something is wrong with this packet */
 			do_tx_balance = false;
 			break;
 		}
 
-		if (ipx_hdr(skb)->ipx_type != IPX_TYPE_NCP) {
+		if (ipxhdr->ipx_type != IPX_TYPE_NCP) {
 			/* The only protocol worth balancing in
 			 * this family since it has an "ARP" like
 			 * mechanism
@@ -1515,9 +1533,11 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev)
 			break;
 		}
 
+		eth_data = eth_hdr(skb);
 		hash_start = (char *)eth_data->h_dest;
 		hash_size = ETH_ALEN;
 		break;
+	}
 	case ETH_P_ARP:
 		do_tx_balance = false;
 		if (bond_info->rlb_enabled)
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index a6cf40e62f3a..1b90a6e63edc 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -2524,13 +2524,17 @@ static void gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue)
 
 	while ((skb = tx_queue->tx_skbuff[skb_dirtytx])) {
 		unsigned long flags;
+		bool do_tstamp;
+
+		do_tstamp = (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) &&
+			    priv->hwts_tx_en;
 
 		frags = skb_shinfo(skb)->nr_frags;
 
 		/* When time stamping, one additional TxBD must be freed.
 		 * Also, we need to dma_unmap_single() the TxPAL.
 		 */
-		if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS))
+		if (unlikely(do_tstamp))
 			nr_txbds = frags + 2;
 		else
 			nr_txbds = frags + 1;
@@ -2544,7 +2548,7 @@ static void gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue)
 		    (lstatus & BD_LENGTH_MASK))
 			break;
 
-		if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) {
+		if (unlikely(do_tstamp)) {
 			next = next_txbd(bdp, base, tx_ring_size);
 			buflen = next->length + GMAC_FCB_LEN + GMAC_TXPAL_LEN;
 		} else
@@ -2553,7 +2557,7 @@ static void gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue)
 		dma_unmap_single(priv->dev, bdp->bufPtr,
 				 buflen, DMA_TO_DEVICE);
 
-		if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) {
+		if (unlikely(do_tstamp)) {
 			struct skb_shared_hwtstamps shhwtstamps;
 			u64 *ns = (u64*) (((u32)skb->data + 0x10) & ~0x7);
 
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
index 2bb8dd09fec2..abe99aa6b002 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -1141,7 +1141,7 @@ static void ath9k_hif_usb_firmware_cb(const struct firmware *fw, void *context)
 static int send_eject_command(struct usb_interface *interface)
 {
 	struct usb_device *udev = interface_to_usbdev(interface);
-	struct usb_host_interface *iface_desc = &interface->altsetting[0];
+	struct usb_host_interface *iface_desc = interface->cur_altsetting;
 	struct usb_endpoint_descriptor *endpoint;
 	unsigned char *cmd;
 	u8 bulk_out_ep;
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index f93bdba6901c..8a1d1e480c9a 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -1971,7 +1971,10 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
 			if (brcmf_sdio_hdparse(bus, bus->rxhdr, &rd_new,
 					       BRCMF_SDIO_FT_NORMAL)) {
 				rd->len = 0;
+				brcmf_sdio_rxfail(bus, true, true);
+				sdio_release_host(bus->sdiodev->func[1]);
 				brcmu_pkt_buf_free_skb(pkt);
+				continue;
 			}
 			bus->sdcnt.rx_readahead_cnt++;
 			if (rd->len != roundup(rd_new.len, 16)) {
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
index f245a39f612c..a31458c6f7a3 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
@@ -41,7 +41,7 @@
 
 #define CONFIGDESC(usb)         (&((usb)->actconfig)->desc)
 #define IFPTR(usb, idx)         ((usb)->actconfig->interface[(idx)])
-#define IFALTS(usb, idx)        (IFPTR((usb), (idx))->altsetting[0])
+#define IFALTS(usb, idx)        (*IFPTR((usb), (idx))->cur_altsetting)
 #define IFDESC(usb, idx)        IFALTS((usb), (idx)).desc
 #define IFEPDESC(usb, idx, ep)  (IFALTS((usb), (idx)).endpoint[(ep)]).desc
 
@@ -365,6 +365,7 @@ brcmf_usbdev_qinit(struct list_head *q, int qsize)
 			usb_free_urb(req->urb);
 		list_del(q->next);
 	}
+	kfree(reqs);
 	return NULL;
 
 }
diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c
index ecc674627e6e..eb22eea328a9 100644
--- a/drivers/net/wireless/iwlegacy/common.c
+++ b/drivers/net/wireless/iwlegacy/common.c
@@ -717,7 +717,7 @@ il_eeprom_init(struct il_priv *il)
 	u32 gp = _il_rd(il, CSR_EEPROM_GP);
 	int sz;
 	int ret;
-	u16 addr;
+	int addr;
 
 	/* allocate eeprom */
 	sz = il->cfg->eeprom_size;
diff --git a/drivers/net/wireless/orinoco/orinoco_usb.c b/drivers/net/wireless/orinoco/orinoco_usb.c
index c90939ced0e4..f97af26e86d6 100644
--- a/drivers/net/wireless/orinoco/orinoco_usb.c
+++ b/drivers/net/wireless/orinoco/orinoco_usb.c
@@ -1602,9 +1602,9 @@ static int ezusb_probe(struct usb_interface *interface,
 	/* set up the endpoint information */
 	/* check out the endpoints */
 
-	iface_desc = &interface->altsetting[0].desc;
+	iface_desc = &interface->cur_altsetting->desc;
 	for (i = 0; i < iface_desc->bNumEndpoints; ++i) {
-		ep = &interface->altsetting[0].endpoint[i].desc;
+		ep = &interface->cur_altsetting->endpoint[i].desc;
 
 		if (((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
 		     == USB_DIR_IN) &&
diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c
index 4c46e5631e2f..16f83f6c1b75 100644
--- a/drivers/net/wireless/rsi/rsi_91x_usb.c
+++ b/drivers/net/wireless/rsi/rsi_91x_usb.c
@@ -103,7 +103,7 @@ static int rsi_find_bulk_in_and_out_endpoints(struct usb_interface *interface,
 	__le16 buffer_size;
 	int ii, bep_found = 0;
 
-	iface_desc = &(interface->altsetting[0]);
+	iface_desc = interface->cur_altsetting;
 
 	for (ii = 0; ii < iface_desc->desc.bNumEndpoints; ++ii) {
 		endpoint = &(iface_desc->endpoint[ii].desc);
@@ -245,6 +245,14 @@ static void rsi_rx_done_handler(struct urb *urb)
 	rsi_set_event(&dev->rx_thread.event);
 }
 
+static void rsi_rx_urb_kill(struct rsi_hw *adapter)
+{
+	struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
+	struct urb *urb = dev->rx_usb_urb[0];
+
+	usb_kill_urb(urb);
+}
+
 /**
  * rsi_rx_urb_submit() - This function submits the given URB to the USB stack.
  * @adapter: Pointer to the adapter structure.
@@ -510,6 +518,8 @@ static void rsi_disconnect(struct usb_interface *pfunction)
 	if (!adapter)
 		return;
 
+	rsi_rx_urb_kill(adapter);
+
 	rsi_mac80211_detach(adapter);
 	rsi_deinit_usb_interface(adapter);
 	rsi_91x_deinit(adapter);
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
index 8d621ee5f349..d51557809c60 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.c
+++ b/drivers/net/wireless/zd1211rw/zd_usb.c
@@ -1272,7 +1272,7 @@ static void print_id(struct usb_device *udev)
 static int eject_installer(struct usb_interface *intf)
 {
 	struct usb_device *udev = interface_to_usbdev(intf);
-	struct usb_host_interface *iface_desc = &intf->altsetting[0];
+	struct usb_host_interface *iface_desc = intf->cur_altsetting;
 	struct usb_endpoint_descriptor *endpoint;
 	unsigned char *cmd;
 	u8 bulk_out_ep;
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index 2dcb0541012d..a3bec421551e 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -78,4 +78,8 @@ config OF_RESERVED_MEM
 	help
 	  Helpers to allow for reservation of memory regions
 
+config OF_DMA_DEFAULT_COHERENT
+	# arches should select this if DMA is coherent by default for OF devices
+	bool
+
 endmenu # OF
diff --git a/drivers/of/address.c b/drivers/of/address.c
index 01570bf23842..2f108ab4e7f6 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -812,12 +812,16 @@ EXPORT_SYMBOL_GPL(of_dma_get_range);
  * @np:	device node
  *
  * It returns true if "dma-coherent" property was found
- * for this device in DT.
+ * for this device in the DT, or if DMA is coherent by
+ * default for OF devices on the current platform.
  */
 bool of_dma_is_coherent(struct device_node *np)
 {
 	struct device_node *node = of_node_get(np);
 
+	if (IS_ENABLED(CONFIG_OF_DMA_DEFAULT_COHERENT))
+		return true;
+
 	while (node) {
 		if (of_property_read_bool(node, "dma-coherent")) {
 			of_node_put(node);
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 8c7496928fb8..5946b071fdcf 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -1650,12 +1650,18 @@ void pci_assign_unassigned_root_bus_resources(struct pci_bus *bus)
 	/* restore size and flags */
 	list_for_each_entry(fail_res, &fail_head, list) {
 		struct resource *res = fail_res->res;
+		int idx;
 
 		res->start = fail_res->start;
 		res->end = fail_res->end;
 		res->flags = fail_res->flags;
-		if (fail_res->dev->subordinate)
-			res->flags = 0;
+
+		if (pci_is_bridge(fail_res->dev)) {
+			idx = res - &fail_res->dev->resource[0];
+			if (idx >= PCI_BRIDGE_RESOURCES &&
+			    idx <= PCI_BRIDGE_RESOURCE_END)
+				res->flags = 0;
+		}
 	}
 	free_list(&fail_head);
 
@@ -1716,12 +1722,18 @@ void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge)
 	/* restore size and flags */
 	list_for_each_entry(fail_res, &fail_head, list) {
 		struct resource *res = fail_res->res;
+		int idx;
 
 		res->start = fail_res->start;
 		res->end = fail_res->end;
 		res->flags = fail_res->flags;
-		if (fail_res->dev->subordinate)
-			res->flags = 0;
+
+		if (pci_is_bridge(fail_res->dev)) {
+			idx = res - &fail_res->dev->resource[0];
+			if (idx >= PCI_BRIDGE_RESOURCES &&
+			    idx <= PCI_BRIDGE_RESOURCE_END)
+				res->flags = 0;
+		}
 	}
 	free_list(&fail_head);
 
diff --git a/drivers/power/sbs-battery.c b/drivers/power/sbs-battery.c
index b5f2a76b6cdf..32553c23d467 100644
--- a/drivers/power/sbs-battery.c
+++ b/drivers/power/sbs-battery.c
@@ -400,7 +400,7 @@ static int sbs_get_battery_capacity(struct i2c_client *client,
 		mode = BATTERY_MODE_AMPS;
 
 	mode = sbs_set_battery_mode(client, mode);
-	if (mode < 0)
+	if ((int)mode < 0)
 		return mode;
 
 	ret = sbs_read_word_data(client, sbs_data[reg_offset].addr);
diff --git a/drivers/rtc/rtc-hym8563.c b/drivers/rtc/rtc-hym8563.c
index 280584b2813b..93ac58d11f3d 100644
--- a/drivers/rtc/rtc-hym8563.c
+++ b/drivers/rtc/rtc-hym8563.c
@@ -105,7 +105,7 @@ static int hym8563_rtc_read_time(struct device *dev, struct rtc_time *tm)
 
 	if (!hym8563->valid) {
 		dev_warn(&client->dev, "no valid clock/calendar values available\n");
-		return -EPERM;
+		return -EINVAL;
 	}
 
 	ret = i2c_smbus_read_i2c_block_data(client, HYM8563_SEC, 7, buf);
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 50f5e6043268..f9054cce41be 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -5388,9 +5388,8 @@ qla2x00_dump_mctp_data(scsi_qla_host_t *vha, dma_addr_t req_dma, uint32_t addr,
 	mcp->mb[7] = LSW(MSD(req_dma));
 	mcp->mb[8] = MSW(addr);
 	/* Setting RAM ID to valid */
-	mcp->mb[10] |= BIT_7;
 	/* For MCTP RAM ID is 0x40 */
-	mcp->mb[10] |= 0x40;
+	mcp->mb[10] = BIT_7 | 0x40;
 
 	mcp->out_mb |= MBX_10|MBX_8|MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|
 	    MBX_0;
diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c
index 66e9e5196c8c..b3e697d5b596 100644
--- a/drivers/spi/spi-dw.c
+++ b/drivers/spi/spi-dw.c
@@ -182,9 +182,11 @@ static inline u32 rx_max(struct dw_spi *dws)
 
 static void dw_writer(struct dw_spi *dws)
 {
-	u32 max = tx_max(dws);
+	u32 max;
 	u16 txw = 0;
 
+	spin_lock(&dws->buf_lock);
+	max = tx_max(dws);
 	while (max--) {
 		/* Set the tx word if the transfer's original "tx" is not null */
 		if (dws->tx_end - dws->len) {
@@ -196,13 +198,16 @@ static void dw_writer(struct dw_spi *dws)
 		dw_writew(dws, DW_SPI_DR, txw);
 		dws->tx += dws->n_bytes;
 	}
+	spin_unlock(&dws->buf_lock);
 }
 
 static void dw_reader(struct dw_spi *dws)
 {
-	u32 max = rx_max(dws);
+	u32 max;
 	u16 rxw;
 
+	spin_lock(&dws->buf_lock);
+	max = rx_max(dws);
 	while (max--) {
 		rxw = dw_readw(dws, DW_SPI_DR);
 		/* Care rx only if the transfer's original "rx" is not null */
@@ -214,6 +219,7 @@ static void dw_reader(struct dw_spi *dws)
 		}
 		dws->rx += dws->n_bytes;
 	}
+	spin_unlock(&dws->buf_lock);
 }
 
 static void *next_transfer(struct dw_spi *dws)
@@ -368,6 +374,7 @@ static void pump_transfers(unsigned long data)
 	struct spi_transfer *previous = NULL;
 	struct spi_device *spi = NULL;
 	struct chip_data *chip = NULL;
+	unsigned long flags;
 	u8 bits = 0;
 	u8 imask = 0;
 	u8 cs_change = 0;
@@ -406,6 +413,7 @@ static void pump_transfers(unsigned long data)
 	dws->dma_width = chip->dma_width;
 	dws->cs_control = chip->cs_control;
 
+	spin_lock_irqsave(&dws->buf_lock, flags);
 	dws->rx_dma = transfer->rx_dma;
 	dws->tx_dma = transfer->tx_dma;
 	dws->tx = (void *)transfer->tx_buf;
@@ -415,6 +423,7 @@ static void pump_transfers(unsigned long data)
 	dws->len = dws->cur_transfer->len;
 	if (chip != dws->prev_chip)
 		cs_change = 1;
+	spin_unlock_irqrestore(&dws->buf_lock, flags);
 
 	cr0 = chip->cr0;
 
@@ -651,6 +660,7 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
 	dws->dma_addr = (dma_addr_t)(dws->paddr + 0x60);
 	snprintf(dws->name, sizeof(dws->name), "dw_spi%d",
 			dws->bus_num);
+	spin_lock_init(&dws->buf_lock);
 
 	ret = request_irq(dws->irq, dw_spi_irq, IRQF_SHARED, dws->name, dws);
 	if (ret < 0) {
diff --git a/drivers/spi/spi-dw.h b/drivers/spi/spi-dw.h
index 6d2acad34f64..be4119a2159b 100644
--- a/drivers/spi/spi-dw.h
+++ b/drivers/spi/spi-dw.h
@@ -116,6 +116,7 @@ struct dw_spi {
 	size_t			len;
 	void			*tx;
 	void			*tx_end;
+	spinlock_t		buf_lock;
 	void			*rx;
 	void			*rx_end;
 	int			dma_mapped;
diff --git a/drivers/staging/wlan-ng/prism2mgmt.c b/drivers/staging/wlan-ng/prism2mgmt.c
index d110b362c3bd..68465e7343ef 100644
--- a/drivers/staging/wlan-ng/prism2mgmt.c
+++ b/drivers/staging/wlan-ng/prism2mgmt.c
@@ -939,7 +939,7 @@ int prism2mgmt_flashdl_state(wlandevice_t *wlandev, void *msgp)
 		}
 	}
 
-	return 0;
+	return result;
 }
 
 /*----------------------------------------------------------------
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 52b30c5b000e..b489be926ebd 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -614,6 +614,9 @@ static void dwc3_core_exit_mode(struct dwc3 *dwc)
 		/* do nothing */
 		break;
 	}
+
+	/* de-assert DRVVBUS for HOST and OTG mode */
+	dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);
 }
 
 #define DWC3_ALIGN_MASK		(16 - 1)
diff --git a/drivers/usb/gadget/f_ecm.c b/drivers/usb/gadget/f_ecm.c
index 798760fa7e70..637f631a66a4 100644
--- a/drivers/usb/gadget/f_ecm.c
+++ b/drivers/usb/gadget/f_ecm.c
@@ -56,6 +56,7 @@ struct f_ecm {
 	struct usb_ep			*notify;
 	struct usb_request		*notify_req;
 	u8				notify_state;
+	atomic_t			notify_count;
 	bool				is_open;
 
 	/* FIXME is_open needs some irq-ish locking
@@ -384,7 +385,7 @@ static void ecm_do_notify(struct f_ecm *ecm)
 	int				status;
 
 	/* notification already in flight? */
-	if (!req)
+	if (atomic_read(&ecm->notify_count))
 		return;
 
 	event = req->buf;
@@ -424,10 +425,10 @@ static void ecm_do_notify(struct f_ecm *ecm)
 	event->bmRequestType = 0xA1;
 	event->wIndex = cpu_to_le16(ecm->ctrl_id);
 
-	ecm->notify_req = NULL;
+	atomic_inc(&ecm->notify_count);
 	status = usb_ep_queue(ecm->notify, req, GFP_ATOMIC);
 	if (status < 0) {
-		ecm->notify_req = req;
+		atomic_dec(&ecm->notify_count);
 		DBG(cdev, "notify --> %d\n", status);
 	}
 }
@@ -452,17 +453,19 @@ static void ecm_notify_complete(struct usb_ep *ep, struct usb_request *req)
 	switch (req->status) {
 	case 0:
 		/* no fault */
+		atomic_dec(&ecm->notify_count);
 		break;
 	case -ECONNRESET:
 	case -ESHUTDOWN:
+		atomic_set(&ecm->notify_count, 0);
 		ecm->notify_state = ECM_NOTIFY_NONE;
 		break;
 	default:
 		DBG(cdev, "event %02x --> %d\n",
 			event->bNotificationType, req->status);
+		atomic_dec(&ecm->notify_count);
 		break;
 	}
-	ecm->notify_req = req;
 	ecm_do_notify(ecm);
 }
 
@@ -922,6 +925,11 @@ static void ecm_unbind(struct usb_configuration *c, struct usb_function *f)
 
 	usb_free_all_descriptors(f);
 
+	if (atomic_read(&ecm->notify_count)) {
+		usb_ep_dequeue(ecm->notify, ecm->notify_req);
+		atomic_set(&ecm->notify_count, 0);
+	}
+
 	kfree(ecm->notify_req->buf);
 	usb_ep_free_request(ecm->notify, ecm->notify_req);
 }
diff --git a/drivers/usb/gadget/f_ncm.c b/drivers/usb/gadget/f_ncm.c
index a9499fd30792..3639d110703f 100644
--- a/drivers/usb/gadget/f_ncm.c
+++ b/drivers/usb/gadget/f_ncm.c
@@ -57,6 +57,7 @@ struct f_ncm {
 	struct usb_ep			*notify;
 	struct usb_request		*notify_req;
 	u8				notify_state;
+	atomic_t			notify_count;
 	bool				is_open;
 
 	const struct ndp_parser_opts	*parser_opts;
@@ -460,7 +461,7 @@ static void ncm_do_notify(struct f_ncm *ncm)
 	int				status;
 
 	/* notification already in flight? */
-	if (!req)
+	if (atomic_read(&ncm->notify_count))
 		return;
 
 	event = req->buf;
@@ -500,7 +501,8 @@ static void ncm_do_notify(struct f_ncm *ncm)
 	event->bmRequestType = 0xA1;
 	event->wIndex = cpu_to_le16(ncm->ctrl_id);
 
-	ncm->notify_req = NULL;
+	atomic_inc(&ncm->notify_count);
+
 	/*
 	 * In double buffering if there is a space in FIFO,
 	 * completion callback can be called right after the call,
@@ -510,7 +512,7 @@ static void ncm_do_notify(struct f_ncm *ncm)
 	status = usb_ep_queue(ncm->notify, req, GFP_ATOMIC);
 	spin_lock(&ncm->lock);
 	if (status < 0) {
-		ncm->notify_req = req;
+		atomic_dec(&ncm->notify_count);
 		DBG(cdev, "notify --> %d\n", status);
 	}
 }
@@ -545,17 +547,19 @@ static void ncm_notify_complete(struct usb_ep *ep, struct usb_request *req)
 	case 0:
 		VDBG(cdev, "Notification %02x sent\n",
 		     event->bNotificationType);
+		atomic_dec(&ncm->notify_count);
 		break;
 	case -ECONNRESET:
 	case -ESHUTDOWN:
+		atomic_set(&ncm->notify_count, 0);
 		ncm->notify_state = NCM_NOTIFY_NONE;
 		break;
 	default:
 		DBG(cdev, "event %02x --> %d\n",
 			event->bNotificationType, req->status);
+		atomic_dec(&ncm->notify_count);
 		break;
 	}
-	ncm->notify_req = req;
 	ncm_do_notify(ncm);
 	spin_unlock(&ncm->lock);
 }
@@ -1382,6 +1386,11 @@ static void ncm_unbind(struct usb_configuration *c, struct usb_function *f)
 
 	usb_free_all_descriptors(f);
 
+	if (atomic_read(&ncm->notify_count)) {
+		usb_ep_dequeue(ncm->notify, ncm->notify_req);
+		atomic_set(&ncm->notify_count, 0);
+	}
+
 	kfree(ncm->notify_req->buf);
 	usb_ep_free_request(ncm->notify, ncm->notify_req);
 }
diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c
index f9734a96d516..a3e3b4703f38 100644
--- a/drivers/usb/serial/ir-usb.c
+++ b/drivers/usb/serial/ir-usb.c
@@ -49,9 +49,10 @@ static int buffer_size;
 static int xbof = -1;
 
 static int  ir_startup (struct usb_serial *serial);
-static int  ir_open(struct tty_struct *tty, struct usb_serial_port *port);
-static int ir_prepare_write_buffer(struct usb_serial_port *port,
-						void *dest, size_t size);
+static int ir_write(struct tty_struct *tty, struct usb_serial_port *port,
+		const unsigned char *buf, int count);
+static int ir_write_room(struct tty_struct *tty);
+static void ir_write_bulk_callback(struct urb *urb);
 static void ir_process_read_urb(struct urb *urb);
 static void ir_set_termios(struct tty_struct *tty,
 		struct usb_serial_port *port, struct ktermios *old_termios);
@@ -81,8 +82,9 @@ static struct usb_serial_driver ir_device = {
 	.num_ports		= 1,
 	.set_termios		= ir_set_termios,
 	.attach			= ir_startup,
-	.open			= ir_open,
-	.prepare_write_buffer	= ir_prepare_write_buffer,
+	.write			= ir_write,
+	.write_room		= ir_write_room,
+	.write_bulk_callback	= ir_write_bulk_callback,
 	.process_read_urb	= ir_process_read_urb,
 };
 
@@ -199,6 +201,9 @@ static int ir_startup(struct usb_serial *serial)
 	struct usb_irda_cs_descriptor *irda_desc;
 	int rates;
 
+	if (serial->num_bulk_in < 1 || serial->num_bulk_out < 1)
+		return -ENODEV;
+
 	irda_desc = irda_usb_find_class_desc(serial, 0);
 	if (!irda_desc) {
 		dev_err(&serial->dev->dev,
@@ -255,35 +260,102 @@ static int ir_startup(struct usb_serial *serial)
 	return 0;
 }
 
-static int ir_open(struct tty_struct *tty, struct usb_serial_port *port)
+static int ir_write(struct tty_struct *tty, struct usb_serial_port *port,
+		const unsigned char *buf, int count)
 {
-	int i;
+	struct urb *urb = NULL;
+	unsigned long flags;
+	int ret;
 
-	for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i)
-		port->write_urbs[i]->transfer_flags = URB_ZERO_PACKET;
+	if (port->bulk_out_size == 0)
+		return -EINVAL;
 
-	/* Start reading from the device */
-	return usb_serial_generic_open(tty, port);
-}
+	if (count == 0)
+		return 0;
 
-static int ir_prepare_write_buffer(struct usb_serial_port *port,
-						void *dest, size_t size)
-{
-	unsigned char *buf = dest;
-	int count;
+	count = min(count, port->bulk_out_size - 1);
+
+	spin_lock_irqsave(&port->lock, flags);
+	if (__test_and_clear_bit(0, &port->write_urbs_free)) {
+		urb = port->write_urbs[0];
+		port->tx_bytes += count;
+	}
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	if (!urb)
+		return 0;
 
 	/*
 	 * The first byte of the packet we send to the device contains an
-	 * inbound header which indicates an additional number of BOFs and
+	 * outbound header which indicates an additional number of BOFs and
 	 * a baud rate change.
 	 *
 	 * See section 5.4.2.2 of the USB IrDA spec.
 	 */
-	*buf = ir_xbof | ir_baud;
+	*(u8 *)urb->transfer_buffer = ir_xbof | ir_baud;
+
+	memcpy(urb->transfer_buffer + 1, buf, count);
+
+	urb->transfer_buffer_length = count + 1;
+	urb->transfer_flags = URB_ZERO_PACKET;
+
+	ret = usb_submit_urb(urb, GFP_ATOMIC);
+	if (ret) {
+		dev_err(&port->dev, "failed to submit write urb: %d\n", ret);
+
+		spin_lock_irqsave(&port->lock, flags);
+		__set_bit(0, &port->write_urbs_free);
+		port->tx_bytes -= count;
+		spin_unlock_irqrestore(&port->lock, flags);
+
+		return ret;
+	}
+
+	return count;
+}
+
+static void ir_write_bulk_callback(struct urb *urb)
+{
+	struct usb_serial_port *port = urb->context;
+	int status = urb->status;
+	unsigned long flags;
+
+	spin_lock_irqsave(&port->lock, flags);
+	__set_bit(0, &port->write_urbs_free);
+	port->tx_bytes -= urb->transfer_buffer_length - 1;
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	switch (status) {
+	case 0:
+		break;
+	case -ENOENT:
+	case -ECONNRESET:
+	case -ESHUTDOWN:
+		dev_dbg(&port->dev, "write urb stopped: %d\n", status);
+		return;
+	case -EPIPE:
+		dev_err(&port->dev, "write urb stopped: %d\n", status);
+		return;
+	default:
+		dev_err(&port->dev, "nonzero write-urb status: %d\n", status);
+		break;
+	}
+
+	usb_serial_port_softint(port);
+}
+
+static int ir_write_room(struct tty_struct *tty)
+{
+	struct usb_serial_port *port = tty->driver_data;
+	int count = 0;
+
+	if (port->bulk_out_size == 0)
+		return 0;
+
+	if (test_bit(0, &port->write_urbs_free))
+		count = port->bulk_out_size - 1;
 
-	count = kfifo_out_locked(&port->write_fifo, buf + 1, size - 1,
-								&port->lock);
-	return count + 1;
+	return count;
 }
 
 static void ir_process_read_urb(struct urb *urb)
@@ -336,34 +408,34 @@ static void ir_set_termios(struct tty_struct *tty,
 
 	switch (baud) {
 	case 2400:
-		ir_baud = USB_IRDA_BR_2400;
+		ir_baud = USB_IRDA_LS_2400;
 		break;
 	case 9600:
-		ir_baud = USB_IRDA_BR_9600;
+		ir_baud = USB_IRDA_LS_9600;
 		break;
 	case 19200:
-		ir_baud = USB_IRDA_BR_19200;
+		ir_baud = USB_IRDA_LS_19200;
 		break;
 	case 38400:
-		ir_baud = USB_IRDA_BR_38400;
+		ir_baud = USB_IRDA_LS_38400;
 		break;
 	case 57600:
-		ir_baud = USB_IRDA_BR_57600;
+		ir_baud = USB_IRDA_LS_57600;
 		break;
 	case 115200:
-		ir_baud = USB_IRDA_BR_115200;
+		ir_baud = USB_IRDA_LS_115200;
 		break;
 	case 576000:
-		ir_baud = USB_IRDA_BR_576000;
+		ir_baud = USB_IRDA_LS_576000;
 		break;
 	case 1152000:
-		ir_baud = USB_IRDA_BR_1152000;
+		ir_baud = USB_IRDA_LS_1152000;
 		break;
 	case 4000000:
-		ir_baud = USB_IRDA_BR_4000000;
+		ir_baud = USB_IRDA_LS_4000000;
 		break;
 	default:
-		ir_baud = USB_IRDA_BR_9600;
+		ir_baud = USB_IRDA_LS_9600;
 		baud = 9600;
 	}
 
diff --git a/drivers/video/fbdev/pxa168fb.c b/drivers/video/fbdev/pxa168fb.c
index c95b9e46d48f..d24018124d11 100644
--- a/drivers/video/fbdev/pxa168fb.c
+++ b/drivers/video/fbdev/pxa168fb.c
@@ -772,8 +772,8 @@ static int pxa168fb_probe(struct platform_device *pdev)
 failed_free_clk:
 	clk_disable(fbi->clk);
 failed_free_fbmem:
-	dma_free_coherent(fbi->dev, info->fix.smem_len,
-			info->screen_base, fbi->fb_start_dma);
+	dma_free_writecombine(fbi->dev, info->fix.smem_len,
+			      info->screen_base, fbi->fb_start_dma);
 failed_free_info:
 	kfree(info);
 failed_put_clk:
@@ -809,7 +809,7 @@ static int pxa168fb_remove(struct platform_device *pdev)
 
 	irq = platform_get_irq(pdev, 0);
 
-	dma_free_writecombine(fbi->dev, PAGE_ALIGN(info->fix.smem_len),
+	dma_free_writecombine(fbi->dev, info->fix.smem_len,
 				info->screen_base, info->fix.smem_start);
 
 	clk_disable(fbi->clk);
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 4d1766e5438a..f33fe516667e 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -365,12 +365,10 @@ u64 btrfs_get_tree_mod_seq(struct btrfs_fs_info *fs_info,
 			   struct seq_list *elem)
 {
 	tree_mod_log_write_lock(fs_info);
-	spin_lock(&fs_info->tree_mod_seq_lock);
 	if (!elem->seq) {
 		elem->seq = btrfs_inc_tree_mod_seq(fs_info);
 		list_add_tail(&elem->list, &fs_info->tree_mod_seq_list);
 	}
-	spin_unlock(&fs_info->tree_mod_seq_lock);
 	tree_mod_log_write_unlock(fs_info);
 
 	return elem->seq;
@@ -390,7 +388,7 @@ void btrfs_put_tree_mod_seq(struct btrfs_fs_info *fs_info,
 	if (!seq_putting)
 		return;
 
-	spin_lock(&fs_info->tree_mod_seq_lock);
+	tree_mod_log_write_lock(fs_info);
 	list_del(&elem->list);
 	elem->seq = 0;
 
@@ -401,19 +399,17 @@ void btrfs_put_tree_mod_seq(struct btrfs_fs_info *fs_info,
 				 * blocker with lower sequence number exists, we
 				 * cannot remove anything from the log
 				 */
-				spin_unlock(&fs_info->tree_mod_seq_lock);
+				tree_mod_log_write_unlock(fs_info);
 				return;
 			}
 			min_seq = cur_elem->seq;
 		}
 	}
-	spin_unlock(&fs_info->tree_mod_seq_lock);
 
 	/*
 	 * anything that's lower than the lowest existing (read: blocked)
 	 * sequence number can be removed from the tree.
 	 */
-	tree_mod_log_write_lock(fs_info);
 	tm_root = &fs_info->tree_mod_log;
 	for (node = rb_first(tm_root); node; node = next) {
 		next = rb_next(node);
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 6bcfc5a98548..fb871710607b 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -1502,14 +1502,12 @@ struct btrfs_fs_info {
 	spinlock_t delayed_iput_lock;
 	struct list_head delayed_iputs;
 
-	/* this protects tree_mod_seq_list */
-	spinlock_t tree_mod_seq_lock;
 	atomic64_t tree_mod_seq;
-	struct list_head tree_mod_seq_list;
 
-	/* this protects tree_mod_log */
+	/* this protects tree_mod_log and tree_mod_seq_list */
 	rwlock_t tree_mod_log_lock;
 	struct rb_root tree_mod_log;
+	struct list_head tree_mod_seq_list;
 
 	atomic_t nr_async_submits;
 	atomic_t async_submit_draining;
diff --git a/fs/btrfs/delayed-ref.c b/fs/btrfs/delayed-ref.c
index 6d16bea94e1c..27e5683167f2 100644
--- a/fs/btrfs/delayed-ref.c
+++ b/fs/btrfs/delayed-ref.c
@@ -344,7 +344,7 @@ void btrfs_merge_delayed_refs(struct btrfs_trans_handle *trans,
 	if (head->is_data)
 		return;
 
-	spin_lock(&fs_info->tree_mod_seq_lock);
+	read_lock(&fs_info->tree_mod_log_lock);
 	if (!list_empty(&fs_info->tree_mod_seq_list)) {
 		struct seq_list *elem;
 
@@ -352,7 +352,7 @@ void btrfs_merge_delayed_refs(struct btrfs_trans_handle *trans,
 					struct seq_list, list);
 		seq = elem->seq;
 	}
-	spin_unlock(&fs_info->tree_mod_seq_lock);
+	read_unlock(&fs_info->tree_mod_log_lock);
 
 	node = rb_first(&head->ref_root);
 	while (node) {
@@ -377,7 +377,7 @@ int btrfs_check_delayed_seq(struct btrfs_fs_info *fs_info,
 	struct seq_list *elem;
 	int ret = 0;
 
-	spin_lock(&fs_info->tree_mod_seq_lock);
+	read_lock(&fs_info->tree_mod_log_lock);
 	if (!list_empty(&fs_info->tree_mod_seq_list)) {
 		elem = list_first_entry(&fs_info->tree_mod_seq_list,
 					struct seq_list, list);
@@ -390,7 +390,7 @@ int btrfs_check_delayed_seq(struct btrfs_fs_info *fs_info,
 		}
 	}
 
-	spin_unlock(&fs_info->tree_mod_seq_lock);
+	read_unlock(&fs_info->tree_mod_log_lock);
 	return ret;
 }
 
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index c3669e689db8..c9c57d98a89b 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -2167,7 +2167,6 @@ int open_ctree(struct super_block *sb,
 	spin_lock_init(&fs_info->delayed_iput_lock);
 	spin_lock_init(&fs_info->defrag_inodes_lock);
 	spin_lock_init(&fs_info->free_chunk_lock);
-	spin_lock_init(&fs_info->tree_mod_seq_lock);
 	spin_lock_init(&fs_info->super_lock);
 	spin_lock_init(&fs_info->qgroup_op_lock);
 	spin_lock_init(&fs_info->buffer_lock);
diff --git a/fs/btrfs/tests/btrfs-tests.c b/fs/btrfs/tests/btrfs-tests.c
index 9626252ee6b4..69255148f0c8 100644
--- a/fs/btrfs/tests/btrfs-tests.c
+++ b/fs/btrfs/tests/btrfs-tests.c
@@ -109,7 +109,6 @@ struct btrfs_fs_info *btrfs_alloc_dummy_fs_info(void)
 	spin_lock_init(&fs_info->qgroup_op_lock);
 	spin_lock_init(&fs_info->super_lock);
 	spin_lock_init(&fs_info->fs_roots_radix_lock);
-	spin_lock_init(&fs_info->tree_mod_seq_lock);
 	mutex_init(&fs_info->qgroup_ioctl_lock);
 	mutex_init(&fs_info->qgroup_rescan_lock);
 	rwlock_init(&fs_info->tree_mod_log_lock);
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 2882ebeff95b..51481fa96283 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -1252,6 +1252,7 @@ struct mid_q_entry {
 	mid_receive_t *receive; /* call receive callback */
 	mid_callback_t *callback; /* call completion callback */
 	void *callback_data;	  /* general purpose pointer for callback */
+	struct task_struct *creator;
 	void *resp_buf;		/* pointer to received SMB header */
 	int mid_state;	/* wish this were enum but can not pass to wait_event */
 	unsigned int mid_flags;
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index ac1dd5564896..753de57ad877 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -250,9 +250,14 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon)
 	 */
 	mutex_lock(&tcon->ses->session_mutex);
 	rc = cifs_negotiate_protocol(0, tcon->ses);
-	if (!rc && tcon->ses->need_reconnect)
+	if (!rc && tcon->ses->need_reconnect) {
 		rc = cifs_setup_session(0, tcon->ses, nls_codepage);
-
+		if ((rc == -EACCES) && !tcon->retry) {
+			rc = -EHOSTDOWN;
+			mutex_unlock(&tcon->ses->session_mutex);
+			goto failed;
+		}
+	}
 	if (rc || !tcon->need_reconnect) {
 		mutex_unlock(&tcon->ses->session_mutex);
 		goto out;
@@ -290,6 +295,7 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon)
 	case SMB2_SET_INFO:
 		rc = -EAGAIN;
 	}
+failed:
 	unload_nls(nls_codepage);
 	return rc;
 }
diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c
index 3fb9be656ce6..5a45ca01d082 100644
--- a/fs/cifs/smb2transport.c
+++ b/fs/cifs/smb2transport.c
@@ -542,6 +542,8 @@ smb2_mid_entry_alloc(const struct smb2_hdr *smb_buffer,
 		 * The default is for the mid to be synchronous, so the
 		 * default callback just wakes up the current task.
 		 */
+		get_task_struct(current);
+		temp->creator = current;
 		temp->callback = cifs_wake_up_task;
 		temp->callback_data = current;
 	}
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 503e7b2eda8c..4adf54163c33 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -72,6 +72,8 @@ AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server)
 		 * The default is for the mid to be synchronous, so the
 		 * default callback just wakes up the current task.
 		 */
+		get_task_struct(current);
+		temp->creator = current;
 		temp->callback = cifs_wake_up_task;
 		temp->callback_data = current;
 	}
@@ -86,6 +88,8 @@ static void _cifs_mid_q_entry_release(struct kref *refcount)
 	struct mid_q_entry *mid = container_of(refcount, struct mid_q_entry,
 					       refcount);
 
+	put_task_struct(mid->creator);
+
 	mempool_free(mid, cifs_mid_poolp);
 }
 
diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c
index d4c7e470dec8..7c3244cafd43 100644
--- a/fs/jbd2/checkpoint.c
+++ b/fs/jbd2/checkpoint.c
@@ -173,7 +173,7 @@ void __jbd2_log_wait_for_space(journal_t *journal)
 				       "journal space in %s\n", __func__,
 				       journal->j_devname);
 				WARN_ON(1);
-				jbd2_journal_abort(journal, 0);
+				jbd2_journal_abort(journal, -EIO);
 			}
 			write_lock(&journal->j_state_lock);
 		} else {
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
index 362e5f614450..943a575a8704 100644
--- a/fs/jbd2/commit.c
+++ b/fs/jbd2/commit.c
@@ -802,7 +802,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
 		err = journal_submit_commit_record(journal, commit_transaction,
 						 &cbh, crc32_sum);
 		if (err)
-			__jbd2_journal_abort_hard(journal);
+			jbd2_journal_abort(journal, err);
 	}
 
 	blk_finish_plug(&plug);
@@ -894,7 +894,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
 		err = journal_submit_commit_record(journal, commit_transaction,
 						&cbh, crc32_sum);
 		if (err)
-			__jbd2_journal_abort_hard(journal);
+			jbd2_journal_abort(journal, err);
 	}
 	if (cbh)
 		err = journal_wait_on_commit_record(journal, cbh);
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
index 59c56e6c41bb..633e94f1a41f 100644
--- a/fs/jbd2/journal.c
+++ b/fs/jbd2/journal.c
@@ -1674,6 +1674,11 @@ int jbd2_journal_load(journal_t *journal)
 		       journal->j_devname);
 		return -EIO;
 	}
+	/*
+	 * clear JBD2_ABORT flag initialized in journal_init_common
+	 * here to update log tail information with the newest seq.
+	 */
+	journal->j_flags &= ~JBD2_ABORT;
 
 	/* OK, we've finished with the dynamic journal bits:
 	 * reinitialise the dynamic contents of the superblock in memory
@@ -1681,7 +1686,6 @@ int jbd2_journal_load(journal_t *journal)
 	if (journal_reset(journal))
 		goto recovery_error;
 
-	journal->j_flags &= ~JBD2_ABORT;
 	journal->j_flags |= JBD2_LOADED;
 	return 0;
 
@@ -2102,12 +2106,10 @@ static void __journal_abort_soft (journal_t *journal, int errno)
 
 	__jbd2_journal_abort_hard(journal);
 
-	if (errno) {
-		jbd2_journal_update_sb_errno(journal);
-		write_lock(&journal->j_state_lock);
-		journal->j_flags |= JBD2_REC_ERR;
-		write_unlock(&journal->j_state_lock);
-	}
+	jbd2_journal_update_sb_errno(journal);
+	write_lock(&journal->j_state_lock);
+	journal->j_flags |= JBD2_REC_ERR;
+	write_unlock(&journal->j_state_lock);
 }
 
 /**
@@ -2149,11 +2151,6 @@ static void __journal_abort_soft (journal_t *journal, int errno)
  * failure to disk.  ext3_error, for example, now uses this
  * functionality.
  *
- * Errors which originate from within the journaling layer will NOT
- * supply an errno; a null errno implies that absolutely no further
- * writes are done to the journal (unless there are any already in
- * progress).
- *
  */
 
 void jbd2_journal_abort(journal_t *journal, int errno)
diff --git a/fs/namespace.c b/fs/namespace.c
index 5acf789efbab..8c41f38617db 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -2937,8 +2937,8 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
 	/* make certain new is below the root */
 	if (!is_path_reachable(new_mnt, new.dentry, &root))
 		goto out4;
-	root_mp->m_count++; /* pin it so it won't go away */
 	lock_mount_hash();
+	root_mp->m_count++; /* pin it so it won't go away */
 	detach_mnt(new_mnt, &parent_path);
 	detach_mnt(root_mnt, &root_parent);
 	if (root_mnt->mnt.mnt_flags & MNT_LOCKED) {
diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig
index 3dece03f2fc8..44c5e3a35cea 100644
--- a/fs/nfs/Kconfig
+++ b/fs/nfs/Kconfig
@@ -89,7 +89,7 @@ config NFS_V4
 config NFS_SWAP
 	bool "Provide swap over NFS support"
 	default n
-	depends on NFS_FS
+	depends on NFS_FS && SWAP
 	select SUNRPC_SWAP
 	help
 	  This option enables swapon to work on files located on NFS mounts.
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 5cbdbb6aedde..94215aac7155 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -169,25 +169,15 @@ typedef struct {
 	unsigned int	eof:1;
 } nfs_readdir_descriptor_t;
 
-/*
- * The caller is responsible for calling nfs_readdir_release_array(page)
- */
 static
-struct nfs_cache_array *nfs_readdir_get_array(struct page *page)
+void nfs_readdir_init_array(struct page *page)
 {
-	void *ptr;
-	if (page == NULL)
-		return ERR_PTR(-EIO);
-	ptr = kmap(page);
-	if (ptr == NULL)
-		return ERR_PTR(-ENOMEM);
-	return ptr;
-}
+	struct nfs_cache_array *array;
 
-static
-void nfs_readdir_release_array(struct page *page)
-{
-	kunmap(page);
+	array = kmap_atomic(page);
+	memset(array, 0, sizeof(struct nfs_cache_array));
+	array->eof_index = -1;
+	kunmap_atomic(array);
 }
 
 /*
@@ -202,6 +192,7 @@ void nfs_readdir_clear_array(struct page *page)
 	array = kmap_atomic(page);
 	for (i = 0; i < array->size; i++)
 		kfree(array->array[i].string.name);
+	array->size = 0;
 	kunmap_atomic(array);
 }
 
@@ -229,13 +220,10 @@ int nfs_readdir_make_qstr(struct qstr *string, const char *name, unsigned int le
 static
 int nfs_readdir_add_to_array(struct nfs_entry *entry, struct page *page)
 {
-	struct nfs_cache_array *array = nfs_readdir_get_array(page);
+	struct nfs_cache_array *array = kmap(page);
 	struct nfs_cache_array_entry *cache_entry;
 	int ret;
 
-	if (IS_ERR(array))
-		return PTR_ERR(array);
-
 	cache_entry = &array->array[array->size];
 
 	/* Check that this entry lies within the page bounds */
@@ -254,7 +242,7 @@ int nfs_readdir_add_to_array(struct nfs_entry *entry, struct page *page)
 	if (entry->eof != 0)
 		array->eof_index = array->size;
 out:
-	nfs_readdir_release_array(page);
+	kunmap(page);
 	return ret;
 }
 
@@ -343,11 +331,7 @@ int nfs_readdir_search_array(nfs_readdir_descriptor_t *desc)
 	struct nfs_cache_array *array;
 	int status;
 
-	array = nfs_readdir_get_array(desc->page);
-	if (IS_ERR(array)) {
-		status = PTR_ERR(array);
-		goto out;
-	}
+	array = kmap(desc->page);
 
 	if (*desc->dir_cookie == 0)
 		status = nfs_readdir_search_for_pos(array, desc);
@@ -359,8 +343,7 @@ int nfs_readdir_search_array(nfs_readdir_descriptor_t *desc)
 		desc->current_index += array->size;
 		desc->page_index++;
 	}
-	nfs_readdir_release_array(desc->page);
-out:
+	kunmap(desc->page);
 	return status;
 }
 
@@ -551,13 +534,10 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en
 	} while (!entry->eof);
 
 	if (count == 0 || (status == -EBADCOOKIE && entry->eof != 0)) {
-		array = nfs_readdir_get_array(page);
-		if (!IS_ERR(array)) {
-			array->eof_index = array->size;
-			status = 0;
-			nfs_readdir_release_array(page);
-		} else
-			status = PTR_ERR(array);
+		array = kmap(page);
+		array->eof_index = array->size;
+		status = 0;
+		kunmap(page);
 	}
 
 	put_page(scratch);
@@ -612,6 +592,8 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page,
 	int status = -ENOMEM;
 	unsigned int array_size = ARRAY_SIZE(pages);
 
+	nfs_readdir_init_array(page);
+
 	entry.prev_cookie = 0;
 	entry.cookie = desc->last_cookie;
 	entry.eof = 0;
@@ -627,13 +609,7 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page,
 		goto out;
 	}
 
-	array = nfs_readdir_get_array(page);
-	if (IS_ERR(array)) {
-		status = PTR_ERR(array);
-		goto out_label_free;
-	}
-	memset(array, 0, sizeof(struct nfs_cache_array));
-	array->eof_index = -1;
+	array = kmap(page);
 
 	status = nfs_readdir_large_page(pages, array_size);
 	if (status < 0)
@@ -655,8 +631,7 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page,
 
 	nfs_readdir_free_large_page(pages_ptr, pages, array_size);
 out_release_array:
-	nfs_readdir_release_array(page);
-out_label_free:
+	kunmap(page);
 	nfs4_label_free(entry.label);
 out:
 	nfs_free_fattr(entry.fattr);
@@ -688,6 +663,7 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page* page)
 	unlock_page(page);
 	return 0;
  error:
+	nfs_readdir_clear_array(page);
 	unlock_page(page);
 	return ret;
 }
@@ -695,8 +671,6 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page* page)
 static
 void cache_page_release(nfs_readdir_descriptor_t *desc)
 {
-	if (!desc->page->mapping)
-		nfs_readdir_clear_array(desc->page);
 	page_cache_release(desc->page);
 	desc->page = NULL;
 }
@@ -710,19 +684,28 @@ struct page *get_cache_page(nfs_readdir_descriptor_t *desc)
 
 /*
  * Returns 0 if desc->dir_cookie was found on page desc->page_index
+ * and locks the page to prevent removal from the page cache.
  */
 static
-int find_cache_page(nfs_readdir_descriptor_t *desc)
+int find_and_lock_cache_page(nfs_readdir_descriptor_t *desc)
 {
 	int res;
 
 	desc->page = get_cache_page(desc);
 	if (IS_ERR(desc->page))
 		return PTR_ERR(desc->page);
-
-	res = nfs_readdir_search_array(desc);
+	res = lock_page_killable(desc->page);
 	if (res != 0)
-		cache_page_release(desc);
+		goto error;
+	res = -EAGAIN;
+	if (desc->page->mapping != NULL) {
+		res = nfs_readdir_search_array(desc);
+		if (res == 0)
+			return 0;
+	}
+	unlock_page(desc->page);
+error:
+	cache_page_release(desc);
 	return res;
 }
 
@@ -737,7 +720,7 @@ int readdir_search_pagecache(nfs_readdir_descriptor_t *desc)
 		desc->last_cookie = 0;
 	}
 	do {
-		res = find_cache_page(desc);
+		res = find_and_lock_cache_page(desc);
 	} while (res == -EAGAIN);
 	return res;
 }
@@ -754,12 +737,7 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc)
 	struct nfs_cache_array *array = NULL;
 	struct nfs_open_dir_context *ctx = file->private_data;
 
-	array = nfs_readdir_get_array(desc->page);
-	if (IS_ERR(array)) {
-		res = PTR_ERR(array);
-		goto out;
-	}
-
+	array = kmap(desc->page);
 	for (i = desc->cache_entry_index; i < array->size; i++) {
 		struct nfs_cache_array_entry *ent;
 
@@ -780,9 +758,7 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc)
 	if (array->eof_index >= 0)
 		desc->eof = 1;
 
-	nfs_readdir_release_array(desc->page);
-out:
-	cache_page_release(desc);
+	kunmap(desc->page);
 	dfprintk(DIRCACHE, "NFS: nfs_do_filldir() filling ended @ cookie %Lu; returning = %d\n",
 			(unsigned long long)*desc->dir_cookie, res);
 	return res;
@@ -828,13 +804,13 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc)
 
 	status = nfs_do_filldir(desc);
 
+ out_release:
+	nfs_readdir_clear_array(desc->page);
+	cache_page_release(desc);
  out:
 	dfprintk(DIRCACHE, "NFS: %s: returns %d\n",
 			__func__, status);
 	return status;
- out_release:
-	cache_page_release(desc);
-	goto out;
 }
 
 /* The file offset position represents the dirent entry number.  A
@@ -900,6 +876,8 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx)
 			break;
 
 		res = nfs_do_filldir(desc);
+		unlock_page(desc->page);
+		cache_page_release(desc);
 		if (res < 0)
 			break;
 	} while (!desc->eof);
diff --git a/fs/pnode.c b/fs/pnode.c
index 52e7506782cb..3f6281239a36 100644
--- a/fs/pnode.c
+++ b/fs/pnode.c
@@ -249,14 +249,13 @@ static int propagate_one(struct mount *m)
 	child = copy_tree(last_source, last_source->mnt.mnt_root, type);
 	if (IS_ERR(child))
 		return PTR_ERR(child);
+	read_seqlock_excl(&mount_lock);
 	mnt_set_mountpoint(m, mp, child);
+	if (m->mnt_master != dest_master)
+		SET_MNT_MARK(m->mnt_master);
+	read_sequnlock_excl(&mount_lock);
 	last_dest = m;
 	last_source = child;
-	if (m->mnt_master != dest_master) {
-		read_seqlock_excl(&mount_lock);
-		SET_MNT_MARK(m->mnt_master);
-		read_sequnlock_excl(&mount_lock);
-	}
 	hlist_add_head(&child->mnt_hash, list);
 	return count_mounts(m->mnt_ns, child);
 }
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index 7daf9e503f80..ffb7612e709b 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -589,6 +589,7 @@ static void reiserfs_put_super(struct super_block *s)
 	reiserfs_write_unlock(s);
 	mutex_destroy(&REISERFS_SB(s)->lock);
 	destroy_workqueue(REISERFS_SB(s)->commit_wq);
+	kfree(REISERFS_SB(s)->s_jdev);
 	kfree(s->s_fs_info);
 	s->s_fs_info = NULL;
 }
@@ -1900,7 +1901,7 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
 		if (!sbi->s_jdev) {
 			SWARN(silent, s, "", "Cannot allocate memory for "
 				"journal device name");
-			goto error;
+			goto error_unlocked;
 		}
 	}
 #ifdef CONFIG_QUOTA
@@ -2188,6 +2189,7 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
 			kfree(qf_names[j]);
 	}
 #endif
+	kfree(sbi->s_jdev);
 	kfree(sbi);
 
 	s->s_fs_info = NULL;
diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c
index fdf6d28c4839..8c0202739ece 100644
--- a/fs/ubifs/file.c
+++ b/fs/ubifs/file.c
@@ -782,8 +782,9 @@ static int ubifs_do_bulk_read(struct ubifs_info *c, struct bu_info *bu,
 
 		if (page_offset > end_index)
 			break;
-		page = find_or_create_page(mapping, page_offset,
-					   GFP_NOFS | __GFP_COLD);
+		page = pagecache_get_page(mapping, page_offset,
+				 FGP_LOCK|FGP_ACCESSED|FGP_CREAT|FGP_NOWAIT,
+				 GFP_NOFS | __GFP_COLD);
 		if (!page)
 			break;
 		if (!PageUptodate(page))
diff --git a/include/linux/padata.h b/include/linux/padata.h
index 438694650471..547a8d1e4a3b 100644
--- a/include/linux/padata.h
+++ b/include/linux/padata.h
@@ -24,7 +24,6 @@
 #include <linux/workqueue.h>
 #include <linux/spinlock.h>
 #include <linux/list.h>
-#include <linux/timer.h>
 #include <linux/notifier.h>
 #include <linux/kobject.h>
 
@@ -37,6 +36,7 @@
  * @list: List entry, to attach to the padata lists.
  * @pd: Pointer to the internal control structure.
  * @cb_cpu: Callback cpu for serializatioon.
+ * @cpu: Cpu for parallelization.
  * @seq_nr: Sequence number of the parallelized data object.
  * @info: Used to pass information from the parallel to the serial function.
  * @parallel: Parallel execution function.
@@ -46,6 +46,7 @@ struct padata_priv {
 	struct list_head	list;
 	struct parallel_data	*pd;
 	int			cb_cpu;
+	int			cpu;
 	int			info;
 	void                    (*parallel)(struct padata_priv *padata);
 	void                    (*serial)(struct padata_priv *padata);
@@ -83,7 +84,6 @@ struct padata_serial_queue {
  * @serial: List to wait for serialization after reordering.
  * @pwork: work struct for parallelization.
  * @swork: work struct for serialization.
- * @pd: Backpointer to the internal control structure.
  * @work: work struct for parallelization.
  * @num_obj: Number of objects that are processed by this cpu.
  * @cpu_index: Index of the cpu.
@@ -91,7 +91,6 @@ struct padata_serial_queue {
 struct padata_parallel_queue {
        struct padata_list    parallel;
        struct padata_list    reorder;
-       struct parallel_data *pd;
        struct work_struct    work;
        atomic_t              num_obj;
        int                   cpu_index;
@@ -118,10 +117,10 @@ struct padata_cpumask {
  * @reorder_objects: Number of objects waiting in the reorder queues.
  * @refcnt: Number of objects holding a reference on this parallel_data.
  * @max_seq_nr:  Maximal used sequence number.
+ * @cpu: Next CPU to be processed.
  * @cpumask: The cpumasks in use for parallel and serial workers.
+ * @reorder_work: work struct for reordering.
  * @lock: Reorder lock.
- * @processed: Number of already processed objects.
- * @timer: Reorder timer.
  */
 struct parallel_data {
 	struct padata_instance		*pinst;
@@ -130,10 +129,10 @@ struct parallel_data {
 	atomic_t			reorder_objects;
 	atomic_t			refcnt;
 	atomic_t			seq_nr;
+	int				cpu;
 	struct padata_cpumask		cpumask;
+	struct work_struct		reorder_work;
 	spinlock_t                      lock ____cacheline_aligned;
-	unsigned int			processed;
-	struct timer_list		timer;
 };
 
 /**
diff --git a/include/linux/usb/irda.h b/include/linux/usb/irda.h
index e345ceaf72d6..9dc46010a067 100644
--- a/include/linux/usb/irda.h
+++ b/include/linux/usb/irda.h
@@ -118,11 +118,22 @@ struct usb_irda_cs_descriptor {
  * 6 - 115200 bps
  * 7 - 576000 bps
  * 8 - 1.152 Mbps
- * 9 - 5 mbps
+ * 9 - 4 Mbps
  * 10..15 - Reserved
  */
 #define USB_IRDA_STATUS_LINK_SPEED	0x0f
 
+#define USB_IRDA_LS_NO_CHANGE		0
+#define USB_IRDA_LS_2400		1
+#define USB_IRDA_LS_9600		2
+#define USB_IRDA_LS_19200		3
+#define USB_IRDA_LS_38400		4
+#define USB_IRDA_LS_57600		5
+#define USB_IRDA_LS_115200		6
+#define USB_IRDA_LS_576000		7
+#define USB_IRDA_LS_1152000		8
+#define USB_IRDA_LS_4000000		9
+
 /* The following is a 4-bit value used only for
  * outbound header:
  *
diff --git a/kernel/padata.c b/kernel/padata.c
index 9978b5712fce..3dbd6d470218 100644
--- a/kernel/padata.c
+++ b/kernel/padata.c
@@ -33,6 +33,8 @@
 
 #define MAX_OBJ_NUM 1000
 
+static void padata_free_pd(struct parallel_data *pd);
+
 static int padata_index_to_cpu(struct parallel_data *pd, int cpu_index)
 {
 	int cpu, target_cpu;
@@ -63,15 +65,11 @@ static int padata_cpu_hash(struct parallel_data *pd)
 static void padata_parallel_worker(struct work_struct *parallel_work)
 {
 	struct padata_parallel_queue *pqueue;
-	struct parallel_data *pd;
-	struct padata_instance *pinst;
 	LIST_HEAD(local_list);
 
 	local_bh_disable();
 	pqueue = container_of(parallel_work,
 			      struct padata_parallel_queue, work);
-	pd = pqueue->pd;
-	pinst = pd->pinst;
 
 	spin_lock(&pqueue->parallel.lock);
 	list_replace_init(&pqueue->parallel.list, &local_list);
@@ -134,6 +132,7 @@ int padata_do_parallel(struct padata_instance *pinst,
 	padata->cb_cpu = cb_cpu;
 
 	target_cpu = padata_cpu_hash(pd);
+	padata->cpu = target_cpu;
 	queue = per_cpu_ptr(pd->pqueue, target_cpu);
 
 	spin_lock(&queue->parallel.lock);
@@ -157,8 +156,6 @@ EXPORT_SYMBOL(padata_do_parallel);
  * A pointer to the control struct of the next object that needs
  * serialization, if present in one of the percpu reorder queues.
  *
- * NULL, if all percpu reorder queues are empty.
- *
  * -EINPROGRESS, if the next object that needs serialization will
  *  be parallel processed by another cpu and is not yet present in
  *  the cpu's reorder queue.
@@ -168,40 +165,29 @@ EXPORT_SYMBOL(padata_do_parallel);
  */
 static struct padata_priv *padata_get_next(struct parallel_data *pd)
 {
-	int cpu, num_cpus;
-	unsigned int next_nr, next_index;
 	struct padata_parallel_queue *next_queue;
 	struct padata_priv *padata;
 	struct padata_list *reorder;
+	int cpu = pd->cpu;
 
-	num_cpus = cpumask_weight(pd->cpumask.pcpu);
-
-	/*
-	 * Calculate the percpu reorder queue and the sequence
-	 * number of the next object.
-	 */
-	next_nr = pd->processed;
-	next_index = next_nr % num_cpus;
-	cpu = padata_index_to_cpu(pd, next_index);
 	next_queue = per_cpu_ptr(pd->pqueue, cpu);
-
-	padata = NULL;
-
 	reorder = &next_queue->reorder;
 
+	spin_lock(&reorder->lock);
 	if (!list_empty(&reorder->list)) {
 		padata = list_entry(reorder->list.next,
 				    struct padata_priv, list);
 
-		spin_lock(&reorder->lock);
 		list_del_init(&padata->list);
 		atomic_dec(&pd->reorder_objects);
-		spin_unlock(&reorder->lock);
 
-		pd->processed++;
+		pd->cpu = cpumask_next_wrap(cpu, pd->cpumask.pcpu, -1,
+					    false);
 
+		spin_unlock(&reorder->lock);
 		goto out;
 	}
+	spin_unlock(&reorder->lock);
 
 	if (__this_cpu_read(pd->pqueue->cpu_index) == next_queue->cpu_index) {
 		padata = ERR_PTR(-ENODATA);
@@ -219,6 +205,7 @@ static void padata_reorder(struct parallel_data *pd)
 	struct padata_priv *padata;
 	struct padata_serial_queue *squeue;
 	struct padata_instance *pinst = pd->pinst;
+	struct padata_parallel_queue *next_queue;
 
 	/*
 	 * We need to ensure that only one cpu can work on dequeueing of
@@ -237,12 +224,11 @@ static void padata_reorder(struct parallel_data *pd)
 		padata = padata_get_next(pd);
 
 		/*
-		 * All reorder queues are empty, or the next object that needs
-		 * serialization is parallel processed by another cpu and is
-		 * still on it's way to the cpu's reorder queue, nothing to
-		 * do for now.
+		 * If the next object that needs serialization is parallel
+		 * processed by another cpu and is still on it's way to the
+		 * cpu's reorder queue, nothing to do for now.
 		 */
-		if (!padata || PTR_ERR(padata) == -EINPROGRESS)
+		if (PTR_ERR(padata) == -EINPROGRESS)
 			break;
 
 		/*
@@ -251,7 +237,6 @@ static void padata_reorder(struct parallel_data *pd)
 		 * so exit immediately.
 		 */
 		if (PTR_ERR(padata) == -ENODATA) {
-			del_timer(&pd->timer);
 			spin_unlock_bh(&pd->lock);
 			return;
 		}
@@ -270,28 +255,27 @@ static void padata_reorder(struct parallel_data *pd)
 
 	/*
 	 * The next object that needs serialization might have arrived to
-	 * the reorder queues in the meantime, we will be called again
-	 * from the timer function if no one else cares for it.
+	 * the reorder queues in the meantime.
 	 *
-	 * Ensure reorder_objects is read after pd->lock is dropped so we see
-	 * an increment from another task in padata_do_serial.  Pairs with
+	 * Ensure reorder queue is read after pd->lock is dropped so we see
+	 * new objects from another task in padata_do_serial.  Pairs with
 	 * smp_mb__after_atomic in padata_do_serial.
 	 */
 	smp_mb();
-	if (atomic_read(&pd->reorder_objects)
-			&& !(pinst->flags & PADATA_RESET))
-		mod_timer(&pd->timer, jiffies + HZ);
-	else
-		del_timer(&pd->timer);
 
-	return;
+	next_queue = per_cpu_ptr(pd->pqueue, pd->cpu);
+	if (!list_empty(&next_queue->reorder.list))
+		queue_work(pinst->wq, &pd->reorder_work);
 }
 
-static void padata_reorder_timer(unsigned long arg)
+static void invoke_padata_reorder(struct work_struct *work)
 {
-	struct parallel_data *pd = (struct parallel_data *)arg;
+	struct parallel_data *pd;
 
+	local_bh_disable();
+	pd = container_of(work, struct parallel_data, reorder_work);
 	padata_reorder(pd);
+	local_bh_enable();
 }
 
 static void padata_serial_worker(struct work_struct *serial_work)
@@ -299,6 +283,7 @@ static void padata_serial_worker(struct work_struct *serial_work)
 	struct padata_serial_queue *squeue;
 	struct parallel_data *pd;
 	LIST_HEAD(local_list);
+	int cnt;
 
 	local_bh_disable();
 	squeue = container_of(serial_work, struct padata_serial_queue, work);
@@ -308,6 +293,8 @@ static void padata_serial_worker(struct work_struct *serial_work)
 	list_replace_init(&squeue->serial.list, &local_list);
 	spin_unlock(&squeue->serial.lock);
 
+	cnt = 0;
+
 	while (!list_empty(&local_list)) {
 		struct padata_priv *padata;
 
@@ -317,9 +304,12 @@ static void padata_serial_worker(struct work_struct *serial_work)
 		list_del_init(&padata->list);
 
 		padata->serial(padata);
-		atomic_dec(&pd->refcnt);
+		cnt++;
 	}
 	local_bh_enable();
+
+	if (atomic_sub_and_test(cnt, &pd->refcnt))
+		padata_free_pd(pd);
 }
 
 /**
@@ -332,29 +322,22 @@ static void padata_serial_worker(struct work_struct *serial_work)
  */
 void padata_do_serial(struct padata_priv *padata)
 {
-	int cpu;
-	struct padata_parallel_queue *pqueue;
-	struct parallel_data *pd;
-
-	pd = padata->pd;
-
-	cpu = get_cpu();
-	pqueue = per_cpu_ptr(pd->pqueue, cpu);
+	struct parallel_data *pd = padata->pd;
+	struct padata_parallel_queue *pqueue = per_cpu_ptr(pd->pqueue,
+							   padata->cpu);
 
 	spin_lock(&pqueue->reorder.lock);
-	atomic_inc(&pd->reorder_objects);
 	list_add_tail(&padata->list, &pqueue->reorder.list);
+	atomic_inc(&pd->reorder_objects);
 	spin_unlock(&pqueue->reorder.lock);
 
 	/*
-	 * Ensure the atomic_inc of reorder_objects above is ordered correctly
+	 * Ensure the addition to the reorder list is ordered correctly
 	 * with the trylock of pd->lock in padata_reorder.  Pairs with smp_mb
 	 * in padata_reorder.
 	 */
 	smp_mb__after_atomic();
 
-	put_cpu();
-
 	padata_reorder(pd);
 }
 EXPORT_SYMBOL(padata_do_serial);
@@ -403,9 +386,14 @@ static void padata_init_pqueues(struct parallel_data *pd)
 	struct padata_parallel_queue *pqueue;
 
 	cpu_index = 0;
-	for_each_cpu(cpu, pd->cpumask.pcpu) {
+	for_each_possible_cpu(cpu) {
 		pqueue = per_cpu_ptr(pd->pqueue, cpu);
-		pqueue->pd = pd;
+
+		if (!cpumask_test_cpu(cpu, pd->cpumask.pcpu)) {
+			pqueue->cpu_index = -1;
+			continue;
+		}
+
 		pqueue->cpu_index = cpu_index;
 		cpu_index++;
 
@@ -439,12 +427,13 @@ static struct parallel_data *padata_alloc_pd(struct padata_instance *pinst,
 
 	padata_init_pqueues(pd);
 	padata_init_squeues(pd);
-	setup_timer(&pd->timer, padata_reorder_timer, (unsigned long)pd);
 	atomic_set(&pd->seq_nr, -1);
 	atomic_set(&pd->reorder_objects, 0);
-	atomic_set(&pd->refcnt, 0);
+	atomic_set(&pd->refcnt, 1);
 	pd->pinst = pinst;
 	spin_lock_init(&pd->lock);
+	pd->cpu = cpumask_first(pd->cpumask.pcpu);
+	INIT_WORK(&pd->reorder_work, invoke_padata_reorder);
 
 	return pd;
 
@@ -467,31 +456,6 @@ static void padata_free_pd(struct parallel_data *pd)
 	kfree(pd);
 }
 
-/* Flush all objects out of the padata queues. */
-static void padata_flush_queues(struct parallel_data *pd)
-{
-	int cpu;
-	struct padata_parallel_queue *pqueue;
-	struct padata_serial_queue *squeue;
-
-	for_each_cpu(cpu, pd->cpumask.pcpu) {
-		pqueue = per_cpu_ptr(pd->pqueue, cpu);
-		flush_work(&pqueue->work);
-	}
-
-	del_timer_sync(&pd->timer);
-
-	if (atomic_read(&pd->reorder_objects))
-		padata_reorder(pd);
-
-	for_each_cpu(cpu, pd->cpumask.cbcpu) {
-		squeue = per_cpu_ptr(pd->squeue, cpu);
-		flush_work(&squeue->work);
-	}
-
-	BUG_ON(atomic_read(&pd->refcnt) != 0);
-}
-
 static void __padata_start(struct padata_instance *pinst)
 {
 	pinst->flags |= PADATA_INIT;
@@ -505,10 +469,6 @@ static void __padata_stop(struct padata_instance *pinst)
 	pinst->flags &= ~PADATA_INIT;
 
 	synchronize_rcu();
-
-	get_online_cpus();
-	padata_flush_queues(pinst->pd);
-	put_online_cpus();
 }
 
 /* Replace the internal control structure with a new one. */
@@ -529,8 +489,8 @@ static void padata_replace(struct padata_instance *pinst,
 	if (!cpumask_equal(pd_old->cpumask.cbcpu, pd_new->cpumask.cbcpu))
 		notification_mask |= PADATA_CPU_SERIAL;
 
-	padata_flush_queues(pd_old);
-	padata_free_pd(pd_old);
+	if (atomic_dec_and_test(&pd_old->refcnt))
+		padata_free_pd(pd_old);
 
 	if (notification_mask)
 		blocking_notifier_call_chain(&pinst->cpumask_change_notifier,
@@ -660,8 +620,8 @@ int padata_set_cpumask(struct padata_instance *pinst, int cpumask_type,
 	struct cpumask *serial_mask, *parallel_mask;
 	int err = -EINVAL;
 
-	mutex_lock(&pinst->lock);
 	get_online_cpus();
+	mutex_lock(&pinst->lock);
 
 	switch (cpumask_type) {
 	case PADATA_CPU_PARALLEL:
@@ -679,8 +639,8 @@ int padata_set_cpumask(struct padata_instance *pinst, int cpumask_type,
 	err =  __padata_set_cpumasks(pinst, parallel_mask, serial_mask);
 
 out:
-	put_online_cpus();
 	mutex_unlock(&pinst->lock);
+	put_online_cpus();
 
 	return err;
 }
diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c
index 7d890e157452..51c68ce92337 100644
--- a/kernel/time/clocksource.c
+++ b/kernel/time/clocksource.c
@@ -343,8 +343,15 @@ static void clocksource_watchdog(unsigned long data)
 	next_cpu = cpumask_next(raw_smp_processor_id(), cpu_online_mask);
 	if (next_cpu >= nr_cpu_ids)
 		next_cpu = cpumask_first(cpu_online_mask);
-	watchdog_timer.expires += WATCHDOG_INTERVAL;
-	add_timer_on(&watchdog_timer, next_cpu);
+
+	/*
+	 * Arm timer if not already pending: could race with concurrent
+	 * pair clocksource_stop_watchdog() clocksource_start_watchdog().
+	 */
+	if (!timer_pending(&watchdog_timer)) {
+		watchdog_timer.expires += WATCHDOG_INTERVAL;
+		add_timer_on(&watchdog_timer, next_cpu);
+	}
 out:
 	spin_unlock(&watchdog_lock);
 }
diff --git a/kernel/trace/trace_stat.c b/kernel/trace/trace_stat.c
index 7af67360b330..9457c39e8d3c 100644
--- a/kernel/trace/trace_stat.c
+++ b/kernel/trace/trace_stat.c
@@ -277,19 +277,23 @@ static int tracing_stat_init(void)
 
 	d_tracing = tracing_init_dentry();
 	if (!d_tracing)
-		return 0;
+		return -ENODEV;
 
 	stat_dir = debugfs_create_dir("trace_stat", d_tracing);
-	if (!stat_dir)
+	if (!stat_dir) {
 		pr_warning("Could not create debugfs "
 			   "'trace_stat' entry\n");
+		return -ENOMEM;
+	}
 	return 0;
 }
 
 static int init_stat_file(struct stat_session *session)
 {
-	if (!stat_dir && tracing_stat_init())
-		return -ENODEV;
+	int ret;
+
+	if (!stat_dir && (ret = tracing_stat_init()))
+		return ret;
 
 	session->file = debugfs_create_file(session->ts->name, 0644,
 					    stat_dir,
@@ -302,7 +306,7 @@ static int init_stat_file(struct stat_session *session)
 int register_stat_tracer(struct tracer_stat *trace)
 {
 	struct stat_session *session, *node;
-	int ret;
+	int ret = -EINVAL;
 
 	if (!trace)
 		return -EINVAL;
@@ -313,17 +317,15 @@ int register_stat_tracer(struct tracer_stat *trace)
 	/* Already registered? */
 	mutex_lock(&all_stat_sessions_mutex);
 	list_for_each_entry(node, &all_stat_sessions, session_list) {
-		if (node->ts == trace) {
-			mutex_unlock(&all_stat_sessions_mutex);
-			return -EINVAL;
-		}
+		if (node->ts == trace)
+			goto out;
 	}
-	mutex_unlock(&all_stat_sessions_mutex);
 
+	ret = -ENOMEM;
 	/* Init the session */
 	session = kzalloc(sizeof(*session), GFP_KERNEL);
 	if (!session)
-		return -ENOMEM;
+		goto out;
 
 	session->ts = trace;
 	INIT_LIST_HEAD(&session->session_list);
@@ -332,15 +334,16 @@ int register_stat_tracer(struct tracer_stat *trace)
 	ret = init_stat_file(session);
 	if (ret) {
 		destroy_session(session);
-		return ret;
+		goto out;
 	}
 
+	ret = 0;
 	/* Register */
-	mutex_lock(&all_stat_sessions_mutex);
 	list_add_tail(&session->session_list, &all_stat_sessions);
+ out:
 	mutex_unlock(&all_stat_sessions_mutex);
 
-	return 0;
+	return ret;
 }
 
 void unregister_stat_tracer(struct tracer_stat *trace)
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index ad5f8f16270c..11fee39672ee 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -2687,6 +2687,9 @@ int mpol_parse_str(char *str, struct mempolicy **mpol)
 	char *flags = strchr(str, '=');
 	int err = 1;
 
+	if (flags)
+		*flags++ = '\0';	/* terminate mode string */
+
 	if (nodelist) {
 		/* NUL-terminate mode or flags string */
 		*nodelist++ = '\0';
@@ -2697,9 +2700,6 @@ int mpol_parse_str(char *str, struct mempolicy **mpol)
 	} else
 		nodes_clear(nodes);
 
-	if (flags)
-		*flags++ = '\0';	/* terminate mode string */
-
 	for (mode = 0; mode < MPOL_MAX; mode++) {
 		if (!strcmp(str, policy_modes[mode])) {
 			break;
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index e16ae4249199..e87ddcbb46f2 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -2363,6 +2363,7 @@ int tcp_disconnect(struct sock *sk, int flags)
 	tp->window_clamp = 0;
 	tcp_set_ca_state(sk, TCP_CA_Open);
 	tcp_clear_retrans(tp);
+	tp->total_retrans = 0;
 	inet_csk_delack_init(sk);
 	/* Initialize rcv_mss to TCP_MIN_MSS to avoid division by 0
 	 * issue in __tcp_select_window()
diff --git a/net/sched/cls_rsvp.h b/net/sched/cls_rsvp.h
index 1020e233a5d6..c424b7aa969b 100644
--- a/net/sched/cls_rsvp.h
+++ b/net/sched/cls_rsvp.h
@@ -404,10 +404,8 @@ static u32 gen_tunnel(struct rsvp_head *data)
 
 static const struct nla_policy rsvp_policy[TCA_RSVP_MAX + 1] = {
 	[TCA_RSVP_CLASSID]	= { .type = NLA_U32 },
-	[TCA_RSVP_DST]		= { .type = NLA_BINARY,
-				    .len = RSVP_DST_LEN * sizeof(u32) },
-	[TCA_RSVP_SRC]		= { .type = NLA_BINARY,
-				    .len = RSVP_DST_LEN * sizeof(u32) },
+	[TCA_RSVP_DST]		= { .len = RSVP_DST_LEN * sizeof(u32) },
+	[TCA_RSVP_SRC]		= { .len = RSVP_DST_LEN * sizeof(u32) },
 	[TCA_RSVP_PINFO]	= { .len = sizeof(struct tc_rsvp_pinfo) },
 };
 
diff --git a/net/sched/ematch.c b/net/sched/ematch.c
index eaf8e3e727dc..cc80a4204c33 100644
--- a/net/sched/ematch.c
+++ b/net/sched/ematch.c
@@ -241,6 +241,9 @@ static int tcf_em_validate(struct tcf_proto *tp,
 			goto errout;
 
 		if (em->ops->change) {
+			err = -EINVAL;
+			if (em_hdr->flags & TCF_EM_SIMPLE)
+				goto errout;
 			err = em->ops->change(tp, data, data_len, em);
 			if (err < 0)
 				goto errout;
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index 03000a10983d..09c2f8c27ec4 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -1171,6 +1171,7 @@ static int gss_proxy_save_rsc(struct cache_detail *cd,
 		dprintk("RPC:       No creds found!\n");
 		goto out;
 	} else {
+		struct timespec boot;
 
 		/* steal creds */
 		rsci.cred = ud->creds;
@@ -1191,6 +1192,9 @@ static int gss_proxy_save_rsc(struct cache_detail *cd,
 						&expiry, GFP_KERNEL);
 		if (status)
 			goto out;
+
+		getboottime(&boot);
+		expiry -= boot.tv_sec;
 	}
 
 	rsci.h.expiry_time = expiry;
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
index 186d5aec7e72..8fce1f5beb88 100644
--- a/scripts/kconfig/confdata.c
+++ b/scripts/kconfig/confdata.c
@@ -1231,7 +1231,7 @@ bool conf_set_all_new_symbols(enum conf_def_mode mode)
 
 		sym_calc_value(csym);
 		if (mode == def_random)
-			has_changed = randomize_choice_values(csym);
+			has_changed |= randomize_choice_values(csym);
 		else {
 			set_all_choice_values(csym);
 			has_changed = true;
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c
index 35cc884bca6b..eb161cf7ffbd 100644
--- a/sound/drivers/dummy.c
+++ b/sound/drivers/dummy.c
@@ -927,7 +927,7 @@ static void print_formats(struct snd_dummy *dummy,
 {
 	int i;
 
-	for (i = 0; i < SNDRV_PCM_FORMAT_LAST; i++) {
+	for (i = 0; i <= SNDRV_PCM_FORMAT_LAST; i++) {
 		if (dummy->pcm_hw.formats & (1ULL << i))
 			snd_iprintf(buffer, " %s", snd_pcm_format_name(i));
 	}
diff --git a/sound/sh/aica.c b/sound/sh/aica.c
index 47849eaf266d..e631d6d71e1a 100644
--- a/sound/sh/aica.c
+++ b/sound/sh/aica.c
@@ -120,10 +120,10 @@ static void spu_memset(u32 toi, u32 what, int length)
 }
 
 /* spu_memload - write to SPU address space */
-static void spu_memload(u32 toi, void *from, int length)
+static void spu_memload(u32 toi, const void *from, int length)
 {
 	unsigned long flags;
-	u32 *froml = from;
+	const u32 *froml = from;
 	u32 __iomem *to = (u32 __iomem *) (SPU_MEMORY_BASE + toi);
 	int i;
 	u32 val;
diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c
index e8ce34c9db32..456131c04c90 100644
--- a/virt/kvm/ioapic.c
+++ b/virt/kvm/ioapic.c
@@ -36,6 +36,7 @@
 #include <linux/io.h>
 #include <linux/slab.h>
 #include <linux/export.h>
+#include <linux/nospec.h>
 #include <asm/processor.h>
 #include <asm/page.h>
 #include <asm/current.h>
@@ -73,13 +74,14 @@ static unsigned long ioapic_read_indirect(struct kvm_ioapic *ioapic,
 	default:
 		{
 			u32 redir_index = (ioapic->ioregsel - 0x10) >> 1;
-			u64 redir_content;
+			u64 redir_content = ~0ULL;
 
-			if (redir_index < IOAPIC_NUM_PINS)
-				redir_content =
-					ioapic->redirtbl[redir_index].bits;
-			else
-				redir_content = ~0ULL;
+			if (redir_index < IOAPIC_NUM_PINS) {
+				u32 index = array_index_nospec(
+					redir_index, IOAPIC_NUM_PINS);
+
+				redir_content = ioapic->redirtbl[index].bits;
+			}
 
 			result = (ioapic->ioregsel & 0x1) ?
 			    (redir_content >> 32) & 0xffffffff :
@@ -310,6 +312,7 @@ static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val)
 		ioapic_debug("change redir index %x val %x\n", index, val);
 		if (index >= IOAPIC_NUM_PINS)
 			return;
+		index = array_index_nospec(index, IOAPIC_NUM_PINS);
 		e = &ioapic->redirtbl[index];
 		mask_before = e->fields.mask;
 		if (ioapic->ioregsel & 1) {
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index cc0b4c5f5c72..dd3068094a01 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -1596,12 +1596,12 @@ int kvm_write_guest_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
 	if (slots->generation != ghc->generation)
 		kvm_gfn_to_hva_cache_init(kvm, ghc, ghc->gpa, ghc->len);
 
-	if (unlikely(!ghc->memslot))
-		return kvm_write_guest(kvm, ghc->gpa, data, len);
-
 	if (kvm_is_error_hva(ghc->hva))
 		return -EFAULT;
 
+	if (unlikely(!ghc->memslot))
+		return kvm_write_guest(kvm, ghc->gpa, data, len);
+
 	r = __copy_to_user((void __user *)ghc->hva, data, len);
 	if (r)
 		return -EFAULT;
@@ -1622,12 +1622,12 @@ int kvm_read_guest_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
 	if (slots->generation != ghc->generation)
 		kvm_gfn_to_hva_cache_init(kvm, ghc, ghc->gpa, ghc->len);
 
-	if (unlikely(!ghc->memslot))
-		return kvm_read_guest(kvm, ghc->gpa, data, len);
-
 	if (kvm_is_error_hva(ghc->hva))
 		return -EFAULT;
 
+	if (unlikely(!ghc->memslot))
+		return kvm_read_guest(kvm, ghc->gpa, data, len);
+
 	r = __copy_from_user(data, (void __user *)ghc->hva, len);
 	if (r)
 		return -EFAULT;

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply related	[relevance 1%]

* Re: [PATCH 3.16 00/99] 3.16.84-rc1 review
  2020-05-21 22:37  6%     ` Guenter Roeck
@ 2020-05-22  0:00  9%       ` Ben Hutchings
  0 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-22  0:00 UTC (permalink / raw)
  To: Guenter Roeck, linux-kernel, stable; +Cc: torvalds, akpm, Denis Kirjanov

[-- Attachment #1: Type: text/plain, Size: 1758 bytes --]

On Thu, 2020-05-21 at 15:37 -0700, Guenter Roeck wrote:
> On 5/21/20 1:20 PM, Ben Hutchings wrote:
> > On Wed, 2020-05-20 at 14:23 -0700, Guenter Roeck wrote:
> > > On 5/20/20 7:13 AM, Ben Hutchings wrote:
> > > > This is the start of the stable review cycle for the 3.16.84 release.
> > > > There are 99 patches in this series, which will be posted as responses
> > > > to this one.  If anyone has any issues with these being applied, please
> > > > let me know.
> > > > 
> > > > Responses should be made by Fri May 22 20:00:00 UTC 2020.
> > > > Anything received after that time might be too late.
> > > > 
> > > Build results:
> > > 	total: 135 pass: 135 fail: 0
> > > Qemu test results:
> > > 	total: 230 pass: 227 fail: 3
> > > Failed tests:
> > > 	arm:cubieboard:multi_v7_defconfig:mem512:sun4i-a10-cubieboard:initrd
> > > 	arm:cubieboard:multi_v7_defconfig:usb:mem512:sun4i-a10-cubieboard:rootfs
> > > 	arm:cubieboard:multi_v7_defconfig:sata:mem512:sun4i-a10-cubieboard:rootfs
> > > 
> > > The arm tests fail due to a compile error.
> > > 
> > > drivers/clk/tegra/clk-tegra-periph.c:524:65: error: 'CLK_IS_CRITICAL' undeclared here (not in a function); did you mean 'CLK_IS_BASIC'?
> > 
> > I already looked at your first test results and dropped the patch that
> > uses CLK_IS_CRITICAL, so there's something else going wrong there...
> > 
> 
> Ah yes. Sorry, I didn't notice that there was a rebuild.
> 
> Images are fine; the three failing tests should not have been
> tested in the first place (they never did, but I didn't update
> the blacklist when I increased the qemu memory size to 512MB).

OK, thanks for checking.

Ben.

-- 
Ben Hutchings
Logic doesn't apply to the real world. - Marvin Minsky



[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[relevance 9%]

* Re: [PATCH 3.16 00/99] 3.16.84-rc1 review
  2020-05-21 20:20  9%   ` Ben Hutchings
@ 2020-05-21 22:37  6%     ` Guenter Roeck
  2020-05-22  0:00  9%       ` Ben Hutchings
  0 siblings, 1 reply; 200+ results
From: Guenter Roeck @ 2020-05-21 22:37 UTC (permalink / raw)
  To: Ben Hutchings, linux-kernel, stable; +Cc: torvalds, akpm, Denis Kirjanov


[-- Attachment #1.1: Type: text/plain, Size: 1497 bytes --]

On 5/21/20 1:20 PM, Ben Hutchings wrote:
> On Wed, 2020-05-20 at 14:23 -0700, Guenter Roeck wrote:
>> On 5/20/20 7:13 AM, Ben Hutchings wrote:
>>> This is the start of the stable review cycle for the 3.16.84 release.
>>> There are 99 patches in this series, which will be posted as responses
>>> to this one.  If anyone has any issues with these being applied, please
>>> let me know.
>>>
>>> Responses should be made by Fri May 22 20:00:00 UTC 2020.
>>> Anything received after that time might be too late.
>>>
>> Build results:
>> 	total: 135 pass: 135 fail: 0
>> Qemu test results:
>> 	total: 230 pass: 227 fail: 3
>> Failed tests:
>> 	arm:cubieboard:multi_v7_defconfig:mem512:sun4i-a10-cubieboard:initrd
>> 	arm:cubieboard:multi_v7_defconfig:usb:mem512:sun4i-a10-cubieboard:rootfs
>> 	arm:cubieboard:multi_v7_defconfig:sata:mem512:sun4i-a10-cubieboard:rootfs
>>
>> The arm tests fail due to a compile error.
>>
>> drivers/clk/tegra/clk-tegra-periph.c:524:65: error: 'CLK_IS_CRITICAL' undeclared here (not in a function); did you mean 'CLK_IS_BASIC'?
> 
> I already looked at your first test results and dropped the patch that
> uses CLK_IS_CRITICAL, so there's something else going wrong there...
> 

Ah yes. Sorry, I didn't notice that there was a rebuild.

Images are fine; the three failing tests should not have been
tested in the first place (they never did, but I didn't update
the blacklist when I increased the qemu memory size to 512MB).

Guenter


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[relevance 6%]

* Re: [PATCH 3.16 35/99] pxa168fb: Fix the function used to release some memory in an error handling path
  2020-05-21 14:31  3%     ` Marion & Christophe JAILLET
@ 2020-05-21 20:28  9%       ` Ben Hutchings
  0 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-21 20:28 UTC (permalink / raw)
  To: Marion & Christophe JAILLET, linux-kernel, stable
  Cc: akpm, Denis Kirjanov, YueHaibing, Bartlomiej Zolnierkiewicz,
	Lubomir Rintel

[-- Attachment #1: Type: text/plain, Size: 3235 bytes --]

On Thu, 2020-05-21 at 16:31 +0200, Marion & Christophe JAILLET wrote:
> Hi,
> 
> sorry for the noise, I have messed up my 
> https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ usage.
> I thought I was looking at the 3.16.83 branch, but I was not.
> 
> The patch looks good to me.

Thanks for reviewing,

Ben.

> CJ
> 
> Le 21/05/2020 à 16:09, Marion & Christophe JAILLET a écrit :
> > Hi,
> > 
> > I don't think that this one is applicable to 3.16.x
> > 
> > The remove function and the error handling path of the probe function 
> > both use 'dma_free_wc'.
> > I've not look in details, but it looks consistent and the patch would 
> > not apply as-is anyway.
> > 
> > just my 2c.
> > 
> > CJ
> > 
> > Le 20/05/2020 à 16:14, Ben Hutchings a écrit :
> > > 3.16.84-rc1 review patch.  If anyone has any objections, please let 
> > > me know.
> > > 
> > > ------------------
> > > 
> > > From: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
> > > 
> > > commit 3c911fe799d1c338d94b78e7182ad452c37af897 upstream.
> > > 
> > > In the probe function, some resources are allocated using 
> > > 'dma_alloc_wc()',
> > > they should be released with 'dma_free_wc()', not 'dma_free_coherent()'.
> > > 
> > > We already use 'dma_free_wc()' in the remove function, but not in the
> > > error handling path of the probe function.
> > > 
> > > Also, remove a useless 'PAGE_ALIGN()'. 'info->fix.smem_len' is already
> > > PAGE_ALIGNed.
> > > 
> > > Fixes: 638772c7553f ("fb: add support of LCD display controller on 
> > > pxa168/910 (base layer)")
> > > Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
> > > Reviewed-by: Lubomir Rintel <lkundrak@v3.sk>
> > > CC: YueHaibing <yuehaibing@huawei.com>
> > > Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> > > Link: 
> > > https://patchwork.freedesktop.org/patch/msgid/20190831100024.3248-1-christophe.jaillet@wanadoo.fr
> > > [bwh: Backported to 3.16: Use dma_free_writecombine().]
> > > Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
> > > ---
> > >   drivers/video/fbdev/pxa168fb.c | 6 +++---
> > >   1 file changed, 3 insertions(+), 3 deletions(-)
> > > 
> > > --- a/drivers/video/fbdev/pxa168fb.c
> > > +++ b/drivers/video/fbdev/pxa168fb.c
> > > @@ -772,8 +772,8 @@ failed_free_cmap:
> > >   failed_free_clk:
> > >       clk_disable(fbi->clk);
> > >   failed_free_fbmem:
> > > -    dma_free_coherent(fbi->dev, info->fix.smem_len,
> > > -            info->screen_base, fbi->fb_start_dma);
> > > +    dma_free_writecombine(fbi->dev, info->fix.smem_len,
> > > +                  info->screen_base, fbi->fb_start_dma);
> > >   failed_free_info:
> > >       kfree(info);
> > >   failed_put_clk:
> > > @@ -809,7 +809,7 @@ static int pxa168fb_remove(struct platfo
> > >         irq = platform_get_irq(pdev, 0);
> > >   -    dma_free_writecombine(fbi->dev, PAGE_ALIGN(info->fix.smem_len),
> > > +    dma_free_writecombine(fbi->dev, info->fix.smem_len,
> > >                   info->screen_base, info->fix.smem_start);
> > >         clk_disable(fbi->clk);
> > > 
-- 
Ben Hutchings
Reality is just a crutch for people who can't handle science fiction.



[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[relevance 9%]

* Re: [PATCH 3.16 00/99] 3.16.84-rc1 review
  2020-05-21  7:40  3%     ` Guenter Roeck
@ 2020-05-21 20:22 13%       ` Ben Hutchings
  0 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-21 20:22 UTC (permalink / raw)
  To: Guenter Roeck, Chen-Yu Tsai
  Cc: linux-kernel, stable, torvalds, Andrew Morton, Denis Kirjanov

[-- Attachment #1: Type: text/plain, Size: 1837 bytes --]

On Thu, 2020-05-21 at 00:40 -0700, Guenter Roeck wrote:
> On 5/20/20 7:47 PM, Chen-Yu Tsai wrote:
> > On Thu, May 21, 2020 at 5:23 AM Guenter Roeck <linux@roeck-us.net> wrote:
> > > On 5/20/20 7:13 AM, Ben Hutchings wrote:
> > > > This is the start of the stable review cycle for the 3.16.84 release.
> > > > There are 99 patches in this series, which will be posted as responses
> > > > to this one.  If anyone has any issues with these being applied, please
> > > > let me know.
> > > > 
> > > > Responses should be made by Fri May 22 20:00:00 UTC 2020.
> > > > Anything received after that time might be too late.
> > > > 
> > > Build results:
> > >         total: 135 pass: 135 fail: 0
> > > Qemu test results:
> > >         total: 230 pass: 227 fail: 3
> > > Failed tests:
> > >         arm:cubieboard:multi_v7_defconfig:mem512:sun4i-a10-cubieboard:initrd
> > >         arm:cubieboard:multi_v7_defconfig:usb:mem512:sun4i-a10-cubieboard:rootfs
> > >         arm:cubieboard:multi_v7_defconfig:sata:mem512:sun4i-a10-cubieboard:rootfs
> > > 
> > > The arm tests fail due to a compile error.
> > > 
> > > drivers/clk/tegra/clk-tegra-periph.c:524:65: error: 'CLK_IS_CRITICAL' undeclared here (not in a function); did you mean 'CLK_IS_BASIC'?
> > 
> > This looks like a result of having
> > 
> >       clk: tegra: Mark fuse clock as critical
> >          [bf83b96f87ae2abb1e535306ea53608e8de5dfbb]
> > 
> > In which case you probably need to add
> > 
> >     32b9b1096186 clk: Allow clocks to be marked as CRITICAL
> > 
> 
> Then you might also need commit ef56b79b66f ("clk: fix critical
> clock locking") which fixes it.

At this stage I don't think it makes sense to add the feature to 3.16.

Ben.

-- 
Ben Hutchings
Reality is just a crutch for people who can't handle science fiction.



[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[relevance 13%]

* Re: [PATCH 3.16 00/99] 3.16.84-rc1 review
  2020-05-20 21:23  6% ` [PATCH 3.16 00/99] 3.16.84-rc1 review Guenter Roeck
  2020-05-21  2:47  3%   ` Chen-Yu Tsai
@ 2020-05-21 20:20  9%   ` Ben Hutchings
  2020-05-21 22:37  6%     ` Guenter Roeck
  1 sibling, 1 reply; 200+ results
From: Ben Hutchings @ 2020-05-21 20:20 UTC (permalink / raw)
  To: Guenter Roeck, linux-kernel, stable; +Cc: torvalds, akpm, Denis Kirjanov

[-- Attachment #1: Type: text/plain, Size: 1273 bytes --]

On Wed, 2020-05-20 at 14:23 -0700, Guenter Roeck wrote:
> On 5/20/20 7:13 AM, Ben Hutchings wrote:
> > This is the start of the stable review cycle for the 3.16.84 release.
> > There are 99 patches in this series, which will be posted as responses
> > to this one.  If anyone has any issues with these being applied, please
> > let me know.
> > 
> > Responses should be made by Fri May 22 20:00:00 UTC 2020.
> > Anything received after that time might be too late.
> > 
> Build results:
> 	total: 135 pass: 135 fail: 0
> Qemu test results:
> 	total: 230 pass: 227 fail: 3
> Failed tests:
> 	arm:cubieboard:multi_v7_defconfig:mem512:sun4i-a10-cubieboard:initrd
> 	arm:cubieboard:multi_v7_defconfig:usb:mem512:sun4i-a10-cubieboard:rootfs
> 	arm:cubieboard:multi_v7_defconfig:sata:mem512:sun4i-a10-cubieboard:rootfs
> 
> The arm tests fail due to a compile error.
> 
> drivers/clk/tegra/clk-tegra-periph.c:524:65: error: 'CLK_IS_CRITICAL' undeclared here (not in a function); did you mean 'CLK_IS_BASIC'?

I already looked at your first test results and dropped the patch that
uses CLK_IS_CRITICAL, so there's something else going wrong there...

Ben.

-- 
Ben Hutchings
Reality is just a crutch for people who can't handle science fiction.



[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[relevance 9%]

* Re: [PATCH 3.16 35/99] pxa168fb: Fix the function used to release some memory in an error handling path
  2020-05-21 14:09  9%   ` Marion & Christophe JAILLET
@ 2020-05-21 14:31  3%     ` Marion & Christophe JAILLET
  2020-05-21 20:28  9%       ` Ben Hutchings
  0 siblings, 1 reply; 200+ results
From: Marion & Christophe JAILLET @ 2020-05-21 14:31 UTC (permalink / raw)
  To: Ben Hutchings, linux-kernel, stable
  Cc: akpm, Denis Kirjanov, YueHaibing, Bartlomiej Zolnierkiewicz,
	Lubomir Rintel

Hi,

sorry for the noise, I have messed up my 
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ usage.
I thought I was looking at the 3.16.83 branch, but I was not.

The patch looks good to me.

CJ

Le 21/05/2020 à 16:09, Marion & Christophe JAILLET a écrit :
> Hi,
>
> I don't think that this one is applicable to 3.16.x
>
> The remove function and the error handling path of the probe function 
> both use 'dma_free_wc'.
> I've not look in details, but it looks consistent and the patch would 
> not apply as-is anyway.
>
> just my 2c.
>
> CJ
>
> Le 20/05/2020 à 16:14, Ben Hutchings a écrit :
>> 3.16.84-rc1 review patch.  If anyone has any objections, please let 
>> me know.
>>
>> ------------------
>>
>> From: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
>>
>> commit 3c911fe799d1c338d94b78e7182ad452c37af897 upstream.
>>
>> In the probe function, some resources are allocated using 
>> 'dma_alloc_wc()',
>> they should be released with 'dma_free_wc()', not 'dma_free_coherent()'.
>>
>> We already use 'dma_free_wc()' in the remove function, but not in the
>> error handling path of the probe function.
>>
>> Also, remove a useless 'PAGE_ALIGN()'. 'info->fix.smem_len' is already
>> PAGE_ALIGNed.
>>
>> Fixes: 638772c7553f ("fb: add support of LCD display controller on 
>> pxa168/910 (base layer)")
>> Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
>> Reviewed-by: Lubomir Rintel <lkundrak@v3.sk>
>> CC: YueHaibing <yuehaibing@huawei.com>
>> Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
>> Link: 
>> https://patchwork.freedesktop.org/patch/msgid/20190831100024.3248-1-christophe.jaillet@wanadoo.fr
>> [bwh: Backported to 3.16: Use dma_free_writecombine().]
>> Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
>> ---
>>   drivers/video/fbdev/pxa168fb.c | 6 +++---
>>   1 file changed, 3 insertions(+), 3 deletions(-)
>>
>> --- a/drivers/video/fbdev/pxa168fb.c
>> +++ b/drivers/video/fbdev/pxa168fb.c
>> @@ -772,8 +772,8 @@ failed_free_cmap:
>>   failed_free_clk:
>>       clk_disable(fbi->clk);
>>   failed_free_fbmem:
>> -    dma_free_coherent(fbi->dev, info->fix.smem_len,
>> -            info->screen_base, fbi->fb_start_dma);
>> +    dma_free_writecombine(fbi->dev, info->fix.smem_len,
>> +                  info->screen_base, fbi->fb_start_dma);
>>   failed_free_info:
>>       kfree(info);
>>   failed_put_clk:
>> @@ -809,7 +809,7 @@ static int pxa168fb_remove(struct platfo
>>         irq = platform_get_irq(pdev, 0);
>>   -    dma_free_writecombine(fbi->dev, PAGE_ALIGN(info->fix.smem_len),
>> +    dma_free_writecombine(fbi->dev, info->fix.smem_len,
>>                   info->screen_base, info->fix.smem_start);
>>         clk_disable(fbi->clk);
>>

^ permalink raw reply	[relevance 3%]

* Re: [PATCH 3.16 35/99] pxa168fb: Fix the function used to release some memory in an error handling path
  2020-05-20 14:14 12% ` [PATCH 3.16 35/99] pxa168fb: Fix the function used to release some memory in an error handling path Ben Hutchings
@ 2020-05-21 14:09  9%   ` Marion & Christophe JAILLET
  2020-05-21 14:31  3%     ` Marion & Christophe JAILLET
  0 siblings, 1 reply; 200+ results
From: Marion & Christophe JAILLET @ 2020-05-21 14:09 UTC (permalink / raw)
  To: Ben Hutchings, linux-kernel, stable
  Cc: akpm, Denis Kirjanov, YueHaibing, Bartlomiej Zolnierkiewicz,
	Lubomir Rintel

Hi,

I don't think that this one is applicable to 3.16.x

The remove function and the error handling path of the probe function 
both use 'dma_free_wc'.
I've not look in details, but it looks consistent and the patch would 
not apply as-is anyway.

just my 2c.

CJ

Le 20/05/2020 à 16:14, Ben Hutchings a écrit :
> 3.16.84-rc1 review patch.  If anyone has any objections, please let me know.
>
> ------------------
>
> From: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
>
> commit 3c911fe799d1c338d94b78e7182ad452c37af897 upstream.
>
> In the probe function, some resources are allocated using 'dma_alloc_wc()',
> they should be released with 'dma_free_wc()', not 'dma_free_coherent()'.
>
> We already use 'dma_free_wc()' in the remove function, but not in the
> error handling path of the probe function.
>
> Also, remove a useless 'PAGE_ALIGN()'. 'info->fix.smem_len' is already
> PAGE_ALIGNed.
>
> Fixes: 638772c7553f ("fb: add support of LCD display controller on pxa168/910 (base layer)")
> Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
> Reviewed-by: Lubomir Rintel <lkundrak@v3.sk>
> CC: YueHaibing <yuehaibing@huawei.com>
> Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> Link: https://patchwork.freedesktop.org/patch/msgid/20190831100024.3248-1-christophe.jaillet@wanadoo.fr
> [bwh: Backported to 3.16: Use dma_free_writecombine().]
> Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
> ---
>   drivers/video/fbdev/pxa168fb.c | 6 +++---
>   1 file changed, 3 insertions(+), 3 deletions(-)
>
> --- a/drivers/video/fbdev/pxa168fb.c
> +++ b/drivers/video/fbdev/pxa168fb.c
> @@ -772,8 +772,8 @@ failed_free_cmap:
>   failed_free_clk:
>   	clk_disable(fbi->clk);
>   failed_free_fbmem:
> -	dma_free_coherent(fbi->dev, info->fix.smem_len,
> -			info->screen_base, fbi->fb_start_dma);
> +	dma_free_writecombine(fbi->dev, info->fix.smem_len,
> +			      info->screen_base, fbi->fb_start_dma);
>   failed_free_info:
>   	kfree(info);
>   failed_put_clk:
> @@ -809,7 +809,7 @@ static int pxa168fb_remove(struct platfo
>   
>   	irq = platform_get_irq(pdev, 0);
>   
> -	dma_free_writecombine(fbi->dev, PAGE_ALIGN(info->fix.smem_len),
> +	dma_free_writecombine(fbi->dev, info->fix.smem_len,
>   				info->screen_base, info->fix.smem_start);
>   
>   	clk_disable(fbi->clk);
>

^ permalink raw reply	[relevance 9%]

* Re: [PATCH 3.16 00/99] 3.16.84-rc1 review
  2020-05-21  2:47  3%   ` Chen-Yu Tsai
@ 2020-05-21  7:40  3%     ` Guenter Roeck
  2020-05-21 20:22 13%       ` Ben Hutchings
  0 siblings, 1 reply; 200+ results
From: Guenter Roeck @ 2020-05-21  7:40 UTC (permalink / raw)
  To: Chen-Yu Tsai, Ben Hutchings
  Cc: linux-kernel, stable, torvalds, Andrew Morton, Denis Kirjanov

On 5/20/20 7:47 PM, Chen-Yu Tsai wrote:
> On Thu, May 21, 2020 at 5:23 AM Guenter Roeck <linux@roeck-us.net> wrote:
>>
>> On 5/20/20 7:13 AM, Ben Hutchings wrote:
>>> This is the start of the stable review cycle for the 3.16.84 release.
>>> There are 99 patches in this series, which will be posted as responses
>>> to this one.  If anyone has any issues with these being applied, please
>>> let me know.
>>>
>>> Responses should be made by Fri May 22 20:00:00 UTC 2020.
>>> Anything received after that time might be too late.
>>>
>> Build results:
>>         total: 135 pass: 135 fail: 0
>> Qemu test results:
>>         total: 230 pass: 227 fail: 3
>> Failed tests:
>>         arm:cubieboard:multi_v7_defconfig:mem512:sun4i-a10-cubieboard:initrd
>>         arm:cubieboard:multi_v7_defconfig:usb:mem512:sun4i-a10-cubieboard:rootfs
>>         arm:cubieboard:multi_v7_defconfig:sata:mem512:sun4i-a10-cubieboard:rootfs
>>
>> The arm tests fail due to a compile error.
>>
>> drivers/clk/tegra/clk-tegra-periph.c:524:65: error: 'CLK_IS_CRITICAL' undeclared here (not in a function); did you mean 'CLK_IS_BASIC'?
> 
> This looks like a result of having
> 
>       clk: tegra: Mark fuse clock as critical
>          [bf83b96f87ae2abb1e535306ea53608e8de5dfbb]
> 
> In which case you probably need to add
> 
>     32b9b1096186 clk: Allow clocks to be marked as CRITICAL
> 

Then you might also need commit ef56b79b66f ("clk: fix critical
clock locking") which fixes it.

Guenter

^ permalink raw reply	[relevance 3%]

* Re: [PATCH 3.16 00/99] 3.16.84-rc1 review
  2020-05-20 21:23  6% ` [PATCH 3.16 00/99] 3.16.84-rc1 review Guenter Roeck
@ 2020-05-21  2:47  3%   ` Chen-Yu Tsai
  2020-05-21  7:40  3%     ` Guenter Roeck
  2020-05-21 20:20  9%   ` Ben Hutchings
  1 sibling, 1 reply; 200+ results
From: Chen-Yu Tsai @ 2020-05-21  2:47 UTC (permalink / raw)
  To: Ben Hutchings
  Cc: linux-kernel, stable, torvalds, Andrew Morton, Denis Kirjanov,
	Guenter Roeck

On Thu, May 21, 2020 at 5:23 AM Guenter Roeck <linux@roeck-us.net> wrote:
>
> On 5/20/20 7:13 AM, Ben Hutchings wrote:
> > This is the start of the stable review cycle for the 3.16.84 release.
> > There are 99 patches in this series, which will be posted as responses
> > to this one.  If anyone has any issues with these being applied, please
> > let me know.
> >
> > Responses should be made by Fri May 22 20:00:00 UTC 2020.
> > Anything received after that time might be too late.
> >
> Build results:
>         total: 135 pass: 135 fail: 0
> Qemu test results:
>         total: 230 pass: 227 fail: 3
> Failed tests:
>         arm:cubieboard:multi_v7_defconfig:mem512:sun4i-a10-cubieboard:initrd
>         arm:cubieboard:multi_v7_defconfig:usb:mem512:sun4i-a10-cubieboard:rootfs
>         arm:cubieboard:multi_v7_defconfig:sata:mem512:sun4i-a10-cubieboard:rootfs
>
> The arm tests fail due to a compile error.
>
> drivers/clk/tegra/clk-tegra-periph.c:524:65: error: 'CLK_IS_CRITICAL' undeclared here (not in a function); did you mean 'CLK_IS_BASIC'?

This looks like a result of having

      clk: tegra: Mark fuse clock as critical
         [bf83b96f87ae2abb1e535306ea53608e8de5dfbb]

In which case you probably need to add

    32b9b1096186 clk: Allow clocks to be marked as CRITICAL

to the pile.


ChenYu

^ permalink raw reply	[relevance 3%]

* Re: [PATCH 3.16 00/99] 3.16.84-rc1 review
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (98 preceding siblings ...)
  2020-05-20 14:15 12% ` [PATCH 3.16 99/99] sunrpc: expiry_time should be seconds not timeval Ben Hutchings
@ 2020-05-20 21:23  6% ` Guenter Roeck
  2020-05-21  2:47  3%   ` Chen-Yu Tsai
  2020-05-21 20:20  9%   ` Ben Hutchings
  99 siblings, 2 replies; 200+ results
From: Guenter Roeck @ 2020-05-20 21:23 UTC (permalink / raw)
  To: Ben Hutchings, linux-kernel, stable; +Cc: torvalds, akpm, Denis Kirjanov

On 5/20/20 7:13 AM, Ben Hutchings wrote:
> This is the start of the stable review cycle for the 3.16.84 release.
> There are 99 patches in this series, which will be posted as responses
> to this one.  If anyone has any issues with these being applied, please
> let me know.
> 
> Responses should be made by Fri May 22 20:00:00 UTC 2020.
> Anything received after that time might be too late.
> 
Build results:
	total: 135 pass: 135 fail: 0
Qemu test results:
	total: 230 pass: 227 fail: 3
Failed tests:
	arm:cubieboard:multi_v7_defconfig:mem512:sun4i-a10-cubieboard:initrd
	arm:cubieboard:multi_v7_defconfig:usb:mem512:sun4i-a10-cubieboard:rootfs
	arm:cubieboard:multi_v7_defconfig:sata:mem512:sun4i-a10-cubieboard:rootfs

The arm tests fail due to a compile error.

drivers/clk/tegra/clk-tegra-periph.c:524:65: error: 'CLK_IS_CRITICAL' undeclared here (not in a function); did you mean 'CLK_IS_BASIC'?

Guenter

^ permalink raw reply	[relevance 6%]

* Re: [PATCH 3.16 43/99] efi: Use early_mem*() instead of early_io*()
  2020-05-20 14:14  7% ` [PATCH 3.16 43/99] efi: Use early_mem*() instead of early_io*() Ben Hutchings
@ 2020-05-20 15:53 10%   ` Ben Hutchings
  0 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 15:53 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Daniel Kiper, Matt Fleming, Mark Salter,
	Leif Lindholm

[-- Attachment #1: Type: text/plain, Size: 6594 bytes --]

On Wed, 2020-05-20 at 15:14 +0100, Ben Hutchings wrote:
> 3.16.84-rc1 review patch.  If anyone has any objections, please let me know.
> 
> ------------------
> 
> From: Daniel Kiper <daniel.kiper@oracle.com>
> 
> commit abc93f8eb6e46a480485f19256bdbda36ec78a84 upstream.

I've now seen that this depends on the preceding commit 4fa62481e231
"arch/ia64: Define early_memunmap()".  I've queued that up as well.

Ben.

> Use early_mem*() instead of early_io*() because all mapped EFI regions
> are memory (usually RAM but they could also be ROM, EPROM, EEPROM, flash,
> etc.) not I/O regions. Additionally, I/O family calls do not work correctly
> under Xen in our case. early_ioremap() skips the PFN to MFN conversion
> when building the PTE. Using it for memory will attempt to map the wrong
> machine frame. However, all artificial EFI structures created under Xen
> live in dom0 memory and should be mapped/unmapped using early_mem*() family
> calls which map domain memory.
> 
> Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
> Cc: Leif Lindholm <leif.lindholm@linaro.org>
> Cc: Mark Salter <msalter@redhat.com>
> Signed-off-by: Matt Fleming <matt.fleming@intel.com>
> Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
> ---
>  arch/x86/platform/efi/efi.c | 28 ++++++++++++++--------------
>  drivers/firmware/efi/efi.c  |  4 ++--
>  2 files changed, 16 insertions(+), 16 deletions(-)
> 
> --- a/arch/x86/platform/efi/efi.c
> +++ b/arch/x86/platform/efi/efi.c
> @@ -435,7 +435,7 @@ void __init efi_unmap_memmap(void)
>  {
>  	clear_bit(EFI_MEMMAP, &efi.flags);
>  	if (memmap.map) {
> -		early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size);
> +		early_memunmap(memmap.map, memmap.nr_map * memmap.desc_size);
>  		memmap.map = NULL;
>  	}
>  }
> @@ -475,12 +475,12 @@ static int __init efi_systab_init(void *
>  			if (!data)
>  				return -ENOMEM;
>  		}
> -		systab64 = early_ioremap((unsigned long)phys,
> +		systab64 = early_memremap((unsigned long)phys,
>  					 sizeof(*systab64));
>  		if (systab64 == NULL) {
>  			pr_err("Couldn't map the system table!\n");
>  			if (data)
> -				early_iounmap(data, sizeof(*data));
> +				early_memunmap(data, sizeof(*data));
>  			return -ENOMEM;
>  		}
>  
> @@ -512,9 +512,9 @@ static int __init efi_systab_init(void *
>  					   systab64->tables;
>  		tmp |= data ? data->tables : systab64->tables;
>  
> -		early_iounmap(systab64, sizeof(*systab64));
> +		early_memunmap(systab64, sizeof(*systab64));
>  		if (data)
> -			early_iounmap(data, sizeof(*data));
> +			early_memunmap(data, sizeof(*data));
>  #ifdef CONFIG_X86_32
>  		if (tmp >> 32) {
>  			pr_err("EFI data located above 4GB, disabling EFI.\n");
> @@ -524,7 +524,7 @@ static int __init efi_systab_init(void *
>  	} else {
>  		efi_system_table_32_t *systab32;
>  
> -		systab32 = early_ioremap((unsigned long)phys,
> +		systab32 = early_memremap((unsigned long)phys,
>  					 sizeof(*systab32));
>  		if (systab32 == NULL) {
>  			pr_err("Couldn't map the system table!\n");
> @@ -545,7 +545,7 @@ static int __init efi_systab_init(void *
>  		efi_systab.nr_tables = systab32->nr_tables;
>  		efi_systab.tables = systab32->tables;
>  
> -		early_iounmap(systab32, sizeof(*systab32));
> +		early_memunmap(systab32, sizeof(*systab32));
>  	}
>  
>  	efi.systab = &efi_systab;
> @@ -571,7 +571,7 @@ static int __init efi_runtime_init32(voi
>  {
>  	efi_runtime_services_32_t *runtime;
>  
> -	runtime = early_ioremap((unsigned long)efi.systab->runtime,
> +	runtime = early_memremap((unsigned long)efi.systab->runtime,
>  			sizeof(efi_runtime_services_32_t));
>  	if (!runtime) {
>  		pr_err("Could not map the runtime service table!\n");
> @@ -586,7 +586,7 @@ static int __init efi_runtime_init32(voi
>  	efi_phys.set_virtual_address_map =
>  			(efi_set_virtual_address_map_t *)
>  			(unsigned long)runtime->set_virtual_address_map;
> -	early_iounmap(runtime, sizeof(efi_runtime_services_32_t));
> +	early_memunmap(runtime, sizeof(efi_runtime_services_32_t));
>  
>  	return 0;
>  }
> @@ -595,7 +595,7 @@ static int __init efi_runtime_init64(voi
>  {
>  	efi_runtime_services_64_t *runtime;
>  
> -	runtime = early_ioremap((unsigned long)efi.systab->runtime,
> +	runtime = early_memremap((unsigned long)efi.systab->runtime,
>  			sizeof(efi_runtime_services_64_t));
>  	if (!runtime) {
>  		pr_err("Could not map the runtime service table!\n");
> @@ -610,7 +610,7 @@ static int __init efi_runtime_init64(voi
>  	efi_phys.set_virtual_address_map =
>  			(efi_set_virtual_address_map_t *)
>  			(unsigned long)runtime->set_virtual_address_map;
> -	early_iounmap(runtime, sizeof(efi_runtime_services_64_t));
> +	early_memunmap(runtime, sizeof(efi_runtime_services_64_t));
>  
>  	return 0;
>  }
> @@ -641,7 +641,7 @@ static int __init efi_runtime_init(void)
>  static int __init efi_memmap_init(void)
>  {
>  	/* Map the EFI memory map */
> -	memmap.map = early_ioremap((unsigned long)memmap.phys_map,
> +	memmap.map = early_memremap((unsigned long)memmap.phys_map,
>  				   memmap.nr_map * memmap.desc_size);
>  	if (memmap.map == NULL) {
>  		pr_err("Could not map the memory map!\n");
> @@ -745,14 +745,14 @@ void __init efi_init(void)
>  	/*
>  	 * Show what we know for posterity
>  	 */
> -	c16 = tmp = early_ioremap(efi.systab->fw_vendor, 2);
> +	c16 = tmp = early_memremap(efi.systab->fw_vendor, 2);
>  	if (c16) {
>  		for (i = 0; i < sizeof(vendor) - 1 && *c16; ++i)
>  			vendor[i] = *c16++;
>  		vendor[i] = '\0';
>  	} else
>  		pr_err("Could not map the firmware vendor!\n");
> -	early_iounmap(tmp, 2);
> +	early_memunmap(tmp, 2);
>  
>  	pr_info("EFI v%u.%.02u by %s\n",
>  		efi.systab->hdr.revision >> 16,
> --- a/drivers/firmware/efi/efi.c
> +++ b/drivers/firmware/efi/efi.c
> @@ -295,7 +295,7 @@ int __init efi_config_init(efi_config_ta
>  			if (table64 >> 32) {
>  				pr_cont("\n");
>  				pr_err("Table located above 4GB, disabling EFI.\n");
> -				early_iounmap(config_tables,
> +				early_memunmap(config_tables,
>  					       efi.systab->nr_tables * sz);
>  				return -EINVAL;
>  			}
> @@ -311,7 +311,7 @@ int __init efi_config_init(efi_config_ta
>  		tablep += sz;
>  	}
>  	pr_cont("\n");
> -	early_iounmap(config_tables, efi.systab->nr_tables * sz);
> +	early_memunmap(config_tables, efi.systab->nr_tables * sz);
>  
>  	set_bit(EFI_CONFIG_TABLES, &efi.flags);
>  
> 
-- 
Ben Hutchings
All the simple programs have been written, and all the good names taken


[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[relevance 10%]

* Re: [PATCH 3.16 37/99] clk: tegra: Mark fuse clock as critical
  2020-05-20 14:14  9% ` [PATCH 3.16 37/99] clk: tegra: Mark fuse clock as critical Ben Hutchings
@ 2020-05-20 15:51 13%   ` Ben Hutchings
  0 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 15:51 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Jonathan Hunter, Thierry Reding, Stephen Warren

[-- Attachment #1: Type: text/plain, Size: 2230 bytes --]

On Wed, 2020-05-20 at 15:14 +0100, Ben Hutchings wrote:
> 3.16.84-rc1 review patch.  If anyone has any objections, please let me know.
> 
> ------------------
> 
> From: Stephen Warren <swarren@nvidia.com>
> 
> commit bf83b96f87ae2abb1e535306ea53608e8de5dfbb upstream.

I've now dropped this, as CLK_IS_CRITICAL is not implemented on 3.16.

Ben.

> For a little over a year, U-Boot on Tegra124 has configured the flow
> controller to perform automatic RAM re-repair on off->on power
> transitions of the CPU rail[1]. This is mandatory for correct operation
> of Tegra124. However, RAM re-repair relies on certain clocks, which the
> kernel must enable and leave running. The fuse clock is one of those
> clocks. Mark this clock as critical so that LP1 power mode (system
> suspend) operates correctly.
> 
> [1] 3cc7942a4ae5 ARM: tegra: implement RAM repair
> 
> Reported-by: Jonathan Hunter <jonathanh@nvidia.com>
> Signed-off-by: Stephen Warren <swarren@nvidia.com>
> Signed-off-by: Thierry Reding <treding@nvidia.com>
> Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
> ---
>  drivers/clk/tegra/clk-tegra-periph.c | 6 +++++-
>  1 file changed, 5 insertions(+), 1 deletion(-)
> 
> --- a/drivers/clk/tegra/clk-tegra-periph.c
> +++ b/drivers/clk/tegra/clk-tegra-periph.c
> @@ -517,7 +517,11 @@ static struct tegra_periph_init_data gat
>  	GATE("vcp", "clk_m", 29, 0, tegra_clk_vcp, 0),
>  	GATE("apbdma", "clk_m", 34, 0, tegra_clk_apbdma, 0),
>  	GATE("kbc", "clk_32k", 36, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_kbc, 0),
> -	GATE("fuse", "clk_m", 39, TEGRA_PERIPH_ON_APB, tegra_clk_fuse, 0),
> +	/*
> +	 * Critical for RAM re-repair operation, which must occur on resume
> +	 * from LP1 system suspend and as part of CCPLEX cluster switching.
> +	 */
> +	GATE("fuse", "clk_m", 39, TEGRA_PERIPH_ON_APB, tegra_clk_fuse, CLK_IS_CRITICAL),
>  	GATE("fuse_burn", "clk_m", 39, TEGRA_PERIPH_ON_APB, tegra_clk_fuse_burn, 0),
>  	GATE("kfuse", "clk_m", 40, TEGRA_PERIPH_ON_APB, tegra_clk_kfuse, 0),
>  	GATE("apbif", "clk_m", 107, TEGRA_PERIPH_ON_APB, tegra_clk_apbif, 0),
> 
-- 
Ben Hutchings
All the simple programs have been written, and all the good names taken



[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[relevance 13%]

* [PATCH 3.16 00/99] 3.16.84-rc1 review
@ 2020-05-20 14:13  6% Ben Hutchings
  2020-05-20 14:13  9% ` [PATCH 3.16 01/99] fs/namespace.c: fix mountpoint reference counter race Ben Hutchings
                   ` (99 more replies)
  0 siblings, 100 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:13 UTC (permalink / raw)
  To: linux-kernel, stable; +Cc: torvalds, Guenter Roeck, akpm, Denis Kirjanov

This is the start of the stable review cycle for the 3.16.84 release.
There are 99 patches in this series, which will be posted as responses
to this one.  If anyone has any issues with these being applied, please
let me know.

Responses should be made by Fri May 22 20:00:00 UTC 2020.
Anything received after that time might be too late.

All the patches have also been committed to the linux-3.16.y-rc branch of
https://git.kernel.org/pub/scm/linux/kernel/git/bwh/linux-stable-rc.git .
A shortlog and diffstat can be found below.

Ben.

-------------

Al Viro (1):
      propagate_one(): mnt_set_mountpoint() needs mount_lock
         [b0d3869ce9eeacbb1bbd541909beeef4126426d5]

Alexandre Belloni (2):
      ARM: dts: at91: sama5d3: define clock rate range for tcb1
         [a7e0f3fc01df4b1b7077df777c37feae8c9e8b6d]
      ARM: dts: at91: sama5d3: fix maximum peripheral clock rates
         [ee0aa926ddb0bd8ba59e33e3803b3b5804e3f5da]

Ard Biesheuvel (1):
      efi/x86: Map the entire EFI vendor string before copying it
         [ffc2760bcf2dba0dbef74013ed73eea8310cc52c]

Arnd Bergmann (2):
      sparc32: fix struct ipc64_perm type definition
         [34ca70ef7d3a9fa7e89151597db5e37ae1d429b4]
      x86: kvm: avoid unused variable warning
         [7288bde1f9df6c1475675419bdd7725ce84dec56]

Bin Liu (1):
      usb: dwc3: turn off VBUS when leaving host mode
         [09ed259fac621634d51cd986aa8d65f035662658]

Bryan O'Donoghue (2):
      usb: gadget: f_ecm: Use atomic_t to track in-flight request
         [d710562e01c48d59be3f60d58b7a85958b39aeda]
      usb: gadget: f_ncm: Use atomic_t to track in-flight request
         [5b24c28cfe136597dc3913e1c00b119307a20c7e]

Chen Yucong (1):
      kvm: x86: use macros to compute bank MSRs
         [81760dccf8d1fe5b128b58736fe3f56a566133cb]

Christoffer Dall (1):
      KVM: arm64: Only sign-extend MMIO up to register width
         [b6ae256afd32f96bec0117175b329d0dd617655e]

Christophe JAILLET (1):
      pxa168fb: Fix the function used to release some memory in an error handling path
         [3c911fe799d1c338d94b78e7182ad452c37af897]

Chuhong Yuan (1):
      crypto: picoxcell - adjust the position of tasklet_init and fix missed tasklet_kill
         [7f8c36fe9be46862c4f3c5302f769378028a34fa]

Colin Ian King (2):
      iwlegacy: ensure loop counter addr does not wrap and cause an infinite loop
         [c2f9a4e4a5abfc84c01b738496b3fd2d471e0b18]
      staging: wlan-ng: ensure error return is actually returned
         [4cc41cbce536876678b35e03c4a8a7bb72c78fa9]

Dan Carpenter (3):
      brcmfmac: Fix use after free in brcmf_sdio_readframes()
         [216b44000ada87a63891a8214c347e05a4aea8fe]
      mm/mempolicy.c: fix out of bounds write in mpol_parse_str()
         [c7a91bc7c2e17e0a9c8b9745a2cb118891218fd1]
      power: supply: sbs-battery: Fix a signedness bug in sbs_get_battery_capacity()
         [eb368de6de32925c65a97c1e929a31cae2155aee]

Daniel Jordan (3):
      padata: always acquire cpu_hotplug_lock before pinst->lock
         [38228e8848cd7dd86ccb90406af32de0cad24be3]
      padata: initialize pd->cpu with effective cpumask
         [ec9c7d19336ee98ecba8de80128aa405c45feebb]
      padata: purge get_cpu and reorder_via_wq from padata_do_serial
         [065cf577135a4977931c7a1e1edf442bfd9773dd]

Daniel Kiper (1):
      efi: Use early_mem*() instead of early_io*()
         [abc93f8eb6e46a480485f19256bdbda36ec78a84]

Eric Dumazet (4):
      bonding/alb: properly access headers in bond_alb_xmit()
         [38f88c45404293bbc027b956def6c10cbd45c616]
      cls_rsvp: fix rsvp_policy
         [cb3c0e6bdf64d0d124e94ce43cbe4ccbb9b37f51]
      net_sched: ematch: reject invalid TCF_EM_SIMPLE
         [55cd9f67f1e45de8517cdaab985fb8e56c0bc1d8]
      tcp: clear tp->total_retrans in tcp_disconnect()
         [c13c48c00a6bc1febc73902505bdec0967bd7095]

Fabian Frederick (1):
      nfs: use kmap/kunmap directly
         [0795bf8357c1887e2a95e6e4f5b89d0896a0d929]

Filipe Manana (1):
      Btrfs: fix race between adding and putting tree mod seq elements and nodes
         [7227ff4de55d931bbdc156c8ef0ce4f100c78a5b]

Geert Uytterhoeven (1):
      nfs: NFS_SWAP should depend on SWAP
         [474c4f306eefbb21b67ebd1de802d005c7d7ecdc]

Guenter Roeck (1):
      brcmfmac: abort and release host after error
         [863844ee3bd38219c88e82966d1df36a77716f3e]

Herbert Xu (7):
      crypto: af_alg - Use bh_lock_sock in sk_destruct
         [37f96694cf73ba116993a9d2d99ad6a75fa7fdb0]
      crypto: api - Check spawn->alg under lock in crypto_drop_spawn
         [7db3b61b6bba4310f454588c2ca6faf2958ad79f]
      crypto: api - Fix race condition in crypto_spawn_alg
         [73669cc556462f4e50376538d77ee312142e8a8a]
      crypto: pcrypt - Do not clear MAY_SLEEP flag in original request
         [e8d998264bffade3cfe0536559f712ab9058d654]
      crypto: pcrypt - Fix user-after-free on module unload
         [07bfd9bdf568a38d9440c607b72342036011f727]
      padata: Remove broken queue flushing
         [07928d9bfc81640bab36f5190e8725894d93b659]
      padata: Replace delayed timer with immediate workqueue in padata_reorder
         [6fc4dbcf0276279d488c5fbbfabe94734134f4fa]

Jan Kara (2):
      reiserfs: Fix memory leak of journal device string
         [5474ca7da6f34fa95e82edc747d5faa19cbdfb5c]
      reiserfs: Fix spurious unlock in reiserfs_fill_super() error handling
         [4d5c1adaf893b8aa52525d2b81995e949bcb3239]

Jason A. Donenfeld (2):
      padata: avoid race in reordering
         [de5540d088fe97ad583cc7d396586437b32149a5]
      padata: get_next is never NULL
         [69b348449bda0f9588737539cfe135774c9939a7]

Joe Thornber (1):
      dm space map common: fix to ensure new block isn't already in use
         [4feaef830de7ffdd8352e1fe14ad3bf13c9688f8]

Johan Hovold (10):
      USB: serial: ir-usb: add missing endpoint sanity check
         [2988a8ae7476fe9535ab620320790d1714bdad1d]
      USB: serial: ir-usb: fix IrLAP framing
         [38c0d5bdf4973f9f5a888166e9d3e9ed0d32057a]
      USB: serial: ir-usb: fix link-speed handling
         [17a0184ca17e288decdca8b2841531e34d49285f]
      ath9k: fix storage endpoint lookup
         [0ef332951e856efa89507cdd13ba8f4fb8d4db12]
      brcmfmac: fix interface sanity check
         [3428fbcd6e6c0850b1a8b2a12082b7b2aabb3da3]
      media: iguanair: fix endpoint sanity check
         [1b257870a78b0a9ce98fdfb052c58542022ffb5b]
      orinoco_usb: fix interface sanity check
         [b73e05aa543cf8db4f4927e36952360d71291d41]
      rsi: fix use-after-free on failed probe and unbind
         [e93cd35101b61e4c79149be2cfc927c4b28dc60c]
      rsi_91x_usb: fix interface sanity check
         [3139b180906af43bc09bd3373fc2338a8271d9d9]
      zd1211rw: fix storage endpoint lookup
         [2d68bb2687abb747558b933e80845ff31570a49c]

John Hubbard (1):
      media/v4l2-core: set pages dirty upon releasing DMA buffers
         [3c7470b6f68434acae459482ab920d1e3fabd1c7]

Kai Li (1):
      jbd2: clear JBD2_ABORT flag before journal_reset to update log tail info when load journal
         [a09decff5c32060639a685581c380f51b14e1fc2]

Konstantin Khlebnikov (1):
      clocksource: Prevent double add_timer_on() for watchdog_timer
         [febac332a819f0e764aa4da62757ba21d18c182b]

Linus Walleij (1):
      mmc: spi: Toggle SPI polarity, do not hardcode it
         [af3ed119329cf9690598c5a562d95dfd128e91d6]

Logan Gunthorpe (1):
      PCI: Don't disable bridge BARs when assigning bus resources
         [9db8dc6d0785225c42a37be7b44d1b07b31b8957]

Luis Henriques (1):
      tracing: Fix tracing_stat return values in error handling paths
         [afccc00f75bbbee4e4ae833a96c2d29a7259c693]

Marios Pomonis (7):
      KVM: x86: Protect DR-based index computations from Spectre-v1/L1TF attacks
         [ea740059ecb37807ba47b84b33d1447435a8d868]
      KVM: x86: Protect MSR-based index computations from Spectre-v1/L1TF attacks in x86.c
         [6ec4c5eee1750d5d17951c4e1960d953376a0dda]
      KVM: x86: Protect ioapic_read_indirect() from Spectre-v1/L1TF attacks
         [8c86405f606ca8508b8d9280680166ca26723695]
      KVM: x86: Protect ioapic_write_indirect() from Spectre-v1/L1TF attacks
         [670564559ca35b439c8d8861fc399451ddf95137]
      KVM: x86: Protect kvm_lapic_reg_write() from Spectre-v1/L1TF attacks
         [4bf79cb089f6b1c6c632492c0271054ce52ad766]
      KVM: x86: Protect x86_decode_insn from Spectre-v1/L1TF attacks
         [3c9053a2cae7ba2ba73766a34cea41baa70f57f7]
      KVM: x86: Refactor picdev_write() to prevent Spectre-v1/L1TF attacks
         [14e32321f3606e4b0970200b6e5e47ee6f1e6410]

Masahiro Yamada (1):
      kconfig: fix broken dependency in randconfig-generated .config
         [c8fb7d7e48d11520ad24808cfce7afb7b9c9f798]

Mathias Krause (2):
      padata: ensure padata_do_serial() runs on the correct CPU
         [350ef88e7e922354f82a931897ad4a4ce6c686ff]
      padata: ensure the reorder timer callback runs on the correct CPU
         [cf5868c8a22dc2854b96e9569064bb92365549ca]

Miaohe Lin (1):
      KVM: nVMX: vmread should not set rflags to specify success in case of #PF
         [a4d956b9390418623ae5d07933e2679c68b6f83c]

Michael Ellerman (1):
      of: Add OF_DMA_DEFAULT_COHERENT & select it on powerpc
         [dabf6b36b83a18d57e3d4b9d50544ed040d86255]

Navid Emamdoost (1):
      brcmfmac: Fix memory leak in brcmf_usbdev_qinit
         [4282dc057d750c6a7dd92953564b15c26b54c22c]

Oliver Neukum (1):
      media: iguanair: add sanity checks
         [ab1cbdf159beba7395a13ab70bc71180929ca064]

Paul Kocialkowski (1):
      rtc: hym8563: Return -EINVAL if the time is known to be invalid
         [f236a2a2ebabad0848ad0995af7ad1dc7029e895]

Pawan Gupta (1):
      x86/cpu: Update cached HLE state on write to TSX_CTRL_CPUID_CLEAR
         [5efc6fa9044c3356d6046c6e1da6d02572dbed6b]

Piotr Krysiuk (1):
      fs/namespace.c: fix mountpoint reference counter race
         [2763d11912317a12318135ca03e592bb6df65624]

Quinn Tran (1):
      scsi: qla2xxx: Fix mtcp dump collection failure
         [641e0efddcbde52461e017136acd3ce7f2ef0c14]

Roberto Bergantinos Corpas (1):
      sunrpc: expiry_time should be seconds not timeval
         [3d96208c30f84d6edf9ab4fac813306ac0d20c10]

Ronnie Sahlberg (1):
      cifs: fail i/o on soft mounts if sessionsetup errors out
         [b0dd940e582b6a60296b9847a54012a4b080dc72]

Sean Christopherson (6):
      KVM: Check for a bad hva before dropping into the ghc slow path
         [fcfbc617547fc6d9552cb6c1c563b6a90ee98085]
      KVM: PPC: Book3S HV: Uninit vCPU if vcore creation fails
         [1a978d9d3e72ddfa40ac60d26301b154247ee0bc]
      KVM: PPC: Book3S PR: Free shared page if mmu initialization fails
         [cb10bf9194f4d2c5d830eddca861f7ca0fecdbb4]
      KVM: x86/mmu: Apply max PA check for MMIO sptes to 32-bit KVM
         [e30a7d623dccdb3f880fbcad980b0cb589a1da45]
      KVM: x86: Don't let userspace set host-reserved cr4 bits
         [b11306b53b2540c6ba068c4deddb6a17d9f8d95b]
      KVM: x86: Free wbinvd_dirty_mask if vCPU creation fails
         [16be9ddea268ad841457a59109963fff8c9de38d]

Stephen Warren (2):
      ARM: tegra: Enable PLLP bypass during Tegra124 LP1
         [1a3388d506bf5b45bb283e6a4c4706cfb4897333]
      clk: tegra: Mark fuse clock as critical
         [bf83b96f87ae2abb1e535306ea53608e8de5dfbb]

Steven Rostedt (1):
      tracing: Fix very unlikely race of registering two stat tracers
         [dfb6cd1e654315168e36d947471bd2a0ccd834ae]

Takashi Iwai (2):
      ALSA: dummy: Fix PCM format loop in proc output
         [2acf25f13ebe8beb40e97a1bbe76f36277c64f1e]
      ALSA: sh: Fix compile warning wrt const
         [f1dd4795b1523fbca7ab4344dd5a8bb439cc770d]

Tobias Klauser (1):
      padata: Remove unused but set variables
         [119a0798dc42ed4c4f96d39b8b676efcea73aec6]

Trond Myklebust (2):
      NFS: Directory page cache pages need to be locked when read
         [114de38225d9b300f027e2aec9afbb6e0def154b]
      NFS: Fix memory leaks and corruption in readdir
         [4b310319c6a8ce708f1033d57145e2aa027a883c]

Vincent Whitchurch (1):
      CIFS: Fix task struct use-after-free on reconnect
         [f1f27ad74557e39f67a8331a808b860f89254f2d]

Vladimir Oltean (1):
      gianfar: Fix TX timestamping with a stacked DSA driver
         [c26a2c2ddc0115eb088873f5c309cf46b982f522]

Will Deacon (1):
      media: uvcvideo: Avoid cyclic entity chains due to malformed USB descriptors
         [68035c80e129c4cfec659aac4180354530b26527]

Wuxu.Wu (1):
      spi: spi-dw: Add lock protect dw_spi rx/tx to prevent concurrent calls
         [19b61392c5a852b4e8a0bf35aecb969983c5932d]

Zhangyi (2):
      ext4, jbd2: ensure panic when aborting with zero errno
         [51f57b01e4a3c7d7bdceffd84de35144e8c538e7]
      jbd2: switch to use jbd2_journal_abort() when failed to submit the commit record
         [d0a186e0d3e7ac05cc77da7c157dae5aa59f95d9]

Zhihao Cheng (1):
      ubifs: Fix deadlock in concurrent bulk-read and writepage
         [f5de5b83303e61b1f3fb09bd77ce3ac2d7a475f2]

 Makefile                                           |   4 +-
 arch/arm/boot/dts/sama5d3.dtsi                     |  26 ++--
 arch/arm/boot/dts/sama5d3_can.dtsi                 |   4 +-
 arch/arm/boot/dts/sama5d3_tcb1.dtsi                |   1 +
 arch/arm/boot/dts/sama5d3_uart.dtsi                |   4 +-
 arch/arm/include/asm/kvm_emulate.h                 |   5 +
 arch/arm/include/asm/kvm_mmio.h                    |   2 +
 arch/arm/kvm/mmio.c                                |   6 +
 arch/arm/mach-tegra/sleep-tegra30.S                |  11 ++
 arch/arm64/include/asm/kvm_emulate.h               |   5 +
 arch/arm64/include/asm/kvm_mmio.h                  |   6 +-
 arch/powerpc/Kconfig                               |   1 +
 arch/powerpc/kvm/book3s_hv.c                       |   4 +-
 arch/powerpc/kvm/book3s_pr.c                       |   4 +-
 arch/sparc/include/uapi/asm/ipcbuf.h               |  22 ++--
 arch/x86/kernel/cpu/tsx.c                          |  13 +-
 arch/x86/kvm/emulate.c                             |  12 +-
 arch/x86/kvm/i8259.c                               |   4 +-
 arch/x86/kvm/lapic.c                               |  14 ++-
 arch/x86/kvm/vmx.c                                 |   4 +-
 arch/x86/kvm/x86.c                                 |  57 +++++++--
 arch/x86/platform/efi/efi.c                        |  37 +++---
 crypto/af_alg.c                                    |   6 +-
 crypto/algapi.c                                    |  22 ++--
 crypto/api.c                                       |   3 +-
 crypto/internal.h                                  |   1 -
 crypto/pcrypt.c                                    |   4 +-
 drivers/clk/tegra/clk-tegra-periph.c               |   6 +-
 drivers/crypto/picoxcell_crypto.c                  |  15 ++-
 drivers/firmware/efi/efi.c                         |   4 +-
 drivers/md/persistent-data/dm-space-map-common.c   |  27 ++++
 drivers/md/persistent-data/dm-space-map-common.h   |   2 +
 drivers/md/persistent-data/dm-space-map-disk.c     |   6 +-
 drivers/md/persistent-data/dm-space-map-metadata.c |   5 +-
 drivers/media/rc/iguanair.c                        |  15 ++-
 drivers/media/usb/uvc/uvc_driver.c                 |  12 ++
 drivers/media/v4l2-core/videobuf-dma-sg.c          |   5 +-
 drivers/mmc/host/mmc_spi.c                         |  11 +-
 drivers/net/bonding/bond_alb.c                     |  44 +++++--
 drivers/net/ethernet/freescale/gianfar.c           |  10 +-
 drivers/net/wireless/ath/ath9k/hif_usb.c           |   2 +-
 drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c |   3 +
 drivers/net/wireless/brcm80211/brcmfmac/usb.c      |   3 +-
 drivers/net/wireless/iwlegacy/common.c             |   2 +-
 drivers/net/wireless/orinoco/orinoco_usb.c         |   4 +-
 drivers/net/wireless/rsi/rsi_91x_usb.c             |  12 +-
 drivers/net/wireless/zd1211rw/zd_usb.c             |   2 +-
 drivers/of/Kconfig                                 |   4 +
 drivers/of/address.c                               |   6 +-
 drivers/pci/setup-bus.c                            |  20 ++-
 drivers/power/sbs-battery.c                        |   2 +-
 drivers/rtc/rtc-hym8563.c                          |   2 +-
 drivers/scsi/qla2xxx/qla_mbx.c                     |   3 +-
 drivers/spi/spi-dw.c                               |  14 ++-
 drivers/spi/spi-dw.h                               |   1 +
 drivers/staging/wlan-ng/prism2mgmt.c               |   2 +-
 drivers/usb/dwc3/core.c                            |   3 +
 drivers/usb/gadget/f_ecm.c                         |  16 ++-
 drivers/usb/gadget/f_ncm.c                         |  17 ++-
 drivers/usb/serial/ir-usb.c                        | 136 ++++++++++++++++-----
 drivers/video/fbdev/pxa168fb.c                     |   6 +-
 fs/btrfs/ctree.c                                   |   8 +-
 fs/btrfs/ctree.h                                   |   6 +-
 fs/btrfs/delayed-ref.c                             |   8 +-
 fs/btrfs/disk-io.c                                 |   1 -
 fs/btrfs/tests/btrfs-tests.c                       |   1 -
 fs/cifs/cifsglob.h                                 |   1 +
 fs/cifs/smb2pdu.c                                  |  10 +-
 fs/cifs/smb2transport.c                            |   2 +
 fs/cifs/transport.c                                |   4 +
 fs/jbd2/checkpoint.c                               |   2 +-
 fs/jbd2/commit.c                                   |   4 +-
 fs/jbd2/journal.c                                  |  21 ++--
 fs/namespace.c                                     |   2 +-
 fs/nfs/Kconfig                                     |   2 +-
 fs/nfs/dir.c                                       | 104 +++++++---------
 fs/pnode.c                                         |   9 +-
 fs/reiserfs/super.c                                |   4 +-
 fs/ubifs/file.c                                    |   5 +-
 include/linux/padata.h                             |  13 +-
 include/linux/usb/irda.h                           |  13 +-
 kernel/padata.c                                    | 134 +++++++-------------
 kernel/time/clocksource.c                          |  11 +-
 kernel/trace/trace_stat.c                          |  31 ++---
 mm/mempolicy.c                                     |   6 +-
 net/ipv4/tcp.c                                     |   1 +
 net/sched/cls_rsvp.h                               |   6 +-
 net/sched/ematch.c                                 |   3 +
 net/sunrpc/auth_gss/svcauth_gss.c                  |   4 +
 scripts/kconfig/confdata.c                         |   2 +-
 sound/drivers/dummy.c                              |   2 +-
 sound/sh/aica.c                                    |   4 +-
 virt/kvm/ioapic.c                                  |  15 ++-
 virt/kvm/kvm_main.c                                |  12 +-
 94 files changed, 711 insertions(+), 444 deletions(-)

-- 
Ben Hutchings
All the simple programs have been written, and all the good names taken


^ permalink raw reply	[relevance 6%]

* [PATCH 3.16 06/99] padata: get_next is never NULL
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (4 preceding siblings ...)
  2020-05-20 14:13  8% ` [PATCH 3.16 05/99] padata: avoid race in reordering Ben Hutchings
@ 2020-05-20 14:13  8% ` Ben Hutchings
  2020-05-20 14:13  8% ` [PATCH 3.16 07/99] padata: ensure the reorder timer callback runs on the correct CPU Ben Hutchings
                   ` (93 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:13 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Jason A. Donenfeld, Herbert Xu,
	Dan Carpenter, Steffen Klassert

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: "Jason A. Donenfeld" <Jason@zx2c4.com>

commit 69b348449bda0f9588737539cfe135774c9939a7 upstream.

Per Dan's static checker warning, the code that returns NULL was removed
in 2010, so this patch updates the comments and fixes the code
assumptions.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Acked-by: Steffen Klassert <steffen.klassert@secunet.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 kernel/padata.c | 13 ++++---------
 1 file changed, 4 insertions(+), 9 deletions(-)

--- a/kernel/padata.c
+++ b/kernel/padata.c
@@ -153,8 +153,6 @@ EXPORT_SYMBOL(padata_do_parallel);
  * A pointer to the control struct of the next object that needs
  * serialization, if present in one of the percpu reorder queues.
  *
- * NULL, if all percpu reorder queues are empty.
- *
  * -EINPROGRESS, if the next object that needs serialization will
  *  be parallel processed by another cpu and is not yet present in
  *  the cpu's reorder queue.
@@ -181,8 +179,6 @@ static struct padata_priv *padata_get_ne
 	cpu = padata_index_to_cpu(pd, next_index);
 	next_queue = per_cpu_ptr(pd->pqueue, cpu);
 
-	padata = NULL;
-
 	reorder = &next_queue->reorder;
 
 	spin_lock(&reorder->lock);
@@ -234,12 +230,11 @@ static void padata_reorder(struct parall
 		padata = padata_get_next(pd);
 
 		/*
-		 * All reorder queues are empty, or the next object that needs
-		 * serialization is parallel processed by another cpu and is
-		 * still on it's way to the cpu's reorder queue, nothing to
-		 * do for now.
+		 * If the next object that needs serialization is parallel
+		 * processed by another cpu and is still on it's way to the
+		 * cpu's reorder queue, nothing to do for now.
 		 */
-		if (!padata || PTR_ERR(padata) == -EINPROGRESS)
+		if (PTR_ERR(padata) == -EINPROGRESS)
 			break;
 
 		/*


^ permalink raw reply	[relevance 8%]

* [PATCH 3.16 01/99] fs/namespace.c: fix mountpoint reference counter race
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
@ 2020-05-20 14:13  9% ` Ben Hutchings
  2020-05-20 14:13 12% ` [PATCH 3.16 02/99] propagate_one(): mnt_set_mountpoint() needs mount_lock Ben Hutchings
                   ` (98 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:13 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Piotr Krysiuk, Al Viro, Greg Kroah-Hartman

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Piotr Krysiuk <piotras@gmail.com>

A race condition between threads updating mountpoint reference counter
affects longterm releases 4.4.220, 4.9.220, 4.14.177 and 4.19.118.

The mountpoint reference counter corruption may occur when:
* one thread increments m_count member of struct mountpoint
  [under namespace_sem, but not holding mount_lock]
    pivot_root()
* another thread simultaneously decrements the same m_count
  [under mount_lock, but not holding namespace_sem]
    put_mountpoint()
      unhash_mnt()
        umount_mnt()
          mntput_no_expire()

To fix this race condition, grab mount_lock before updating m_count in
pivot_root().

Reference: CVE-2020-12114
Cc: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Piotr Krysiuk <piotras@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 fs/namespace.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -2937,8 +2937,8 @@ SYSCALL_DEFINE2(pivot_root, const char _
 	/* make certain new is below the root */
 	if (!is_path_reachable(new_mnt, new.dentry, &root))
 		goto out4;
-	root_mp->m_count++; /* pin it so it won't go away */
 	lock_mount_hash();
+	root_mp->m_count++; /* pin it so it won't go away */
 	detach_mnt(new_mnt, &parent_path);
 	detach_mnt(root_mnt, &root_parent);
 	if (root_mnt->mnt.mnt_flags & MNT_LOCKED) {


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 08/99] padata: ensure padata_do_serial() runs on the correct CPU
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (6 preceding siblings ...)
  2020-05-20 14:13  8% ` [PATCH 3.16 07/99] padata: ensure the reorder timer callback runs on the correct CPU Ben Hutchings
@ 2020-05-20 14:13  8% ` Ben Hutchings
  2020-05-20 14:13  8% ` [PATCH 3.16 09/99] padata: Replace delayed timer with immediate workqueue in padata_reorder Ben Hutchings
                   ` (91 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:13 UTC (permalink / raw)
  To: linux-kernel, stable; +Cc: akpm, Denis Kirjanov, Mathias Krause, Herbert Xu

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Mathias Krause <minipli@googlemail.com>

commit 350ef88e7e922354f82a931897ad4a4ce6c686ff upstream.

If the algorithm we're parallelizing is asynchronous we might change
CPUs between padata_do_parallel() and padata_do_serial(). However, we
don't expect this to happen as we need to enqueue the padata object into
the per-cpu reorder queue we took it from, i.e. the same-cpu's parallel
queue.

Ensure we're not switching CPUs for a given padata object by tracking
the CPU within the padata object. If the serial callback gets called on
the wrong CPU, defer invoking padata_reorder() via a kernel worker on
the CPU we're expected to run on.

Signed-off-by: Mathias Krause <minipli@googlemail.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 include/linux/padata.h |  2 ++
 kernel/padata.c        | 20 +++++++++++++++++++-
 2 files changed, 21 insertions(+), 1 deletion(-)

--- a/include/linux/padata.h
+++ b/include/linux/padata.h
@@ -37,6 +37,7 @@
  * @list: List entry, to attach to the padata lists.
  * @pd: Pointer to the internal control structure.
  * @cb_cpu: Callback cpu for serializatioon.
+ * @cpu: Cpu for parallelization.
  * @seq_nr: Sequence number of the parallelized data object.
  * @info: Used to pass information from the parallel to the serial function.
  * @parallel: Parallel execution function.
@@ -46,6 +47,7 @@ struct padata_priv {
 	struct list_head	list;
 	struct parallel_data	*pd;
 	int			cb_cpu;
+	int			cpu;
 	int			info;
 	void                    (*parallel)(struct padata_priv *padata);
 	void                    (*serial)(struct padata_priv *padata);
--- a/kernel/padata.c
+++ b/kernel/padata.c
@@ -130,6 +130,7 @@ int padata_do_parallel(struct padata_ins
 	padata->cb_cpu = cb_cpu;
 
 	target_cpu = padata_cpu_hash(pd);
+	padata->cpu = target_cpu;
 	queue = per_cpu_ptr(pd->pqueue, target_cpu);
 
 	spin_lock(&queue->parallel.lock);
@@ -367,10 +368,21 @@ void padata_do_serial(struct padata_priv
 	int cpu;
 	struct padata_parallel_queue *pqueue;
 	struct parallel_data *pd;
+	int reorder_via_wq = 0;
 
 	pd = padata->pd;
 
 	cpu = get_cpu();
+
+	/* We need to run on the same CPU padata_do_parallel(.., padata, ..)
+	 * was called on -- or, at least, enqueue the padata object into the
+	 * correct per-cpu queue.
+	 */
+	if (cpu != padata->cpu) {
+		reorder_via_wq = 1;
+		cpu = padata->cpu;
+	}
+
 	pqueue = per_cpu_ptr(pd->pqueue, cpu);
 
 	spin_lock(&pqueue->reorder.lock);
@@ -387,7 +399,13 @@ void padata_do_serial(struct padata_priv
 
 	put_cpu();
 
-	padata_reorder(pd);
+	/* If we're running on the wrong CPU, call padata_reorder() via a
+	 * kernel worker.
+	 */
+	if (reorder_via_wq)
+		queue_work_on(cpu, pd->pinst->wq, &pqueue->reorder_work);
+	else
+		padata_reorder(pd);
 }
 EXPORT_SYMBOL(padata_do_serial);
 


^ permalink raw reply	[relevance 8%]

* [PATCH 3.16 04/99] padata: Remove unused but set variables
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (2 preceding siblings ...)
  2020-05-20 14:13 10% ` [PATCH 3.16 03/99] spi: spi-dw: Add lock protect dw_spi rx/tx to prevent concurrent calls Ben Hutchings
@ 2020-05-20 14:13  9% ` Ben Hutchings
  2020-05-20 14:13  8% ` [PATCH 3.16 05/99] padata: avoid race in reordering Ben Hutchings
                   ` (95 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:13 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Steffen Klassert, Herbert Xu, Tobias Klauser

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Tobias Klauser <tklauser@distanz.ch>

commit 119a0798dc42ed4c4f96d39b8b676efcea73aec6 upstream.

Remove the unused but set variable pinst in padata_parallel_worker to
fix the following warning when building with 'W=1':

  kernel/padata.c: In function ‘padata_parallel_worker’:
  kernel/padata.c:68:26: warning: variable ‘pinst’ set but not used [-Wunused-but-set-variable]

Also remove the now unused variable pd which is only used to set pinst.

Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
Acked-by: Steffen Klassert <steffen.klassert@secunet.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 kernel/padata.c | 4 ----
 1 file changed, 4 deletions(-)

--- a/kernel/padata.c
+++ b/kernel/padata.c
@@ -63,15 +63,11 @@ static int padata_cpu_hash(struct parall
 static void padata_parallel_worker(struct work_struct *parallel_work)
 {
 	struct padata_parallel_queue *pqueue;
-	struct parallel_data *pd;
-	struct padata_instance *pinst;
 	LIST_HEAD(local_list);
 
 	local_bh_disable();
 	pqueue = container_of(parallel_work,
 			      struct padata_parallel_queue, work);
-	pd = pqueue->pd;
-	pinst = pd->pinst;
 
 	spin_lock(&pqueue->parallel.lock);
 	list_replace_init(&pqueue->parallel.list, &local_list);


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 18/99] crypto: api - Fix race condition in crypto_spawn_alg
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (16 preceding siblings ...)
  2020-05-20 14:13  9% ` [PATCH 3.16 17/99] crypto: api - Check spawn->alg under lock in crypto_drop_spawn Ben Hutchings
@ 2020-05-20 14:13  9% ` Ben Hutchings
  2020-05-20 14:13  8% ` [PATCH 3.16 19/99] mmc: spi: Toggle SPI polarity, do not hardcode it Ben Hutchings
                   ` (81 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:13 UTC (permalink / raw)
  To: linux-kernel, stable; +Cc: akpm, Denis Kirjanov, Herbert Xu

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Herbert Xu <herbert@gondor.apana.org.au>

commit 73669cc556462f4e50376538d77ee312142e8a8a upstream.

The function crypto_spawn_alg is racy because it drops the lock
before shooting the dying algorithm.  The algorithm could disappear
altogether before we shoot it.

This patch fixes it by moving the shooting into the locked section.

Fixes: 6bfd48096ff8 ("[CRYPTO] api: Added spawns")
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 crypto/algapi.c   | 16 +++++-----------
 crypto/api.c      |  3 +--
 crypto/internal.h |  1 -
 3 files changed, 6 insertions(+), 14 deletions(-)

--- a/crypto/algapi.c
+++ b/crypto/algapi.c
@@ -628,22 +628,16 @@ EXPORT_SYMBOL_GPL(crypto_drop_spawn);
 static struct crypto_alg *crypto_spawn_alg(struct crypto_spawn *spawn)
 {
 	struct crypto_alg *alg;
-	struct crypto_alg *alg2;
 
 	down_read(&crypto_alg_sem);
 	alg = spawn->alg;
-	alg2 = alg;
-	if (alg2)
-		alg2 = crypto_mod_get(alg2);
-	up_read(&crypto_alg_sem);
-
-	if (!alg2) {
-		if (alg)
-			crypto_shoot_alg(alg);
-		return ERR_PTR(-EAGAIN);
+	if (alg && !crypto_mod_get(alg)) {
+		alg->cra_flags |= CRYPTO_ALG_DYING;
+		alg = NULL;
 	}
+	up_read(&crypto_alg_sem);
 
-	return alg;
+	return alg ?: ERR_PTR(-EAGAIN);
 }
 
 struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn, u32 type,
--- a/crypto/api.c
+++ b/crypto/api.c
@@ -345,13 +345,12 @@ static unsigned int crypto_ctxsize(struc
 	return len;
 }
 
-void crypto_shoot_alg(struct crypto_alg *alg)
+static void crypto_shoot_alg(struct crypto_alg *alg)
 {
 	down_write(&crypto_alg_sem);
 	alg->cra_flags |= CRYPTO_ALG_DYING;
 	up_write(&crypto_alg_sem);
 }
-EXPORT_SYMBOL_GPL(crypto_shoot_alg);
 
 struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type,
 				      u32 mask)
--- a/crypto/internal.h
+++ b/crypto/internal.h
@@ -88,7 +88,6 @@ void crypto_alg_tested(const char *name,
 void crypto_remove_spawns(struct crypto_alg *alg, struct list_head *list,
 			  struct crypto_alg *nalg);
 void crypto_remove_final(struct list_head *list);
-void crypto_shoot_alg(struct crypto_alg *alg);
 struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type,
 				      u32 mask);
 void *crypto_create_tfm(struct crypto_alg *alg,


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 07/99] padata: ensure the reorder timer callback runs on the correct CPU
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (5 preceding siblings ...)
  2020-05-20 14:13  8% ` [PATCH 3.16 06/99] padata: get_next is never NULL Ben Hutchings
@ 2020-05-20 14:13  8% ` Ben Hutchings
  2020-05-20 14:13  8% ` [PATCH 3.16 08/99] padata: ensure padata_do_serial() " Ben Hutchings
                   ` (92 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:13 UTC (permalink / raw)
  To: linux-kernel, stable; +Cc: akpm, Denis Kirjanov, Herbert Xu, Mathias Krause

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Mathias Krause <minipli@googlemail.com>

commit cf5868c8a22dc2854b96e9569064bb92365549ca upstream.

The reorder timer function runs on the CPU where the timer interrupt was
handled which is not necessarily one of the CPUs of the 'pcpu' CPU mask
set.

Ensure the padata_reorder() callback runs on the correct CPU, which is
one in the 'pcpu' CPU mask set and, preferrably, the next expected one.
Do so by comparing the current CPU with the expected target CPU. If they
match, call padata_reorder() right away. If they differ, schedule a work
item on the target CPU that does the padata_reorder() call for us.

Signed-off-by: Mathias Krause <minipli@googlemail.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 include/linux/padata.h |  2 ++
 kernel/padata.c        | 43 +++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 44 insertions(+), 1 deletion(-)

--- a/include/linux/padata.h
+++ b/include/linux/padata.h
@@ -85,6 +85,7 @@ struct padata_serial_queue {
  * @swork: work struct for serialization.
  * @pd: Backpointer to the internal control structure.
  * @work: work struct for parallelization.
+ * @reorder_work: work struct for reordering.
  * @num_obj: Number of objects that are processed by this cpu.
  * @cpu_index: Index of the cpu.
  */
@@ -93,6 +94,7 @@ struct padata_parallel_queue {
        struct padata_list    reorder;
        struct parallel_data *pd;
        struct work_struct    work;
+       struct work_struct    reorder_work;
        atomic_t              num_obj;
        int                   cpu_index;
 };
--- a/kernel/padata.c
+++ b/kernel/padata.c
@@ -279,11 +279,51 @@ static void padata_reorder(struct parall
 	return;
 }
 
+static void invoke_padata_reorder(struct work_struct *work)
+{
+	struct padata_parallel_queue *pqueue;
+	struct parallel_data *pd;
+
+	local_bh_disable();
+	pqueue = container_of(work, struct padata_parallel_queue, reorder_work);
+	pd = pqueue->pd;
+	padata_reorder(pd);
+	local_bh_enable();
+}
+
 static void padata_reorder_timer(unsigned long arg)
 {
 	struct parallel_data *pd = (struct parallel_data *)arg;
+	unsigned int weight;
+	int target_cpu, cpu;
 
-	padata_reorder(pd);
+	cpu = get_cpu();
+
+	/* We don't lock pd here to not interfere with parallel processing
+	 * padata_reorder() calls on other CPUs. We just need any CPU out of
+	 * the cpumask.pcpu set. It would be nice if it's the right one but
+	 * it doesn't matter if we're off to the next one by using an outdated
+	 * pd->processed value.
+	 */
+	weight = cpumask_weight(pd->cpumask.pcpu);
+	target_cpu = padata_index_to_cpu(pd, pd->processed % weight);
+
+	/* ensure to call the reorder callback on the correct CPU */
+	if (cpu != target_cpu) {
+		struct padata_parallel_queue *pqueue;
+		struct padata_instance *pinst;
+
+		/* The timer function is serialized wrt itself -- no locking
+		 * needed.
+		 */
+		pinst = pd->pinst;
+		pqueue = per_cpu_ptr(pd->pqueue, target_cpu);
+		queue_work_on(target_cpu, pinst->wq, &pqueue->reorder_work);
+	} else {
+		padata_reorder(pd);
+	}
+
+	put_cpu();
 }
 
 static void padata_serial_worker(struct work_struct *serial_work)
@@ -404,6 +444,7 @@ static void padata_init_pqueues(struct p
 		__padata_list_init(&pqueue->reorder);
 		__padata_list_init(&pqueue->parallel);
 		INIT_WORK(&pqueue->work, padata_parallel_worker);
+		INIT_WORK(&pqueue->reorder_work, invoke_padata_reorder);
 		atomic_set(&pqueue->num_obj, 0);
 	}
 }


^ permalink raw reply	[relevance 8%]

* [PATCH 3.16 11/99] padata: Remove broken queue flushing
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (9 preceding siblings ...)
  2020-05-20 14:13  8% ` [PATCH 3.16 10/99] padata: initialize pd->cpu with effective cpumask Ben Hutchings
@ 2020-05-20 14:13  8% ` Ben Hutchings
  2020-05-20 14:13  9% ` [PATCH 3.16 12/99] padata: purge get_cpu and reorder_via_wq from padata_do_serial Ben Hutchings
                   ` (88 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:13 UTC (permalink / raw)
  To: linux-kernel, stable; +Cc: akpm, Denis Kirjanov, Herbert Xu, Daniel Jordan

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Herbert Xu <herbert@gondor.apana.org.au>

commit 07928d9bfc81640bab36f5190e8725894d93b659 upstream.

The function padata_flush_queues is fundamentally broken because
it cannot force padata users to complete the request that is
underway.  IOW padata has to passively wait for the completion
of any outstanding work.

As it stands flushing is used in two places.  Its use in padata_stop
is simply unnecessary because nothing depends on the queues to
be flushed afterwards.

The other use in padata_replace is more substantial as we depend
on it to free the old pd structure.  This patch instead uses the
pd->refcnt to dynamically free the pd structure once all requests
are complete.

Fixes: 2b73b07ab8a4 ("padata: Flush the padata queues actively")
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Reviewed-by: Daniel Jordan <daniel.m.jordan@oracle.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
--- a/kernel/padata.c
+++ b/kernel/padata.c
@@ -33,6 +33,8 @@
 
 #define MAX_OBJ_NUM 1000
 
+static void padata_free_pd(struct parallel_data *pd);
+
 static int padata_index_to_cpu(struct parallel_data *pd, int cpu_index)
 {
 	int cpu, target_cpu;
@@ -281,6 +283,7 @@ static void padata_serial_worker(struct
 	struct padata_serial_queue *squeue;
 	struct parallel_data *pd;
 	LIST_HEAD(local_list);
+	int cnt;
 
 	local_bh_disable();
 	squeue = container_of(serial_work, struct padata_serial_queue, work);
@@ -290,6 +293,8 @@ static void padata_serial_worker(struct
 	list_replace_init(&squeue->serial.list, &local_list);
 	spin_unlock(&squeue->serial.lock);
 
+	cnt = 0;
+
 	while (!list_empty(&local_list)) {
 		struct padata_priv *padata;
 
@@ -299,9 +304,12 @@ static void padata_serial_worker(struct
 		list_del_init(&padata->list);
 
 		padata->serial(padata);
-		atomic_dec(&pd->refcnt);
+		cnt++;
 	}
 	local_bh_enable();
+
+	if (atomic_sub_and_test(cnt, &pd->refcnt))
+		padata_free_pd(pd);
 }
 
 /**
@@ -432,7 +440,7 @@ static struct parallel_data *padata_allo
 	padata_init_squeues(pd);
 	atomic_set(&pd->seq_nr, -1);
 	atomic_set(&pd->reorder_objects, 0);
-	atomic_set(&pd->refcnt, 0);
+	atomic_set(&pd->refcnt, 1);
 	pd->pinst = pinst;
 	spin_lock_init(&pd->lock);
 	pd->cpu = cpumask_first(pd->cpumask.pcpu);
@@ -459,29 +467,6 @@ static void padata_free_pd(struct parall
 	kfree(pd);
 }
 
-/* Flush all objects out of the padata queues. */
-static void padata_flush_queues(struct parallel_data *pd)
-{
-	int cpu;
-	struct padata_parallel_queue *pqueue;
-	struct padata_serial_queue *squeue;
-
-	for_each_cpu(cpu, pd->cpumask.pcpu) {
-		pqueue = per_cpu_ptr(pd->pqueue, cpu);
-		flush_work(&pqueue->work);
-	}
-
-	if (atomic_read(&pd->reorder_objects))
-		padata_reorder(pd);
-
-	for_each_cpu(cpu, pd->cpumask.cbcpu) {
-		squeue = per_cpu_ptr(pd->squeue, cpu);
-		flush_work(&squeue->work);
-	}
-
-	BUG_ON(atomic_read(&pd->refcnt) != 0);
-}
-
 static void __padata_start(struct padata_instance *pinst)
 {
 	pinst->flags |= PADATA_INIT;
@@ -495,10 +480,6 @@ static void __padata_stop(struct padata_
 	pinst->flags &= ~PADATA_INIT;
 
 	synchronize_rcu();
-
-	get_online_cpus();
-	padata_flush_queues(pinst->pd);
-	put_online_cpus();
 }
 
 /* Replace the internal control structure with a new one. */
@@ -519,8 +500,8 @@ static void padata_replace(struct padata
 	if (!cpumask_equal(pd_old->cpumask.cbcpu, pd_new->cpumask.cbcpu))
 		notification_mask |= PADATA_CPU_SERIAL;
 
-	padata_flush_queues(pd_old);
-	padata_free_pd(pd_old);
+	if (atomic_dec_and_test(&pd_old->refcnt))
+		padata_free_pd(pd_old);
 
 	if (notification_mask)
 		blocking_notifier_call_chain(&pinst->cpumask_change_notifier,


^ permalink raw reply	[relevance 8%]

* [PATCH 3.16 13/99] crypto: pcrypt - Fix user-after-free on module unload
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (11 preceding siblings ...)
  2020-05-20 14:13  9% ` [PATCH 3.16 12/99] padata: purge get_cpu and reorder_via_wq from padata_do_serial Ben Hutchings
@ 2020-05-20 14:13 13% ` Ben Hutchings
  2020-05-20 14:13  9% ` [PATCH 3.16 14/99] crypto: pcrypt - Do not clear MAY_SLEEP flag in original request Ben Hutchings
                   ` (86 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:13 UTC (permalink / raw)
  To: linux-kernel, stable; +Cc: akpm, Denis Kirjanov, Herbert Xu

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Herbert Xu <herbert@gondor.apana.org.au>

commit 07bfd9bdf568a38d9440c607b72342036011f727 upstream.

On module unload of pcrypt we must unregister the crypto algorithms
first and then tear down the padata structure.  As otherwise the
crypto algorithms are still alive and can be used while the padata
structure is being freed.

Fixes: 5068c7a883d1 ("crypto: pcrypt - Add pcrypt crypto...")
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 crypto/pcrypt.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

--- a/crypto/pcrypt.c
+++ b/crypto/pcrypt.c
@@ -552,11 +552,12 @@ err:
 
 static void __exit pcrypt_exit(void)
 {
+	crypto_unregister_template(&pcrypt_tmpl);
+
 	pcrypt_fini_padata(&pencrypt);
 	pcrypt_fini_padata(&pdecrypt);
 
 	kset_unregister(pcrypt_kset);
-	crypto_unregister_template(&pcrypt_tmpl);
 }
 
 module_init(pcrypt_init);


^ permalink raw reply	[relevance 13%]

* [PATCH 3.16 21/99] reiserfs: Fix spurious unlock in reiserfs_fill_super() error handling
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (19 preceding siblings ...)
  2020-05-20 14:13  9% ` [PATCH 3.16 20/99] reiserfs: Fix memory leak of journal device string Ben Hutchings
@ 2020-05-20 14:13  9% ` Ben Hutchings
  2020-05-20 14:13  9% ` [PATCH 3.16 22/99] ath9k: fix storage endpoint lookup Ben Hutchings
                   ` (78 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:13 UTC (permalink / raw)
  To: linux-kernel, stable; +Cc: akpm, Denis Kirjanov, Jan Kara

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Jan Kara <jack@suse.cz>

commit 4d5c1adaf893b8aa52525d2b81995e949bcb3239 upstream.

When we fail to allocate string for journal device name we jump to
'error' label which tries to unlock reiserfs write lock which is not
held. Jump to 'error_unlocked' instead.

Fixes: f32485be8397 ("reiserfs: delay reiserfs lock until journal initialization")
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 fs/reiserfs/super.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -1901,7 +1901,7 @@ static int reiserfs_fill_super(struct su
 		if (!sbi->s_jdev) {
 			SWARN(silent, s, "", "Cannot allocate memory for "
 				"journal device name");
-			goto error;
+			goto error_unlocked;
 		}
 	}
 #ifdef CONFIG_QUOTA


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 10/99] padata: initialize pd->cpu with effective cpumask
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (8 preceding siblings ...)
  2020-05-20 14:13  8% ` [PATCH 3.16 09/99] padata: Replace delayed timer with immediate workqueue in padata_reorder Ben Hutchings
@ 2020-05-20 14:13  8% ` Ben Hutchings
  2020-05-20 14:13  8% ` [PATCH 3.16 11/99] padata: Remove broken queue flushing Ben Hutchings
                   ` (89 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:13 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Steffen Klassert, linux-crypto, Herbert Xu,
	Daniel Jordan

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Daniel Jordan <daniel.m.jordan@oracle.com>

commit ec9c7d19336ee98ecba8de80128aa405c45feebb upstream.

Exercising CPU hotplug on a 5.2 kernel with recent padata fixes from
cryptodev-2.6.git in an 8-CPU kvm guest...

    # modprobe tcrypt alg="pcrypt(rfc4106(gcm(aes)))" type=3
    # echo 0 > /sys/devices/system/cpu/cpu1/online
    # echo c > /sys/kernel/pcrypt/pencrypt/parallel_cpumask
    # modprobe tcrypt mode=215

...caused the following crash:

    BUG: kernel NULL pointer dereference, address: 0000000000000000
    #PF: supervisor read access in kernel mode
    #PF: error_code(0x0000) - not-present page
    PGD 0 P4D 0
    Oops: 0000 [#1] SMP PTI
    CPU: 2 PID: 134 Comm: kworker/2:2 Not tainted 5.2.0-padata-base+ #7
    Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-<snip>
    Workqueue: pencrypt padata_parallel_worker
    RIP: 0010:padata_reorder+0xcb/0x180
    ...
    Call Trace:
     padata_do_serial+0x57/0x60
     pcrypt_aead_enc+0x3a/0x50 [pcrypt]
     padata_parallel_worker+0x9b/0xe0
     process_one_work+0x1b5/0x3f0
     worker_thread+0x4a/0x3c0
     ...

In padata_alloc_pd, pd->cpu is set using the user-supplied cpumask
instead of the effective cpumask, and in this case cpumask_first picked
an offline CPU.

The offline CPU's reorder->list.next is NULL in padata_reorder because
the list wasn't initialized in padata_init_pqueues, which only operates
on CPUs in the effective mask.

Fix by using the effective mask in padata_alloc_pd.

Fixes: 6fc4dbcf0276 ("padata: Replace delayed timer with immediate workqueue in padata_reorder")
Signed-off-by: Daniel Jordan <daniel.m.jordan@oracle.com>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: Steffen Klassert <steffen.klassert@secunet.com>
Cc: linux-crypto@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 kernel/padata.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/kernel/padata.c
+++ b/kernel/padata.c
@@ -435,7 +435,7 @@ static struct parallel_data *padata_allo
 	atomic_set(&pd->refcnt, 0);
 	pd->pinst = pinst;
 	spin_lock_init(&pd->lock);
-	pd->cpu = cpumask_first(pcpumask);
+	pd->cpu = cpumask_first(pd->cpumask.pcpu);
 	INIT_WORK(&pd->reorder_work, invoke_padata_reorder);
 
 	return pd;


^ permalink raw reply	[relevance 8%]

* [PATCH 3.16 03/99] spi: spi-dw: Add lock protect dw_spi rx/tx to prevent concurrent calls
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
  2020-05-20 14:13  9% ` [PATCH 3.16 01/99] fs/namespace.c: fix mountpoint reference counter race Ben Hutchings
  2020-05-20 14:13 12% ` [PATCH 3.16 02/99] propagate_one(): mnt_set_mountpoint() needs mount_lock Ben Hutchings
@ 2020-05-20 14:13 10% ` Ben Hutchings
  2020-05-20 14:13  9% ` [PATCH 3.16 04/99] padata: Remove unused but set variables Ben Hutchings
                   ` (96 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:13 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Nobuhiro Iwamatsu (CIP), Mark Brown, wuxu.wu

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: "wuxu.wu" <wuxu.wu@huawei.com>

commit 19b61392c5a852b4e8a0bf35aecb969983c5932d upstream.

dw_spi_irq() and dw_spi_transfer_one concurrent calls.

I find a panic in dw_writer(): txw = *(u8 *)(dws->tx), when dw->tx==null,
dw->len==4, and dw->tx_end==1.

When tpm driver's message overtime dw_spi_irq() and dw_spi_transfer_one
may concurrent visit dw_spi, so I think dw_spi structure lack of protection.

Otherwise dw_spi_transfer_one set dw rx/tx buffer and then open irq,
store dw rx/tx instructions and other cores handle irq load dw rx/tx
instructions may out of order.

	[ 1025.321302] Call trace:
	...
	[ 1025.321319]  __crash_kexec+0x98/0x148
	[ 1025.321323]  panic+0x17c/0x314
	[ 1025.321329]  die+0x29c/0x2e8
	[ 1025.321334]  die_kernel_fault+0x68/0x78
	[ 1025.321337]  __do_kernel_fault+0x90/0xb0
	[ 1025.321346]  do_page_fault+0x88/0x500
	[ 1025.321347]  do_translation_fault+0xa8/0xb8
	[ 1025.321349]  do_mem_abort+0x68/0x118
	[ 1025.321351]  el1_da+0x20/0x8c
	[ 1025.321362]  dw_writer+0xc8/0xd0
	[ 1025.321364]  interrupt_transfer+0x60/0x110
	[ 1025.321365]  dw_spi_irq+0x48/0x70
	...

Signed-off-by: wuxu.wu <wuxu.wu@huawei.com>
Link: https://lore.kernel.org/r/1577849981-31489-1-git-send-email-wuxu.wu@huawei.com
Signed-off-by: Mark Brown <broonie@kernel.org>
[iwamatsu: Backported to 3.16: adjut context]
Signed-off-by: Nobuhiro Iwamatsu (CIP) <nobuhiro1.iwamatsu@toshiba.co.jp>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/spi/spi-dw.c | 14 ++++++++++++--
 drivers/spi/spi-dw.h |  1 +
 2 files changed, 13 insertions(+), 2 deletions(-)

--- a/drivers/spi/spi-dw.c
+++ b/drivers/spi/spi-dw.c
@@ -182,9 +182,11 @@ static inline u32 rx_max(struct dw_spi *
 
 static void dw_writer(struct dw_spi *dws)
 {
-	u32 max = tx_max(dws);
+	u32 max;
 	u16 txw = 0;
 
+	spin_lock(&dws->buf_lock);
+	max = tx_max(dws);
 	while (max--) {
 		/* Set the tx word if the transfer's original "tx" is not null */
 		if (dws->tx_end - dws->len) {
@@ -196,13 +198,16 @@ static void dw_writer(struct dw_spi *dws
 		dw_writew(dws, DW_SPI_DR, txw);
 		dws->tx += dws->n_bytes;
 	}
+	spin_unlock(&dws->buf_lock);
 }
 
 static void dw_reader(struct dw_spi *dws)
 {
-	u32 max = rx_max(dws);
+	u32 max;
 	u16 rxw;
 
+	spin_lock(&dws->buf_lock);
+	max = rx_max(dws);
 	while (max--) {
 		rxw = dw_readw(dws, DW_SPI_DR);
 		/* Care rx only if the transfer's original "rx" is not null */
@@ -214,6 +219,7 @@ static void dw_reader(struct dw_spi *dws
 		}
 		dws->rx += dws->n_bytes;
 	}
+	spin_unlock(&dws->buf_lock);
 }
 
 static void *next_transfer(struct dw_spi *dws)
@@ -368,6 +374,7 @@ static void pump_transfers(unsigned long
 	struct spi_transfer *previous = NULL;
 	struct spi_device *spi = NULL;
 	struct chip_data *chip = NULL;
+	unsigned long flags;
 	u8 bits = 0;
 	u8 imask = 0;
 	u8 cs_change = 0;
@@ -406,6 +413,7 @@ static void pump_transfers(unsigned long
 	dws->dma_width = chip->dma_width;
 	dws->cs_control = chip->cs_control;
 
+	spin_lock_irqsave(&dws->buf_lock, flags);
 	dws->rx_dma = transfer->rx_dma;
 	dws->tx_dma = transfer->tx_dma;
 	dws->tx = (void *)transfer->tx_buf;
@@ -415,6 +423,7 @@ static void pump_transfers(unsigned long
 	dws->len = dws->cur_transfer->len;
 	if (chip != dws->prev_chip)
 		cs_change = 1;
+	spin_unlock_irqrestore(&dws->buf_lock, flags);
 
 	cr0 = chip->cr0;
 
@@ -651,6 +660,7 @@ int dw_spi_add_host(struct device *dev,
 	dws->dma_addr = (dma_addr_t)(dws->paddr + 0x60);
 	snprintf(dws->name, sizeof(dws->name), "dw_spi%d",
 			dws->bus_num);
+	spin_lock_init(&dws->buf_lock);
 
 	ret = request_irq(dws->irq, dw_spi_irq, IRQF_SHARED, dws->name, dws);
 	if (ret < 0) {
--- a/drivers/spi/spi-dw.h
+++ b/drivers/spi/spi-dw.h
@@ -116,6 +116,7 @@ struct dw_spi {
 	size_t			len;
 	void			*tx;
 	void			*tx_end;
+	spinlock_t		buf_lock;
 	void			*rx;
 	void			*rx_end;
 	int			dma_mapped;


^ permalink raw reply	[relevance 10%]

* [PATCH 3.16 12/99] padata: purge get_cpu and reorder_via_wq from padata_do_serial
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (10 preceding siblings ...)
  2020-05-20 14:13  8% ` [PATCH 3.16 11/99] padata: Remove broken queue flushing Ben Hutchings
@ 2020-05-20 14:13  9% ` Ben Hutchings
  2020-05-20 14:13 13% ` [PATCH 3.16 13/99] crypto: pcrypt - Fix user-after-free on module unload Ben Hutchings
                   ` (87 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:13 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Steffen Klassert, linux-crypto, Herbert Xu,
	Daniel Jordan

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Daniel Jordan <daniel.m.jordan@oracle.com>

commit 065cf577135a4977931c7a1e1edf442bfd9773dd upstream.

With the removal of the padata timer, padata_do_serial no longer
needs special CPU handling, so remove it.

Signed-off-by: Daniel Jordan <daniel.m.jordan@oracle.com>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: Steffen Klassert <steffen.klassert@secunet.com>
Cc: linux-crypto@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 kernel/padata.c | 23 +++--------------------
 1 file changed, 3 insertions(+), 20 deletions(-)

--- a/kernel/padata.c
+++ b/kernel/padata.c
@@ -322,24 +322,9 @@ static void padata_serial_worker(struct
  */
 void padata_do_serial(struct padata_priv *padata)
 {
-	int cpu;
-	struct padata_parallel_queue *pqueue;
-	struct parallel_data *pd;
-	int reorder_via_wq = 0;
-
-	pd = padata->pd;
-
-	cpu = get_cpu();
-
-	/* We need to enqueue the padata object into the correct
-	 * per-cpu queue.
-	 */
-	if (cpu != padata->cpu) {
-		reorder_via_wq = 1;
-		cpu = padata->cpu;
-	}
-
-	pqueue = per_cpu_ptr(pd->pqueue, cpu);
+	struct parallel_data *pd = padata->pd;
+	struct padata_parallel_queue *pqueue = per_cpu_ptr(pd->pqueue,
+							   padata->cpu);
 
 	spin_lock(&pqueue->reorder.lock);
 	list_add_tail(&padata->list, &pqueue->reorder.list);
@@ -353,8 +338,6 @@ void padata_do_serial(struct padata_priv
 	 */
 	smp_mb__after_atomic();
 
-	put_cpu();
-
 	padata_reorder(pd);
 }
 EXPORT_SYMBOL(padata_do_serial);


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 16/99] crypto: af_alg - Use bh_lock_sock in sk_destruct
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (14 preceding siblings ...)
  2020-05-20 14:13  8% ` [PATCH 3.16 15/99] padata: always acquire cpu_hotplug_lock before pinst->lock Ben Hutchings
@ 2020-05-20 14:13  9% ` Ben Hutchings
  2020-05-20 14:13  9% ` [PATCH 3.16 17/99] crypto: api - Check spawn->alg under lock in crypto_drop_spawn Ben Hutchings
                   ` (83 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:13 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Eric Dumazet, syzbot+c2f1558d49e25cc36e5e,
	Herbert Xu

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Herbert Xu <herbert@gondor.apana.org.au>

commit 37f96694cf73ba116993a9d2d99ad6a75fa7fdb0 upstream.

As af_alg_release_parent may be called from BH context (most notably
due to an async request that only completes after socket closure,
or as reported here because of an RCU-delayed sk_destruct call), we
must use bh_lock_sock instead of lock_sock.

Reported-by: syzbot+c2f1558d49e25cc36e5e@syzkaller.appspotmail.com
Reported-by: Eric Dumazet <eric.dumazet@gmail.com>
Fixes: c840ac6af3f8 ("crypto: af_alg - Disallow bind/setkey/...")
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 crypto/af_alg.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

--- a/crypto/af_alg.c
+++ b/crypto/af_alg.c
@@ -136,11 +136,13 @@ void af_alg_release_parent(struct sock *
 	sk = ask->parent;
 	ask = alg_sk(sk);
 
-	lock_sock(sk);
+	local_bh_disable();
+	bh_lock_sock(sk);
 	ask->nokey_refcnt -= nokey;
 	if (!last)
 		last = !--ask->refcnt;
-	release_sock(sk);
+	bh_unlock_sock(sk);
+	local_bh_enable();
 
 	if (last)
 		sock_put(sk);


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 15/99] padata: always acquire cpu_hotplug_lock before pinst->lock
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (13 preceding siblings ...)
  2020-05-20 14:13  9% ` [PATCH 3.16 14/99] crypto: pcrypt - Do not clear MAY_SLEEP flag in original request Ben Hutchings
@ 2020-05-20 14:13  8% ` Ben Hutchings
  2020-05-20 14:13  9% ` [PATCH 3.16 16/99] crypto: af_alg - Use bh_lock_sock in sk_destruct Ben Hutchings
                   ` (84 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:13 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Steffen Klassert, Eric Biggers,
	linux-crypto, Herbert Xu, Daniel Jordan

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Daniel Jordan <daniel.m.jordan@oracle.com>

commit 38228e8848cd7dd86ccb90406af32de0cad24be3 upstream.

lockdep complains when padata's paths to update cpumasks via CPU hotplug
and sysfs are both taken:

  # echo 0 > /sys/devices/system/cpu/cpu1/online
  # echo ff > /sys/kernel/pcrypt/pencrypt/parallel_cpumask

  ======================================================
  WARNING: possible circular locking dependency detected
  5.4.0-rc8-padata-cpuhp-v3+ #1 Not tainted
  ------------------------------------------------------
  bash/205 is trying to acquire lock:
  ffffffff8286bcd0 (cpu_hotplug_lock.rw_sem){++++}, at: padata_set_cpumask+0x2b/0x120

  but task is already holding lock:
  ffff8880001abfa0 (&pinst->lock){+.+.}, at: padata_set_cpumask+0x26/0x120

  which lock already depends on the new lock.

padata doesn't take cpu_hotplug_lock and pinst->lock in a consistent
order.  Which should be first?  CPU hotplug calls into padata with
cpu_hotplug_lock already held, so it should have priority.

Fixes: 6751fb3c0e0c ("padata: Use get_online_cpus/put_online_cpus")
Signed-off-by: Daniel Jordan <daniel.m.jordan@oracle.com>
Cc: Eric Biggers <ebiggers@kernel.org>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: Steffen Klassert <steffen.klassert@secunet.com>
Cc: linux-crypto@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 kernel/padata.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

--- a/kernel/padata.c
+++ b/kernel/padata.c
@@ -614,8 +614,8 @@ int padata_set_cpumask(struct padata_ins
 	struct cpumask *serial_mask, *parallel_mask;
 	int err = -EINVAL;
 
-	mutex_lock(&pinst->lock);
 	get_online_cpus();
+	mutex_lock(&pinst->lock);
 
 	switch (cpumask_type) {
 	case PADATA_CPU_PARALLEL:
@@ -633,8 +633,8 @@ int padata_set_cpumask(struct padata_ins
 	err =  __padata_set_cpumasks(pinst, parallel_mask, serial_mask);
 
 out:
-	put_online_cpus();
 	mutex_unlock(&pinst->lock);
+	put_online_cpus();
 
 	return err;
 }


^ permalink raw reply	[relevance 8%]

* [PATCH 3.16 24/99] brcmfmac: Fix use after free in brcmf_sdio_readframes()
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (22 preceding siblings ...)
  2020-05-20 14:13 12% ` [PATCH 3.16 23/99] rsi: fix use-after-free on failed probe and unbind Ben Hutchings
@ 2020-05-20 14:13 13% ` Ben Hutchings
  2020-05-20 14:13 12% ` [PATCH 3.16 25/99] brcmfmac: abort and release host after error Ben Hutchings
                   ` (75 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:13 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Franky Lin, Kalle Valo, Dan Carpenter

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Dan Carpenter <dan.carpenter@oracle.com>

commit 216b44000ada87a63891a8214c347e05a4aea8fe upstream.

The brcmu_pkt_buf_free_skb() function frees "pkt" so it leads to a
static checker warning:

    drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c:1974 brcmf_sdio_readframes()
    error: dereferencing freed memory 'pkt'

It looks like there was supposed to be a continue after we free "pkt".

Fixes: 4754fceeb9a6 ("brcmfmac: streamline SDIO read frame routine")
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Acked-by: Franky Lin <franky.lin@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
[bwh: Backported to 3.16: adjust filename]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | 1 +
 1 file changed, 1 insertion(+)

--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -1972,6 +1972,7 @@ static uint brcmf_sdio_readframes(struct
 					       BRCMF_SDIO_FT_NORMAL)) {
 				rd->len = 0;
 				brcmu_pkt_buf_free_skb(pkt);
+				continue;
 			}
 			bus->sdcnt.rx_readahead_cnt++;
 			if (rd->len != roundup(rd_new.len, 16)) {


^ permalink raw reply	[relevance 13%]

* [PATCH 3.16 30/99] brcmfmac: Fix memory leak in brcmf_usbdev_qinit
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (28 preceding siblings ...)
  2020-05-20 14:13 13% ` [PATCH 3.16 29/99] zd1211rw: fix storage endpoint lookup Ben Hutchings
@ 2020-05-20 14:13  9% ` Ben Hutchings
  2020-05-20 14:13  9% ` [PATCH 3.16 31/99] crypto: picoxcell - adjust the position of tasklet_init and fix missed tasklet_kill Ben Hutchings
                   ` (69 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:13 UTC (permalink / raw)
  To: linux-kernel, stable; +Cc: akpm, Denis Kirjanov, Kalle Valo, Navid Emamdoost

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Navid Emamdoost <navid.emamdoost@gmail.com>

commit 4282dc057d750c6a7dd92953564b15c26b54c22c upstream.

In the implementation of brcmf_usbdev_qinit() the allocated memory for
reqs is leaking if usb_alloc_urb() fails. Release reqs in the error
handling path.

Fixes: 71bb244ba2fd ("brcm80211: fmac: add USB support for bcm43235/6/8 chipsets")
Signed-off-by: Navid Emamdoost <navid.emamdoost@gmail.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/net/wireless/brcm80211/brcmfmac/usb.c | 1 +
 1 file changed, 1 insertion(+)

--- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
@@ -365,6 +365,7 @@ fail:
 			usb_free_urb(req->urb);
 		list_del(q->next);
 	}
+	kfree(reqs);
 	return NULL;
 
 }


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 26/99] brcmfmac: fix interface sanity check
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (24 preceding siblings ...)
  2020-05-20 14:13 12% ` [PATCH 3.16 25/99] brcmfmac: abort and release host after error Ben Hutchings
@ 2020-05-20 14:13 12% ` Ben Hutchings
  2020-05-20 14:13 13% ` [PATCH 3.16 27/99] orinoco_usb: " Ben Hutchings
                   ` (73 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:13 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Johan Hovold, Arend van Spriel, Kalle Valo

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Johan Hovold <johan@kernel.org>

commit 3428fbcd6e6c0850b1a8b2a12082b7b2aabb3da3 upstream.

Make sure to use the current alternate setting when verifying the
interface descriptors to avoid binding to an invalid interface.

Failing to do so could cause the driver to misbehave or trigger a WARN()
in usb_submit_urb() that kernels with panic_on_warn set would choke on.

Fixes: 71bb244ba2fd ("brcm80211: fmac: add USB support for bcm43235/6/8 chipsets")
Cc: Arend van Spriel <arend@broadcom.com>
Signed-off-by: Johan Hovold <johan@kernel.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
[bwh: Backported to 3.16:
 - Altsetting lookup is done by the IFALTS() macro
 - Adjust filename]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
--- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
@@ -41,7 +41,7 @@
 
 #define CONFIGDESC(usb)         (&((usb)->actconfig)->desc)
 #define IFPTR(usb, idx)         ((usb)->actconfig->interface[(idx)])
-#define IFALTS(usb, idx)        (IFPTR((usb), (idx))->altsetting[0])
+#define IFALTS(usb, idx)        (*IFPTR((usb), (idx))->cur_altsetting)
 #define IFDESC(usb, idx)        IFALTS((usb), (idx)).desc
 #define IFEPDESC(usb, idx, ep)  (IFALTS((usb), (idx)).endpoint[(ep)]).desc
 


^ permalink raw reply	[relevance 12%]

* [PATCH 3.16 31/99] crypto: picoxcell - adjust the position of tasklet_init and fix missed tasklet_kill
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (29 preceding siblings ...)
  2020-05-20 14:13  9% ` [PATCH 3.16 30/99] brcmfmac: Fix memory leak in brcmf_usbdev_qinit Ben Hutchings
@ 2020-05-20 14:13  9% ` Ben Hutchings
  2020-05-20 14:14  9% ` [PATCH 3.16 32/99] scsi: qla2xxx: Fix mtcp dump collection failure Ben Hutchings
                   ` (68 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:13 UTC (permalink / raw)
  To: linux-kernel, stable; +Cc: akpm, Denis Kirjanov, Herbert Xu, Chuhong Yuan

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Chuhong Yuan <hslester96@gmail.com>

commit 7f8c36fe9be46862c4f3c5302f769378028a34fa upstream.

Since tasklet is needed to be initialized before registering IRQ
handler, adjust the position of tasklet_init to fix the wrong order.

Besides, to fix the missed tasklet_kill, this patch adds a helper
function and uses devm_add_action to kill the tasklet automatically.

Fixes: ce92136843cb ("crypto: picoxcell - add support for the picoxcell crypto engines")
Signed-off-by: Chuhong Yuan <hslester96@gmail.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/crypto/picoxcell_crypto.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

--- a/drivers/crypto/picoxcell_crypto.c
+++ b/drivers/crypto/picoxcell_crypto.c
@@ -1690,6 +1690,11 @@ static bool spacc_is_compatible(struct p
 	return false;
 }
 
+static void spacc_tasklet_kill(void *data)
+{
+	tasklet_kill(data);
+}
+
 static int spacc_probe(struct platform_device *pdev)
 {
 	int i, err, ret = -EINVAL;
@@ -1730,6 +1735,14 @@ static int spacc_probe(struct platform_d
 		return -ENXIO;
 	}
 
+	tasklet_init(&engine->complete, spacc_spacc_complete,
+		     (unsigned long)engine);
+
+	ret = devm_add_action(&pdev->dev, spacc_tasklet_kill,
+			      &engine->complete);
+	if (ret)
+		return ret;
+
 	if (devm_request_irq(&pdev->dev, irq->start, spacc_spacc_irq, 0,
 			     engine->name, engine)) {
 		dev_err(engine->dev, "failed to request IRQ\n");
@@ -1792,8 +1805,6 @@ static int spacc_probe(struct platform_d
 	INIT_LIST_HEAD(&engine->completed);
 	INIT_LIST_HEAD(&engine->in_progress);
 	engine->in_flight = 0;
-	tasklet_init(&engine->complete, spacc_spacc_complete,
-		     (unsigned long)engine);
 
 	platform_set_drvdata(pdev, engine);
 


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 27/99] orinoco_usb: fix interface sanity check
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (25 preceding siblings ...)
  2020-05-20 14:13 12% ` [PATCH 3.16 26/99] brcmfmac: fix interface sanity check Ben Hutchings
@ 2020-05-20 14:13 13% ` Ben Hutchings
  2020-05-20 14:13  9% ` [PATCH 3.16 28/99] rsi_91x_usb: " Ben Hutchings
                   ` (72 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:13 UTC (permalink / raw)
  To: linux-kernel, stable; +Cc: akpm, Denis Kirjanov, Johan Hovold, Kalle Valo

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Johan Hovold <johan@kernel.org>

commit b73e05aa543cf8db4f4927e36952360d71291d41 upstream.

Make sure to use the current alternate setting when verifying the
interface descriptors to avoid binding to an invalid interface.

Failing to do so could cause the driver to misbehave or trigger a WARN()
in usb_submit_urb() that kernels with panic_on_warn set would choke on.

Fixes: 9afac70a7305 ("orinoco: add orinoco_usb driver")
Signed-off-by: Johan Hovold <johan@kernel.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
[bwh: Backported to 3.16: adjust filename]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/net/wireless/orinoco/orinoco_usb.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

--- a/drivers/net/wireless/orinoco/orinoco_usb.c
+++ b/drivers/net/wireless/orinoco/orinoco_usb.c
@@ -1602,9 +1602,9 @@ static int ezusb_probe(struct usb_interf
 	/* set up the endpoint information */
 	/* check out the endpoints */
 
-	iface_desc = &interface->altsetting[0].desc;
+	iface_desc = &interface->cur_altsetting->desc;
 	for (i = 0; i < iface_desc->bNumEndpoints; ++i) {
-		ep = &interface->altsetting[0].endpoint[i].desc;
+		ep = &interface->cur_altsetting->endpoint[i].desc;
 
 		if (((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
 		     == USB_DIR_IN) &&


^ permalink raw reply	[relevance 13%]

* [PATCH 3.16 28/99] rsi_91x_usb: fix interface sanity check
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (26 preceding siblings ...)
  2020-05-20 14:13 13% ` [PATCH 3.16 27/99] orinoco_usb: " Ben Hutchings
@ 2020-05-20 14:13  9% ` Ben Hutchings
  2020-05-20 14:13 13% ` [PATCH 3.16 29/99] zd1211rw: fix storage endpoint lookup Ben Hutchings
                   ` (71 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:13 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Johan Hovold, Fariya Fatima, Kalle Valo

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Johan Hovold <johan@kernel.org>

commit 3139b180906af43bc09bd3373fc2338a8271d9d9 upstream.

Make sure to use the current alternate setting when verifying the
interface descriptors to avoid binding to an invalid interface.

Failing to do so could cause the driver to misbehave or trigger a WARN()
in usb_submit_urb() that kernels with panic_on_warn set would choke on.

Fixes: dad0d04fa7ba ("rsi: Add RS9113 wireless driver")
Cc: Fariya Fatima <fariyaf@gmail.com>
Signed-off-by: Johan Hovold <johan@kernel.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/net/wireless/rsi/rsi_91x_usb.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/drivers/net/wireless/rsi/rsi_91x_usb.c
+++ b/drivers/net/wireless/rsi/rsi_91x_usb.c
@@ -103,7 +103,7 @@ static int rsi_find_bulk_in_and_out_endp
 	__le16 buffer_size;
 	int ii, bep_found = 0;
 
-	iface_desc = &(interface->altsetting[0]);
+	iface_desc = interface->cur_altsetting;
 
 	for (ii = 0; ii < iface_desc->desc.bNumEndpoints; ++ii) {
 		endpoint = &(iface_desc->endpoint[ii].desc);


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 36/99] ALSA: sh: Fix compile warning wrt const
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (34 preceding siblings ...)
  2020-05-20 14:14 12% ` [PATCH 3.16 35/99] pxa168fb: Fix the function used to release some memory in an error handling path Ben Hutchings
@ 2020-05-20 14:14  9% ` Ben Hutchings
  2020-05-20 14:14  9% ` [PATCH 3.16 37/99] clk: tegra: Mark fuse clock as critical Ben Hutchings
                   ` (63 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable; +Cc: akpm, Denis Kirjanov, Takashi Iwai

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Takashi Iwai <tiwai@suse.de>

commit f1dd4795b1523fbca7ab4344dd5a8bb439cc770d upstream.

A long-standing compile warning was seen during build test:
  sound/sh/aica.c: In function 'load_aica_firmware':
  sound/sh/aica.c:521:25: warning: passing argument 2 of 'spu_memload' discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers]

Fixes: 198de43d758c ("[ALSA] Add ALSA support for the SEGA Dreamcast PCM device")
Link: https://lore.kernel.org/r/20200105144823.29547-69-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 sound/sh/aica.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

--- a/sound/sh/aica.c
+++ b/sound/sh/aica.c
@@ -120,10 +120,10 @@ static void spu_memset(u32 toi, u32 what
 }
 
 /* spu_memload - write to SPU address space */
-static void spu_memload(u32 toi, void *from, int length)
+static void spu_memload(u32 toi, const void *from, int length)
 {
 	unsigned long flags;
-	u32 *froml = from;
+	const u32 *froml = from;
 	u32 __iomem *to = (u32 __iomem *) (SPU_MEMORY_BASE + toi);
 	int i;
 	u32 val;


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 33/99] rtc: hym8563: Return -EINVAL if the time is known to be invalid
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (31 preceding siblings ...)
  2020-05-20 14:14  9% ` [PATCH 3.16 32/99] scsi: qla2xxx: Fix mtcp dump collection failure Ben Hutchings
@ 2020-05-20 14:14  9% ` Ben Hutchings
  2020-05-20 14:14 11% ` [PATCH 3.16 34/99] gianfar: Fix TX timestamping with a stacked DSA driver Ben Hutchings
                   ` (66 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Paul Kocialkowski, Alexandre Belloni

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Paul Kocialkowski <paul.kocialkowski@bootlin.com>

commit f236a2a2ebabad0848ad0995af7ad1dc7029e895 upstream.

The current code returns -EPERM when the voltage loss bit is set.
Since the bit indicates that the time value is not valid, return
-EINVAL instead, which is the appropriate error code for this
situation.

Fixes: dcaf03849352 ("rtc: add hym8563 rtc-driver")
Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
Link: https://lore.kernel.org/r/20191212153111.966923-1-paul.kocialkowski@bootlin.com
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/rtc/rtc-hym8563.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/drivers/rtc/rtc-hym8563.c
+++ b/drivers/rtc/rtc-hym8563.c
@@ -105,7 +105,7 @@ static int hym8563_rtc_read_time(struct
 
 	if (!hym8563->valid) {
 		dev_warn(&client->dev, "no valid clock/calendar values available\n");
-		return -EPERM;
+		return -EINVAL;
 	}
 
 	ret = i2c_smbus_read_i2c_block_data(client, HYM8563_SEC, 7, buf);


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 48/99] usb: dwc3: turn off VBUS when leaving host mode
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (46 preceding siblings ...)
  2020-05-20 14:14  7% ` [PATCH 3.16 47/99] dm space map common: fix to ensure new block isn't already in use Ben Hutchings
@ 2020-05-20 14:14  9% ` Ben Hutchings
  2020-05-20 14:14 11% ` [PATCH 3.16 49/99] usb: gadget: f_ncm: Use atomic_t to track in-flight request Ben Hutchings
                   ` (51 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Sasha Levin, Felipe Balbi, Bin Liu,
	Greg Kroah-Hartman

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Bin Liu <b-liu@ti.com>

commit 09ed259fac621634d51cd986aa8d65f035662658 upstream.

VBUS should be turned off when leaving the host mode.
Set GCTL_PRTCAP to device mode in teardown to de-assert DRVVBUS pin to
turn off VBUS power.

Fixes: 5f94adfeed97 ("usb: dwc3: core: refactor mode initialization to its own function")
Signed-off-by: Bin Liu <b-liu@ti.com>
Signed-off-by: Felipe Balbi <balbi@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/usb/dwc3/core.c | 3 +++
 1 file changed, 3 insertions(+)

--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -614,6 +614,9 @@ static void dwc3_core_exit_mode(struct d
 		/* do nothing */
 		break;
 	}
+
+	/* de-assert DRVVBUS for HOST and OTG mode */
+	dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);
 }
 
 #define DWC3_ALIGN_MASK		(16 - 1)


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 51/99] staging: wlan-ng: ensure error return is actually returned
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (49 preceding siblings ...)
  2020-05-20 14:14 11% ` [PATCH 3.16 50/99] usb: gadget: f_ecm: " Ben Hutchings
@ 2020-05-20 14:14  9% ` Ben Hutchings
  2020-05-20 14:14  9% ` [PATCH 3.16 52/99] nfs: NFS_SWAP should depend on SWAP Ben Hutchings
                   ` (48 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Greg Kroah-Hartman, Colin Ian King

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Colin Ian King <colin.king@canonical.com>

commit 4cc41cbce536876678b35e03c4a8a7bb72c78fa9 upstream.

Currently when the call to prism2sta_ifst fails a netdev_err error
is reported, error return variable result is set to -1 but the
function always returns 0 for success.  Fix this by returning
the error value in variable result rather than 0.

Addresses-Coverity: ("Unused value")
Fixes: 00b3ed168508 ("Staging: add wlan-ng prism2 usb driver")
Signed-off-by: Colin Ian King <colin.king@canonical.com>
Link: https://lore.kernel.org/r/20200114181604.390235-1-colin.king@canonical.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/staging/wlan-ng/prism2mgmt.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/drivers/staging/wlan-ng/prism2mgmt.c
+++ b/drivers/staging/wlan-ng/prism2mgmt.c
@@ -939,7 +939,7 @@ int prism2mgmt_flashdl_state(wlandevice_
 		}
 	}
 
-	return 0;
+	return result;
 }
 
 /*----------------------------------------------------------------


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 46/99] power: supply: sbs-battery: Fix a signedness bug in sbs_get_battery_capacity()
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (44 preceding siblings ...)
  2020-05-20 14:14  7% ` [PATCH 3.16 45/99] PCI: Don't disable bridge BARs when assigning bus resources Ben Hutchings
@ 2020-05-20 14:14 13% ` Ben Hutchings
  2020-05-20 14:14  7% ` [PATCH 3.16 47/99] dm space map common: fix to ensure new block isn't already in use Ben Hutchings
                   ` (53 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Sebastian Reichel, Dan Carpenter

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Dan Carpenter <dan.carpenter@oracle.com>

commit eb368de6de32925c65a97c1e929a31cae2155aee upstream.

The "mode" variable is an enum and in this context GCC treats it as an
unsigned int so the error handling is never triggered.

Fixes: 51d075660457 ("bq20z75: Add support for charge properties")
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
[bwh: Backported to 3.16: adjust filename, context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/power/sbs-battery.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/drivers/power/sbs-battery.c
+++ b/drivers/power/sbs-battery.c
@@ -400,7 +400,7 @@ static int sbs_get_battery_capacity(stru
 		mode = BATTERY_MODE_AMPS;
 
 	mode = sbs_set_battery_mode(client, mode);
-	if (mode < 0)
+	if ((int)mode < 0)
 		return mode;
 
 	ret = sbs_read_word_data(client, sbs_data[reg_offset].addr);


^ permalink raw reply	[relevance 13%]

* [PATCH 3.16 37/99] clk: tegra: Mark fuse clock as critical
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (35 preceding siblings ...)
  2020-05-20 14:14  9% ` [PATCH 3.16 36/99] ALSA: sh: Fix compile warning wrt const Ben Hutchings
@ 2020-05-20 14:14  9% ` Ben Hutchings
  2020-05-20 15:51 13%   ` Ben Hutchings
  2020-05-20 14:14  8% ` [PATCH 3.16 38/99] ARM: tegra: Enable PLLP bypass during Tegra124 LP1 Ben Hutchings
                   ` (62 subsequent siblings)
  99 siblings, 1 reply; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Jonathan Hunter, Thierry Reding, Stephen Warren

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Stephen Warren <swarren@nvidia.com>

commit bf83b96f87ae2abb1e535306ea53608e8de5dfbb upstream.

For a little over a year, U-Boot on Tegra124 has configured the flow
controller to perform automatic RAM re-repair on off->on power
transitions of the CPU rail[1]. This is mandatory for correct operation
of Tegra124. However, RAM re-repair relies on certain clocks, which the
kernel must enable and leave running. The fuse clock is one of those
clocks. Mark this clock as critical so that LP1 power mode (system
suspend) operates correctly.

[1] 3cc7942a4ae5 ARM: tegra: implement RAM repair

Reported-by: Jonathan Hunter <jonathanh@nvidia.com>
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/clk/tegra/clk-tegra-periph.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

--- a/drivers/clk/tegra/clk-tegra-periph.c
+++ b/drivers/clk/tegra/clk-tegra-periph.c
@@ -517,7 +517,11 @@ static struct tegra_periph_init_data gat
 	GATE("vcp", "clk_m", 29, 0, tegra_clk_vcp, 0),
 	GATE("apbdma", "clk_m", 34, 0, tegra_clk_apbdma, 0),
 	GATE("kbc", "clk_32k", 36, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_kbc, 0),
-	GATE("fuse", "clk_m", 39, TEGRA_PERIPH_ON_APB, tegra_clk_fuse, 0),
+	/*
+	 * Critical for RAM re-repair operation, which must occur on resume
+	 * from LP1 system suspend and as part of CCPLEX cluster switching.
+	 */
+	GATE("fuse", "clk_m", 39, TEGRA_PERIPH_ON_APB, tegra_clk_fuse, CLK_IS_CRITICAL),
 	GATE("fuse_burn", "clk_m", 39, TEGRA_PERIPH_ON_APB, tegra_clk_fuse_burn, 0),
 	GATE("kfuse", "clk_m", 40, TEGRA_PERIPH_ON_APB, tegra_clk_kfuse, 0),
 	GATE("apbif", "clk_m", 107, TEGRA_PERIPH_ON_APB, tegra_clk_apbif, 0),


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 32/99] scsi: qla2xxx: Fix mtcp dump collection failure
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (30 preceding siblings ...)
  2020-05-20 14:13  9% ` [PATCH 3.16 31/99] crypto: picoxcell - adjust the position of tasklet_init and fix missed tasklet_kill Ben Hutchings
@ 2020-05-20 14:14  9% ` Ben Hutchings
  2020-05-20 14:14  9% ` [PATCH 3.16 33/99] rtc: hym8563: Return -EINVAL if the time is known to be invalid Ben Hutchings
                   ` (67 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Martin K. Petersen, Himanshu Madhani, Quinn Tran

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Quinn Tran <qutran@marvell.com>

commit 641e0efddcbde52461e017136acd3ce7f2ef0c14 upstream.

MTCP dump failed due to MB Reg 10 was picking garbage data from stack
memory.

Fixes: 81178772b636a ("[SCSI] qla2xxx: Implemetation of mctp.")
Link: https://lore.kernel.org/r/20191217220617.28084-14-hmadhani@marvell.com
Signed-off-by: Quinn Tran <qutran@marvell.com>
Signed-off-by: Himanshu Madhani <hmadhani@marvell.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/scsi/qla2xxx/qla_mbx.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -5388,9 +5388,8 @@ qla2x00_dump_mctp_data(scsi_qla_host_t *
 	mcp->mb[7] = LSW(MSD(req_dma));
 	mcp->mb[8] = MSW(addr);
 	/* Setting RAM ID to valid */
-	mcp->mb[10] |= BIT_7;
 	/* For MCTP RAM ID is 0x40 */
-	mcp->mb[10] |= 0x40;
+	mcp->mb[10] = BIT_7 | 0x40;
 
 	mcp->out_mb |= MBX_10|MBX_8|MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|
 	    MBX_0;


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 34/99] gianfar: Fix TX timestamping with a stacked DSA driver
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (32 preceding siblings ...)
  2020-05-20 14:14  9% ` [PATCH 3.16 33/99] rtc: hym8563: Return -EINVAL if the time is known to be invalid Ben Hutchings
@ 2020-05-20 14:14 11% ` Ben Hutchings
  2020-05-20 14:14 12% ` [PATCH 3.16 35/99] pxa168fb: Fix the function used to release some memory in an error handling path Ben Hutchings
                   ` (65 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, David S. Miller, Vladimir Oltean, Richard Cochran

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Vladimir Oltean <olteanv@gmail.com>

commit c26a2c2ddc0115eb088873f5c309cf46b982f522 upstream.

The driver wrongly assumes that it is the only entity that can set the
SKBTX_IN_PROGRESS bit of the current skb. Therefore, in the
gfar_clean_tx_ring function, where the TX timestamp is collected if
necessary, the aforementioned bit is used to discriminate whether or not
the TX timestamp should be delivered to the socket's error queue.

But a stacked driver such as a DSA switch can also set the
SKBTX_IN_PROGRESS bit, which is actually exactly what it should do in
order to denote that the hardware timestamping process is undergoing.

Therefore, gianfar would misinterpret the "in progress" bit as being its
own, and deliver a second skb clone in the socket's error queue,
completely throwing off a PTP process which is not expecting to receive
it, _even though_ TX timestamping is not enabled for gianfar.

There have been discussions [0] as to whether non-MAC drivers need or
not to set SKBTX_IN_PROGRESS at all (whose purpose is to avoid sending 2
timestamps, a sw and a hw one, to applications which only expect one).
But as of this patch, there are at least 2 PTP drivers that would break
in conjunction with gianfar: the sja1105 DSA switch and the felix
switch, by way of its ocelot core driver.

So regardless of that conclusion, fix the gianfar driver to not do stuff
based on flags set by others and not intended for it.

[0]: https://www.spinics.net/lists/netdev/msg619699.html

Fixes: f0ee7acfcdd4 ("gianfar: Add hardware TX timestamping support")
Signed-off-by: Vladimir Oltean <olteanv@gmail.com>
Acked-by: Richard Cochran <richardcochran@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/net/ethernet/freescale/gianfar.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -2524,13 +2524,17 @@ static void gfar_clean_tx_ring(struct gf
 
 	while ((skb = tx_queue->tx_skbuff[skb_dirtytx])) {
 		unsigned long flags;
+		bool do_tstamp;
+
+		do_tstamp = (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) &&
+			    priv->hwts_tx_en;
 
 		frags = skb_shinfo(skb)->nr_frags;
 
 		/* When time stamping, one additional TxBD must be freed.
 		 * Also, we need to dma_unmap_single() the TxPAL.
 		 */
-		if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS))
+		if (unlikely(do_tstamp))
 			nr_txbds = frags + 2;
 		else
 			nr_txbds = frags + 1;
@@ -2544,7 +2548,7 @@ static void gfar_clean_tx_ring(struct gf
 		    (lstatus & BD_LENGTH_MASK))
 			break;
 
-		if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) {
+		if (unlikely(do_tstamp)) {
 			next = next_txbd(bdp, base, tx_ring_size);
 			buflen = next->length + GMAC_FCB_LEN + GMAC_TXPAL_LEN;
 		} else
@@ -2553,7 +2557,7 @@ static void gfar_clean_tx_ring(struct gf
 		dma_unmap_single(priv->dev, bdp->bufPtr,
 				 buflen, DMA_TO_DEVICE);
 
-		if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) {
+		if (unlikely(do_tstamp)) {
 			struct skb_shared_hwtstamps shhwtstamps;
 			u64 *ns = (u64*) (((u32)skb->data + 0x10) & ~0x7);
 


^ permalink raw reply	[relevance 11%]

* [PATCH 3.16 62/99] USB: serial: ir-usb: add missing endpoint sanity check
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (60 preceding siblings ...)
  2020-05-20 14:14 12% ` [PATCH 3.16 61/99] KVM: x86/mmu: Apply max PA check for MMIO sptes to 32-bit KVM Ben Hutchings
@ 2020-05-20 14:14  9% ` Ben Hutchings
  2020-05-20 14:14  8% ` [PATCH 3.16 63/99] USB: serial: ir-usb: fix link-speed handling Ben Hutchings
                   ` (37 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Greg Kroah-Hartman, Johan Hovold

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Johan Hovold <johan@kernel.org>

commit 2988a8ae7476fe9535ab620320790d1714bdad1d upstream.

Add missing endpoint sanity check to avoid dereferencing a NULL-pointer
on open() in case a device lacks a bulk-out endpoint.

Note that prior to commit f4a4cbb2047e ("USB: ir-usb: reimplement using
generic framework") the oops would instead happen on open() if the
device lacked a bulk-in endpoint and on write() if it lacked a bulk-out
endpoint.

Fixes: f4a4cbb2047e ("USB: ir-usb: reimplement using generic framework")
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Johan Hovold <johan@kernel.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/usb/serial/ir-usb.c | 3 +++
 1 file changed, 3 insertions(+)

--- a/drivers/usb/serial/ir-usb.c
+++ b/drivers/usb/serial/ir-usb.c
@@ -199,6 +199,9 @@ static int ir_startup(struct usb_serial
 	struct usb_irda_cs_descriptor *irda_desc;
 	int rates;
 
+	if (serial->num_bulk_in < 1 || serial->num_bulk_out < 1)
+		return -ENODEV;
+
 	irda_desc = irda_usb_find_class_desc(serial, 0);
 	if (!irda_desc) {
 		dev_err(&serial->dev->dev,


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 39/99] media: iguanair: add sanity checks
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (37 preceding siblings ...)
  2020-05-20 14:14  8% ` [PATCH 3.16 38/99] ARM: tegra: Enable PLLP bypass during Tegra124 LP1 Ben Hutchings
@ 2020-05-20 14:14  9% ` Ben Hutchings
  2020-05-20 14:14  9% ` [PATCH 3.16 40/99] media: iguanair: fix endpoint sanity check Ben Hutchings
                   ` (60 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Mauro Carvalho Chehab, Oliver Neukum,
	Sean Young, syzbot+01a77b82edaa374068e1

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Oliver Neukum <oneukum@suse.com>

commit ab1cbdf159beba7395a13ab70bc71180929ca064 upstream.

The driver needs to check the endpoint types, too, as opposed
to the number of endpoints. This also requires moving the check earlier.

Reported-by: syzbot+01a77b82edaa374068e1@syzkaller.appspotmail.com
Signed-off-by: Oliver Neukum <oneukum@suse.com>
Signed-off-by: Sean Young <sean@mess.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/media/rc/iguanair.c | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)

--- a/drivers/media/rc/iguanair.c
+++ b/drivers/media/rc/iguanair.c
@@ -430,6 +430,10 @@ static int iguanair_probe(struct usb_int
 	int ret, pipein, pipeout;
 	struct usb_host_interface *idesc;
 
+	idesc = intf->altsetting;
+	if (idesc->desc.bNumEndpoints < 2)
+		return -ENODEV;
+
 	ir = kzalloc(sizeof(*ir), GFP_KERNEL);
 	rc = rc_allocate_device();
 	if (!ir || !rc) {
@@ -444,18 +448,13 @@ static int iguanair_probe(struct usb_int
 	ir->urb_in = usb_alloc_urb(0, GFP_KERNEL);
 	ir->urb_out = usb_alloc_urb(0, GFP_KERNEL);
 
-	if (!ir->buf_in || !ir->packet || !ir->urb_in || !ir->urb_out) {
+	if (!ir->buf_in || !ir->packet || !ir->urb_in || !ir->urb_out ||
+	    !usb_endpoint_is_int_in(&idesc->endpoint[0].desc) ||
+	    !usb_endpoint_is_int_out(&idesc->endpoint[1].desc)) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
-	idesc = intf->altsetting;
-
-	if (idesc->desc.bNumEndpoints < 2) {
-		ret = -ENODEV;
-		goto out;
-	}
-
 	ir->rc = rc;
 	ir->dev = &intf->dev;
 	ir->udev = udev;


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 91/99] clocksource: Prevent double add_timer_on() for watchdog_timer
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (89 preceding siblings ...)
  2020-05-20 14:14  9% ` [PATCH 3.16 90/99] ALSA: dummy: Fix PCM format loop in proc output Ben Hutchings
@ 2020-05-20 14:14  8% ` Ben Hutchings
  2020-05-20 14:15  7% ` [PATCH 3.16 92/99] cls_rsvp: fix rsvp_policy Ben Hutchings
                   ` (8 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Thomas Gleixner, Konstantin Khlebnikov

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Konstantin Khlebnikov <khlebnikov@yandex-team.ru>

commit febac332a819f0e764aa4da62757ba21d18c182b upstream.

Kernel crashes inside QEMU/KVM are observed:

  kernel BUG at kernel/time/timer.c:1154!
  BUG_ON(timer_pending(timer) || !timer->function) in add_timer_on().

At the same time another cpu got:

  general protection fault: 0000 [#1] SMP PTI of poinson pointer 0xdead000000000200 in:

  __hlist_del at include/linux/list.h:681
  (inlined by) detach_timer at kernel/time/timer.c:818
  (inlined by) expire_timers at kernel/time/timer.c:1355
  (inlined by) __run_timers at kernel/time/timer.c:1686
  (inlined by) run_timer_softirq at kernel/time/timer.c:1699

Unfortunately kernel logs are badly scrambled, stacktraces are lost.

Printing the timer->function before the BUG_ON() pointed to
clocksource_watchdog().

The execution of clocksource_watchdog() can race with a sequence of
clocksource_stop_watchdog() .. clocksource_start_watchdog():

expire_timers()
 detach_timer(timer, true);
  timer->entry.pprev = NULL;
 raw_spin_unlock_irq(&base->lock);
 call_timer_fn
  clocksource_watchdog()

					clocksource_watchdog_kthread() or
					clocksource_unbind()

					spin_lock_irqsave(&watchdog_lock, flags);
					clocksource_stop_watchdog();
					 del_timer(&watchdog_timer);
					 watchdog_running = 0;
					spin_unlock_irqrestore(&watchdog_lock, flags);

					spin_lock_irqsave(&watchdog_lock, flags);
					clocksource_start_watchdog();
					 add_timer_on(&watchdog_timer, ...);
					 watchdog_running = 1;
					spin_unlock_irqrestore(&watchdog_lock, flags);

  spin_lock(&watchdog_lock);
  add_timer_on(&watchdog_timer, ...);
   BUG_ON(timer_pending(timer) || !timer->function);
    timer_pending() -> true
    BUG()

I.e. inside clocksource_watchdog() watchdog_timer could be already armed.

Check timer_pending() before calling add_timer_on(). This is sufficient as
all operations are synchronized by watchdog_lock.

Fixes: 75c5158f70c0 ("timekeeping: Update clocksource with stop_machine")
Signed-off-by: Konstantin Khlebnikov <khlebnikov@yandex-team.ru>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lore.kernel.org/r/158048693917.4378.13823603769948933793.stgit@buzz
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 kernel/time/clocksource.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

--- a/kernel/time/clocksource.c
+++ b/kernel/time/clocksource.c
@@ -343,8 +343,15 @@ static void clocksource_watchdog(unsigne
 	next_cpu = cpumask_next(raw_smp_processor_id(), cpu_online_mask);
 	if (next_cpu >= nr_cpu_ids)
 		next_cpu = cpumask_first(cpu_online_mask);
-	watchdog_timer.expires += WATCHDOG_INTERVAL;
-	add_timer_on(&watchdog_timer, next_cpu);
+
+	/*
+	 * Arm timer if not already pending: could race with concurrent
+	 * pair clocksource_stop_watchdog() clocksource_start_watchdog().
+	 */
+	if (!timer_pending(&watchdog_timer)) {
+		watchdog_timer.expires += WATCHDOG_INTERVAL;
+		add_timer_on(&watchdog_timer, next_cpu);
+	}
 out:
 	spin_unlock(&watchdog_lock);
 }


^ permalink raw reply	[relevance 8%]

* [PATCH 3.16 40/99] media: iguanair: fix endpoint sanity check
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (38 preceding siblings ...)
  2020-05-20 14:14  9% ` [PATCH 3.16 39/99] media: iguanair: add sanity checks Ben Hutchings
@ 2020-05-20 14:14  9% ` Ben Hutchings
  2020-05-20 14:14 11% ` [PATCH 3.16 41/99] ARM: dts: at91: sama5d3: fix maximum peripheral clock rates Ben Hutchings
                   ` (59 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Oliver Neukum, Johan Hovold, Sean Young,
	Mauro Carvalho Chehab

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Johan Hovold <johan@kernel.org>

commit 1b257870a78b0a9ce98fdfb052c58542022ffb5b upstream.

Make sure to use the current alternate setting, which need not be the
first one by index, when verifying the endpoint descriptors and
initialising the URBs.

Failing to do so could cause the driver to misbehave or trigger a WARN()
in usb_submit_urb() that kernels with panic_on_warn set would choke on.

Fixes: 26ff63137c45 ("[media] Add support for the IguanaWorks USB IR Transceiver")
Fixes: ab1cbdf159be ("media: iguanair: add sanity checks")
Cc: Oliver Neukum <oneukum@suse.com>
Signed-off-by: Johan Hovold <johan@kernel.org>
Signed-off-by: Sean Young <sean@mess.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/media/rc/iguanair.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/drivers/media/rc/iguanair.c
+++ b/drivers/media/rc/iguanair.c
@@ -430,7 +430,7 @@ static int iguanair_probe(struct usb_int
 	int ret, pipein, pipeout;
 	struct usb_host_interface *idesc;
 
-	idesc = intf->altsetting;
+	idesc = intf->cur_altsetting;
 	if (idesc->desc.bNumEndpoints < 2)
 		return -ENODEV;
 


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 49/99] usb: gadget: f_ncm: Use atomic_t to track in-flight request
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (47 preceding siblings ...)
  2020-05-20 14:14  9% ` [PATCH 3.16 48/99] usb: dwc3: turn off VBUS when leaving host mode Ben Hutchings
@ 2020-05-20 14:14 11% ` Ben Hutchings
  2020-05-20 14:14 11% ` [PATCH 3.16 50/99] usb: gadget: f_ecm: " Ben Hutchings
                   ` (50 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Felipe Balbi, Greg Kroah-Hartman,
	Bryan O'Donoghue

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Bryan O'Donoghue <bryan.odonoghue@linaro.org>

commit 5b24c28cfe136597dc3913e1c00b119307a20c7e upstream.

Currently ncm->notify_req is used to flag when a request is in-flight.
ncm->notify_req is set to NULL and when a request completes it is
subsequently reset.

This is fundamentally buggy in that the unbind logic of the NCM driver will
unconditionally free ncm->notify_req leading to a NULL pointer dereference.

Fixes: 40d133d7f542 ("usb: gadget: f_ncm: convert to new function interface with backward compatibility")
Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Signed-off-by: Felipe Balbi <balbi@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
[bwh: Backported to 3.16: adjust filename]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/usb/gadget/f_ncm.c | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

--- a/drivers/usb/gadget/f_ncm.c
+++ b/drivers/usb/gadget/f_ncm.c
@@ -57,6 +57,7 @@ struct f_ncm {
 	struct usb_ep			*notify;
 	struct usb_request		*notify_req;
 	u8				notify_state;
+	atomic_t			notify_count;
 	bool				is_open;
 
 	const struct ndp_parser_opts	*parser_opts;
@@ -460,7 +461,7 @@ static void ncm_do_notify(struct f_ncm *
 	int				status;
 
 	/* notification already in flight? */
-	if (!req)
+	if (atomic_read(&ncm->notify_count))
 		return;
 
 	event = req->buf;
@@ -500,7 +501,8 @@ static void ncm_do_notify(struct f_ncm *
 	event->bmRequestType = 0xA1;
 	event->wIndex = cpu_to_le16(ncm->ctrl_id);
 
-	ncm->notify_req = NULL;
+	atomic_inc(&ncm->notify_count);
+
 	/*
 	 * In double buffering if there is a space in FIFO,
 	 * completion callback can be called right after the call,
@@ -510,7 +512,7 @@ static void ncm_do_notify(struct f_ncm *
 	status = usb_ep_queue(ncm->notify, req, GFP_ATOMIC);
 	spin_lock(&ncm->lock);
 	if (status < 0) {
-		ncm->notify_req = req;
+		atomic_dec(&ncm->notify_count);
 		DBG(cdev, "notify --> %d\n", status);
 	}
 }
@@ -545,17 +547,19 @@ static void ncm_notify_complete(struct u
 	case 0:
 		VDBG(cdev, "Notification %02x sent\n",
 		     event->bNotificationType);
+		atomic_dec(&ncm->notify_count);
 		break;
 	case -ECONNRESET:
 	case -ESHUTDOWN:
+		atomic_set(&ncm->notify_count, 0);
 		ncm->notify_state = NCM_NOTIFY_NONE;
 		break;
 	default:
 		DBG(cdev, "event %02x --> %d\n",
 			event->bNotificationType, req->status);
+		atomic_dec(&ncm->notify_count);
 		break;
 	}
-	ncm->notify_req = req;
 	ncm_do_notify(ncm);
 	spin_unlock(&ncm->lock);
 }
@@ -1382,6 +1386,11 @@ static void ncm_unbind(struct usb_config
 
 	usb_free_all_descriptors(f);
 
+	if (atomic_read(&ncm->notify_count)) {
+		usb_ep_dequeue(ncm->notify, ncm->notify_req);
+		atomic_set(&ncm->notify_count, 0);
+	}
+
 	kfree(ncm->notify_req->buf);
 	usb_ep_free_request(ncm->notify, ncm->notify_req);
 }


^ permalink raw reply	[relevance 11%]

* [PATCH 3.16 93/99] kconfig: fix broken dependency in randconfig-generated .config
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (91 preceding siblings ...)
  2020-05-20 14:15  7% ` [PATCH 3.16 92/99] cls_rsvp: fix rsvp_policy Ben Hutchings
@ 2020-05-20 14:15  9% ` Ben Hutchings
  2020-05-20 14:15  8% ` [PATCH 3.16 94/99] nfs: use kmap/kunmap directly Ben Hutchings
                   ` (6 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:15 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Vincenzo Frascino, Masahiro Yamada

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Masahiro Yamada <masahiroy@kernel.org>

commit c8fb7d7e48d11520ad24808cfce7afb7b9c9f798 upstream.

Running randconfig on arm64 using KCONFIG_SEED=0x40C5E904 (e.g. on v5.5)
produces the .config with CONFIG_EFI=y and CONFIG_CPU_BIG_ENDIAN=y,
which does not meet the !CONFIG_CPU_BIG_ENDIAN dependency.

This is because the user choice for CONFIG_CPU_LITTLE_ENDIAN vs
CONFIG_CPU_BIG_ENDIAN is set by randomize_choice_values() after the
value of CONFIG_EFI is calculated.

When this happens, the has_changed flag should be set.

Currently, it takes the result from the last iteration. It should
accumulate all the results of the loop.

Fixes: 3b9a19e08960 ("kconfig: loop as long as we changed some symbols in randconfig")
Reported-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 scripts/kconfig/confdata.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/scripts/kconfig/confdata.c
+++ b/scripts/kconfig/confdata.c
@@ -1231,7 +1231,7 @@ bool conf_set_all_new_symbols(enum conf_
 
 		sym_calc_value(csym);
 		if (mode == def_random)
-			has_changed = randomize_choice_values(csym);
+			has_changed |= randomize_choice_values(csym);
 		else {
 			set_all_choice_values(csym);
 			has_changed = true;


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 63/99] USB: serial: ir-usb: fix link-speed handling
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (61 preceding siblings ...)
  2020-05-20 14:14  9% ` [PATCH 3.16 62/99] USB: serial: ir-usb: add missing endpoint sanity check Ben Hutchings
@ 2020-05-20 14:14  8% ` Ben Hutchings
  2020-05-20 14:14  7% ` [PATCH 3.16 64/99] USB: serial: ir-usb: fix IrLAP framing Ben Hutchings
                   ` (36 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Johan Hovold, Greg Kroah-Hartman, Felipe Balbi

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Johan Hovold <johan@kernel.org>

commit 17a0184ca17e288decdca8b2841531e34d49285f upstream.

Commit e0d795e4f36c ("usb: irda: cleanup on ir-usb module") added a USB
IrDA header with common defines, but mistakingly switched to using the
class-descriptor baud-rate bitmask values for the outbound header.

This broke link-speed handling for rates above 9600 baud, but a device
would also be able to operate at the default 9600 baud until a
link-speed request was issued (e.g. using the TCGETS ioctl).

Fixes: e0d795e4f36c ("usb: irda: cleanup on ir-usb module")
Cc: Felipe Balbi <balbi@kernel.org>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Johan Hovold <johan@kernel.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/usb/serial/ir-usb.c | 20 ++++++++++----------
 include/linux/usb/irda.h    | 13 ++++++++++++-
 2 files changed, 22 insertions(+), 11 deletions(-)

--- a/drivers/usb/serial/ir-usb.c
+++ b/drivers/usb/serial/ir-usb.c
@@ -339,34 +339,34 @@ static void ir_set_termios(struct tty_st
 
 	switch (baud) {
 	case 2400:
-		ir_baud = USB_IRDA_BR_2400;
+		ir_baud = USB_IRDA_LS_2400;
 		break;
 	case 9600:
-		ir_baud = USB_IRDA_BR_9600;
+		ir_baud = USB_IRDA_LS_9600;
 		break;
 	case 19200:
-		ir_baud = USB_IRDA_BR_19200;
+		ir_baud = USB_IRDA_LS_19200;
 		break;
 	case 38400:
-		ir_baud = USB_IRDA_BR_38400;
+		ir_baud = USB_IRDA_LS_38400;
 		break;
 	case 57600:
-		ir_baud = USB_IRDA_BR_57600;
+		ir_baud = USB_IRDA_LS_57600;
 		break;
 	case 115200:
-		ir_baud = USB_IRDA_BR_115200;
+		ir_baud = USB_IRDA_LS_115200;
 		break;
 	case 576000:
-		ir_baud = USB_IRDA_BR_576000;
+		ir_baud = USB_IRDA_LS_576000;
 		break;
 	case 1152000:
-		ir_baud = USB_IRDA_BR_1152000;
+		ir_baud = USB_IRDA_LS_1152000;
 		break;
 	case 4000000:
-		ir_baud = USB_IRDA_BR_4000000;
+		ir_baud = USB_IRDA_LS_4000000;
 		break;
 	default:
-		ir_baud = USB_IRDA_BR_9600;
+		ir_baud = USB_IRDA_LS_9600;
 		baud = 9600;
 	}
 
--- a/include/linux/usb/irda.h
+++ b/include/linux/usb/irda.h
@@ -118,11 +118,22 @@ struct usb_irda_cs_descriptor {
  * 6 - 115200 bps
  * 7 - 576000 bps
  * 8 - 1.152 Mbps
- * 9 - 5 mbps
+ * 9 - 4 Mbps
  * 10..15 - Reserved
  */
 #define USB_IRDA_STATUS_LINK_SPEED	0x0f
 
+#define USB_IRDA_LS_NO_CHANGE		0
+#define USB_IRDA_LS_2400		1
+#define USB_IRDA_LS_9600		2
+#define USB_IRDA_LS_19200		3
+#define USB_IRDA_LS_38400		4
+#define USB_IRDA_LS_57600		5
+#define USB_IRDA_LS_115200		6
+#define USB_IRDA_LS_576000		7
+#define USB_IRDA_LS_1152000		8
+#define USB_IRDA_LS_4000000		9
+
 /* The following is a 4-bit value used only for
  * outbound header:
  *


^ permalink raw reply	[relevance 8%]

* [PATCH 3.16 38/99] ARM: tegra: Enable PLLP bypass during Tegra124 LP1
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (36 preceding siblings ...)
  2020-05-20 14:14  9% ` [PATCH 3.16 37/99] clk: tegra: Mark fuse clock as critical Ben Hutchings
@ 2020-05-20 14:14  8% ` Ben Hutchings
  2020-05-20 14:14  9% ` [PATCH 3.16 39/99] media: iguanair: add sanity checks Ben Hutchings
                   ` (61 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Thierry Reding, Stephen Warren, Jonathan Hunter

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Stephen Warren <swarren@nvidia.com>

commit 1a3388d506bf5b45bb283e6a4c4706cfb4897333 upstream.

For a little over a year, U-Boot has configured the flow controller to
perform automatic RAM re-repair on off->on power transitions of the CPU
rail[1]. This is mandatory for correct operation of Tegra124. However,
RAM re-repair relies on certain clocks, which the kernel must enable and
leave running. PLLP is one of those clocks. This clock is shut down
during LP1 in order to save power. Enable bypass (which I believe routes
osc_div_clk, essentially the crystal clock, to the PLL output) so that
this clock signal toggles even though the PLL is not active. This is
required so that LP1 power mode (system suspend) operates correctly.

The bypass configuration must then be undone when resuming from LP1, so
that all peripheral clocks run at the expected rate. Without this, many
peripherals won't work correctly; for example, the UART baud rate would
be incorrect.

NVIDIA's downstream kernel code only does this if not compiled for
Tegra30, so the added code is made conditional upon the chip ID.
NVIDIA's downstream code makes this change conditional upon the active
CPU cluster. The upstream kernel currently doesn't support cluster
switching, so this patch doesn't test the active CPU cluster ID.

[1] 3cc7942a4ae5 ARM: tegra: implement RAM repair

Reported-by: Jonathan Hunter <jonathanh@nvidia.com>
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 arch/arm/mach-tegra/sleep-tegra30.S | 11 +++++++++++
 1 file changed, 11 insertions(+)

--- a/arch/arm/mach-tegra/sleep-tegra30.S
+++ b/arch/arm/mach-tegra/sleep-tegra30.S
@@ -378,6 +378,14 @@ _pll_m_c_x_done:
 	pll_locked r1, r0, CLK_RESET_PLLC_BASE
 	pll_locked r1, r0, CLK_RESET_PLLX_BASE
 
+	tegra_get_soc_id TEGRA_APB_MISC_BASE, r1
+	cmp	r1, #TEGRA30
+	beq	1f
+	ldr	r1, [r0, #CLK_RESET_PLLP_BASE]
+	bic	r1, r1, #(1<<31)	@ disable PllP bypass
+	str	r1, [r0, #CLK_RESET_PLLP_BASE]
+1:
+
 	mov32	r7, TEGRA_TMRUS_BASE
 	ldr	r1, [r7]
 	add	r1, r1, #LOCK_DELAY
@@ -637,7 +645,10 @@ tegra30_switch_cpu_to_clk32k:
 	str	r0, [r4, #PMC_PLLP_WB0_OVERRIDE]
 
 	/* disable PLLP, PLLA, PLLC and PLLX */
+	tegra_get_soc_id TEGRA_APB_MISC_BASE, r1
+	cmp	r1, #TEGRA30
 	ldr	r0, [r5, #CLK_RESET_PLLP_BASE]
+	orrne	r0, r0, #(1 << 31)	@ enable PllP bypass on fast cluster
 	bic	r0, r0, #(1 << 30)
 	str	r0, [r5, #CLK_RESET_PLLP_BASE]
 	ldr	r0, [r5, #CLK_RESET_PLLA_BASE]


^ permalink raw reply	[relevance 8%]

* [PATCH 3.16 25/99] brcmfmac: abort and release host after error
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (23 preceding siblings ...)
  2020-05-20 14:13 13% ` [PATCH 3.16 24/99] brcmfmac: Fix use after free in brcmf_sdio_readframes() Ben Hutchings
@ 2020-05-20 14:13 12% ` Ben Hutchings
  2020-05-20 14:13 12% ` [PATCH 3.16 26/99] brcmfmac: fix interface sanity check Ben Hutchings
                   ` (74 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:13 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Dan Carpenter, Guenter Roeck, Brian Norris,
	Douglas Anderson, Kalle Valo, franky.lin, Matthias Kaehlcke

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Guenter Roeck <linux@roeck-us.net>

commit 863844ee3bd38219c88e82966d1df36a77716f3e upstream.

With commit 216b44000ada ("brcmfmac: Fix use after free in
brcmf_sdio_readframes()") applied, we see locking timeouts in
brcmf_sdio_watchdog_thread().

brcmfmac: brcmf_escan_timeout: timer expired
INFO: task brcmf_wdog/mmc1:621 blocked for more than 120 seconds.
Not tainted 4.19.94-07984-g24ff99a0f713 #1
"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
brcmf_wdog/mmc1 D    0   621      2 0x00000000 last_sleep: 2440793077.  last_runnable: 2440766827
[<c0aa1e60>] (__schedule) from [<c0aa2100>] (schedule+0x98/0xc4)
[<c0aa2100>] (schedule) from [<c0853830>] (__mmc_claim_host+0x154/0x274)
[<c0853830>] (__mmc_claim_host) from [<bf10c5b8>] (brcmf_sdio_watchdog_thread+0x1b0/0x1f8 [brcmfmac])
[<bf10c5b8>] (brcmf_sdio_watchdog_thread [brcmfmac]) from [<c02570b8>] (kthread+0x178/0x180)

In addition to restarting or exiting the loop, it is also necessary to
abort the command and to release the host.

Fixes: 216b44000ada ("brcmfmac: Fix use after free in brcmf_sdio_readframes()")
Cc: Dan Carpenter <dan.carpenter@oracle.com>
Cc: Matthias Kaehlcke <mka@chromium.org>
Cc: Brian Norris <briannorris@chromium.org>
Cc: Douglas Anderson <dianders@chromium.org>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Reviewed-by: Douglas Anderson <dianders@chromium.org>
Acked-by: franky.lin@broadcom.com
Acked-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
[bwh: Backported to 3.16:
 - Use bus->sdiodev->func[1] instead of ->func1
 - Adjust filename]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | 2 ++
 1 file changed, 2 insertions(+)

--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -1971,6 +1971,8 @@ static uint brcmf_sdio_readframes(struct
 			if (brcmf_sdio_hdparse(bus, bus->rxhdr, &rd_new,
 					       BRCMF_SDIO_FT_NORMAL)) {
 				rd->len = 0;
+				brcmf_sdio_rxfail(bus, true, true);
+				sdio_release_host(bus->sdiodev->func[1]);
 				brcmu_pkt_buf_free_skb(pkt);
 				continue;
 			}


^ permalink raw reply	[relevance 12%]

* [PATCH 3.16 23/99] rsi: fix use-after-free on failed probe and unbind
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (21 preceding siblings ...)
  2020-05-20 14:13  9% ` [PATCH 3.16 22/99] ath9k: fix storage endpoint lookup Ben Hutchings
@ 2020-05-20 14:13 12% ` Ben Hutchings
  2020-05-20 14:13 13% ` [PATCH 3.16 24/99] brcmfmac: Fix use after free in brcmf_sdio_readframes() Ben Hutchings
                   ` (76 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:13 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Siva Rebbagondla, Fariya Fatima,
	Johan Hovold, Amitkumar Karwar, Prameela Rani Garnepudi,
	Kalle Valo, syzbot+b563b7f8dbe8223a51e8

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Johan Hovold <johan@kernel.org>

commit e93cd35101b61e4c79149be2cfc927c4b28dc60c upstream.

Make sure to stop both URBs before returning after failed probe as well
as on disconnect to avoid use-after-free in the completion handler.

Reported-by: syzbot+b563b7f8dbe8223a51e8@syzkaller.appspotmail.com
Fixes: a4302bff28e2 ("rsi: add bluetooth rx endpoint")
Fixes: dad0d04fa7ba ("rsi: Add RS9113 wireless driver")
Cc: Siva Rebbagondla <siva.rebbagondla@redpinesignals.com>
Cc: Prameela Rani Garnepudi <prameela.j04cs@gmail.com>
Cc: Amitkumar Karwar <amit.karwar@redpinesignals.com>
Cc: Fariya Fatima <fariyaf@gmail.com>
Signed-off-by: Johan Hovold <johan@kernel.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
[bwh: Backported to 3.16: There is no BT support, so we only need to
 kill one URB on disconnect.]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
--- a/drivers/net/wireless/rsi/rsi_91x_usb.c
+++ b/drivers/net/wireless/rsi/rsi_91x_usb.c
@@ -245,6 +245,14 @@ static void rsi_rx_done_handler(struct u
 	rsi_set_event(&dev->rx_thread.event);
 }
 
+static void rsi_rx_urb_kill(struct rsi_hw *adapter)
+{
+	struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
+	struct urb *urb = dev->rx_usb_urb[0];
+
+	usb_kill_urb(urb);
+}
+
 /**
  * rsi_rx_urb_submit() - This function submits the given URB to the USB stack.
  * @adapter: Pointer to the adapter structure.
@@ -510,6 +518,8 @@ static void rsi_disconnect(struct usb_in
 	if (!adapter)
 		return;
 
+	rsi_rx_urb_kill(adapter);
+
 	rsi_mac80211_detach(adapter);
 	rsi_deinit_usb_interface(adapter);
 	rsi_91x_deinit(adapter);


^ permalink raw reply	[relevance 12%]

* [PATCH 3.16 99/99] sunrpc: expiry_time should be seconds not timeval
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (97 preceding siblings ...)
  2020-05-20 14:15  9% ` [PATCH 3.16 98/99] bonding/alb: properly access headers in bond_alb_xmit() Ben Hutchings
@ 2020-05-20 14:15 12% ` Ben Hutchings
  2020-05-20 21:23  6% ` [PATCH 3.16 00/99] 3.16.84-rc1 review Guenter Roeck
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:15 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, J. Bruce Fields,
	Roberto Bergantinos Corpas, Frank Sorenson

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Roberto Bergantinos Corpas <rbergant@redhat.com>

commit 3d96208c30f84d6edf9ab4fac813306ac0d20c10 upstream.

When upcalling gssproxy, cache_head.expiry_time is set as a
timeval, not seconds since boot. As such, RPC cache expiry
logic will not clean expired objects created under
auth.rpcsec.context cache.

This has proven to cause kernel memory leaks on field. Using
64 bit variants of getboottime/timespec

Expiration times have worked this way since 2010's c5b29f885afe "sunrpc:
use seconds since boot in expiry cache".  The gssproxy code introduced
in 2012 added gss_proxy_save_rsc and introduced the bug.  That's a while
for this to lurk, but it required a bit of an extreme case to make it
obvious.

Signed-off-by: Roberto Bergantinos Corpas <rbergant@redhat.com>
Fixes: 030d794bf498 "SUNRPC: Use gssproxy upcall for server..."
Tested-By: Frank Sorenson <sorenson@redhat.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
[bwh: Backported to 3.16: Use struct timespec and getboottime()]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 net/sunrpc/auth_gss/svcauth_gss.c | 4 ++++
 1 file changed, 4 insertions(+)

--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -1171,6 +1171,7 @@ static int gss_proxy_save_rsc(struct cac
 		dprintk("RPC:       No creds found!\n");
 		goto out;
 	} else {
+		struct timespec boot;
 
 		/* steal creds */
 		rsci.cred = ud->creds;
@@ -1191,6 +1192,9 @@ static int gss_proxy_save_rsc(struct cac
 						&expiry, GFP_KERNEL);
 		if (status)
 			goto out;
+
+		getboottime(&boot);
+		expiry -= boot.tv_sec;
 	}
 
 	rsci.h.expiry_time = expiry;


^ permalink raw reply	[relevance 12%]

* [PATCH 3.16 47/99] dm space map common: fix to ensure new block isn't already in use
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (45 preceding siblings ...)
  2020-05-20 14:14 13% ` [PATCH 3.16 46/99] power: supply: sbs-battery: Fix a signedness bug in sbs_get_battery_capacity() Ben Hutchings
@ 2020-05-20 14:14  7% ` Ben Hutchings
  2020-05-20 14:14  9% ` [PATCH 3.16 48/99] usb: dwc3: turn off VBUS when leaving host mode Ben Hutchings
                   ` (52 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Joe Thornber, Mike Snitzer, Eric Wheeler

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Joe Thornber <ejt@redhat.com>

commit 4feaef830de7ffdd8352e1fe14ad3bf13c9688f8 upstream.

The space-maps track the reference counts for disk blocks allocated by
both the thin-provisioning and cache targets.  There are variants for
tracking metadata blocks and data blocks.

Transactionality is implemented by never touching blocks from the
previous transaction, so we can rollback in the event of a crash.

When allocating a new block we need to ensure the block is free (has
reference count of 0) in both the current and previous transaction.
Prior to this fix we were doing this by searching for a free block in
the previous transaction, and relying on a 'begin' counter to track
where the last allocation in the current transaction was.  This
'begin' field was not being updated in all code paths (eg, increment
of a data block reference count due to breaking sharing of a neighbour
block in the same btree leaf).

This fix keeps the 'begin' field, but now it's just a hint to speed up
the search.  Instead the current transaction is searched for a free
block, and then the old transaction is double checked to ensure it's
free.  Much simpler.

This fixes reports of sm_disk_new_block()'s BUG_ON() triggering when
DM thin-provisioning's snapshots are heavily used.

Reported-by: Eric Wheeler <dm-devel@lists.ewheeler.net>
Signed-off-by: Joe Thornber <ejt@redhat.com>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 .../md/persistent-data/dm-space-map-common.c  | 27 +++++++++++++++++++
 .../md/persistent-data/dm-space-map-common.h  |  2 ++
 .../md/persistent-data/dm-space-map-disk.c    |  6 +++--
 .../persistent-data/dm-space-map-metadata.c   |  5 +++-
 4 files changed, 37 insertions(+), 3 deletions(-)

--- a/drivers/md/persistent-data/dm-space-map-common.c
+++ b/drivers/md/persistent-data/dm-space-map-common.c
@@ -384,6 +384,33 @@ int sm_ll_find_free_block(struct ll_disk
 	return -ENOSPC;
 }
 
+int sm_ll_find_common_free_block(struct ll_disk *old_ll, struct ll_disk *new_ll,
+	                         dm_block_t begin, dm_block_t end, dm_block_t *b)
+{
+	int r;
+	uint32_t count;
+
+	do {
+		r = sm_ll_find_free_block(new_ll, begin, new_ll->nr_blocks, b);
+		if (r)
+			break;
+
+		/* double check this block wasn't used in the old transaction */
+		if (*b >= old_ll->nr_blocks)
+			count = 0;
+		else {
+			r = sm_ll_lookup(old_ll, *b, &count);
+			if (r)
+				break;
+
+			if (count)
+				begin = *b + 1;
+		}
+	} while (count);
+
+	return r;
+}
+
 static int sm_ll_mutate(struct ll_disk *ll, dm_block_t b,
 			int (*mutator)(void *context, uint32_t old, uint32_t *new),
 			void *context, enum allocation_event *ev)
--- a/drivers/md/persistent-data/dm-space-map-common.h
+++ b/drivers/md/persistent-data/dm-space-map-common.h
@@ -109,6 +109,8 @@ int sm_ll_lookup_bitmap(struct ll_disk *
 int sm_ll_lookup(struct ll_disk *ll, dm_block_t b, uint32_t *result);
 int sm_ll_find_free_block(struct ll_disk *ll, dm_block_t begin,
 			  dm_block_t end, dm_block_t *result);
+int sm_ll_find_common_free_block(struct ll_disk *old_ll, struct ll_disk *new_ll,
+	                         dm_block_t begin, dm_block_t end, dm_block_t *result);
 int sm_ll_insert(struct ll_disk *ll, dm_block_t b, uint32_t ref_count, enum allocation_event *ev);
 int sm_ll_inc(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev);
 int sm_ll_dec(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev);
--- a/drivers/md/persistent-data/dm-space-map-disk.c
+++ b/drivers/md/persistent-data/dm-space-map-disk.c
@@ -165,8 +165,10 @@ static int sm_disk_new_block(struct dm_s
 	enum allocation_event ev;
 	struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
 
-	/* FIXME: we should loop round a couple of times */
-	r = sm_ll_find_free_block(&smd->old_ll, smd->begin, smd->old_ll.nr_blocks, b);
+	/*
+	 * Any block we allocate has to be free in both the old and current ll.
+	 */
+	r = sm_ll_find_common_free_block(&smd->old_ll, &smd->ll, smd->begin, smd->ll.nr_blocks, b);
 	if (r)
 		return r;
 
--- a/drivers/md/persistent-data/dm-space-map-metadata.c
+++ b/drivers/md/persistent-data/dm-space-map-metadata.c
@@ -447,7 +447,10 @@ static int sm_metadata_new_block_(struct
 	enum allocation_event ev;
 	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
 
-	r = sm_ll_find_free_block(&smm->old_ll, smm->begin, smm->old_ll.nr_blocks, b);
+	/*
+	 * Any block we allocate has to be free in both the old and current ll.
+	 */
+	r = sm_ll_find_common_free_block(&smm->old_ll, &smm->ll, smm->begin, smm->ll.nr_blocks, b);
 	if (r)
 		return r;
 


^ permalink raw reply	[relevance 7%]

* [PATCH 3.16 60/99] x86: kvm: avoid unused variable warning
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (58 preceding siblings ...)
  2020-05-20 14:14 13% ` [PATCH 3.16 59/99] KVM: nVMX: vmread should not set rflags to specify success in case of #PF Ben Hutchings
@ 2020-05-20 14:14  9% ` Ben Hutchings
  2020-05-20 14:14 12% ` [PATCH 3.16 61/99] KVM: x86/mmu: Apply max PA check for MMIO sptes to 32-bit KVM Ben Hutchings
                   ` (39 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable; +Cc: akpm, Denis Kirjanov, Paolo Bonzini, Arnd Bergmann

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Arnd Bergmann <arnd@arndb.de>

commit 7288bde1f9df6c1475675419bdd7725ce84dec56 upstream.

Removing one of the two accesses of the maxphyaddr variable led to
a harmless warning:

arch/x86/kvm/x86.c: In function 'kvm_set_mmio_spte_mask':
arch/x86/kvm/x86.c:6563:6: error: unused variable 'maxphyaddr' [-Werror=unused-variable]

Removing the #ifdef seems to be the nicest workaround, as it
makes the code look cleaner than adding another #ifdef.

Fixes: 28a1f3ac1d0c ("kvm: x86: Set highest physical address bits in non-present/reserved SPTEs")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 arch/x86/kvm/x86.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -5730,14 +5730,12 @@ static void kvm_set_mmio_spte_mask(void)
 	/* Set the present bit. */
 	mask |= 1ull;
 
-#ifdef CONFIG_X86_64
 	/*
 	 * If reserved bit is not supported, clear the present bit to disable
 	 * mmio page fault.
 	 */
-	if (maxphyaddr == 52)
+	if (IS_ENABLED(CONFIG_X86_64) && maxphyaddr == 52)
 		mask &= ~1ull;
-#endif
 
 	kvm_mmu_set_mmio_spte_mask(mask);
 }


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 72/99] ext4, jbd2: ensure panic when aborting with zero errno
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (70 preceding siblings ...)
  2020-05-20 14:14  9% ` [PATCH 3.16 71/99] jbd2: switch to use jbd2_journal_abort() when failed to submit the commit record Ben Hutchings
@ 2020-05-20 14:14  8% ` Ben Hutchings
  2020-05-20 14:14 12% ` [PATCH 3.16 73/99] iwlegacy: ensure loop counter addr does not wrap and cause an infinite loop Ben Hutchings
                   ` (27 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Theodore Ts'o, zhangyi (F), Jan Kara

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: "zhangyi (F)" <yi.zhang@huawei.com>

commit 51f57b01e4a3c7d7bdceffd84de35144e8c538e7 upstream.

JBD2_REC_ERR flag used to indicate the errno has been updated when jbd2
aborted, and then __ext4_abort() and ext4_handle_error() can invoke
panic if ERRORS_PANIC is specified. But if the journal has been aborted
with zero errno, jbd2_journal_abort() didn't set this flag so we can
no longer panic. Fix this by always record the proper errno in the
journal superblock.

Fixes: 4327ba52afd03 ("ext4, jbd2: ensure entering into panic after recording an error in superblock")
Signed-off-by: zhangyi (F) <yi.zhang@huawei.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Link: https://lore.kernel.org/r/20191204124614.45424-3-yi.zhang@huawei.com
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 fs/jbd2/checkpoint.c |  2 +-
 fs/jbd2/journal.c    | 15 ++++-----------
 2 files changed, 5 insertions(+), 12 deletions(-)

--- a/fs/jbd2/checkpoint.c
+++ b/fs/jbd2/checkpoint.c
@@ -173,7 +173,7 @@ void __jbd2_log_wait_for_space(journal_t
 				       "journal space in %s\n", __func__,
 				       journal->j_devname);
 				WARN_ON(1);
-				jbd2_journal_abort(journal, 0);
+				jbd2_journal_abort(journal, -EIO);
 			}
 			write_lock(&journal->j_state_lock);
 		} else {
--- a/fs/jbd2/journal.c
+++ b/fs/jbd2/journal.c
@@ -2106,12 +2106,10 @@ static void __journal_abort_soft (journa
 
 	__jbd2_journal_abort_hard(journal);
 
-	if (errno) {
-		jbd2_journal_update_sb_errno(journal);
-		write_lock(&journal->j_state_lock);
-		journal->j_flags |= JBD2_REC_ERR;
-		write_unlock(&journal->j_state_lock);
-	}
+	jbd2_journal_update_sb_errno(journal);
+	write_lock(&journal->j_state_lock);
+	journal->j_flags |= JBD2_REC_ERR;
+	write_unlock(&journal->j_state_lock);
 }
 
 /**
@@ -2153,11 +2151,6 @@ static void __journal_abort_soft (journa
  * failure to disk.  ext3_error, for example, now uses this
  * functionality.
  *
- * Errors which originate from within the journaling layer will NOT
- * supply an errno; a null errno implies that absolutely no further
- * writes are done to the journal (unless there are any already in
- * progress).
- *
  */
 
 void jbd2_journal_abort(journal_t *journal, int errno)


^ permalink raw reply	[relevance 8%]

* [PATCH 3.16 41/99] ARM: dts: at91: sama5d3: fix maximum peripheral clock rates
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (39 preceding siblings ...)
  2020-05-20 14:14  9% ` [PATCH 3.16 40/99] media: iguanair: fix endpoint sanity check Ben Hutchings
@ 2020-05-20 14:14 11% ` Ben Hutchings
  2020-05-20 14:14  9% ` [PATCH 3.16 42/99] ARM: dts: at91: sama5d3: define clock rate range for tcb1 Ben Hutchings
                   ` (58 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Alexandre Belloni, Karl Rudbæk Olsen

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Alexandre Belloni <alexandre.belloni@bootlin.com>

commit ee0aa926ddb0bd8ba59e33e3803b3b5804e3f5da upstream.

Currently the maximum rate for peripheral clock is calculated based on a
typical 133MHz MCK. The maximum frequency is defined in the datasheet as a
ratio to MCK. Some sama5d3 platforms are using a 166MHz MCK. Update the
device trees to match the maximum rate based on 166MHz.

Reported-by: Karl Rudbæk Olsen <karl@micro-technic.com>
Fixes: d2e8190b7916 ("ARM: at91/dt: define sama5d3 clocks")
Link: https://lore.kernel.org/r/20200110172007.1253659-1-alexandre.belloni@bootlin.com
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
[bwh: Backported to 3.16: uart0_clk is only defined in sama5d3_uart.dtsi]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
--- a/arch/arm/boot/dts/sama5d3.dtsi
+++ b/arch/arm/boot/dts/sama5d3.dtsi
@@ -1031,43 +1031,43 @@
 					usart0_clk: usart0_clk {
 						#clock-cells = <0>;
 						reg = <12>;
-						atmel,clk-output-range = <0 66000000>;
+						atmel,clk-output-range = <0 83000000>;
 					};
 
 					usart1_clk: usart1_clk {
 						#clock-cells = <0>;
 						reg = <13>;
-						atmel,clk-output-range = <0 66000000>;
+						atmel,clk-output-range = <0 83000000>;
 					};
 
 					usart2_clk: usart2_clk {
 						#clock-cells = <0>;
 						reg = <14>;
-						atmel,clk-output-range = <0 66000000>;
+						atmel,clk-output-range = <0 83000000>;
 					};
 
 					usart3_clk: usart3_clk {
 						#clock-cells = <0>;
 						reg = <15>;
-						atmel,clk-output-range = <0 66000000>;
+						atmel,clk-output-range = <0 83000000>;
 					};
 
 					twi0_clk: twi0_clk {
 						reg = <18>;
 						#clock-cells = <0>;
-						atmel,clk-output-range = <0 16625000>;
+						atmel,clk-output-range = <0 41500000>;
 					};
 
 					twi1_clk: twi1_clk {
 						#clock-cells = <0>;
 						reg = <19>;
-						atmel,clk-output-range = <0 16625000>;
+						atmel,clk-output-range = <0 41500000>;
 					};
 
 					twi2_clk: twi2_clk {
 						#clock-cells = <0>;
 						reg = <20>;
-						atmel,clk-output-range = <0 16625000>;
+						atmel,clk-output-range = <0 41500000>;
 					};
 
 					mci0_clk: mci0_clk {
@@ -1083,19 +1083,19 @@
 					spi0_clk: spi0_clk {
 						#clock-cells = <0>;
 						reg = <24>;
-						atmel,clk-output-range = <0 133000000>;
+						atmel,clk-output-range = <0 166000000>;
 					};
 
 					spi1_clk: spi1_clk {
 						#clock-cells = <0>;
 						reg = <25>;
-						atmel,clk-output-range = <0 133000000>;
+						atmel,clk-output-range = <0 166000000>;
 					};
 
 					tcb0_clk: tcb0_clk {
 						#clock-cells = <0>;
 						reg = <26>;
-						atmel,clk-output-range = <0 133000000>;
+						atmel,clk-output-range = <0 166000000>;
 					};
 
 					pwm_clk: pwm_clk {
@@ -1106,7 +1106,7 @@
 					adc_clk: adc_clk {
 						#clock-cells = <0>;
 						reg = <29>;
-						atmel,clk-output-range = <0 66000000>;
+						atmel,clk-output-range = <0 83000000>;
 					};
 
 					dma0_clk: dma0_clk {
@@ -1137,13 +1137,13 @@
 					ssc0_clk: ssc0_clk {
 						#clock-cells = <0>;
 						reg = <38>;
-						atmel,clk-output-range = <0 66000000>;
+						atmel,clk-output-range = <0 83000000>;
 					};
 
 					ssc1_clk: ssc1_clk {
 						#clock-cells = <0>;
 						reg = <39>;
-						atmel,clk-output-range = <0 66000000>;
+						atmel,clk-output-range = <0 83000000>;
 					};
 
 					sha_clk: sha_clk {
--- a/arch/arm/boot/dts/sama5d3_can.dtsi
+++ b/arch/arm/boot/dts/sama5d3_can.dtsi
@@ -37,13 +37,13 @@
 					can0_clk: can0_clk {
 						#clock-cells = <0>;
 						reg = <40>;
-						atmel,clk-output-range = <0 66000000>;
+						atmel,clk-output-range = <0 83000000>;
 					};
 
 					can1_clk: can1_clk {
 						#clock-cells = <0>;
 						reg = <41>;
-						atmel,clk-output-range = <0 66000000>;
+						atmel,clk-output-range = <0 83000000>;
 					};
 				};
 			};
--- a/arch/arm/boot/dts/sama5d3_uart.dtsi
+++ b/arch/arm/boot/dts/sama5d3_uart.dtsi
@@ -42,13 +42,13 @@
 					uart0_clk: uart0_clk {
 						#clock-cells = <0>;
 						reg = <16>;
-						atmel,clk-output-range = <0 66000000>;
+						atmel,clk-output-range = <0 83000000>;
 					};
 
 					uart1_clk: uart1_clk {
 						#clock-cells = <0>;
 						reg = <17>;
-						atmel,clk-output-range = <0 66000000>;
+						atmel,clk-output-range = <0 83000000>;
 					};
 				};
 			};


^ permalink raw reply	[relevance 11%]

* [PATCH 3.16 78/99] KVM: x86: Protect ioapic_read_indirect() from Spectre-v1/L1TF attacks
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (76 preceding siblings ...)
  2020-05-20 14:14 12% ` [PATCH 3.16 77/99] KVM: x86: Refactor picdev_write() to prevent " Ben Hutchings
@ 2020-05-20 14:14 12% ` Ben Hutchings
  2020-05-20 14:14 12% ` [PATCH 3.16 79/99] KVM: x86: Protect ioapic_write_indirect() " Ben Hutchings
                   ` (21 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Jim Mattson, Marios Pomonis, Nick Finco,
	Andrew Honig, Paolo Bonzini

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Marios Pomonis <pomonis@google.com>

commit 8c86405f606ca8508b8d9280680166ca26723695 upstream.

This fixes a Spectre-v1/L1TF vulnerability in ioapic_read_indirect().
This function contains index computations based on the
(attacker-controlled) IOREGSEL register.

Fixes: a2c118bfab8b ("KVM: Fix bounds checking in ioapic indirect register reads (CVE-2013-1798)")

Signed-off-by: Nick Finco <nifi@google.com>
Signed-off-by: Marios Pomonis <pomonis@google.com>
Reviewed-by: Andrew Honig <ahonig@google.com>
Reviewed-by: Jim Mattson <jmattson@google.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
[bwh: Backported to 3.16: adjust filename]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 virt/kvm/ioapic.c | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

--- a/virt/kvm/ioapic.c
+++ b/virt/kvm/ioapic.c
@@ -36,6 +36,7 @@
 #include <linux/io.h>
 #include <linux/slab.h>
 #include <linux/export.h>
+#include <linux/nospec.h>
 #include <asm/processor.h>
 #include <asm/page.h>
 #include <asm/current.h>
@@ -73,13 +74,14 @@ static unsigned long ioapic_read_indirec
 	default:
 		{
 			u32 redir_index = (ioapic->ioregsel - 0x10) >> 1;
-			u64 redir_content;
+			u64 redir_content = ~0ULL;
 
-			if (redir_index < IOAPIC_NUM_PINS)
-				redir_content =
-					ioapic->redirtbl[redir_index].bits;
-			else
-				redir_content = ~0ULL;
+			if (redir_index < IOAPIC_NUM_PINS) {
+				u32 index = array_index_nospec(
+					redir_index, IOAPIC_NUM_PINS);
+
+				redir_content = ioapic->redirtbl[index].bits;
+			}
 
 			result = (ioapic->ioregsel & 0x1) ?
 			    (redir_content >> 32) & 0xffffffff :


^ permalink raw reply	[relevance 12%]

* [PATCH 3.16 42/99] ARM: dts: at91: sama5d3: define clock rate range for tcb1
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (40 preceding siblings ...)
  2020-05-20 14:14 11% ` [PATCH 3.16 41/99] ARM: dts: at91: sama5d3: fix maximum peripheral clock rates Ben Hutchings
@ 2020-05-20 14:14  9% ` Ben Hutchings
  2020-05-20 14:14  7% ` [PATCH 3.16 43/99] efi: Use early_mem*() instead of early_io*() Ben Hutchings
                   ` (57 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Karl Rudbæk Olsen, Alexandre Belloni

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Alexandre Belloni <alexandre.belloni@bootlin.com>

commit a7e0f3fc01df4b1b7077df777c37feae8c9e8b6d upstream.

The clock rate range for the TCB1 clock is missing. define it in the device
tree.

Reported-by: Karl Rudbæk Olsen <karl@micro-technic.com>
Fixes: d2e8190b7916 ("ARM: at91/dt: define sama5d3 clocks")
Link: https://lore.kernel.org/r/20200110172007.1253659-2-alexandre.belloni@bootlin.com
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 arch/arm/boot/dts/sama5d3_tcb1.dtsi | 1 +
 1 file changed, 1 insertion(+)

--- a/arch/arm/boot/dts/sama5d3_tcb1.dtsi
+++ b/arch/arm/boot/dts/sama5d3_tcb1.dtsi
@@ -23,6 +23,7 @@
 					tcb1_clk: tcb1_clk {
 						#clock-cells = <0>;
 						reg = <27>;
+						atmel,clk-output-range = <0 166000000>;
 					};
 				};
 			};


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 73/99] iwlegacy: ensure loop counter addr does not wrap and cause an infinite loop
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (71 preceding siblings ...)
  2020-05-20 14:14  8% ` [PATCH 3.16 72/99] ext4, jbd2: ensure panic when aborting with zero errno Ben Hutchings
@ 2020-05-20 14:14 12% ` Ben Hutchings
  2020-05-20 14:14  9% ` [PATCH 3.16 74/99] CIFS: Fix task struct use-after-free on reconnect Ben Hutchings
                   ` (26 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Colin Ian King, Kalle Valo, Stanislaw Gruszka

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Colin Ian King <colin.king@canonical.com>

commit c2f9a4e4a5abfc84c01b738496b3fd2d471e0b18 upstream.

The loop counter addr is a u16 where as the upper limit of the loop
is an int. In the unlikely event that the il->cfg->eeprom_size is
greater than 64K then we end up with an infinite loop since addr will
wrap around an never reach upper loop limit. Fix this by making addr
an int.

Addresses-Coverity: ("Infinite loop")
Fixes: be663ab67077 ("iwlwifi: split the drivers for agn and legacy devices 3945/4965")
Signed-off-by: Colin Ian King <colin.king@canonical.com>
Acked-by: Stanislaw Gruszka <stf_xl@wp.pl>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
[bwh: Backported to 3.16: adjust filename]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/net/wireless/iwlegacy/common.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/drivers/net/wireless/iwlegacy/common.c
+++ b/drivers/net/wireless/iwlegacy/common.c
@@ -717,7 +717,7 @@ il_eeprom_init(struct il_priv *il)
 	u32 gp = _il_rd(il, CSR_EEPROM_GP);
 	int sz;
 	int ret;
-	u16 addr;
+	int addr;
 
 	/* allocate eeprom */
 	sz = il->cfg->eeprom_size;


^ permalink raw reply	[relevance 12%]

* [PATCH 3.16 86/99] Btrfs: fix race between adding and putting tree mod seq elements and nodes
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (84 preceding siblings ...)
  2020-05-20 14:14 11% ` [PATCH 3.16 85/99] of: Add OF_DMA_DEFAULT_COHERENT & select it on powerpc Ben Hutchings
@ 2020-05-20 14:14  8% ` Ben Hutchings
  2020-05-20 14:14  8% ` [PATCH 3.16 87/99] mm/mempolicy.c: fix out of bounds write in mpol_parse_str() Ben Hutchings
                   ` (13 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, David Sterba, Filipe Manana,
	Nikolay Borisov, Josef Bacik

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Filipe Manana <fdmanana@suse.com>

commit 7227ff4de55d931bbdc156c8ef0ce4f100c78a5b upstream.

There is a race between adding and removing elements to the tree mod log
list and rbtree that can lead to use-after-free problems.

Consider the following example that explains how/why the problems happens:

1) Task A has mod log element with sequence number 200. It currently is
   the only element in the mod log list;

2) Task A calls btrfs_put_tree_mod_seq() because it no longer needs to
   access the tree mod log. When it enters the function, it initializes
   'min_seq' to (u64)-1. Then it acquires the lock 'tree_mod_seq_lock'
   before checking if there are other elements in the mod seq list.
   Since the list it empty, 'min_seq' remains set to (u64)-1. Then it
   unlocks the lock 'tree_mod_seq_lock';

3) Before task A acquires the lock 'tree_mod_log_lock', task B adds
   itself to the mod seq list through btrfs_get_tree_mod_seq() and gets a
   sequence number of 201;

4) Some other task, name it task C, modifies a btree and because there
   elements in the mod seq list, it adds a tree mod elem to the tree
   mod log rbtree. That node added to the mod log rbtree is assigned
   a sequence number of 202;

5) Task B, which is doing fiemap and resolving indirect back references,
   calls btrfs get_old_root(), with 'time_seq' == 201, which in turn
   calls tree_mod_log_search() - the search returns the mod log node
   from the rbtree with sequence number 202, created by task C;

6) Task A now acquires the lock 'tree_mod_log_lock', starts iterating
   the mod log rbtree and finds the node with sequence number 202. Since
   202 is less than the previously computed 'min_seq', (u64)-1, it
   removes the node and frees it;

7) Task B still has a pointer to the node with sequence number 202, and
   it dereferences the pointer itself and through the call to
   __tree_mod_log_rewind(), resulting in a use-after-free problem.

This issue can be triggered sporadically with the test case generic/561
from fstests, and it happens more frequently with a higher number of
duperemove processes. When it happens to me, it either freezes the VM or
it produces a trace like the following before crashing:

  [ 1245.321140] general protection fault: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC PTI
  [ 1245.321200] CPU: 1 PID: 26997 Comm: pool Not tainted 5.5.0-rc6-btrfs-next-52 #1
  [ 1245.321235] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.0-0-ga698c8995f-prebuilt.qemu.org 04/01/2014
  [ 1245.321287] RIP: 0010:rb_next+0x16/0x50
  [ 1245.321307] Code: ....
  [ 1245.321372] RSP: 0018:ffffa151c4d039b0 EFLAGS: 00010202
  [ 1245.321388] RAX: 6b6b6b6b6b6b6b6b RBX: ffff8ae221363c80 RCX: 6b6b6b6b6b6b6b6b
  [ 1245.321409] RDX: 0000000000000001 RSI: 0000000000000000 RDI: ffff8ae221363c80
  [ 1245.321439] RBP: ffff8ae20fcc4688 R08: 0000000000000002 R09: 0000000000000000
  [ 1245.321475] R10: ffff8ae20b120910 R11: 00000000243f8bb1 R12: 0000000000000038
  [ 1245.321506] R13: ffff8ae221363c80 R14: 000000000000075f R15: ffff8ae223f762b8
  [ 1245.321539] FS:  00007fdee1ec7700(0000) GS:ffff8ae236c80000(0000) knlGS:0000000000000000
  [ 1245.321591] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
  [ 1245.321614] CR2: 00007fded4030c48 CR3: 000000021da16003 CR4: 00000000003606e0
  [ 1245.321642] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
  [ 1245.321668] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
  [ 1245.321706] Call Trace:
  [ 1245.321798]  __tree_mod_log_rewind+0xbf/0x280 [btrfs]
  [ 1245.321841]  btrfs_search_old_slot+0x105/0xd00 [btrfs]
  [ 1245.321877]  resolve_indirect_refs+0x1eb/0xc60 [btrfs]
  [ 1245.321912]  find_parent_nodes+0x3dc/0x11b0 [btrfs]
  [ 1245.321947]  btrfs_check_shared+0x115/0x1c0 [btrfs]
  [ 1245.321980]  ? extent_fiemap+0x59d/0x6d0 [btrfs]
  [ 1245.322029]  extent_fiemap+0x59d/0x6d0 [btrfs]
  [ 1245.322066]  do_vfs_ioctl+0x45a/0x750
  [ 1245.322081]  ksys_ioctl+0x70/0x80
  [ 1245.322092]  ? trace_hardirqs_off_thunk+0x1a/0x1c
  [ 1245.322113]  __x64_sys_ioctl+0x16/0x20
  [ 1245.322126]  do_syscall_64+0x5c/0x280
  [ 1245.322139]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
  [ 1245.322155] RIP: 0033:0x7fdee3942dd7
  [ 1245.322177] Code: ....
  [ 1245.322258] RSP: 002b:00007fdee1ec6c88 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
  [ 1245.322294] RAX: ffffffffffffffda RBX: 00007fded40210d8 RCX: 00007fdee3942dd7
  [ 1245.322314] RDX: 00007fded40210d8 RSI: 00000000c020660b RDI: 0000000000000004
  [ 1245.322337] RBP: 0000562aa89e7510 R08: 0000000000000000 R09: 00007fdee1ec6d44
  [ 1245.322369] R10: 0000000000000073 R11: 0000000000000246 R12: 00007fdee1ec6d48
  [ 1245.322390] R13: 00007fdee1ec6d40 R14: 00007fded40210d0 R15: 00007fdee1ec6d50
  [ 1245.322423] Modules linked in: ....
  [ 1245.323443] ---[ end trace 01de1e9ec5dff3cd ]---

Fix this by ensuring that btrfs_put_tree_mod_seq() computes the minimum
sequence number and iterates the rbtree while holding the lock
'tree_mod_log_lock' in write mode. Also get rid of the 'tree_mod_seq_lock'
lock, since it is now redundant.

Fixes: bd989ba359f2ac ("Btrfs: add tree modification log functions")
Fixes: 097b8a7c9e48e2 ("Btrfs: join tree mod log code with the code holding back delayed refs")
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Reviewed-by: Nikolay Borisov <nborisov@suse.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
[bwh: Backported to 3.16:
 - Use tree_mod_log_write_{,un}lock() in ctree.c for consistency
 - Adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 fs/btrfs/ctree.c             | 8 ++------
 fs/btrfs/ctree.h             | 6 ++----
 fs/btrfs/delayed-ref.c       | 8 ++++----
 fs/btrfs/disk-io.c           | 1 -
 fs/btrfs/tests/btrfs-tests.c | 1 -
 5 files changed, 8 insertions(+), 16 deletions(-)

--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -365,12 +365,10 @@ u64 btrfs_get_tree_mod_seq(struct btrfs_
 			   struct seq_list *elem)
 {
 	tree_mod_log_write_lock(fs_info);
-	spin_lock(&fs_info->tree_mod_seq_lock);
 	if (!elem->seq) {
 		elem->seq = btrfs_inc_tree_mod_seq(fs_info);
 		list_add_tail(&elem->list, &fs_info->tree_mod_seq_list);
 	}
-	spin_unlock(&fs_info->tree_mod_seq_lock);
 	tree_mod_log_write_unlock(fs_info);
 
 	return elem->seq;
@@ -390,7 +388,7 @@ void btrfs_put_tree_mod_seq(struct btrfs
 	if (!seq_putting)
 		return;
 
-	spin_lock(&fs_info->tree_mod_seq_lock);
+	tree_mod_log_write_lock(fs_info);
 	list_del(&elem->list);
 	elem->seq = 0;
 
@@ -401,19 +399,17 @@ void btrfs_put_tree_mod_seq(struct btrfs
 				 * blocker with lower sequence number exists, we
 				 * cannot remove anything from the log
 				 */
-				spin_unlock(&fs_info->tree_mod_seq_lock);
+				tree_mod_log_write_unlock(fs_info);
 				return;
 			}
 			min_seq = cur_elem->seq;
 		}
 	}
-	spin_unlock(&fs_info->tree_mod_seq_lock);
 
 	/*
 	 * anything that's lower than the lowest existing (read: blocked)
 	 * sequence number can be removed from the tree.
 	 */
-	tree_mod_log_write_lock(fs_info);
 	tm_root = &fs_info->tree_mod_log;
 	for (node = rb_first(tm_root); node; node = next) {
 		next = rb_next(node);
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -1502,14 +1502,12 @@ struct btrfs_fs_info {
 	spinlock_t delayed_iput_lock;
 	struct list_head delayed_iputs;
 
-	/* this protects tree_mod_seq_list */
-	spinlock_t tree_mod_seq_lock;
 	atomic64_t tree_mod_seq;
-	struct list_head tree_mod_seq_list;
 
-	/* this protects tree_mod_log */
+	/* this protects tree_mod_log and tree_mod_seq_list */
 	rwlock_t tree_mod_log_lock;
 	struct rb_root tree_mod_log;
+	struct list_head tree_mod_seq_list;
 
 	atomic_t nr_async_submits;
 	atomic_t async_submit_draining;
--- a/fs/btrfs/delayed-ref.c
+++ b/fs/btrfs/delayed-ref.c
@@ -344,7 +344,7 @@ void btrfs_merge_delayed_refs(struct btr
 	if (head->is_data)
 		return;
 
-	spin_lock(&fs_info->tree_mod_seq_lock);
+	read_lock(&fs_info->tree_mod_log_lock);
 	if (!list_empty(&fs_info->tree_mod_seq_list)) {
 		struct seq_list *elem;
 
@@ -352,7 +352,7 @@ void btrfs_merge_delayed_refs(struct btr
 					struct seq_list, list);
 		seq = elem->seq;
 	}
-	spin_unlock(&fs_info->tree_mod_seq_lock);
+	read_unlock(&fs_info->tree_mod_log_lock);
 
 	node = rb_first(&head->ref_root);
 	while (node) {
@@ -377,7 +377,7 @@ int btrfs_check_delayed_seq(struct btrfs
 	struct seq_list *elem;
 	int ret = 0;
 
-	spin_lock(&fs_info->tree_mod_seq_lock);
+	read_lock(&fs_info->tree_mod_log_lock);
 	if (!list_empty(&fs_info->tree_mod_seq_list)) {
 		elem = list_first_entry(&fs_info->tree_mod_seq_list,
 					struct seq_list, list);
@@ -390,7 +390,7 @@ int btrfs_check_delayed_seq(struct btrfs
 		}
 	}
 
-	spin_unlock(&fs_info->tree_mod_seq_lock);
+	read_unlock(&fs_info->tree_mod_log_lock);
 	return ret;
 }
 
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -2167,7 +2167,6 @@ int open_ctree(struct super_block *sb,
 	spin_lock_init(&fs_info->delayed_iput_lock);
 	spin_lock_init(&fs_info->defrag_inodes_lock);
 	spin_lock_init(&fs_info->free_chunk_lock);
-	spin_lock_init(&fs_info->tree_mod_seq_lock);
 	spin_lock_init(&fs_info->super_lock);
 	spin_lock_init(&fs_info->qgroup_op_lock);
 	spin_lock_init(&fs_info->buffer_lock);
--- a/fs/btrfs/tests/btrfs-tests.c
+++ b/fs/btrfs/tests/btrfs-tests.c
@@ -109,7 +109,6 @@ struct btrfs_fs_info *btrfs_alloc_dummy_
 	spin_lock_init(&fs_info->qgroup_op_lock);
 	spin_lock_init(&fs_info->super_lock);
 	spin_lock_init(&fs_info->fs_roots_radix_lock);
-	spin_lock_init(&fs_info->tree_mod_seq_lock);
 	mutex_init(&fs_info->qgroup_ioctl_lock);
 	mutex_init(&fs_info->qgroup_rescan_lock);
 	rwlock_init(&fs_info->tree_mod_log_lock);


^ permalink raw reply	[relevance 8%]

* [PATCH 3.16 53/99] ubifs: Fix deadlock in concurrent bulk-read and writepage
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (51 preceding siblings ...)
  2020-05-20 14:14  9% ` [PATCH 3.16 52/99] nfs: NFS_SWAP should depend on SWAP Ben Hutchings
@ 2020-05-20 14:14 12% ` Ben Hutchings
  2020-05-20 14:14  8% ` [PATCH 3.16 54/99] x86/cpu: Update cached HLE state on write to TSX_CTRL_CPUID_CLEAR Ben Hutchings
                   ` (46 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Zhihao Cheng, zhangyi (F), Richard Weinberger

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Zhihao Cheng <chengzhihao1@huawei.com>

commit f5de5b83303e61b1f3fb09bd77ce3ac2d7a475f2 upstream.

In ubifs, concurrent execution of writepage and bulk read on the same file
may cause ABBA deadlock, for example (Reproduce method see Link):

Process A(Bulk-read starts from page4)         Process B(write page4 back)
  vfs_read                                       wb_workfn or fsync
  ...                                            ...
  generic_file_buffered_read                     write_cache_pages
    ubifs_readpage                                 LOCK(page4)

      ubifs_bulk_read                              ubifs_writepage
        LOCK(ui->ui_mutex)                           ubifs_write_inode

	  ubifs_do_bulk_read                           LOCK(ui->ui_mutex)
	    find_or_create_page(alloc page4)                  ↑
	      LOCK(page4)                   <--     ABBA deadlock occurs!

In order to ensure the serialization execution of bulk read, we can't
remove the big lock 'ui->ui_mutex' in ubifs_bulk_read(). Instead, we
allow ubifs_do_bulk_read() to lock page failed by replacing
find_or_create_page(FGP_LOCK) with
pagecache_get_page(FGP_LOCK | FGP_NOWAIT).

Signed-off-by: Zhihao Cheng <chengzhihao1@huawei.com>
Suggested-by: zhangyi (F) <yi.zhang@huawei.com>
Fixes: 4793e7c5e1c ("UBIFS: add bulk-read facility")
Link: https://bugzilla.kernel.org/show_bug.cgi?id=206153
Signed-off-by: Richard Weinberger <richard@nod.at>
[bwh: Backported to 3.16: Keep using constant GFP flags parameter.]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 fs/ubifs/file.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

--- a/fs/ubifs/file.c
+++ b/fs/ubifs/file.c
@@ -782,8 +782,9 @@ static int ubifs_do_bulk_read(struct ubi
 
 		if (page_offset > end_index)
 			break;
-		page = find_or_create_page(mapping, page_offset,
-					   GFP_NOFS | __GFP_COLD);
+		page = pagecache_get_page(mapping, page_offset,
+				 FGP_LOCK|FGP_ACCESSED|FGP_CREAT|FGP_NOWAIT,
+				 GFP_NOFS | __GFP_COLD);
 		if (!page)
 			break;
 		if (!PageUptodate(page))


^ permalink raw reply	[relevance 12%]

* [PATCH 3.16 90/99] ALSA: dummy: Fix PCM format loop in proc output
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (88 preceding siblings ...)
  2020-05-20 14:14  9% ` [PATCH 3.16 89/99] tcp: clear tp->total_retrans in tcp_disconnect() Ben Hutchings
@ 2020-05-20 14:14  9% ` Ben Hutchings
  2020-05-20 14:14  8% ` [PATCH 3.16 91/99] clocksource: Prevent double add_timer_on() for watchdog_timer Ben Hutchings
                   ` (9 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable; +Cc: akpm, Denis Kirjanov, Takashi Iwai

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Takashi Iwai <tiwai@suse.de>

commit 2acf25f13ebe8beb40e97a1bbe76f36277c64f1e upstream.

The loop termination for iterating over all formats should contain
SNDRV_PCM_FORMAT_LAST, not less than it.

Fixes: 9b151fec139d ("ALSA: dummy - Add debug proc file")
Link: https://lore.kernel.org/r/20200201080530.22390-3-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 sound/drivers/dummy.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/sound/drivers/dummy.c
+++ b/sound/drivers/dummy.c
@@ -927,7 +927,7 @@ static void print_formats(struct snd_dum
 {
 	int i;
 
-	for (i = 0; i < SNDRV_PCM_FORMAT_LAST; i++) {
+	for (i = 0; i <= SNDRV_PCM_FORMAT_LAST; i++) {
 		if (dummy->pcm_hw.formats & (1ULL << i))
 			snd_iprintf(buffer, " %s", snd_pcm_format_name(i));
 	}


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 79/99] KVM: x86: Protect ioapic_write_indirect() from Spectre-v1/L1TF attacks
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (77 preceding siblings ...)
  2020-05-20 14:14 12% ` [PATCH 3.16 78/99] KVM: x86: Protect ioapic_read_indirect() from " Ben Hutchings
@ 2020-05-20 14:14 12% ` Ben Hutchings
  2020-05-20 14:14 12% ` [PATCH 3.16 80/99] KVM: x86: Protect kvm_lapic_reg_write() " Ben Hutchings
                   ` (20 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Andrew Honig, Paolo Bonzini, Jim Mattson,
	Marios Pomonis, Nick Finco

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Marios Pomonis <pomonis@google.com>

commit 670564559ca35b439c8d8861fc399451ddf95137 upstream.

This fixes a Spectre-v1/L1TF vulnerability in ioapic_write_indirect().
This function contains index computations based on the
(attacker-controlled) IOREGSEL register.

This patch depends on patch
"KVM: x86: Protect ioapic_read_indirect() from Spectre-v1/L1TF attacks".

Fixes: 70f93dae32ac ("KVM: Use temporary variable to shorten lines.")

Signed-off-by: Nick Finco <nifi@google.com>
Signed-off-by: Marios Pomonis <pomonis@google.com>
Reviewed-by: Andrew Honig <ahonig@google.com>
Reviewed-by: Jim Mattson <jmattson@google.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
[bwh: Backported to 3.16: adjust filename]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 virt/kvm/ioapic.c | 1 +
 1 file changed, 1 insertion(+)

--- a/virt/kvm/ioapic.c
+++ b/virt/kvm/ioapic.c
@@ -312,6 +312,7 @@ static void ioapic_write_indirect(struct
 		ioapic_debug("change redir index %x val %x\n", index, val);
 		if (index >= IOAPIC_NUM_PINS)
 			return;
+		index = array_index_nospec(index, IOAPIC_NUM_PINS);
 		e = &ioapic->redirtbl[index];
 		mask_before = e->fields.mask;
 		if (ioapic->ioregsel & 1) {


^ permalink raw reply	[relevance 12%]

* [PATCH 3.16 81/99] kvm: x86: use macros to compute bank MSRs
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (79 preceding siblings ...)
  2020-05-20 14:14 12% ` [PATCH 3.16 80/99] KVM: x86: Protect kvm_lapic_reg_write() " Ben Hutchings
@ 2020-05-20 14:14 12% ` Ben Hutchings
  2020-05-20 14:14 12% ` [PATCH 3.16 82/99] KVM: x86: Protect MSR-based index computations from Spectre-v1/L1TF attacks in x86.c Ben Hutchings
                   ` (18 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable; +Cc: akpm, Denis Kirjanov, Paolo Bonzini, Chen Yucong

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Chen Yucong <slaoub@gmail.com>

commit 81760dccf8d1fe5b128b58736fe3f56a566133cb upstream.

Avoid open coded calculations for bank MSRs by using well-defined
macros that hide the index of higher bank MSRs.

No semantic changes.

Signed-off-by: Chen Yucong <slaoub@gmail.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 arch/x86/kvm/x86.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1915,7 +1915,7 @@ static int set_msr_mce(struct kvm_vcpu *
 		break;
 	default:
 		if (msr >= MSR_IA32_MC0_CTL &&
-		    msr < MSR_IA32_MC0_CTL + 4 * bank_num) {
+		    msr < MSR_IA32_MCx_CTL(bank_num)) {
 			u32 offset = msr - MSR_IA32_MC0_CTL;
 			/* only 0 or all 1s can be written to IA32_MCi_CTL
 			 * some Linux kernels though clear bit 10 in bank 4 to
@@ -2276,7 +2276,7 @@ int kvm_set_msr_common(struct kvm_vcpu *
 
 	case MSR_IA32_MCG_CTL:
 	case MSR_IA32_MCG_STATUS:
-	case MSR_IA32_MC0_CTL ... MSR_IA32_MC0_CTL + 4 * KVM_MAX_MCE_BANKS - 1:
+	case MSR_IA32_MC0_CTL ... MSR_IA32_MCx_CTL(KVM_MAX_MCE_BANKS) - 1:
 		return set_msr_mce(vcpu, msr, data);
 
 	/* Performance counters are not protected by a CPUID bit,
@@ -2442,7 +2442,7 @@ static int get_msr_mce(struct kvm_vcpu *
 		break;
 	default:
 		if (msr >= MSR_IA32_MC0_CTL &&
-		    msr < MSR_IA32_MC0_CTL + 4 * bank_num) {
+		    msr < MSR_IA32_MCx_CTL(bank_num)) {
 			u32 offset = msr - MSR_IA32_MC0_CTL;
 			data = vcpu->arch.mce_banks[offset];
 			break;
@@ -2628,7 +2628,7 @@ int kvm_get_msr_common(struct kvm_vcpu *
 	case MSR_IA32_MCG_CAP:
 	case MSR_IA32_MCG_CTL:
 	case MSR_IA32_MCG_STATUS:
-	case MSR_IA32_MC0_CTL ... MSR_IA32_MC0_CTL + 4 * KVM_MAX_MCE_BANKS - 1:
+	case MSR_IA32_MC0_CTL ... MSR_IA32_MCx_CTL(KVM_MAX_MCE_BANKS) - 1:
 		return get_msr_mce(vcpu, msr_info->index, &msr_info->data);
 	case MSR_K7_CLK_CTL:
 		/*


^ permalink raw reply	[relevance 12%]

* [PATCH 3.16 56/99] KVM: arm64: Only sign-extend MMIO up to register width
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (54 preceding siblings ...)
  2020-05-20 14:14  9% ` [PATCH 3.16 55/99] jbd2: clear JBD2_ABORT flag before journal_reset to update log tail info when load journal Ben Hutchings
@ 2020-05-20 14:14 10% ` Ben Hutchings
  2020-05-20 14:14  8% ` [PATCH 3.16 57/99] sparc32: fix struct ipc64_perm type definition Ben Hutchings
                   ` (43 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable; +Cc: akpm, Denis Kirjanov, Marc Zyngier, Christoffer Dall

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Christoffer Dall <christoffer.dall@arm.com>

commit b6ae256afd32f96bec0117175b329d0dd617655e upstream.

On AArch64 you can do a sign-extended load to either a 32-bit or 64-bit
register, and we should only sign extend the register up to the width of
the register as specified in the operation (by using the 32-bit Wn or
64-bit Xn register specifier).

As it turns out, the architecture provides this decoding information in
the SF ("Sixty-Four" -- how cute...) bit.

Let's take advantage of this with the usual 32-bit/64-bit header file
dance and do the right thing on AArch64 hosts.

Signed-off-by: Christoffer Dall <christoffer.dall@arm.com>
Signed-off-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20191212195055.5541-1-christoffer.dall@arm.com
[bwh: Backported to 3.16:
 - Use ESR_EL2_SF
 - Adjust filename, context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 arch/arm/include/asm/kvm_emulate.h   | 5 +++++
 arch/arm/include/asm/kvm_mmio.h      | 2 ++
 arch/arm/kvm/mmio.c                  | 6 ++++++
 arch/arm64/include/asm/kvm_emulate.h | 5 +++++
 arch/arm64/include/asm/kvm_mmio.h    | 6 ++----
 5 files changed, 20 insertions(+), 4 deletions(-)

--- a/arch/arm/include/asm/kvm_emulate.h
+++ b/arch/arm/include/asm/kvm_emulate.h
@@ -105,6 +105,11 @@ static inline bool kvm_vcpu_dabt_issext(
 	return kvm_vcpu_get_hsr(vcpu) & HSR_SSE;
 }
 
+static inline bool kvm_vcpu_dabt_issf(const struct kvm_vcpu *vcpu)
+{
+	return false;
+}
+
 static inline int kvm_vcpu_dabt_get_rd(struct kvm_vcpu *vcpu)
 {
 	return (kvm_vcpu_get_hsr(vcpu) & HSR_SRT_MASK) >> HSR_SRT_SHIFT;
--- a/arch/arm/include/asm/kvm_mmio.h
+++ b/arch/arm/include/asm/kvm_mmio.h
@@ -26,6 +26,8 @@
 struct kvm_decode {
 	unsigned long rt;
 	bool sign_extend;
+	/* Not used on 32-bit arm */
+	bool sixty_four;
 };
 
 /*
--- a/arch/arm64/include/asm/kvm_emulate.h
+++ b/arch/arm64/include/asm/kvm_emulate.h
@@ -140,6 +140,11 @@ static inline bool kvm_vcpu_dabt_issext(
 	return !!(kvm_vcpu_get_hsr(vcpu) & ESR_EL2_SSE);
 }
 
+static inline bool kvm_vcpu_dabt_issf(const struct kvm_vcpu *vcpu)
+{
+	return !!(kvm_vcpu_get_hsr(vcpu) & ESR_EL2_SF);
+}
+
 static inline int kvm_vcpu_dabt_get_rd(const struct kvm_vcpu *vcpu)
 {
 	return (kvm_vcpu_get_hsr(vcpu) & ESR_EL2_SRT_MASK) >> ESR_EL2_SRT_SHIFT;
--- a/arch/arm64/include/asm/kvm_mmio.h
+++ b/arch/arm64/include/asm/kvm_mmio.h
@@ -22,13 +22,11 @@
 #include <asm/kvm_asm.h>
 #include <asm/kvm_arm.h>
 
-/*
- * This is annoying. The mmio code requires this, even if we don't
- * need any decoding. To be fixed.
- */
 struct kvm_decode {
 	unsigned long rt;
 	bool sign_extend;
+	/* Witdth of the register accessed by the faulting instruction is 64-bits */
+	bool sixty_four;
 };
 
 /*
--- a/arch/arm/kvm/mmio.c
+++ b/arch/arm/kvm/mmio.c
@@ -112,6 +112,9 @@ int kvm_handle_mmio_return(struct kvm_vc
 			data = (data ^ mask) - mask;
 		}
 
+		if (!vcpu->arch.mmio_decode.sixty_four)
+			data = data & 0xffffffff;
+
 		trace_kvm_mmio(KVM_TRACE_MMIO_READ, len, run->mmio.phys_addr,
 			       &data);
 		data = vcpu_data_host_to_guest(vcpu, data, len);
@@ -127,6 +130,7 @@ static int decode_hsr(struct kvm_vcpu *v
 	unsigned long rt;
 	int len;
 	bool is_write, sign_extend;
+	bool sixty_four;
 
 	if (kvm_vcpu_dabt_isextabt(vcpu)) {
 		/* cache operation on I/O addr, tell guest unsupported */
@@ -146,6 +150,7 @@ static int decode_hsr(struct kvm_vcpu *v
 
 	is_write = kvm_vcpu_dabt_iswrite(vcpu);
 	sign_extend = kvm_vcpu_dabt_issext(vcpu);
+	sixty_four = kvm_vcpu_dabt_issf(vcpu);
 	rt = kvm_vcpu_dabt_get_rd(vcpu);
 
 	mmio->is_write = is_write;
@@ -153,6 +158,7 @@ static int decode_hsr(struct kvm_vcpu *v
 	mmio->len = len;
 	vcpu->arch.mmio_decode.sign_extend = sign_extend;
 	vcpu->arch.mmio_decode.rt = rt;
+	vcpu->arch.mmio_decode.sixty_four = sixty_four;
 
 	/*
 	 * The MMIO instruction is emulated and should not be re-executed


^ permalink raw reply	[relevance 10%]

* [PATCH 3.16 54/99] x86/cpu: Update cached HLE state on write to TSX_CTRL_CPUID_CLEAR
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (52 preceding siblings ...)
  2020-05-20 14:14 12% ` [PATCH 3.16 53/99] ubifs: Fix deadlock in concurrent bulk-read and writepage Ben Hutchings
@ 2020-05-20 14:14  8% ` Ben Hutchings
  2020-05-20 14:14  9% ` [PATCH 3.16 55/99] jbd2: clear JBD2_ABORT flag before journal_reset to update log tail info when load journal Ben Hutchings
                   ` (45 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Josh Poimboeuf, Dave Hansen,
	Neelima Krishnan, Thomas Gleixner, Pawan Gupta

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>

commit 5efc6fa9044c3356d6046c6e1da6d02572dbed6b upstream.

/proc/cpuinfo currently reports Hardware Lock Elision (HLE) feature to
be present on boot cpu even if it was disabled during the bootup. This
is because cpuinfo_x86->x86_capability HLE bit is not updated after TSX
state is changed via the new MSR IA32_TSX_CTRL.

Update the cached HLE bit also since it is expected to change after an
update to CPUID_CLEAR bit in MSR IA32_TSX_CTRL.

Fixes: 95c5824f75f3 ("x86/cpu: Add a "tsx=" cmdline option with TSX disabled by default")
Signed-off-by: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Neelima Krishnan <neelima.krishnan@intel.com>
Reviewed-by: Dave Hansen <dave.hansen@linux.intel.com>
Reviewed-by: Josh Poimboeuf <jpoimboe@redhat.com>
Link: https://lore.kernel.org/r/2529b99546294c893dfa1c89e2b3e46da3369a59.1578685425.git.pawan.kumar.gupta@linux.intel.com
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 arch/x86/kernel/cpu/tsx.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

--- a/arch/x86/kernel/cpu/tsx.c
+++ b/arch/x86/kernel/cpu/tsx.c
@@ -115,11 +115,12 @@ void __init tsx_init(void)
 		tsx_disable();
 
 		/*
-		 * tsx_disable() will change the state of the
-		 * RTM CPUID bit.  Clear it here since it is now
-		 * expected to be not set.
+		 * tsx_disable() will change the state of the RTM and HLE CPUID
+		 * bits. Clear them here since they are now expected to be not
+		 * set.
 		 */
 		setup_clear_cpu_cap(X86_FEATURE_RTM);
+		setup_clear_cpu_cap(X86_FEATURE_HLE);
 	} else if (tsx_ctrl_state == TSX_CTRL_ENABLE) {
 
 		/*
@@ -131,10 +132,10 @@ void __init tsx_init(void)
 		tsx_enable();
 
 		/*
-		 * tsx_enable() will change the state of the
-		 * RTM CPUID bit.  Force it here since it is now
-		 * expected to be set.
+		 * tsx_enable() will change the state of the RTM and HLE CPUID
+		 * bits. Force them here since they are now expected to be set.
 		 */
 		setup_force_cpu_cap(X86_FEATURE_RTM);
+		setup_force_cpu_cap(X86_FEATURE_HLE);
 	}
 }


^ permalink raw reply	[relevance 8%]

* [PATCH 3.16 97/99] cifs: fail i/o on soft mounts if sessionsetup errors out
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (95 preceding siblings ...)
  2020-05-20 14:15 11% ` [PATCH 3.16 96/99] NFS: Directory page cache pages need to be locked when read Ben Hutchings
@ 2020-05-20 14:15  9% ` Ben Hutchings
  2020-05-20 14:15  9% ` [PATCH 3.16 98/99] bonding/alb: properly access headers in bond_alb_xmit() Ben Hutchings
                   ` (2 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:15 UTC (permalink / raw)
  To: linux-kernel, stable; +Cc: akpm, Denis Kirjanov, Ronnie Sahlberg, Steve French

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Ronnie Sahlberg <lsahlber@redhat.com>

commit b0dd940e582b6a60296b9847a54012a4b080dc72 upstream.

RHBZ: 1579050

If we have a soft mount we should fail commands for session-setup
failures (such as the password having changed/ account being deleted/ ...)
and return an error back to the application.

Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 fs/cifs/smb2pdu.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -250,9 +250,14 @@ smb2_reconnect(__le16 smb2_command, stru
 	 */
 	mutex_lock(&tcon->ses->session_mutex);
 	rc = cifs_negotiate_protocol(0, tcon->ses);
-	if (!rc && tcon->ses->need_reconnect)
+	if (!rc && tcon->ses->need_reconnect) {
 		rc = cifs_setup_session(0, tcon->ses, nls_codepage);
-
+		if ((rc == -EACCES) && !tcon->retry) {
+			rc = -EHOSTDOWN;
+			mutex_unlock(&tcon->ses->session_mutex);
+			goto failed;
+		}
+	}
 	if (rc || !tcon->need_reconnect) {
 		mutex_unlock(&tcon->ses->session_mutex);
 		goto out;
@@ -290,6 +295,7 @@ out:
 	case SMB2_SET_INFO:
 		rc = -EAGAIN;
 	}
+failed:
 	unload_nls(nls_codepage);
 	return rc;
 }


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 64/99] USB: serial: ir-usb: fix IrLAP framing
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (62 preceding siblings ...)
  2020-05-20 14:14  8% ` [PATCH 3.16 63/99] USB: serial: ir-usb: fix link-speed handling Ben Hutchings
@ 2020-05-20 14:14  7% ` Ben Hutchings
  2020-05-20 14:14  7% ` [PATCH 3.16 65/99] media: uvcvideo: Avoid cyclic entity chains due to malformed USB descriptors Ben Hutchings
                   ` (35 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Johan Hovold, Greg Kroah-Hartman

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Johan Hovold <johan@kernel.org>

commit 38c0d5bdf4973f9f5a888166e9d3e9ed0d32057a upstream.

Commit f4a4cbb2047e ("USB: ir-usb: reimplement using generic framework")
switched to using the generic write implementation which may combine
multiple write requests into larger transfers. This can break the IrLAP
protocol where end-of-frame is determined using the USB short packet
mechanism, for example, if multiple frames are sent in rapid succession.

Fixes: f4a4cbb2047e ("USB: ir-usb: reimplement using generic framework")
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Johan Hovold <johan@kernel.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/usb/serial/ir-usb.c | 113 +++++++++++++++++++++++++++++-------
 1 file changed, 91 insertions(+), 22 deletions(-)

--- a/drivers/usb/serial/ir-usb.c
+++ b/drivers/usb/serial/ir-usb.c
@@ -49,9 +49,10 @@ static int buffer_size;
 static int xbof = -1;
 
 static int  ir_startup (struct usb_serial *serial);
-static int  ir_open(struct tty_struct *tty, struct usb_serial_port *port);
-static int ir_prepare_write_buffer(struct usb_serial_port *port,
-						void *dest, size_t size);
+static int ir_write(struct tty_struct *tty, struct usb_serial_port *port,
+		const unsigned char *buf, int count);
+static int ir_write_room(struct tty_struct *tty);
+static void ir_write_bulk_callback(struct urb *urb);
 static void ir_process_read_urb(struct urb *urb);
 static void ir_set_termios(struct tty_struct *tty,
 		struct usb_serial_port *port, struct ktermios *old_termios);
@@ -81,8 +82,9 @@ static struct usb_serial_driver ir_devic
 	.num_ports		= 1,
 	.set_termios		= ir_set_termios,
 	.attach			= ir_startup,
-	.open			= ir_open,
-	.prepare_write_buffer	= ir_prepare_write_buffer,
+	.write			= ir_write,
+	.write_room		= ir_write_room,
+	.write_bulk_callback	= ir_write_bulk_callback,
 	.process_read_urb	= ir_process_read_urb,
 };
 
@@ -258,35 +260,102 @@ static int ir_startup(struct usb_serial
 	return 0;
 }
 
-static int ir_open(struct tty_struct *tty, struct usb_serial_port *port)
+static int ir_write(struct tty_struct *tty, struct usb_serial_port *port,
+		const unsigned char *buf, int count)
 {
-	int i;
+	struct urb *urb = NULL;
+	unsigned long flags;
+	int ret;
 
-	for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i)
-		port->write_urbs[i]->transfer_flags = URB_ZERO_PACKET;
+	if (port->bulk_out_size == 0)
+		return -EINVAL;
 
-	/* Start reading from the device */
-	return usb_serial_generic_open(tty, port);
-}
+	if (count == 0)
+		return 0;
 
-static int ir_prepare_write_buffer(struct usb_serial_port *port,
-						void *dest, size_t size)
-{
-	unsigned char *buf = dest;
-	int count;
+	count = min(count, port->bulk_out_size - 1);
+
+	spin_lock_irqsave(&port->lock, flags);
+	if (__test_and_clear_bit(0, &port->write_urbs_free)) {
+		urb = port->write_urbs[0];
+		port->tx_bytes += count;
+	}
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	if (!urb)
+		return 0;
 
 	/*
 	 * The first byte of the packet we send to the device contains an
-	 * inbound header which indicates an additional number of BOFs and
+	 * outbound header which indicates an additional number of BOFs and
 	 * a baud rate change.
 	 *
 	 * See section 5.4.2.2 of the USB IrDA spec.
 	 */
-	*buf = ir_xbof | ir_baud;
+	*(u8 *)urb->transfer_buffer = ir_xbof | ir_baud;
+
+	memcpy(urb->transfer_buffer + 1, buf, count);
+
+	urb->transfer_buffer_length = count + 1;
+	urb->transfer_flags = URB_ZERO_PACKET;
+
+	ret = usb_submit_urb(urb, GFP_ATOMIC);
+	if (ret) {
+		dev_err(&port->dev, "failed to submit write urb: %d\n", ret);
+
+		spin_lock_irqsave(&port->lock, flags);
+		__set_bit(0, &port->write_urbs_free);
+		port->tx_bytes -= count;
+		spin_unlock_irqrestore(&port->lock, flags);
+
+		return ret;
+	}
+
+	return count;
+}
+
+static void ir_write_bulk_callback(struct urb *urb)
+{
+	struct usb_serial_port *port = urb->context;
+	int status = urb->status;
+	unsigned long flags;
+
+	spin_lock_irqsave(&port->lock, flags);
+	__set_bit(0, &port->write_urbs_free);
+	port->tx_bytes -= urb->transfer_buffer_length - 1;
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	switch (status) {
+	case 0:
+		break;
+	case -ENOENT:
+	case -ECONNRESET:
+	case -ESHUTDOWN:
+		dev_dbg(&port->dev, "write urb stopped: %d\n", status);
+		return;
+	case -EPIPE:
+		dev_err(&port->dev, "write urb stopped: %d\n", status);
+		return;
+	default:
+		dev_err(&port->dev, "nonzero write-urb status: %d\n", status);
+		break;
+	}
+
+	usb_serial_port_softint(port);
+}
+
+static int ir_write_room(struct tty_struct *tty)
+{
+	struct usb_serial_port *port = tty->driver_data;
+	int count = 0;
+
+	if (port->bulk_out_size == 0)
+		return 0;
+
+	if (test_bit(0, &port->write_urbs_free))
+		count = port->bulk_out_size - 1;
 
-	count = kfifo_out_locked(&port->write_fifo, buf + 1, size - 1,
-								&port->lock);
-	return count + 1;
+	return count;
 }
 
 static void ir_process_read_urb(struct urb *urb)


^ permalink raw reply	[relevance 7%]

* [PATCH 3.16 35/99] pxa168fb: Fix the function used to release some memory in an error handling path
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (33 preceding siblings ...)
  2020-05-20 14:14 11% ` [PATCH 3.16 34/99] gianfar: Fix TX timestamping with a stacked DSA driver Ben Hutchings
@ 2020-05-20 14:14 12% ` Ben Hutchings
  2020-05-21 14:09  9%   ` Marion & Christophe JAILLET
  2020-05-20 14:14  9% ` [PATCH 3.16 36/99] ALSA: sh: Fix compile warning wrt const Ben Hutchings
                   ` (64 subsequent siblings)
  99 siblings, 1 reply; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, YueHaibing, Bartlomiej Zolnierkiewicz,
	Christophe JAILLET, Lubomir Rintel

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Christophe JAILLET <christophe.jaillet@wanadoo.fr>

commit 3c911fe799d1c338d94b78e7182ad452c37af897 upstream.

In the probe function, some resources are allocated using 'dma_alloc_wc()',
they should be released with 'dma_free_wc()', not 'dma_free_coherent()'.

We already use 'dma_free_wc()' in the remove function, but not in the
error handling path of the probe function.

Also, remove a useless 'PAGE_ALIGN()'. 'info->fix.smem_len' is already
PAGE_ALIGNed.

Fixes: 638772c7553f ("fb: add support of LCD display controller on pxa168/910 (base layer)")
Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
Reviewed-by: Lubomir Rintel <lkundrak@v3.sk>
CC: YueHaibing <yuehaibing@huawei.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190831100024.3248-1-christophe.jaillet@wanadoo.fr
[bwh: Backported to 3.16: Use dma_free_writecombine().]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/video/fbdev/pxa168fb.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

--- a/drivers/video/fbdev/pxa168fb.c
+++ b/drivers/video/fbdev/pxa168fb.c
@@ -772,8 +772,8 @@ failed_free_cmap:
 failed_free_clk:
 	clk_disable(fbi->clk);
 failed_free_fbmem:
-	dma_free_coherent(fbi->dev, info->fix.smem_len,
-			info->screen_base, fbi->fb_start_dma);
+	dma_free_writecombine(fbi->dev, info->fix.smem_len,
+			      info->screen_base, fbi->fb_start_dma);
 failed_free_info:
 	kfree(info);
 failed_put_clk:
@@ -809,7 +809,7 @@ static int pxa168fb_remove(struct platfo
 
 	irq = platform_get_irq(pdev, 0);
 
-	dma_free_writecombine(fbi->dev, PAGE_ALIGN(info->fix.smem_len),
+	dma_free_writecombine(fbi->dev, info->fix.smem_len,
 				info->screen_base, info->fix.smem_start);
 
 	clk_disable(fbi->clk);


^ permalink raw reply	[relevance 12%]

* [PATCH 3.16 52/99] nfs: NFS_SWAP should depend on SWAP
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (50 preceding siblings ...)
  2020-05-20 14:14  9% ` [PATCH 3.16 51/99] staging: wlan-ng: ensure error return is actually returned Ben Hutchings
@ 2020-05-20 14:14  9% ` Ben Hutchings
  2020-05-20 14:14 12% ` [PATCH 3.16 53/99] ubifs: Fix deadlock in concurrent bulk-read and writepage Ben Hutchings
                   ` (47 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Geert Uytterhoeven, Anna Schumaker

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Geert Uytterhoeven <geert+renesas@glider.be>

commit 474c4f306eefbb21b67ebd1de802d005c7d7ecdc upstream.

If CONFIG_SWAP=n, it does not make much sense to offer the user the
option to enable support for swapping over NFS, as that will still fail
at run time:

    # swapon /swap
    swapon: /swap: swapon failed: Function not implemented

Fix this by adding a dependency on CONFIG_SWAP.

Fixes: a564b8f0398636ba ("nfs: enable swap on NFS")
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 fs/nfs/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/fs/nfs/Kconfig
+++ b/fs/nfs/Kconfig
@@ -89,7 +89,7 @@ config NFS_V4
 config NFS_SWAP
 	bool "Provide swap over NFS support"
 	default n
-	depends on NFS_FS
+	depends on NFS_FS && SWAP
 	select SUNRPC_SWAP
 	help
 	  This option enables swapon to work on files located on NFS mounts.


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 80/99] KVM: x86: Protect kvm_lapic_reg_write() from Spectre-v1/L1TF attacks
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (78 preceding siblings ...)
  2020-05-20 14:14 12% ` [PATCH 3.16 79/99] KVM: x86: Protect ioapic_write_indirect() " Ben Hutchings
@ 2020-05-20 14:14 12% ` Ben Hutchings
  2020-05-20 14:14 12% ` [PATCH 3.16 81/99] kvm: x86: use macros to compute bank MSRs Ben Hutchings
                   ` (19 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Marios Pomonis, Nick Finco, Jim Mattson,
	Paolo Bonzini, Andrew Honig

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Marios Pomonis <pomonis@google.com>

commit 4bf79cb089f6b1c6c632492c0271054ce52ad766 upstream.

This fixes a Spectre-v1/L1TF vulnerability in kvm_lapic_reg_write().
This function contains index computations based on the
(attacker-controlled) MSR number.

Fixes: 0105d1a52640 ("KVM: x2apic interface to lapic")

Signed-off-by: Nick Finco <nifi@google.com>
Signed-off-by: Marios Pomonis <pomonis@google.com>
Reviewed-by: Andrew Honig <ahonig@google.com>
Reviewed-by: Jim Mattson <jmattson@google.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
[bwh: Backported to 3.16:
 - Add #include <linux/nospec.h>
 - Adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -35,6 +35,7 @@
 #include <asm/apicdef.h>
 #include <linux/atomic.h>
 #include <linux/jump_label.h>
+#include <linux/nospec.h>
 #include "kvm_cache_regs.h"
 #include "irq.h"
 #include "trace.h"
@@ -1196,15 +1197,20 @@ static int apic_reg_write(struct kvm_lap
 	case APIC_LVTTHMR:
 	case APIC_LVTPC:
 	case APIC_LVT1:
-	case APIC_LVTERR:
+	case APIC_LVTERR: {
 		/* TODO: Check vector */
+		size_t size;
+		u32 index;
+
 		if (!kvm_apic_sw_enabled(apic))
 			val |= APIC_LVT_MASKED;
-
-		val &= apic_lvt_mask[(reg - APIC_LVTT) >> 4];
+		size = ARRAY_SIZE(apic_lvt_mask);
+		index = array_index_nospec(
+				(reg - APIC_LVTT) >> 4, size);
+		val &= apic_lvt_mask[index];
 		apic_set_reg(apic, reg, val);
-
 		break;
+	}
 
 	case APIC_LVTT:
 		if ((kvm_apic_get_reg(apic, APIC_LVTT) &


^ permalink raw reply	[relevance 12%]

* [PATCH 3.16 92/99] cls_rsvp: fix rsvp_policy
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (90 preceding siblings ...)
  2020-05-20 14:14  8% ` [PATCH 3.16 91/99] clocksource: Prevent double add_timer_on() for watchdog_timer Ben Hutchings
@ 2020-05-20 14:15  7% ` Ben Hutchings
  2020-05-20 14:15  9% ` [PATCH 3.16 93/99] kconfig: fix broken dependency in randconfig-generated .config Ben Hutchings
                   ` (7 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:15 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, syzbot, Cong Wang, Jakub Kicinski, Eric Dumazet

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Eric Dumazet <edumazet@google.com>

commit cb3c0e6bdf64d0d124e94ce43cbe4ccbb9b37f51 upstream.

NLA_BINARY can be confusing, since .len value represents
the max size of the blob.

cls_rsvp really wants user space to provide long enough data
for TCA_RSVP_DST and TCA_RSVP_SRC attributes.

BUG: KMSAN: uninit-value in rsvp_get net/sched/cls_rsvp.h:258 [inline]
BUG: KMSAN: uninit-value in gen_handle net/sched/cls_rsvp.h:402 [inline]
BUG: KMSAN: uninit-value in rsvp_change+0x1ae9/0x4220 net/sched/cls_rsvp.h:572
CPU: 1 PID: 13228 Comm: syz-executor.1 Not tainted 5.5.0-rc5-syzkaller #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
Call Trace:
 __dump_stack lib/dump_stack.c:77 [inline]
 dump_stack+0x1c9/0x220 lib/dump_stack.c:118
 kmsan_report+0xf7/0x1e0 mm/kmsan/kmsan_report.c:118
 __msan_warning+0x58/0xa0 mm/kmsan/kmsan_instr.c:215
 rsvp_get net/sched/cls_rsvp.h:258 [inline]
 gen_handle net/sched/cls_rsvp.h:402 [inline]
 rsvp_change+0x1ae9/0x4220 net/sched/cls_rsvp.h:572
 tc_new_tfilter+0x31fe/0x5010 net/sched/cls_api.c:2104
 rtnetlink_rcv_msg+0xcb7/0x1570 net/core/rtnetlink.c:5415
 netlink_rcv_skb+0x451/0x650 net/netlink/af_netlink.c:2477
 rtnetlink_rcv+0x50/0x60 net/core/rtnetlink.c:5442
 netlink_unicast_kernel net/netlink/af_netlink.c:1302 [inline]
 netlink_unicast+0xf9e/0x1100 net/netlink/af_netlink.c:1328
 netlink_sendmsg+0x1248/0x14d0 net/netlink/af_netlink.c:1917
 sock_sendmsg_nosec net/socket.c:639 [inline]
 sock_sendmsg net/socket.c:659 [inline]
 ____sys_sendmsg+0x12b6/0x1350 net/socket.c:2330
 ___sys_sendmsg net/socket.c:2384 [inline]
 __sys_sendmsg+0x451/0x5f0 net/socket.c:2417
 __do_sys_sendmsg net/socket.c:2426 [inline]
 __se_sys_sendmsg+0x97/0xb0 net/socket.c:2424
 __x64_sys_sendmsg+0x4a/0x70 net/socket.c:2424
 do_syscall_64+0xb8/0x160 arch/x86/entry/common.c:296
 entry_SYSCALL_64_after_hwframe+0x44/0xa9
RIP: 0033:0x45b349
Code: ad b6 fb ff c3 66 2e 0f 1f 84 00 00 00 00 00 66 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 0f 83 7b b6 fb ff c3 66 2e 0f 1f 84 00 00 00 00
RSP: 002b:00007f269d43dc78 EFLAGS: 00000246 ORIG_RAX: 000000000000002e
RAX: ffffffffffffffda RBX: 00007f269d43e6d4 RCX: 000000000045b349
RDX: 0000000000000000 RSI: 00000000200001c0 RDI: 0000000000000003
RBP: 000000000075bfc8 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 00000000ffffffff
R13: 00000000000009c2 R14: 00000000004cb338 R15: 000000000075bfd4

Uninit was created at:
 kmsan_save_stack_with_flags mm/kmsan/kmsan.c:144 [inline]
 kmsan_internal_poison_shadow+0x66/0xd0 mm/kmsan/kmsan.c:127
 kmsan_slab_alloc+0x8a/0xe0 mm/kmsan/kmsan_hooks.c:82
 slab_alloc_node mm/slub.c:2774 [inline]
 __kmalloc_node_track_caller+0xb40/0x1200 mm/slub.c:4382
 __kmalloc_reserve net/core/skbuff.c:141 [inline]
 __alloc_skb+0x2fd/0xac0 net/core/skbuff.c:209
 alloc_skb include/linux/skbuff.h:1049 [inline]
 netlink_alloc_large_skb net/netlink/af_netlink.c:1174 [inline]
 netlink_sendmsg+0x7d3/0x14d0 net/netlink/af_netlink.c:1892
 sock_sendmsg_nosec net/socket.c:639 [inline]
 sock_sendmsg net/socket.c:659 [inline]
 ____sys_sendmsg+0x12b6/0x1350 net/socket.c:2330
 ___sys_sendmsg net/socket.c:2384 [inline]
 __sys_sendmsg+0x451/0x5f0 net/socket.c:2417
 __do_sys_sendmsg net/socket.c:2426 [inline]
 __se_sys_sendmsg+0x97/0xb0 net/socket.c:2424
 __x64_sys_sendmsg+0x4a/0x70 net/socket.c:2424
 do_syscall_64+0xb8/0x160 arch/x86/entry/common.c:296
 entry_SYSCALL_64_after_hwframe+0x44/0xa9

Fixes: 6fa8c0144b77 ("[NET_SCHED]: Use nla_policy for attribute validation in classifiers")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reported-by: syzbot <syzkaller@googlegroups.com>
Acked-by: Cong Wang <xiyou.wangcong@gmail.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 net/sched/cls_rsvp.h | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

--- a/net/sched/cls_rsvp.h
+++ b/net/sched/cls_rsvp.h
@@ -404,10 +404,8 @@ static u32 gen_tunnel(struct rsvp_head *
 
 static const struct nla_policy rsvp_policy[TCA_RSVP_MAX + 1] = {
 	[TCA_RSVP_CLASSID]	= { .type = NLA_U32 },
-	[TCA_RSVP_DST]		= { .type = NLA_BINARY,
-				    .len = RSVP_DST_LEN * sizeof(u32) },
-	[TCA_RSVP_SRC]		= { .type = NLA_BINARY,
-				    .len = RSVP_DST_LEN * sizeof(u32) },
+	[TCA_RSVP_DST]		= { .len = RSVP_DST_LEN * sizeof(u32) },
+	[TCA_RSVP_SRC]		= { .len = RSVP_DST_LEN * sizeof(u32) },
 	[TCA_RSVP_PINFO]	= { .len = sizeof(struct tc_rsvp_pinfo) },
 };
 


^ permalink raw reply	[relevance 7%]

* [PATCH 3.16 68/99] KVM: x86: Free wbinvd_dirty_mask if vCPU creation fails
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (66 preceding siblings ...)
  2020-05-20 14:14  9% ` [PATCH 3.16 67/99] KVM: PPC: Book3S PR: Free shared page if mmu initialization fails Ben Hutchings
@ 2020-05-20 14:14 13% ` Ben Hutchings
  2020-05-20 14:14  8% ` [PATCH 3.16 69/99] tracing: Fix very unlikely race of registering two stat tracers Ben Hutchings
                   ` (31 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Paolo Bonzini, Sean Christopherson

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Sean Christopherson <sean.j.christopherson@intel.com>

commit 16be9ddea268ad841457a59109963fff8c9de38d upstream.

Free the vCPU's wbinvd_dirty_mask if vCPU creation fails after
kvm_arch_vcpu_init(), e.g. when installing the vCPU's file descriptor.
Do the freeing by calling kvm_arch_vcpu_free() instead of open coding
the freeing.  This adds a likely superfluous, but ultimately harmless,
call to kvmclock_reset(), which only clears vcpu->arch.pv_time_enabled.
Using kvm_arch_vcpu_free() allows for additional cleanup in the future.

Fixes: f5f48ee15c2ee ("KVM: VMX: Execute WBINVD to keep data consistency with assigned devices")
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
[bwh: Backported to 3.16: Also delete the preceding fx_free(), since
 kvm_arch_vcpu_free() calls it.]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -7087,8 +7087,7 @@ void kvm_arch_vcpu_destroy(struct kvm_vc
 	kvm_mmu_unload(vcpu);
 	vcpu_put(vcpu);
 
-	fx_free(vcpu);
-	kvm_x86_ops->vcpu_free(vcpu);
+	kvm_arch_vcpu_free(vcpu);
 }
 
 void kvm_vcpu_reset(struct kvm_vcpu *vcpu)


^ permalink raw reply	[relevance 13%]

* [PATCH 3.16 69/99] tracing: Fix very unlikely race of registering two stat tracers
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (67 preceding siblings ...)
  2020-05-20 14:14 13% ` [PATCH 3.16 68/99] KVM: x86: Free wbinvd_dirty_mask if vCPU creation fails Ben Hutchings
@ 2020-05-20 14:14  8% ` Ben Hutchings
  2020-05-20 14:14 12% ` [PATCH 3.16 70/99] tracing: Fix tracing_stat return values in error handling paths Ben Hutchings
                   ` (30 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Steven Rostedt (VMware), Luis Henriques

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: "Steven Rostedt (VMware)" <rostedt@goodmis.org>

commit dfb6cd1e654315168e36d947471bd2a0ccd834ae upstream.

Looking through old emails in my INBOX, I came across a patch from Luis
Henriques that attempted to fix a race of two stat tracers registering the
same stat trace (extremely unlikely, as this is done in the kernel, and
probably doesn't even exist). The submitted patch wasn't quite right as it
needed to deal with clean up a bit better (if two stat tracers were the
same, it would have the same files).

But to make the code cleaner, all we needed to do is to keep the
all_stat_sessions_mutex held for most of the registering function.

Link: http://lkml.kernel.org/r/1410299375-20068-1-git-send-email-luis.henriques@canonical.com

Fixes: 002bb86d8d42f ("tracing/ftrace: separate events tracing and stats tracing engine")
Reported-by: Luis Henriques <luis.henriques@canonical.com>
Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 kernel/trace/trace_stat.c | 19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)

--- a/kernel/trace/trace_stat.c
+++ b/kernel/trace/trace_stat.c
@@ -302,7 +302,7 @@ static int init_stat_file(struct stat_se
 int register_stat_tracer(struct tracer_stat *trace)
 {
 	struct stat_session *session, *node;
-	int ret;
+	int ret = -EINVAL;
 
 	if (!trace)
 		return -EINVAL;
@@ -313,17 +313,15 @@ int register_stat_tracer(struct tracer_s
 	/* Already registered? */
 	mutex_lock(&all_stat_sessions_mutex);
 	list_for_each_entry(node, &all_stat_sessions, session_list) {
-		if (node->ts == trace) {
-			mutex_unlock(&all_stat_sessions_mutex);
-			return -EINVAL;
-		}
+		if (node->ts == trace)
+			goto out;
 	}
-	mutex_unlock(&all_stat_sessions_mutex);
 
+	ret = -ENOMEM;
 	/* Init the session */
 	session = kzalloc(sizeof(*session), GFP_KERNEL);
 	if (!session)
-		return -ENOMEM;
+		goto out;
 
 	session->ts = trace;
 	INIT_LIST_HEAD(&session->session_list);
@@ -332,15 +330,16 @@ int register_stat_tracer(struct tracer_s
 	ret = init_stat_file(session);
 	if (ret) {
 		destroy_session(session);
-		return ret;
+		goto out;
 	}
 
+	ret = 0;
 	/* Register */
-	mutex_lock(&all_stat_sessions_mutex);
 	list_add_tail(&session->session_list, &all_stat_sessions);
+ out:
 	mutex_unlock(&all_stat_sessions_mutex);
 
-	return 0;
+	return ret;
 }
 
 void unregister_stat_tracer(struct tracer_stat *trace)


^ permalink raw reply	[relevance 8%]

* [PATCH 3.16 61/99] KVM: x86/mmu: Apply max PA check for MMIO sptes to 32-bit KVM
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (59 preceding siblings ...)
  2020-05-20 14:14  9% ` [PATCH 3.16 60/99] x86: kvm: avoid unused variable warning Ben Hutchings
@ 2020-05-20 14:14 12% ` Ben Hutchings
  2020-05-20 14:14  9% ` [PATCH 3.16 62/99] USB: serial: ir-usb: add missing endpoint sanity check Ben Hutchings
                   ` (38 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Paolo Bonzini, Sean Christopherson

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Sean Christopherson <sean.j.christopherson@intel.com>

commit e30a7d623dccdb3f880fbcad980b0cb589a1da45 upstream.

Remove the bogus 64-bit only condition from the check that disables MMIO
spte optimization when the system supports the max PA, i.e. doesn't have
any reserved PA bits.  32-bit KVM always uses PAE paging for the shadow
MMU, and per Intel's SDM:

  PAE paging translates 32-bit linear addresses to 52-bit physical
  addresses.

The kernel's restrictions on max physical addresses are limits on how
much memory the kernel can reasonably use, not what physical addresses
are supported by hardware.

Fixes: ce88decffd17 ("KVM: MMU: mmio page fault support")
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
[bwh: Backported to 3.16: adjust filename, context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 arch/x86/kvm/x86.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -5734,7 +5734,7 @@ static void kvm_set_mmio_spte_mask(void)
 	 * If reserved bit is not supported, clear the present bit to disable
 	 * mmio page fault.
 	 */
-	if (IS_ENABLED(CONFIG_X86_64) && maxphyaddr == 52)
+	if (maxphyaddr == 52)
 		mask &= ~1ull;
 
 	kvm_mmu_set_mmio_spte_mask(mask);


^ permalink raw reply	[relevance 12%]

* [PATCH 3.16 70/99] tracing: Fix tracing_stat return values in error handling paths
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (68 preceding siblings ...)
  2020-05-20 14:14  8% ` [PATCH 3.16 69/99] tracing: Fix very unlikely race of registering two stat tracers Ben Hutchings
@ 2020-05-20 14:14 12% ` Ben Hutchings
  2020-05-20 14:14  9% ` [PATCH 3.16 71/99] jbd2: switch to use jbd2_journal_abort() when failed to submit the commit record Ben Hutchings
                   ` (29 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Luis Henriques, Steven Rostedt (VMware)

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Luis Henriques <luis.henriques@canonical.com>

commit afccc00f75bbbee4e4ae833a96c2d29a7259c693 upstream.

tracing_stat_init() was always returning '0', even on the error paths.  It
now returns -ENODEV if tracing_init_dentry() fails or -ENOMEM if it fails
to created the 'trace_stat' debugfs directory.

Link: http://lkml.kernel.org/r/1410299381-20108-1-git-send-email-luis.henriques@canonical.com

Fixes: ed6f1c996bfe4 ("tracing: Check return value of tracing_init_dentry()")
Signed-off-by: Luis Henriques <luis.henriques@canonical.com>
[ Pulled from the archeological digging of my INBOX ]
Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 kernel/trace/trace_stat.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

--- a/kernel/trace/trace_stat.c
+++ b/kernel/trace/trace_stat.c
@@ -277,19 +277,23 @@ static int tracing_stat_init(void)
 
 	d_tracing = tracing_init_dentry();
 	if (!d_tracing)
-		return 0;
+		return -ENODEV;
 
 	stat_dir = debugfs_create_dir("trace_stat", d_tracing);
-	if (!stat_dir)
+	if (!stat_dir) {
 		pr_warning("Could not create debugfs "
 			   "'trace_stat' entry\n");
+		return -ENOMEM;
+	}
 	return 0;
 }
 
 static int init_stat_file(struct stat_session *session)
 {
-	if (!stat_dir && tracing_stat_init())
-		return -ENODEV;
+	int ret;
+
+	if (!stat_dir && (ret = tracing_stat_init()))
+		return ret;
 
 	session->file = debugfs_create_file(session->ts->name, 0644,
 					    stat_dir,


^ permalink raw reply	[relevance 12%]

* [PATCH 3.16 71/99] jbd2: switch to use jbd2_journal_abort() when failed to submit the commit record
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (69 preceding siblings ...)
  2020-05-20 14:14 12% ` [PATCH 3.16 70/99] tracing: Fix tracing_stat return values in error handling paths Ben Hutchings
@ 2020-05-20 14:14  9% ` Ben Hutchings
  2020-05-20 14:14  8% ` [PATCH 3.16 72/99] ext4, jbd2: ensure panic when aborting with zero errno Ben Hutchings
                   ` (28 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Jan Kara, zhangyi (F), Theodore Ts'o

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: "zhangyi (F)" <yi.zhang@huawei.com>

commit d0a186e0d3e7ac05cc77da7c157dae5aa59f95d9 upstream.

We invoke jbd2_journal_abort() to abort the journal and record errno
in the jbd2 superblock when committing journal transaction besides the
failure on submitting the commit record. But there is no need for the
case and we can also invoke jbd2_journal_abort() instead of
__jbd2_journal_abort_hard().

Fixes: 818d276ceb83a ("ext4: Add the journal checksum feature")
Signed-off-by: zhangyi (F) <yi.zhang@huawei.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Link: https://lore.kernel.org/r/20191204124614.45424-2-yi.zhang@huawei.com
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 fs/jbd2/commit.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

--- a/fs/jbd2/commit.c
+++ b/fs/jbd2/commit.c
@@ -802,7 +802,7 @@ start_journal_io:
 		err = journal_submit_commit_record(journal, commit_transaction,
 						 &cbh, crc32_sum);
 		if (err)
-			__jbd2_journal_abort_hard(journal);
+			jbd2_journal_abort(journal, err);
 	}
 
 	blk_finish_plug(&plug);
@@ -894,7 +894,7 @@ start_journal_io:
 		err = journal_submit_commit_record(journal, commit_transaction,
 						&cbh, crc32_sum);
 		if (err)
-			__jbd2_journal_abort_hard(journal);
+			jbd2_journal_abort(journal, err);
 	}
 	if (cbh)
 		err = journal_wait_on_commit_record(journal, cbh);


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 82/99] KVM: x86: Protect MSR-based index computations from Spectre-v1/L1TF attacks in x86.c
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (80 preceding siblings ...)
  2020-05-20 14:14 12% ` [PATCH 3.16 81/99] kvm: x86: use macros to compute bank MSRs Ben Hutchings
@ 2020-05-20 14:14 12% ` Ben Hutchings
  2020-05-20 14:14  9% ` [PATCH 3.16 83/99] KVM: x86: Protect DR-based index computations from Spectre-v1/L1TF attacks Ben Hutchings
                   ` (17 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Marios Pomonis, Nick Finco, Jim Mattson,
	Paolo Bonzini, Andrew Honig

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Marios Pomonis <pomonis@google.com>

commit 6ec4c5eee1750d5d17951c4e1960d953376a0dda upstream.

This fixes a Spectre-v1/L1TF vulnerability in set_msr_mce() and
get_msr_mce().
Both functions contain index computations based on the
(attacker-controlled) MSR number.

Fixes: 890ca9aefa78 ("KVM: Add MCE support")

Signed-off-by: Nick Finco <nifi@google.com>
Signed-off-by: Marios Pomonis <pomonis@google.com>
Reviewed-by: Andrew Honig <ahonig@google.com>
Reviewed-by: Jim Mattson <jmattson@google.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
[bwh: Backported to 3.16: Add #include <linux/nospec.h>]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -48,6 +48,7 @@
 #include <linux/pci.h>
 #include <linux/timekeeper_internal.h>
 #include <linux/pvclock_gtod.h>
+#include <linux/nospec.h>
 #include <trace/events/kvm.h>
 
 #define CREATE_TRACE_POINTS
@@ -1916,7 +1917,10 @@ static int set_msr_mce(struct kvm_vcpu *
 	default:
 		if (msr >= MSR_IA32_MC0_CTL &&
 		    msr < MSR_IA32_MCx_CTL(bank_num)) {
-			u32 offset = msr - MSR_IA32_MC0_CTL;
+			u32 offset = array_index_nospec(
+				msr - MSR_IA32_MC0_CTL,
+				MSR_IA32_MCx_CTL(bank_num) - MSR_IA32_MC0_CTL);
+
 			/* only 0 or all 1s can be written to IA32_MCi_CTL
 			 * some Linux kernels though clear bit 10 in bank 4 to
 			 * workaround a BIOS/GART TBL issue on AMD K8s, ignore
@@ -2443,7 +2447,10 @@ static int get_msr_mce(struct kvm_vcpu *
 	default:
 		if (msr >= MSR_IA32_MC0_CTL &&
 		    msr < MSR_IA32_MCx_CTL(bank_num)) {
-			u32 offset = msr - MSR_IA32_MC0_CTL;
+			u32 offset = array_index_nospec(
+				msr - MSR_IA32_MC0_CTL,
+				MSR_IA32_MCx_CTL(bank_num) - MSR_IA32_MC0_CTL);
+
 			data = vcpu->arch.mce_banks[offset];
 			break;
 		}


^ permalink raw reply	[relevance 12%]

* [PATCH 3.16 89/99] tcp: clear tp->total_retrans in tcp_disconnect()
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (87 preceding siblings ...)
  2020-05-20 14:14 11% ` [PATCH 3.16 88/99] media/v4l2-core: set pages dirty upon releasing DMA buffers Ben Hutchings
@ 2020-05-20 14:14  9% ` Ben Hutchings
  2020-05-20 14:14  9% ` [PATCH 3.16 90/99] ALSA: dummy: Fix PCM format loop in proc output Ben Hutchings
                   ` (10 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Jakub Kicinski, Eric Dumazet, SeongJae Park

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Eric Dumazet <edumazet@google.com>

commit c13c48c00a6bc1febc73902505bdec0967bd7095 upstream.

total_retrans needs to be cleared in tcp_disconnect().

tcp_disconnect() is rarely used, but it is worth fixing it.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: SeongJae Park <sjpark@amazon.de>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 net/ipv4/tcp.c | 1 +
 1 file changed, 1 insertion(+)

--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -2363,6 +2363,7 @@ int tcp_disconnect(struct sock *sk, int
 	tp->window_clamp = 0;
 	tcp_set_ca_state(sk, TCP_CA_Open);
 	tcp_clear_retrans(tp);
+	tp->total_retrans = 0;
 	inet_csk_delack_init(sk);
 	/* Initialize rcv_mss to TCP_MIN_MSS to avoid division by 0
 	 * issue in __tcp_select_window()


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 95/99] NFS: Fix memory leaks and corruption in readdir
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (93 preceding siblings ...)
  2020-05-20 14:15  8% ` [PATCH 3.16 94/99] nfs: use kmap/kunmap directly Ben Hutchings
@ 2020-05-20 14:15  9% ` Ben Hutchings
  2020-05-20 14:15 11% ` [PATCH 3.16 96/99] NFS: Directory page cache pages need to be locked when read Ben Hutchings
                   ` (4 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:15 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Benjamin Coddington, Trond Myklebust,
	Trond Myklebust, Anna Schumaker

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Trond Myklebust <trondmy@gmail.com>

commit 4b310319c6a8ce708f1033d57145e2aa027a883c upstream.

nfs_readdir_xdr_to_array() must not exit without having initialised
the array, so that the page cache deletion routines can safely
call nfs_readdir_clear_array().
Furthermore, we should ensure that if we exit nfs_readdir_filler()
with an error, we free up any page contents to prevent a leak
if we try to fill the page again.

Fixes: 11de3b11e08c ("NFS: Fix a memory leak in nfs_readdir")
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Reviewed-by: Benjamin Coddington <bcodding@redhat.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 fs/nfs/dir.c | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -169,6 +169,17 @@ typedef struct {
 	unsigned int	eof:1;
 } nfs_readdir_descriptor_t;
 
+static
+void nfs_readdir_init_array(struct page *page)
+{
+	struct nfs_cache_array *array;
+
+	array = kmap_atomic(page);
+	memset(array, 0, sizeof(struct nfs_cache_array));
+	array->eof_index = -1;
+	kunmap_atomic(array);
+}
+
 /*
  * we are freeing strings created by nfs_add_to_readdir_array()
  */
@@ -181,6 +192,7 @@ void nfs_readdir_clear_array(struct page
 	array = kmap_atomic(page);
 	for (i = 0; i < array->size; i++)
 		kfree(array->array[i].string.name);
+	array->size = 0;
 	kunmap_atomic(array);
 }
 
@@ -580,6 +592,8 @@ int nfs_readdir_xdr_to_array(nfs_readdir
 	int status = -ENOMEM;
 	unsigned int array_size = ARRAY_SIZE(pages);
 
+	nfs_readdir_init_array(page);
+
 	entry.prev_cookie = 0;
 	entry.cookie = desc->last_cookie;
 	entry.eof = 0;
@@ -596,8 +610,6 @@ int nfs_readdir_xdr_to_array(nfs_readdir
 	}
 
 	array = kmap(page);
-	memset(array, 0, sizeof(struct nfs_cache_array));
-	array->eof_index = -1;
 
 	status = nfs_readdir_large_page(pages, array_size);
 	if (status < 0)
@@ -651,6 +663,7 @@ int nfs_readdir_filler(nfs_readdir_descr
 	unlock_page(page);
 	return 0;
  error:
+	nfs_readdir_clear_array(page);
 	unlock_page(page);
 	return ret;
 }


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 58/99] KVM: x86: Don't let userspace set host-reserved cr4 bits
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (56 preceding siblings ...)
  2020-05-20 14:14  8% ` [PATCH 3.16 57/99] sparc32: fix struct ipc64_perm type definition Ben Hutchings
@ 2020-05-20 14:14 10% ` Ben Hutchings
  2020-05-20 14:14 13% ` [PATCH 3.16 59/99] KVM: nVMX: vmread should not set rflags to specify success in case of #PF Ben Hutchings
                   ` (41 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Sean Christopherson, Paolo Bonzini, Jun Nakajima

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Sean Christopherson <sean.j.christopherson@intel.com>

commit b11306b53b2540c6ba068c4deddb6a17d9f8d95b upstream.

Calculate the host-reserved cr4 bits at runtime based on the system's
capabilities (using logic similar to __do_cpuid_func()), and use the
dynamically generated mask for the reserved bit check in kvm_set_cr4()
instead using of the static CR4_RESERVED_BITS define.  This prevents
userspace from "enabling" features in cr4 that are not supported by the
system, e.g. by ignoring KVM_GET_SUPPORTED_CPUID and specifying a bogus
CPUID for the vCPU.

Allowing userspace to set unsupported bits in cr4 can lead to a variety
of undesirable behavior, e.g. failed VM-Enter, and in general increases
KVM's attack surface.  A crafty userspace can even abuse CR4.LA57 to
induce an unchecked #GP on a WRMSR.

On a platform without LA57 support:

  KVM_SET_CPUID2 // CPUID_7_0_ECX.LA57 = 1
  KVM_SET_SREGS  // CR4.LA57 = 1
  KVM_SET_MSRS   // KERNEL_GS_BASE = 0x0004000000000000
  KVM_RUN

leads to a #GP when writing KERNEL_GS_BASE into hardware:

  unchecked MSR access error: WRMSR to 0xc0000102 (tried to write 0x0004000000000000)
  at rIP: 0xffffffffa00f239a (vmx_prepare_switch_to_guest+0x10a/0x1d0 [kvm_intel])
  Call Trace:
   kvm_arch_vcpu_ioctl_run+0x671/0x1c70 [kvm]
   kvm_vcpu_ioctl+0x36b/0x5d0 [kvm]
   do_vfs_ioctl+0xa1/0x620
   ksys_ioctl+0x66/0x70
   __x64_sys_ioctl+0x16/0x20
   do_syscall_64+0x4c/0x170
   entry_SYSCALL_64_after_hwframe+0x44/0xa9
  RIP: 0033:0x7fc08133bf47

Note, the above sequence fails VM-Enter due to invalid guest state.
Userspace can allow VM-Enter to succeed (after the WRMSR #GP) by adding
a KVM_SET_SREGS w/ CR4.LA57=0 after KVM_SET_MSRS, in which case KVM will
technically leak the host's KERNEL_GS_BASE into the guest.  But, as
KERNEL_GS_BASE is a userspace-defined value/address, the leak is largely
benign as a malicious userspace would simply be exposing its own data to
the guest, and attacking a benevolent userspace would require multiple
bugs in the userspace VMM.

Cc: Jun Nakajima <jun.nakajima@intel.com>
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
[bwh: Backported to 3.16:
 - PKE, LA57, and UMIP are totally unsupported and already included in
   CR4_RESERVED_BITS
 - Adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -82,6 +82,8 @@ u64 __read_mostly efer_reserved_bits = ~
 static u64 __read_mostly efer_reserved_bits = ~((u64)EFER_SCE);
 #endif
 
+static u64 __read_mostly cr4_reserved_bits = CR4_RESERVED_BITS;
+
 #define VM_STAT(x) offsetof(struct kvm, stat.x), KVM_STAT_VM
 #define VCPU_STAT(x) offsetof(struct kvm_vcpu, stat.x), KVM_STAT_VCPU
 
@@ -660,13 +662,32 @@ int kvm_set_xcr(struct kvm_vcpu *vcpu, u
 }
 EXPORT_SYMBOL_GPL(kvm_set_xcr);
 
+static u64 kvm_host_cr4_reserved_bits(struct cpuinfo_x86 *c)
+{
+	u64 reserved_bits = CR4_RESERVED_BITS;
+
+	if (!cpu_has(c, X86_FEATURE_XSAVE))
+		reserved_bits |= X86_CR4_OSXSAVE;
+
+	if (!cpu_has(c, X86_FEATURE_SMEP))
+		reserved_bits |= X86_CR4_SMEP;
+
+	if (!cpu_has(c, X86_FEATURE_SMAP))
+		reserved_bits |= X86_CR4_SMAP;
+
+	if (!cpu_has(c, X86_FEATURE_FSGSBASE))
+		reserved_bits |= X86_CR4_FSGSBASE;
+
+	return reserved_bits;
+}
+
 int kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
 {
 	unsigned long old_cr4 = kvm_read_cr4(vcpu);
 	unsigned long pdptr_bits = X86_CR4_PGE | X86_CR4_PSE | X86_CR4_PAE |
 				   X86_CR4_SMEP | X86_CR4_SMAP;
 
-	if (cr4 & CR4_RESERVED_BITS)
+	if (cr4 & cr4_reserved_bits)
 		return 1;
 
 	if (!guest_cpuid_has_xsave(vcpu) && (cr4 & X86_CR4_OSXSAVE))
@@ -7220,6 +7241,8 @@ int kvm_arch_hardware_setup(void)
 	if (r != 0)
 		return r;
 
+	cr4_reserved_bits = kvm_host_cr4_reserved_bits(&boot_cpu_data);
+
 	kvm_init_msr_list();
 	return 0;
 }


^ permalink raw reply	[relevance 10%]

* [PATCH 3.16 75/99] net_sched: ematch: reject invalid TCF_EM_SIMPLE
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (73 preceding siblings ...)
  2020-05-20 14:14  9% ` [PATCH 3.16 74/99] CIFS: Fix task struct use-after-free on reconnect Ben Hutchings
@ 2020-05-20 14:14 11% ` Ben Hutchings
  2020-05-20 14:14 12% ` [PATCH 3.16 76/99] KVM: x86: Protect x86_decode_insn from Spectre-v1/L1TF attacks Ben Hutchings
                   ` (24 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, David S. Miller, Eric Dumazet,
	syzbot+03c4738ed29d5d366ddf, Cong Wang

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Eric Dumazet <edumazet@google.com>

commit 55cd9f67f1e45de8517cdaab985fb8e56c0bc1d8 upstream.

It is possible for malicious userspace to set TCF_EM_SIMPLE bit
even for matches that should not have this bit set.

This can fool two places using tcf_em_is_simple()

1) tcf_em_tree_destroy() -> memory leak of em->data
   if ops->destroy() is NULL

2) tcf_em_tree_dump() wrongly report/leak 4 low-order bytes
   of a kernel pointer.

BUG: memory leak
unreferenced object 0xffff888121850a40 (size 32):
  comm "syz-executor927", pid 7193, jiffies 4294941655 (age 19.840s)
  hex dump (first 32 bytes):
    00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00  ................
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
  backtrace:
    [<00000000f67036ea>] kmemleak_alloc_recursive include/linux/kmemleak.h:43 [inline]
    [<00000000f67036ea>] slab_post_alloc_hook mm/slab.h:586 [inline]
    [<00000000f67036ea>] slab_alloc mm/slab.c:3320 [inline]
    [<00000000f67036ea>] __do_kmalloc mm/slab.c:3654 [inline]
    [<00000000f67036ea>] __kmalloc_track_caller+0x165/0x300 mm/slab.c:3671
    [<00000000fab0cc8e>] kmemdup+0x27/0x60 mm/util.c:127
    [<00000000d9992e0a>] kmemdup include/linux/string.h:453 [inline]
    [<00000000d9992e0a>] em_nbyte_change+0x5b/0x90 net/sched/em_nbyte.c:32
    [<000000007e04f711>] tcf_em_validate net/sched/ematch.c:241 [inline]
    [<000000007e04f711>] tcf_em_tree_validate net/sched/ematch.c:359 [inline]
    [<000000007e04f711>] tcf_em_tree_validate+0x332/0x46f net/sched/ematch.c:300
    [<000000007a769204>] basic_set_parms net/sched/cls_basic.c:157 [inline]
    [<000000007a769204>] basic_change+0x1d7/0x5f0 net/sched/cls_basic.c:219
    [<00000000e57a5997>] tc_new_tfilter+0x566/0xf70 net/sched/cls_api.c:2104
    [<0000000074b68559>] rtnetlink_rcv_msg+0x3b2/0x4b0 net/core/rtnetlink.c:5415
    [<00000000b7fe53fb>] netlink_rcv_skb+0x61/0x170 net/netlink/af_netlink.c:2477
    [<00000000e83a40d0>] rtnetlink_rcv+0x1d/0x30 net/core/rtnetlink.c:5442
    [<00000000d62ba933>] netlink_unicast_kernel net/netlink/af_netlink.c:1302 [inline]
    [<00000000d62ba933>] netlink_unicast+0x223/0x310 net/netlink/af_netlink.c:1328
    [<0000000088070f72>] netlink_sendmsg+0x2c0/0x570 net/netlink/af_netlink.c:1917
    [<00000000f70b15ea>] sock_sendmsg_nosec net/socket.c:639 [inline]
    [<00000000f70b15ea>] sock_sendmsg+0x54/0x70 net/socket.c:659
    [<00000000ef95a9be>] ____sys_sendmsg+0x2d0/0x300 net/socket.c:2330
    [<00000000b650f1ab>] ___sys_sendmsg+0x8a/0xd0 net/socket.c:2384
    [<0000000055bfa74a>] __sys_sendmsg+0x80/0xf0 net/socket.c:2417
    [<000000002abac183>] __do_sys_sendmsg net/socket.c:2426 [inline]
    [<000000002abac183>] __se_sys_sendmsg net/socket.c:2424 [inline]
    [<000000002abac183>] __x64_sys_sendmsg+0x23/0x30 net/socket.c:2424

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reported-by: syzbot+03c4738ed29d5d366ddf@syzkaller.appspotmail.com
Cc: Cong Wang <xiyou.wangcong@gmail.com>
Acked-by: Cong Wang <xiyou.wangcong@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 net/sched/ematch.c | 3 +++
 1 file changed, 3 insertions(+)

--- a/net/sched/ematch.c
+++ b/net/sched/ematch.c
@@ -241,6 +241,9 @@ static int tcf_em_validate(struct tcf_pr
 			goto errout;
 
 		if (em->ops->change) {
+			err = -EINVAL;
+			if (em_hdr->flags & TCF_EM_SIMPLE)
+				goto errout;
 			err = em->ops->change(tp, data, data_len, em);
 			if (err < 0)
 				goto errout;


^ permalink raw reply	[relevance 11%]

* [PATCH 3.16 96/99] NFS: Directory page cache pages need to be locked when read
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (94 preceding siblings ...)
  2020-05-20 14:15  9% ` [PATCH 3.16 95/99] NFS: Fix memory leaks and corruption in readdir Ben Hutchings
@ 2020-05-20 14:15 11% ` Ben Hutchings
  2020-05-20 14:15  9% ` [PATCH 3.16 97/99] cifs: fail i/o on soft mounts if sessionsetup errors out Ben Hutchings
                   ` (3 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:15 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Anna Schumaker, Trond Myklebust,
	Trond Myklebust, Benjamin Coddington

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Trond Myklebust <trondmy@gmail.com>

commit 114de38225d9b300f027e2aec9afbb6e0def154b upstream.

When a NFS directory page cache page is removed from the page cache,
its contents are freed through a call to nfs_readdir_clear_array().
To prevent the removal of the page cache entry until after we've
finished reading it, we must take the page lock.

Fixes: 11de3b11e08c ("NFS: Fix a memory leak in nfs_readdir")
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Reviewed-by: Benjamin Coddington <bcodding@redhat.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 fs/nfs/dir.c | 30 +++++++++++++++++++-----------
 1 file changed, 19 insertions(+), 11 deletions(-)

--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -671,8 +671,6 @@ int nfs_readdir_filler(nfs_readdir_descr
 static
 void cache_page_release(nfs_readdir_descriptor_t *desc)
 {
-	if (!desc->page->mapping)
-		nfs_readdir_clear_array(desc->page);
 	page_cache_release(desc->page);
 	desc->page = NULL;
 }
@@ -686,19 +684,28 @@ struct page *get_cache_page(nfs_readdir_
 
 /*
  * Returns 0 if desc->dir_cookie was found on page desc->page_index
+ * and locks the page to prevent removal from the page cache.
  */
 static
-int find_cache_page(nfs_readdir_descriptor_t *desc)
+int find_and_lock_cache_page(nfs_readdir_descriptor_t *desc)
 {
 	int res;
 
 	desc->page = get_cache_page(desc);
 	if (IS_ERR(desc->page))
 		return PTR_ERR(desc->page);
-
-	res = nfs_readdir_search_array(desc);
+	res = lock_page_killable(desc->page);
 	if (res != 0)
-		cache_page_release(desc);
+		goto error;
+	res = -EAGAIN;
+	if (desc->page->mapping != NULL) {
+		res = nfs_readdir_search_array(desc);
+		if (res == 0)
+			return 0;
+	}
+	unlock_page(desc->page);
+error:
+	cache_page_release(desc);
 	return res;
 }
 
@@ -713,7 +720,7 @@ int readdir_search_pagecache(nfs_readdir
 		desc->last_cookie = 0;
 	}
 	do {
-		res = find_cache_page(desc);
+		res = find_and_lock_cache_page(desc);
 	} while (res == -EAGAIN);
 	return res;
 }
@@ -752,7 +759,6 @@ int nfs_do_filldir(nfs_readdir_descripto
 		desc->eof = 1;
 
 	kunmap(desc->page);
-	cache_page_release(desc);
 	dfprintk(DIRCACHE, "NFS: nfs_do_filldir() filling ended @ cookie %Lu; returning = %d\n",
 			(unsigned long long)*desc->dir_cookie, res);
 	return res;
@@ -798,13 +804,13 @@ int uncached_readdir(nfs_readdir_descrip
 
 	status = nfs_do_filldir(desc);
 
+ out_release:
+	nfs_readdir_clear_array(desc->page);
+	cache_page_release(desc);
  out:
 	dfprintk(DIRCACHE, "NFS: %s: returns %d\n",
 			__func__, status);
 	return status;
- out_release:
-	cache_page_release(desc);
-	goto out;
 }
 
 /* The file offset position represents the dirent entry number.  A
@@ -870,6 +876,8 @@ static int nfs_readdir(struct file *file
 			break;
 
 		res = nfs_do_filldir(desc);
+		unlock_page(desc->page);
+		cache_page_release(desc);
 		if (res < 0)
 			break;
 	} while (!desc->eof);


^ permalink raw reply	[relevance 11%]

* [PATCH 3.16 59/99] KVM: nVMX: vmread should not set rflags to specify success in case of #PF
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (57 preceding siblings ...)
  2020-05-20 14:14 10% ` [PATCH 3.16 58/99] KVM: x86: Don't let userspace set host-reserved cr4 bits Ben Hutchings
@ 2020-05-20 14:14 13% ` Ben Hutchings
  2020-05-20 14:14  9% ` [PATCH 3.16 60/99] x86: kvm: avoid unused variable warning Ben Hutchings
                   ` (40 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Miaohe Lin, Paolo Bonzini,
	Sean Christopherson, Liran Alon

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Miaohe Lin <linmiaohe@huawei.com>

commit a4d956b9390418623ae5d07933e2679c68b6f83c upstream.

In case writing to vmread destination operand result in a #PF, vmread
should not call nested_vmx_succeed() to set rflags to specify success.
Similar to as done in VMPTRST (See handle_vmptrst()).

Reviewed-by: Liran Alon <liran.alon@oracle.com>
Signed-off-by: Miaohe Lin <linmiaohe@huawei.com>
Reviewed-by: Sean Christopherson <sean.j.christopherson@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
[bwh: Backported to 3.16: adjust filename, context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 arch/x86/kvm/vmx.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -6455,8 +6455,10 @@ static int handle_vmread(struct kvm_vcpu
 		/* _system ok, as nested_vmx_check_permission verified cpl=0 */
 		if (kvm_write_guest_virt_system(vcpu, gva, &field_value,
 						(is_long_mode(vcpu) ? 8 : 4),
-						&e))
+						&e)) {
 			kvm_inject_page_fault(vcpu, &e);
+			return 1;
+		}
 	}
 
 	nested_vmx_succeed(vcpu);


^ permalink raw reply	[relevance 13%]

* [PATCH 3.16 67/99] KVM: PPC: Book3S PR: Free shared page if mmu initialization fails
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (65 preceding siblings ...)
  2020-05-20 14:14  9% ` [PATCH 3.16 66/99] KVM: PPC: Book3S HV: Uninit vCPU if vcore creation fails Ben Hutchings
@ 2020-05-20 14:14  9% ` Ben Hutchings
  2020-05-20 14:14 13% ` [PATCH 3.16 68/99] KVM: x86: Free wbinvd_dirty_mask if vCPU creation fails Ben Hutchings
                   ` (32 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Greg Kurz, Sean Christopherson,
	Paolo Bonzini, Paul Mackerras

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Sean Christopherson <sean.j.christopherson@intel.com>

commit cb10bf9194f4d2c5d830eddca861f7ca0fecdbb4 upstream.

Explicitly free the shared page if kvmppc_mmu_init() fails during
kvmppc_core_vcpu_create(), as the page is freed only in
kvmppc_core_vcpu_free(), which is not reached via kvm_vcpu_uninit().

Fixes: 96bc451a15329 ("KVM: PPC: Introduce shared page")
Reviewed-by: Greg Kurz <groug@kaod.org>
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
Acked-by: Paul Mackerras <paulus@ozlabs.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 arch/powerpc/kvm/book3s_pr.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

--- a/arch/powerpc/kvm/book3s_pr.c
+++ b/arch/powerpc/kvm/book3s_pr.c
@@ -1346,10 +1346,12 @@ static struct kvm_vcpu *kvmppc_core_vcpu
 
 	err = kvmppc_mmu_init(vcpu);
 	if (err < 0)
-		goto uninit_vcpu;
+		goto free_shared_page;
 
 	return vcpu;
 
+free_shared_page:
+	free_page((unsigned long)vcpu->arch.shared);
 uninit_vcpu:
 	kvm_vcpu_uninit(vcpu);
 free_shadow_vcpu:


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 94/99] nfs: use kmap/kunmap directly
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (92 preceding siblings ...)
  2020-05-20 14:15  9% ` [PATCH 3.16 93/99] kconfig: fix broken dependency in randconfig-generated .config Ben Hutchings
@ 2020-05-20 14:15  8% ` Ben Hutchings
  2020-05-20 14:15  9% ` [PATCH 3.16 95/99] NFS: Fix memory leaks and corruption in readdir Ben Hutchings
                   ` (5 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:15 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Fabian Frederick, Trond Myklebust

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Fabian Frederick <fabf@skynet.be>

commit 0795bf8357c1887e2a95e6e4f5b89d0896a0d929 upstream.

This patch removes useless nfs_readdir_get_array() and
nfs_readdir_release_array() as suggested by Trond Myklebust

nfs_readdir() calls nfs_revalidate_mapping() before
readdir_search_pagecache() , nfs_do_filldir(), uncached_readdir()
so mapping should be correct.

While kmap() can't fail, all subsequent error checks were removed
as well as unused labels.

Signed-off-by: Fabian Frederick <fabf@skynet.be>
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 fs/nfs/dir.c | 67 ++++++++++------------------------------------------
 1 file changed, 12 insertions(+), 55 deletions(-)

--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -170,27 +170,6 @@ typedef struct {
 } nfs_readdir_descriptor_t;
 
 /*
- * The caller is responsible for calling nfs_readdir_release_array(page)
- */
-static
-struct nfs_cache_array *nfs_readdir_get_array(struct page *page)
-{
-	void *ptr;
-	if (page == NULL)
-		return ERR_PTR(-EIO);
-	ptr = kmap(page);
-	if (ptr == NULL)
-		return ERR_PTR(-ENOMEM);
-	return ptr;
-}
-
-static
-void nfs_readdir_release_array(struct page *page)
-{
-	kunmap(page);
-}
-
-/*
  * we are freeing strings created by nfs_add_to_readdir_array()
  */
 static
@@ -229,13 +208,10 @@ int nfs_readdir_make_qstr(struct qstr *s
 static
 int nfs_readdir_add_to_array(struct nfs_entry *entry, struct page *page)
 {
-	struct nfs_cache_array *array = nfs_readdir_get_array(page);
+	struct nfs_cache_array *array = kmap(page);
 	struct nfs_cache_array_entry *cache_entry;
 	int ret;
 
-	if (IS_ERR(array))
-		return PTR_ERR(array);
-
 	cache_entry = &array->array[array->size];
 
 	/* Check that this entry lies within the page bounds */
@@ -254,7 +230,7 @@ int nfs_readdir_add_to_array(struct nfs_
 	if (entry->eof != 0)
 		array->eof_index = array->size;
 out:
-	nfs_readdir_release_array(page);
+	kunmap(page);
 	return ret;
 }
 
@@ -343,11 +319,7 @@ int nfs_readdir_search_array(nfs_readdir
 	struct nfs_cache_array *array;
 	int status;
 
-	array = nfs_readdir_get_array(desc->page);
-	if (IS_ERR(array)) {
-		status = PTR_ERR(array);
-		goto out;
-	}
+	array = kmap(desc->page);
 
 	if (*desc->dir_cookie == 0)
 		status = nfs_readdir_search_for_pos(array, desc);
@@ -359,8 +331,7 @@ int nfs_readdir_search_array(nfs_readdir
 		desc->current_index += array->size;
 		desc->page_index++;
 	}
-	nfs_readdir_release_array(desc->page);
-out:
+	kunmap(desc->page);
 	return status;
 }
 
@@ -551,13 +522,10 @@ int nfs_readdir_page_filler(nfs_readdir_
 	} while (!entry->eof);
 
 	if (count == 0 || (status == -EBADCOOKIE && entry->eof != 0)) {
-		array = nfs_readdir_get_array(page);
-		if (!IS_ERR(array)) {
-			array->eof_index = array->size;
-			status = 0;
-			nfs_readdir_release_array(page);
-		} else
-			status = PTR_ERR(array);
+		array = kmap(page);
+		array->eof_index = array->size;
+		status = 0;
+		kunmap(page);
 	}
 
 	put_page(scratch);
@@ -627,11 +595,7 @@ int nfs_readdir_xdr_to_array(nfs_readdir
 		goto out;
 	}
 
-	array = nfs_readdir_get_array(page);
-	if (IS_ERR(array)) {
-		status = PTR_ERR(array);
-		goto out_label_free;
-	}
+	array = kmap(page);
 	memset(array, 0, sizeof(struct nfs_cache_array));
 	array->eof_index = -1;
 
@@ -655,8 +619,7 @@ int nfs_readdir_xdr_to_array(nfs_readdir
 
 	nfs_readdir_free_large_page(pages_ptr, pages, array_size);
 out_release_array:
-	nfs_readdir_release_array(page);
-out_label_free:
+	kunmap(page);
 	nfs4_label_free(entry.label);
 out:
 	nfs_free_fattr(entry.fattr);
@@ -754,12 +717,7 @@ int nfs_do_filldir(nfs_readdir_descripto
 	struct nfs_cache_array *array = NULL;
 	struct nfs_open_dir_context *ctx = file->private_data;
 
-	array = nfs_readdir_get_array(desc->page);
-	if (IS_ERR(array)) {
-		res = PTR_ERR(array);
-		goto out;
-	}
-
+	array = kmap(desc->page);
 	for (i = desc->cache_entry_index; i < array->size; i++) {
 		struct nfs_cache_array_entry *ent;
 
@@ -780,8 +738,7 @@ int nfs_do_filldir(nfs_readdir_descripto
 	if (array->eof_index >= 0)
 		desc->eof = 1;
 
-	nfs_readdir_release_array(desc->page);
-out:
+	kunmap(desc->page);
 	cache_page_release(desc);
 	dfprintk(DIRCACHE, "NFS: nfs_do_filldir() filling ended @ cookie %Lu; returning = %d\n",
 			(unsigned long long)*desc->dir_cookie, res);


^ permalink raw reply	[relevance 8%]

* [PATCH 3.16 84/99] KVM: Check for a bad hva before dropping into the ghc slow path
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (82 preceding siblings ...)
  2020-05-20 14:14  9% ` [PATCH 3.16 83/99] KVM: x86: Protect DR-based index computations from Spectre-v1/L1TF attacks Ben Hutchings
@ 2020-05-20 14:14 11% ` Ben Hutchings
  2020-05-20 14:14 11% ` [PATCH 3.16 85/99] of: Add OF_DMA_DEFAULT_COHERENT & select it on powerpc Ben Hutchings
                   ` (15 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Sean Christopherson, Jim Mattson,
	Paolo Bonzini, Andrew Honig

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Sean Christopherson <sean.j.christopherson@intel.com>

commit fcfbc617547fc6d9552cb6c1c563b6a90ee98085 upstream.

When reading/writing using the guest/host cache, check for a bad hva
before checking for a NULL memslot, which triggers the slow path for
handing cross-page accesses.  Because the memslot is nullified on error
by __kvm_gfn_to_hva_cache_init(), if the bad hva is encountered after
crossing into a new page, then the kvm_{read,write}_guest() slow path
could potentially write/access the first chunk prior to detecting the
bad hva.

Arguably, performing a partial access is semantically correct from an
architectural perspective, but that behavior is certainly not intended.
In the original implementation, memslot was not explicitly nullified
and therefore the partial access behavior varied based on whether the
memslot itself was null, or if the hva was simply bad.  The current
behavior was introduced as a seemingly unintentional side effect in
commit f1b9dd5eb86c ("kvm: Disallow wraparound in
kvm_gfn_to_hva_cache_init"), which justified the change with "since some
callers don't check the return code from this function, it sit seems
prudent to clear ghc->memslot in the event of an error".

Regardless of intent, the partial access is dependent on _not_ checking
the result of the cache initialization, which is arguably a bug in its
own right, at best simply weird.

Fixes: 8f964525a121 ("KVM: Allow cross page reads and writes from cached translations.")
Cc: Jim Mattson <jmattson@google.com>
Cc: Andrew Honig <ahonig@google.com>
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 virt/kvm/kvm_main.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -1596,12 +1596,12 @@ int kvm_write_guest_cached(struct kvm *k
 	if (slots->generation != ghc->generation)
 		kvm_gfn_to_hva_cache_init(kvm, ghc, ghc->gpa, ghc->len);
 
-	if (unlikely(!ghc->memslot))
-		return kvm_write_guest(kvm, ghc->gpa, data, len);
-
 	if (kvm_is_error_hva(ghc->hva))
 		return -EFAULT;
 
+	if (unlikely(!ghc->memslot))
+		return kvm_write_guest(kvm, ghc->gpa, data, len);
+
 	r = __copy_to_user((void __user *)ghc->hva, data, len);
 	if (r)
 		return -EFAULT;
@@ -1622,12 +1622,12 @@ int kvm_read_guest_cached(struct kvm *kv
 	if (slots->generation != ghc->generation)
 		kvm_gfn_to_hva_cache_init(kvm, ghc, ghc->gpa, ghc->len);
 
-	if (unlikely(!ghc->memslot))
-		return kvm_read_guest(kvm, ghc->gpa, data, len);
-
 	if (kvm_is_error_hva(ghc->hva))
 		return -EFAULT;
 
+	if (unlikely(!ghc->memslot))
+		return kvm_read_guest(kvm, ghc->gpa, data, len);
+
 	r = __copy_from_user(data, (void __user *)ghc->hva, len);
 	if (r)
 		return -EFAULT;


^ permalink raw reply	[relevance 11%]

* [PATCH 3.16 45/99] PCI: Don't disable bridge BARs when assigning bus resources
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (43 preceding siblings ...)
  2020-05-20 14:14 11% ` [PATCH 3.16 44/99] efi/x86: Map the entire EFI vendor string before copying it Ben Hutchings
@ 2020-05-20 14:14  7% ` Ben Hutchings
  2020-05-20 14:14 13% ` [PATCH 3.16 46/99] power: supply: sbs-battery: Fix a signedness bug in sbs_get_battery_capacity() Ben Hutchings
                   ` (54 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Logan Gunthorpe, Bjorn Helgaas, Kit Chow

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Logan Gunthorpe <logang@deltatee.com>

commit 9db8dc6d0785225c42a37be7b44d1b07b31b8957 upstream.

Some PCI bridges implement BARs in addition to bridge windows.  For
example, here's a PLX switch:

  04:00.0 PCI bridge: PLX Technology, Inc. PEX 8724 24-Lane, 6-Port PCI
            Express Gen 3 (8 GT/s) Switch, 19 x 19mm FCBGA (rev ca)
	    (prog-if 00 [Normal decode])
      Flags: bus master, fast devsel, latency 0, IRQ 30, NUMA node 0
      Memory at 90a00000 (32-bit, non-prefetchable) [size=256K]
      Bus: primary=04, secondary=05, subordinate=0a, sec-latency=0
      I/O behind bridge: 00002000-00003fff
      Memory behind bridge: 90000000-909fffff
      Prefetchable memory behind bridge: 0000380000800000-0000380000bfffff

Previously, when the kernel assigned resource addresses (with the
pci=realloc command line parameter, for example) it could clear the struct
resource corresponding to the BAR.  When this happened, lspci would report
this BAR as "ignored":

   Region 0: Memory at <ignored> (32-bit, non-prefetchable) [size=256K]

This is because the kernel reports a zero start address and zero flags
in the corresponding sysfs resource file and in /proc/bus/pci/devices.
Investigation with 'lspci -x', however, shows the BIOS-assigned address
will still be programmed in the device's BAR registers.

It's clearly a bug that the kernel lost track of the BAR value, but in most
cases, this still won't result in a visible issue because nothing uses the
memory, so nothing is affected.  However, when an IOMMU is in use, it will
not reserve this space in the IOVA because the kernel no longer thinks the
range is valid.  (See dmar_init_reserved_ranges() for the Intel
implementation of this.)

Without the proper reserved range, a DMA mapping may allocate an IOVA that
matches a bridge BAR, which results in DMA accesses going to the BAR
instead of the intended RAM.

The problem was in pci_assign_unassigned_root_bus_resources().  When any
resource from a bridge device fails to get assigned, the code set the
resource's flags to zero.  This makes sense for bridge windows, as they
will be re-enabled later, but for regular BARs, it makes the kernel
permanently lose track of the fact that they decode address space.

Change pci_assign_unassigned_root_bus_resources() and
pci_assign_unassigned_bridge_resources() so they only clear "res->flags"
for bridge *windows*, not bridge BARs.

Fixes: da7822e5ad71 ("PCI: update bridge resources to get more big ranges when allocating space (again)")
Link: https://lore.kernel.org/r/20200108213208.4612-1-logang@deltatee.com
[bhelgaas: commit log, check for pci_is_bridge()]
Reported-by: Kit Chow <kchow@gigaio.com>
Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/pci/setup-bus.c | 20 ++++++++++++++++----
 1 file changed, 16 insertions(+), 4 deletions(-)

--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -1650,12 +1650,18 @@ again:
 	/* restore size and flags */
 	list_for_each_entry(fail_res, &fail_head, list) {
 		struct resource *res = fail_res->res;
+		int idx;
 
 		res->start = fail_res->start;
 		res->end = fail_res->end;
 		res->flags = fail_res->flags;
-		if (fail_res->dev->subordinate)
-			res->flags = 0;
+
+		if (pci_is_bridge(fail_res->dev)) {
+			idx = res - &fail_res->dev->resource[0];
+			if (idx >= PCI_BRIDGE_RESOURCES &&
+			    idx <= PCI_BRIDGE_RESOURCE_END)
+				res->flags = 0;
+		}
 	}
 	free_list(&fail_head);
 
@@ -1716,12 +1722,18 @@ again:
 	/* restore size and flags */
 	list_for_each_entry(fail_res, &fail_head, list) {
 		struct resource *res = fail_res->res;
+		int idx;
 
 		res->start = fail_res->start;
 		res->end = fail_res->end;
 		res->flags = fail_res->flags;
-		if (fail_res->dev->subordinate)
-			res->flags = 0;
+
+		if (pci_is_bridge(fail_res->dev)) {
+			idx = res - &fail_res->dev->resource[0];
+			if (idx >= PCI_BRIDGE_RESOURCES &&
+			    idx <= PCI_BRIDGE_RESOURCE_END)
+				res->flags = 0;
+		}
 	}
 	free_list(&fail_head);
 


^ permalink raw reply	[relevance 7%]

* [PATCH 3.16 87/99] mm/mempolicy.c: fix out of bounds write in mpol_parse_str()
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (85 preceding siblings ...)
  2020-05-20 14:14  8% ` [PATCH 3.16 86/99] Btrfs: fix race between adding and putting tree mod seq elements and nodes Ben Hutchings
@ 2020-05-20 14:14  8% ` Ben Hutchings
  2020-05-20 14:14 11% ` [PATCH 3.16 88/99] media/v4l2-core: set pages dirty upon releasing DMA buffers Ben Hutchings
                   ` (12 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Vlastimil Babka, Hugh Dickins,
	Lee Schermerhorn, Linus Torvalds, syzbot+e64a13c5369a194d67df,
	Andrea Arcangeli, Michal Hocko, Dan Carpenter

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Dan Carpenter <dan.carpenter@oracle.com>

commit c7a91bc7c2e17e0a9c8b9745a2cb118891218fd1 upstream.

What we are trying to do is change the '=' character to a NUL terminator
and then at the end of the function we restore it back to an '='.  The
problem is there are two error paths where we jump to the end of the
function before we have replaced the '=' with NUL.

We end up putting the '=' in the wrong place (possibly one element
before the start of the buffer).

Link: http://lkml.kernel.org/r/20200115055426.vdjwvry44nfug7yy@kili.mountain
Reported-by: syzbot+e64a13c5369a194d67df@syzkaller.appspotmail.com
Fixes: 095f1fc4ebf3 ("mempolicy: rework shmem mpol parsing and display")
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Acked-by: Vlastimil Babka <vbabka@suse.cz>
Dmitry Vyukov <dvyukov@google.com>
Cc: Michal Hocko <mhocko@kernel.org>
Cc: Dan Carpenter <dan.carpenter@oracle.com>
Cc: Lee Schermerhorn <lee.schermerhorn@hp.com>
Cc: Andrea Arcangeli <aarcange@redhat.com>
Cc: Hugh Dickins <hughd@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 mm/mempolicy.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -2687,6 +2687,9 @@ int mpol_parse_str(char *str, struct mem
 	char *flags = strchr(str, '=');
 	int err = 1;
 
+	if (flags)
+		*flags++ = '\0';	/* terminate mode string */
+
 	if (nodelist) {
 		/* NUL-terminate mode or flags string */
 		*nodelist++ = '\0';
@@ -2697,9 +2700,6 @@ int mpol_parse_str(char *str, struct mem
 	} else
 		nodes_clear(nodes);
 
-	if (flags)
-		*flags++ = '\0';	/* terminate mode string */
-
 	for (mode = 0; mode < MPOL_MAX; mode++) {
 		if (!strcmp(str, policy_modes[mode])) {
 			break;


^ permalink raw reply	[relevance 8%]

* [PATCH 3.16 55/99] jbd2: clear JBD2_ABORT flag before journal_reset to update log tail info when load journal
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (53 preceding siblings ...)
  2020-05-20 14:14  8% ` [PATCH 3.16 54/99] x86/cpu: Update cached HLE state on write to TSX_CTRL_CPUID_CLEAR Ben Hutchings
@ 2020-05-20 14:14  9% ` Ben Hutchings
  2020-05-20 14:14 10% ` [PATCH 3.16 56/99] KVM: arm64: Only sign-extend MMIO up to register width Ben Hutchings
                   ` (44 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable; +Cc: akpm, Denis Kirjanov, Theodore Ts'o, Kai Li

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Kai Li <li.kai4@h3c.com>

commit a09decff5c32060639a685581c380f51b14e1fc2 upstream.

If the journal is dirty when the filesystem is mounted, jbd2 will replay
the journal but the journal superblock will not be updated by
journal_reset() because JBD2_ABORT flag is still set (it was set in
journal_init_common()). This is problematic because when a new transaction
is then committed, it will be recorded in block 1 (journal->j_tail was set
to 1 in journal_reset()). If unclean shutdown happens again before the
journal superblock is updated, the new recorded transaction will not be
replayed during the next mount (because of stale sb->s_start and
sb->s_sequence values) which can lead to filesystem corruption.

Fixes: 85e0c4e89c1b ("jbd2: if the journal is aborted then don't allow update of the log tail")
Signed-off-by: Kai Li <li.kai4@h3c.com>
Link: https://lore.kernel.org/r/20200111022542.5008-1-li.kai4@h3c.com
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 fs/jbd2/journal.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

--- a/fs/jbd2/journal.c
+++ b/fs/jbd2/journal.c
@@ -1674,6 +1674,11 @@ int jbd2_journal_load(journal_t *journal
 		       journal->j_devname);
 		return -EIO;
 	}
+	/*
+	 * clear JBD2_ABORT flag initialized in journal_init_common
+	 * here to update log tail information with the newest seq.
+	 */
+	journal->j_flags &= ~JBD2_ABORT;
 
 	/* OK, we've finished with the dynamic journal bits:
 	 * reinitialise the dynamic contents of the superblock in memory
@@ -1681,7 +1686,6 @@ int jbd2_journal_load(journal_t *journal
 	if (journal_reset(journal))
 		goto recovery_error;
 
-	journal->j_flags &= ~JBD2_ABORT;
 	journal->j_flags |= JBD2_LOADED;
 	return 0;
 


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 57/99] sparc32: fix struct ipc64_perm type definition
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (55 preceding siblings ...)
  2020-05-20 14:14 10% ` [PATCH 3.16 56/99] KVM: arm64: Only sign-extend MMIO up to register width Ben Hutchings
@ 2020-05-20 14:14  8% ` Ben Hutchings
  2020-05-20 14:14 10% ` [PATCH 3.16 58/99] KVM: x86: Don't let userspace set host-reserved cr4 bits Ben Hutchings
                   ` (42 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Dmitry V . Levin, Arnd Bergmann,
	Rich Felker, libc-alpha, David S. Miller, Sam Ravnborg

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Arnd Bergmann <arnd@arndb.de>

commit 34ca70ef7d3a9fa7e89151597db5e37ae1d429b4 upstream.

As discussed in the strace issue tracker, it appears that the sparc32
sysvipc support has been broken for the past 11 years. It was however
working in compat mode, which is how it must have escaped most of the
regular testing.

The problem is that a cleanup patch inadvertently changed the uid/gid
fields in struct ipc64_perm from 32-bit types to 16-bit types in uapi
headers.

Both glibc and uclibc-ng still use the original types, so they should
work fine with compat mode, but not natively.  Change the definitions
to use __kernel_uid32_t and __kernel_gid32_t again.

Fixes: 83c86984bff2 ("sparc: unify ipcbuf.h")
Link: https://github.com/strace/strace/issues/116
Cc: Sam Ravnborg <sam@ravnborg.org>
Cc: "Dmitry V . Levin" <ldv@altlinux.org>
Cc: Rich Felker <dalias@libc.org>
Cc: libc-alpha@sourceware.org
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 arch/sparc/include/uapi/asm/ipcbuf.h | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

--- a/arch/sparc/include/uapi/asm/ipcbuf.h
+++ b/arch/sparc/include/uapi/asm/ipcbuf.h
@@ -14,19 +14,19 @@
 
 struct ipc64_perm
 {
-	__kernel_key_t	key;
-	__kernel_uid_t	uid;
-	__kernel_gid_t	gid;
-	__kernel_uid_t	cuid;
-	__kernel_gid_t	cgid;
+	__kernel_key_t		key;
+	__kernel_uid32_t	uid;
+	__kernel_gid32_t	gid;
+	__kernel_uid32_t	cuid;
+	__kernel_gid32_t	cgid;
 #ifndef __arch64__
-	unsigned short	__pad0;
+	unsigned short		__pad0;
 #endif
-	__kernel_mode_t	mode;
-	unsigned short	__pad1;
-	unsigned short	seq;
-	unsigned long long __unused1;
-	unsigned long long __unused2;
+	__kernel_mode_t		mode;
+	unsigned short		__pad1;
+	unsigned short		seq;
+	unsigned long long	__unused1;
+	unsigned long long	__unused2;
 };
 
 #endif /* __SPARC_IPCBUF_H */


^ permalink raw reply	[relevance 8%]

* [PATCH 3.16 85/99] of: Add OF_DMA_DEFAULT_COHERENT & select it on powerpc
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (83 preceding siblings ...)
  2020-05-20 14:14 11% ` [PATCH 3.16 84/99] KVM: Check for a bad hva before dropping into the ghc slow path Ben Hutchings
@ 2020-05-20 14:14 11% ` Ben Hutchings
  2020-05-20 14:14  8% ` [PATCH 3.16 86/99] Btrfs: fix race between adding and putting tree mod seq elements and nodes Ben Hutchings
                   ` (14 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Christian Zigotzky, Ulf Hansson,
	Michael Ellerman, Rob Herring

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Michael Ellerman <mpe@ellerman.id.au>

commit dabf6b36b83a18d57e3d4b9d50544ed040d86255 upstream.

There's an OF helper called of_dma_is_coherent(), which checks if a
device has a "dma-coherent" property to see if the device is coherent
for DMA.

But on some platforms devices are coherent by default, and on some
platforms it's not possible to update existing device trees to add the
"dma-coherent" property.

So add a Kconfig symbol to allow arch code to tell
of_dma_is_coherent() that devices are coherent by default, regardless
of the presence of the property.

Select that symbol on powerpc when NOT_COHERENT_CACHE is not set, ie.
when the system has a coherent cache.

Fixes: 92ea637edea3 ("of: introduce of_dma_is_coherent() helper")
Reported-by: Christian Zigotzky <chzigotzky@xenosoft.de>
Tested-by: Christian Zigotzky <chzigotzky@xenosoft.de>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
Signed-off-by: Rob Herring <robh@kernel.org>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 arch/powerpc/Kconfig | 1 +
 drivers/of/Kconfig   | 4 ++++
 drivers/of/address.c | 6 +++++-
 3 files changed, 10 insertions(+), 1 deletion(-)

--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -89,6 +89,7 @@ config PPC
 	select ARCH_MIGHT_HAVE_PC_SERIO
 	select BINFMT_ELF
 	select OF
+	select OF_DMA_DEFAULT_COHERENT		if !NOT_COHERENT_CACHE
 	select OF_EARLY_FLATTREE
 	select OF_RESERVED_MEM
 	select HAVE_FTRACE_MCOUNT_RECORD
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -78,4 +78,8 @@ config OF_RESERVED_MEM
 	help
 	  Helpers to allow for reservation of memory regions
 
+config OF_DMA_DEFAULT_COHERENT
+	# arches should select this if DMA is coherent by default for OF devices
+	bool
+
 endmenu # OF
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -812,12 +812,16 @@ EXPORT_SYMBOL_GPL(of_dma_get_range);
  * @np:	device node
  *
  * It returns true if "dma-coherent" property was found
- * for this device in DT.
+ * for this device in the DT, or if DMA is coherent by
+ * default for OF devices on the current platform.
  */
 bool of_dma_is_coherent(struct device_node *np)
 {
 	struct device_node *node = of_node_get(np);
 
+	if (IS_ENABLED(CONFIG_OF_DMA_DEFAULT_COHERENT))
+		return true;
+
 	while (node) {
 		if (of_property_read_bool(node, "dma-coherent")) {
 			of_node_put(node);


^ permalink raw reply	[relevance 11%]

* [PATCH 3.16 76/99] KVM: x86: Protect x86_decode_insn from Spectre-v1/L1TF attacks
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (74 preceding siblings ...)
  2020-05-20 14:14 11% ` [PATCH 3.16 75/99] net_sched: ematch: reject invalid TCF_EM_SIMPLE Ben Hutchings
@ 2020-05-20 14:14 12% ` Ben Hutchings
  2020-05-20 14:14 12% ` [PATCH 3.16 77/99] KVM: x86: Refactor picdev_write() to prevent " Ben Hutchings
                   ` (23 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Marios Pomonis, Nick Finco, Jim Mattson,
	Paolo Bonzini, Andrew Honig

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Marios Pomonis <pomonis@google.com>

commit 3c9053a2cae7ba2ba73766a34cea41baa70f57f7 upstream.

This fixes a Spectre-v1/L1TF vulnerability in x86_decode_insn().
kvm_emulate_instruction() (an ancestor of x86_decode_insn()) is an exported
symbol, so KVM should treat it conservatively from a security perspective.

Fixes: 045a282ca415 ("KVM: emulator: implement fninit, fnstsw, fnstcw")

Signed-off-by: Nick Finco <nifi@google.com>
Signed-off-by: Marios Pomonis <pomonis@google.com>
Reviewed-by: Andrew Honig <ahonig@google.com>
Reviewed-by: Jim Mattson <jmattson@google.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
[bwh: Backported to 3.16: Add #include <linux/nospec.h>]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 arch/x86/kvm/emulate.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -26,6 +26,7 @@
 #include <asm/kvm_emulate.h>
 #include <linux/stringify.h>
 #include <asm/nospec-branch.h>
+#include <linux/nospec.h>
 
 #include "x86.h"
 #include "tss.h"
@@ -4487,10 +4488,15 @@ done_prefixes:
 			}
 			break;
 		case Escape:
-			if (ctxt->modrm > 0xbf)
-				opcode = opcode.u.esc->high[ctxt->modrm - 0xc0];
-			else
+			if (ctxt->modrm > 0xbf) {
+				size_t size = ARRAY_SIZE(opcode.u.esc->high);
+				u32 index = array_index_nospec(
+					ctxt->modrm - 0xc0, size);
+
+				opcode = opcode.u.esc->high[index];
+			} else {
 				opcode = opcode.u.esc->op[(ctxt->modrm >> 3) & 7];
+			}
 			break;
 		default:
 			return EMULATION_FAILED;


^ permalink raw reply	[relevance 12%]

* [PATCH 3.16 83/99] KVM: x86: Protect DR-based index computations from Spectre-v1/L1TF attacks
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (81 preceding siblings ...)
  2020-05-20 14:14 12% ` [PATCH 3.16 82/99] KVM: x86: Protect MSR-based index computations from Spectre-v1/L1TF attacks in x86.c Ben Hutchings
@ 2020-05-20 14:14  9% ` Ben Hutchings
  2020-05-20 14:14 11% ` [PATCH 3.16 84/99] KVM: Check for a bad hva before dropping into the ghc slow path Ben Hutchings
                   ` (16 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Marios Pomonis, Nick Finco, Jim Mattson,
	Paolo Bonzini, Andrew Honig

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Marios Pomonis <pomonis@google.com>

commit ea740059ecb37807ba47b84b33d1447435a8d868 upstream.

This fixes a Spectre-v1/L1TF vulnerability in __kvm_set_dr() and
kvm_get_dr().
Both kvm_get_dr() and kvm_set_dr() (a wrapper of __kvm_set_dr()) are
exported symbols so KVM should tream them conservatively from a security
perspective.

Fixes: 020df0794f57 ("KVM: move DR register access handling into generic code")

Signed-off-by: Nick Finco <nifi@google.com>
Signed-off-by: Marios Pomonis <pomonis@google.com>
Reviewed-by: Andrew Honig <ahonig@google.com>
Reviewed-by: Jim Mattson <jmattson@google.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 arch/x86/kvm/x86.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -801,9 +801,11 @@ static void kvm_update_dr7(struct kvm_vc
 
 static int __kvm_set_dr(struct kvm_vcpu *vcpu, int dr, unsigned long val)
 {
+	size_t size = ARRAY_SIZE(vcpu->arch.db);
+
 	switch (dr) {
 	case 0 ... 3:
-		vcpu->arch.db[dr] = val;
+		vcpu->arch.db[array_index_nospec(dr, size)] = val;
 		if (!(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP))
 			vcpu->arch.eff_db[dr] = val;
 		break;
@@ -848,9 +850,11 @@ EXPORT_SYMBOL_GPL(kvm_set_dr);
 
 static int _kvm_get_dr(struct kvm_vcpu *vcpu, int dr, unsigned long *val)
 {
+	size_t size = ARRAY_SIZE(vcpu->arch.db);
+
 	switch (dr) {
 	case 0 ... 3:
-		*val = vcpu->arch.db[dr];
+		*val = vcpu->arch.db[array_index_nospec(dr, size)];
 		break;
 	case 4:
 		if (kvm_read_cr4_bits(vcpu, X86_CR4_DE))


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 98/99] bonding/alb: properly access headers in bond_alb_xmit()
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (96 preceding siblings ...)
  2020-05-20 14:15  9% ` [PATCH 3.16 97/99] cifs: fail i/o on soft mounts if sessionsetup errors out Ben Hutchings
@ 2020-05-20 14:15  9% ` Ben Hutchings
  2020-05-20 14:15 12% ` [PATCH 3.16 99/99] sunrpc: expiry_time should be seconds not timeval Ben Hutchings
  2020-05-20 21:23  6% ` [PATCH 3.16 00/99] 3.16.84-rc1 review Guenter Roeck
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:15 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Eric Dumazet, Andy Gospodarek,
	David S. Miller, syzbot, Veaceslav Falico, Jay Vosburgh

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Eric Dumazet <edumazet@google.com>

commit 38f88c45404293bbc027b956def6c10cbd45c616 upstream.

syzbot managed to send an IPX packet through bond_alb_xmit()
and af_packet and triggered a use-after-free.

First, bond_alb_xmit() was using ipx_hdr() helper to reach
the IPX header, but ipx_hdr() was using the transport offset
instead of the network offset. In the particular syzbot
report transport offset was 0xFFFF

This patch removes ipx_hdr() since it was only (mis)used from bonding.

Then we need to make sure IPv4/IPv6/IPX headers are pulled
in skb->head before dereferencing anything.

BUG: KASAN: use-after-free in bond_alb_xmit+0x153a/0x1590 drivers/net/bonding/bond_alb.c:1452
Read of size 2 at addr ffff8801ce56dfff by task syz-executor.2/18108
 (if (ipx_hdr(skb)->ipx_checksum != IPX_NO_CHECKSUM) ...)

Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
Call Trace:
 [<ffffffff8441fc42>] __dump_stack lib/dump_stack.c:17 [inline]
 [<ffffffff8441fc42>] dump_stack+0x14d/0x20b lib/dump_stack.c:53
 [<ffffffff81a7dec4>] print_address_description+0x6f/0x20b mm/kasan/report.c:282
 [<ffffffff81a7e0ec>] kasan_report_error mm/kasan/report.c:380 [inline]
 [<ffffffff81a7e0ec>] kasan_report mm/kasan/report.c:438 [inline]
 [<ffffffff81a7e0ec>] kasan_report.cold+0x8c/0x2a0 mm/kasan/report.c:422
 [<ffffffff81a7dc4f>] __asan_report_load_n_noabort+0xf/0x20 mm/kasan/report.c:469
 [<ffffffff82c8c00a>] bond_alb_xmit+0x153a/0x1590 drivers/net/bonding/bond_alb.c:1452
 [<ffffffff82c60c74>] __bond_start_xmit drivers/net/bonding/bond_main.c:4199 [inline]
 [<ffffffff82c60c74>] bond_start_xmit+0x4f4/0x1570 drivers/net/bonding/bond_main.c:4224
 [<ffffffff83baa558>] __netdev_start_xmit include/linux/netdevice.h:4525 [inline]
 [<ffffffff83baa558>] netdev_start_xmit include/linux/netdevice.h:4539 [inline]
 [<ffffffff83baa558>] xmit_one net/core/dev.c:3611 [inline]
 [<ffffffff83baa558>] dev_hard_start_xmit+0x168/0x910 net/core/dev.c:3627
 [<ffffffff83bacf35>] __dev_queue_xmit+0x1f55/0x33b0 net/core/dev.c:4238
 [<ffffffff83bae3a8>] dev_queue_xmit+0x18/0x20 net/core/dev.c:4278
 [<ffffffff84339189>] packet_snd net/packet/af_packet.c:3226 [inline]
 [<ffffffff84339189>] packet_sendmsg+0x4919/0x70b0 net/packet/af_packet.c:3252
 [<ffffffff83b1ac0c>] sock_sendmsg_nosec net/socket.c:673 [inline]
 [<ffffffff83b1ac0c>] sock_sendmsg+0x12c/0x160 net/socket.c:684
 [<ffffffff83b1f5a2>] __sys_sendto+0x262/0x380 net/socket.c:1996
 [<ffffffff83b1f700>] SYSC_sendto net/socket.c:2008 [inline]
 [<ffffffff83b1f700>] SyS_sendto+0x40/0x60 net/socket.c:2004

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reported-by: syzbot <syzkaller@googlegroups.com>
Cc: Jay Vosburgh <j.vosburgh@gmail.com>
Cc: Veaceslav Falico <vfalico@gmail.com>
Cc: Andy Gospodarek <andy@greyhouse.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
[bwh: Backported to 3.16:
 - Don't delete ipx_hdr() as it's still used by net/ipx here
 - Adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -1450,26 +1450,31 @@ int bond_alb_xmit(struct sk_buff *skb, s
 	bool do_tx_balance = true;
 	u32 hash_index = 0;
 	const u8 *hash_start = NULL;
-	struct ipv6hdr *ip6hdr;
 
 	skb_reset_mac_header(skb);
 	eth_data = eth_hdr(skb);
 
 	switch (ntohs(skb->protocol)) {
 	case ETH_P_IP: {
-		const struct iphdr *iph = ip_hdr(skb);
+		const struct iphdr *iph;
 
 		if (ether_addr_equal_64bits(eth_data->h_dest, mac_bcast) ||
-		    (iph->daddr == ip_bcast) ||
-		    (iph->protocol == IPPROTO_IGMP)) {
+		    !pskb_network_may_pull(skb, sizeof(*iph))) {
+			do_tx_balance = false;
+			break;
+		}
+		iph = ip_hdr(skb);
+		if (iph->daddr == ip_bcast || iph->protocol == IPPROTO_IGMP) {
 			do_tx_balance = false;
 			break;
 		}
 		hash_start = (char *)&(iph->daddr);
 		hash_size = sizeof(iph->daddr);
-	}
 		break;
-	case ETH_P_IPV6:
+	}
+	case ETH_P_IPV6: {
+		const struct ipv6hdr *ip6hdr;
+
 		/* IPv6 doesn't really use broadcast mac address, but leave
 		 * that here just in case.
 		 */
@@ -1486,7 +1491,11 @@ int bond_alb_xmit(struct sk_buff *skb, s
 			break;
 		}
 
-		/* Additianally, DAD probes should not be tx-balanced as that
+		if (!pskb_network_may_pull(skb, sizeof(*ip6hdr))) {
+			do_tx_balance = false;
+			break;
+		}
+		/* Additionally, DAD probes should not be tx-balanced as that
 		 * will lead to false positives for duplicate addresses and
 		 * prevent address configuration from working.
 		 */
@@ -1496,17 +1505,26 @@ int bond_alb_xmit(struct sk_buff *skb, s
 			break;
 		}
 
-		hash_start = (char *)&(ipv6_hdr(skb)->daddr);
-		hash_size = sizeof(ipv6_hdr(skb)->daddr);
+		hash_start = (char *)&ip6hdr->daddr;
+		hash_size = sizeof(ip6hdr->daddr);
 		break;
-	case ETH_P_IPX:
-		if (ipx_hdr(skb)->ipx_checksum != IPX_NO_CHECKSUM) {
+	}
+	case ETH_P_IPX: {
+		const struct ipxhdr *ipxhdr;
+
+		if (pskb_network_may_pull(skb, sizeof(*ipxhdr))) {
+			do_tx_balance = false;
+			break;
+		}
+		ipxhdr = (struct ipxhdr *)skb_network_header(skb);
+
+		if (ipxhdr->ipx_checksum != IPX_NO_CHECKSUM) {
 			/* something is wrong with this packet */
 			do_tx_balance = false;
 			break;
 		}
 
-		if (ipx_hdr(skb)->ipx_type != IPX_TYPE_NCP) {
+		if (ipxhdr->ipx_type != IPX_TYPE_NCP) {
 			/* The only protocol worth balancing in
 			 * this family since it has an "ARP" like
 			 * mechanism
@@ -1515,9 +1533,11 @@ int bond_alb_xmit(struct sk_buff *skb, s
 			break;
 		}
 
+		eth_data = eth_hdr(skb);
 		hash_start = (char *)eth_data->h_dest;
 		hash_size = ETH_ALEN;
 		break;
+	}
 	case ETH_P_ARP:
 		do_tx_balance = false;
 		if (bond_info->rlb_enabled)


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 66/99] KVM: PPC: Book3S HV: Uninit vCPU if vcore creation fails
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (64 preceding siblings ...)
  2020-05-20 14:14  7% ` [PATCH 3.16 65/99] media: uvcvideo: Avoid cyclic entity chains due to malformed USB descriptors Ben Hutchings
@ 2020-05-20 14:14  9% ` Ben Hutchings
  2020-05-20 14:14  9% ` [PATCH 3.16 67/99] KVM: PPC: Book3S PR: Free shared page if mmu initialization fails Ben Hutchings
                   ` (33 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Sean Christopherson, Greg Kurz,
	Paul Mackerras, Paolo Bonzini

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Sean Christopherson <sean.j.christopherson@intel.com>

commit 1a978d9d3e72ddfa40ac60d26301b154247ee0bc upstream.

Call kvm_vcpu_uninit() if vcore creation fails to avoid leaking any
resources allocated by kvm_vcpu_init(), i.e. the vcpu->run page.

Fixes: 371fefd6f2dc4 ("KVM: PPC: Allow book3s_hv guests to use SMT processor modes")
Reviewed-by: Greg Kurz <groug@kaod.org>
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
Acked-by: Paul Mackerras <paulus@ozlabs.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 arch/powerpc/kvm/book3s_hv.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -1316,7 +1316,7 @@ static struct kvm_vcpu *kvmppc_core_vcpu
 	mutex_unlock(&kvm->lock);
 
 	if (!vcore)
-		goto free_vcpu;
+		goto uninit_vcpu;
 
 	spin_lock(&vcore->lock);
 	++vcore->num_threads;
@@ -1329,6 +1329,8 @@ static struct kvm_vcpu *kvmppc_core_vcpu
 
 	return vcpu;
 
+uninit_vcpu:
+	kvm_vcpu_uninit(vcpu);
 free_vcpu:
 	kmem_cache_free(kvm_vcpu_cache, vcpu);
 out:


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 74/99] CIFS: Fix task struct use-after-free on reconnect
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (72 preceding siblings ...)
  2020-05-20 14:14 12% ` [PATCH 3.16 73/99] iwlegacy: ensure loop counter addr does not wrap and cause an infinite loop Ben Hutchings
@ 2020-05-20 14:14  9% ` Ben Hutchings
  2020-05-20 14:14 11% ` [PATCH 3.16 75/99] net_sched: ematch: reject invalid TCF_EM_SIMPLE Ben Hutchings
                   ` (25 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Paulo Alcantara (SUSE),
	Steve French, Vincent Whitchurch, Pavel Shilovsky

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Vincent Whitchurch <vincent.whitchurch@axis.com>

commit f1f27ad74557e39f67a8331a808b860f89254f2d upstream.

The task which created the MID may be gone by the time cifsd attempts to
call the callbacks on MIDs from cifs_reconnect().

This leads to a use-after-free of the task struct in cifs_wake_up_task:

 ==================================================================
 BUG: KASAN: use-after-free in __lock_acquire+0x31a0/0x3270
 Read of size 8 at addr ffff8880103e3a68 by task cifsd/630

 CPU: 0 PID: 630 Comm: cifsd Not tainted 5.5.0-rc6+ #119
 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1 04/01/2014
 Call Trace:
  dump_stack+0x8e/0xcb
  print_address_description.constprop.5+0x1d3/0x3c0
  ? __lock_acquire+0x31a0/0x3270
  __kasan_report+0x152/0x1aa
  ? __lock_acquire+0x31a0/0x3270
  ? __lock_acquire+0x31a0/0x3270
  kasan_report+0xe/0x20
  __lock_acquire+0x31a0/0x3270
  ? __wake_up_common+0x1dc/0x630
  ? _raw_spin_unlock_irqrestore+0x4c/0x60
  ? mark_held_locks+0xf0/0xf0
  ? _raw_spin_unlock_irqrestore+0x39/0x60
  ? __wake_up_common_lock+0xd5/0x130
  ? __wake_up_common+0x630/0x630
  lock_acquire+0x13f/0x330
  ? try_to_wake_up+0xa3/0x19e0
  _raw_spin_lock_irqsave+0x38/0x50
  ? try_to_wake_up+0xa3/0x19e0
  try_to_wake_up+0xa3/0x19e0
  ? cifs_compound_callback+0x178/0x210
  ? set_cpus_allowed_ptr+0x10/0x10
  cifs_reconnect+0xa1c/0x15d0
  ? generic_ip_connect+0x1860/0x1860
  ? rwlock_bug.part.0+0x90/0x90
  cifs_readv_from_socket+0x479/0x690
  cifs_read_from_socket+0x9d/0xe0
  ? cifs_readv_from_socket+0x690/0x690
  ? mempool_resize+0x690/0x690
  ? rwlock_bug.part.0+0x90/0x90
  ? memset+0x1f/0x40
  ? allocate_buffers+0xff/0x340
  cifs_demultiplex_thread+0x388/0x2a50
  ? cifs_handle_standard+0x610/0x610
  ? rcu_read_lock_held_common+0x120/0x120
  ? mark_lock+0x11b/0xc00
  ? __lock_acquire+0x14ed/0x3270
  ? __kthread_parkme+0x78/0x100
  ? lockdep_hardirqs_on+0x3e8/0x560
  ? lock_downgrade+0x6a0/0x6a0
  ? lockdep_hardirqs_on+0x3e8/0x560
  ? _raw_spin_unlock_irqrestore+0x39/0x60
  ? cifs_handle_standard+0x610/0x610
  kthread+0x2bb/0x3a0
  ? kthread_create_worker_on_cpu+0xc0/0xc0
  ret_from_fork+0x3a/0x50

 Allocated by task 649:
  save_stack+0x19/0x70
  __kasan_kmalloc.constprop.5+0xa6/0xf0
  kmem_cache_alloc+0x107/0x320
  copy_process+0x17bc/0x5370
  _do_fork+0x103/0xbf0
  __x64_sys_clone+0x168/0x1e0
  do_syscall_64+0x9b/0xec0
  entry_SYSCALL_64_after_hwframe+0x49/0xbe

 Freed by task 0:
  save_stack+0x19/0x70
  __kasan_slab_free+0x11d/0x160
  kmem_cache_free+0xb5/0x3d0
  rcu_core+0x52f/0x1230
  __do_softirq+0x24d/0x962

 The buggy address belongs to the object at ffff8880103e32c0
  which belongs to the cache task_struct of size 6016
 The buggy address is located 1960 bytes inside of
  6016-byte region [ffff8880103e32c0, ffff8880103e4a40)
 The buggy address belongs to the page:
 page:ffffea000040f800 refcount:1 mapcount:0 mapping:ffff8880108da5c0
 index:0xffff8880103e4c00 compound_mapcount: 0
 raw: 4000000000010200 ffffea00001f2208 ffffea00001e3408 ffff8880108da5c0
 raw: ffff8880103e4c00 0000000000050003 00000001ffffffff 0000000000000000
 page dumped because: kasan: bad access detected

 Memory state around the buggy address:
  ffff8880103e3900: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
  ffff8880103e3980: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
 >ffff8880103e3a00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
                                                           ^
  ffff8880103e3a80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
  ffff8880103e3b00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
 ==================================================================

This can be reliably reproduced by adding the below delay to
cifs_reconnect(), running find(1) on the mount, restarting the samba
server while find is running, and killing find during the delay:

  	spin_unlock(&GlobalMid_Lock);
  	mutex_unlock(&server->srv_mutex);

 +	msleep(10000);
 +
  	cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__);
  	list_for_each_safe(tmp, tmp2, &retry_list) {
  		mid_entry = list_entry(tmp, struct mid_q_entry, qhead);

Fix this by holding a reference to the task struct until the MID is
freed.

Signed-off-by: Vincent Whitchurch <vincent.whitchurch@axis.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
Reviewed-by: Paulo Alcantara (SUSE) <pc@cjr.nz>
Reviewed-by: Pavel Shilovsky <pshilov@microsoft.com>
[bwh: Backported to 3.16:
 - In _cifs_mid_q_entry_release(), use mid instead of midEntry
 - Adjust context, indentation]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -1252,6 +1252,7 @@ struct mid_q_entry {
 	mid_receive_t *receive; /* call receive callback */
 	mid_callback_t *callback; /* call completion callback */
 	void *callback_data;	  /* general purpose pointer for callback */
+	struct task_struct *creator;
 	void *resp_buf;		/* pointer to received SMB header */
 	int mid_state;	/* wish this were enum but can not pass to wait_event */
 	unsigned int mid_flags;
--- a/fs/cifs/smb2transport.c
+++ b/fs/cifs/smb2transport.c
@@ -542,6 +542,8 @@ smb2_mid_entry_alloc(const struct smb2_h
 		 * The default is for the mid to be synchronous, so the
 		 * default callback just wakes up the current task.
 		 */
+		get_task_struct(current);
+		temp->creator = current;
 		temp->callback = cifs_wake_up_task;
 		temp->callback_data = current;
 	}
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -72,6 +72,8 @@ AllocMidQEntry(const struct smb_hdr *smb
 		 * The default is for the mid to be synchronous, so the
 		 * default callback just wakes up the current task.
 		 */
+		get_task_struct(current);
+		temp->creator = current;
 		temp->callback = cifs_wake_up_task;
 		temp->callback_data = current;
 	}
@@ -86,6 +88,8 @@ static void _cifs_mid_q_entry_release(st
 	struct mid_q_entry *mid = container_of(refcount, struct mid_q_entry,
 					       refcount);
 
+	put_task_struct(mid->creator);
+
 	mempool_free(mid, cifs_mid_poolp);
 }
 


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 43/99] efi: Use early_mem*() instead of early_io*()
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (41 preceding siblings ...)
  2020-05-20 14:14  9% ` [PATCH 3.16 42/99] ARM: dts: at91: sama5d3: define clock rate range for tcb1 Ben Hutchings
@ 2020-05-20 14:14  7% ` Ben Hutchings
  2020-05-20 15:53 10%   ` Ben Hutchings
  2020-05-20 14:14 11% ` [PATCH 3.16 44/99] efi/x86: Map the entire EFI vendor string before copying it Ben Hutchings
                   ` (56 subsequent siblings)
  99 siblings, 1 reply; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Daniel Kiper, Matt Fleming, Mark Salter,
	Leif Lindholm

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Daniel Kiper <daniel.kiper@oracle.com>

commit abc93f8eb6e46a480485f19256bdbda36ec78a84 upstream.

Use early_mem*() instead of early_io*() because all mapped EFI regions
are memory (usually RAM but they could also be ROM, EPROM, EEPROM, flash,
etc.) not I/O regions. Additionally, I/O family calls do not work correctly
under Xen in our case. early_ioremap() skips the PFN to MFN conversion
when building the PTE. Using it for memory will attempt to map the wrong
machine frame. However, all artificial EFI structures created under Xen
live in dom0 memory and should be mapped/unmapped using early_mem*() family
calls which map domain memory.

Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
Cc: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Mark Salter <msalter@redhat.com>
Signed-off-by: Matt Fleming <matt.fleming@intel.com>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 arch/x86/platform/efi/efi.c | 28 ++++++++++++++--------------
 drivers/firmware/efi/efi.c  |  4 ++--
 2 files changed, 16 insertions(+), 16 deletions(-)

--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -435,7 +435,7 @@ void __init efi_unmap_memmap(void)
 {
 	clear_bit(EFI_MEMMAP, &efi.flags);
 	if (memmap.map) {
-		early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size);
+		early_memunmap(memmap.map, memmap.nr_map * memmap.desc_size);
 		memmap.map = NULL;
 	}
 }
@@ -475,12 +475,12 @@ static int __init efi_systab_init(void *
 			if (!data)
 				return -ENOMEM;
 		}
-		systab64 = early_ioremap((unsigned long)phys,
+		systab64 = early_memremap((unsigned long)phys,
 					 sizeof(*systab64));
 		if (systab64 == NULL) {
 			pr_err("Couldn't map the system table!\n");
 			if (data)
-				early_iounmap(data, sizeof(*data));
+				early_memunmap(data, sizeof(*data));
 			return -ENOMEM;
 		}
 
@@ -512,9 +512,9 @@ static int __init efi_systab_init(void *
 					   systab64->tables;
 		tmp |= data ? data->tables : systab64->tables;
 
-		early_iounmap(systab64, sizeof(*systab64));
+		early_memunmap(systab64, sizeof(*systab64));
 		if (data)
-			early_iounmap(data, sizeof(*data));
+			early_memunmap(data, sizeof(*data));
 #ifdef CONFIG_X86_32
 		if (tmp >> 32) {
 			pr_err("EFI data located above 4GB, disabling EFI.\n");
@@ -524,7 +524,7 @@ static int __init efi_systab_init(void *
 	} else {
 		efi_system_table_32_t *systab32;
 
-		systab32 = early_ioremap((unsigned long)phys,
+		systab32 = early_memremap((unsigned long)phys,
 					 sizeof(*systab32));
 		if (systab32 == NULL) {
 			pr_err("Couldn't map the system table!\n");
@@ -545,7 +545,7 @@ static int __init efi_systab_init(void *
 		efi_systab.nr_tables = systab32->nr_tables;
 		efi_systab.tables = systab32->tables;
 
-		early_iounmap(systab32, sizeof(*systab32));
+		early_memunmap(systab32, sizeof(*systab32));
 	}
 
 	efi.systab = &efi_systab;
@@ -571,7 +571,7 @@ static int __init efi_runtime_init32(voi
 {
 	efi_runtime_services_32_t *runtime;
 
-	runtime = early_ioremap((unsigned long)efi.systab->runtime,
+	runtime = early_memremap((unsigned long)efi.systab->runtime,
 			sizeof(efi_runtime_services_32_t));
 	if (!runtime) {
 		pr_err("Could not map the runtime service table!\n");
@@ -586,7 +586,7 @@ static int __init efi_runtime_init32(voi
 	efi_phys.set_virtual_address_map =
 			(efi_set_virtual_address_map_t *)
 			(unsigned long)runtime->set_virtual_address_map;
-	early_iounmap(runtime, sizeof(efi_runtime_services_32_t));
+	early_memunmap(runtime, sizeof(efi_runtime_services_32_t));
 
 	return 0;
 }
@@ -595,7 +595,7 @@ static int __init efi_runtime_init64(voi
 {
 	efi_runtime_services_64_t *runtime;
 
-	runtime = early_ioremap((unsigned long)efi.systab->runtime,
+	runtime = early_memremap((unsigned long)efi.systab->runtime,
 			sizeof(efi_runtime_services_64_t));
 	if (!runtime) {
 		pr_err("Could not map the runtime service table!\n");
@@ -610,7 +610,7 @@ static int __init efi_runtime_init64(voi
 	efi_phys.set_virtual_address_map =
 			(efi_set_virtual_address_map_t *)
 			(unsigned long)runtime->set_virtual_address_map;
-	early_iounmap(runtime, sizeof(efi_runtime_services_64_t));
+	early_memunmap(runtime, sizeof(efi_runtime_services_64_t));
 
 	return 0;
 }
@@ -641,7 +641,7 @@ static int __init efi_runtime_init(void)
 static int __init efi_memmap_init(void)
 {
 	/* Map the EFI memory map */
-	memmap.map = early_ioremap((unsigned long)memmap.phys_map,
+	memmap.map = early_memremap((unsigned long)memmap.phys_map,
 				   memmap.nr_map * memmap.desc_size);
 	if (memmap.map == NULL) {
 		pr_err("Could not map the memory map!\n");
@@ -745,14 +745,14 @@ void __init efi_init(void)
 	/*
 	 * Show what we know for posterity
 	 */
-	c16 = tmp = early_ioremap(efi.systab->fw_vendor, 2);
+	c16 = tmp = early_memremap(efi.systab->fw_vendor, 2);
 	if (c16) {
 		for (i = 0; i < sizeof(vendor) - 1 && *c16; ++i)
 			vendor[i] = *c16++;
 		vendor[i] = '\0';
 	} else
 		pr_err("Could not map the firmware vendor!\n");
-	early_iounmap(tmp, 2);
+	early_memunmap(tmp, 2);
 
 	pr_info("EFI v%u.%.02u by %s\n",
 		efi.systab->hdr.revision >> 16,
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -295,7 +295,7 @@ int __init efi_config_init(efi_config_ta
 			if (table64 >> 32) {
 				pr_cont("\n");
 				pr_err("Table located above 4GB, disabling EFI.\n");
-				early_iounmap(config_tables,
+				early_memunmap(config_tables,
 					       efi.systab->nr_tables * sz);
 				return -EINVAL;
 			}
@@ -311,7 +311,7 @@ int __init efi_config_init(efi_config_ta
 		tablep += sz;
 	}
 	pr_cont("\n");
-	early_iounmap(config_tables, efi.systab->nr_tables * sz);
+	early_memunmap(config_tables, efi.systab->nr_tables * sz);
 
 	set_bit(EFI_CONFIG_TABLES, &efi.flags);
 


^ permalink raw reply	[relevance 7%]

* [PATCH 3.16 88/99] media/v4l2-core: set pages dirty upon releasing DMA buffers
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (86 preceding siblings ...)
  2020-05-20 14:14  8% ` [PATCH 3.16 87/99] mm/mempolicy.c: fix out of bounds write in mpol_parse_str() Ben Hutchings
@ 2020-05-20 14:14 11% ` Ben Hutchings
  2020-05-20 14:14  9% ` [PATCH 3.16 89/99] tcp: clear tp->total_retrans in tcp_disconnect() Ben Hutchings
                   ` (11 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Jens Axboe, Jerome Glisse,
	Aneesh Kumar K.V, John Hubbard, Linus Torvalds, Jan Kara,
	Dan Williams, Jason Gunthorpe, Hans Verkuil, Christoph Hellwig,
	Leon Romanovsky, Alex Williamson, Daniel Vetter, Jonathan Corbet,
	Jason Gunthorpe, Björn Töpel, Ira Weiny, Mike Rapoport,
	Mauro Carvalho Chehab, Kirill A. Shutemov

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: John Hubbard <jhubbard@nvidia.com>

commit 3c7470b6f68434acae459482ab920d1e3fabd1c7 upstream.

After DMA is complete, and the device and CPU caches are synchronized,
it's still required to mark the CPU pages as dirty, if the data was
coming from the device.  However, this driver was just issuing a bare
put_page() call, without any set_page_dirty*() call.

Fix the problem, by calling set_page_dirty_lock() if the CPU pages were
potentially receiving data from the device.

Link: http://lkml.kernel.org/r/20200107224558.2362728-11-jhubbard@nvidia.com
Signed-off-by: John Hubbard <jhubbard@nvidia.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Acked-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Cc: Mauro Carvalho Chehab <mchehab@kernel.org>
Cc: Alex Williamson <alex.williamson@redhat.com>
Cc: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
Cc: Björn Töpel <bjorn.topel@intel.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Ira Weiny <ira.weiny@intel.com>
Cc: Jan Kara <jack@suse.cz>
Cc: Jason Gunthorpe <jgg@mellanox.com>
Cc: Jason Gunthorpe <jgg@ziepe.ca>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Jerome Glisse <jglisse@redhat.com>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Kirill A. Shutemov <kirill@shutemov.name>
Cc: Leon Romanovsky <leonro@mellanox.com>
Cc: Mike Rapoport <rppt@linux.ibm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/media/v4l2-core/videobuf-dma-sg.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

--- a/drivers/media/v4l2-core/videobuf-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf-dma-sg.c
@@ -316,8 +316,11 @@ int videobuf_dma_free(struct videobuf_dm
 	BUG_ON(dma->sglen);
 
 	if (dma->pages) {
-		for (i = 0; i < dma->nr_pages; i++)
+		for (i = 0; i < dma->nr_pages; i++) {
+			if (dma->direction == DMA_FROM_DEVICE)
+				set_page_dirty_lock(dma->pages[i]);
 			page_cache_release(dma->pages[i]);
+		}
 		kfree(dma->pages);
 		dma->pages = NULL;
 	}


^ permalink raw reply	[relevance 11%]

* [PATCH 3.16 44/99] efi/x86: Map the entire EFI vendor string before copying it
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (42 preceding siblings ...)
  2020-05-20 14:14  7% ` [PATCH 3.16 43/99] efi: Use early_mem*() instead of early_io*() Ben Hutchings
@ 2020-05-20 14:14 11% ` Ben Hutchings
  2020-05-20 14:14  7% ` [PATCH 3.16 45/99] PCI: Don't disable bridge BARs when assigning bus resources Ben Hutchings
                   ` (55 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Matthew Garrett, Ard Biesheuvel,
	Ard Biesheuvel, linux-efi, Arvind Sankar, Andy Lutomirski,
	Ingo Molnar

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Ard Biesheuvel <ardb@kernel.org>

commit ffc2760bcf2dba0dbef74013ed73eea8310cc52c upstream.

Fix a couple of issues with the way we map and copy the vendor string:
- we map only 2 bytes, which usually works since you get at least a
  page, but if the vendor string happens to cross a page boundary,
  a crash will result
- only call early_memunmap() if early_memremap() succeeded, or we will
  call it with a NULL address which it doesn't like,
- while at it, switch to early_memremap_ro(), and array indexing rather
  than pointer dereferencing to read the CHAR16 characters.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Arvind Sankar <nivedita@alum.mit.edu>
Cc: Matthew Garrett <mjg59@google.com>
Cc: linux-efi@vger.kernel.org
Fixes: 5b83683f32b1 ("x86: EFI runtime service support")
Link: https://lkml.kernel.org/r/20200103113953.9571-5-ardb@kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
[bwh: Backported to 3.16: Keep using early_memremap() since
 early_memremap_ro() is not defined.]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 arch/x86/platform/efi/efi.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -718,7 +718,6 @@ void __init efi_init(void)
 	efi_char16_t *c16;
 	char vendor[100] = "unknown";
 	int i = 0;
-	void *tmp;
 
 #ifdef CONFIG_X86_32
 	if (boot_params.efi_info.efi_systab_hi ||
@@ -745,14 +744,16 @@ void __init efi_init(void)
 	/*
 	 * Show what we know for posterity
 	 */
-	c16 = tmp = early_memremap(efi.systab->fw_vendor, 2);
+	c16 = early_memremap(efi.systab->fw_vendor,
+			     sizeof(vendor) * sizeof(efi_char16_t));
 	if (c16) {
-		for (i = 0; i < sizeof(vendor) - 1 && *c16; ++i)
-			vendor[i] = *c16++;
+		for (i = 0; i < sizeof(vendor) - 1 && c16[i]; ++i)
+			vendor[i] = c16[i];
 		vendor[i] = '\0';
-	} else
+		early_memunmap(c16, sizeof(vendor) * sizeof(efi_char16_t));
+	} else {
 		pr_err("Could not map the firmware vendor!\n");
-	early_memunmap(tmp, 2);
+	}
 
 	pr_info("EFI v%u.%.02u by %s\n",
 		efi.systab->hdr.revision >> 16,


^ permalink raw reply	[relevance 11%]

* [PATCH 3.16 29/99] zd1211rw: fix storage endpoint lookup
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (27 preceding siblings ...)
  2020-05-20 14:13  9% ` [PATCH 3.16 28/99] rsi_91x_usb: " Ben Hutchings
@ 2020-05-20 14:13 13% ` Ben Hutchings
  2020-05-20 14:13  9% ` [PATCH 3.16 30/99] brcmfmac: Fix memory leak in brcmf_usbdev_qinit Ben Hutchings
                   ` (70 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:13 UTC (permalink / raw)
  To: linux-kernel, stable; +Cc: akpm, Denis Kirjanov, Johan Hovold, Kalle Valo

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Johan Hovold <johan@kernel.org>

commit 2d68bb2687abb747558b933e80845ff31570a49c upstream.

Make sure to use the current alternate setting when verifying the
storage interface descriptors to avoid submitting an URB to an invalid
endpoint.

Failing to do so could cause the driver to misbehave or trigger a WARN()
in usb_submit_urb() that kernels with panic_on_warn set would choke on.

Fixes: a1030e92c150 ("[PATCH] zd1211rw: Convert installer CDROM device into WLAN device")
Signed-off-by: Johan Hovold <johan@kernel.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
[bwh: Backported to 3.16: adjust filename]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/net/wireless/zd1211rw/zd_usb.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/drivers/net/wireless/zd1211rw/zd_usb.c
+++ b/drivers/net/wireless/zd1211rw/zd_usb.c
@@ -1272,7 +1272,7 @@ static void print_id(struct usb_device *
 static int eject_installer(struct usb_interface *intf)
 {
 	struct usb_device *udev = interface_to_usbdev(intf);
-	struct usb_host_interface *iface_desc = &intf->altsetting[0];
+	struct usb_host_interface *iface_desc = intf->cur_altsetting;
 	struct usb_endpoint_descriptor *endpoint;
 	unsigned char *cmd;
 	u8 bulk_out_ep;


^ permalink raw reply	[relevance 13%]

* [PATCH 3.16 22/99] ath9k: fix storage endpoint lookup
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (20 preceding siblings ...)
  2020-05-20 14:13  9% ` [PATCH 3.16 21/99] reiserfs: Fix spurious unlock in reiserfs_fill_super() error handling Ben Hutchings
@ 2020-05-20 14:13  9% ` Ben Hutchings
  2020-05-20 14:13 12% ` [PATCH 3.16 23/99] rsi: fix use-after-free on failed probe and unbind Ben Hutchings
                   ` (77 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:13 UTC (permalink / raw)
  To: linux-kernel, stable; +Cc: akpm, Denis Kirjanov, Kalle Valo, Johan Hovold

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Johan Hovold <johan@kernel.org>

commit 0ef332951e856efa89507cdd13ba8f4fb8d4db12 upstream.

Make sure to use the current alternate setting when verifying the
storage interface descriptors to avoid submitting an URB to an invalid
endpoint.

Failing to do so could cause the driver to misbehave or trigger a WARN()
in usb_submit_urb() that kernels with panic_on_warn set would choke on.

Fixes: 36bcce430657 ("ath9k_htc: Handle storage devices")
Signed-off-by: Johan Hovold <johan@kernel.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/net/wireless/ath/ath9k/hif_usb.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -1141,7 +1141,7 @@ err_fw:
 static int send_eject_command(struct usb_interface *interface)
 {
 	struct usb_device *udev = interface_to_usbdev(interface);
-	struct usb_host_interface *iface_desc = &interface->altsetting[0];
+	struct usb_host_interface *iface_desc = interface->cur_altsetting;
 	struct usb_endpoint_descriptor *endpoint;
 	unsigned char *cmd;
 	u8 bulk_out_ep;


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 65/99] media: uvcvideo: Avoid cyclic entity chains due to malformed USB descriptors
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (63 preceding siblings ...)
  2020-05-20 14:14  7% ` [PATCH 3.16 64/99] USB: serial: ir-usb: fix IrLAP framing Ben Hutchings
@ 2020-05-20 14:14  7% ` Ben Hutchings
  2020-05-20 14:14  9% ` [PATCH 3.16 66/99] KVM: PPC: Book3S HV: Uninit vCPU if vcore creation fails Ben Hutchings
                   ` (34 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Will Deacon, Andrey Konovalov,
	Laurent Pinchart, Mauro Carvalho Chehab

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Will Deacon <will@kernel.org>

commit 68035c80e129c4cfec659aac4180354530b26527 upstream.

Way back in 2017, fuzzing the 4.14-rc2 USB stack with syzkaller kicked
up the following WARNING from the UVC chain scanning code:

  | list_add double add: new=ffff880069084010, prev=ffff880069084010,
  | next=ffff880067d22298.
  | ------------[ cut here ]------------
  | WARNING: CPU: 1 PID: 1846 at lib/list_debug.c:31 __list_add_valid+0xbd/0xf0
  | Modules linked in:
  | CPU: 1 PID: 1846 Comm: kworker/1:2 Not tainted
  | 4.14.0-rc2-42613-g1488251d1a98 #238
  | Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
  | Workqueue: usb_hub_wq hub_event
  | task: ffff88006b01ca40 task.stack: ffff880064358000
  | RIP: 0010:__list_add_valid+0xbd/0xf0 lib/list_debug.c:29
  | RSP: 0018:ffff88006435ddd0 EFLAGS: 00010286
  | RAX: 0000000000000058 RBX: ffff880067d22298 RCX: 0000000000000000
  | RDX: 0000000000000058 RSI: ffffffff85a58800 RDI: ffffed000c86bbac
  | RBP: ffff88006435dde8 R08: 1ffff1000c86ba52 R09: 0000000000000000
  | R10: 0000000000000002 R11: 0000000000000000 R12: ffff880069084010
  | R13: ffff880067d22298 R14: ffff880069084010 R15: ffff880067d222a0
  | FS:  0000000000000000(0000) GS:ffff88006c900000(0000) knlGS:0000000000000000
  | CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
  | CR2: 0000000020004ff2 CR3: 000000006b447000 CR4: 00000000000006e0
  | Call Trace:
  |  __list_add ./include/linux/list.h:59
  |  list_add_tail+0x8c/0x1b0 ./include/linux/list.h:92
  |  uvc_scan_chain_forward.isra.8+0x373/0x416
  | drivers/media/usb/uvc/uvc_driver.c:1471
  |  uvc_scan_chain drivers/media/usb/uvc/uvc_driver.c:1585
  |  uvc_scan_device drivers/media/usb/uvc/uvc_driver.c:1769
  |  uvc_probe+0x77f2/0x8f00 drivers/media/usb/uvc/uvc_driver.c:2104

Looking into the output from usbmon, the interesting part is the
following data packet:

  ffff880069c63e00 30710169 C Ci:1:002:0 0 143 = 09028f00 01030080
  00090403 00000e01 00000924 03000103 7c003328 010204db

If we drop the lead configuration and interface descriptors, we're left
with an output terminal descriptor describing a generic display:

  /* Output terminal descriptor */
  buf[0]	09
  buf[1]	24
  buf[2]	03	/* UVC_VC_OUTPUT_TERMINAL */
  buf[3]	00	/* ID */
  buf[4]	01	/* type == 0x0301 (UVC_OTT_DISPLAY) */
  buf[5]	03
  buf[6]	7c
  buf[7]	00	/* source ID refers to self! */
  buf[8]	33

The problem with this descriptor is that it is self-referential: the
source ID of 0 matches itself! This causes the 'struct uvc_entity'
representing the display to be added to its chain list twice during
'uvc_scan_chain()': once via 'uvc_scan_chain_entity()' when it is
processed directly from the 'dev->entities' list and then again
immediately afterwards when trying to follow the source ID in
'uvc_scan_chain_forward()'

Add a check before adding an entity to a chain list to ensure that the
entity is not already part of a chain.

Link: https://lore.kernel.org/linux-media/CAAeHK+z+Si69jUR+N-SjN9q4O+o5KFiNManqEa-PjUta7EOb7A@mail.gmail.com/

Fixes: c0efd232929c ("V4L/DVB (8145a): USB Video Class driver")
Reported-by: Andrey Konovalov <andreyknvl@google.com>
Signed-off-by: Will Deacon <will@kernel.org>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/media/usb/uvc/uvc_driver.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

--- a/drivers/media/usb/uvc/uvc_driver.c
+++ b/drivers/media/usb/uvc/uvc_driver.c
@@ -1369,6 +1369,11 @@ static int uvc_scan_chain_forward(struct
 			break;
 		if (forward == prev)
 			continue;
+		if (forward->chain.next || forward->chain.prev) {
+			uvc_trace(UVC_TRACE_DESCR, "Found reference to "
+				"entity %d already in chain.\n", forward->id);
+			return -EINVAL;
+		}
 
 		switch (UVC_ENTITY_TYPE(forward)) {
 		case UVC_VC_EXTENSION_UNIT:
@@ -1450,6 +1455,13 @@ static int uvc_scan_chain_backward(struc
 				return -1;
 			}
 
+			if (term->chain.next || term->chain.prev) {
+				uvc_trace(UVC_TRACE_DESCR, "Found reference to "
+					"entity %d already in chain.\n",
+					term->id);
+				return -EINVAL;
+			}
+
 			if (uvc_trace_param & UVC_TRACE_PROBE)
 				printk(" %d", term->id);
 


^ permalink raw reply	[relevance 7%]

* [PATCH 3.16 77/99] KVM: x86: Refactor picdev_write() to prevent Spectre-v1/L1TF attacks
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (75 preceding siblings ...)
  2020-05-20 14:14 12% ` [PATCH 3.16 76/99] KVM: x86: Protect x86_decode_insn from Spectre-v1/L1TF attacks Ben Hutchings
@ 2020-05-20 14:14 12% ` Ben Hutchings
  2020-05-20 14:14 12% ` [PATCH 3.16 78/99] KVM: x86: Protect ioapic_read_indirect() from " Ben Hutchings
                   ` (22 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Paolo Bonzini, Andrew Honig, Nick Finco,
	Marios Pomonis, Jim Mattson

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Marios Pomonis <pomonis@google.com>

commit 14e32321f3606e4b0970200b6e5e47ee6f1e6410 upstream.

This fixes a Spectre-v1/L1TF vulnerability in picdev_write().
It replaces index computations based on the (attacked-controlled) port
number with constants through a minor refactoring.

Fixes: 85f455f7ddbe ("KVM: Add support for in-kernel PIC emulation")

Signed-off-by: Nick Finco <nifi@google.com>
Signed-off-by: Marios Pomonis <pomonis@google.com>
Reviewed-by: Andrew Honig <ahonig@google.com>
Reviewed-by: Jim Mattson <jmattson@google.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
[bwh: Backported to 3.16: pic_{,un}lock() are called outside the switch]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
--- a/arch/x86/kvm/i8259.c
+++ b/arch/x86/kvm/i8259.c
@@ -486,9 +486,11 @@ static int picdev_write(struct kvm_pic *
 	switch (addr) {
 	case 0x20:
 	case 0x21:
+		pic_ioport_write(&s->pics[0], addr, data);
+		break;
 	case 0xa0:
 	case 0xa1:
-		pic_ioport_write(&s->pics[addr >> 7], addr, data);
+		pic_ioport_write(&s->pics[1], addr, data);
 		break;
 	case 0x4d0:
 	case 0x4d1:


^ permalink raw reply	[relevance 12%]

* [PATCH 3.16 50/99] usb: gadget: f_ecm: Use atomic_t to track in-flight request
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (48 preceding siblings ...)
  2020-05-20 14:14 11% ` [PATCH 3.16 49/99] usb: gadget: f_ncm: Use atomic_t to track in-flight request Ben Hutchings
@ 2020-05-20 14:14 11% ` Ben Hutchings
  2020-05-20 14:14  9% ` [PATCH 3.16 51/99] staging: wlan-ng: ensure error return is actually returned Ben Hutchings
                   ` (49 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:14 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Greg Kroah-Hartman, Bryan O'Donoghue,
	Felipe Balbi

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Bryan O'Donoghue <bryan.odonoghue@linaro.org>

commit d710562e01c48d59be3f60d58b7a85958b39aeda upstream.

Currently ecm->notify_req is used to flag when a request is in-flight.
ecm->notify_req is set to NULL and when a request completes it is
subsequently reset.

This is fundamentally buggy in that the unbind logic of the ECM driver will
unconditionally free ecm->notify_req leading to a NULL pointer dereference.

Fixes: da741b8c56d6 ("usb ethernet gadget: split CDC Ethernet function")
Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Signed-off-by: Felipe Balbi <balbi@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
[bwh: Backported to 3.16: adjust filename]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/usb/gadget/f_ecm.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

--- a/drivers/usb/gadget/f_ecm.c
+++ b/drivers/usb/gadget/f_ecm.c
@@ -56,6 +56,7 @@ struct f_ecm {
 	struct usb_ep			*notify;
 	struct usb_request		*notify_req;
 	u8				notify_state;
+	atomic_t			notify_count;
 	bool				is_open;
 
 	/* FIXME is_open needs some irq-ish locking
@@ -384,7 +385,7 @@ static void ecm_do_notify(struct f_ecm *
 	int				status;
 
 	/* notification already in flight? */
-	if (!req)
+	if (atomic_read(&ecm->notify_count))
 		return;
 
 	event = req->buf;
@@ -424,10 +425,10 @@ static void ecm_do_notify(struct f_ecm *
 	event->bmRequestType = 0xA1;
 	event->wIndex = cpu_to_le16(ecm->ctrl_id);
 
-	ecm->notify_req = NULL;
+	atomic_inc(&ecm->notify_count);
 	status = usb_ep_queue(ecm->notify, req, GFP_ATOMIC);
 	if (status < 0) {
-		ecm->notify_req = req;
+		atomic_dec(&ecm->notify_count);
 		DBG(cdev, "notify --> %d\n", status);
 	}
 }
@@ -452,17 +453,19 @@ static void ecm_notify_complete(struct u
 	switch (req->status) {
 	case 0:
 		/* no fault */
+		atomic_dec(&ecm->notify_count);
 		break;
 	case -ECONNRESET:
 	case -ESHUTDOWN:
+		atomic_set(&ecm->notify_count, 0);
 		ecm->notify_state = ECM_NOTIFY_NONE;
 		break;
 	default:
 		DBG(cdev, "event %02x --> %d\n",
 			event->bNotificationType, req->status);
+		atomic_dec(&ecm->notify_count);
 		break;
 	}
-	ecm->notify_req = req;
 	ecm_do_notify(ecm);
 }
 
@@ -922,6 +925,11 @@ static void ecm_unbind(struct usb_config
 
 	usb_free_all_descriptors(f);
 
+	if (atomic_read(&ecm->notify_count)) {
+		usb_ep_dequeue(ecm->notify, ecm->notify_req);
+		atomic_set(&ecm->notify_count, 0);
+	}
+
 	kfree(ecm->notify_req->buf);
 	usb_ep_free_request(ecm->notify, ecm->notify_req);
 }


^ permalink raw reply	[relevance 11%]

* [PATCH 3.16 19/99] mmc: spi: Toggle SPI polarity, do not hardcode it
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (17 preceding siblings ...)
  2020-05-20 14:13  9% ` [PATCH 3.16 18/99] crypto: api - Fix race condition in crypto_spawn_alg Ben Hutchings
@ 2020-05-20 14:13  8% ` Ben Hutchings
  2020-05-20 14:13  9% ` [PATCH 3.16 20/99] reiserfs: Fix memory leak of journal device string Ben Hutchings
                   ` (80 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:13 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Mark Brown, Linus Walleij, Ulf Hansson,
	Phil Elwell

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Linus Walleij <linus.walleij@linaro.org>

commit af3ed119329cf9690598c5a562d95dfd128e91d6 upstream.

The code in mmc_spi_initsequence() tries to send a burst with
high chipselect and for this reason hardcodes the device into
SPI_CS_HIGH.

This is not good because the SPI_CS_HIGH flag indicates
logical "asserted" CS not always the physical level. In
some cases the signal is inverted in the GPIO library and
in that case SPI_CS_HIGH is already set, and enforcing
SPI_CS_HIGH again will actually drive it low.

Instead of hard-coding this, toggle the polarity so if the
default is LOW it goes high to assert chipselect but if it
is already high then toggle it low instead.

Cc: Phil Elwell <phil@raspberrypi.org>
Reported-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Reviewed-by: Mark Brown <broonie@kernel.org>
Link: https://lore.kernel.org/r/20191204152749.12652-1-linus.walleij@linaro.org
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/mmc/host/mmc_spi.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

--- a/drivers/mmc/host/mmc_spi.c
+++ b/drivers/mmc/host/mmc_spi.c
@@ -1149,17 +1149,22 @@ static void mmc_spi_initsequence(struct
 	 * SPI protocol.  Another is that when chipselect is released while
 	 * the card returns BUSY status, the clock must issue several cycles
 	 * with chipselect high before the card will stop driving its output.
+	 *
+	 * SPI_CS_HIGH means "asserted" here. In some cases like when using
+	 * GPIOs for chip select, SPI_CS_HIGH is set but this will be logically
+	 * inverted by gpiolib, so if we want to ascertain to drive it high
+	 * we should toggle the default with an XOR as we do here.
 	 */
-	host->spi->mode |= SPI_CS_HIGH;
+	host->spi->mode ^= SPI_CS_HIGH;
 	if (spi_setup(host->spi) != 0) {
 		/* Just warn; most cards work without it. */
 		dev_warn(&host->spi->dev,
 				"can't change chip-select polarity\n");
-		host->spi->mode &= ~SPI_CS_HIGH;
+		host->spi->mode ^= SPI_CS_HIGH;
 	} else {
 		mmc_spi_readbytes(host, 18);
 
-		host->spi->mode &= ~SPI_CS_HIGH;
+		host->spi->mode ^= SPI_CS_HIGH;
 		if (spi_setup(host->spi) != 0) {
 			/* Wot, we can't get the same setup we had before? */
 			dev_err(&host->spi->dev,


^ permalink raw reply	[relevance 8%]

* [PATCH 3.16 20/99] reiserfs: Fix memory leak of journal device string
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (18 preceding siblings ...)
  2020-05-20 14:13  8% ` [PATCH 3.16 19/99] mmc: spi: Toggle SPI polarity, do not hardcode it Ben Hutchings
@ 2020-05-20 14:13  9% ` Ben Hutchings
  2020-05-20 14:13  9% ` [PATCH 3.16 21/99] reiserfs: Fix spurious unlock in reiserfs_fill_super() error handling Ben Hutchings
                   ` (79 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:13 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, syzbot+1c6756baf4b16b94d2a6, Jan Kara

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Jan Kara <jack@suse.cz>

commit 5474ca7da6f34fa95e82edc747d5faa19cbdfb5c upstream.

When a filesystem is mounted with jdev mount option, we store the
journal device name in an allocated string in superblock. However we
fail to ever free that string. Fix it.

Reported-by: syzbot+1c6756baf4b16b94d2a6@syzkaller.appspotmail.com
Fixes: c3aa077648e1 ("reiserfs: Properly display mount options in /proc/mounts")
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 fs/reiserfs/super.c | 2 ++
 1 file changed, 2 insertions(+)

--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -589,6 +589,7 @@ static void reiserfs_put_super(struct su
 	reiserfs_write_unlock(s);
 	mutex_destroy(&REISERFS_SB(s)->lock);
 	destroy_workqueue(REISERFS_SB(s)->commit_wq);
+	kfree(REISERFS_SB(s)->s_jdev);
 	kfree(s->s_fs_info);
 	s->s_fs_info = NULL;
 }
@@ -2188,6 +2189,7 @@ error_unlocked:
 			kfree(qf_names[j]);
 	}
 #endif
+	kfree(sbi->s_jdev);
 	kfree(sbi);
 
 	s->s_fs_info = NULL;


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 17/99] crypto: api - Check spawn->alg under lock in crypto_drop_spawn
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (15 preceding siblings ...)
  2020-05-20 14:13  9% ` [PATCH 3.16 16/99] crypto: af_alg - Use bh_lock_sock in sk_destruct Ben Hutchings
@ 2020-05-20 14:13  9% ` Ben Hutchings
  2020-05-20 14:13  9% ` [PATCH 3.16 18/99] crypto: api - Fix race condition in crypto_spawn_alg Ben Hutchings
                   ` (82 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:13 UTC (permalink / raw)
  To: linux-kernel, stable; +Cc: akpm, Denis Kirjanov, Herbert Xu

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Herbert Xu <herbert@gondor.apana.org.au>

commit 7db3b61b6bba4310f454588c2ca6faf2958ad79f upstream.

We need to check whether spawn->alg is NULL under lock as otherwise
the algorithm could be removed from under us after we have checked
it and found it to be non-NULL.  This could cause us to remove the
spawn from a non-existent list.

Fixes: 7ede5a5ba55a ("crypto: api - Fix crypto_drop_spawn crash...")
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 crypto/algapi.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

--- a/crypto/algapi.c
+++ b/crypto/algapi.c
@@ -618,11 +618,9 @@ EXPORT_SYMBOL_GPL(crypto_init_spawn2);
 
 void crypto_drop_spawn(struct crypto_spawn *spawn)
 {
-	if (!spawn->alg)
-		return;
-
 	down_write(&crypto_alg_sem);
-	list_del(&spawn->list);
+	if (spawn->alg)
+		list_del(&spawn->list);
 	up_write(&crypto_alg_sem);
 }
 EXPORT_SYMBOL_GPL(crypto_drop_spawn);


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 14/99] crypto: pcrypt - Do not clear MAY_SLEEP flag in original request
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (12 preceding siblings ...)
  2020-05-20 14:13 13% ` [PATCH 3.16 13/99] crypto: pcrypt - Fix user-after-free on module unload Ben Hutchings
@ 2020-05-20 14:13  9% ` Ben Hutchings
  2020-05-20 14:13  8% ` [PATCH 3.16 15/99] padata: always acquire cpu_hotplug_lock before pinst->lock Ben Hutchings
                   ` (85 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:13 UTC (permalink / raw)
  To: linux-kernel, stable; +Cc: akpm, Denis Kirjanov, Eric Biggers, Herbert Xu

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Herbert Xu <herbert@gondor.apana.org.au>

commit e8d998264bffade3cfe0536559f712ab9058d654 upstream.

We should not be modifying the original request's MAY_SLEEP flag
upon completion.  It makes no sense to do so anyway.

Reported-by: Eric Biggers <ebiggers@kernel.org>
Fixes: 5068c7a883d1 ("crypto: pcrypt - Add pcrypt crypto...")
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Tested-by: Eric Biggers <ebiggers@kernel.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 crypto/pcrypt.c | 1 -
 1 file changed, 1 deletion(-)

--- a/crypto/pcrypt.c
+++ b/crypto/pcrypt.c
@@ -137,7 +137,6 @@ static void pcrypt_aead_done(struct cryp
 	struct padata_priv *padata = pcrypt_request_padata(preq);
 
 	padata->info = err;
-	req->base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
 
 	padata_do_serial(padata);
 }


^ permalink raw reply	[relevance 9%]

* [PATCH 3.16 05/99] padata: avoid race in reordering
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (3 preceding siblings ...)
  2020-05-20 14:13  9% ` [PATCH 3.16 04/99] padata: Remove unused but set variables Ben Hutchings
@ 2020-05-20 14:13  8% ` Ben Hutchings
  2020-05-20 14:13  8% ` [PATCH 3.16 06/99] padata: get_next is never NULL Ben Hutchings
                   ` (94 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:13 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Jason A. Donenfeld, Herbert Xu, Steffen Klassert

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: "Jason A. Donenfeld" <Jason@zx2c4.com>

commit de5540d088fe97ad583cc7d396586437b32149a5 upstream.

Under extremely heavy uses of padata, crashes occur, and with list
debugging turned on, this happens instead:

[87487.298728] WARNING: CPU: 1 PID: 882 at lib/list_debug.c:33
__list_add+0xae/0x130
[87487.301868] list_add corruption. prev->next should be next
(ffffb17abfc043d0), but was ffff8dba70872c80. (prev=ffff8dba70872b00).
[87487.339011]  [<ffffffff9a53d075>] dump_stack+0x68/0xa3
[87487.342198]  [<ffffffff99e119a1>] ? console_unlock+0x281/0x6d0
[87487.345364]  [<ffffffff99d6b91f>] __warn+0xff/0x140
[87487.348513]  [<ffffffff99d6b9aa>] warn_slowpath_fmt+0x4a/0x50
[87487.351659]  [<ffffffff9a58b5de>] __list_add+0xae/0x130
[87487.354772]  [<ffffffff9add5094>] ? _raw_spin_lock+0x64/0x70
[87487.357915]  [<ffffffff99eefd66>] padata_reorder+0x1e6/0x420
[87487.361084]  [<ffffffff99ef0055>] padata_do_serial+0xa5/0x120

padata_reorder calls list_add_tail with the list to which its adding
locked, which seems correct:

spin_lock(&squeue->serial.lock);
list_add_tail(&padata->list, &squeue->serial.list);
spin_unlock(&squeue->serial.lock);

This therefore leaves only place where such inconsistency could occur:
if padata->list is added at the same time on two different threads.
This pdata pointer comes from the function call to
padata_get_next(pd), which has in it the following block:

next_queue = per_cpu_ptr(pd->pqueue, cpu);
padata = NULL;
reorder = &next_queue->reorder;
if (!list_empty(&reorder->list)) {
       padata = list_entry(reorder->list.next,
                           struct padata_priv, list);
       spin_lock(&reorder->lock);
       list_del_init(&padata->list);
       atomic_dec(&pd->reorder_objects);
       spin_unlock(&reorder->lock);

       pd->processed++;

       goto out;
}
out:
return padata;

I strongly suspect that the problem here is that two threads can race
on reorder list. Even though the deletion is locked, call to
list_entry is not locked, which means it's feasible that two threads
pick up the same padata object and subsequently call list_add_tail on
them at the same time. The fix is thus be hoist that lock outside of
that block.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Acked-by: Steffen Klassert <steffen.klassert@secunet.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 kernel/padata.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

--- a/kernel/padata.c
+++ b/kernel/padata.c
@@ -185,19 +185,20 @@ static struct padata_priv *padata_get_ne
 
 	reorder = &next_queue->reorder;
 
+	spin_lock(&reorder->lock);
 	if (!list_empty(&reorder->list)) {
 		padata = list_entry(reorder->list.next,
 				    struct padata_priv, list);
 
-		spin_lock(&reorder->lock);
 		list_del_init(&padata->list);
 		atomic_dec(&pd->reorder_objects);
-		spin_unlock(&reorder->lock);
 
 		pd->processed++;
 
+		spin_unlock(&reorder->lock);
 		goto out;
 	}
+	spin_unlock(&reorder->lock);
 
 	if (__this_cpu_read(pd->pqueue->cpu_index) == next_queue->cpu_index) {
 		padata = ERR_PTR(-ENODATA);


^ permalink raw reply	[relevance 8%]

* [PATCH 3.16 09/99] padata: Replace delayed timer with immediate workqueue in padata_reorder
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
                   ` (7 preceding siblings ...)
  2020-05-20 14:13  8% ` [PATCH 3.16 08/99] padata: ensure padata_do_serial() " Ben Hutchings
@ 2020-05-20 14:13  8% ` Ben Hutchings
  2020-05-20 14:13  8% ` [PATCH 3.16 10/99] padata: initialize pd->cpu with effective cpumask Ben Hutchings
                   ` (90 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:13 UTC (permalink / raw)
  To: linux-kernel, stable; +Cc: akpm, Denis Kirjanov, Herbert Xu

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Herbert Xu <herbert@gondor.apana.org.au>

commit 6fc4dbcf0276279d488c5fbbfabe94734134f4fa upstream.

The function padata_reorder will use a timer when it cannot progress
while completed jobs are outstanding (pd->reorder_objects > 0).  This
is suboptimal as if we do end up using the timer then it would have
introduced a gratuitous delay of one second.

In fact we can easily distinguish between whether completed jobs
are outstanding and whether we can make progress.  All we have to
do is look at the next pqueue list.

This patch does that by replacing pd->processed with pd->cpu so
that the next pqueue is more accessible.

A work queue is used instead of the original try_again to avoid
hogging the CPU.

Note that we don't bother removing the work queue in
padata_flush_queues because the whole premise is broken.  You
cannot flush async crypto requests so it makes no sense to even
try.  A subsequent patch will fix it by replacing it with a ref
counting scheme.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
[bwh: Backported to 3.16:
 - Deleted code used the old timer API here
 - Adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 include/linux/padata.h | 13 ++----
 kernel/padata.c        | 97 ++++++++----------------------------------
 2 files changed, 22 insertions(+), 88 deletions(-)

--- a/include/linux/padata.h
+++ b/include/linux/padata.h
@@ -24,7 +24,6 @@
 #include <linux/workqueue.h>
 #include <linux/spinlock.h>
 #include <linux/list.h>
-#include <linux/timer.h>
 #include <linux/notifier.h>
 #include <linux/kobject.h>
 
@@ -85,18 +84,14 @@ struct padata_serial_queue {
  * @serial: List to wait for serialization after reordering.
  * @pwork: work struct for parallelization.
  * @swork: work struct for serialization.
- * @pd: Backpointer to the internal control structure.
  * @work: work struct for parallelization.
- * @reorder_work: work struct for reordering.
  * @num_obj: Number of objects that are processed by this cpu.
  * @cpu_index: Index of the cpu.
  */
 struct padata_parallel_queue {
        struct padata_list    parallel;
        struct padata_list    reorder;
-       struct parallel_data *pd;
        struct work_struct    work;
-       struct work_struct    reorder_work;
        atomic_t              num_obj;
        int                   cpu_index;
 };
@@ -122,10 +117,10 @@ struct padata_cpumask {
  * @reorder_objects: Number of objects waiting in the reorder queues.
  * @refcnt: Number of objects holding a reference on this parallel_data.
  * @max_seq_nr:  Maximal used sequence number.
+ * @cpu: Next CPU to be processed.
  * @cpumask: The cpumasks in use for parallel and serial workers.
+ * @reorder_work: work struct for reordering.
  * @lock: Reorder lock.
- * @processed: Number of already processed objects.
- * @timer: Reorder timer.
  */
 struct parallel_data {
 	struct padata_instance		*pinst;
@@ -134,10 +129,10 @@ struct parallel_data {
 	atomic_t			reorder_objects;
 	atomic_t			refcnt;
 	atomic_t			seq_nr;
+	int				cpu;
 	struct padata_cpumask		cpumask;
+	struct work_struct		reorder_work;
 	spinlock_t                      lock ____cacheline_aligned;
-	unsigned int			processed;
-	struct timer_list		timer;
 };
 
 /**
--- a/kernel/padata.c
+++ b/kernel/padata.c
@@ -163,23 +163,12 @@ EXPORT_SYMBOL(padata_do_parallel);
  */
 static struct padata_priv *padata_get_next(struct parallel_data *pd)
 {
-	int cpu, num_cpus;
-	unsigned int next_nr, next_index;
 	struct padata_parallel_queue *next_queue;
 	struct padata_priv *padata;
 	struct padata_list *reorder;
+	int cpu = pd->cpu;
 
-	num_cpus = cpumask_weight(pd->cpumask.pcpu);
-
-	/*
-	 * Calculate the percpu reorder queue and the sequence
-	 * number of the next object.
-	 */
-	next_nr = pd->processed;
-	next_index = next_nr % num_cpus;
-	cpu = padata_index_to_cpu(pd, next_index);
 	next_queue = per_cpu_ptr(pd->pqueue, cpu);
-
 	reorder = &next_queue->reorder;
 
 	spin_lock(&reorder->lock);
@@ -190,7 +179,8 @@ static struct padata_priv *padata_get_ne
 		list_del_init(&padata->list);
 		atomic_dec(&pd->reorder_objects);
 
-		pd->processed++;
+		pd->cpu = cpumask_next_wrap(cpu, pd->cpumask.pcpu, -1,
+					    false);
 
 		spin_unlock(&reorder->lock);
 		goto out;
@@ -213,6 +203,7 @@ static void padata_reorder(struct parall
 	struct padata_priv *padata;
 	struct padata_serial_queue *squeue;
 	struct padata_instance *pinst = pd->pinst;
+	struct padata_parallel_queue *next_queue;
 
 	/*
 	 * We need to ensure that only one cpu can work on dequeueing of
@@ -244,7 +235,6 @@ static void padata_reorder(struct parall
 		 * so exit immediately.
 		 */
 		if (PTR_ERR(padata) == -ENODATA) {
-			del_timer(&pd->timer);
 			spin_unlock_bh(&pd->lock);
 			return;
 		}
@@ -263,70 +253,29 @@ static void padata_reorder(struct parall
 
 	/*
 	 * The next object that needs serialization might have arrived to
-	 * the reorder queues in the meantime, we will be called again
-	 * from the timer function if no one else cares for it.
+	 * the reorder queues in the meantime.
 	 *
-	 * Ensure reorder_objects is read after pd->lock is dropped so we see
-	 * an increment from another task in padata_do_serial.  Pairs with
+	 * Ensure reorder queue is read after pd->lock is dropped so we see
+	 * new objects from another task in padata_do_serial.  Pairs with
 	 * smp_mb__after_atomic in padata_do_serial.
 	 */
 	smp_mb();
-	if (atomic_read(&pd->reorder_objects)
-			&& !(pinst->flags & PADATA_RESET))
-		mod_timer(&pd->timer, jiffies + HZ);
-	else
-		del_timer(&pd->timer);
 
-	return;
+	next_queue = per_cpu_ptr(pd->pqueue, pd->cpu);
+	if (!list_empty(&next_queue->reorder.list))
+		queue_work(pinst->wq, &pd->reorder_work);
 }
 
 static void invoke_padata_reorder(struct work_struct *work)
 {
-	struct padata_parallel_queue *pqueue;
 	struct parallel_data *pd;
 
 	local_bh_disable();
-	pqueue = container_of(work, struct padata_parallel_queue, reorder_work);
-	pd = pqueue->pd;
+	pd = container_of(work, struct parallel_data, reorder_work);
 	padata_reorder(pd);
 	local_bh_enable();
 }
 
-static void padata_reorder_timer(unsigned long arg)
-{
-	struct parallel_data *pd = (struct parallel_data *)arg;
-	unsigned int weight;
-	int target_cpu, cpu;
-
-	cpu = get_cpu();
-
-	/* We don't lock pd here to not interfere with parallel processing
-	 * padata_reorder() calls on other CPUs. We just need any CPU out of
-	 * the cpumask.pcpu set. It would be nice if it's the right one but
-	 * it doesn't matter if we're off to the next one by using an outdated
-	 * pd->processed value.
-	 */
-	weight = cpumask_weight(pd->cpumask.pcpu);
-	target_cpu = padata_index_to_cpu(pd, pd->processed % weight);
-
-	/* ensure to call the reorder callback on the correct CPU */
-	if (cpu != target_cpu) {
-		struct padata_parallel_queue *pqueue;
-		struct padata_instance *pinst;
-
-		/* The timer function is serialized wrt itself -- no locking
-		 * needed.
-		 */
-		pinst = pd->pinst;
-		pqueue = per_cpu_ptr(pd->pqueue, target_cpu);
-		queue_work_on(target_cpu, pinst->wq, &pqueue->reorder_work);
-	} else {
-		padata_reorder(pd);
-	}
-
-	put_cpu();
-}
-
 static void padata_serial_worker(struct work_struct *serial_work)
 {
 	struct padata_serial_queue *squeue;
@@ -374,9 +323,8 @@ void padata_do_serial(struct padata_priv
 
 	cpu = get_cpu();
 
-	/* We need to run on the same CPU padata_do_parallel(.., padata, ..)
-	 * was called on -- or, at least, enqueue the padata object into the
-	 * correct per-cpu queue.
+	/* We need to enqueue the padata object into the correct
+	 * per-cpu queue.
 	 */
 	if (cpu != padata->cpu) {
 		reorder_via_wq = 1;
@@ -386,12 +334,12 @@ void padata_do_serial(struct padata_priv
 	pqueue = per_cpu_ptr(pd->pqueue, cpu);
 
 	spin_lock(&pqueue->reorder.lock);
-	atomic_inc(&pd->reorder_objects);
 	list_add_tail(&padata->list, &pqueue->reorder.list);
+	atomic_inc(&pd->reorder_objects);
 	spin_unlock(&pqueue->reorder.lock);
 
 	/*
-	 * Ensure the atomic_inc of reorder_objects above is ordered correctly
+	 * Ensure the addition to the reorder list is ordered correctly
 	 * with the trylock of pd->lock in padata_reorder.  Pairs with smp_mb
 	 * in padata_reorder.
 	 */
@@ -399,13 +347,7 @@ void padata_do_serial(struct padata_priv
 
 	put_cpu();
 
-	/* If we're running on the wrong CPU, call padata_reorder() via a
-	 * kernel worker.
-	 */
-	if (reorder_via_wq)
-		queue_work_on(cpu, pd->pinst->wq, &pqueue->reorder_work);
-	else
-		padata_reorder(pd);
+	padata_reorder(pd);
 }
 EXPORT_SYMBOL(padata_do_serial);
 
@@ -455,14 +397,12 @@ static void padata_init_pqueues(struct p
 	cpu_index = 0;
 	for_each_cpu(cpu, pd->cpumask.pcpu) {
 		pqueue = per_cpu_ptr(pd->pqueue, cpu);
-		pqueue->pd = pd;
 		pqueue->cpu_index = cpu_index;
 		cpu_index++;
 
 		__padata_list_init(&pqueue->reorder);
 		__padata_list_init(&pqueue->parallel);
 		INIT_WORK(&pqueue->work, padata_parallel_worker);
-		INIT_WORK(&pqueue->reorder_work, invoke_padata_reorder);
 		atomic_set(&pqueue->num_obj, 0);
 	}
 }
@@ -490,12 +430,13 @@ static struct parallel_data *padata_allo
 
 	padata_init_pqueues(pd);
 	padata_init_squeues(pd);
-	setup_timer(&pd->timer, padata_reorder_timer, (unsigned long)pd);
 	atomic_set(&pd->seq_nr, -1);
 	atomic_set(&pd->reorder_objects, 0);
 	atomic_set(&pd->refcnt, 0);
 	pd->pinst = pinst;
 	spin_lock_init(&pd->lock);
+	pd->cpu = cpumask_first(pcpumask);
+	INIT_WORK(&pd->reorder_work, invoke_padata_reorder);
 
 	return pd;
 
@@ -530,8 +471,6 @@ static void padata_flush_queues(struct p
 		flush_work(&pqueue->work);
 	}
 
-	del_timer_sync(&pd->timer);
-
 	if (atomic_read(&pd->reorder_objects))
 		padata_reorder(pd);
 


^ permalink raw reply	[relevance 8%]

* [PATCH 3.16 02/99] propagate_one(): mnt_set_mountpoint() needs mount_lock
  2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
  2020-05-20 14:13  9% ` [PATCH 3.16 01/99] fs/namespace.c: fix mountpoint reference counter race Ben Hutchings
@ 2020-05-20 14:13 12% ` Ben Hutchings
  2020-05-20 14:13 10% ` [PATCH 3.16 03/99] spi: spi-dw: Add lock protect dw_spi rx/tx to prevent concurrent calls Ben Hutchings
                   ` (97 subsequent siblings)
  99 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-05-20 14:13 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: akpm, Denis Kirjanov, Greg Kroah-Hartman, stable, Piotr Krysiuk, Al Viro

3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Al Viro <viro@zeniv.linux.org.uk>

commit b0d3869ce9eeacbb1bbd541909beeef4126426d5 upstream.

... to protect the modification of mp->m_count done by it.  Most of
the places that modify that thing also have namespace_lock held,
but not all of them can do so, so we really need mount_lock here.
Kudos to Piotr Krysiuk <piotras@gmail.com>, who'd spotted a related
bug in pivot_root(2) (fixed unnoticed in 5.3); search for other
similar turds has caught out this one.

Cc: stable@kernel.org
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Piotr Krysiuk <piotras@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 fs/pnode.c |    9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

--- a/fs/pnode.c
+++ b/fs/pnode.c
@@ -249,14 +249,13 @@ static int propagate_one(struct mount *m
 	child = copy_tree(last_source, last_source->mnt.mnt_root, type);
 	if (IS_ERR(child))
 		return PTR_ERR(child);
+	read_seqlock_excl(&mount_lock);
 	mnt_set_mountpoint(m, mp, child);
+	if (m->mnt_master != dest_master)
+		SET_MNT_MARK(m->mnt_master);
+	read_sequnlock_excl(&mount_lock);
 	last_dest = m;
 	last_source = child;
-	if (m->mnt_master != dest_master) {
-		read_seqlock_excl(&mount_lock);
-		SET_MNT_MARK(m->mnt_master);
-		read_sequnlock_excl(&mount_lock);
-	}
 	hlist_add_head(&child->mnt_hash, list);
 	return count_mounts(m->mnt_ns, child);
 }


^ permalink raw reply	[relevance 12%]

* [PATCH] doc:it_IT: align Italian translation
@ 2020-04-30 22:20  4% Federico Vaga
  0 siblings, 0 replies; 200+ results
From: Federico Vaga @ 2020-04-30 22:20 UTC (permalink / raw)
  To: Jonathan Corbet; +Cc: linux-kernel, linux-doc, Federico Vaga

Translation for the following patches:

commit c4f4af4094d6 ("docs: Add documentation for Symbol Namespaces")
commit 36bc683dde0a ("kernel-doc: rename the kernel-doc directive 'functions' to 'identifiers'")
commit a035d552a93b ("Makefile: Globally enable fall-through warning")
commit b9918bdcac1f ("Documentation/process: Add fallthrough pseudo-keyword")
commit 58ad30cf91f0 ("docs: fix reference to core-api/namespaces.rst")
commit fb0e0ffe7fc8 ("Documentation: bring process docs up to date")
commit 7af51678b6d3 ("docs: deprecated.rst: Add BUG()-family")
commit 7929b9836ed0 ("docs: Remove :c:func: from process/deprecated.rst")
commit 76136e028d3b ("docs: deprecated.rst: Clean up fall-through details")
commit d8401f504b49 ("docs: deprecated.rst: Add %p to the list")
commit b1735296cef9 ("docs: locking: Drop :c:func: throughout")
commit 6adb7755996f ("docs: locking: Add 'need' to hardirq section")

Signed-off-by: Federico Vaga <federico.vaga@vaga.pv.it>
---
 .../it_IT/doc-guide/kernel-doc.rst            |  25 ++-
 .../it_IT/kernel-hacking/hacking.rst          |  18 ++
 .../it_IT/kernel-hacking/locking.rst          | 172 +++++++++---------
 .../translations/it_IT/process/2.Process.rst  |  95 +++++-----
 .../it_IT/process/coding-style.rst            |   6 +-
 .../translations/it_IT/process/deprecated.rst | 130 +++++++++++--
 6 files changed, 287 insertions(+), 159 deletions(-)

diff --git a/Documentation/translations/it_IT/doc-guide/kernel-doc.rst b/Documentation/translations/it_IT/doc-guide/kernel-doc.rst
index a4ecd8f27631..524ad86cadbb 100644
--- a/Documentation/translations/it_IT/doc-guide/kernel-doc.rst
+++ b/Documentation/translations/it_IT/doc-guide/kernel-doc.rst
@@ -515,6 +515,22 @@ internal: *[source-pattern ...]*
     .. kernel-doc:: drivers/gpu/drm/i915/intel_audio.c
        :internal:
 
+identifiers: *[ function/type ...]*
+  Include la documentazione per ogni *function* e *type*  in *source*.
+  Se non vengono esplicitamente specificate le funzioni da includere, allora
+  verranno incluse tutte quelle disponibili in *source*.
+
+  Esempi::
+
+    .. kernel-doc:: lib/bitmap.c
+       :identifiers: bitmap_parselist bitmap_parselist_user
+
+    .. kernel-doc:: lib/idr.c
+       :identifiers:
+
+functions: *[ function ...]*
+  Questo è uno pseudonimo, deprecato, per la direttiva 'identifiers'.
+
 doc: *title*
   Include la documentazione del paragrafo ``DOC:`` identificato dal titolo
   (*title*) all'interno del file sorgente (*source*). Gli spazi in *title* sono
@@ -528,15 +544,6 @@ doc: *title*
     .. kernel-doc:: drivers/gpu/drm/i915/intel_audio.c
        :doc: High Definition Audio over HDMI and Display Port
 
-functions: *function* *[...]*
-  Dal file sorgente (*source*) include la documentazione per le funzioni
-  elencate (*function*).
-
-  Esempio::
-
-    .. kernel-doc:: lib/bitmap.c
-       :functions: bitmap_parselist bitmap_parselist_user
-
 Senza alcuna opzione, la direttiva kernel-doc include tutti i commenti di
 documentazione presenti nel file sorgente (*source*).
 
diff --git a/Documentation/translations/it_IT/kernel-hacking/hacking.rst b/Documentation/translations/it_IT/kernel-hacking/hacking.rst
index 24c592852bf1..6aab27a8d323 100644
--- a/Documentation/translations/it_IT/kernel-hacking/hacking.rst
+++ b/Documentation/translations/it_IT/kernel-hacking/hacking.rst
@@ -627,6 +627,24 @@ Alcuni manutentori e sviluppatori potrebbero comunque richiedere
 :c:func:`EXPORT_SYMBOL_GPL()` quando si aggiungono nuove funzionalità o
 interfacce.
 
+:c:func:`EXPORT_SYMBOL_NS()`
+----------------------------
+
+Definita in ``include/linux/export.h``
+
+Questa è una variate di `EXPORT_SYMBOL()` che permette di specificare uno
+spazio dei nomi. Lo spazio dei nomi è documentato in
+:doc:`../core-api/symbol-namespaces`
+
+:c:func:`EXPORT_SYMBOL_NS_GPL()`
+--------------------------------
+
+Definita in ``include/linux/export.h``
+
+Questa è una variate di `EXPORT_SYMBOL_GPL()` che permette di specificare uno
+spazio dei nomi. Lo spazio dei nomi è documentato in
+:doc:`../core-api/symbol-namespaces`
+
 Procedure e convenzioni
 =======================
 
diff --git a/Documentation/translations/it_IT/kernel-hacking/locking.rst b/Documentation/translations/it_IT/kernel-hacking/locking.rst
index b9a6be4b8499..4615df5723fb 100644
--- a/Documentation/translations/it_IT/kernel-hacking/locking.rst
+++ b/Documentation/translations/it_IT/kernel-hacking/locking.rst
@@ -159,17 +159,17 @@ Sincronizzazione in contesto utente
 Se avete una struttura dati che verrà utilizzata solo dal contesto utente,
 allora, per proteggerla, potete utilizzare un semplice mutex
 (``include/linux/mutex.h``). Questo è il caso più semplice: inizializzate il
-mutex; invocate :c:func:`mutex_lock_interruptible()` per trattenerlo e
-:c:func:`mutex_unlock()` per rilasciarlo. C'è anche :c:func:`mutex_lock()`
+mutex; invocate mutex_lock_interruptible() per trattenerlo e
+mutex_unlock() per rilasciarlo. C'è anche mutex_lock()
 ma questa dovrebbe essere evitata perché non ritorna in caso di segnali.
 
 Per esempio: ``net/netfilter/nf_sockopt.c`` permette la registrazione
-di nuove chiamate per :c:func:`setsockopt()` e :c:func:`getsockopt()`
-usando la funzione :c:func:`nf_register_sockopt()`. La registrazione e
+di nuove chiamate per setsockopt() e getsockopt()
+usando la funzione nf_register_sockopt(). La registrazione e
 la rimozione vengono eseguite solamente quando il modulo viene caricato
 o scaricato (e durante l'avvio del sistema, qui non abbiamo concorrenza),
 e la lista delle funzioni registrate viene consultata solamente quando
-:c:func:`setsockopt()` o :c:func:`getsockopt()` sono sconosciute al sistema.
+setsockopt() o getsockopt() sono sconosciute al sistema.
 In questo caso ``nf_sockopt_mutex`` è perfetto allo scopo, in particolar modo
 visto che setsockopt e getsockopt potrebbero dormire.
 
@@ -179,19 +179,19 @@ Sincronizzazione fra il contesto utente e i softirq
 Se un softirq condivide dati col contesto utente, avete due problemi.
 Primo, il contesto utente corrente potrebbe essere interroto da un softirq,
 e secondo, la sezione critica potrebbe essere eseguita da un altro
-processore. Questo è quando :c:func:`spin_lock_bh()`
+processore. Questo è quando spin_lock_bh()
 (``include/linux/spinlock.h``) viene utilizzato. Questo disabilita i softirq
-sul processore e trattiene il *lock*. Invece, :c:func:`spin_unlock_bh()` fa
+sul processore e trattiene il *lock*. Invece, spin_unlock_bh() fa
 l'opposto. (Il suffisso '_bh' è un residuo storico che fa riferimento al
 "Bottom Halves", il vecchio nome delle interruzioni software. In un mondo
 perfetto questa funzione si chiamerebbe 'spin_lock_softirq()').
 
-Da notare che in questo caso potete utilizzare anche :c:func:`spin_lock_irq()`
-o :c:func:`spin_lock_irqsave()`, queste fermano anche le interruzioni hardware:
+Da notare che in questo caso potete utilizzare anche spin_lock_irq()
+o spin_lock_irqsave(), queste fermano anche le interruzioni hardware:
 vedere :ref:`Contesto di interruzione hardware <it_hardirq-context>`.
 
 Questo funziona alla perfezione anche sui sistemi monoprocessore: gli spinlock
-svaniscono e questa macro diventa semplicemente :c:func:`local_bh_disable()`
+svaniscono e questa macro diventa semplicemente local_bh_disable()
 (``include/linux/interrupt.h``), la quale impedisce ai softirq d'essere
 eseguiti.
 
@@ -224,8 +224,8 @@ Differenti tasklet/timer
 ~~~~~~~~~~~~~~~~~~~~~~~~
 
 Se un altro tasklet/timer vuole condividere dati col vostro tasklet o timer,
-allora avrete bisogno entrambe di :c:func:`spin_lock()` e
-:c:func:`spin_unlock()`. Qui :c:func:`spin_lock_bh()` è inutile, siete già
+allora avrete bisogno entrambe di spin_lock() e
+spin_unlock(). Qui spin_lock_bh() è inutile, siete già
 in un tasklet ed avete la garanzia che nessun altro verrà eseguito sullo
 stesso processore.
 
@@ -243,13 +243,13 @@ processore (vedere :ref:`Dati per processore <it_per-cpu>`). Se siete arrivati
 fino a questo punto nell'uso dei softirq, probabilmente tenete alla scalabilità
 delle prestazioni abbastanza da giustificarne la complessità aggiuntiva.
 
-Dovete utilizzare :c:func:`spin_lock()` e :c:func:`spin_unlock()` per
+Dovete utilizzare spin_lock() e spin_unlock() per
 proteggere i dati condivisi.
 
 Diversi Softirqs
 ~~~~~~~~~~~~~~~~
 
-Dovete utilizzare :c:func:`spin_lock()` e :c:func:`spin_unlock()` per
+Dovete utilizzare spin_lock() e spin_unlock() per
 proteggere i dati condivisi, che siano timer, tasklet, diversi softirq o
 lo stesso o altri softirq: uno qualsiasi di essi potrebbe essere in esecuzione
 su un diverso processore.
@@ -270,40 +270,40 @@ Se un gestore di interruzioni hardware condivide dati con un softirq, allora
 avrete due preoccupazioni. Primo, il softirq può essere interrotto da
 un'interruzione hardware, e secondo, la sezione critica potrebbe essere
 eseguita da un'interruzione hardware su un processore diverso. Questo è il caso
-dove :c:func:`spin_lock_irq()` viene utilizzato. Disabilita le interruzioni
-sul processore che l'esegue, poi trattiene il lock. :c:func:`spin_unlock_irq()`
+dove spin_lock_irq() viene utilizzato. Disabilita le interruzioni
+sul processore che l'esegue, poi trattiene il lock. spin_unlock_irq()
 fa l'opposto.
 
-Il gestore d'interruzione hardware non usa :c:func:`spin_lock_irq()` perché
-i softirq non possono essere eseguiti quando il gestore d'interruzione hardware
-è in esecuzione: per questo si può usare :c:func:`spin_lock()`, che è un po'
+Il gestore d'interruzione hardware non ha bisogno di usare spin_lock_irq()
+perché i softirq non possono essere eseguiti quando il gestore d'interruzione
+hardware è in esecuzione: per questo si può usare spin_lock(), che è un po'
 più veloce. L'unica eccezione è quando un altro gestore d'interruzioni
-hardware utilizza lo stesso *lock*: :c:func:`spin_lock_irq()` impedirà a questo
+hardware utilizza lo stesso *lock*: spin_lock_irq() impedirà a questo
 secondo gestore di interrompere quello in esecuzione.
 
 Questo funziona alla perfezione anche sui sistemi monoprocessore: gli spinlock
-svaniscono e questa macro diventa semplicemente :c:func:`local_irq_disable()`
+svaniscono e questa macro diventa semplicemente local_irq_disable()
 (``include/asm/smp.h``), la quale impedisce a softirq/tasklet/BH d'essere
 eseguiti.
 
-:c:func:`spin_lock_irqsave()` (``include/linux/spinlock.h``) è una variante che
+spin_lock_irqsave() (``include/linux/spinlock.h``) è una variante che
 salva lo stato delle interruzioni in una variabile, questa verrà poi passata
-a :c:func:`spin_unlock_irqrestore()`. Questo significa che lo stesso codice
+a spin_unlock_irqrestore(). Questo significa che lo stesso codice
 potrà essere utilizzato in un'interruzione hardware (dove le interruzioni sono
 già disabilitate) e in un softirq (dove la disabilitazione delle interruzioni
 è richiesta).
 
 Da notare che i softirq (e quindi tasklet e timer) sono eseguiti al ritorno
-da un'interruzione hardware, quindi :c:func:`spin_lock_irq()` interrompe
+da un'interruzione hardware, quindi spin_lock_irq() interrompe
 anche questi. Tenuto conto di questo si può dire che
-:c:func:`spin_lock_irqsave()` è la funzione di sincronizzazione più generica
+spin_lock_irqsave() è la funzione di sincronizzazione più generica
 e potente.
 
 Sincronizzazione fra due gestori d'interruzioni hardware
 --------------------------------------------------------
 
 Condividere dati fra due gestori di interruzione hardware è molto raro, ma se
-succede, dovreste usare :c:func:`spin_lock_irqsave()`: è una specificità
+succede, dovreste usare spin_lock_irqsave(): è una specificità
 dell'architettura il fatto che tutte le interruzioni vengano interrotte
 quando si eseguono di gestori di interruzioni.
 
@@ -317,11 +317,11 @@ Pete Zaitcev ci offre il seguente riassunto:
    il mutex e dormire (``copy_from_user*(`` o ``kmalloc(x,GFP_KERNEL)``).
 
 -  Altrimenti (== i dati possono essere manipolati da un'interruzione) usate
-   :c:func:`spin_lock_irqsave()` e :c:func:`spin_unlock_irqrestore()`.
+   spin_lock_irqsave() e spin_unlock_irqrestore().
 
 -  Evitate di trattenere uno spinlock per più di 5 righe di codice incluse
    le chiamate a funzione (ad eccezione di quell per l'accesso come
-   :c:func:`readb()`).
+   readb()).
 
 Tabella dei requisiti minimi
 ----------------------------
@@ -334,7 +334,7 @@ processore alla volta, ma se deve condividere dati con un altro thread, allora
 la sincronizzazione è necessaria).
 
 Ricordatevi il suggerimento qui sopra: potete sempre usare
-:c:func:`spin_lock_irqsave()`, che è un sovrainsieme di tutte le altre funzioni
+spin_lock_irqsave(), che è un sovrainsieme di tutte le altre funzioni
 per spinlock.
 
 ============== ============= ============= ========= ========= ========= ========= ======= ======= ============== ==============
@@ -378,13 +378,13 @@ protetti dal *lock* quando qualche altro thread lo sta già facendo
 trattenendo il *lock*. Potrete acquisire il *lock* più tardi se vi
 serve accedere ai dati protetti da questo *lock*.
 
-La funzione :c:func:`spin_trylock()` non ritenta di acquisire il *lock*,
+La funzione spin_trylock() non ritenta di acquisire il *lock*,
 se ci riesce al primo colpo ritorna un valore diverso da zero, altrimenti
 se fallisce ritorna 0. Questa funzione può essere utilizzata in un qualunque
-contesto, ma come :c:func:`spin_lock()`: dovete disabilitare i contesti che
+contesto, ma come spin_lock(): dovete disabilitare i contesti che
 potrebbero interrompervi e quindi trattenere lo spinlock.
 
-La funzione :c:func:`mutex_trylock()` invece di sospendere il vostro processo
+La funzione mutex_trylock() invece di sospendere il vostro processo
 ritorna un valore diverso da zero se è possibile trattenere il lock al primo
 colpo, altrimenti se fallisce ritorna 0. Nonostante non dorma, questa funzione
 non può essere usata in modo sicuro in contesti di interruzione hardware o
@@ -506,7 +506,7 @@ della memoria che il suo contenuto sono protetti dal *lock*. Questo
 caso è semplice dato che copiamo i dati dall'utente e non permettiamo
 mai loro di accedere direttamente agli oggetti.
 
-C'è una piccola ottimizzazione qui: nella funzione :c:func:`cache_add()`
+C'è una piccola ottimizzazione qui: nella funzione cache_add()
 impostiamo i campi dell'oggetto prima di acquisire il *lock*. Questo è
 sicuro perché nessun altro potrà accedervi finché non lo inseriremo
 nella memoria.
@@ -514,7 +514,7 @@ nella memoria.
 Accesso dal contesto utente
 ---------------------------
 
-Ora consideriamo il caso in cui :c:func:`cache_find()` può essere invocata
+Ora consideriamo il caso in cui cache_find() può essere invocata
 dal contesto d'interruzione: sia hardware che software. Un esempio potrebbe
 essere un timer che elimina oggetti dalla memoria.
 
@@ -583,15 +583,15 @@ sono quelle rimosse, mentre quelle ``+`` sono quelle aggiunte.
              return ret;
      }
 
-Da notare che :c:func:`spin_lock_irqsave()` disabiliterà le interruzioni
+Da notare che spin_lock_irqsave() disabiliterà le interruzioni
 se erano attive, altrimenti non farà niente (quando siamo già in un contesto
 d'interruzione); dunque queste funzioni possono essere chiamante in
 sicurezza da qualsiasi contesto.
 
-Sfortunatamente, :c:func:`cache_add()` invoca :c:func:`kmalloc()` con
+Sfortunatamente, cache_add() invoca kmalloc() con
 l'opzione ``GFP_KERNEL`` che è permessa solo in contesto utente. Ho supposto
-che :c:func:`cache_add()` venga chiamata dal contesto utente, altrimenti
-questa opzione deve diventare un parametro di :c:func:`cache_add()`.
+che cache_add() venga chiamata dal contesto utente, altrimenti
+questa opzione deve diventare un parametro di cache_add().
 
 Esporre gli oggetti al di fuori del file
 ----------------------------------------
@@ -610,7 +610,7 @@ Il secondo problema è il problema del ciclo di vita: se un'altra struttura
 mantiene un puntatore ad un oggetto, presumibilmente si aspetta che questo
 puntatore rimanga valido. Sfortunatamente, questo è garantito solo mentre
 si trattiene il *lock*, altrimenti qualcuno potrebbe chiamare
-:c:func:`cache_delete()` o peggio, aggiungere un oggetto che riutilizza lo
+cache_delete() o peggio, aggiungere un oggetto che riutilizza lo
 stesso indirizzo.
 
 Dato che c'è un solo *lock*, non potete trattenerlo a vita: altrimenti
@@ -710,9 +710,9 @@ Ecco il codice::
      }
 
 Abbiamo incapsulato il contatore di riferimenti nelle tipiche funzioni
-di 'get' e 'put'. Ora possiamo ritornare l'oggetto da :c:func:`cache_find()`
+di 'get' e 'put'. Ora possiamo ritornare l'oggetto da cache_find()
 col vantaggio che l'utente può dormire trattenendo l'oggetto (per esempio,
-:c:func:`copy_to_user()` per copiare il nome verso lo spazio utente).
+copy_to_user() per copiare il nome verso lo spazio utente).
 
 Un altro punto da notare è che ho detto che il contatore dovrebbe incrementarsi
 per ogni puntatore ad un oggetto: quindi il contatore di riferimenti è 1
@@ -727,8 +727,8 @@ Ci sono un certo numbero di operazioni atomiche definite
 in ``include/asm/atomic.h``: queste sono garantite come atomiche su qualsiasi
 processore del sistema, quindi non sono necessari i *lock*. In questo caso è
 più semplice rispetto all'uso degli spinlock, benché l'uso degli spinlock
-sia più elegante per casi non banali. Le funzioni :c:func:`atomic_inc()` e
-:c:func:`atomic_dec_and_test()` vengono usate al posto dei tipici operatori di
+sia più elegante per casi non banali. Le funzioni atomic_inc() e
+atomic_dec_and_test() vengono usate al posto dei tipici operatori di
 incremento e decremento, e i *lock* non sono più necessari per proteggere il
 contatore stesso.
 
@@ -820,7 +820,7 @@ al nome di cambiare abbiamo tre possibilità:
 -  Si può togliere static da ``cache_lock`` e dire agli utenti che devono
    trattenere il *lock* prima di modificare il nome di un oggetto.
 
--  Si può fornire una funzione :c:func:`cache_obj_rename()` che prende il
+-  Si può fornire una funzione cache_obj_rename() che prende il
    *lock* e cambia il nome per conto del chiamante; si dirà poi agli utenti
    di usare questa funzione.
 
@@ -878,11 +878,11 @@ Da notare che ho deciso che il contatore di popolarità dovesse essere
 protetto da ``cache_lock`` piuttosto che dal *lock* dell'oggetto; questo
 perché è logicamente parte dell'infrastruttura (come
 :c:type:`struct list_head <list_head>` nell'oggetto). In questo modo,
-in :c:func:`__cache_add()`, non ho bisogno di trattenere il *lock* di ogni
+in __cache_add(), non ho bisogno di trattenere il *lock* di ogni
 oggetto mentre si cerca il meno popolare.
 
 Ho anche deciso che il campo id è immutabile, quindi non ho bisogno di
-trattenere il lock dell'oggetto quando si usa :c:func:`__cache_find()`
+trattenere il lock dell'oggetto quando si usa __cache_find()
 per leggere questo campo; il *lock* dell'oggetto è usato solo dal chiamante
 che vuole leggere o scrivere il campo name.
 
@@ -907,7 +907,7 @@ Questo è facile da diagnosticare: non è uno di quei problemi che ti tengono
 sveglio 5 notti a parlare da solo.
 
 Un caso un pochino più complesso; immaginate d'avere una spazio condiviso
-fra un softirq ed il contesto utente. Se usate :c:func:`spin_lock()` per
+fra un softirq ed il contesto utente. Se usate spin_lock() per
 proteggerlo, il contesto utente potrebbe essere interrotto da un softirq
 mentre trattiene il lock, da qui il softirq rimarrà in attesa attiva provando
 ad acquisire il *lock* già trattenuto nel contesto utente.
@@ -1006,12 +1006,12 @@ potreste fare come segue::
             spin_unlock_bh(&list_lock);
 
 Primo o poi, questo esploderà su un sistema multiprocessore perché un
-temporizzatore potrebbe essere già partiro prima di :c:func:`spin_lock_bh()`,
-e prenderà il *lock* solo dopo :c:func:`spin_unlock_bh()`, e cercherà
+temporizzatore potrebbe essere già partiro prima di spin_lock_bh(),
+e prenderà il *lock* solo dopo spin_unlock_bh(), e cercherà
 di eliminare il suo oggetto (che però è già stato eliminato).
 
 Questo può essere evitato controllando il valore di ritorno di
-:c:func:`del_timer()`: se ritorna 1, il temporizzatore è stato già
+del_timer(): se ritorna 1, il temporizzatore è stato già
 rimosso. Se 0, significa (in questo caso) che il temporizzatore è in
 esecuzione, quindi possiamo fare come segue::
 
@@ -1032,9 +1032,9 @@ esecuzione, quindi possiamo fare come segue::
                     spin_unlock_bh(&list_lock);
 
 Un altro problema è l'eliminazione dei temporizzatori che si riavviano
-da soli (chiamando :c:func:`add_timer()` alla fine della loro esecuzione).
+da soli (chiamando add_timer() alla fine della loro esecuzione).
 Dato che questo è un problema abbastanza comune con una propensione
-alle corse critiche, dovreste usare :c:func:`del_timer_sync()`
+alle corse critiche, dovreste usare del_timer_sync()
 (``include/linux/timer.h``) per gestire questo caso. Questa ritorna il
 numero di volte che il temporizzatore è stato interrotto prima che
 fosse in grado di fermarlo senza che si riavviasse.
@@ -1116,7 +1116,7 @@ chiamata ``list``::
             wmb();
             list->next = new;
 
-La funzione :c:func:`wmb()` è una barriera di sincronizzazione delle
+La funzione wmb() è una barriera di sincronizzazione delle
 scritture. Questa garantisce che la prima operazione (impostare l'elemento
 ``next`` del nuovo elemento) venga completata e vista da tutti i processori
 prima che venga eseguita la seconda operazione (che sarebbe quella di mettere
@@ -1127,7 +1127,7 @@ completamente il nuovo elemento; oppure che lo vedano correttamente e quindi
 il puntatore ``next`` deve puntare al resto della lista.
 
 Fortunatamente, c'è una funzione che fa questa operazione sulle liste
-:c:type:`struct list_head <list_head>`: :c:func:`list_add_rcu()`
+:c:type:`struct list_head <list_head>`: list_add_rcu()
 (``include/linux/list.h``).
 
 Rimuovere un elemento dalla lista è anche più facile: sostituiamo il puntatore
@@ -1138,7 +1138,7 @@ l'elemento o lo salteranno.
 
             list->next = old->next;
 
-La funzione :c:func:`list_del_rcu()` (``include/linux/list.h``) fa esattamente
+La funzione list_del_rcu() (``include/linux/list.h``) fa esattamente
 questo (la versione normale corrompe il vecchio oggetto, e non vogliamo che
 accada).
 
@@ -1146,9 +1146,9 @@ Anche i lettori devono stare attenti: alcuni processori potrebbero leggere
 attraverso il puntatore ``next`` il contenuto dell'elemento successivo
 troppo presto, ma non accorgersi che il contenuto caricato è sbagliato quando
 il puntatore ``next`` viene modificato alla loro spalle. Ancora una volta
-c'è una funzione che viene in vostro aiuto :c:func:`list_for_each_entry_rcu()`
+c'è una funzione che viene in vostro aiuto list_for_each_entry_rcu()
 (``include/linux/list.h``). Ovviamente, gli scrittori possono usare
-:c:func:`list_for_each_entry()` dato che non ci possono essere due scrittori
+list_for_each_entry() dato che non ci possono essere due scrittori
 in contemporanea.
 
 Il nostro ultimo dilemma è il seguente: quando possiamo realmente distruggere
@@ -1156,15 +1156,15 @@ l'elemento rimosso? Ricordate, un lettore potrebbe aver avuto accesso a questo
 elemento proprio ora: se eliminiamo questo elemento ed il puntatore ``next``
 cambia, il lettore salterà direttamente nella spazzatura e scoppierà. Dobbiamo
 aspettare finché tutti i lettori che stanno attraversando la lista abbiano
-finito. Utilizziamo :c:func:`call_rcu()` per registrare una funzione di
+finito. Utilizziamo call_rcu() per registrare una funzione di
 richiamo che distrugga l'oggetto quando tutti i lettori correnti hanno
 terminato. In alternative, potrebbe essere usata la funzione
-:c:func:`synchronize_rcu()` che blocca l'esecuzione finché tutti i lettori
+synchronize_rcu() che blocca l'esecuzione finché tutti i lettori
 non terminano di ispezionare la lista.
 
 Ma come fa l'RCU a sapere quando i lettori sono finiti? Il meccanismo è
 il seguente: innanzi tutto i lettori accedono alla lista solo fra la coppia
-:c:func:`rcu_read_lock()`/:c:func:`rcu_read_unlock()` che disabilita la
+rcu_read_lock()/rcu_read_unlock() che disabilita la
 prelazione così che i lettori non vengano sospesi mentre stanno leggendo
 la lista.
 
@@ -1253,12 +1253,12 @@ codice RCU è un po' più ottimizzato di così, ma questa è l'idea di fondo.
      }
 
 Da notare che i lettori modificano il campo popularity nella funzione
-:c:func:`__cache_find()`, e ora non trattiene alcun *lock*. Una soluzione
+__cache_find(), e ora non trattiene alcun *lock*. Una soluzione
 potrebbe essere quella di rendere la variabile ``atomic_t``, ma per l'uso
 che ne abbiamo fatto qui, non ci interessano queste corse critiche perché un
 risultato approssimativo è comunque accettabile, quindi non l'ho cambiato.
 
-Il risultato è che la funzione :c:func:`cache_find()` non ha bisogno di alcuna
+Il risultato è che la funzione cache_find() non ha bisogno di alcuna
 sincronizzazione con le altre funzioni, quindi è veloce su un sistema
 multi-processore tanto quanto lo sarebbe su un sistema mono-processore.
 
@@ -1271,9 +1271,9 @@ riferimenti.
 
 Ora, dato che il '*lock* di lettura' di un RCU non fa altro che disabilitare
 la prelazione, un chiamante che ha sempre la prelazione disabilitata fra le
-chiamate :c:func:`cache_find()` e :c:func:`object_put()` non necessita
+chiamate cache_find() e object_put() non necessita
 di incrementare e decrementare il contatore di riferimenti. Potremmo
-esporre la funzione :c:func:`__cache_find()` dichiarandola non-static,
+esporre la funzione __cache_find() dichiarandola non-static,
 e quel chiamante potrebbe usare direttamente questa funzione.
 
 Il beneficio qui sta nel fatto che il contatore di riferimenti no
@@ -1293,10 +1293,10 @@ singolo contatore. Facile e pulito.
 Se questo dovesse essere troppo lento (solitamente non lo è, ma se avete
 dimostrato che lo è devvero), potreste usare un contatore per ogni processore
 e quindi non sarebbe più necessaria la mutua esclusione. Vedere
-:c:func:`DEFINE_PER_CPU()`, :c:func:`get_cpu_var()` e :c:func:`put_cpu_var()`
+DEFINE_PER_CPU(), get_cpu_var() e put_cpu_var()
 (``include/linux/percpu.h``).
 
-Il tipo di dato ``local_t``, la funzione :c:func:`cpu_local_inc()` e tutte
+Il tipo di dato ``local_t``, la funzione cpu_local_inc() e tutte
 le altre funzioni associate, sono di particolare utilità per semplici contatori
 per-processore; su alcune architetture sono anche più efficienti
 (``include/asm/local.h``).
@@ -1324,11 +1324,11 @@ da un'interruzione software. Il gestore d'interruzione non utilizza alcun
         enable_irq(irq);
         spin_unlock(&lock);
 
-La funzione :c:func:`disable_irq()` impedisce al gestore d'interruzioni
+La funzione disable_irq() impedisce al gestore d'interruzioni
 d'essere eseguito (e aspetta che finisca nel caso fosse in esecuzione su
 un altro processore). Lo spinlock, invece, previene accessi simultanei.
 Naturalmente, questo è più lento della semplice chiamata
-:c:func:`spin_lock_irq()`, quindi ha senso solo se questo genere di accesso
+spin_lock_irq(), quindi ha senso solo se questo genere di accesso
 è estremamente raro.
 
 .. _`it_sleeping-things`:
@@ -1336,7 +1336,7 @@ Naturalmente, questo è più lento della semplice chiamata
 Quali funzioni possono essere chiamate in modo sicuro dalle interruzioni?
 =========================================================================
 
-Molte funzioni del kernel dormono (in sostanza, chiamano ``schedule()``)
+Molte funzioni del kernel dormono (in sostanza, chiamano schedule())
 direttamente od indirettamente: non potete chiamarle se trattenere uno
 spinlock o avete la prelazione disabilitata, mai. Questo significa che
 dovete necessariamente essere nel contesto utente: chiamarle da un
@@ -1354,23 +1354,23 @@ dormire.
 
 -  Accessi allo spazio utente:
 
-   -  :c:func:`copy_from_user()`
+   -  copy_from_user()
 
-   -  :c:func:`copy_to_user()`
+   -  copy_to_user()
 
-   -  :c:func:`get_user()`
+   -  get_user()
 
-   -  :c:func:`put_user()`
+   -  put_user()
 
--  :c:func:`kmalloc(GFP_KERNEL) <kmalloc>`
+-  kmalloc(GFP_KERNEL) <kmalloc>`
 
--  :c:func:`mutex_lock_interruptible()` and
-   :c:func:`mutex_lock()`
+-  mutex_lock_interruptible() and
+   mutex_lock()
 
-   C'è anche :c:func:`mutex_trylock()` che però non dorme.
+   C'è anche mutex_trylock() che però non dorme.
    Comunque, non deve essere usata in un contesto d'interruzione dato
    che la sua implementazione non è sicura in quel contesto.
-   Anche :c:func:`mutex_unlock()` non dorme mai. Non può comunque essere
+   Anche mutex_unlock() non dorme mai. Non può comunque essere
    usata in un contesto d'interruzione perché un mutex deve essere rilasciato
    dallo stesso processo che l'ha acquisito.
 
@@ -1380,11 +1380,11 @@ Alcune funzioni che non dormono
 Alcune funzioni possono essere chiamate tranquillamente da qualsiasi
 contesto, o trattenendo un qualsiasi *lock*.
 
--  :c:func:`printk()`
+-  printk()
 
--  :c:func:`kfree()`
+-  kfree()
 
--  :c:func:`add_timer()` e :c:func:`del_timer()`
+-  add_timer() e del_timer()
 
 Riferimento per l'API dei Mutex
 ===============================
@@ -1444,14 +1444,14 @@ prelazione
 bh
   Bottom Half: per ragioni storiche, le funzioni che contengono '_bh' nel
   loro nome ora si riferiscono a qualsiasi interruzione software; per esempio,
-  :c:func:`spin_lock_bh()` blocca qualsiasi interuzione software sul processore
+  spin_lock_bh() blocca qualsiasi interuzione software sul processore
   corrente. I *Bottom Halves* sono deprecati, e probabilmente verranno
   sostituiti dai tasklet. In un dato momento potrà esserci solo un
   *bottom half* in esecuzione.
 
 contesto d'interruzione
   Non è il contesto utente: qui si processano le interruzioni hardware e
-  software. La macro :c:func:`in_interrupt()` ritorna vero.
+  software. La macro in_interrupt() ritorna vero.
 
 contesto utente
   Il kernel che esegue qualcosa per conto di un particolare processo (per
@@ -1461,12 +1461,12 @@ contesto utente
   che hardware.
 
 interruzione hardware
-  Richiesta di interruzione hardware. :c:func:`in_irq()` ritorna vero in un
+  Richiesta di interruzione hardware. in_irq() ritorna vero in un
   gestore d'interruzioni hardware.
 
 interruzione software / softirq
-  Gestore di interruzioni software: :c:func:`in_irq()` ritorna falso;
-  :c:func:`in_softirq()` ritorna vero. I tasklet e le softirq sono entrambi
+  Gestore di interruzioni software: in_irq() ritorna falso;
+  in_softirq() ritorna vero. I tasklet e le softirq sono entrambi
   considerati 'interruzioni software'.
 
   In soldoni, un softirq è uno delle 32 interruzioni software che possono
diff --git a/Documentation/translations/it_IT/process/2.Process.rst b/Documentation/translations/it_IT/process/2.Process.rst
index 9af4d01617c4..30dc172f06b0 100644
--- a/Documentation/translations/it_IT/process/2.Process.rst
+++ b/Documentation/translations/it_IT/process/2.Process.rst
@@ -23,18 +23,18 @@ ogni due o tre mesi viene effettuata un rilascio importante del kernel.
 I rilasci più recenti sono stati:
 
 	======  =================
-	4.11	Aprile 30, 2017
-	4.12	Luglio 2, 2017
-	4.13	Settembre 3, 2017
-	4.14	Novembre 12, 2017
-	4.15	Gennaio 28, 2018
-	4.16	Aprile 1, 2018
+	5.0     3 marzo, 2019
+	5.1     5 maggio, 2019
+	5.2     7 luglio, 2019
+	5.3     15 settembre, 2019
+	5.4     24 novembre, 2019
+	5.5     6 gennaio, 2020
 	======  =================
 
-Ciascun rilascio 4.x è un importante rilascio del kernel con nuove
+Ciascun rilascio 5.x è un importante rilascio del kernel con nuove
 funzionalità, modifiche interne dell'API, e molto altro.  Un tipico
-rilascio 4.x contiene quasi 13,000 gruppi di modifiche con ulteriori
-modifiche a parecchie migliaia di linee di codice.  La 4.x. è pertanto la
+rilascio contiene quasi 13,000 gruppi di modifiche con ulteriori
+modifiche a parecchie migliaia di linee di codice.  La 5.x. è pertanto la
 linea di confine nello sviluppo del kernel Linux; il kernel utilizza un sistema
 di sviluppo continuo che integra costantemente nuove importanti modifiche.
 
@@ -55,8 +55,8 @@ verrà descritto dettagliatamente più avanti).
 La finestra di inclusione resta attiva approssimativamente per due settimane.
 Al termine di questo periodo, Linus Torvald dichiarerà che la finestra è
 chiusa e rilascerà il primo degli "rc" del kernel.
-Per il kernel che è destinato ad essere 2.6.40, per esempio, il rilascio
-che emerge al termine della finestra d'inclusione si chiamerà 2.6.40-rc1.
+Per il kernel che è destinato ad essere 5.6, per esempio, il rilascio
+che emerge al termine della finestra d'inclusione si chiamerà 5.6-rc1.
 Questo rilascio indica che il momento di aggiungere nuovi componenti è
 passato, e che è iniziato il periodo di stabilizzazione del prossimo kernel.
 
@@ -76,22 +76,23 @@ Mentre le correzioni si aprono la loro strada all'interno del ramo principale,
 il ritmo delle modifiche rallenta col tempo.  Linus rilascia un nuovo
 kernel -rc circa una volta alla settimana; e ne usciranno circa 6 o 9 prima
 che il kernel venga considerato sufficientemente stabile e che il rilascio
-finale 2.6.x venga fatto.  A quel punto tutto il processo ricomincerà.
+finale venga fatto.  A quel punto tutto il processo ricomincerà.
 
-Esempio: ecco com'è andato il ciclo di sviluppo della versione 4.16
+Esempio: ecco com'è andato il ciclo di sviluppo della versione 5.4
 (tutte le date si collocano nel 2018)
 
 
 	==============  =======================================
-	Gennaio 28	4.15 rilascio stabile
-	Febbraio 11	4.16-rc1, finestra di inclusione chiusa
-	Febbraio 18	4.16-rc2
-	Febbraio 25	4.16-rc3
-	Marzo 4		4.16-rc4
-	Marzo 11	4.16-rc5
-	Marzo 18	4.16-rc6
-	Marzo 25	4.16-rc7
-	Aprile 1		4.17 rilascio stabile
+	15 settembre	5.3 rilascio stabile
+	30 settembre	5.4-rc1, finestra di inclusione chiusa
+	6 ottobre	5.4-rc2
+	13 ottobre	5.4-rc3
+	20 ottobre	5.4-rc4
+	27 ottobre	5.4-rc5
+	3 novembre	5.4-rc6
+	10 novembre	5.4-rc7
+	17 novembre	5.4-rc8
+	24 novembre	5.4 rilascio stabile
 	==============  =======================================
 
 In che modo gli sviluppatori decidono quando chiudere il ciclo di sviluppo e
@@ -108,43 +109,44 @@ tipo di perfezione difficilmente viene raggiunta; esistono troppe variabili
 in un progetto di questa portata.  Arriva un punto dove ritardare il rilascio
 finale peggiora la situazione; la quantità di modifiche in attesa della
 prossima finestra di inclusione crescerà enormemente, creando ancor più
-regressioni al giro successivo.  Quindi molti kernel 4.x escono con una
+regressioni al giro successivo.  Quindi molti kernel 5.x escono con una
 manciata di regressioni delle quali, si spera, nessuna è grave.
 
 Una volta che un rilascio stabile è fatto, il suo costante mantenimento è
 affidato al "squadra stabilità", attualmente composta da Greg Kroah-Hartman.
 Questa squadra rilascia occasionalmente degli aggiornamenti relativi al
-rilascio stabile usando la numerazione 4.x.y.  Per essere presa in
+rilascio stabile usando la numerazione 5.x.y.  Per essere presa in
 considerazione per un rilascio d'aggiornamento, una modifica deve:
 (1) correggere un baco importante (2) essere già inserita nel ramo principale
 per il prossimo sviluppo del kernel.  Solitamente, passato il loro rilascio
 iniziale, i kernel ricevono aggiornamenti per più di un ciclo di sviluppo.
-Quindi, per esempio, la storia del kernel 4.13 appare così:
+Quindi, per esempio, la storia del kernel 5.2 appare così (anno 2019):
 
 	==============  ===============================
-	Settembre 3 	4.13 rilascio stabile
-	Settembre 13	4.13.1
-	Settembre 20	4.13.2
-	Settembre 27	4.13.3
-	Ottobre 5	4.13.4
-	Ottobre 12	4.13.5
+	15 settembre	5.2 rilascio stabile FIXME settembre è sbagliato
+	14 luglio	5.2.1
+	21 luglio	5.2.2
+	26 luglio	5.2.3
+	28 luglio	5.2.4
+	31 luglio	5.2.5
 	...		...
-	Novembre 24	4.13.16
+	11 ottobre	5.2.21
 	==============  ===============================
 
-La 4.13.16 fu l'aggiornamento finale per la versione 4.13.
+La 5.2.21 fu l'aggiornamento finale per la versione 5.2.
 
 Alcuni kernel sono destinati ad essere kernel a "lungo termine"; questi
 riceveranno assistenza per un lungo periodo di tempo.  Al momento in cui
 scriviamo, i manutentori dei kernel stabili a lungo termine sono:
 
-	======  ======================  ==========================================
-	3.16	Ben Hutchings		(kernel stabile molto più a lungo termine)
-	4.1	Sasha Levin
-	4.4	Greg Kroah-Hartman	(kernel stabile molto più a lungo termine)
-	4.9	Greg Kroah-Hartman
-	4.14	Greg Kroah-Hartman
-	======  ======================  ==========================================
+	======  ================================  ==========================================
+	3.16	Ben Hutchings			  (kernel stabile molto più a lungo termine)
+	4.4	Greg Kroah-Hartman e Sasha Levin  (kernel stabile molto più a lungo termine)
+	4.9	Greg Kroah-Hartman e Sasha Levin
+	4.14	Greg Kroah-Hartman e Sasha Levin
+	4.19	Greg Kroah-Hartman e Sasha Levin
+	5.4i	Greg Kroah-Hartman e Sasha Levin
+	======  ================================  ==========================================
 
 
 Questa selezione di kernel di lungo periodo sono puramente dovuti ai loro
@@ -229,12 +231,13 @@ Come le modifiche finiscono nel Kernel
 --------------------------------------
 
 Esiste una sola persona che può inserire le patch nel repositorio principale
-del kernel: Linus Torvalds.  Ma, di tutte le 9500 patch che entrarono nella
-versione 2.6.38 del kernel, solo 112 (circa l'1,3%) furono scelte direttamente
-da Linus in persona.  Il progetto del kernel è cresciuto fino a raggiungere
-una dimensione tale per cui un singolo sviluppatore non può controllare e
-selezionare indipendentemente ogni modifica senza essere supportato.
-La via scelta dagli sviluppatori per indirizzare tale crescita è stata quella
+del kernel: Linus Torvalds.  Ma, per esempio, di tutte le 9500 patch
+che entrarono nella versione 2.6.38 del kernel, solo 112 (circa
+l'1,3%) furono scelte direttamente da Linus in persona.  Il progetto
+del kernel è cresciuto fino a raggiungere una dimensione tale per cui
+un singolo sviluppatore non può controllare e selezionare
+indipendentemente ogni modifica senza essere supportato.  La via
+scelta dagli sviluppatori per indirizzare tale crescita è stata quella
 di utilizzare un sistema di "sottotenenti" basato sulla fiducia.
 
 Il codice base del kernel è spezzato in una serie si sottosistemi: rete,
diff --git a/Documentation/translations/it_IT/process/coding-style.rst b/Documentation/translations/it_IT/process/coding-style.rst
index 8725f2b9e960..6f4f85832dee 100644
--- a/Documentation/translations/it_IT/process/coding-style.rst
+++ b/Documentation/translations/it_IT/process/coding-style.rst
@@ -313,7 +313,7 @@ che conta gli utenti attivi, dovreste chiamarla ``count_active_users()`` o
 qualcosa di simile, **non** dovreste chiamarla ``cntusr()``.
 
 Codificare il tipo di funzione nel suo nome (quella cosa chiamata notazione
-ungherese) fa male al cervello - il compilatore conosce comunque il tipo e
+ungherese) è stupido - il compilatore conosce comunque il tipo e
 può verificarli, e inoltre confonde i programmatori.  Non c'è da
 sorprendersi che MicroSoft faccia programmi bacati.
 
@@ -825,8 +825,8 @@ linguaggio assembler.
 
 Agli sviluppatori del kernel piace essere visti come dotti. Tenete un occhio
 di riguardo per l'ortografia e farete una belle figura. In inglese, evitate
-l'uso di parole mozzate come ``dont``: usate ``do not`` oppure ``don't``.
-Scrivete messaggi concisi, chiari, e inequivocabili.
+l'uso incorretto di abbreviazioni come ``dont``: usate ``do not`` oppure
+``don't``.  Scrivete messaggi concisi, chiari, e inequivocabili.
 
 I messaggi del kernel non devono terminare con un punto fermo.
 
diff --git a/Documentation/translations/it_IT/process/deprecated.rst b/Documentation/translations/it_IT/process/deprecated.rst
index 776f26732a94..e108eaf82cf6 100644
--- a/Documentation/translations/it_IT/process/deprecated.rst
+++ b/Documentation/translations/it_IT/process/deprecated.rst
@@ -34,6 +34,33 @@ interfaccia come 'vecchia', questa non è una soluzione completa. L'interfaccia
 deve essere rimossa dal kernel, o aggiunta a questo documento per scoraggiarne
 l'uso.
 
+BUG() e BUG_ON()
+----------------
+Al loro posto usate WARN() e WARN_ON() per gestire le
+condizioni "impossibili" e gestitele come se fosse possibile farlo.
+Nonostante le funzioni della famiglia BUG() siano state progettate
+per asserire "situazioni impossibili" e interrompere in sicurezza un
+thread del kernel, queste si sono rivelate essere troppo rischiose
+(per esempio, in quale ordine rilasciare i *lock*? Ci sono stati che
+sono stati ripristinati?). Molto spesso l'uso di BUG()
+destabilizza il sistema o lo corrompe del tutto, il che rende
+impossibile un'attività di debug o anche solo leggere un rapporto
+circa l'errore.  Linus ha un'opinione molto critica al riguardo:
+`email 1
+<https://lore.kernel.org/lkml/CA+55aFy6jNLsywVYdGp83AMrXBo_P-pkjkphPGrO=82SPKCpLQ@mail.gmail.com/>`_,
+`email 2
+<https://lore.kernel.org/lkml/CAHk-=whDHsbK3HTOpTF=ue_o04onRwTEaK_ZoJp_fjbqq4+=Jw@mail.gmail.com/>`_
+
+Tenete presente che la famiglia di funzioni WARN() dovrebbe essere
+usato solo per situazioni che si suppone siano "impossibili".  Se
+volete avvisare gli utenti riguardo a qualcosa di possibile anche se
+indesiderato, usare le funzioni della famiglia pr_warn().  Chi
+amministra il sistema potrebbe aver attivato l'opzione sysctl
+*panic_on_warn* per essere sicuri che il sistema smetta di funzionare
+in caso si verifichino delle condizioni "inaspettate". (per esempio,
+date un'occhiata al questo `commit
+<https://git.kernel.org/linus/d4689846881d160a4d12a514e991a740bcb5d65a>`_)
+
 Calcoli codificati negli argomenti di un allocatore
 ----------------------------------------------------
 Il calcolo dinamico delle dimensioni (specialmente le moltiplicazioni) non
@@ -68,52 +95,81 @@ Invece, usate la seguente funzione::
 
 	header = kzalloc(struct_size(header, item, count), GFP_KERNEL);
 
-Per maggiori dettagli fate riferimento a :c:func:`array_size`,
-:c:func:`array3_size`, e :c:func:`struct_size`, così come la famiglia di
-funzioni :c:func:`check_add_overflow` e :c:func:`check_mul_overflow`.
+Per maggiori dettagli fate riferimento a array_size(),
+array3_size(), e struct_size(), così come la famiglia di
+funzioni check_add_overflow() e check_mul_overflow().
 
 simple_strtol(), simple_strtoll(), simple_strtoul(), simple_strtoull()
 ----------------------------------------------------------------------
-Le funzioni :c:func:`simple_strtol`, :c:func:`simple_strtoll`,
-:c:func:`simple_strtoul`, e :c:func:`simple_strtoull` ignorano volutamente
+Le funzioni simple_strtol(), simple_strtoll(),
+simple_strtoul(), e simple_strtoull() ignorano volutamente
 i possibili overflow, e questo può portare il chiamante a generare risultati
-inaspettati. Le rispettive funzioni :c:func:`kstrtol`, :c:func:`kstrtoll`,
-:c:func:`kstrtoul`, e :c:func:`kstrtoull` sono da considerarsi le corrette
+inaspettati. Le rispettive funzioni kstrtol(), kstrtoll(),
+kstrtoul(), e kstrtoull() sono da considerarsi le corrette
 sostitute; tuttavia va notato che queste richiedono che la stringa sia
 terminata con il carattere NUL o quello di nuova riga.
 
 strcpy()
 --------
-La funzione :c:func:`strcpy` non fa controlli agli estremi del buffer
+La funzione strcpy() non fa controlli agli estremi del buffer
 di destinazione. Questo può portare ad un overflow oltre i limiti del
 buffer e generare svariati tipi di malfunzionamenti. Nonostante l'opzione
 `CONFIG_FORTIFY_SOURCE=y` e svariate opzioni del compilatore aiutano
 a ridurne il rischio, non c'è alcuna buona ragione per continuare ad usare
-questa funzione. La versione sicura da usare è :c:func:`strscpy`.
+questa funzione. La versione sicura da usare è strscpy().
 
 strncpy() su stringe terminate con NUL
 --------------------------------------
-L'utilizzo di :c:func:`strncpy` non fornisce alcuna garanzia sul fatto che
+L'utilizzo di strncpy() non fornisce alcuna garanzia sul fatto che
 il buffer di destinazione verrà terminato con il carattere NUL. Questo
 potrebbe portare a diversi overflow di lettura o altri malfunzionamenti
 causati, appunto, dalla mancanza del terminatore. Questa estende la
 terminazione nel buffer di destinazione quando la stringa d'origine è più
 corta; questo potrebbe portare ad una penalizzazione delle prestazioni per
 chi usa solo stringe terminate. La versione sicura da usare è
-:c:func:`strscpy`. (chi usa :c:func:`strscpy` e necessita di estendere la
-terminazione con NUL deve aggiungere una chiamata a :c:func:`memset`)
+strscpy(). (chi usa strscpy() e necessita di estendere la
+terminazione con NUL deve aggiungere una chiamata a memset())
 
-Se il chiamate no usa stringhe terminate con NUL, allore :c:func:`strncpy()`
+Se il chiamate no usa stringhe terminate con NUL, allore strncpy()()
 può continuare ad essere usata, ma i buffer di destinazione devono essere
 marchiati con l'attributo `__nonstring <https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html>`_
 per evitare avvisi durante la compilazione.
 
 strlcpy()
 ---------
-La funzione :c:func:`strlcpy`, per prima cosa, legge interamente il buffer di
+La funzione strlcpy(), per prima cosa, legge interamente il buffer di
 origine, magari leggendo più di quanto verrà effettivamente copiato. Questo
 è inefficiente e può portare a overflow di lettura quando la stringa non è
-terminata con NUL. La versione sicura da usare è :c:func:`strscpy`.
+terminata con NUL. La versione sicura da usare è strscpy().
+
+Segnaposto %p nella stringa di formato
+--------------------------------------
+
+Tradizionalmente, l'uso del segnaposto "%p" nella stringa di formato
+esponne un indirizzo di memoria in dmesg, proc, sysfs, eccetera.  Per
+evitare che questi indirizzi vengano sfruttati da malintenzionati,
+tutto gli usi di "%p" nel kernel rappresentano l'hash dell'indirizzo,
+rendendolo di fatto inutilizzabile.  Nuovi usi di "%p" non dovrebbero
+essere aggiunti al kernel.  Per una rappresentazione testuale di un
+indirizzo usate "%pS", l'output è migliore perché mostrerà il nome del
+simbolo.  Per tutto il resto, semplicemente non usate "%p".
+
+Parafrasando la `guida
+<https://lore.kernel.org/lkml/CA+55aFwQEd_d40g4mUCSsVRZzrFPUJt74vc6PPpb675hYNXcKw@mail.gmail.com/>`_
+di Linus:
+
+- Se il valore hash di "%p" è inutile, chiediti se il puntatore stesso
+  è importante. Forse dovrebbe essere rimosso del tutto?
+- Se credi davvero che il vero valore del puntatore sia importante,
+  perché alcuni stati del sistema o i livelli di privilegi di un
+  utente sono considerati "special"? Se pensi di poterlo giustificare
+  (in un commento e nel messaggio del commit) abbastanza bene da
+  affrontare il giudizio di Linus, allora forse potrai usare "%px",
+  assicurandosi anche di averne il permesso.
+
+Infine, sappi che un cambio in favore di "%p" con hash `non verrà
+accettato
+<https://lore.kernel.org/lkml/CA+55aFwieC1-nAs+NFq9RTwaR8ef9hWa4MjNBWL41F-8wM49eA@mail.gmail.com/>`_.
 
 Vettori a dimensione variabile (VLA)
 ------------------------------------
@@ -127,3 +183,47 @@ Questo può portare a dei malfunzionamenti, potrebbe sovrascrivere
 dati importanti alla fine dello stack (quando il kernel è compilato senza
 `CONFIG_THREAD_INFO_IN_TASK=y`), o sovrascrivere un pezzo di memoria adiacente
 allo stack (quando il kernel è compilato senza `CONFIG_VMAP_STACK=y`).
+
+Salto implicito nell'istruzione switch-case
+-------------------------------------------
+
+Il linguaggio C permette ai casi di un'istruzione `switch` di saltare al
+prossimo caso quando l'istruzione "break" viene omessa alla fine del caso
+corrente. Tuttavia questo rende il codice ambiguo perché non è sempre ovvio se
+l'istruzione "break" viene omessa intenzionalmente o è un baco. Per esempio,
+osservando il seguente pezzo di codice non è chiaro se lo stato
+`STATE_ONE` è stato progettato apposta per eseguire anche `STATE_TWO`::
+
+  switch (value) {
+  case STATE_ONE:
+          do_something();
+  case STATE_TWO:
+          do_other();
+          break;
+  default:
+          WARN("unknown state");
+  }
+
+Dato che c'è stata una lunga lista di problemi `dovuti alla mancanza dell'istruzione
+"break" <https://cwe.mitre.org/data/definitions/484.html>`_, oggigiorno non
+permettiamo più che vi sia un "salto implicito" (*fall-through*). Per
+identificare un salto implicito intenzionale abbiamo adottato la pseudo
+parola chiave 'fallthrough' che viene espansa nell'estensione di gcc
+`__attribute__((fallthrough))` `Statement Attributes
+<https://gcc.gnu.org/onlinedocs/gcc/Statement-Attributes.html>`_.
+(Quando la sintassi C17/C18 `[[fallthrough]]` sarà più comunemente
+supportata dai compilatori C, analizzatori statici, e dagli IDE,
+allora potremo usare quella sintassi per la pseudo parola chiave)
+
+Quando la sintassi [[fallthrough]] sarà più comunemente supportata dai
+compilatori, analizzatori statici, e ambienti di sviluppo IDE,
+allora potremo usarla anche noi.
+
+Ne consegue che tutti i blocchi switch/case devono finire in uno dei seguenti
+modi:
+
+* ``break;``
+* `fallthrough;``
+* ``continue;``
+* ``goto <label>;``
+* ``return [expression];``
-- 
2.25.4


^ permalink raw reply related	[relevance 4%]

* Linux 3.16.83
@ 2020-04-28 19:17  1% Ben Hutchings
  0 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-04-28 19:17 UTC (permalink / raw)
  To: linux-kernel, Andrew Morton, torvalds, Jiri Slaby, stable; +Cc: lwn


[-- Attachment #1.1: Type: text/plain, Size: 30299 bytes --]

I'm announcing the release of the 3.16.83 kernel.

All users of the 3.16 kernel series should upgrade.

The updated 3.16.y git tree can be found at:
        https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git linux-3.16.y
and can be browsed at the normal kernel.org git web browser:
        https://git.kernel.org/?p=linux/kernel/git/stable/linux-stable.git

The diff from 3.16.82 is attached to this message.

Ben.

------------

 Documentation/sysctl/fs.txt                       |  36 ++
 Makefile                                          |   2 +-
 arch/powerpc/kernel/irq.c                         |   4 +-
 arch/x86/boot/compressed/head_64.S                |   5 +
 arch/x86/include/asm/kaiser.h                     |  10 +
 arch/x86/kernel/cpu/microcode/amd.c               |   4 +
 arch/x86/kvm/cpuid.c                              |   3 +-
 arch/x86/kvm/vmx.c                                |   2 +-
 arch/x86/realmode/init.c                          |   4 +-
 arch/x86/realmode/rm/trampoline_64.S              |   3 +-
 block/blk-settings.c                              |   2 +-
 drivers/acpi/device_pm.c                          |  12 +-
 drivers/block/floppy.c                            |   7 +-
 drivers/gpio/gpiolib.c                            |  13 +-
 drivers/hid/hid-core.c                            |   6 +
 drivers/hid/hid-input.c                           |  16 +-
 drivers/hid/hidraw.c                              |   7 +-
 drivers/hid/uhid.c                                |   5 +-
 drivers/hwmon/adt7475.c                           |   5 +-
 drivers/iio/industrialio-buffer.c                 |   6 +-
 drivers/infiniband/hw/mlx4/main.c                 |  16 +-
 drivers/input/input.c                             |  26 +-
 drivers/input/misc/keyspan_remote.c               |   9 +-
 drivers/input/tablet/aiptek.c                     |   6 +-
 drivers/input/tablet/gtco.c                       |  10 +-
 drivers/input/touchscreen/sur40.c                 |   2 +-
 drivers/isdn/gigaset/usb-gigaset.c                |  23 +-
 drivers/md/dm-crypt.c                             |   4 +-
 drivers/md/dm-delay.c                             |  16 +-
 drivers/md/dm-flakey.c                            |  40 +-
 drivers/md/dm-linear.c                            |   7 +-
 drivers/md/dm-raid1.c                             |   8 +-
 drivers/md/dm-snap-persistent.c                   |   2 +-
 drivers/md/dm-stripe.c                            |   8 +-
 drivers/md/dm-thin-metadata.c                     |  29 +
 drivers/md/dm-thin-metadata.h                     |   7 +
 drivers/md/persistent-data/dm-btree-remove.c      |   8 +-
 drivers/md/raid0.c                                |   2 +-
 drivers/media/media-device.c                      |  43 +-
 drivers/media/media-devnode.c                     | 171 +++---
 drivers/media/usb/gspca/ov519.c                   |  10 +
 drivers/media/usb/gspca/stv06xx/stv06xx.c         |  19 +-
 drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c  |   4 +
 drivers/media/usb/gspca/xirlink_cit.c             |  18 +-
 drivers/media/usb/uvc/uvc_driver.c                |   2 +-
 drivers/misc/enclosure.c                          |   3 +-
 drivers/mmc/host/sdhci.c                          |  10 +-
 drivers/net/bonding/bond_main.c                   |  40 +-
 drivers/net/can/mscan/mscan.c                     |  21 +-
 drivers/net/can/slcan.c                           |  16 +-
 drivers/net/can/usb/gs_usb.c                      |   4 +-
 drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c |   5 -
 drivers/net/ethernet/natsemi/sonic.c              | 113 +++-
 drivers/net/ethernet/natsemi/sonic.h              |  25 +-
 drivers/net/ethernet/stmicro/stmmac/common.h      |   5 +-
 drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c |   2 +-
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c |   4 +-
 drivers/net/hamradio/6pack.c                      |   4 +-
 drivers/net/hamradio/mkiss.c                      |   4 +-
 drivers/net/macvlan.c                             |   3 +-
 drivers/net/slip/slip.c                           |  12 +-
 drivers/net/usb/r8152.c                           |   3 +
 drivers/net/vxlan.c                               |   5 +-
 drivers/net/wireless/libertas/cfg.c               |  18 +-
 drivers/net/wireless/mwifiex/sta_ioctl.c          |   1 +
 drivers/net/wireless/mwifiex/tdls.c               |  74 ++-
 drivers/pinctrl/pinctrl-baytrail.c                | 212 ++++---
 drivers/platform/x86/asus-wmi.c                   |   8 +-
 drivers/platform/x86/hp-wmi.c                     |   2 +-
 drivers/ptp/ptp_clock.c                           |  42 +-
 drivers/ptp/ptp_private.h                         |   9 +-
 drivers/ptp/ptp_sysfs.c                           | 162 +++---
 drivers/scsi/fnic/vnic_dev.c                      |  20 +-
 drivers/scsi/qla4xxx/ql4_os.c                     |   1 -
 drivers/scsi/sd.c                                 |   4 +-
 drivers/staging/android/ashmem.c                  |  28 +
 drivers/staging/rtl8188eu/os_dep/usb_intf.c       |   3 +-
 drivers/staging/rtl8712/usb_intf.c                |   2 +-
 drivers/staging/usbip/vhci_rx.c                   |  13 +-
 drivers/tty/serial/msm_serial.c                   |  13 +-
 drivers/tty/serial/serial_core.c                  |   1 +
 drivers/tty/vt/selection.c                        |  34 +-
 drivers/tty/vt/vt.c                               |   2 -
 drivers/usb/atm/ueagle-atm.c                      |  18 +-
 drivers/usb/core/config.c                         |  77 ++-
 drivers/usb/core/hub.c                            |   1 +
 drivers/usb/core/quirks.c                         |  37 ++
 drivers/usb/core/urb.c                            |   1 +
 drivers/usb/core/usb.h                            |   3 +
 drivers/usb/dwc3/dwc3-pci.c                       |  30 +
 drivers/usb/host/ehci-q.c                         |  13 +-
 drivers/usb/host/xhci-hub.c                       |   8 +-
 drivers/usb/host/xhci-ring.c                      |   3 +-
 drivers/usb/misc/adutux.c                         |   2 +-
 drivers/usb/misc/idmouse.c                        |   2 +-
 drivers/usb/mon/mon_bin.c                         |  32 +-
 drivers/usb/musb/musbhsdma.c                      |   2 +-
 drivers/usb/serial/ch341.c                        |   6 +-
 drivers/usb/serial/io_edgeport.c                  |  26 +-
 drivers/usb/serial/keyspan.c                      |   4 +
 drivers/usb/serial/opticon.c                      |   2 +-
 drivers/usb/serial/quatech2.c                     |   6 +
 drivers/usb/serial/usb-serial-simple.c            |   2 +
 drivers/usb/serial/usb-serial.c                   |   3 +
 drivers/vhost/net.c                               |  13 +-
 drivers/video/console/vgacon.c                    |   3 +
 drivers/virtio/virtio_balloon.c                   |  10 +
 firmware/Makefile                                 |   2 +-
 fs/btrfs/Makefile                                 |   2 +-
 fs/btrfs/ctree.c                                  |  19 +-
 fs/btrfs/ctree.h                                  | 157 +++---
 fs/btrfs/dev-replace.c                            |   2 +-
 fs/btrfs/disk-io.c                                |  80 +--
 fs/btrfs/extent-tree.c                            | 110 +++-
 fs/btrfs/extent_io.c                              |  98 ++--
 fs/btrfs/extent_io.h                              |  25 +-
 fs/btrfs/extent_map.c                             |   2 +-
 fs/btrfs/extent_map.h                             |  10 +-
 fs/btrfs/inode.c                                  |   8 +-
 fs/btrfs/ioctl.c                                  |  10 +-
 fs/btrfs/relocation.c                             |   1 +
 fs/btrfs/root-tree.c                              |  10 +-
 fs/btrfs/scrub.c                                  |   2 +-
 fs/btrfs/struct-funcs.c                           |   9 +-
 fs/btrfs/tree-checker.c                           | 649 ++++++++++++++++++++++
 fs/btrfs/tree-checker.h                           |  38 ++
 fs/btrfs/tree-log.c                               |  24 +-
 fs/btrfs/uuid-tree.c                              |   2 +
 fs/btrfs/volumes.c                                | 206 +++++--
 fs/btrfs/volumes.h                                |   2 +
 fs/char_dev.c                                     |  88 ++-
 fs/ext4/dir.c                                     |   5 +
 fs/ext4/ext4.h                                    |  13 +
 fs/ext4/extents.c                                 |  89 +--
 fs/ext4/file.c                                    |   2 +-
 fs/ext4/inode.c                                   | 117 +++-
 fs/ext4/super.c                                   |   1 +
 fs/ext4/truncate.h                                |   2 +
 fs/inode.c                                        |   1 +
 fs/locks.c                                        |   2 +-
 fs/namei.c                                        |  56 +-
 include/linux/blkdev.h                            |  10 +-
 include/linux/blktrace_api.h                      |   6 +-
 include/linux/cdev.h                              |   5 +
 include/linux/fs.h                                |   3 +
 include/linux/futex.h                             |  17 +-
 include/linux/if_ether.h                          |   8 +
 include/linux/kobject.h                           |   2 +
 include/linux/mod_devicetable.h                   |   4 +-
 include/linux/netfilter_arp/arp_tables.h          |   2 +-
 include/linux/posix-clock.h                       |  19 +-
 include/linux/quotaops.h                          |   2 +-
 include/linux/usb/quirks.h                        |   3 +
 include/media/media-device.h                      |   5 +-
 include/media/media-devnode.h                     |  32 +-
 include/net/addrconf.h                            |   5 +-
 include/net/cfg80211.h                            |  11 +
 include/net/neighbour.h                           |   1 -
 kernel/futex.c                                    |  93 ++--
 kernel/sysctl.c                                   |  18 +
 kernel/taskstats.c                                |  30 +-
 kernel/time/posix-clock.c                         |  31 +-
 kernel/trace/blktrace.c                           | 129 +++--
 kernel/trace/ftrace.c                             |   6 +-
 kernel/trace/trace_sched_wakeup.c                 |   4 +-
 kernel/trace/trace_stack.c                        |   5 +
 lib/kobject.c                                     |   5 +-
 mm/mempolicy.c                                    |   6 +-
 net/8021q/vlan_netlink.c                          |  10 +-
 net/batman-adv/distributed-arp-table.c            |   4 +-
 net/bridge/br_netfilter.c                         |   3 +
 net/bridge/netfilter/ebtables.c                   |  58 +-
 net/core/neighbour.c                              |   3 -
 net/ipv4/netfilter/arp_tables.c                   |  42 +-
 net/ipv4/netfilter/arptable_filter.c              |   2 +-
 net/ipv4/tcp_input.c                              |   5 +-
 net/ipv4/tcp_output.c                             |   8 +
 net/ipv6/af_inet6.c                               |   2 +-
 net/mac80211/cfg.c                                |  55 +-
 net/mac80211/sta_info.c                           |   4 +
 net/netfilter/ipset/ip_set_bitmap_gen.h           |   2 +-
 net/netfilter/ipset/ip_set_core.c                 |   3 +-
 net/netfilter/nf_conntrack_netlink.c              |   3 +
 net/netfilter/nft_bitwise.c                       |  19 +-
 net/netfilter/nft_cmp.c                           |  18 +-
 net/packet/af_packet.c                            |   3 +-
 net/sched/ematch.c                                |   2 +-
 net/sched/sch_fq.c                                |  10 +-
 net/sctp/sm_sideeffect.c                          |  28 +-
 net/wireless/util.c                               |  45 ++
 scripts/recordmcount.c                            |  17 +
 sound/core/pcm_native.c                           |   4 +
 sound/core/seq/seq_timer.c                        |  14 +-
 sound/pci/hda/patch_ca0132.c                      |   5 +-
 sound/pci/ice1712/ice1724.c                       |   9 +-
 sound/soc/codecs/wm8962.c                         |   4 +-
 sound/usb/pcm.c                                   |  44 +-
 197 files changed, 3377 insertions(+), 1229 deletions(-)

Al Viro (2):
      do_last(): fetch directory ->i_mode and ->i_uid before it's too late
      vfs: fix do_last() regression

Alan Cox (1):
      usb: dwc3: pci: Add PCI ID for Intel Braswell

Alan Stern (1):
      HID: Fix slab-out-of-bounds read in hid_field_extract

Alberto Aguirre (2):
      ALSA: usb-audio: add implicit fb quirk for Axe-Fx II
      ALSA: usb-audio: simplify set_sync_ep_implicit_fb_quirk

Alex Sverdlin (1):
      ARM: 8950/1: ftrace/recordmcount: filter relocation types

Amir Goldstein (1):
      locks: print unsigned ino in /proc/locks

Ard Biesheuvel (1):
      x86/efistub: Disable paging at mixed mode entry

Arnd Bergmann (2):
      btrfs: tree-checker: use %zu format string for size_t
      scsi: fnic: fix invalid stack access

Avinash Patil (1):
      mwifiex: fix probable memory corruption while processing TDLS frame

Ben Hutchings (1):
      Linux 3.16.83

Brian Norris (1):
      mwifiex: fix unbalanced locking in mwifiex_process_country_ie()

Cengiz Can (1):
      blktrace: fix dereference after null check

Chao Yu (1):
      quota: fix wrong condition in is_quota_modification()

Chen-Yu Tsai (1):
      net: stmmac: dwmac-sunxi: Allow all RGMII modes

Christian Brauner (1):
      taskstats: fix data-race

Christophe Leroy (1):
      powerpc/irq: fix stack overflow verification

Cong Wang (2):
      netfilter: fix a use-after-free in mtype_destroy()
      net_sched: fix datalen for ematch

Dan Carpenter (1):
      scsi: iscsi: qla4xxx: fix double free in probe

David Hildenbrand (1):
      virtio-balloon: fix managed page counts when migrating pages between zones

David Sterba (6):
      btrfs: new define for the inline extent data start
      btrfs: kill extent_buffer_page helper
      btrfs: cleanup, rename a few variables in btrfs_read_sys_array
      btrfs: add more checks to btrfs_read_sys_array
      btrfs: handle invalid num_stripes in sys_array
      btrfs: tree-check: reduce stack consumption in check_dir_item

Davidlohr Bueso (1):
      blktrace: re-write setting q->blk_trace

Dedy Lansky (1):
      cfg80211/mac80211: make ieee80211_send_layer2_update a public function

Dmitry Torokhov (5):
      HID: hid-input: clear unmapped usages
      Input: add safety guards to input_set_keycode()
      ptp: do not explicitly set drvdata in ptp_clock_register()
      ptp: use is_visible method to hide unused attributes
      ptp: create "pins" together with the rest of attributes

Emiliano Ingrassia (1):
      usb: core: urb: fix URB structure initialization function

Eric Dumazet (9):
      netfilter: bridge: make sure to pull arp header in br_nf_forward_arp()
      neighbour: remove neigh_cleanup() method
      bonding: fix bond_neigh_init()
      6pack,mkiss: fix possible deadlock
      tcp: do not send empty skb from tcp_write_xmit()
      vlan: vlan_changelink() should propagate errors
      pkt_sched: fq: do not accept silly TCA_FQ_QUANTUM
      macvlan: do not assume mac_header is set in macvlan_broadcast()
      macvlan: use skb_reset_mac_header() in macvlan_queue_xmit()

Erkka Talvitie (1):
      USB: EHCI: Do not return -EPIPE when hub is disconnected

Eryu Guan (1):
      ext4: update c/mtime on truncate up

Eugenio Pérez (1):
      vhost: Check docket sk_family instead of call getname

Fabian Henneke (1):
      hidraw: Return EPOLLOUT from hidraw_poll

Felipe Balbi (3):
      usb: dwc3: pci: add support for Comet Lake PCH ID
      usb: dwc3: pci: Add Support for Intel Elkhart Lake Devices
      usb: dwc3: pci: add support for TigerLake Devices

Filipe Manana (3):
      Btrfs: fix emptiness check for dirtied extent buffers at check_leaf()
      Btrfs: fix removal logic of the tree mod log that leads to use-after-free issues
      Btrfs: fix infinite loop during nocow writeback due to race

Finn Thain (4):
      net/sonic: Add mutual exclusion for accessing shared state
      net/sonic: Use MMIO accessors
      net/sonic: Fix receive buffer handling
      net/sonic: Quiesce SONIC before re-initializing descriptor memory

Florian Faber (1):
      can: mscan: mscan_rx_poll(): fix rx path lockup when returning from polling to irq mode

Florian Westphal (6):
      netfilter: ctnetlink: netns exit must wait for callbacks
      netfilter: ebtables: convert BUG_ONs to WARN_ONs
      netfilter: ebtables: compat: reject all padding in matches/watchers
      netfilter: arp_tables: init netns pointer in xt_tgchk_param struct
      netfilter: ipset: avoid null deref when IPSET_ATTR_LINENO is present
      netfilter: arp_tables: init netns pointer in xt_tgdtor_param struct

Geert Uytterhoeven (1):
      gpio: Fix error message on out-of-range GPIO in lookup table

Goldwyn Rodrigues (1):
      dm flakey: check for null arg_name in parse_features()

Gu Jinxiang (1):
      btrfs: validate type when reading a chunk

Hangbin Liu (1):
      vxlan: fix tos value before xmit

Hans de Goede (2):
      pinctrl: baytrail: Really serialize all register accesses
      platform/x86: hp-wmi: Make buffer for HPWMI_FEATURE2_QUERY 128 bytes

Heikki Krogerus (8):
      usb: dwc3: pci: add support for Intel Sunrise Point PCH
      usb: dwc3: pci: add support for Intel Broxton SOC
      usb: dwc3: pci: add ID for one more Intel Broxton platform
      usb: dwc3: pci: add Intel Kabylake PCI ID
      usb: dwc3: pci: add Intel Gemini Lake PCI ID
      usb: dwc3: pci: add Intel Cannonlake PCI IDs
      usb: dwc3: pci: add support for Intel IceLake
      usb: dwc3: pci: add ID for the Intel Comet Lake -H variant

Hou Tao (1):
      dm btree: increase rebalance threshold in __rebalance2()

James Bottomley (1):
      scsi: enclosure: Fix stale device oops with hot replug

Jan Kara (7):
      ext4: fix races between page faults and hole punching
      ext4: move unlocked dio protection from ext4_alloc_file_blocks()
      ext4: fix races between buffered IO and collapse / insert range
      ext4: fix races of writeback with punch hole and zero range
      ext4: check for directory entries too close to block end
      kobject: Export kobject_get_unless_zero()
      blktrace: Protect q->blk_trace with RCU

Jari Ruusu (1):
      Fix built-in early-load Intel microcode alignment

Jeff Mahoney (2):
      btrfs: cleanup, stop casting for extent_map->lookup everywhere
      btrfs: struct-funcs, constify readers

Jerónimo Borque (1):
      USB: serial: simple: Add Motorola Solutions TETRA MTP3xxx and MTP85xx

Jian-Hong Pan (1):
      platform/x86: asus-wmi: Fix keyboard brightness cannot be set to 0

Jim Mattson (1):
      kvm: x86: Host feature SSBD doesn't imply guest feature SPEC_CTRL_SSBD

Jiri Kosina (1):
      HID: hidraw, uhid: Always report EPOLLOUT

Jiri Slaby (4):
      vt: selection, handle pending signals in paste_selection
      vt: selection, close sel_buffer race
      vt: selection, push console lock down
      vt: selection, push sel_lock up

Johan Hovold (29):
      staging: gigaset: fix general protection fault on probe
      staging: gigaset: fix illegal free on probe errors
      staging: gigaset: add endpoint-type sanity check
      USB: serial: io_edgeport: fix epic endpoint lookup
      USB: idmouse: fix interface sanity checks
      USB: adutux: fix interface sanity check
      USB: atm: ueagle-atm: add missing endpoint check
      staging: rtl8188eu: fix interface sanity check
      staging: rtl8712: fix interface sanity check
      USB: core: fix check for duplicate endpoints
      USB: core: add endpoint-blacklist quirk
      USB: quirks: blacklist duplicate ep on Sound Devices USBPre2
      can: gs_usb: gs_usb_probe(): use descriptors of current altsetting
      Input: aiptek - fix endpoint sanity check
      Input: gtco - fix endpoint sanity check
      Input: sur40 - fix interface sanity checks
      ALSA: usb-audio: fix sync-ep altsetting sanity check
      USB: serial: opticon: fix control-message timeouts
      r8152: add missing endpoint sanity check
      Input: keyspan-remote - fix control-message timeouts
      USB: serial: suppress driver bind attributes
      USB: serial: ch341: handle unbound port at reset_resume
      USB: serial: io_edgeport: handle unbound ports on URB completion
      USB: serial: io_edgeport: add missing active-port sanity check
      USB: serial: keyspan: handle unbound ports
      USB: serial: quatech2: handle unbound ports
      media: ov519: add missing endpoint sanity checks
      media: stv06xx: add missing descriptor sanity checks
      media: xirlink_cit: add missing descriptor sanity checks

Johannes Thumshirn (1):
      btrfs: ensure that a DUP or RAID1 block group has exactly two stripes

Jose Abreu (2):
      net: stmmac: 16KB buffer must be 16 byte aligned
      net: stmmac: Enable 16KB buffer size

Josef Bacik (9):
      ext4: only call ext4_truncate when size <= isize
      Btrfs: fix em leak in find_first_block_group
      btrfs: do not call synchronize_srcu() in inode_tree_del
      btrfs: abort transaction after failed inode updates in create_subvol
      btrfs: handle ENOENT in btrfs_uuid_tree_iterate
      btrfs: skip log replay on orphaned roots
      btrfs: do not leak reloc root if we fail to read the fs root
      btrfs: do not delete mismatched root refs
      btrfs: check rw_devices, not num_devices for balance

Jouni Malinen (1):
      mac80211: Do not send Layer 2 Update frame before authorization

Kaitao Cheng (1):
      kernel/trace: Fix do not unregister tracepoints when register sched_migrate_task fail

Keiya Nobuta (1):
      usb: core: hub: Improved device recognition on remote wakeup

Kenneth Klette Jonassen (1):
      pkt_sched: fq: avoid hang when quantum 0

Lars Möllendorf (1):
      iio: buffer: align the size of scan bytes to size of the largest element

Leo Yan (1):
      tty: serial: msm_serial: Fix lockup for sysrq and oops

Linus Torvalds (1):
      floppy: check FDC index for errors before assigning it

Liu Bo (9):
      Btrfs: add validadtion checks for chunk loading
      Btrfs: check inconsistence between chunk and block group
      Btrfs: detect corruption when non-root leaf has zero item
      Btrfs: check btree node's nritems
      Btrfs: fix BUG_ON in btrfs_mark_buffer_dirty
      Btrfs: memset to avoid stale content in btree node block
      Btrfs: improve check_node to avoid reading corrupted nodes
      Btrfs: kill BUG_ON in run_delayed_tree_ref
      Btrfs: memset to avoid stale content in btree leaf

Logan Gunthorpe (1):
      chardev: add helper function to register char devs with a struct device

Lu Fengqi (1):
      btrfs: Remove redundant btrfs_release_path from btrfs_unlink_subvol

Lukas Czerner (1):
      ext4: wait for existing dio workers in ext4_alloc_file_blocks()

Luuk Paulussen (1):
      hwmon: (adt7475) Make volt2reg return same reg as reg2volt input

Mao Wenan (2):
      af_packet: set defaule value for tmo
      net: sonic: return NETDEV_TX_OK if failed to map buffer

Marcel Holtmann (2):
      HID: uhid: Fix returning EPOLLOUT from uhid_char_poll
      HID: hidraw: Fix returning EPOLLOUT from hidraw_poll

Mathias Nyman (2):
      xhci: handle some XHCI_TRUST_TX_LENGTH quirks cases as default behaviour.
      xhci: make sure interrupts are restored to correct state

Mauro Carvalho Chehab (3):
      media-devnode: just return 0 instead of using a var
      media-devnode: fix namespace mess
      media-device: dynamically allocate struct media_devnode

Max Kellermann (2):
      drivers/media/media-devnode: clear private_data before put_device()
      media-devnode: add missing mutex lock in error handler

Michael Straube (1):
      staging: rtl8188eu: Add device code for TP-Link TL-WN727N v5.21

Michał Mirosław (1):
      mmc: sdhci: fix minimum clock rate for v3 controller

Mika Westerberg (4):
      pinctrl: baytrail: Relax GPIO request rules
      pinctrl: baytrail: Clear interrupt triggering from pins that are in GPIO mode
      pinctrl: baytrail: Rework interrupt handling
      pinctrl: baytrail: Serialize all register access

Mike Snitzer (1):
      dm flakey: fix reads to be issued if drop_writes configured

Mikulas Patocka (1):
      block: fix an integer overflow in logical block size

Moni Shoua (1):
      IB/mlx4: Avoid executing gid task when device is being removed

Nicolai Stange (2):
      libertas: don't exit from lbs_ibss_join_existing() with RCU read lock held
      libertas: make lbs_ibss_join_existing() return error code on rates overflow

Nikos Tsironis (1):
      dm thin metadata: Add support for a pre-commit callback

Pablo Neira Ayuso (2):
      netfilter: nf_tables: missing sanitization in data from userspace
      netfilter: nf_tables: validate NFT_DATA_VALUE after nft_data_init()

Paolo Bonzini (1):
      KVM: nVMX: Don't emulate instructions in guest mode

Parav Pandit (1):
      IB/mlx4: Follow mirror sequence of device add during device removal

Paul Cercueil (1):
      usb: musb: dma: Correct parameter passed to IRQ handler

Pavel Tatashin (1):
      x86/pti/efi: broken conversion from efi to kernel page table

Pengcheng Yang (1):
      tcp: fix "old stuff" D-SACK causing SACK to be treated as D-SACK

Pete Zaitcev (1):
      usb: mon: Fix a deadlock in usbmon between mmap and read

Peter Hurley (1):
      tty: vt: Fix !TASK_RUNNING diagnostic warning from paste_selection()

Peter Zijlstra (1):
      futex: Fix inode life-time issue

Qu Wenruo (14):
      btrfs: Enhance chunk validation check
      btrfs: Refactor check_leaf function for later expansion
      btrfs: Check if item pointer overlaps with the item itself
      btrfs: Add sanity check for EXTENT_DATA when reading out leaf
      btrfs: Add checker for EXTENT_CSUM
      btrfs: Move leaf and node validation checker to tree-checker.c
      btrfs: tree-checker: Enhance btrfs_check_node output
      btrfs: tree-checker: Fix false panic for sanity test
      btrfs: tree-checker: Add checker for dir item
      btrfs: tree-checker: Verify block_group_item
      btrfs: tree-checker: Detect invalid and empty essential trees
      btrfs: Check that each block group has corresponding chunk at mount time
      btrfs: Verify that every chunk has corresponding block group at mount time
      btrfs: tree-checker: Check level for leaves and nodes

Radoslaw Tyl (1):
      ixgbevf: Remove limit of 10 entries for unicast filter list

Rafael J. Wysocki (1):
      ACPI: PM: Avoid attaching ACPI PM domain to certain devices

Randy Dunlap (1):
      mm: mempolicy: require at least one nodeid for MPOL_PREFERRED

Richard Palethorpe (2):
      can, slip: Protect tty->disc_data in write_wakeup and close with RCU
      slcan: Don't transmit uninitialized stack data in padding

Russell King (2):
      gpiolib: fix up emulated open drain outputs
      mod_devicetable: fix PHY module format

Sabrina Dubroca (1):
      net: ipv6_stub: use ip6_dst_lookup_flow instead of ip6_dst_lookup

Salvatore Mesoraca (1):
      namei: allow restricted O_CREAT of FIFOs and regular files

Shaokun Zhang (1):
      btrfs: tree-checker: Fix misleading group system information

Shengjiu Wang (1):
      ASoC: wm8962: fix lambda value

Shuah Khan (3):
      media: Fix media_open() to clear filp->private_data in error leg
      media: fix use-after-free in cdev_put() when app exits after driver unbind
      media: fix media devnode ioctl/syscall and unregister race

Steven Rostedt (VMware) (1):
      tracing: Have stack tracer compile when MCOUNT_INSN_SIZE is not defined

Sudip Mukherjee (2):
      tty: link tty and port before configuring it as console
      tty: always relink the port

Suren Baghdasaryan (1):
      staging: android: ashmem: Disallow ashmem memory from being remapped

Suwan Kim (1):
      usbip: Fix error path of vhci_recv_ret_submit()

Sven Eckelmann (1):
      batman-adv: Fix DAT candidate selection on little endian systems

Takashi Iwai (4):
      ALSA: pcm: Avoid possible info leaks from PCM stream buffers
      ALSA: hda/ca0132 - Avoid endless loop
      ALSA: ice1724: Fix sleep-in-atomic in Infrasonic Quartet support code
      ALSA: seq: Fix racy access for queue timer in proc read

Thomas Gleixner (1):
      futex: Unbreak futex hashing

Tom Lendacky (1):
      x86/microcode/AMD: Add support for fam17h microcode loading

Vivek Goyal (1):
      dm: do not override error code returned from dm_get_device()

Vladis Dronov (2):
      ptp: fix the race between the release of ptp_clock and cdev
      ptp: free ptp device pin descriptors properly

Wang Shilong (1):
      Btrfs: fix wrong max inline data size limit

Wei Yongjun (1):
      dm flakey: return -EINVAL on interval bounds error in flakey_ctr()

Wen Huang (1):
      libertas: Fix two buffer overflows at parsing bss descriptor

Wen Yang (1):
      ftrace: Avoid potential division by zero in function profiler

Will Deacon (1):
      chardev: Avoid potential use-after-free in 'chrdev_open()'

Xiang Chen (1):
      scsi: sd: Clear sdkp->protection_type if disk is reformatted without PI

Xin Long (1):
      sctp: free cmd->obj.chunk for the unprocessed SCTP_CMD_REPLY

YueHaibing (1):
      ptp: Fix pass zero to ERR_PTR() in ptp_clock_register

Zhang Xiaoxu (1):
      vgacon: Fix a UAF in vgacon_invert_region

qize wang (1):
      mwifiex: Fix heap overflow in mmwifiex_process_tdls_action_frame()


[-- Attachment #1.2: linux-3.16.83.patch --]
[-- Type: text/x-diff, Size: 337423 bytes --]

diff --git a/Documentation/sysctl/fs.txt b/Documentation/sysctl/fs.txt
index 35e17f748ca7..af5859b2d0f9 100644
--- a/Documentation/sysctl/fs.txt
+++ b/Documentation/sysctl/fs.txt
@@ -34,7 +34,9 @@ before actually making adjustments.
 - overflowgid
 - pipe-user-pages-hard
 - pipe-user-pages-soft
+- protected_fifos
 - protected_hardlinks
+- protected_regular
 - protected_symlinks
 - suid_dumpable
 - super-max
@@ -182,6 +184,24 @@ applied.
 
 ==============================================================
 
+protected_fifos:
+
+The intent of this protection is to avoid unintentional writes to
+an attacker-controlled FIFO, where a program expected to create a regular
+file.
+
+When set to "0", writing to FIFOs is unrestricted.
+
+When set to "1" don't allow O_CREAT open on FIFOs that we don't own
+in world writable sticky directories, unless they are owned by the
+owner of the directory.
+
+When set to "2" it also applies to group writable sticky directories.
+
+This protection is based on the restrictions in Openwall.
+
+==============================================================
+
 protected_hardlinks:
 
 A long-standing class of security issues is the hardlink-based
@@ -202,6 +222,22 @@ This protection is based on the restrictions in Openwall and grsecurity.
 
 ==============================================================
 
+protected_regular:
+
+This protection is similar to protected_fifos, but it
+avoids writes to an attacker-controlled regular file, where a program
+expected to create one.
+
+When set to "0", writing to regular files is unrestricted.
+
+When set to "1" don't allow O_CREAT open on regular files that we
+don't own in world writable sticky directories, unless they are
+owned by the owner of the directory.
+
+When set to "2" it also applies to group writable sticky directories.
+
+==============================================================
+
 protected_symlinks:
 
 A long-standing class of security issues is the symlink-based
diff --git a/Makefile b/Makefile
index 64e7647e6a9d..99500d145fab 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 3
 PATCHLEVEL = 16
-SUBLEVEL = 82
+SUBLEVEL = 83
 EXTRAVERSION =
 NAME = Museum of Fishiegoodies
 
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 856a6cac5c3e..c755e672d96e 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -471,8 +471,6 @@ void __do_irq(struct pt_regs *regs)
 
 	trace_irq_entry(regs);
 
-	check_stack_overflow();
-
 	/*
 	 * Query the platform PIC for the interrupt & ack it.
 	 *
@@ -504,6 +502,8 @@ void do_IRQ(struct pt_regs *regs)
 	irqtp = hardirq_ctx[raw_smp_processor_id()];
 	sirqtp = softirq_ctx[raw_smp_processor_id()];
 
+	check_stack_overflow();
+
 	/* Already there ? */
 	if (unlikely(curtp == irqtp || curtp == sirqtp)) {
 		__do_irq(regs);
diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
index 6b1766c6c082..2fcd71219b92 100644
--- a/arch/x86/boot/compressed/head_64.S
+++ b/arch/x86/boot/compressed/head_64.S
@@ -216,6 +216,11 @@ ENTRY(efi32_stub_entry)
 	leal	efi32_config(%ebp), %eax
 	movl	%eax, efi_config(%ebp)
 
+	/* Disable paging */
+	movl	%cr0, %eax
+	btrl	$X86_CR0_PG_BIT, %eax
+	movl	%eax, %cr0
+
 	jmp	startup_32
 ENDPROC(efi32_stub_entry)
 #endif
diff --git a/arch/x86/include/asm/kaiser.h b/arch/x86/include/asm/kaiser.h
index 802bbbdfe143..48c791a411ab 100644
--- a/arch/x86/include/asm/kaiser.h
+++ b/arch/x86/include/asm/kaiser.h
@@ -19,6 +19,16 @@
 
 #define KAISER_SHADOW_PGD_OFFSET 0x1000
 
+#ifdef CONFIG_PAGE_TABLE_ISOLATION
+/*
+ *  A page table address must have this alignment to stay the same when
+ *  KAISER_SHADOW_PGD_OFFSET mask is applied
+ */
+#define KAISER_KERNEL_PGD_ALIGNMENT (KAISER_SHADOW_PGD_OFFSET << 1)
+#else
+#define KAISER_KERNEL_PGD_ALIGNMENT PAGE_SIZE
+#endif
+
 #ifdef __ASSEMBLY__
 #ifdef CONFIG_PAGE_TABLE_ISOLATION
 
diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c
index ff16949e7f3d..6068c25e7c48 100644
--- a/arch/x86/kernel/cpu/microcode/amd.c
+++ b/arch/x86/kernel/cpu/microcode/amd.c
@@ -154,6 +154,7 @@ static unsigned int verify_patch_size(u8 family, u32 patch_size,
 #define F14H_MPB_MAX_SIZE 1824
 #define F15H_MPB_MAX_SIZE 4096
 #define F16H_MPB_MAX_SIZE 3458
+#define F17H_MPB_MAX_SIZE 3200
 
 	switch (family) {
 	case 0x14:
@@ -165,6 +166,9 @@ static unsigned int verify_patch_size(u8 family, u32 patch_size,
 	case 0x16:
 		max_size = F16H_MPB_MAX_SIZE;
 		break;
+	case 0x17:
+		max_size = F17H_MPB_MAX_SIZE;
+		break;
 	default:
 		max_size = F1XH_MPB_MAX_SIZE;
 		break;
diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index 66062325d4b7..22958dcfccd9 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -400,7 +400,8 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
 				entry->edx |= F(SPEC_CTRL);
 			if (boot_cpu_has(X86_FEATURE_STIBP))
 				entry->edx |= F(INTEL_STIBP);
-			if (boot_cpu_has(X86_FEATURE_SSBD))
+			if (boot_cpu_has(X86_FEATURE_SPEC_CTRL_SSBD) ||
+			    boot_cpu_has(X86_FEATURE_AMD_SSBD))
 				entry->edx |= F(SPEC_CTRL_SSBD);
 			/*
 			 * We emulate ARCH_CAPABILITIES in software even
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index a1dbb20b768b..1faaa78505f4 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -8938,7 +8938,7 @@ static int vmx_check_intercept(struct kvm_vcpu *vcpu,
 			       struct x86_instruction_info *info,
 			       enum x86_intercept_stage stage)
 {
-	return X86EMUL_CONTINUE;
+	return X86EMUL_UNHANDLEABLE;
 }
 
 static struct kvm_x86_ops vmx_x86_ops = {
diff --git a/arch/x86/realmode/init.c b/arch/x86/realmode/init.c
index bad628a620c4..66f20e7756cc 100644
--- a/arch/x86/realmode/init.c
+++ b/arch/x86/realmode/init.c
@@ -4,6 +4,7 @@
 #include <asm/cacheflush.h>
 #include <asm/pgtable.h>
 #include <asm/realmode.h>
+#include <asm/kaiser.h>
 
 struct real_mode_header *real_mode_header;
 u32 *trampoline_cr4_features;
@@ -15,7 +16,8 @@ void __init reserve_real_mode(void)
 	size_t size = PAGE_ALIGN(real_mode_blob_end - real_mode_blob);
 
 	/* Has to be under 1M so we can execute real-mode AP code. */
-	mem = memblock_find_in_range(0, 1<<20, size, PAGE_SIZE);
+	mem = memblock_find_in_range(0, 1 << 20, size,
+				     KAISER_KERNEL_PGD_ALIGNMENT);
 	if (!mem)
 		panic("Cannot allocate trampoline\n");
 
diff --git a/arch/x86/realmode/rm/trampoline_64.S b/arch/x86/realmode/rm/trampoline_64.S
index dac7b20d2f9d..781cca63f795 100644
--- a/arch/x86/realmode/rm/trampoline_64.S
+++ b/arch/x86/realmode/rm/trampoline_64.S
@@ -30,6 +30,7 @@
 #include <asm/msr.h>
 #include <asm/segment.h>
 #include <asm/processor-flags.h>
+#include <asm/kaiser.h>
 #include "realmode.h"
 
 	.text
@@ -139,7 +140,7 @@ ENTRY(startup_64)
 tr_gdt_end:
 
 	.bss
-	.balign	PAGE_SIZE
+	.balign	KAISER_KERNEL_PGD_ALIGNMENT
 GLOBAL(trampoline_pgd)		.space	PAGE_SIZE
 
 	.balign	8
diff --git a/block/blk-settings.c b/block/blk-settings.c
index aa02247d227e..f1bd4ca22c6b 100644
--- a/block/blk-settings.c
+++ b/block/blk-settings.c
@@ -373,7 +373,7 @@ EXPORT_SYMBOL(blk_queue_max_segment_size);
  *   storage device can address.  The default of 512 covers most
  *   hardware.
  **/
-void blk_queue_logical_block_size(struct request_queue *q, unsigned short size)
+void blk_queue_logical_block_size(struct request_queue *q, unsigned int size)
 {
 	q->limits.logical_block_size = size;
 
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c
index e9f44a210712..4a41ec7414db 100644
--- a/drivers/acpi/device_pm.c
+++ b/drivers/acpi/device_pm.c
@@ -1041,9 +1041,19 @@ static struct dev_pm_domain acpi_general_pm_domain = {
  */
 int acpi_dev_pm_attach(struct device *dev, bool power_on)
 {
+	/*
+	 * Skip devices whose ACPI companions match the device IDs below,
+	 * because they require special power management handling incompatible
+	 * with the generic ACPI PM domain.
+	 */
+	static const struct acpi_device_id special_pm_ids[] = {
+		{"PNP0C0B", }, /* Generic ACPI fan */
+		{"INT3404", }, /* Fan */
+		{}
+	};
 	struct acpi_device *adev = ACPI_COMPANION(dev);
 
-	if (!adev)
+	if (!adev || !acpi_match_device_ids(adev, special_pm_ids))
 		return -ENODEV;
 
 	if (dev->pm_domain)
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 3999b8c6a09d..85c8bcb8157b 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -847,14 +847,17 @@ static void reset_fdc_info(int mode)
 /* selects the fdc and drive, and enables the fdc's input/dma. */
 static void set_fdc(int drive)
 {
+	unsigned int new_fdc = fdc;
+
 	if (drive >= 0 && drive < N_DRIVE) {
-		fdc = FDC(drive);
+		new_fdc = FDC(drive);
 		current_drive = drive;
 	}
-	if (fdc != 1 && fdc != 0) {
+	if (new_fdc >= N_FDC) {
 		pr_info("bad fdc value\n");
 		return;
 	}
+	fdc = new_fdc;
 	set_dor(fdc, ~0, 8);
 #if N_FDC > 1
 	set_dor(1 - fdc, ~8, 0);
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index c6eaa7a4539c..770eabbc554b 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -273,6 +273,14 @@ int gpiod_get_direction(const struct gpio_desc *desc)
 	chip = gpiod_to_chip(desc);
 	offset = gpio_chip_hwgpio(desc);
 
+	/*
+	 * Open drain emulation using input mode may incorrectly report
+	 * input here, fix that up.
+	 */
+	if (test_bit(FLAG_OPEN_DRAIN, &desc->flags) &&
+	    test_bit(FLAG_IS_OUT, &desc->flags))
+		return 0;
+
 	if (!chip->get_direction)
 		return status;
 
@@ -2743,8 +2751,9 @@ static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id,
 
 		if (chip->ngpio <= p->chip_hwnum) {
 			dev_err(dev,
-				"requested GPIO %d is out of range [0..%d] for chip %s\n",
-				idx, chip->ngpio, chip->label);
+				"requested GPIO %u (%u) is out of range [0..%u] for chip %s\n",
+				idx, p->chip_hwnum, chip->ngpio - 1,
+				chip->label);
 			return ERR_PTR(-EINVAL);
 		}
 
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 38b1cad80322..c8f21de0fc19 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -248,6 +248,12 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign
 	offset = report->size;
 	report->size += parser->global.report_size * parser->global.report_count;
 
+	/* Total size check: Allow for possible report index byte */
+	if (report->size > (HID_MAX_BUFFER_SIZE - 1) << 3) {
+		hid_err(parser->device, "report is too long\n");
+		return -1;
+	}
+
 	if (!parser->local.usage_index) /* Ignore padding fields */
 		return 0;
 
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 39b4193a37f4..b65eb2a723ac 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -947,9 +947,15 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
 	}
 
 mapped:
-	if (device->driver->input_mapped && device->driver->input_mapped(device,
-				hidinput, field, usage, &bit, &max) < 0)
-		goto ignore;
+	if (device->driver->input_mapped &&
+	    device->driver->input_mapped(device, hidinput, field, usage,
+					 &bit, &max) < 0) {
+		/*
+		 * The driver indicated that no further generic handling
+		 * of the usage is desired.
+		 */
+		return;
+	}
 
 	set_bit(usage->type, input->evbit);
 
@@ -1008,9 +1014,11 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
 		set_bit(MSC_SCAN, input->mscbit);
 	}
 
-ignore:
 	return;
 
+ignore:
+	usage->type = 0;
+	usage->code = 0;
 }
 
 void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value)
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index 627a24d3ea7c..ef9e196b54a5 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -262,13 +262,14 @@ static ssize_t hidraw_get_report(struct file *file, char __user *buffer, size_t
 static unsigned int hidraw_poll(struct file *file, poll_table *wait)
 {
 	struct hidraw_list *list = file->private_data;
+	unsigned int mask = POLLOUT | POLLWRNORM; /* hidraw is always writable */
 
 	poll_wait(file, &list->hidraw->wait, wait);
 	if (list->head != list->tail)
-		return POLLIN | POLLRDNORM;
+		mask |= POLLIN | POLLRDNORM;
 	if (!list->hidraw->exist)
-		return POLLERR | POLLHUP;
-	return 0;
+		mask |= POLLERR | POLLHUP;
+	return mask;
 }
 
 static int hidraw_open(struct inode *inode, struct file *file)
diff --git a/drivers/hid/uhid.c b/drivers/hid/uhid.c
index 035c7c2863dc..f4063d788469 100644
--- a/drivers/hid/uhid.c
+++ b/drivers/hid/uhid.c
@@ -720,13 +720,14 @@ static ssize_t uhid_char_write(struct file *file, const char __user *buffer,
 static unsigned int uhid_char_poll(struct file *file, poll_table *wait)
 {
 	struct uhid_device *uhid = file->private_data;
+	unsigned int mask = POLLOUT | POLLWRNORM; /* uhid is always writable */
 
 	poll_wait(file, &uhid->waitq, wait);
 
 	if (uhid->head != uhid->tail)
-		return POLLIN | POLLRDNORM;
+		mask |= POLLIN | POLLRDNORM;
 
-	return 0;
+	return mask;
 }
 
 static const struct file_operations uhid_fops = {
diff --git a/drivers/hwmon/adt7475.c b/drivers/hwmon/adt7475.c
index 3cefd1aeb24f..1b9f6adcbd85 100644
--- a/drivers/hwmon/adt7475.c
+++ b/drivers/hwmon/adt7475.c
@@ -268,9 +268,10 @@ static inline u16 volt2reg(int channel, long volt, u8 bypass_attn)
 	long reg;
 
 	if (bypass_attn & (1 << channel))
-		reg = (volt * 1024) / 2250;
+		reg = DIV_ROUND_CLOSEST(volt * 1024, 2250);
 	else
-		reg = (volt * r[1] * 1024) / ((r[0] + r[1]) * 2250);
+		reg = DIV_ROUND_CLOSEST(volt * r[1] * 1024,
+					(r[0] + r[1]) * 2250);
 	return clamp_val(reg, 0, 1023) & (0xff << 2);
 }
 
diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
index 77b19ca8b763..6479e3ec2110 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -478,7 +478,7 @@ static int iio_compute_scan_bytes(struct iio_dev *indio_dev,
 {
 	const struct iio_chan_spec *ch;
 	unsigned bytes = 0;
-	int length, i;
+	int length, i, largest = 0;
 
 	/* How much space will the demuxed element take? */
 	for_each_set_bit(i, mask,
@@ -491,6 +491,7 @@ static int iio_compute_scan_bytes(struct iio_dev *indio_dev,
 			length = ch->scan_type.storagebits / 8;
 		bytes = ALIGN(bytes, length);
 		bytes += length;
+		largest = max(largest, length);
 	}
 	if (timestamp) {
 		ch = iio_find_channel_from_si(indio_dev,
@@ -502,7 +503,10 @@ static int iio_compute_scan_bytes(struct iio_dev *indio_dev,
 			length = ch->scan_type.storagebits / 8;
 		bytes = ALIGN(bytes, length);
 		bytes += length;
+		largest = max(largest, length);
 	}
+
+	bytes = ALIGN(bytes, largest);
 	return bytes;
 }
 
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
index 79a8accc0801..401f556d954c 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -1395,6 +1395,9 @@ static void update_gids_task(struct work_struct *work)
 	int err;
 	struct mlx4_dev	*dev = gw->dev->dev;
 
+	if (!gw->dev->ib_active)
+		return;
+
 	mailbox = mlx4_alloc_cmd_mailbox(dev);
 	if (IS_ERR(mailbox)) {
 		pr_warn("update gid table failed %ld\n", PTR_ERR(mailbox));
@@ -1425,6 +1428,9 @@ static void reset_gids_task(struct work_struct *work)
 	int err;
 	struct mlx4_dev	*dev = gw->dev->dev;
 
+	if (!gw->dev->ib_active)
+		return;
+
 	mailbox = mlx4_alloc_cmd_mailbox(dev);
 	if (IS_ERR(mailbox)) {
 		pr_warn("reset gid table failed\n");
@@ -2363,15 +2369,19 @@ static void mlx4_ib_remove(struct mlx4_dev *dev, void *ibdev_ptr)
 	struct mlx4_ib_dev *ibdev = ibdev_ptr;
 	int p;
 
-	mlx4_ib_close_sriov(ibdev);
-	mlx4_ib_mad_cleanup(ibdev);
-	ib_unregister_device(&ibdev->ib_dev);
+	ibdev->ib_active = false;
+	flush_workqueue(wq);
+
 	if (ibdev->iboe.nb.notifier_call) {
 		if (unregister_netdevice_notifier(&ibdev->iboe.nb))
 			pr_warn("failure unregistering notifier\n");
 		ibdev->iboe.nb.notifier_call = NULL;
 	}
 
+	mlx4_ib_close_sriov(ibdev);
+	mlx4_ib_mad_cleanup(ibdev);
+	ib_unregister_device(&ibdev->ib_dev);
+
 	mlx4_qp_release_range(dev, ibdev->steer_qpn_base,
 			      ibdev->steer_qpn_count);
 	kfree(ibdev->ib_uc_qpns_bitmap);
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 29ca0bb4f561..0a9e49e425a1 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -841,16 +841,18 @@ static int input_default_setkeycode(struct input_dev *dev,
 		}
 	}
 
-	__clear_bit(*old_keycode, dev->keybit);
-	__set_bit(ke->keycode, dev->keybit);
-
-	for (i = 0; i < dev->keycodemax; i++) {
-		if (input_fetch_keycode(dev, i) == *old_keycode) {
-			__set_bit(*old_keycode, dev->keybit);
-			break; /* Setting the bit twice is useless, so break */
+	if (*old_keycode <= KEY_MAX) {
+		__clear_bit(*old_keycode, dev->keybit);
+		for (i = 0; i < dev->keycodemax; i++) {
+			if (input_fetch_keycode(dev, i) == *old_keycode) {
+				__set_bit(*old_keycode, dev->keybit);
+				/* Setting the bit twice is useless, so break */
+				break;
+			}
 		}
 	}
 
+	__set_bit(ke->keycode, dev->keybit);
 	return 0;
 }
 
@@ -906,9 +908,13 @@ int input_set_keycode(struct input_dev *dev,
 	 * Simulate keyup event if keycode is not present
 	 * in the keymap anymore
 	 */
-	if (test_bit(EV_KEY, dev->evbit) &&
-	    !is_event_supported(old_keycode, dev->keybit, KEY_MAX) &&
-	    __test_and_clear_bit(old_keycode, dev->key)) {
+	if (old_keycode > KEY_MAX) {
+		dev_warn(dev->dev.parent ?: &dev->dev,
+			 "%s: got too big old keycode %#x\n",
+			 __func__, old_keycode);
+	} else if (test_bit(EV_KEY, dev->evbit) &&
+		   !is_event_supported(old_keycode, dev->keybit, KEY_MAX) &&
+		   __test_and_clear_bit(old_keycode, dev->key)) {
 		struct input_value vals[] =  {
 			{ EV_KEY, old_keycode, 0 },
 			input_value_sync
diff --git a/drivers/input/misc/keyspan_remote.c b/drivers/input/misc/keyspan_remote.c
index 01f3b5b300f3..7ed630da6b19 100644
--- a/drivers/input/misc/keyspan_remote.c
+++ b/drivers/input/misc/keyspan_remote.c
@@ -344,7 +344,8 @@ static int keyspan_setup(struct usb_device* dev)
 	int retval = 0;
 
 	retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-				 0x11, 0x40, 0x5601, 0x0, NULL, 0, 0);
+				 0x11, 0x40, 0x5601, 0x0, NULL, 0,
+				 USB_CTRL_SET_TIMEOUT);
 	if (retval) {
 		dev_dbg(&dev->dev, "%s - failed to set bit rate due to error: %d\n",
 			__func__, retval);
@@ -352,7 +353,8 @@ static int keyspan_setup(struct usb_device* dev)
 	}
 
 	retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-				 0x44, 0x40, 0x0, 0x0, NULL, 0, 0);
+				 0x44, 0x40, 0x0, 0x0, NULL, 0,
+				 USB_CTRL_SET_TIMEOUT);
 	if (retval) {
 		dev_dbg(&dev->dev, "%s - failed to set resume sensitivity due to error: %d\n",
 			__func__, retval);
@@ -360,7 +362,8 @@ static int keyspan_setup(struct usb_device* dev)
 	}
 
 	retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-				 0x22, 0x40, 0x0, 0x0, NULL, 0, 0);
+				 0x22, 0x40, 0x0, 0x0, NULL, 0,
+				 USB_CTRL_SET_TIMEOUT);
 	if (retval) {
 		dev_dbg(&dev->dev, "%s - failed to turn receive on due to error: %d\n",
 			__func__, retval);
diff --git a/drivers/input/tablet/aiptek.c b/drivers/input/tablet/aiptek.c
index 78ca44840d60..40a166773c1b 100644
--- a/drivers/input/tablet/aiptek.c
+++ b/drivers/input/tablet/aiptek.c
@@ -1820,14 +1820,14 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
 	input_set_abs_params(inputdev, ABS_WHEEL, AIPTEK_WHEEL_MIN, AIPTEK_WHEEL_MAX - 1, 0, 0);
 
 	/* Verify that a device really has an endpoint */
-	if (intf->altsetting[0].desc.bNumEndpoints < 1) {
+	if (intf->cur_altsetting->desc.bNumEndpoints < 1) {
 		dev_err(&intf->dev,
 			"interface has %d endpoints, but must have minimum 1\n",
-			intf->altsetting[0].desc.bNumEndpoints);
+			intf->cur_altsetting->desc.bNumEndpoints);
 		err = -EINVAL;
 		goto fail3;
 	}
-	endpoint = &intf->altsetting[0].endpoint[0].desc;
+	endpoint = &intf->cur_altsetting->endpoint[0].desc;
 
 	/* Go set up our URB, which is called when the tablet receives
 	 * input.
diff --git a/drivers/input/tablet/gtco.c b/drivers/input/tablet/gtco.c
index cf3af3a3297a..a0f69a015e0e 100644
--- a/drivers/input/tablet/gtco.c
+++ b/drivers/input/tablet/gtco.c
@@ -886,18 +886,14 @@ static int gtco_probe(struct usb_interface *usbinterface,
 	}
 
 	/* Sanity check that a device has an endpoint */
-	if (usbinterface->altsetting[0].desc.bNumEndpoints < 1) {
+	if (usbinterface->cur_altsetting->desc.bNumEndpoints < 1) {
 		dev_err(&usbinterface->dev,
 			"Invalid number of endpoints\n");
 		error = -EINVAL;
 		goto err_free_urb;
 	}
 
-	/*
-	 * The endpoint is always altsetting 0, we know this since we know
-	 * this device only has one interrupt endpoint
-	 */
-	endpoint = &usbinterface->altsetting[0].endpoint[0].desc;
+	endpoint = &usbinterface->cur_altsetting->endpoint[0].desc;
 
 	/* Some debug */
 	dev_dbg(&usbinterface->dev, "gtco # interfaces: %d\n", usbinterface->num_altsetting);
@@ -984,7 +980,7 @@ static int gtco_probe(struct usb_interface *usbinterface,
 	input_dev->dev.parent = &usbinterface->dev;
 
 	/* Setup the URB, it will be posted later on open of input device */
-	endpoint = &usbinterface->altsetting[0].endpoint[0].desc;
+	endpoint = &usbinterface->cur_altsetting->endpoint[0].desc;
 
 	usb_fill_int_urb(gtco->urbinfo,
 			 gtco->usbdev,
diff --git a/drivers/input/touchscreen/sur40.c b/drivers/input/touchscreen/sur40.c
index af96ffcbcffd..c218ac6c2745 100644
--- a/drivers/input/touchscreen/sur40.c
+++ b/drivers/input/touchscreen/sur40.c
@@ -357,7 +357,7 @@ static int sur40_probe(struct usb_interface *interface,
 	int error;
 
 	/* Check if we really have the right interface. */
-	iface_desc = &interface->altsetting[0];
+	iface_desc = interface->cur_altsetting;
 	if (iface_desc->desc.bInterfaceClass != 0xFF)
 		return -ENODEV;
 
diff --git a/drivers/isdn/gigaset/usb-gigaset.c b/drivers/isdn/gigaset/usb-gigaset.c
index d0a41cb0cf62..3a6c6bc4a7ae 100644
--- a/drivers/isdn/gigaset/usb-gigaset.c
+++ b/drivers/isdn/gigaset/usb-gigaset.c
@@ -578,8 +578,7 @@ static int gigaset_initcshw(struct cardstate *cs)
 {
 	struct usb_cardstate *ucs;
 
-	cs->hw.usb = ucs =
-		kmalloc(sizeof(struct usb_cardstate), GFP_KERNEL);
+	cs->hw.usb = ucs = kzalloc(sizeof(struct usb_cardstate), GFP_KERNEL);
 	if (!ucs) {
 		pr_err("out of memory\n");
 		return -ENOMEM;
@@ -591,9 +590,6 @@ static int gigaset_initcshw(struct cardstate *cs)
 	ucs->bchars[3] = 0;
 	ucs->bchars[4] = 0x11;
 	ucs->bchars[5] = 0x13;
-	ucs->bulk_out_buffer = NULL;
-	ucs->bulk_out_urb = NULL;
-	ucs->read_urb = NULL;
 	tasklet_init(&cs->write_tasklet,
 		     gigaset_modem_fill, (unsigned long) cs);
 
@@ -693,6 +689,11 @@ static int gigaset_probe(struct usb_interface *interface,
 		return -ENODEV;
 	}
 
+	if (hostif->desc.bNumEndpoints < 2) {
+		dev_err(&interface->dev, "missing endpoints\n");
+		return -ENODEV;
+	}
+
 	dev_info(&udev->dev, "%s: Device matched ... !\n", __func__);
 
 	/* allocate memory for our device state and initialize it */
@@ -712,6 +713,12 @@ static int gigaset_probe(struct usb_interface *interface,
 
 	endpoint = &hostif->endpoint[0].desc;
 
+	if (!usb_endpoint_is_bulk_out(endpoint)) {
+		dev_err(&interface->dev, "missing bulk-out endpoint\n");
+		retval = -ENODEV;
+		goto error;
+	}
+
 	buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
 	ucs->bulk_out_size = buffer_size;
 	ucs->bulk_out_endpointAddr = endpoint->bEndpointAddress;
@@ -731,6 +738,12 @@ static int gigaset_probe(struct usb_interface *interface,
 
 	endpoint = &hostif->endpoint[1].desc;
 
+	if (!usb_endpoint_is_int_in(endpoint)) {
+		dev_err(&interface->dev, "missing int-in endpoint\n");
+		retval = -ENODEV;
+		goto error;
+	}
+
 	ucs->busy = 0;
 
 	ucs->read_urb = usb_alloc_urb(0, GFP_KERNEL);
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index dfab51ff09ea..284871a103f8 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -1762,11 +1762,13 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 	}
 	cc->iv_offset = tmpll;
 
-	if (dm_get_device(ti, argv[3], dm_table_get_mode(ti->table), &cc->dev)) {
+	ret = dm_get_device(ti, argv[3], dm_table_get_mode(ti->table), &cc->dev);
+	if (ret) {
 		ti->error = "Device lookup failed";
 		goto bad;
 	}
 
+	ret = -EINVAL;
 	if (sscanf(argv[4], "%llu%c", &tmpll, &dummy) != 1) {
 		ti->error = "Invalid device sector";
 		goto bad;
diff --git a/drivers/md/dm-delay.c b/drivers/md/dm-delay.c
index 42c3a27a14cc..7e194aa14634 100644
--- a/drivers/md/dm-delay.c
+++ b/drivers/md/dm-delay.c
@@ -129,6 +129,7 @@ static int delay_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 	struct delay_c *dc;
 	unsigned long long tmpll;
 	char dummy;
+	int ret;
 
 	if (argc != 3 && argc != 6) {
 		ti->error = "requires exactly 3 or 6 arguments";
@@ -143,6 +144,7 @@ static int delay_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 
 	dc->reads = dc->writes = 0;
 
+	ret = -EINVAL;
 	if (sscanf(argv[1], "%llu%c", &tmpll, &dummy) != 1) {
 		ti->error = "Invalid device sector";
 		goto bad;
@@ -154,12 +156,14 @@ static int delay_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 		goto bad;
 	}
 
-	if (dm_get_device(ti, argv[0], dm_table_get_mode(ti->table),
-			  &dc->dev_read)) {
+	ret = dm_get_device(ti, argv[0], dm_table_get_mode(ti->table),
+			    &dc->dev_read);
+	if (ret) {
 		ti->error = "Device lookup failed";
 		goto bad;
 	}
 
+	ret = -EINVAL;
 	dc->dev_write = NULL;
 	if (argc == 3)
 		goto out;
@@ -175,13 +179,15 @@ static int delay_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 		goto bad_dev_read;
 	}
 
-	if (dm_get_device(ti, argv[3], dm_table_get_mode(ti->table),
-			  &dc->dev_write)) {
+	ret = dm_get_device(ti, argv[3], dm_table_get_mode(ti->table),
+			    &dc->dev_write);
+	if (ret) {
 		ti->error = "Write device lookup failed";
 		goto bad_dev_read;
 	}
 
 out:
+	ret = -EINVAL;
 	dc->kdelayd_wq = alloc_workqueue("kdelayd", WQ_MEM_RECLAIM, 0);
 	if (!dc->kdelayd_wq) {
 		DMERR("Couldn't start kdelayd");
@@ -208,7 +214,7 @@ static int delay_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 	dm_put_device(ti, dc->dev_read);
 bad:
 	kfree(dc);
-	return -EINVAL;
+	return ret;
 }
 
 static void delay_dtr(struct dm_target *ti)
diff --git a/drivers/md/dm-flakey.c b/drivers/md/dm-flakey.c
index 0f5e1820c92d..8809c5e6f6ac 100644
--- a/drivers/md/dm-flakey.c
+++ b/drivers/md/dm-flakey.c
@@ -69,6 +69,11 @@ static int parse_features(struct dm_arg_set *as, struct flakey_c *fc,
 		arg_name = dm_shift_arg(as);
 		argc--;
 
+		if (!arg_name) {
+			ti->error = "Insufficient feature arguments";
+			return -EINVAL;
+		}
+
 		/*
 		 * drop_writes
 		 */
@@ -183,6 +188,7 @@ static int flakey_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 
 	devname = dm_shift_arg(&as);
 
+	r = -EINVAL;
 	if (sscanf(dm_shift_arg(&as), "%llu%c", &tmpll, &dummy) != 1) {
 		ti->error = "Invalid device sector";
 		goto bad;
@@ -199,11 +205,13 @@ static int flakey_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 
 	if (!(fc->up_interval + fc->down_interval)) {
 		ti->error = "Total (up + down) interval is zero";
+		r = -EINVAL;
 		goto bad;
 	}
 
 	if (fc->up_interval + fc->down_interval < fc->up_interval) {
 		ti->error = "Interval overflow";
+		r = -EINVAL;
 		goto bad;
 	}
 
@@ -211,7 +219,8 @@ static int flakey_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 	if (r)
 		goto bad;
 
-	if (dm_get_device(ti, devname, dm_table_get_mode(ti->table), &fc->dev)) {
+	r = dm_get_device(ti, devname, dm_table_get_mode(ti->table), &fc->dev);
+	if (r) {
 		ti->error = "Device lookup failed";
 		goto bad;
 	}
@@ -224,7 +233,7 @@ static int flakey_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 
 bad:
 	kfree(fc);
-	return -EINVAL;
+	return r;
 }
 
 static void flakey_dtr(struct dm_target *ti)
@@ -287,15 +296,13 @@ static int flakey_map(struct dm_target *ti, struct bio *bio)
 		pb->bio_submitted = true;
 
 		/*
-		 * Map reads as normal only if corrupt_bio_byte set.
+		 * Error reads if neither corrupt_bio_byte or drop_writes are set.
+		 * Otherwise, flakey_end_io() will decide if the reads should be modified.
 		 */
 		if (bio_data_dir(bio) == READ) {
-			/* If flags were specified, only corrupt those that match. */
-			if (fc->corrupt_bio_byte && (fc->corrupt_bio_rw == READ) &&
-			    all_corrupt_bio_flags_match(bio, fc))
-				goto map_bio;
-			else
+			if (!fc->corrupt_bio_byte && !test_bit(DROP_WRITES, &fc->flags))
 				return -EIO;
+			goto map_bio;
 		}
 
 		/*
@@ -332,14 +339,21 @@ static int flakey_end_io(struct dm_target *ti, struct bio *bio, int error)
 	struct flakey_c *fc = ti->private;
 	struct per_bio_data *pb = dm_per_bio_data(bio, sizeof(struct per_bio_data));
 
-	/*
-	 * Corrupt successful READs while in down state.
-	 */
 	if (!error && pb->bio_submitted && (bio_data_dir(bio) == READ)) {
-		if (fc->corrupt_bio_byte)
+		if (fc->corrupt_bio_byte && (fc->corrupt_bio_rw == READ) &&
+		    all_corrupt_bio_flags_match(bio, fc)) {
+			/*
+			 * Corrupt successful matching READs while in down state.
+			 */
 			corrupt_bio_data(bio, fc);
-		else
+
+		} else if (!test_bit(DROP_WRITES, &fc->flags)) {
+			/*
+			 * Error read during the down_interval if drop_writes
+			 * wasn't configured.
+			 */
 			return -EIO;
+		}
 	}
 
 	return error;
diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c
index 53e848c10939..62c26e4ad6ac 100644
--- a/drivers/md/dm-linear.c
+++ b/drivers/md/dm-linear.c
@@ -30,6 +30,7 @@ static int linear_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 	struct linear_c *lc;
 	unsigned long long tmp;
 	char dummy;
+	int ret;
 
 	if (argc != 2) {
 		ti->error = "Invalid argument count";
@@ -42,13 +43,15 @@ static int linear_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 		return -ENOMEM;
 	}
 
+	ret = -EINVAL;
 	if (sscanf(argv[1], "%llu%c", &tmp, &dummy) != 1) {
 		ti->error = "dm-linear: Invalid device sector";
 		goto bad;
 	}
 	lc->start = tmp;
 
-	if (dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), &lc->dev)) {
+	ret = dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), &lc->dev);
+	if (ret) {
 		ti->error = "dm-linear: Device lookup failed";
 		goto bad;
 	}
@@ -61,7 +64,7 @@ static int linear_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 
       bad:
 	kfree(lc);
-	return -EINVAL;
+	return ret;
 }
 
 static void linear_dtr(struct dm_target *ti)
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index 089d62751f7f..3a477f97952a 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -923,16 +923,18 @@ static int get_mirror(struct mirror_set *ms, struct dm_target *ti,
 {
 	unsigned long long offset;
 	char dummy;
+	int ret;
 
 	if (sscanf(argv[1], "%llu%c", &offset, &dummy) != 1) {
 		ti->error = "Invalid offset";
 		return -EINVAL;
 	}
 
-	if (dm_get_device(ti, argv[0], dm_table_get_mode(ti->table),
-			  &ms->mirror[mirror].dev)) {
+	ret = dm_get_device(ti, argv[0], dm_table_get_mode(ti->table),
+			    &ms->mirror[mirror].dev);
+	if (ret) {
 		ti->error = "Device lookup failure";
-		return -ENXIO;
+		return ret;
 	}
 
 	ms->mirror[mirror].ms = ms;
diff --git a/drivers/md/dm-snap-persistent.c b/drivers/md/dm-snap-persistent.c
index d3272acc0f0e..2d6a12bd3b28 100644
--- a/drivers/md/dm-snap-persistent.c
+++ b/drivers/md/dm-snap-persistent.c
@@ -16,7 +16,7 @@
 #include "dm-bufio.h"
 
 #define DM_MSG_PREFIX "persistent snapshot"
-#define DM_CHUNK_SIZE_DEFAULT_SECTORS 32	/* 16KB */
+#define DM_CHUNK_SIZE_DEFAULT_SECTORS 32U	/* 16KB */
 
 #define DM_PREFETCH_CHUNKS		12
 
diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c
index d1600d2aa2e2..e7b07b1282d8 100644
--- a/drivers/md/dm-stripe.c
+++ b/drivers/md/dm-stripe.c
@@ -75,13 +75,15 @@ static int get_stripe(struct dm_target *ti, struct stripe_c *sc,
 {
 	unsigned long long start;
 	char dummy;
+	int ret;
 
 	if (sscanf(argv[1], "%llu%c", &start, &dummy) != 1)
 		return -EINVAL;
 
-	if (dm_get_device(ti, argv[0], dm_table_get_mode(ti->table),
-			  &sc->stripe[stripe].dev))
-		return -ENXIO;
+	ret = dm_get_device(ti, argv[0], dm_table_get_mode(ti->table),
+			    &sc->stripe[stripe].dev);
+	if (ret)
+		return ret;
 
 	sc->stripe[stripe].physical_start = start;
 
diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c
index e6f64c472d5e..da54c8172df0 100644
--- a/drivers/md/dm-thin-metadata.c
+++ b/drivers/md/dm-thin-metadata.c
@@ -197,6 +197,15 @@ struct dm_pool_metadata {
 	 */
 	bool fail_io:1;
 
+	/*
+	 * Pre-commit callback.
+	 *
+	 * This allows the thin provisioning target to run a callback before
+	 * the metadata are committed.
+	 */
+	dm_pool_pre_commit_fn pre_commit_fn;
+	void *pre_commit_context;
+
 	/*
 	 * Reading the space map roots can fail, so we read it into these
 	 * buffers before the superblock is locked and updated.
@@ -784,6 +793,14 @@ static int __commit_transaction(struct dm_pool_metadata *pmd)
 	 */
 	BUILD_BUG_ON(sizeof(struct thin_disk_superblock) > 512);
 
+	if (pmd->pre_commit_fn) {
+		r = pmd->pre_commit_fn(pmd->pre_commit_context);
+		if (r < 0) {
+			DMERR("pre-commit callback failed");
+			return r;
+		}
+	}
+
 	r = __write_changed_details(pmd);
 	if (r < 0)
 		return r;
@@ -844,6 +861,8 @@ struct dm_pool_metadata *dm_pool_metadata_open(struct block_device *bdev,
 	pmd->fail_io = false;
 	pmd->bdev = bdev;
 	pmd->data_block_size = data_block_size;
+	pmd->pre_commit_fn = NULL;
+	pmd->pre_commit_context = NULL;
 
 	r = __create_persistent_data_objects(pmd, format_device);
 	if (r) {
@@ -1789,6 +1808,16 @@ int dm_pool_register_metadata_threshold(struct dm_pool_metadata *pmd,
 	return r;
 }
 
+void dm_pool_register_pre_commit_callback(struct dm_pool_metadata *pmd,
+					  dm_pool_pre_commit_fn fn,
+					  void *context)
+{
+	down_write(&pmd->root_lock);
+	pmd->pre_commit_fn = fn;
+	pmd->pre_commit_context = context;
+	up_write(&pmd->root_lock);
+}
+
 int dm_pool_metadata_set_needs_check(struct dm_pool_metadata *pmd)
 {
 	int r;
diff --git a/drivers/md/dm-thin-metadata.h b/drivers/md/dm-thin-metadata.h
index e3c857db195a..9859dd9fb921 100644
--- a/drivers/md/dm-thin-metadata.h
+++ b/drivers/md/dm-thin-metadata.h
@@ -213,6 +213,13 @@ int dm_pool_register_metadata_threshold(struct dm_pool_metadata *pmd,
 int dm_pool_metadata_set_needs_check(struct dm_pool_metadata *pmd);
 bool dm_pool_metadata_needs_check(struct dm_pool_metadata *pmd);
 
+/* Pre-commit callback */
+typedef int (*dm_pool_pre_commit_fn)(void *context);
+
+void dm_pool_register_pre_commit_callback(struct dm_pool_metadata *pmd,
+					  dm_pool_pre_commit_fn fn,
+					  void *context);
+
 /*----------------------------------------------------------------*/
 
 #endif
diff --git a/drivers/md/persistent-data/dm-btree-remove.c b/drivers/md/persistent-data/dm-btree-remove.c
index 92cd09f3c69b..d9fb3490da5d 100644
--- a/drivers/md/persistent-data/dm-btree-remove.c
+++ b/drivers/md/persistent-data/dm-btree-remove.c
@@ -203,7 +203,13 @@ static void __rebalance2(struct dm_btree_info *info, struct btree_node *parent,
 	struct btree_node *right = r->n;
 	uint32_t nr_left = le32_to_cpu(left->header.nr_entries);
 	uint32_t nr_right = le32_to_cpu(right->header.nr_entries);
-	unsigned threshold = 2 * merge_threshold(left) + 1;
+	/*
+	 * Ensure the number of entries in each child will be greater
+	 * than or equal to (max_entries / 3 + 1), so no matter which
+	 * child is used for removal, the number will still be not
+	 * less than (max_entries / 3).
+	 */
+	unsigned int threshold = 2 * (merge_threshold(left) + 1);
 
 	if (nr_left + nr_right < threshold) {
 		/*
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index 8f7dfc58f965..61165e528a5e 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -88,7 +88,7 @@ static int create_strip_zones(struct mddev *mddev, struct r0conf **private_conf)
 	char b[BDEVNAME_SIZE];
 	char b2[BDEVNAME_SIZE];
 	struct r0conf *conf = kzalloc(sizeof(*conf), GFP_KERNEL);
-	unsigned short blksize = 512;
+	unsigned blksize = 512;
 
 	if (!conf)
 		return -ENOMEM;
diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
index 73a432934bd8..2a489e6debc0 100644
--- a/drivers/media/media-device.c
+++ b/drivers/media/media-device.c
@@ -24,6 +24,7 @@
 #include <linux/export.h>
 #include <linux/ioctl.h>
 #include <linux/media.h>
+#include <linux/slab.h>
 #include <linux/types.h>
 
 #include <media/media-device.h>
@@ -236,7 +237,7 @@ static long media_device_ioctl(struct file *filp, unsigned int cmd,
 			       unsigned long arg)
 {
 	struct media_devnode *devnode = media_devnode_data(filp);
-	struct media_device *dev = to_media_device(devnode);
+	struct media_device *dev = devnode->media_dev;
 	long ret;
 
 	switch (cmd) {
@@ -305,7 +306,7 @@ static long media_device_compat_ioctl(struct file *filp, unsigned int cmd,
 				      unsigned long arg)
 {
 	struct media_devnode *devnode = media_devnode_data(filp);
-	struct media_device *dev = to_media_device(devnode);
+	struct media_device *dev = devnode->media_dev;
 	long ret;
 
 	switch (cmd) {
@@ -346,7 +347,8 @@ static const struct media_file_operations media_device_fops = {
 static ssize_t show_model(struct device *cd,
 			  struct device_attribute *attr, char *buf)
 {
-	struct media_device *mdev = to_media_device(to_media_devnode(cd));
+	struct media_devnode *devnode = to_media_devnode(cd);
+	struct media_device *mdev = devnode->media_dev;
 
 	return sprintf(buf, "%.*s\n", (int)sizeof(mdev->model), mdev->model);
 }
@@ -374,6 +376,7 @@ static void media_device_release(struct media_devnode *mdev)
 int __must_check __media_device_register(struct media_device *mdev,
 					 struct module *owner)
 {
+	struct media_devnode *devnode;
 	int ret;
 
 	if (WARN_ON(mdev->dev == NULL || mdev->model[0] == 0))
@@ -384,17 +387,28 @@ int __must_check __media_device_register(struct media_device *mdev,
 	spin_lock_init(&mdev->lock);
 	mutex_init(&mdev->graph_mutex);
 
+	devnode = kzalloc(sizeof(*devnode), GFP_KERNEL);
+	if (!devnode)
+		return -ENOMEM;
+
 	/* Register the device node. */
-	mdev->devnode.fops = &media_device_fops;
-	mdev->devnode.parent = mdev->dev;
-	mdev->devnode.release = media_device_release;
-	ret = media_devnode_register(&mdev->devnode, owner);
-	if (ret < 0)
+	mdev->devnode = devnode;
+	devnode->fops = &media_device_fops;
+	devnode->parent = mdev->dev;
+	devnode->release = media_device_release;
+	ret = media_devnode_register(mdev, devnode, owner);
+	if (ret < 0) {
+		/* devnode free is handled in media_devnode_*() */
+		mdev->devnode = NULL;
 		return ret;
+	}
 
-	ret = device_create_file(&mdev->devnode.dev, &dev_attr_model);
+	ret = device_create_file(&devnode->dev, &dev_attr_model);
 	if (ret < 0) {
-		media_devnode_unregister(&mdev->devnode);
+		/* devnode free is handled in media_devnode_*() */
+		mdev->devnode = NULL;
+		media_devnode_unregister_prepare(devnode);
+		media_devnode_unregister(devnode);
 		return ret;
 	}
 
@@ -412,11 +426,16 @@ void media_device_unregister(struct media_device *mdev)
 	struct media_entity *entity;
 	struct media_entity *next;
 
+	/* Clear the devnode register bit to avoid races with media dev open */
+	media_devnode_unregister_prepare(mdev->devnode);
+
 	list_for_each_entry_safe(entity, next, &mdev->entities, list)
 		media_device_unregister_entity(entity);
 
-	device_remove_file(&mdev->devnode.dev, &dev_attr_model);
-	media_devnode_unregister(&mdev->devnode);
+	device_remove_file(&mdev->devnode->dev, &dev_attr_model);
+	media_devnode_unregister(mdev->devnode);
+	/* devnode free is handled in media_devnode_*() */
+	mdev->devnode = NULL;
 }
 EXPORT_SYMBOL_GPL(media_device_unregister);
 
diff --git a/drivers/media/media-devnode.c b/drivers/media/media-devnode.c
index 7acd19c881de..e887120d19aa 100644
--- a/drivers/media/media-devnode.c
+++ b/drivers/media/media-devnode.c
@@ -44,6 +44,7 @@
 #include <linux/uaccess.h>
 
 #include <media/media-devnode.h>
+#include <media/media-device.h>
 
 #define MEDIA_NUM_DEVICES	256
 #define MEDIA_NAME		"media"
@@ -59,21 +60,19 @@ static DECLARE_BITMAP(media_devnode_nums, MEDIA_NUM_DEVICES);
 /* Called when the last user of the media device exits. */
 static void media_devnode_release(struct device *cd)
 {
-	struct media_devnode *mdev = to_media_devnode(cd);
+	struct media_devnode *devnode = to_media_devnode(cd);
 
 	mutex_lock(&media_devnode_lock);
-
-	/* Delete the cdev on this minor as well */
-	cdev_del(&mdev->cdev);
-
 	/* Mark device node number as free */
-	clear_bit(mdev->minor, media_devnode_nums);
-
+	clear_bit(devnode->minor, media_devnode_nums);
 	mutex_unlock(&media_devnode_lock);
 
 	/* Release media_devnode and perform other cleanups as needed. */
-	if (mdev->release)
-		mdev->release(mdev);
+	if (devnode->release)
+		devnode->release(devnode);
+
+	kfree(devnode);
+	pr_debug("%s: Media Devnode Deallocated\n", __func__);
 }
 
 static struct bus_type media_bus_type = {
@@ -83,37 +82,37 @@ static struct bus_type media_bus_type = {
 static ssize_t media_read(struct file *filp, char __user *buf,
 		size_t sz, loff_t *off)
 {
-	struct media_devnode *mdev = media_devnode_data(filp);
+	struct media_devnode *devnode = media_devnode_data(filp);
 
-	if (!mdev->fops->read)
+	if (!devnode->fops->read)
 		return -EINVAL;
-	if (!media_devnode_is_registered(mdev))
+	if (!media_devnode_is_registered(devnode))
 		return -EIO;
-	return mdev->fops->read(filp, buf, sz, off);
+	return devnode->fops->read(filp, buf, sz, off);
 }
 
 static ssize_t media_write(struct file *filp, const char __user *buf,
 		size_t sz, loff_t *off)
 {
-	struct media_devnode *mdev = media_devnode_data(filp);
+	struct media_devnode *devnode = media_devnode_data(filp);
 
-	if (!mdev->fops->write)
+	if (!devnode->fops->write)
 		return -EINVAL;
-	if (!media_devnode_is_registered(mdev))
+	if (!media_devnode_is_registered(devnode))
 		return -EIO;
-	return mdev->fops->write(filp, buf, sz, off);
+	return devnode->fops->write(filp, buf, sz, off);
 }
 
 static unsigned int media_poll(struct file *filp,
 			       struct poll_table_struct *poll)
 {
-	struct media_devnode *mdev = media_devnode_data(filp);
+	struct media_devnode *devnode = media_devnode_data(filp);
 
-	if (!media_devnode_is_registered(mdev))
+	if (!media_devnode_is_registered(devnode))
 		return POLLERR | POLLHUP;
-	if (!mdev->fops->poll)
+	if (!devnode->fops->poll)
 		return DEFAULT_POLLMASK;
-	return mdev->fops->poll(filp, poll);
+	return devnode->fops->poll(filp, poll);
 }
 
 static long
@@ -121,12 +120,12 @@ __media_ioctl(struct file *filp, unsigned int cmd, unsigned long arg,
 	      long (*ioctl_func)(struct file *filp, unsigned int cmd,
 				 unsigned long arg))
 {
-	struct media_devnode *mdev = media_devnode_data(filp);
+	struct media_devnode *devnode = media_devnode_data(filp);
 
 	if (!ioctl_func)
 		return -ENOTTY;
 
-	if (!media_devnode_is_registered(mdev))
+	if (!media_devnode_is_registered(devnode))
 		return -EIO;
 
 	return ioctl_func(filp, cmd, arg);
@@ -134,9 +133,9 @@ __media_ioctl(struct file *filp, unsigned int cmd, unsigned long arg,
 
 static long media_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
-	struct media_devnode *mdev = media_devnode_data(filp);
+	struct media_devnode *devnode = media_devnode_data(filp);
 
-	return __media_ioctl(filp, cmd, arg, mdev->fops->ioctl);
+	return __media_ioctl(filp, cmd, arg, devnode->fops->ioctl);
 }
 
 #ifdef CONFIG_COMPAT
@@ -144,9 +143,9 @@ static long media_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 static long media_compat_ioctl(struct file *filp, unsigned int cmd,
 			       unsigned long arg)
 {
-	struct media_devnode *mdev = media_devnode_data(filp);
+	struct media_devnode *devnode = media_devnode_data(filp);
 
-	return __media_ioctl(filp, cmd, arg, mdev->fops->compat_ioctl);
+	return __media_ioctl(filp, cmd, arg, devnode->fops->compat_ioctl);
 }
 
 #endif /* CONFIG_COMPAT */
@@ -154,7 +153,7 @@ static long media_compat_ioctl(struct file *filp, unsigned int cmd,
 /* Override for the open function */
 static int media_open(struct inode *inode, struct file *filp)
 {
-	struct media_devnode *mdev;
+	struct media_devnode *devnode;
 	int ret;
 
 	/* Check if the media device is available. This needs to be done with
@@ -164,23 +163,24 @@ static int media_open(struct inode *inode, struct file *filp)
 	 * a crash.
 	 */
 	mutex_lock(&media_devnode_lock);
-	mdev = container_of(inode->i_cdev, struct media_devnode, cdev);
+	devnode = container_of(inode->i_cdev, struct media_devnode, cdev);
 	/* return ENXIO if the media device has been removed
 	   already or if it is not registered anymore. */
-	if (!media_devnode_is_registered(mdev)) {
+	if (!media_devnode_is_registered(devnode)) {
 		mutex_unlock(&media_devnode_lock);
 		return -ENXIO;
 	}
 	/* and increase the device refcount */
-	get_device(&mdev->dev);
+	get_device(&devnode->dev);
 	mutex_unlock(&media_devnode_lock);
 
-	filp->private_data = mdev;
+	filp->private_data = devnode;
 
-	if (mdev->fops->open) {
-		ret = mdev->fops->open(filp);
+	if (devnode->fops->open) {
+		ret = devnode->fops->open(filp);
 		if (ret) {
-			put_device(&mdev->dev);
+			put_device(&devnode->dev);
+			filp->private_data = NULL;
 			return ret;
 		}
 	}
@@ -191,17 +191,19 @@ static int media_open(struct inode *inode, struct file *filp)
 /* Override for the release function */
 static int media_release(struct inode *inode, struct file *filp)
 {
-	struct media_devnode *mdev = media_devnode_data(filp);
-	int ret = 0;
+	struct media_devnode *devnode = media_devnode_data(filp);
+
+	if (devnode->fops->release)
+		devnode->fops->release(filp);
 
-	if (mdev->fops->release)
-		mdev->fops->release(filp);
+	filp->private_data = NULL;
 
 	/* decrease the refcount unconditionally since the release()
 	   return value is ignored. */
-	put_device(&mdev->dev);
-	filp->private_data = NULL;
-	return ret;
+	put_device(&devnode->dev);
+
+	pr_debug("%s: Media Release\n", __func__);
+	return 0;
 }
 
 static const struct file_operations media_devnode_fops = {
@@ -220,7 +222,8 @@ static const struct file_operations media_devnode_fops = {
 
 /**
  * media_devnode_register - register a media device node
- * @mdev: media device node structure we want to register
+ * @media_dev: struct media_device we want to register a device node
+ * @devnode: media device node structure we want to register
  *
  * The registration code assigns minor numbers and registers the new device node
  * with the kernel. An error is returned if no free minor number can be found,
@@ -232,7 +235,8 @@ static const struct file_operations media_devnode_fops = {
  * the media_devnode structure is *not* called, so the caller is responsible for
  * freeing any data.
  */
-int __must_check media_devnode_register(struct media_devnode *mdev,
+int __must_check media_devnode_register(struct media_device *mdev,
+					struct media_devnode *devnode,
 					struct module *owner)
 {
 	int minor;
@@ -244,68 +248,89 @@ int __must_check media_devnode_register(struct media_devnode *mdev,
 	if (minor == MEDIA_NUM_DEVICES) {
 		mutex_unlock(&media_devnode_lock);
 		pr_err("could not get a free minor\n");
+		kfree(devnode);
 		return -ENFILE;
 	}
 
 	set_bit(minor, media_devnode_nums);
 	mutex_unlock(&media_devnode_lock);
 
-	mdev->minor = minor;
+	devnode->minor = minor;
+	devnode->media_dev = mdev;
+
+	/* Part 1: Initialize dev now to use dev.kobj for cdev.kobj.parent */
+	devnode->dev.bus = &media_bus_type;
+	devnode->dev.devt = MKDEV(MAJOR(media_dev_t), devnode->minor);
+	devnode->dev.release = media_devnode_release;
+	if (devnode->parent)
+		devnode->dev.parent = devnode->parent;
+	dev_set_name(&devnode->dev, "media%d", devnode->minor);
+	device_initialize(&devnode->dev);
 
 	/* Part 2: Initialize and register the character device */
-	cdev_init(&mdev->cdev, &media_devnode_fops);
-	mdev->cdev.owner = owner;
+	cdev_init(&devnode->cdev, &media_devnode_fops);
+	devnode->cdev.owner = owner;
+	devnode->cdev.kobj.parent = &devnode->dev.kobj;
 
-	ret = cdev_add(&mdev->cdev, MKDEV(MAJOR(media_dev_t), mdev->minor), 1);
+	ret = cdev_add(&devnode->cdev, MKDEV(MAJOR(media_dev_t), devnode->minor), 1);
 	if (ret < 0) {
 		pr_err("%s: cdev_add failed\n", __func__);
-		goto error;
+		goto cdev_add_error;
 	}
 
-	/* Part 3: Register the media device */
-	mdev->dev.bus = &media_bus_type;
-	mdev->dev.devt = MKDEV(MAJOR(media_dev_t), mdev->minor);
-	mdev->dev.release = media_devnode_release;
-	if (mdev->parent)
-		mdev->dev.parent = mdev->parent;
-	dev_set_name(&mdev->dev, "media%d", mdev->minor);
-	ret = device_register(&mdev->dev);
+	/* Part 3: Add the media device */
+	ret = device_add(&devnode->dev);
 	if (ret < 0) {
-		pr_err("%s: device_register failed\n", __func__);
-		goto error;
+		pr_err("%s: device_add failed\n", __func__);
+		goto device_add_error;
 	}
 
 	/* Part 4: Activate this minor. The char device can now be used. */
-	set_bit(MEDIA_FLAG_REGISTERED, &mdev->flags);
+	set_bit(MEDIA_FLAG_REGISTERED, &devnode->flags);
 
 	return 0;
 
-error:
-	cdev_del(&mdev->cdev);
-	clear_bit(mdev->minor, media_devnode_nums);
+device_add_error:
+	cdev_del(&devnode->cdev);
+cdev_add_error:
+	mutex_lock(&media_devnode_lock);
+	clear_bit(devnode->minor, media_devnode_nums);
+	devnode->media_dev = NULL;
+	mutex_unlock(&media_devnode_lock);
+
+	put_device(&devnode->dev);
 	return ret;
 }
 
+void media_devnode_unregister_prepare(struct media_devnode *devnode)
+{
+	/* Check if devnode was ever registered at all */
+	if (!media_devnode_is_registered(devnode))
+		return;
+
+	mutex_lock(&media_devnode_lock);
+	clear_bit(MEDIA_FLAG_REGISTERED, &devnode->flags);
+	mutex_unlock(&media_devnode_lock);
+}
+
 /**
  * media_devnode_unregister - unregister a media device node
- * @mdev: the device node to unregister
+ * @devnode: the device node to unregister
  *
  * This unregisters the passed device. Future open calls will be met with
  * errors.
  *
- * This function can safely be called if the device node has never been
- * registered or has already been unregistered.
+ * Should be called after media_devnode_unregister_prepare()
  */
-void media_devnode_unregister(struct media_devnode *mdev)
+void media_devnode_unregister(struct media_devnode *devnode)
 {
-	/* Check if mdev was ever registered at all */
-	if (!media_devnode_is_registered(mdev))
-		return;
-
 	mutex_lock(&media_devnode_lock);
-	clear_bit(MEDIA_FLAG_REGISTERED, &mdev->flags);
+	/* Delete the cdev on this minor as well */
+	cdev_del(&devnode->cdev);
 	mutex_unlock(&media_devnode_lock);
-	device_unregister(&mdev->dev);
+	device_del(&devnode->dev);
+	devnode->media_dev = NULL;
+	put_device(&devnode->dev);
 }
 
 /*
diff --git a/drivers/media/usb/gspca/ov519.c b/drivers/media/usb/gspca/ov519.c
index c95f32a0c02b..6acb2132aedc 100644
--- a/drivers/media/usb/gspca/ov519.c
+++ b/drivers/media/usb/gspca/ov519.c
@@ -3497,6 +3497,11 @@ static void ov511_mode_init_regs(struct sd *sd)
 		return;
 	}
 
+	if (alt->desc.bNumEndpoints < 1) {
+		sd->gspca_dev.usb_err = -ENODEV;
+		return;
+	}
+
 	packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
 	reg_w(sd, R51x_FIFO_PSIZE, packet_size >> 5);
 
@@ -3622,6 +3627,11 @@ static void ov518_mode_init_regs(struct sd *sd)
 		return;
 	}
 
+	if (alt->desc.bNumEndpoints < 1) {
+		sd->gspca_dev.usb_err = -ENODEV;
+		return;
+	}
+
 	packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
 	ov518_reg_w32(sd, R51x_FIFO_PSIZE, packet_size & ~7, 2);
 
diff --git a/drivers/media/usb/gspca/stv06xx/stv06xx.c b/drivers/media/usb/gspca/stv06xx/stv06xx.c
index 49d209bbf9ee..66a007203b78 100644
--- a/drivers/media/usb/gspca/stv06xx/stv06xx.c
+++ b/drivers/media/usb/gspca/stv06xx/stv06xx.c
@@ -293,6 +293,9 @@ static int stv06xx_start(struct gspca_dev *gspca_dev)
 		return -EIO;
 	}
 
+	if (alt->desc.bNumEndpoints < 1)
+		return -ENODEV;
+
 	packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
 	err = stv06xx_write_bridge(sd, STV_ISO_SIZE_L, packet_size);
 	if (err < 0)
@@ -317,11 +320,21 @@ static int stv06xx_start(struct gspca_dev *gspca_dev)
 
 static int stv06xx_isoc_init(struct gspca_dev *gspca_dev)
 {
+	struct usb_interface_cache *intfc;
 	struct usb_host_interface *alt;
 	struct sd *sd = (struct sd *) gspca_dev;
 
+	intfc = gspca_dev->dev->actconfig->intf_cache[0];
+
+	if (intfc->num_altsetting < 2)
+		return -ENODEV;
+
+	alt = &intfc->altsetting[1];
+
+	if (alt->desc.bNumEndpoints < 1)
+		return -ENODEV;
+
 	/* Start isoc bandwidth "negotiation" at max isoc bandwidth */
-	alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1];
 	alt->endpoint[0].desc.wMaxPacketSize =
 		cpu_to_le16(sd->sensor->max_packet_size[gspca_dev->curr_mode]);
 
@@ -334,6 +347,10 @@ static int stv06xx_isoc_nego(struct gspca_dev *gspca_dev)
 	struct usb_host_interface *alt;
 	struct sd *sd = (struct sd *) gspca_dev;
 
+	/*
+	 * Existence of altsetting and endpoint was verified in
+	 * stv06xx_isoc_init()
+	 */
 	alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1];
 	packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
 	min_packet_size = sd->sensor->min_packet_size[gspca_dev->curr_mode];
diff --git a/drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c b/drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c
index 8d785edcccf2..cc88c059b8d7 100644
--- a/drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c
+++ b/drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c
@@ -198,6 +198,10 @@ static int pb0100_start(struct sd *sd)
 	alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
 	if (!alt)
 		return -ENODEV;
+
+	if (alt->desc.bNumEndpoints < 1)
+		return -ENODEV;
+
 	packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
 
 	/* If we don't have enough bandwidth use a lower framerate */
diff --git a/drivers/media/usb/gspca/xirlink_cit.c b/drivers/media/usb/gspca/xirlink_cit.c
index a41aa7817c54..b05c27e847e4 100644
--- a/drivers/media/usb/gspca/xirlink_cit.c
+++ b/drivers/media/usb/gspca/xirlink_cit.c
@@ -1455,6 +1455,9 @@ static int cit_get_packet_size(struct gspca_dev *gspca_dev)
 		return -EIO;
 	}
 
+	if (alt->desc.bNumEndpoints < 1)
+		return -ENODEV;
+
 	return le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
 }
 
@@ -2632,6 +2635,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
 
 static int sd_isoc_init(struct gspca_dev *gspca_dev)
 {
+	struct usb_interface_cache *intfc;
 	struct usb_host_interface *alt;
 	int max_packet_size;
 
@@ -2647,8 +2651,17 @@ static int sd_isoc_init(struct gspca_dev *gspca_dev)
 		break;
 	}
 
+	intfc = gspca_dev->dev->actconfig->intf_cache[0];
+
+	if (intfc->num_altsetting < 2)
+		return -ENODEV;
+
+	alt = &intfc->altsetting[1];
+
+	if (alt->desc.bNumEndpoints < 1)
+		return -ENODEV;
+
 	/* Start isoc bandwidth "negotiation" at max isoc bandwidth */
-	alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1];
 	alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(max_packet_size);
 
 	return 0;
@@ -2671,6 +2684,9 @@ static int sd_isoc_nego(struct gspca_dev *gspca_dev)
 		break;
 	}
 
+	/*
+	 * Existence of altsetting and endpoint was verified in sd_isoc_init()
+	 */
 	alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1];
 	packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
 	if (packet_size <= min_packet_size)
diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
index 3b5f73ffe17a..9da63b6ff167 100644
--- a/drivers/media/usb/uvc/uvc_driver.c
+++ b/drivers/media/usb/uvc/uvc_driver.c
@@ -1640,7 +1640,7 @@ static void uvc_delete(struct uvc_device *dev)
 	if (dev->vdev.dev)
 		v4l2_device_unregister(&dev->vdev);
 #ifdef CONFIG_MEDIA_CONTROLLER
-	if (media_devnode_is_registered(&dev->mdev.devnode))
+	if (media_devnode_is_registered(dev->mdev.devnode))
 		media_device_unregister(&dev->mdev);
 #endif
 
diff --git a/drivers/misc/enclosure.c b/drivers/misc/enclosure.c
index 6cab9411b158..56c52497d56c 100644
--- a/drivers/misc/enclosure.c
+++ b/drivers/misc/enclosure.c
@@ -364,10 +364,9 @@ int enclosure_remove_device(struct enclosure_device *edev, struct device *dev)
 		cdev = &edev->component[i];
 		if (cdev->dev == dev) {
 			enclosure_remove_links(cdev);
-			device_del(&cdev->cdev);
 			put_device(dev);
 			cdev->dev = NULL;
-			return device_add(&cdev->cdev);
+			return 0;
 		}
 	}
 	return -ENODEV;
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 393444edc78e..be03d058528c 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2945,11 +2945,13 @@ int sdhci_add_host(struct sdhci_host *host)
 	if (host->ops->get_min_clock)
 		mmc->f_min = host->ops->get_min_clock(host);
 	else if (host->version >= SDHCI_SPEC_300) {
-		if (host->clk_mul) {
-			mmc->f_min = (host->max_clk * host->clk_mul) / 1024;
+		if (host->clk_mul)
 			mmc->f_max = host->max_clk * host->clk_mul;
-		} else
-			mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_300;
+		/*
+		 * Divided Clock Mode minimum clock rate is always less than
+		 * Programmable Clock Mode minimum clock rate.
+		 */
+		mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_300;
 	} else
 		mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200;
 
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 98f9fd6e37b6..3fb81bddf05b 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -3421,33 +3421,35 @@ static int bond_neigh_init(struct neighbour *n)
 	const struct net_device_ops *slave_ops;
 	struct neigh_parms parms;
 	struct slave *slave;
-	int ret;
+	int ret = 0;
 
-	slave = bond_first_slave(bond);
+	rcu_read_lock();
+	slave = bond_first_slave_rcu(bond);
 	if (!slave)
-		return 0;
+		goto out;
 	slave_ops = slave->dev->netdev_ops;
 	if (!slave_ops->ndo_neigh_setup)
-		return 0;
-
-	parms.neigh_setup = NULL;
-	parms.neigh_cleanup = NULL;
-	ret = slave_ops->ndo_neigh_setup(slave->dev, &parms);
-	if (ret)
-		return ret;
+		goto out;
 
-	/*
-	 * Assign slave's neigh_cleanup to neighbour in case cleanup is called
-	 * after the last slave has been detached.  Assumes that all slaves
-	 * utilize the same neigh_cleanup (true at this writing as only user
-	 * is ipoib).
+	/* TODO: find another way [1] to implement this.
+	 * Passing a zeroed structure is fragile,
+	 * but at least we do not pass garbage.
+	 *
+	 * [1] One way would be that ndo_neigh_setup() never touch
+	 *     struct neigh_parms, but propagate the new neigh_setup()
+	 *     back to ___neigh_create() / neigh_parms_alloc()
 	 */
-	n->parms->neigh_cleanup = parms.neigh_cleanup;
+	memset(&parms, 0, sizeof(parms));
+	ret = slave_ops->ndo_neigh_setup(slave->dev, &parms);
 
-	if (!parms.neigh_setup)
-		return 0;
+	if (ret)
+		goto out;
 
-	return parms.neigh_setup(n);
+	if (parms.neigh_setup)
+		ret = parms.neigh_setup(n);
+out:
+	rcu_read_unlock();
+	return ret;
 }
 
 /*
diff --git a/drivers/net/can/mscan/mscan.c b/drivers/net/can/mscan/mscan.c
index e0c9be5e2ab7..9aa851f865f4 100644
--- a/drivers/net/can/mscan/mscan.c
+++ b/drivers/net/can/mscan/mscan.c
@@ -412,13 +412,12 @@ static int mscan_rx_poll(struct napi_struct *napi, int quota)
 	struct net_device *dev = napi->dev;
 	struct mscan_regs __iomem *regs = priv->reg_base;
 	struct net_device_stats *stats = &dev->stats;
-	int npackets = 0;
-	int ret = 1;
+	int work_done = 0;
 	struct sk_buff *skb;
 	struct can_frame *frame;
 	u8 canrflg;
 
-	while (npackets < quota) {
+	while (work_done < quota) {
 		canrflg = in_8(&regs->canrflg);
 		if (!(canrflg & (MSCAN_RXF | MSCAN_ERR_IF)))
 			break;
@@ -439,18 +438,18 @@ static int mscan_rx_poll(struct napi_struct *napi, int quota)
 
 		stats->rx_packets++;
 		stats->rx_bytes += frame->can_dlc;
-		npackets++;
+		work_done++;
 		netif_receive_skb(skb);
 	}
 
-	if (!(in_8(&regs->canrflg) & (MSCAN_RXF | MSCAN_ERR_IF))) {
-		napi_complete(&priv->napi);
-		clear_bit(F_RX_PROGRESS, &priv->flags);
-		if (priv->can.state < CAN_STATE_BUS_OFF)
-			out_8(&regs->canrier, priv->shadow_canrier);
-		ret = 0;
+	if (work_done < quota) {
+		if (likely(napi_complete_done(&priv->napi, work_done))) {
+			clear_bit(F_RX_PROGRESS, &priv->flags);
+			if (priv->can.state < CAN_STATE_BUS_OFF)
+				out_8(&regs->canrier, priv->shadow_canrier);
+		}
 	}
-	return ret;
+	return work_done;
 }
 
 static irqreturn_t mscan_isr(int irq, void *dev_id)
diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c
index ea4d4f1a6411..f0769ce11c4b 100644
--- a/drivers/net/can/slcan.c
+++ b/drivers/net/can/slcan.c
@@ -150,7 +150,7 @@ static void slc_bump(struct slcan *sl)
 	u32 tmpid;
 	char *cmd = sl->rbuff;
 
-	cf.can_id = 0;
+	memset(&cf, 0, sizeof(cf));
 
 	switch (*cmd) {
 	case 'r':
@@ -189,8 +189,6 @@ static void slc_bump(struct slcan *sl)
 	else
 		return;
 
-	*(u64 *) (&cf.data) = 0; /* clear payload */
-
 	/* RTR frames may have a dlc > 0 but they never have any data bytes */
 	if (!(cf.can_id & CAN_RTR_FLAG)) {
 		for (i = 0; i < cf.can_dlc; i++) {
@@ -346,9 +344,16 @@ static void slcan_transmit(struct work_struct *work)
  */
 static void slcan_write_wakeup(struct tty_struct *tty)
 {
-	struct slcan *sl = tty->disc_data;
+	struct slcan *sl;
+
+	rcu_read_lock();
+	sl = rcu_dereference(tty->disc_data);
+	if (!sl)
+		goto out;
 
 	schedule_work(&sl->tx_work);
+out:
+	rcu_read_unlock();
 }
 
 /* Send a can_frame to a TTY queue. */
@@ -640,10 +645,11 @@ static void slcan_close(struct tty_struct *tty)
 		return;
 
 	spin_lock_bh(&sl->lock);
-	tty->disc_data = NULL;
+	rcu_assign_pointer(tty->disc_data, NULL);
 	sl->tty = NULL;
 	spin_unlock_bh(&sl->lock);
 
+	synchronize_rcu();
 	flush_work(&sl->tx_work);
 
 	/* Flush network side */
diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c
index 3da1be6b508b..b58d25aedb72 100644
--- a/drivers/net/can/usb/gs_usb.c
+++ b/drivers/net/can/usb/gs_usb.c
@@ -846,7 +846,7 @@ static int gs_usb_probe(struct usb_interface *intf, const struct usb_device_id *
 			     GS_USB_BREQ_HOST_FORMAT,
 			     USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE,
 			     1,
-			     intf->altsetting[0].desc.bInterfaceNumber,
+			     intf->cur_altsetting->desc.bInterfaceNumber,
 			     hconf,
 			     sizeof(*hconf),
 			     1000);
@@ -869,7 +869,7 @@ static int gs_usb_probe(struct usb_interface *intf, const struct usb_device_id *
 			     GS_USB_BREQ_DEVICE_CONFIG,
 			     USB_DIR_IN|USB_TYPE_VENDOR|USB_RECIP_INTERFACE,
 			     1,
-			     intf->altsetting[0].desc.bInterfaceNumber,
+			     intf->cur_altsetting->desc.bInterfaceNumber,
 			     dconf,
 			     sizeof(*dconf),
 			     1000);
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
index c932436c6a47..35ab6f85a0df 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
@@ -1465,11 +1465,6 @@ static int ixgbevf_write_uc_addr_list(struct net_device *netdev)
 	struct ixgbe_hw *hw = &adapter->hw;
 	int count = 0;
 
-	if ((netdev_uc_count(netdev)) > 10) {
-		pr_err("Too many unicast filters - No Space\n");
-		return -ENOSPC;
-	}
-
 	if (!netdev_uc_empty(netdev)) {
 		struct netdev_hw_addr *ha;
 		netdev_for_each_uc_addr(ha, netdev) {
diff --git a/drivers/net/ethernet/natsemi/sonic.c b/drivers/net/ethernet/natsemi/sonic.c
index 1bd419dbda6d..cf3aaffc445f 100644
--- a/drivers/net/ethernet/natsemi/sonic.c
+++ b/drivers/net/ethernet/natsemi/sonic.c
@@ -50,6 +50,8 @@ static int sonic_open(struct net_device *dev)
 	if (sonic_debug > 2)
 		printk("sonic_open: initializing sonic driver.\n");
 
+	spin_lock_init(&lp->lock);
+
 	for (i = 0; i < SONIC_NUM_RRS; i++) {
 		struct sk_buff *skb = netdev_alloc_skb(dev, SONIC_RBSIZE + 2);
 		if (skb == NULL) {
@@ -101,6 +103,24 @@ static int sonic_open(struct net_device *dev)
 	return 0;
 }
 
+/* Wait for the SONIC to become idle. */
+static void sonic_quiesce(struct net_device *dev, u16 mask)
+{
+	struct sonic_local * __maybe_unused lp = netdev_priv(dev);
+	int i;
+	u16 bits;
+
+	for (i = 0; i < 1000; ++i) {
+		bits = SONIC_READ(SONIC_CMD) & mask;
+		if (!bits)
+			return;
+		if (irqs_disabled() || in_interrupt())
+			udelay(20);
+		else
+			usleep_range(100, 200);
+	}
+	WARN_ONCE(1, "command deadline expired! 0x%04x\n", bits);
+}
 
 /*
  * Close the SONIC device
@@ -118,6 +138,9 @@ static int sonic_close(struct net_device *dev)
 	/*
 	 * stop the SONIC, disable interrupts
 	 */
+	SONIC_WRITE(SONIC_CMD, SONIC_CR_RXDIS);
+	sonic_quiesce(dev, SONIC_CR_ALL);
+
 	SONIC_WRITE(SONIC_IMR, 0);
 	SONIC_WRITE(SONIC_ISR, 0x7fff);
 	SONIC_WRITE(SONIC_CMD, SONIC_CR_RST);
@@ -157,6 +180,9 @@ static void sonic_tx_timeout(struct net_device *dev)
 	 * put the Sonic into software-reset mode and
 	 * disable all interrupts before releasing DMA buffers
 	 */
+	SONIC_WRITE(SONIC_CMD, SONIC_CR_RXDIS);
+	sonic_quiesce(dev, SONIC_CR_ALL);
+
 	SONIC_WRITE(SONIC_IMR, 0);
 	SONIC_WRITE(SONIC_ISR, 0x7fff);
 	SONIC_WRITE(SONIC_CMD, SONIC_CR_RST);
@@ -194,8 +220,6 @@ static void sonic_tx_timeout(struct net_device *dev)
  *   wake the tx queue
  * Concurrently with all of this, the SONIC is potentially writing to
  * the status flags of the TDs.
- * Until some mutual exclusion is added, this code will not work with SMP. However,
- * MIPS Jazz machines and m68k Macs were all uni-processor machines.
  */
 
 static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev)
@@ -203,7 +227,8 @@ static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev)
 	struct sonic_local *lp = netdev_priv(dev);
 	dma_addr_t laddr;
 	int length;
-	int entry = lp->next_tx;
+	int entry;
+	unsigned long flags;
 
 	if (sonic_debug > 2)
 		printk("sonic_send_packet: skb=%p, dev=%p\n", skb, dev);
@@ -221,11 +246,15 @@ static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev)
 
 	laddr = dma_map_single(lp->device, skb->data, length, DMA_TO_DEVICE);
 	if (!laddr) {
-		printk(KERN_ERR "%s: failed to map tx DMA buffer.\n", dev->name);
+		pr_err_ratelimited("%s: failed to map tx DMA buffer.\n", dev->name);
 		dev_kfree_skb(skb);
-		return NETDEV_TX_BUSY;
+		return NETDEV_TX_OK;
 	}
 
+	spin_lock_irqsave(&lp->lock, flags);
+
+	entry = lp->next_tx;
+
 	sonic_tda_put(dev, entry, SONIC_TD_STATUS, 0);       /* clear status */
 	sonic_tda_put(dev, entry, SONIC_TD_FRAG_COUNT, 1);   /* single fragment */
 	sonic_tda_put(dev, entry, SONIC_TD_PKTSIZE, length); /* length of packet */
@@ -235,10 +264,6 @@ static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev)
 	sonic_tda_put(dev, entry, SONIC_TD_LINK,
 		sonic_tda_get(dev, entry, SONIC_TD_LINK) | SONIC_EOL);
 
-	/*
-	 * Must set tx_skb[entry] only after clearing status, and
-	 * before clearing EOL and before stopping queue
-	 */
 	wmb();
 	lp->tx_len[entry] = length;
 	lp->tx_laddr[entry] = laddr;
@@ -263,6 +288,8 @@ static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev)
 
 	SONIC_WRITE(SONIC_CMD, SONIC_CR_TXP);
 
+	spin_unlock_irqrestore(&lp->lock, flags);
+
 	return NETDEV_TX_OK;
 }
 
@@ -275,9 +302,21 @@ static irqreturn_t sonic_interrupt(int irq, void *dev_id)
 	struct net_device *dev = dev_id;
 	struct sonic_local *lp = netdev_priv(dev);
 	int status;
+	unsigned long flags;
+
+	/* The lock has two purposes. Firstly, it synchronizes sonic_interrupt()
+	 * with sonic_send_packet() so that the two functions can share state.
+	 * Secondly, it makes sonic_interrupt() re-entrant, as that is required
+	 * by macsonic which must use two IRQs with different priority levels.
+	 */
+	spin_lock_irqsave(&lp->lock, flags);
+
+	status = SONIC_READ(SONIC_ISR) & SONIC_IMR_DEFAULT;
+	if (!status) {
+		spin_unlock_irqrestore(&lp->lock, flags);
 
-	if (!(status = SONIC_READ(SONIC_ISR) & SONIC_IMR_DEFAULT))
 		return IRQ_NONE;
+	}
 
 	do {
 		if (status & SONIC_INT_PKTRX) {
@@ -292,11 +331,12 @@ static irqreturn_t sonic_interrupt(int irq, void *dev_id)
 			int td_status;
 			int freed_some = 0;
 
-			/* At this point, cur_tx is the index of a TD that is one of:
-			 *   unallocated/freed                          (status set   & tx_skb[entry] clear)
-			 *   allocated and sent                         (status set   & tx_skb[entry] set  )
-			 *   allocated and not yet sent                 (status clear & tx_skb[entry] set  )
-			 *   still being allocated by sonic_send_packet (status clear & tx_skb[entry] clear)
+			/* The state of a Transmit Descriptor may be inferred
+			 * from { tx_skb[entry], td_status } as follows.
+			 * { clear, clear } => the TD has never been used
+			 * { set,   clear } => the TD was handed to SONIC
+			 * { set,   set   } => the TD was handed back
+			 * { clear, set   } => the TD is available for re-use
 			 */
 
 			if (sonic_debug > 2)
@@ -398,10 +438,30 @@ static irqreturn_t sonic_interrupt(int irq, void *dev_id)
 		/* load CAM done */
 		if (status & SONIC_INT_LCD)
 			SONIC_WRITE(SONIC_ISR, SONIC_INT_LCD); /* clear the interrupt */
-	} while((status = SONIC_READ(SONIC_ISR) & SONIC_IMR_DEFAULT));
+
+		status = SONIC_READ(SONIC_ISR) & SONIC_IMR_DEFAULT;
+	} while (status);
+
+	spin_unlock_irqrestore(&lp->lock, flags);
+
 	return IRQ_HANDLED;
 }
 
+/* Return the array index corresponding to a given Receive Buffer pointer. */
+static int index_from_addr(struct sonic_local *lp, dma_addr_t addr,
+			   unsigned int last)
+{
+	unsigned int i = last;
+
+	do {
+		i = (i + 1) & SONIC_RRS_MASK;
+		if (addr == lp->rx_laddr[i])
+			return i;
+	} while (i != last);
+
+	return -ENOENT;
+}
+
 /*
  * We have a good packet(s), pass it/them up the network stack.
  */
@@ -421,6 +481,16 @@ static void sonic_rx(struct net_device *dev)
 
 		status = sonic_rda_get(dev, entry, SONIC_RD_STATUS);
 		if (status & SONIC_RCR_PRX) {
+			u32 addr = (sonic_rda_get(dev, entry,
+						  SONIC_RD_PKTPTR_H) << 16) |
+				   sonic_rda_get(dev, entry, SONIC_RD_PKTPTR_L);
+			int i = index_from_addr(lp, addr, entry);
+
+			if (i < 0) {
+				WARN_ONCE(1, "failed to find buffer!\n");
+				break;
+			}
+
 			/* Malloc up new buffer. */
 			new_skb = netdev_alloc_skb(dev, SONIC_RBSIZE + 2);
 			if (new_skb == NULL) {
@@ -442,7 +512,7 @@ static void sonic_rx(struct net_device *dev)
 
 			/* now we have a new skb to replace it, pass the used one up the stack */
 			dma_unmap_single(lp->device, lp->rx_laddr[entry], SONIC_RBSIZE, DMA_FROM_DEVICE);
-			used_skb = lp->rx_skb[entry];
+			used_skb = lp->rx_skb[i];
 			pkt_len = sonic_rda_get(dev, entry, SONIC_RD_PKTLEN);
 			skb_trim(used_skb, pkt_len);
 			used_skb->protocol = eth_type_trans(used_skb, dev);
@@ -451,13 +521,13 @@ static void sonic_rx(struct net_device *dev)
 			lp->stats.rx_bytes += pkt_len;
 
 			/* and insert the new skb */
-			lp->rx_laddr[entry] = new_laddr;
-			lp->rx_skb[entry] = new_skb;
+			lp->rx_laddr[i] = new_laddr;
+			lp->rx_skb[i] = new_skb;
 
 			bufadr_l = (unsigned long)new_laddr & 0xffff;
 			bufadr_h = (unsigned long)new_laddr >> 16;
-			sonic_rra_put(dev, entry, SONIC_RR_BUFADR_L, bufadr_l);
-			sonic_rra_put(dev, entry, SONIC_RR_BUFADR_H, bufadr_h);
+			sonic_rra_put(dev, i, SONIC_RR_BUFADR_L, bufadr_l);
+			sonic_rra_put(dev, i, SONIC_RR_BUFADR_H, bufadr_h);
 		} else {
 			/* This should only happen, if we enable accepting broken packets. */
 			lp->stats.rx_errors++;
@@ -592,6 +662,7 @@ static int sonic_init(struct net_device *dev)
 	 */
 	SONIC_WRITE(SONIC_CMD, 0);
 	SONIC_WRITE(SONIC_CMD, SONIC_CR_RXDIS);
+	sonic_quiesce(dev, SONIC_CR_ALL);
 
 	/*
 	 * initialize the receive resource area
diff --git a/drivers/net/ethernet/natsemi/sonic.h b/drivers/net/ethernet/natsemi/sonic.h
index 07091dd27e5d..7dcf913d7395 100644
--- a/drivers/net/ethernet/natsemi/sonic.h
+++ b/drivers/net/ethernet/natsemi/sonic.h
@@ -109,6 +109,9 @@
 #define SONIC_CR_TXP            0x0002
 #define SONIC_CR_HTX            0x0001
 
+#define SONIC_CR_ALL (SONIC_CR_LCAM | SONIC_CR_RRRA | \
+		      SONIC_CR_RXEN | SONIC_CR_TXP)
+
 /*
  * SONIC data configuration bits
  */
@@ -273,8 +276,9 @@
 #define SONIC_NUM_RDS   SONIC_NUM_RRS /* number of receive descriptors */
 #define SONIC_NUM_TDS   16            /* number of transmit descriptors */
 
-#define SONIC_RDS_MASK  (SONIC_NUM_RDS-1)
-#define SONIC_TDS_MASK  (SONIC_NUM_TDS-1)
+#define SONIC_RRS_MASK  (SONIC_NUM_RRS - 1)
+#define SONIC_RDS_MASK  (SONIC_NUM_RDS - 1)
+#define SONIC_TDS_MASK  (SONIC_NUM_TDS - 1)
 
 #define SONIC_RBSIZE	1520          /* size of one resource buffer */
 
@@ -320,6 +324,7 @@ struct sonic_local {
 	unsigned int next_tx;          /* next free TD */
 	struct device *device;         /* generic device */
 	struct net_device_stats stats;
+	spinlock_t lock;
 };
 
 #define TX_TIMEOUT (3 * HZ)
@@ -341,30 +346,30 @@ static void sonic_tx_timeout(struct net_device *dev);
    as far as we can tell. */
 /* OpenBSD calls this "SWO".  I'd like to think that sonic_buf_put()
    is a much better name. */
-static inline void sonic_buf_put(void* base, int bitmode,
+static inline void sonic_buf_put(u16 *base, int bitmode,
 				 int offset, __u16 val)
 {
 	if (bitmode)
 #ifdef __BIG_ENDIAN
-		((__u16 *) base + (offset*2))[1] = val;
+		__raw_writew(val, base + (offset * 2) + 1);
 #else
-		((__u16 *) base + (offset*2))[0] = val;
+		__raw_writew(val, base + (offset * 2) + 0);
 #endif
 	else
-	 	((__u16 *) base)[offset] = val;
+		__raw_writew(val, base + (offset * 1) + 0);
 }
 
-static inline __u16 sonic_buf_get(void* base, int bitmode,
+static inline __u16 sonic_buf_get(u16 *base, int bitmode,
 				  int offset)
 {
 	if (bitmode)
 #ifdef __BIG_ENDIAN
-		return ((volatile __u16 *) base + (offset*2))[1];
+		return __raw_readw(base + (offset * 2) + 1);
 #else
-		return ((volatile __u16 *) base + (offset*2))[0];
+		return __raw_readw(base + (offset * 2) + 0);
 #endif
 	else
-		return ((volatile __u16 *) base)[offset];
+		return __raw_readw(base + (offset * 1) + 0);
 }
 
 /* Inlines that you should actually use for reading/writing DMA buffers */
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index 4561b16a9ebb..4747facb3edc 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -270,9 +270,8 @@ struct dma_features {
 	unsigned int enh_desc;
 };
 
-/* GMAC TX FIFO is 8K, Rx FIFO is 16K */
-#define BUF_SIZE_16KiB 16384
-/* RX Buffer size must be < 8191 and multiple of 4/8/16 bytes */
+/* RX Buffer size must be multiple of 4/8/16 bytes */
+#define BUF_SIZE_16KiB 16368
 #define BUF_SIZE_8KiB 8188
 #define BUF_SIZE_4KiB 4096
 #define BUF_SIZE_2KiB 2048
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
index 771cd15fca18..0f7a4d70d919 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
@@ -78,7 +78,7 @@ static int sun7i_gmac_init(struct platform_device *pdev, void *priv)
 	 * rate, which then uses the auto-reparenting feature of the
 	 * clock driver, and enabling/disabling the clock.
 	 */
-	if (gmac->interface == PHY_INTERFACE_MODE_RGMII) {
+	if (phy_interface_mode_is_rgmii(gmac->interface)) {
 		clk_set_rate(gmac->tx_clk, SUN7I_GMAC_GMII_RGMII_RATE);
 		clk_prepare_enable(gmac->tx_clk);
 		gmac->clk_enabled = 1;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 5fe95ef7954b..ad9f1f022457 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -904,7 +904,9 @@ static int stmmac_set_bfsize(int mtu, int bufsize)
 {
 	int ret = bufsize;
 
-	if (mtu >= BUF_SIZE_4KiB)
+	if (mtu >= BUF_SIZE_8KiB)
+		ret = BUF_SIZE_16KiB;
+	else if (mtu >= BUF_SIZE_4KiB)
 		ret = BUF_SIZE_8KiB;
 	else if (mtu >= BUF_SIZE_2KiB)
 		ret = BUF_SIZE_4KiB;
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
index 5e8aff812f20..bd109f981d8b 100644
--- a/drivers/net/hamradio/6pack.c
+++ b/drivers/net/hamradio/6pack.c
@@ -685,10 +685,10 @@ static void sixpack_close(struct tty_struct *tty)
 {
 	struct sixpack *sp;
 
-	write_lock_bh(&disc_data_lock);
+	write_lock_irq(&disc_data_lock);
 	sp = tty->disc_data;
 	tty->disc_data = NULL;
-	write_unlock_bh(&disc_data_lock);
+	write_unlock_irq(&disc_data_lock);
 	if (!sp)
 		return;
 
diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
index 8a6c720a4cc9..dba143836753 100644
--- a/drivers/net/hamradio/mkiss.c
+++ b/drivers/net/hamradio/mkiss.c
@@ -811,10 +811,10 @@ static void mkiss_close(struct tty_struct *tty)
 {
 	struct mkiss *ax;
 
-	write_lock_bh(&disc_data_lock);
+	write_lock_irq(&disc_data_lock);
 	ax = tty->disc_data;
 	tty->disc_data = NULL;
-	write_unlock_bh(&disc_data_lock);
+	write_unlock_irq(&disc_data_lock);
 
 	if (!ax)
 		return;
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 9493690885cf..02efd2775dcf 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -345,10 +345,11 @@ static int macvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev)
 	const struct macvlan_dev *dest;
 
 	if (vlan->mode == MACVLAN_MODE_BRIDGE) {
-		const struct ethhdr *eth = (void *)skb->data;
+		const struct ethhdr *eth = skb_eth_hdr(skb);
 
 		/* send to other bridge ports directly */
 		if (is_multicast_ether_addr(eth->h_dest)) {
+			skb_reset_mac_header(skb);
 			macvlan_broadcast(skb, port, dev, MACVLAN_MODE_BRIDGE);
 			goto xmit_world;
 		}
diff --git a/drivers/net/slip/slip.c b/drivers/net/slip/slip.c
index 3780c4672bfa..65df455c056e 100644
--- a/drivers/net/slip/slip.c
+++ b/drivers/net/slip/slip.c
@@ -452,9 +452,16 @@ static void slip_transmit(struct work_struct *work)
  */
 static void slip_write_wakeup(struct tty_struct *tty)
 {
-	struct slip *sl = tty->disc_data;
+	struct slip *sl;
+
+	rcu_read_lock();
+	sl = rcu_dereference(tty->disc_data);
+	if (!sl)
+		goto out;
 
 	schedule_work(&sl->tx_work);
+out:
+	rcu_read_unlock();
 }
 
 static void sl_tx_timeout(struct net_device *dev)
@@ -885,10 +892,11 @@ static void slip_close(struct tty_struct *tty)
 		return;
 
 	spin_lock_bh(&sl->lock);
-	tty->disc_data = NULL;
+	rcu_assign_pointer(tty->disc_data, NULL);
 	sl->tty = NULL;
 	spin_unlock_bh(&sl->lock);
 
+	synchronize_rcu();
 	flush_work(&sl->tx_work);
 
 	/* VSV = very important to remove timers */
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index 6fa1d2c9c556..714beecd16ef 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -3425,6 +3425,9 @@ static int rtl8152_probe(struct usb_interface *intf,
 		return -ENODEV;
 	}
 
+	if (intf->cur_altsetting->desc.bNumEndpoints < 3)
+		return -ENODEV;
+
 	usb_reset_device(udev);
 	netdev = alloc_etherdev(sizeof(struct r8152));
 	if (!netdev) {
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 73874090cf42..78f3e8612bab 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -1904,7 +1904,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
 			return;
 		}
 
-		tos = ip_tunnel_ecn_encap(tos, old_iph, skb);
+		tos = ip_tunnel_ecn_encap(RT_TOS(tos), old_iph, skb);
 		ttl = ttl ? : ip4_dst_hoplimit(&rt->dst);
 
 		err = vxlan_xmit_skb(vxlan->vn_sock, rt, skb,
@@ -1929,7 +1929,8 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
 		fl6.saddr = vxlan->saddr.sin6.sin6_addr;
 		fl6.flowi6_proto = IPPROTO_UDP;
 
-		if (ipv6_stub->ipv6_dst_lookup(sk, &ndst, &fl6)) {
+		ndst = ipv6_stub->ipv6_dst_lookup_flow(sk, &fl6, NULL);
+		if (unlikely(IS_ERR(ndst))) {
 			netdev_dbg(dev, "no route to %pI6\n",
 				   &dst->sin6.sin6_addr);
 			dev->stats.tx_carrier_errors++;
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c
index 47a998d8f99e..390541173138 100644
--- a/drivers/net/wireless/libertas/cfg.c
+++ b/drivers/net/wireless/libertas/cfg.c
@@ -272,6 +272,10 @@ add_ie_rates(u8 *tlv, const u8 *ie, int *nrates)
 	int hw, ap, ap_max = ie[1];
 	u8 hw_rate;
 
+	if (ap_max > MAX_RATES) {
+		lbs_deb_assoc("invalid rates\n");
+		return tlv;
+	}
 	/* Advance past IE header */
 	ie += 2;
 
@@ -1785,6 +1789,9 @@ static int lbs_ibss_join_existing(struct lbs_private *priv,
 	struct cmd_ds_802_11_ad_hoc_join cmd;
 	u8 preamble = RADIO_PREAMBLE_SHORT;
 	int ret = 0;
+	int hw, i;
+	u8 rates_max;
+	u8 *rates;
 
 	lbs_deb_enter(LBS_DEB_CFG80211);
 
@@ -1845,9 +1852,14 @@ static int lbs_ibss_join_existing(struct lbs_private *priv,
 	if (!rates_eid) {
 		lbs_add_rates(cmd.bss.rates);
 	} else {
-		int hw, i;
-		u8 rates_max = rates_eid[1];
-		u8 *rates = cmd.bss.rates;
+		rates_max = rates_eid[1];
+		if (rates_max > MAX_RATES) {
+			lbs_deb_join("invalid rates");
+			rcu_read_unlock();
+			ret = -EINVAL;
+			goto out;
+		}
+		rates = cmd.bss.rates;
 		for (hw = 0; hw < ARRAY_SIZE(lbs_rates); hw++) {
 			u8 hw_rate = lbs_rates[hw].bitrate / 5;
 			for (i = 0; i < rates_max; i++) {
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c
index 5326a0095601..501505f2e3c7 100644
--- a/drivers/net/wireless/mwifiex/sta_ioctl.c
+++ b/drivers/net/wireless/mwifiex/sta_ioctl.c
@@ -226,6 +226,7 @@ static int mwifiex_process_country_ie(struct mwifiex_private *priv,
 
 	if (country_ie_len >
 	    (IEEE80211_COUNTRY_STRING_LEN + MWIFIEX_MAX_TRIPLET_802_11D)) {
+		rcu_read_unlock();
 		wiphy_dbg(priv->wdev->wiphy,
 			  "11D: country_ie_len overflow!, deauth AP\n");
 		return -EINVAL;
diff --git a/drivers/net/wireless/mwifiex/tdls.c b/drivers/net/wireless/mwifiex/tdls.c
index 0e88364e0c67..bc374d8825b7 100644
--- a/drivers/net/wireless/mwifiex/tdls.c
+++ b/drivers/net/wireless/mwifiex/tdls.c
@@ -847,57 +847,117 @@ void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv,
 
 		switch (*pos) {
 		case WLAN_EID_SUPP_RATES:
+			if (pos[1] > 32)
+				return;
 			sta_ptr->tdls_cap.rates_len = pos[1];
 			for (i = 0; i < pos[1]; i++)
 				sta_ptr->tdls_cap.rates[i] = pos[i + 2];
 			break;
 
 		case WLAN_EID_EXT_SUPP_RATES:
+			if (pos[1] > 32)
+				return;
 			basic = sta_ptr->tdls_cap.rates_len;
+			if (pos[1] > 32 - basic)
+				return;
 			for (i = 0; i < pos[1]; i++)
 				sta_ptr->tdls_cap.rates[basic + i] = pos[i + 2];
 			sta_ptr->tdls_cap.rates_len += pos[1];
 			break;
 		case WLAN_EID_HT_CAPABILITY:
-			memcpy((u8 *)&sta_ptr->tdls_cap.ht_capb, pos,
+			if (pos > end - sizeof(struct ieee80211_ht_cap) - 2)
+				return;
+			if (pos[1] != sizeof(struct ieee80211_ht_cap))
+				return;
+			/* copy the ie's value into ht_capb*/
+			memcpy((u8 *)&sta_ptr->tdls_cap.ht_capb, pos + 2,
 			       sizeof(struct ieee80211_ht_cap));
 			sta_ptr->is_11n_enabled = 1;
 			break;
 		case WLAN_EID_HT_OPERATION:
-			memcpy(&sta_ptr->tdls_cap.ht_oper, pos,
+			if (pos > end -
+			    sizeof(struct ieee80211_ht_operation) - 2)
+				return;
+			if (pos[1] != sizeof(struct ieee80211_ht_operation))
+				return;
+			/* copy the ie's value into ht_oper*/
+			memcpy(&sta_ptr->tdls_cap.ht_oper, pos + 2,
 			       sizeof(struct ieee80211_ht_operation));
 			break;
 		case WLAN_EID_BSS_COEX_2040:
+			if (pos > end - 3)
+				return;
+			if (pos[1] != 1)
+				return;
 			sta_ptr->tdls_cap.coex_2040 = pos[2];
 			break;
 		case WLAN_EID_EXT_CAPABILITY:
+			if (pos > end - sizeof(struct ieee_types_header))
+				return;
+			if (pos[1] < sizeof(struct ieee_types_header))
+				return;
+			if (pos[1] > 8)
+				return;
 			memcpy((u8 *)&sta_ptr->tdls_cap.extcap, pos,
 			       sizeof(struct ieee_types_header) +
 			       min_t(u8, pos[1], 8));
 			break;
 		case WLAN_EID_RSN:
+			if (pos > end - sizeof(struct ieee_types_header))
+				return;
+			if (pos[1] < sizeof(struct ieee_types_header))
+				return;
+			if (pos[1] > IEEE_MAX_IE_SIZE -
+			    sizeof(struct ieee_types_header))
+				return;
 			memcpy((u8 *)&sta_ptr->tdls_cap.rsn_ie, pos,
-			       sizeof(struct ieee_types_header) + pos[1]);
+			       sizeof(struct ieee_types_header) +
+			       min_t(u8, pos[1], IEEE_MAX_IE_SIZE -
+				     sizeof(struct ieee_types_header)));
 			break;
 		case WLAN_EID_QOS_CAPA:
+			if (pos > end - 3)
+				return;
+			if (pos[1] != 1)
+				return;
 			sta_ptr->tdls_cap.qos_info = pos[2];
 			break;
 		case WLAN_EID_VHT_OPERATION:
-			if (priv->adapter->is_hw_11ac_capable)
-				memcpy(&sta_ptr->tdls_cap.vhtoper, pos,
+			if (priv->adapter->is_hw_11ac_capable) {
+				if (pos > end -
+				    sizeof(struct ieee80211_vht_operation) - 2)
+					return;
+				if (pos[1] !=
+				    sizeof(struct ieee80211_vht_operation))
+					return;
+				/* copy the ie's value into vhtoper*/
+				memcpy(&sta_ptr->tdls_cap.vhtoper, pos + 2,
 				       sizeof(struct ieee80211_vht_operation));
+			}
 			break;
 		case WLAN_EID_VHT_CAPABILITY:
 			if (priv->adapter->is_hw_11ac_capable) {
-				memcpy((u8 *)&sta_ptr->tdls_cap.vhtcap, pos,
+				if (pos > end -
+				    sizeof(struct ieee80211_vht_cap) - 2)
+					return;
+				if (pos[1] != sizeof(struct ieee80211_vht_cap))
+					return;
+				/* copy the ie's value into vhtcap*/
+				memcpy((u8 *)&sta_ptr->tdls_cap.vhtcap, pos + 2,
 				       sizeof(struct ieee80211_vht_cap));
 				sta_ptr->is_11ac_enabled = 1;
 			}
 			break;
 		case WLAN_EID_AID:
-			if (priv->adapter->is_hw_11ac_capable)
+			if (priv->adapter->is_hw_11ac_capable) {
+				if (pos > end - 4)
+					return;
+				if (pos[1] != 2)
+					return;
 				sta_ptr->tdls_cap.aid =
 					      le16_to_cpu(*(__le16 *)(pos + 2));
+			}
+			break;
 		default:
 			break;
 		}
diff --git a/drivers/pinctrl/pinctrl-baytrail.c b/drivers/pinctrl/pinctrl-baytrail.c
index ecbfec9e54d9..bc9312adecf6 100644
--- a/drivers/pinctrl/pinctrl-baytrail.c
+++ b/drivers/pinctrl/pinctrl-baytrail.c
@@ -44,6 +44,7 @@
 
 /* BYT_CONF0_REG register bits */
 #define BYT_IODEN		BIT(31)
+#define BYT_DIRECT_IRQ_EN	BIT(27)
 #define BYT_TRIG_NEG		BIT(26)
 #define BYT_TRIG_POS		BIT(25)
 #define BYT_TRIG_LVL		BIT(24)
@@ -139,13 +140,14 @@ struct byt_gpio {
 	struct gpio_chip		chip;
 	struct irq_domain		*domain;
 	struct platform_device		*pdev;
-	spinlock_t			lock;
 	void __iomem			*reg_base;
 	struct pinctrl_gpio_range	*range;
 };
 
 #define to_byt_gpio(c)	container_of(c, struct byt_gpio, chip)
 
+static DEFINE_RAW_SPINLOCK(byt_lock);
+
 static void __iomem *byt_gpio_reg(struct gpio_chip *chip, unsigned offset,
 				 int reg)
 {
@@ -160,42 +162,65 @@ static void __iomem *byt_gpio_reg(struct gpio_chip *chip, unsigned offset,
 	return vg->reg_base + reg_offset + reg;
 }
 
-static bool is_special_pin(struct byt_gpio *vg, unsigned offset)
+static void byt_gpio_clear_triggering(struct byt_gpio *vg, unsigned offset)
+{
+	void __iomem *reg = byt_gpio_reg(&vg->chip, offset, BYT_CONF0_REG);
+	unsigned long flags;
+	u32 value;
+
+	raw_spin_lock_irqsave(&byt_lock, flags);
+	value = readl(reg);
+	value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL);
+	writel(value, reg);
+	raw_spin_unlock_irqrestore(&byt_lock, flags);
+}
+
+static u32 byt_get_gpio_mux(struct byt_gpio *vg, unsigned offset)
 {
 	/* SCORE pin 92-93 */
 	if (!strcmp(vg->range->name, BYT_SCORE_ACPI_UID) &&
 		offset >= 92 && offset <= 93)
-		return true;
+		return 1;
 
 	/* SUS pin 11-21 */
 	if (!strcmp(vg->range->name, BYT_SUS_ACPI_UID) &&
 		offset >= 11 && offset <= 21)
-		return true;
+		return 1;
 
-	return false;
+	return 0;
 }
 
 static int byt_gpio_request(struct gpio_chip *chip, unsigned offset)
 {
 	struct byt_gpio *vg = to_byt_gpio(chip);
 	void __iomem *reg = byt_gpio_reg(chip, offset, BYT_CONF0_REG);
-	u32 value;
-	bool special;
+	u32 value, gpio_mux;
+	unsigned long flags;
+
+	raw_spin_lock_irqsave(&byt_lock, flags);
 
 	/*
 	 * In most cases, func pin mux 000 means GPIO function.
 	 * But, some pins may have func pin mux 001 represents
-	 * GPIO function. Only allow user to export pin with
-	 * func pin mux preset as GPIO function by BIOS/FW.
+	 * GPIO function.
+	 *
+	 * Because there are devices out there where some pins were not
+	 * configured correctly we allow changing the mux value from
+	 * request (but print out warning about that).
 	 */
 	value = readl(reg) & BYT_PIN_MUX;
-	special = is_special_pin(vg, offset);
-	if ((special && value != 1) || (!special && value)) {
-		dev_err(&vg->pdev->dev,
-			"pin %u cannot be used as GPIO.\n", offset);
-		return -EINVAL;
+	gpio_mux = byt_get_gpio_mux(vg, offset);
+	if (WARN_ON(gpio_mux != value)) {
+		value = readl(reg) & ~BYT_PIN_MUX;
+		value |= gpio_mux;
+		writel(value, reg);
+
+		dev_warn(&vg->pdev->dev,
+			 "pin %u forcibly re-configured as GPIO\n", offset);
 	}
 
+	raw_spin_unlock_irqrestore(&byt_lock, flags);
+
 	pm_runtime_get(&vg->pdev->dev);
 
 	return 0;
@@ -204,14 +229,8 @@ static int byt_gpio_request(struct gpio_chip *chip, unsigned offset)
 static void byt_gpio_free(struct gpio_chip *chip, unsigned offset)
 {
 	struct byt_gpio *vg = to_byt_gpio(chip);
-	void __iomem *reg = byt_gpio_reg(&vg->chip, offset, BYT_CONF0_REG);
-	u32 value;
-
-	/* clear interrupt triggering */
-	value = readl(reg);
-	value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL);
-	writel(value, reg);
 
+	byt_gpio_clear_triggering(vg, offset);
 	pm_runtime_put(&vg->pdev->dev);
 }
 
@@ -226,7 +245,7 @@ static int byt_irq_type(struct irq_data *d, unsigned type)
 	if (offset >= vg->chip.ngpio)
 		return -EINVAL;
 
-	spin_lock_irqsave(&vg->lock, flags);
+	raw_spin_lock_irqsave(&byt_lock, flags);
 	value = readl(reg);
 
 	/* For level trigges the BYT_TRIG_POS and BYT_TRIG_NEG bits
@@ -234,24 +253,14 @@ static int byt_irq_type(struct irq_data *d, unsigned type)
 	 */
 	value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL);
 
-	switch (type) {
-	case IRQ_TYPE_LEVEL_HIGH:
-		value |= BYT_TRIG_LVL;
-	case IRQ_TYPE_EDGE_RISING:
-		value |= BYT_TRIG_POS;
-		break;
-	case IRQ_TYPE_LEVEL_LOW:
-		value |= BYT_TRIG_LVL;
-	case IRQ_TYPE_EDGE_FALLING:
-		value |= BYT_TRIG_NEG;
-		break;
-	case IRQ_TYPE_EDGE_BOTH:
-		value |= (BYT_TRIG_NEG | BYT_TRIG_POS);
-		break;
-	}
 	writel(value, reg);
 
-	spin_unlock_irqrestore(&vg->lock, flags);
+	if (type & IRQ_TYPE_EDGE_BOTH)
+		__irq_set_handler_locked(d->irq, handle_edge_irq);
+	else if (type & IRQ_TYPE_LEVEL_MASK)
+		__irq_set_handler_locked(d->irq, handle_level_irq);
+
+	raw_spin_unlock_irqrestore(&byt_lock, flags);
 
 	return 0;
 }
@@ -259,17 +268,23 @@ static int byt_irq_type(struct irq_data *d, unsigned type)
 static int byt_gpio_get(struct gpio_chip *chip, unsigned offset)
 {
 	void __iomem *reg = byt_gpio_reg(chip, offset, BYT_VAL_REG);
-	return readl(reg) & BYT_LEVEL;
+	unsigned long flags;
+	u32 val;
+
+	raw_spin_lock_irqsave(&byt_lock, flags);
+	val = readl(reg);
+	raw_spin_unlock_irqrestore(&byt_lock, flags);
+
+	return val & BYT_LEVEL;
 }
 
 static void byt_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 {
-	struct byt_gpio *vg = to_byt_gpio(chip);
 	void __iomem *reg = byt_gpio_reg(chip, offset, BYT_VAL_REG);
 	unsigned long flags;
 	u32 old_val;
 
-	spin_lock_irqsave(&vg->lock, flags);
+	raw_spin_lock_irqsave(&byt_lock, flags);
 
 	old_val = readl(reg);
 
@@ -278,23 +293,22 @@ static void byt_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 	else
 		writel(old_val & ~BYT_LEVEL, reg);
 
-	spin_unlock_irqrestore(&vg->lock, flags);
+	raw_spin_unlock_irqrestore(&byt_lock, flags);
 }
 
 static int byt_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
 {
-	struct byt_gpio *vg = to_byt_gpio(chip);
 	void __iomem *reg = byt_gpio_reg(chip, offset, BYT_VAL_REG);
 	unsigned long flags;
 	u32 value;
 
-	spin_lock_irqsave(&vg->lock, flags);
+	raw_spin_lock_irqsave(&byt_lock, flags);
 
 	value = readl(reg) | BYT_DIR_MASK;
 	value &= ~BYT_INPUT_EN;		/* active low */
 	writel(value, reg);
 
-	spin_unlock_irqrestore(&vg->lock, flags);
+	raw_spin_unlock_irqrestore(&byt_lock, flags);
 
 	return 0;
 }
@@ -302,12 +316,11 @@ static int byt_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
 static int byt_gpio_direction_output(struct gpio_chip *chip,
 				     unsigned gpio, int value)
 {
-	struct byt_gpio *vg = to_byt_gpio(chip);
 	void __iomem *reg = byt_gpio_reg(chip, gpio, BYT_VAL_REG);
 	unsigned long flags;
 	u32 reg_val;
 
-	spin_lock_irqsave(&vg->lock, flags);
+	raw_spin_lock_irqsave(&byt_lock, flags);
 
 	reg_val = readl(reg) | BYT_DIR_MASK;
 	reg_val &= ~(BYT_OUTPUT_EN | BYT_INPUT_EN);
@@ -317,7 +330,7 @@ static int byt_gpio_direction_output(struct gpio_chip *chip,
 	else
 		writel(reg_val & ~BYT_LEVEL, reg);
 
-	spin_unlock_irqrestore(&vg->lock, flags);
+	raw_spin_unlock_irqrestore(&byt_lock, flags);
 
 	return 0;
 }
@@ -329,7 +342,7 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
 	unsigned long flags;
 	u32 conf0, val, offs;
 
-	spin_lock_irqsave(&vg->lock, flags);
+	raw_spin_lock_irqsave(&byt_lock, flags);
 
 	for (i = 0; i < vg->chip.ngpio; i++) {
 		const char *pull_str = NULL;
@@ -390,7 +403,7 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
 
 		seq_puts(s, "\n");
 	}
-	spin_unlock_irqrestore(&vg->lock, flags);
+	raw_spin_unlock_irqrestore(&byt_lock, flags);
 }
 
 static int byt_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
@@ -404,54 +417,77 @@ static void byt_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
 	struct irq_data *data = irq_desc_get_irq_data(desc);
 	struct byt_gpio *vg = irq_data_get_irq_handler_data(data);
 	struct irq_chip *chip = irq_data_get_irq_chip(data);
-	u32 base, pin, mask;
+	u32 base, pin;
 	void __iomem *reg;
-	u32 pending;
+	unsigned long pending;
 	unsigned virq;
-	int looplimit = 0;
 
 	/* check from GPIO controller which pin triggered the interrupt */
 	for (base = 0; base < vg->chip.ngpio; base += 32) {
-
 		reg = byt_gpio_reg(&vg->chip, base, BYT_INT_STAT_REG);
-
-		while ((pending = readl(reg))) {
-			pin = __ffs(pending);
-			mask = BIT(pin);
-			/* Clear before handling so we can't lose an edge */
-			writel(mask, reg);
-
+		pending = readl(reg);
+		for_each_set_bit(pin, &pending, 32) {
 			virq = irq_find_mapping(vg->domain, base + pin);
 			generic_handle_irq(virq);
-
-			/* In case bios or user sets triggering incorretly a pin
-			 * might remain in "interrupt triggered" state.
-			 */
-			if (looplimit++ > 32) {
-				dev_err(&vg->pdev->dev,
-					"Gpio %d interrupt flood, disabling\n",
-					base + pin);
-
-				reg = byt_gpio_reg(&vg->chip, base + pin,
-						   BYT_CONF0_REG);
-				mask = readl(reg);
-				mask &= ~(BYT_TRIG_NEG | BYT_TRIG_POS |
-					  BYT_TRIG_LVL);
-				writel(mask, reg);
-				mask = readl(reg); /* flush */
-				break;
-			}
 		}
 	}
 	chip->irq_eoi(data);
 }
 
+static void byt_irq_ack(struct irq_data *d)
+{
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct byt_gpio *vg = to_byt_gpio(gc);
+	unsigned offset = irqd_to_hwirq(d);
+	void __iomem *reg;
+
+	raw_spin_lock(&byt_lock);
+	reg = byt_gpio_reg(&vg->chip, offset, BYT_INT_STAT_REG);
+	writel(BIT(offset % 32), reg);
+	raw_spin_unlock(&byt_lock);
+}
+
 static void byt_irq_unmask(struct irq_data *d)
 {
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct byt_gpio *vg = to_byt_gpio(gc);
+	unsigned offset = irqd_to_hwirq(d);
+	unsigned long flags;
+	void __iomem *reg;
+	u32 value;
+
+	raw_spin_lock_irqsave(&byt_lock, flags);
+
+	reg = byt_gpio_reg(&vg->chip, offset, BYT_CONF0_REG);
+	value = readl(reg);
+
+	switch (irqd_get_trigger_type(d)) {
+	case IRQ_TYPE_LEVEL_HIGH:
+		value |= BYT_TRIG_LVL;
+	case IRQ_TYPE_EDGE_RISING:
+		value |= BYT_TRIG_POS;
+		break;
+	case IRQ_TYPE_LEVEL_LOW:
+		value |= BYT_TRIG_LVL;
+	case IRQ_TYPE_EDGE_FALLING:
+		value |= BYT_TRIG_NEG;
+		break;
+	case IRQ_TYPE_EDGE_BOTH:
+		value |= (BYT_TRIG_NEG | BYT_TRIG_POS);
+		break;
+	}
+
+	writel(value, reg);
+
+	raw_spin_unlock_irqrestore(&byt_lock, flags);
 }
 
 static void byt_irq_mask(struct irq_data *d)
 {
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct byt_gpio *vg = to_byt_gpio(gc);
+
+	byt_gpio_clear_triggering(vg, irqd_to_hwirq(d));
 }
 
 static int byt_irq_reqres(struct irq_data *d)
@@ -476,6 +512,7 @@ static void byt_irq_relres(struct irq_data *d)
 
 static struct irq_chip byt_irqchip = {
 	.name = "BYT-GPIO",
+	.irq_ack = byt_irq_ack,
 	.irq_mask = byt_irq_mask,
 	.irq_unmask = byt_irq_unmask,
 	.irq_set_type = byt_irq_type,
@@ -487,6 +524,21 @@ static void byt_gpio_irq_init_hw(struct byt_gpio *vg)
 {
 	void __iomem *reg;
 	u32 base, value;
+	int i;
+
+	/*
+	 * Clear interrupt triggers for all pins that are GPIOs and
+	 * do not use direct IRQ mode. This will prevent spurious
+	 * interrupts from misconfigured pins.
+	 */
+	for (i = 0; i < vg->chip.ngpio; i++) {
+		value = readl(byt_gpio_reg(&vg->chip, i, BYT_CONF0_REG));
+		if ((value & BYT_PIN_MUX) == byt_get_gpio_mux(vg, i) &&
+		    !(value & BYT_DIRECT_IRQ_EN)) {
+			byt_gpio_clear_triggering(vg, i);
+			dev_dbg(&vg->pdev->dev, "disabling GPIO %d\n", i);
+		}
+	}
 
 	/* clear interrupt status trigger registers */
 	for (base = 0; base < vg->chip.ngpio; base += 32) {
@@ -558,8 +610,6 @@ static int byt_gpio_probe(struct platform_device *pdev)
 	if (IS_ERR(vg->reg_base))
 		return PTR_ERR(vg->reg_base);
 
-	spin_lock_init(&vg->lock);
-
 	gc = &vg->chip;
 	gc->label = dev_name(&pdev->dev);
 	gc->owner = THIS_MODULE;
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index 3c6ccedc82b6..53329896837f 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -386,13 +386,7 @@ static void kbd_led_update(struct work_struct *work)
 
 	asus = container_of(work, struct asus_wmi, kbd_led_work);
 
-	/*
-	 * bits 0-2: level
-	 * bit 7: light on/off
-	 */
-	if (asus->kbd_led_wk > 0)
-		ctrl_param = 0x80 | (asus->kbd_led_wk & 0x7F);
-
+	ctrl_param = 0x80 | (asus->kbd_led_wk & 0x7F);
 	asus_wmi_set_devstate(ASUS_WMI_DEVID_KBD_BACKLIGHT, ctrl_param, NULL);
 }
 
diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c
index d5f86dbf6dd6..7129e40e2788 100644
--- a/drivers/platform/x86/hp-wmi.c
+++ b/drivers/platform/x86/hp-wmi.c
@@ -309,7 +309,7 @@ static int __init hp_wmi_bios_2008_later(void)
 
 static int __init hp_wmi_bios_2009_later(void)
 {
-	int state = 0;
+	u8 state[128];
 	int ret = hp_wmi_perform_query(HPWMI_FEATURE2_QUERY, 0, &state,
 				       sizeof(state), sizeof(state));
 	if (!ret)
diff --git a/drivers/ptp/ptp_clock.c b/drivers/ptp/ptp_clock.c
index 296b0ec8744d..c72ee5966733 100644
--- a/drivers/ptp/ptp_clock.c
+++ b/drivers/ptp/ptp_clock.c
@@ -167,10 +167,11 @@ static struct posix_clock_operations ptp_clock_ops = {
 	.read		= ptp_read,
 };
 
-static void delete_ptp_clock(struct posix_clock *pc)
+static void ptp_clock_release(struct device *dev)
 {
-	struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock);
+	struct ptp_clock *ptp = container_of(dev, struct ptp_clock, dev);
 
+	ptp_cleanup_pin_groups(ptp);
 	mutex_destroy(&ptp->tsevq_mux);
 	mutex_destroy(&ptp->pincfg_mux);
 	ida_simple_remove(&ptp_clocks_map, ptp->index);
@@ -201,7 +202,6 @@ struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info,
 	}
 
 	ptp->clock.ops = ptp_clock_ops;
-	ptp->clock.release = delete_ptp_clock;
 	ptp->info = info;
 	ptp->devid = MKDEV(major, index);
 	ptp->index = index;
@@ -210,17 +210,9 @@ struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info,
 	mutex_init(&ptp->pincfg_mux);
 	init_waitqueue_head(&ptp->tsev_wq);
 
-	/* Create a new device in our class. */
-	ptp->dev = device_create(ptp_class, parent, ptp->devid, ptp,
-				 "ptp%d", ptp->index);
-	if (IS_ERR(ptp->dev))
-		goto no_device;
-
-	dev_set_drvdata(ptp->dev, ptp);
-
-	err = ptp_populate_sysfs(ptp);
+	err = ptp_populate_pin_groups(ptp);
 	if (err)
-		goto no_sysfs;
+		goto no_pin_groups;
 
 	/* Register a new PPS source. */
 	if (info->pps) {
@@ -231,13 +223,24 @@ struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info,
 		pps.owner = info->owner;
 		ptp->pps_source = pps_register_source(&pps, PTP_PPS_DEFAULTS);
 		if (!ptp->pps_source) {
+			err = -EINVAL;
 			pr_err("failed to register pps source\n");
 			goto no_pps;
 		}
 	}
 
-	/* Create a posix clock. */
-	err = posix_clock_register(&ptp->clock, ptp->devid);
+	/* Initialize a new device of our class in our clock structure. */
+	device_initialize(&ptp->dev);
+	ptp->dev.devt = ptp->devid;
+	ptp->dev.class = ptp_class;
+	ptp->dev.parent = parent;
+	ptp->dev.groups = ptp->pin_attr_groups;
+	ptp->dev.release = ptp_clock_release;
+	dev_set_drvdata(&ptp->dev, ptp);
+	dev_set_name(&ptp->dev, "ptp%d", ptp->index);
+
+	/* Create a posix clock and link it to the device. */
+	err = posix_clock_register(&ptp->clock, &ptp->dev);
 	if (err) {
 		pr_err("failed to create posix clock\n");
 		goto no_clock;
@@ -249,10 +252,8 @@ struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info,
 	if (ptp->pps_source)
 		pps_unregister_source(ptp->pps_source);
 no_pps:
-	ptp_cleanup_sysfs(ptp);
-no_sysfs:
-	device_destroy(ptp_class, ptp->devid);
-no_device:
+	ptp_cleanup_pin_groups(ptp);
+no_pin_groups:
 	mutex_destroy(&ptp->tsevq_mux);
 	mutex_destroy(&ptp->pincfg_mux);
 no_slot:
@@ -270,10 +271,9 @@ int ptp_clock_unregister(struct ptp_clock *ptp)
 	/* Release the clock's resources. */
 	if (ptp->pps_source)
 		pps_unregister_source(ptp->pps_source);
-	ptp_cleanup_sysfs(ptp);
-	device_destroy(ptp_class, ptp->devid);
 
 	posix_clock_unregister(&ptp->clock);
+
 	return 0;
 }
 EXPORT_SYMBOL(ptp_clock_unregister);
diff --git a/drivers/ptp/ptp_private.h b/drivers/ptp/ptp_private.h
index 9c5d41421b65..15346e840caa 100644
--- a/drivers/ptp/ptp_private.h
+++ b/drivers/ptp/ptp_private.h
@@ -40,7 +40,7 @@ struct timestamp_event_queue {
 
 struct ptp_clock {
 	struct posix_clock clock;
-	struct device *dev;
+	struct device dev;
 	struct ptp_clock_info *info;
 	dev_t devid;
 	int index; /* index into clocks.map */
@@ -54,6 +54,8 @@ struct ptp_clock {
 	struct device_attribute *pin_dev_attr;
 	struct attribute **pin_attr;
 	struct attribute_group pin_attr_group;
+	/* 1st entry is a pointer to the real group, 2nd is NULL terminator */
+	const struct attribute_group *pin_attr_groups[2];
 };
 
 /*
@@ -94,8 +96,7 @@ uint ptp_poll(struct posix_clock *pc,
 
 extern const struct attribute_group *ptp_groups[];
 
-int ptp_cleanup_sysfs(struct ptp_clock *ptp);
-
-int ptp_populate_sysfs(struct ptp_clock *ptp);
+int ptp_populate_pin_groups(struct ptp_clock *ptp);
+void ptp_cleanup_pin_groups(struct ptp_clock *ptp);
 
 #endif
diff --git a/drivers/ptp/ptp_sysfs.c b/drivers/ptp/ptp_sysfs.c
index 302e626fe6b0..731d0423c8aa 100644
--- a/drivers/ptp/ptp_sysfs.c
+++ b/drivers/ptp/ptp_sysfs.c
@@ -46,27 +46,6 @@ PTP_SHOW_INT(n_periodic_outputs, n_per_out);
 PTP_SHOW_INT(n_programmable_pins, n_pins);
 PTP_SHOW_INT(pps_available, pps);
 
-static struct attribute *ptp_attrs[] = {
-	&dev_attr_clock_name.attr,
-	&dev_attr_max_adjustment.attr,
-	&dev_attr_n_alarms.attr,
-	&dev_attr_n_external_timestamps.attr,
-	&dev_attr_n_periodic_outputs.attr,
-	&dev_attr_n_programmable_pins.attr,
-	&dev_attr_pps_available.attr,
-	NULL,
-};
-
-static const struct attribute_group ptp_group = {
-	.attrs = ptp_attrs,
-};
-
-const struct attribute_group *ptp_groups[] = {
-	&ptp_group,
-	NULL,
-};
-
-
 static ssize_t extts_enable_store(struct device *dev,
 				  struct device_attribute *attr,
 				  const char *buf, size_t count)
@@ -91,6 +70,7 @@ static ssize_t extts_enable_store(struct device *dev,
 out:
 	return err;
 }
+static DEVICE_ATTR(extts_enable, 0220, NULL, extts_enable_store);
 
 static ssize_t extts_fifo_show(struct device *dev,
 			       struct device_attribute *attr, char *page)
@@ -124,6 +104,7 @@ static ssize_t extts_fifo_show(struct device *dev,
 	mutex_unlock(&ptp->tsevq_mux);
 	return cnt;
 }
+static DEVICE_ATTR(fifo, 0444, extts_fifo_show, NULL);
 
 static ssize_t period_store(struct device *dev,
 			    struct device_attribute *attr,
@@ -151,6 +132,7 @@ static ssize_t period_store(struct device *dev,
 out:
 	return err;
 }
+static DEVICE_ATTR(period, 0220, NULL, period_store);
 
 static ssize_t pps_enable_store(struct device *dev,
 				struct device_attribute *attr,
@@ -177,6 +159,57 @@ static ssize_t pps_enable_store(struct device *dev,
 out:
 	return err;
 }
+static DEVICE_ATTR(pps_enable, 0220, NULL, pps_enable_store);
+
+static struct attribute *ptp_attrs[] = {
+	&dev_attr_clock_name.attr,
+
+	&dev_attr_max_adjustment.attr,
+	&dev_attr_n_alarms.attr,
+	&dev_attr_n_external_timestamps.attr,
+	&dev_attr_n_periodic_outputs.attr,
+	&dev_attr_n_programmable_pins.attr,
+	&dev_attr_pps_available.attr,
+
+	&dev_attr_extts_enable.attr,
+	&dev_attr_fifo.attr,
+	&dev_attr_period.attr,
+	&dev_attr_pps_enable.attr,
+	NULL
+};
+
+static umode_t ptp_is_attribute_visible(struct kobject *kobj,
+					struct attribute *attr, int n)
+{
+	struct device *dev = kobj_to_dev(kobj);
+	struct ptp_clock *ptp = dev_get_drvdata(dev);
+	struct ptp_clock_info *info = ptp->info;
+	umode_t mode = attr->mode;
+
+	if (attr == &dev_attr_extts_enable.attr ||
+	    attr == &dev_attr_fifo.attr) {
+		if (!info->n_ext_ts)
+			mode = 0;
+	} else if (attr == &dev_attr_period.attr) {
+		if (!info->n_per_out)
+			mode = 0;
+	} else if (attr == &dev_attr_pps_enable.attr) {
+		if (!info->pps)
+			mode = 0;
+	}
+
+	return mode;
+}
+
+static const struct attribute_group ptp_group = {
+	.is_visible	= ptp_is_attribute_visible,
+	.attrs		= ptp_attrs,
+};
+
+const struct attribute_group *ptp_groups[] = {
+	&ptp_group,
+	NULL
+};
 
 static int ptp_pin_name2index(struct ptp_clock *ptp, const char *name)
 {
@@ -235,40 +268,14 @@ static ssize_t ptp_pin_store(struct device *dev, struct device_attribute *attr,
 	return count;
 }
 
-static DEVICE_ATTR(extts_enable, 0220, NULL, extts_enable_store);
-static DEVICE_ATTR(fifo,         0444, extts_fifo_show, NULL);
-static DEVICE_ATTR(period,       0220, NULL, period_store);
-static DEVICE_ATTR(pps_enable,   0220, NULL, pps_enable_store);
-
-int ptp_cleanup_sysfs(struct ptp_clock *ptp)
+int ptp_populate_pin_groups(struct ptp_clock *ptp)
 {
-	struct device *dev = ptp->dev;
-	struct ptp_clock_info *info = ptp->info;
-
-	if (info->n_ext_ts) {
-		device_remove_file(dev, &dev_attr_extts_enable);
-		device_remove_file(dev, &dev_attr_fifo);
-	}
-	if (info->n_per_out)
-		device_remove_file(dev, &dev_attr_period);
-
-	if (info->pps)
-		device_remove_file(dev, &dev_attr_pps_enable);
-
-	if (info->n_pins) {
-		sysfs_remove_group(&dev->kobj, &ptp->pin_attr_group);
-		kfree(ptp->pin_attr);
-		kfree(ptp->pin_dev_attr);
-	}
-	return 0;
-}
-
-static int ptp_populate_pins(struct ptp_clock *ptp)
-{
-	struct device *dev = ptp->dev;
 	struct ptp_clock_info *info = ptp->info;
 	int err = -ENOMEM, i, n_pins = info->n_pins;
 
+	if (!n_pins)
+		return 0;
+
 	ptp->pin_dev_attr = kzalloc(n_pins * sizeof(*ptp->pin_dev_attr),
 				    GFP_KERNEL);
 	if (!ptp->pin_dev_attr)
@@ -292,61 +299,18 @@ static int ptp_populate_pins(struct ptp_clock *ptp)
 	ptp->pin_attr_group.name = "pins";
 	ptp->pin_attr_group.attrs = ptp->pin_attr;
 
-	err = sysfs_create_group(&dev->kobj, &ptp->pin_attr_group);
-	if (err)
-		goto no_group;
+	ptp->pin_attr_groups[0] = &ptp->pin_attr_group;
+
 	return 0;
 
-no_group:
-	kfree(ptp->pin_attr);
 no_pin_attr:
 	kfree(ptp->pin_dev_attr);
 no_dev_attr:
 	return err;
 }
 
-int ptp_populate_sysfs(struct ptp_clock *ptp)
+void ptp_cleanup_pin_groups(struct ptp_clock *ptp)
 {
-	struct device *dev = ptp->dev;
-	struct ptp_clock_info *info = ptp->info;
-	int err;
-
-	if (info->n_ext_ts) {
-		err = device_create_file(dev, &dev_attr_extts_enable);
-		if (err)
-			goto out1;
-		err = device_create_file(dev, &dev_attr_fifo);
-		if (err)
-			goto out2;
-	}
-	if (info->n_per_out) {
-		err = device_create_file(dev, &dev_attr_period);
-		if (err)
-			goto out3;
-	}
-	if (info->pps) {
-		err = device_create_file(dev, &dev_attr_pps_enable);
-		if (err)
-			goto out4;
-	}
-	if (info->n_pins) {
-		err = ptp_populate_pins(ptp);
-		if (err)
-			goto out5;
-	}
-	return 0;
-out5:
-	if (info->pps)
-		device_remove_file(dev, &dev_attr_pps_enable);
-out4:
-	if (info->n_per_out)
-		device_remove_file(dev, &dev_attr_period);
-out3:
-	if (info->n_ext_ts)
-		device_remove_file(dev, &dev_attr_fifo);
-out2:
-	if (info->n_ext_ts)
-		device_remove_file(dev, &dev_attr_extts_enable);
-out1:
-	return err;
+	kfree(ptp->pin_attr);
+	kfree(ptp->pin_dev_attr);
 }
diff --git a/drivers/scsi/fnic/vnic_dev.c b/drivers/scsi/fnic/vnic_dev.c
index 9795d6f3e197..4532ef9b46de 100644
--- a/drivers/scsi/fnic/vnic_dev.c
+++ b/drivers/scsi/fnic/vnic_dev.c
@@ -445,26 +445,26 @@ int vnic_dev_soft_reset_done(struct vnic_dev *vdev, int *done)
 
 int vnic_dev_hang_notify(struct vnic_dev *vdev)
 {
-	u64 a0, a1;
+	u64 a0 = 0, a1 = 0;
 	int wait = 1000;
 	return vnic_dev_cmd(vdev, CMD_HANG_NOTIFY, &a0, &a1, wait);
 }
 
 int vnic_dev_mac_addr(struct vnic_dev *vdev, u8 *mac_addr)
 {
-	u64 a0, a1;
+	u64 a[2] = {};
 	int wait = 1000;
 	int err, i;
 
 	for (i = 0; i < ETH_ALEN; i++)
 		mac_addr[i] = 0;
 
-	err = vnic_dev_cmd(vdev, CMD_MAC_ADDR, &a0, &a1, wait);
+	err = vnic_dev_cmd(vdev, CMD_MAC_ADDR, &a[0], &a[1], wait);
 	if (err)
 		return err;
 
 	for (i = 0; i < ETH_ALEN; i++)
-		mac_addr[i] = ((u8 *)&a0)[i];
+		mac_addr[i] = ((u8 *)&a)[i];
 
 	return 0;
 }
@@ -489,15 +489,15 @@ void vnic_dev_packet_filter(struct vnic_dev *vdev, int directed, int multicast,
 
 void vnic_dev_add_addr(struct vnic_dev *vdev, u8 *addr)
 {
-	u64 a0 = 0, a1 = 0;
+	u64 a[2] = {};
 	int wait = 1000;
 	int err;
 	int i;
 
 	for (i = 0; i < ETH_ALEN; i++)
-		((u8 *)&a0)[i] = addr[i];
+		((u8 *)&a)[i] = addr[i];
 
-	err = vnic_dev_cmd(vdev, CMD_ADDR_ADD, &a0, &a1, wait);
+	err = vnic_dev_cmd(vdev, CMD_ADDR_ADD, &a[0], &a[1], wait);
 	if (err)
 		printk(KERN_ERR
 			"Can't add addr [%02x:%02x:%02x:%02x:%02x:%02x], %d\n",
@@ -507,15 +507,15 @@ void vnic_dev_add_addr(struct vnic_dev *vdev, u8 *addr)
 
 void vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr)
 {
-	u64 a0 = 0, a1 = 0;
+	u64 a[2] = {};
 	int wait = 1000;
 	int err;
 	int i;
 
 	for (i = 0; i < ETH_ALEN; i++)
-		((u8 *)&a0)[i] = addr[i];
+		((u8 *)&a)[i] = addr[i];
 
-	err = vnic_dev_cmd(vdev, CMD_ADDR_DEL, &a0, &a1, wait);
+	err = vnic_dev_cmd(vdev, CMD_ADDR_DEL, &a[0], &a[1], wait);
 	if (err)
 		printk(KERN_ERR
 			"Can't del addr [%02x:%02x:%02x:%02x:%02x:%02x], %d\n",
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index 91bceca76aa9..dc7c7c17b272 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -4269,7 +4269,6 @@ static int qla4xxx_mem_alloc(struct scsi_qla_host *ha)
 	return QLA_SUCCESS;
 
 mem_alloc_error_exit:
-	qla4xxx_mem_free(ha);
 	return QLA_ERROR;
 }
 
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 2fcda75ef688..34bfd7ebc664 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -1910,8 +1910,10 @@ static int sd_read_protection_type(struct scsi_disk *sdkp, unsigned char *buffer
 	u8 type;
 	int ret = 0;
 
-	if (scsi_device_protection(sdp) == 0 || (buffer[12] & 1) == 0)
+	if (scsi_device_protection(sdp) == 0 || (buffer[12] & 1) == 0) {
+		sdkp->protection_type = 0;
 		return ret;
+	}
 
 	type = ((buffer[12] >> 1) & 7) + 1; /* P_TYPE 0 = Type 1 */
 
diff --git a/drivers/staging/android/ashmem.c b/drivers/staging/android/ashmem.c
index 5dbc68da8727..610981e49b51 100644
--- a/drivers/staging/android/ashmem.c
+++ b/drivers/staging/android/ashmem.c
@@ -351,8 +351,23 @@ static inline vm_flags_t calc_vm_may_flags(unsigned long prot)
 	       _calc_vm_trans(prot, PROT_EXEC,  VM_MAYEXEC);
 }
 
+static int ashmem_vmfile_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	/* do not allow to mmap ashmem backing shmem file directly */
+	return -EPERM;
+}
+
+static unsigned long
+ashmem_vmfile_get_unmapped_area(struct file *file, unsigned long addr,
+				unsigned long len, unsigned long pgoff,
+				unsigned long flags)
+{
+	return current->mm->get_unmapped_area(file, addr, len, pgoff, flags);
+}
+
 static int ashmem_mmap(struct file *file, struct vm_area_struct *vma)
 {
+	static struct file_operations vmfile_fops;
 	struct ashmem_area *asma = file->private_data;
 	int ret = 0;
 
@@ -386,6 +401,19 @@ static int ashmem_mmap(struct file *file, struct vm_area_struct *vma)
 			goto out;
 		}
 		asma->file = vmfile;
+		/*
+		 * override mmap operation of the vmfile so that it can't be
+		 * remapped which would lead to creation of a new vma with no
+		 * asma permission checks. Have to override get_unmapped_area
+		 * as well to prevent VM_BUG_ON check for f_ops modification.
+		 */
+		if (!vmfile_fops.mmap) {
+			vmfile_fops = *vmfile->f_op;
+			vmfile_fops.mmap = ashmem_vmfile_mmap;
+			vmfile_fops.get_unmapped_area =
+					ashmem_vmfile_get_unmapped_area;
+		}
+		vmfile->f_op = &vmfile_fops;
 	}
 	get_file(asma->file);
 
diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c
index 1000e87faa73..df88448d1eaa 100644
--- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c
+++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c
@@ -61,6 +61,7 @@ static struct usb_device_id rtw_usb_id_tbl[] = {
 	{USB_DEVICE(0x2001, 0x3311)}, /* DLink GO-USB-N150 REV B1 */
 	{USB_DEVICE(0x2001, 0x331B)}, /* D-Link DWA-121 rev B1 */
 	{USB_DEVICE(0x2357, 0x010c)}, /* TP-Link TL-WN722N v2 */
+	{USB_DEVICE(0x2357, 0x0111)}, /* TP-Link TL-WN727N v5.21 */
 	{USB_DEVICE(0x0df6, 0x0076)}, /* Sitecom N150 v2 */
 	{USB_DEVICE(USB_VENDER_ID_REALTEK, 0xffef)}, /* Rosewill RNX-N150NUB */
 	{}	/* Terminating entry */
@@ -141,7 +142,7 @@ static struct dvobj_priv *usb_dvobj_init(struct usb_interface *usb_intf)
 	phost_conf = pusbd->actconfig;
 	pconf_desc = &phost_conf->desc;
 
-	phost_iface = &usb_intf->altsetting[0];
+	phost_iface = usb_intf->cur_altsetting;
 	piface_desc = &phost_iface->desc;
 
 	pdvobjpriv->NumInterfaces = pconf_desc->bNumInterfaces;
diff --git a/drivers/staging/rtl8712/usb_intf.c b/drivers/staging/rtl8712/usb_intf.c
index 22a28becf275..af79582dbc28 100644
--- a/drivers/staging/rtl8712/usb_intf.c
+++ b/drivers/staging/rtl8712/usb_intf.c
@@ -269,7 +269,7 @@ static uint r8712_usb_dvobj_init(struct _adapter *padapter)
 	pdev_desc = &pusbd->descriptor;
 	phost_conf = pusbd->actconfig;
 	pconf_desc = &phost_conf->desc;
-	phost_iface = &pintf->altsetting[0];
+	phost_iface = pintf->cur_altsetting;
 	piface_desc = &phost_iface->desc;
 	pdvobjpriv->nr_endpoint = piface_desc->bNumEndpoints;
 	if (pusbd->speed == USB_SPEED_HIGH) {
diff --git a/drivers/staging/usbip/vhci_rx.c b/drivers/staging/usbip/vhci_rx.c
index d573917f998c..d9e0c76ead6e 100644
--- a/drivers/staging/usbip/vhci_rx.c
+++ b/drivers/staging/usbip/vhci_rx.c
@@ -88,16 +88,21 @@ static void vhci_recv_ret_submit(struct vhci_device *vdev,
 	usbip_pack_pdu(pdu, urb, USBIP_RET_SUBMIT, 0);
 
 	/* recv transfer buffer */
-	if (usbip_recv_xbuff(ud, urb) < 0)
-		return;
+	if (usbip_recv_xbuff(ud, urb) < 0) {
+		urb->status = -EPROTO;
+		goto error;
+	}
 
 	/* recv iso_packet_descriptor */
-	if (usbip_recv_iso(ud, urb) < 0)
-		return;
+	if (usbip_recv_iso(ud, urb) < 0) {
+		urb->status = -EPROTO;
+		goto error;
+	}
 
 	/* restore the padding in iso packets */
 	usbip_pad_iso(ud, urb);
 
+error:
 	if (usbip_dbg_flag_vhci_rx)
 		usbip_dump_urb(urb);
 
diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c
index 1c438396c630..15bf626abd8b 100644
--- a/drivers/tty/serial/msm_serial.c
+++ b/drivers/tty/serial/msm_serial.c
@@ -857,6 +857,7 @@ static void msm_console_write(struct console *co, const char *s,
 	struct msm_port *msm_port;
 	int num_newlines = 0;
 	bool replaced = false;
+	int locked = 1;
 
 	BUG_ON(co->index < 0 || co->index >= UART_NR);
 
@@ -869,7 +870,13 @@ static void msm_console_write(struct console *co, const char *s,
 			num_newlines++;
 	count += num_newlines;
 
-	spin_lock(&port->lock);
+	if (port->sysrq)
+		locked = 0;
+	else if (oops_in_progress)
+		locked = spin_trylock(&port->lock);
+	else
+		spin_lock(&port->lock);
+
 	if (msm_port->is_uartdm)
 		reset_dm_count(port, count);
 
@@ -906,7 +913,9 @@ static void msm_console_write(struct console *co, const char *s,
 		msm_write(port, *bf, msm_port->is_uartdm ? UARTDM_TF : UART_TF);
 		i += num_chars;
 	}
-	spin_unlock(&port->lock);
+
+	if (locked)
+		spin_unlock(&port->lock);
 }
 
 static int __init msm_console_setup(struct console *co, char *options)
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 6b71032b8123..1726bab49e40 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -2639,6 +2639,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
 		lockdep_set_class(&uport->lock, &port_lock_key);
 	}
 
+	tty_port_link_device(port, drv->tty_driver, uport->line);
 	uart_configure_port(drv, state, uport);
 
 	/*
diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c
index ea27804d87af..4e0c3d95884b 100644
--- a/drivers/tty/vt/selection.c
+++ b/drivers/tty/vt/selection.c
@@ -13,6 +13,7 @@
 #include <linux/tty.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
+#include <linux/mutex.h>
 #include <linux/slab.h>
 #include <linux/types.h>
 
@@ -40,6 +41,7 @@ static volatile int sel_start = -1; 	/* cleared by clear_selection */
 static int sel_end;
 static int sel_buffer_lth;
 static char *sel_buffer;
+static DEFINE_MUTEX(sel_lock);
 
 /* clear_selection, highlight and highlight_pointer can be called
    from interrupt (via scrollback/front) */
@@ -156,14 +158,14 @@ static int store_utf8(u16 c, char *p)
  *	The entire selection process is managed under the console_lock. It's
  *	 a lot under the lock but its hardly a performance path
  */
-int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *tty)
+static int __set_selection(const struct tiocl_selection __user *sel, struct tty_struct *tty)
 {
 	struct vc_data *vc = vc_cons[fg_console].d;
 	int sel_mode, new_sel_start, new_sel_end, spc;
 	char *bp, *obp;
 	int i, ps, pe, multiplier;
 	u16 c;
-	int mode;
+	int mode, ret = 0;
 
 	poke_blanked_console();
 
@@ -324,7 +326,21 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t
 		}
 	}
 	sel_buffer_lth = bp - sel_buffer;
-	return 0;
+
+	return ret;
+}
+
+int set_selection(const struct tiocl_selection __user *v, struct tty_struct *tty)
+{
+	int ret;
+
+	mutex_lock(&sel_lock);
+	console_lock();
+	ret = __set_selection(v, tty);
+	console_unlock();
+	mutex_unlock(&sel_lock);
+
+	return ret;
 }
 
 /* Insert the contents of the selection buffer into the
@@ -341,6 +357,7 @@ int paste_selection(struct tty_struct *tty)
 	unsigned int count;
 	struct  tty_ldisc *ld;
 	DECLARE_WAITQUEUE(wait, current);
+	int ret = 0;
 
 	console_lock();
 	poke_blanked_console();
@@ -350,21 +367,30 @@ int paste_selection(struct tty_struct *tty)
 	tty_buffer_lock_exclusive(&vc->port);
 
 	add_wait_queue(&vc->paste_wait, &wait);
+	mutex_lock(&sel_lock);
 	while (sel_buffer && sel_buffer_lth > pasted) {
 		set_current_state(TASK_INTERRUPTIBLE);
+		if (signal_pending(current)) {
+			ret = -EINTR;
+			break;
+		}
 		if (test_bit(TTY_THROTTLED, &tty->flags)) {
+			mutex_unlock(&sel_lock);
 			schedule();
+			mutex_lock(&sel_lock);
 			continue;
 		}
+		__set_current_state(TASK_RUNNING);
 		count = sel_buffer_lth - pasted;
 		count = tty_ldisc_receive_buf(ld, sel_buffer + pasted, NULL,
 					      count);
 		pasted += count;
 	}
+	mutex_unlock(&sel_lock);
 	remove_wait_queue(&vc->paste_wait, &wait);
 	__set_current_state(TASK_RUNNING);
 
 	tty_buffer_unlock_exclusive(&vc->port);
 	tty_ldisc_deref(ld);
-	return 0;
+	return ret;
 }
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 6f5d249d454d..b9d4075ddc17 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -2670,9 +2670,7 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
 	switch (type)
 	{
 		case TIOCL_SETSEL:
-			console_lock();
 			ret = set_selection((struct tiocl_selection __user *)(p+1), tty);
-			console_unlock();
 			break;
 		case TIOCL_PASTESEL:
 			ret = paste_selection(tty);
diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c
index 5a459377574b..6038314056cd 100644
--- a/drivers/usb/atm/ueagle-atm.c
+++ b/drivers/usb/atm/ueagle-atm.c
@@ -2167,10 +2167,11 @@ static void uea_intr(struct urb *urb)
 /*
  * Start the modem : init the data and start kernel thread
  */
-static int uea_boot(struct uea_softc *sc)
+static int uea_boot(struct uea_softc *sc, struct usb_interface *intf)
 {
-	int ret, size;
 	struct intr_pkt *intr;
+	int ret = -ENOMEM;
+	int size;
 
 	uea_enters(INS_TO_USBDEV(sc));
 
@@ -2195,6 +2196,11 @@ static int uea_boot(struct uea_softc *sc)
 	if (UEA_CHIP_VERSION(sc) == ADI930)
 		load_XILINX_firmware(sc);
 
+	if (intf->cur_altsetting->desc.bNumEndpoints < 1) {
+		ret = -ENODEV;
+		goto err0;
+	}
+
 	intr = kmalloc(size, GFP_KERNEL);
 	if (!intr) {
 		uea_err(INS_TO_USBDEV(sc),
@@ -2211,8 +2217,7 @@ static int uea_boot(struct uea_softc *sc)
 	usb_fill_int_urb(sc->urb_int, sc->usb_dev,
 			 usb_rcvintpipe(sc->usb_dev, UEA_INTR_PIPE),
 			 intr, size, uea_intr, sc,
-			 sc->usb_dev->actconfig->interface[0]->altsetting[0].
-			 endpoint[0].desc.bInterval);
+			 intf->cur_altsetting->endpoint[0].desc.bInterval);
 
 	ret = usb_submit_urb(sc->urb_int, GFP_KERNEL);
 	if (ret < 0) {
@@ -2227,6 +2232,7 @@ static int uea_boot(struct uea_softc *sc)
 	sc->kthread = kthread_create(uea_kthread, sc, "ueagle-atm");
 	if (IS_ERR(sc->kthread)) {
 		uea_err(INS_TO_USBDEV(sc), "failed to create thread\n");
+		ret = PTR_ERR(sc->kthread);
 		goto err2;
 	}
 
@@ -2241,7 +2247,7 @@ static int uea_boot(struct uea_softc *sc)
 	kfree(intr);
 err0:
 	uea_leaves(INS_TO_USBDEV(sc));
-	return -ENOMEM;
+	return ret;
 }
 
 /*
@@ -2604,7 +2610,7 @@ static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf,
 	if (ret < 0)
 		goto error;
 
-	ret = uea_boot(sc);
+	ret = uea_boot(sc, intf);
 	if (ret < 0)
 		goto error_rm_grp;
 
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
index 872669da443e..4722b6a93a89 100644
--- a/drivers/usb/core/config.c
+++ b/drivers/usb/core/config.c
@@ -169,10 +169,60 @@ static const unsigned short super_speed_maxpacket_maxes[4] = {
 	[USB_ENDPOINT_XFER_INT] = 1024,
 };
 
-static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
-    int asnum, struct usb_host_interface *ifp, int num_ep,
-    unsigned char *buffer, int size)
+static bool endpoint_is_duplicate(struct usb_endpoint_descriptor *e1,
+		struct usb_endpoint_descriptor *e2)
 {
+	if (e1->bEndpointAddress == e2->bEndpointAddress)
+		return true;
+
+	if (usb_endpoint_xfer_control(e1) || usb_endpoint_xfer_control(e2)) {
+		if (usb_endpoint_num(e1) == usb_endpoint_num(e2))
+			return true;
+	}
+
+	return false;
+}
+
+/*
+ * Check for duplicate endpoint addresses in other interfaces and in the
+ * altsetting currently being parsed.
+ */
+static bool config_endpoint_is_duplicate(struct usb_host_config *config,
+		int inum, int asnum, struct usb_endpoint_descriptor *d)
+{
+	struct usb_endpoint_descriptor *epd;
+	struct usb_interface_cache *intfc;
+	struct usb_host_interface *alt;
+	int i, j, k;
+
+	for (i = 0; i < config->desc.bNumInterfaces; ++i) {
+		intfc = config->intf_cache[i];
+
+		for (j = 0; j < intfc->num_altsetting; ++j) {
+			alt = &intfc->altsetting[j];
+
+			if (alt->desc.bInterfaceNumber == inum &&
+					alt->desc.bAlternateSetting != asnum)
+				continue;
+
+			for (k = 0; k < alt->desc.bNumEndpoints; ++k) {
+				epd = &alt->endpoint[k].desc;
+
+				if (endpoint_is_duplicate(epd, d))
+					return true;
+			}
+		}
+	}
+
+	return false;
+}
+
+static int usb_parse_endpoint(struct device *ddev, int cfgno,
+		struct usb_host_config *config, int inum, int asnum,
+		struct usb_host_interface *ifp, int num_ep,
+		unsigned char *buffer, int size)
+{
+	struct usb_device *udev = to_usb_device(ddev);
 	unsigned char *buffer0 = buffer;
 	struct usb_endpoint_descriptor *d;
 	struct usb_host_endpoint *endpoint;
@@ -208,11 +258,18 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
 		goto skip_to_next_endpoint_or_interface_descriptor;
 
 	/* Check for duplicate endpoint addresses */
-	for (i = 0; i < ifp->desc.bNumEndpoints; ++i) {
-		if (ifp->endpoint[i].desc.bEndpointAddress ==
-		    d->bEndpointAddress) {
-			dev_warn(ddev, "config %d interface %d altsetting %d has a duplicate endpoint with address 0x%X, skipping\n",
-			    cfgno, inum, asnum, d->bEndpointAddress);
+	if (config_endpoint_is_duplicate(config, inum, asnum, d)) {
+		dev_warn(ddev, "config %d interface %d altsetting %d has a duplicate endpoint with address 0x%X, skipping\n",
+				cfgno, inum, asnum, d->bEndpointAddress);
+		goto skip_to_next_endpoint_or_interface_descriptor;
+	}
+
+	/* Ignore blacklisted endpoints */
+	if (udev->quirks & USB_QUIRK_ENDPOINT_BLACKLIST) {
+		if (usb_endpoint_is_blacklisted(udev, ifp, d)) {
+			dev_warn(ddev, "config %d interface %d altsetting %d has a blacklisted endpoint with address 0x%X, skipping\n",
+					cfgno, inum, asnum,
+					d->bEndpointAddress);
 			goto skip_to_next_endpoint_or_interface_descriptor;
 		}
 	}
@@ -481,8 +538,8 @@ static int usb_parse_interface(struct device *ddev, int cfgno,
 		if (((struct usb_descriptor_header *) buffer)->bDescriptorType
 		     == USB_DT_INTERFACE)
 			break;
-		retval = usb_parse_endpoint(ddev, cfgno, inum, asnum, alt,
-		    num_ep, buffer, size);
+		retval = usb_parse_endpoint(ddev, cfgno, config, inum, asnum,
+				alt, num_ep, buffer, size);
 		if (retval < 0)
 			return retval;
 		++n;
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 2e9e0012286b..464e4ac307a8 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1125,6 +1125,7 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
 			 * PORT_OVER_CURRENT is not. So check for any of them.
 			 */
 			if (udev || (portstatus & USB_PORT_STAT_CONNECTION) ||
+			    (portchange & USB_PORT_STAT_C_CONNECTION) ||
 			    (portstatus & USB_PORT_STAT_OVERCURRENT) ||
 			    (portchange & USB_PORT_STAT_C_OVERCURRENT))
 				set_bit(port1, hub->change_bits);
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
index 33772a954df6..312eee48cda1 100644
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -206,6 +206,10 @@ static const struct usb_device_id usb_quirk_list[] = {
 	{ USB_DEVICE(0x0904, 0x6103), .driver_info =
 			USB_QUIRK_LINEAR_FRAME_INTR_BINTERVAL },
 
+	/* Sound Devices USBPre2 */
+	{ USB_DEVICE(0x0926, 0x0202), .driver_info =
+			USB_QUIRK_ENDPOINT_BLACKLIST },
+
 	/* Keytouch QWERTY Panel keyboard */
 	{ USB_DEVICE(0x0926, 0x3333), .driver_info =
 			USB_QUIRK_CONFIG_INTF_STRINGS },
@@ -318,6 +322,39 @@ static const struct usb_device_id usb_amd_resume_quirk_list[] = {
 	{ }  /* terminating entry must be last */
 };
 
+/*
+ * Entries for blacklisted endpoints that should be ignored when parsing
+ * configuration descriptors.
+ *
+ * Matched for devices with USB_QUIRK_ENDPOINT_BLACKLIST.
+ */
+static const struct usb_device_id usb_endpoint_blacklist[] = {
+	{ USB_DEVICE_INTERFACE_NUMBER(0x0926, 0x0202, 1), .driver_info = 0x85 },
+	{ }
+};
+
+bool usb_endpoint_is_blacklisted(struct usb_device *udev,
+		struct usb_host_interface *intf,
+		struct usb_endpoint_descriptor *epd)
+{
+	const struct usb_device_id *id;
+	unsigned int address;
+
+	for (id = usb_endpoint_blacklist; id->match_flags; ++id) {
+		if (!usb_match_device(udev, id))
+			continue;
+
+		if (!usb_match_one_id_intf(udev, intf, id))
+			continue;
+
+		address = id->driver_info;
+		if (address == epd->bEndpointAddress)
+			return true;
+	}
+
+	return false;
+}
+
 static bool usb_match_any_interface(struct usb_device *udev,
 				    const struct usb_device_id *id)
 {
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index ce5f13d62b64..65ffab5e9a8d 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -40,6 +40,7 @@ void usb_init_urb(struct urb *urb)
 	if (urb) {
 		memset(urb, 0, sizeof(*urb));
 		kref_init(&urb->kref);
+		INIT_LIST_HEAD(&urb->urb_list);
 		INIT_LIST_HEAD(&urb->anchor_list);
 	}
 }
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index d7ac1603826b..283de7f3840e 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -29,6 +29,9 @@ extern int usb_deauthorize_device(struct usb_device *);
 extern int usb_authorize_device(struct usb_device *);
 extern void usb_detect_quirks(struct usb_device *udev);
 extern void usb_detect_interface_quirks(struct usb_device *udev);
+extern bool usb_endpoint_is_blacklisted(struct usb_device *udev,
+		struct usb_host_interface *intf,
+		struct usb_endpoint_descriptor *epd);
 extern int usb_remove_device(struct usb_device *udev);
 
 extern int usb_get_device_descriptor(struct usb_device *dev,
diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c
index 69f27169081b..1b1ef79f02fa 100644
--- a/drivers/usb/dwc3/dwc3-pci.c
+++ b/drivers/usb/dwc3/dwc3-pci.c
@@ -30,6 +30,21 @@
 #define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3	0xabcd
 #define PCI_DEVICE_ID_INTEL_BYT		0x0f37
 #define PCI_DEVICE_ID_INTEL_MRFLD	0x119e
+#define PCI_DEVICE_ID_INTEL_BSW		0x22B7
+#define PCI_DEVICE_ID_INTEL_SPTLP	0x9d30
+#define PCI_DEVICE_ID_INTEL_SPTH	0xa130
+#define PCI_DEVICE_ID_INTEL_BXT		0x0aaa
+#define PCI_DEVICE_ID_INTEL_BXT_M	0x1aaa
+#define PCI_DEVICE_ID_INTEL_APL		0x5aaa
+#define PCI_DEVICE_ID_INTEL_KBP		0xa2b0
+#define PCI_DEVICE_ID_INTEL_CMLLP	0x02ee
+#define PCI_DEVICE_ID_INTEL_CMLH	0x06ee
+#define PCI_DEVICE_ID_INTEL_GLK		0x31aa
+#define PCI_DEVICE_ID_INTEL_CNPLP	0x9dee
+#define PCI_DEVICE_ID_INTEL_CNPH	0xa36e
+#define PCI_DEVICE_ID_INTEL_ICLLP	0x34ee
+#define PCI_DEVICE_ID_INTEL_EHLLP	0x4b7e
+#define PCI_DEVICE_ID_INTEL_TGPLP	0xa0ee
 
 struct dwc3_pci {
 	struct device		*dev;
@@ -183,8 +198,23 @@ static const struct pci_device_id dwc3_pci_id_table[] = {
 		PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS,
 				PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3),
 	},
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BSW), },
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BYT), },
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MRFLD), },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CMLLP), },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CMLH), },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SPTLP), },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SPTH), },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BXT), },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BXT_M), },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_APL), },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_KBP), },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_GLK), },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CNPLP), },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CNPH), },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICLLP), },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EHLLP), },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TGPLP), },
 	{  }	/* Terminating Entry */
 };
 MODULE_DEVICE_TABLE(pci, dwc3_pci_id_table);
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index 54f5332f814d..230c56d40557 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -40,6 +40,10 @@
 
 /*-------------------------------------------------------------------------*/
 
+/* PID Codes that are used here, from EHCI specification, Table 3-16. */
+#define PID_CODE_IN    1
+#define PID_CODE_SETUP 2
+
 /* fill a qtd, returning how much of the buffer we were able to queue up */
 
 static int
@@ -199,7 +203,7 @@ static int qtd_copy_status (
 	int	status = -EINPROGRESS;
 
 	/* count IN/OUT bytes, not SETUP (even short packets) */
-	if (likely (QTD_PID (token) != 2))
+	if (likely(QTD_PID(token) != PID_CODE_SETUP))
 		urb->actual_length += length - QTD_LENGTH (token);
 
 	/* don't modify error codes */
@@ -215,6 +219,13 @@ static int qtd_copy_status (
 		if (token & QTD_STS_BABBLE) {
 			/* FIXME "must" disable babbling device's port too */
 			status = -EOVERFLOW;
+		/*
+		 * When MMF is active and PID Code is IN, queue is halted.
+		 * EHCI Specification, Table 4-13.
+		 */
+		} else if ((token & QTD_STS_MMF) &&
+					(QTD_PID(token) == PID_CODE_IN)) {
+			status = -EPROTO;
 		/* CERR nonzero + halt --> stall */
 		} else if (QTD_CERR(token)) {
 			status = -EPIPE;
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 79dabb14c2bf..d527dcebed81 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -580,7 +580,7 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
 		struct xhci_bus_state *bus_state,
 		__le32 __iomem **port_array,
 		u16 wIndex, u32 raw_port_status,
-		unsigned long flags)
+		unsigned long *flags)
 	__releases(&xhci->lock)
 	__acquires(&xhci->lock)
 {
@@ -670,12 +670,12 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
 			xhci_set_link_state(xhci, port_array, wIndex,
 					XDEV_U0);
 
-			spin_unlock_irqrestore(&xhci->lock, flags);
+			spin_unlock_irqrestore(&xhci->lock, *flags);
 			time_left = wait_for_completion_timeout(
 					&bus_state->rexit_done[wIndex],
 					msecs_to_jiffies(
 						XHCI_MAX_REXIT_TIMEOUT_MS));
-			spin_lock_irqsave(&xhci->lock, flags);
+			spin_lock_irqsave(&xhci->lock, *flags);
 
 			if (time_left) {
 				slot_id = xhci_find_slot_id_by_port(hcd,
@@ -834,7 +834,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 			break;
 		}
 		status = xhci_get_port_status(hcd, bus_state, port_array,
-				wIndex, temp, flags);
+				wIndex, temp, &flags);
 		if (status == 0xffffffff)
 			goto error;
 
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index ae3b2b5fa9f6..0d18385f85bb 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -2345,7 +2345,8 @@ static int handle_tx_event(struct xhci_hcd *xhci,
 	case COMP_SUCCESS:
 		if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) == 0)
 			break;
-		if (xhci->quirks & XHCI_TRUST_TX_LENGTH)
+		if (xhci->quirks & XHCI_TRUST_TX_LENGTH ||
+		    ep_ring->last_td_was_short)
 			trb_comp_code = COMP_SHORT_TX;
 		else
 			xhci_warn_ratelimited(xhci,
diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c
index 684ce2ad1a39..ab5be88930d7 100644
--- a/drivers/usb/misc/adutux.c
+++ b/drivers/usb/misc/adutux.c
@@ -682,7 +682,7 @@ static int adu_probe(struct usb_interface *interface,
 	init_waitqueue_head(&dev->read_wait);
 	init_waitqueue_head(&dev->write_wait);
 
-	iface_desc = &interface->altsetting[0];
+	iface_desc = interface->cur_altsetting;
 
 	/* set up the endpoint information */
 	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
diff --git a/drivers/usb/misc/idmouse.c b/drivers/usb/misc/idmouse.c
index 6d4e75785710..066dce850cc6 100644
--- a/drivers/usb/misc/idmouse.c
+++ b/drivers/usb/misc/idmouse.c
@@ -342,7 +342,7 @@ static int idmouse_probe(struct usb_interface *interface,
 	int result;
 
 	/* check if we have gotten the data or the hid interface */
-	iface_desc = &interface->altsetting[0];
+	iface_desc = interface->cur_altsetting;
 	if (iface_desc->desc.bInterfaceClass != 0x0A)
 		return -ENODEV;
 
diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c
index bbec84dd34fb..4c5aa817162f 100644
--- a/drivers/usb/mon/mon_bin.c
+++ b/drivers/usb/mon/mon_bin.c
@@ -1034,12 +1034,18 @@ static long mon_bin_ioctl(struct file *file, unsigned int cmd, unsigned long arg
 
 		mutex_lock(&rp->fetch_lock);
 		spin_lock_irqsave(&rp->b_lock, flags);
-		mon_free_buff(rp->b_vec, rp->b_size/CHUNK_SIZE);
-		kfree(rp->b_vec);
-		rp->b_vec  = vec;
-		rp->b_size = size;
-		rp->b_read = rp->b_in = rp->b_out = rp->b_cnt = 0;
-		rp->cnt_lost = 0;
+		if (rp->mmap_active) {
+			mon_free_buff(vec, size/CHUNK_SIZE);
+			kfree(vec);
+			ret = -EBUSY;
+		} else {
+			mon_free_buff(rp->b_vec, rp->b_size/CHUNK_SIZE);
+			kfree(rp->b_vec);
+			rp->b_vec  = vec;
+			rp->b_size = size;
+			rp->b_read = rp->b_in = rp->b_out = rp->b_cnt = 0;
+			rp->cnt_lost = 0;
+		}
 		spin_unlock_irqrestore(&rp->b_lock, flags);
 		mutex_unlock(&rp->fetch_lock);
 		}
@@ -1211,13 +1217,21 @@ mon_bin_poll(struct file *file, struct poll_table_struct *wait)
 static void mon_bin_vma_open(struct vm_area_struct *vma)
 {
 	struct mon_reader_bin *rp = vma->vm_private_data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&rp->b_lock, flags);
 	rp->mmap_active++;
+	spin_unlock_irqrestore(&rp->b_lock, flags);
 }
 
 static void mon_bin_vma_close(struct vm_area_struct *vma)
 {
+	unsigned long flags;
+
 	struct mon_reader_bin *rp = vma->vm_private_data;
+	spin_lock_irqsave(&rp->b_lock, flags);
 	rp->mmap_active--;
+	spin_unlock_irqrestore(&rp->b_lock, flags);
 }
 
 /*
@@ -1229,16 +1243,12 @@ static int mon_bin_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 	unsigned long offset, chunk_idx;
 	struct page *pageptr;
 
-	mutex_lock(&rp->fetch_lock);
 	offset = vmf->pgoff << PAGE_SHIFT;
-	if (offset >= rp->b_size) {
-		mutex_unlock(&rp->fetch_lock);
+	if (offset >= rp->b_size)
 		return VM_FAULT_SIGBUS;
-	}
 	chunk_idx = offset / CHUNK_SIZE;
 	pageptr = rp->b_vec[chunk_idx].pg;
 	get_page(pageptr);
-	mutex_unlock(&rp->fetch_lock);
 	vmf->page = pageptr;
 	return 0;
 }
diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c
index d006f54d5e15..5edca85a491a 100644
--- a/drivers/usb/musb/musbhsdma.c
+++ b/drivers/usb/musb/musbhsdma.c
@@ -396,7 +396,7 @@ struct dma_controller *dma_controller_create(struct musb *musb, void __iomem *ba
 	controller->controller.channel_abort = dma_channel_abort;
 
 	if (request_irq(irq, dma_controller_irq, 0,
-			dev_name(musb->controller), &controller->controller)) {
+			dev_name(musb->controller), controller)) {
 		dev_err(dev, "request_irq %d failed!\n", irq);
 		dma_controller_destroy(&controller->controller);
 
diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c
index 83b2602c6ae1..9b0282cc927a 100644
--- a/drivers/usb/serial/ch341.c
+++ b/drivers/usb/serial/ch341.c
@@ -571,9 +571,13 @@ static int ch341_tiocmget(struct tty_struct *tty)
 static int ch341_reset_resume(struct usb_serial *serial)
 {
 	struct usb_serial_port *port = serial->port[0];
-	struct ch341_private *priv = usb_get_serial_port_data(port);
+	struct ch341_private *priv;
 	int ret;
 
+	priv = usb_get_serial_port_data(port);
+	if (!priv)
+		return 0;
+
 	/* reconfigure ch341 serial port after bus-reset */
 	ch341_configure(serial->dev, priv);
 
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index 6947985ccfb0..aea82f20deaa 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -638,7 +638,7 @@ static void edge_interrupt_callback(struct urb *urb)
 			if (txCredits) {
 				port = edge_serial->serial->port[portNumber];
 				edge_port = usb_get_serial_port_data(port);
-				if (edge_port->open) {
+				if (edge_port && edge_port->open) {
 					spin_lock(&edge_port->ep_lock);
 					edge_port->txCredits += txCredits;
 					spin_unlock(&edge_port->ep_lock);
@@ -1666,7 +1666,8 @@ static void edge_break(struct tty_struct *tty, int break_state)
 static void process_rcvd_data(struct edgeport_serial *edge_serial,
 				unsigned char *buffer, __u16 bufferLength)
 {
-	struct device *dev = &edge_serial->serial->dev->dev;
+	struct usb_serial *serial = edge_serial->serial;
+	struct device *dev = &serial->dev->dev;
 	struct usb_serial_port *port;
 	struct edgeport_port *edge_port;
 	__u16 lastBufferLength;
@@ -1771,11 +1772,10 @@ static void process_rcvd_data(struct edgeport_serial *edge_serial,
 
 			/* spit this data back into the tty driver if this
 			   port is open */
-			if (rxLen) {
-				port = edge_serial->serial->port[
-							edge_serial->rxPort];
+			if (rxLen && edge_serial->rxPort < serial->num_ports) {
+				port = serial->port[edge_serial->rxPort];
 				edge_port = usb_get_serial_port_data(port);
-				if (edge_port->open) {
+				if (edge_port && edge_port->open) {
 					dev_dbg(dev, "%s - Sending %d bytes to TTY for port %d\n",
 						__func__, rxLen,
 						edge_serial->rxPort);
@@ -1783,8 +1783,8 @@ static void process_rcvd_data(struct edgeport_serial *edge_serial,
 							rxLen);
 					edge_port->port->icount.rx += rxLen;
 				}
-				buffer += rxLen;
 			}
+			buffer += rxLen;
 			break;
 
 		case EXPECT_HDR3:	/* Expect 3rd byte of status header */
@@ -1819,6 +1819,8 @@ static void process_rcvd_status(struct edgeport_serial *edge_serial,
 	__u8 code = edge_serial->rxStatusCode;
 
 	/* switch the port pointer to the one being currently talked about */
+	if (edge_serial->rxPort >= edge_serial->serial->num_ports)
+		return;
 	port = edge_serial->serial->port[edge_serial->rxPort];
 	edge_port = usb_get_serial_port_data(port);
 	if (edge_port == NULL) {
@@ -2859,16 +2861,18 @@ static int edge_startup(struct usb_serial *serial)
 	response = 0;
 
 	if (edge_serial->is_epic) {
+		struct usb_host_interface *alt;
+
+		alt = serial->interface->cur_altsetting;
+
 		/* EPIC thing, set up our interrupt polling now and our read
 		 * urb, so that the device knows it really is connected. */
 		interrupt_in_found = bulk_in_found = bulk_out_found = false;
-		for (i = 0; i < serial->interface->altsetting[0]
-						.desc.bNumEndpoints; ++i) {
+		for (i = 0; i < alt->desc.bNumEndpoints; ++i) {
 			struct usb_endpoint_descriptor *endpoint;
 			int buffer_size;
 
-			endpoint = &serial->interface->altsetting[0].
-							endpoint[i].desc;
+			endpoint = &alt->endpoint[i].desc;
 			buffer_size = usb_endpoint_maxp(endpoint);
 			if (!interrupt_in_found &&
 			    (usb_endpoint_is_int_in(endpoint))) {
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index 38112be0dbae..f211d0792d63 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -962,6 +962,10 @@ static void usa67_glocont_callback(struct urb *urb)
 	for (i = 0; i < serial->num_ports; ++i) {
 		port = serial->port[i];
 		p_priv = usb_get_serial_port_data(port);
+		if (!p_priv)
+			continue;
+		if (!p_priv)
+			continue;
 
 		if (p_priv->resend_cont) {
 			dev_dbg(&port->dev, "%s - sending setup\n", __func__);
diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c
index 64bf258e7e00..9606dde3194c 100644
--- a/drivers/usb/serial/opticon.c
+++ b/drivers/usb/serial/opticon.c
@@ -116,7 +116,7 @@ static int send_control_msg(struct usb_serial_port *port, u8 requesttype,
 	retval = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
 				requesttype,
 				USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE,
-				0, 0, buffer, 1, 0);
+				0, 0, buffer, 1, USB_CTRL_SET_TIMEOUT);
 	kfree(buffer);
 
 	if (retval < 0)
diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c
index af0c87276299..82f28192694f 100644
--- a/drivers/usb/serial/quatech2.c
+++ b/drivers/usb/serial/quatech2.c
@@ -872,7 +872,10 @@ static void qt2_update_msr(struct usb_serial_port *port, unsigned char *ch)
 	u8 newMSR = (u8) *ch;
 	unsigned long flags;
 
+	/* May be called from qt2_process_read_urb() for an unbound port. */
 	port_priv = usb_get_serial_port_data(port);
+	if (!port_priv)
+		return;
 
 	spin_lock_irqsave(&port_priv->lock, flags);
 	port_priv->shadowMSR = newMSR;
@@ -900,7 +903,10 @@ static void qt2_update_lsr(struct usb_serial_port *port, unsigned char *ch)
 	unsigned long flags;
 	u8 newLSR = (u8) *ch;
 
+	/* May be called from qt2_process_read_urb() for an unbound port. */
 	port_priv = usb_get_serial_port_data(port);
+	if (!port_priv)
+		return;
 
 	if (newLSR & UART_LSR_BI)
 		newLSR &= (u8) (UART_LSR_OE | UART_LSR_BI);
diff --git a/drivers/usb/serial/usb-serial-simple.c b/drivers/usb/serial/usb-serial-simple.c
index 235733c69272..11d925bfdf1e 100644
--- a/drivers/usb/serial/usb-serial-simple.c
+++ b/drivers/usb/serial/usb-serial-simple.c
@@ -89,6 +89,8 @@ DEVICE(moto_modem, MOTO_IDS);
 #define MOTOROLA_TETRA_IDS()			\
 	{ USB_DEVICE(0x0cad, 0x9011) },	/* Motorola Solutions TETRA PEI */ \
 	{ USB_DEVICE(0x0cad, 0x9012) },	/* MTP6550 */ \
+	{ USB_DEVICE(0x0cad, 0x9013) },	/* MTP3xxx */ \
+	{ USB_DEVICE(0x0cad, 0x9015) },	/* MTP85xx */ \
 	{ USB_DEVICE(0x0cad, 0x9016) }	/* TPG2200 */
 DEVICE(motorola_tetra, MOTOROLA_TETRA_IDS);
 
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 97b9af49c1d2..f3ed3c65e855 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -1337,6 +1337,9 @@ static int usb_serial_register(struct usb_serial_driver *driver)
 		return -EINVAL;
 	}
 
+	/* Prevent individual ports from being unbound. */
+	driver->driver.suppress_bind_attrs = true;
+
 	usb_serial_operations_init(driver);
 
 	/* Add this device to our list of devices */
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index 3f16c299263f..c99c71afcd5c 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -843,11 +843,7 @@ static int vhost_net_release(struct inode *inode, struct file *f)
 
 static struct socket *get_raw_socket(int fd)
 {
-	struct {
-		struct sockaddr_ll sa;
-		char  buf[MAX_ADDR_LEN];
-	} uaddr;
-	int uaddr_len = sizeof uaddr, r;
+	int r;
 	struct socket *sock = sockfd_lookup(fd, &r);
 
 	if (!sock)
@@ -859,12 +855,7 @@ static struct socket *get_raw_socket(int fd)
 		goto err;
 	}
 
-	r = sock->ops->getname(sock, (struct sockaddr *)&uaddr.sa,
-			       &uaddr_len, 0);
-	if (r)
-		goto err;
-
-	if (uaddr.sa.sll_family != AF_PACKET) {
+	if (sock->sk->sk_family != AF_PACKET) {
 		r = -EPFNOSUPPORT;
 		goto err;
 	}
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 6e6aa704fe84..ba0ef937e517 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -1312,6 +1312,9 @@ static int vgacon_font_get(struct vc_data *c, struct console_font *font)
 static int vgacon_resize(struct vc_data *c, unsigned int width,
 			 unsigned int height, unsigned int user)
 {
+	if ((width << 1) * height > vga_vram_size)
+		return -EINVAL;
+
 	if (width % 2 || width > screen_info.orig_video_cols ||
 	    height > (screen_info.orig_video_lines * vga_default_font_height)/
 	    c->vc_font.height)
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
index 5ca1928979f6..341c025a230b 100644
--- a/drivers/virtio/virtio_balloon.c
+++ b/drivers/virtio/virtio_balloon.c
@@ -403,6 +403,16 @@ static int virtballoon_migratepage(struct address_space *mapping,
 
 	get_page(newpage); /* balloon reference */
 
+	/*
+	  * When we migrate a page to a different zone and adjusted the
+	  * managed page count when inflating, we have to fixup the count of
+	  * both involved zones.
+	  */
+	if (page_zone(page) != page_zone(newpage)) {
+		adjust_managed_page_count(page, 1);
+		adjust_managed_page_count(newpage, -1);
+	}
+
 	/* balloon's page migration 1st step  -- inflate "newpage" */
 	spin_lock_irqsave(&vb_dev_info->pages_lock, flags);
 	balloon_page_insert(newpage, mapping, &vb_dev_info->pages);
diff --git a/firmware/Makefile b/firmware/Makefile
index 0862d34cf7d1..3a678382b8cc 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -156,7 +156,7 @@ quiet_cmd_fwbin = MK_FW   $@
 		  PROGBITS=$(if $(CONFIG_ARM),%,@)progbits;		     \
 		  echo "/* Generated by firmware/Makefile */"		> $@;\
 		  echo "    .section .rodata"				>>$@;\
-		  echo "    .p2align $${ASM_ALIGN}"			>>$@;\
+		  echo "    .p2align 4"					>>$@;\
 		  echo "_fw_$${FWSTR}_bin:"				>>$@;\
 		  echo "    .incbin \"$(2)\""				>>$@;\
 		  echo "_fw_end:"					>>$@;\
diff --git a/fs/btrfs/Makefile b/fs/btrfs/Makefile
index 6d1d0b93b1aa..c792df826e12 100644
--- a/fs/btrfs/Makefile
+++ b/fs/btrfs/Makefile
@@ -9,7 +9,7 @@ btrfs-y += super.o ctree.o extent-tree.o print-tree.o root-tree.o dir-item.o \
 	   export.o tree-log.o free-space-cache.o zlib.o lzo.o \
 	   compression.o delayed-ref.o relocation.o delayed-inode.o scrub.o \
 	   reada.o backref.o ulist.o qgroup.o send.o dev-replace.o raid56.o \
-	   uuid-tree.o props.o hash.o
+	   uuid-tree.o props.o hash.o tree-checker.o
 
 btrfs-$(CONFIG_BTRFS_FS_POSIX_ACL) += acl.o
 btrfs-$(CONFIG_BTRFS_FS_CHECK_INTEGRITY) += check-integrity.o
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 8c65bac0c8a2..4d1766e5438a 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -418,7 +418,7 @@ void btrfs_put_tree_mod_seq(struct btrfs_fs_info *fs_info,
 	for (node = rb_first(tm_root); node; node = next) {
 		next = rb_next(node);
 		tm = container_of(node, struct tree_mod_elem, node);
-		if (tm->seq > min_seq)
+		if (tm->seq >= min_seq)
 			continue;
 		rb_erase(node, tm_root);
 		kfree(tm);
@@ -1721,20 +1721,6 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
 	return err;
 }
 
-/*
- * The leaf data grows from end-to-front in the node.
- * this returns the address of the start of the last item,
- * which is the stop of the leaf data stack
- */
-static inline unsigned int leaf_data_end(struct btrfs_root *root,
-					 struct extent_buffer *leaf)
-{
-	u32 nr = btrfs_header_nritems(leaf);
-	if (nr == 0)
-		return BTRFS_LEAF_DATA_SIZE(root);
-	return btrfs_item_offset_nr(leaf, nr - 1);
-}
-
 
 /*
  * search for key in the extent_buffer.  The items start at offset p,
@@ -4609,8 +4595,7 @@ void btrfs_truncate_item(struct btrfs_root *root, struct btrfs_path *path,
 				ptr = btrfs_item_ptr_offset(leaf, slot);
 				memmove_extent_buffer(leaf, ptr,
 				      (unsigned long)fi,
-				      offsetof(struct btrfs_file_extent_item,
-						 disk_bytenr));
+				      BTRFS_FILE_EXTENT_INLINE_DATA_START);
 			}
 		}
 
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 796f1d2374ff..6bcfc5a98548 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -34,6 +34,7 @@
 #include <linux/pagemap.h>
 #include <linux/btrfs.h>
 #include <linux/workqueue.h>
+#include <linux/sizes.h>
 #include "extent_io.h"
 #include "extent_map.h"
 #include "async-thread.h"
@@ -392,9 +393,11 @@ struct btrfs_header {
 				     sizeof(struct btrfs_key_ptr))
 #define __BTRFS_LEAF_DATA_SIZE(bs) ((bs) - sizeof(struct btrfs_header))
 #define BTRFS_LEAF_DATA_SIZE(r) (__BTRFS_LEAF_DATA_SIZE(r->leafsize))
+#define BTRFS_FILE_EXTENT_INLINE_DATA_START		\
+		(offsetof(struct btrfs_file_extent_item, disk_bytenr))
 #define BTRFS_MAX_INLINE_DATA_SIZE(r) (BTRFS_LEAF_DATA_SIZE(r) - \
 					sizeof(struct btrfs_item) - \
-					sizeof(struct btrfs_file_extent_item))
+					BTRFS_FILE_EXTENT_INLINE_DATA_START)
 #define BTRFS_MAX_XATTR_SIZE(r)	(BTRFS_LEAF_DATA_SIZE(r) - \
 				 sizeof(struct btrfs_item) -\
 				 sizeof(struct btrfs_dir_item))
@@ -872,6 +875,7 @@ struct btrfs_balance_item {
 #define BTRFS_FILE_EXTENT_INLINE 0
 #define BTRFS_FILE_EXTENT_REG 1
 #define BTRFS_FILE_EXTENT_PREALLOC 2
+#define BTRFS_FILE_EXTENT_TYPES	2
 
 struct btrfs_file_extent_item {
 	/*
@@ -904,6 +908,8 @@ struct btrfs_file_extent_item {
 	/*
 	 * disk space consumed by the extent, checksum blocks are included
 	 * in these numbers
+	 *
+	 * At this offset in the structure, the inline extent data start.
 	 */
 	__le64 disk_bytenr;
 	__le64 disk_num_bytes;
@@ -2134,7 +2140,7 @@ struct btrfs_ioctl_defrag_range_args {
 #define BTRFS_INODE_ROOT_ITEM_INIT	(1 << 31)
 
 struct btrfs_map_token {
-	struct extent_buffer *eb;
+	const struct extent_buffer *eb;
 	char *kaddr;
 	unsigned long offset;
 };
@@ -2165,18 +2171,19 @@ static inline void btrfs_init_map_token (struct btrfs_map_token *token)
 			   sizeof(((type *)0)->member)))
 
 #define DECLARE_BTRFS_SETGET_BITS(bits)					\
-u##bits btrfs_get_token_##bits(struct extent_buffer *eb, void *ptr,	\
-			       unsigned long off,			\
-                              struct btrfs_map_token *token);		\
-void btrfs_set_token_##bits(struct extent_buffer *eb, void *ptr,	\
+u##bits btrfs_get_token_##bits(const struct extent_buffer *eb,		\
+			       const void *ptr, unsigned long off,	\
+			       struct btrfs_map_token *token);		\
+void btrfs_set_token_##bits(struct extent_buffer *eb, const void *ptr,	\
 			    unsigned long off, u##bits val,		\
 			    struct btrfs_map_token *token);		\
-static inline u##bits btrfs_get_##bits(struct extent_buffer *eb, void *ptr, \
+static inline u##bits btrfs_get_##bits(const struct extent_buffer *eb,	\
+				       const void *ptr,			\
 				       unsigned long off)		\
 {									\
 	return btrfs_get_token_##bits(eb, ptr, off, NULL);		\
 }									\
-static inline void btrfs_set_##bits(struct extent_buffer *eb, void *ptr, \
+static inline void btrfs_set_##bits(struct extent_buffer *eb, void *ptr,\
 				    unsigned long off, u##bits val)	\
 {									\
        btrfs_set_token_##bits(eb, ptr, off, val, NULL);			\
@@ -2188,7 +2195,8 @@ DECLARE_BTRFS_SETGET_BITS(32)
 DECLARE_BTRFS_SETGET_BITS(64)
 
 #define BTRFS_SETGET_FUNCS(name, type, member, bits)			\
-static inline u##bits btrfs_##name(struct extent_buffer *eb, type *s)	\
+static inline u##bits btrfs_##name(const struct extent_buffer *eb,	\
+				   const type *s)			\
 {									\
 	BUILD_BUG_ON(sizeof(u##bits) != sizeof(((type *)0))->member);	\
 	return btrfs_get_##bits(eb, s, offsetof(type, member));		\
@@ -2199,7 +2207,8 @@ static inline void btrfs_set_##name(struct extent_buffer *eb, type *s,	\
 	BUILD_BUG_ON(sizeof(u##bits) != sizeof(((type *)0))->member);	\
 	btrfs_set_##bits(eb, s, offsetof(type, member), val);		\
 }									\
-static inline u##bits btrfs_token_##name(struct extent_buffer *eb, type *s, \
+static inline u##bits btrfs_token_##name(const struct extent_buffer *eb,\
+					 const type *s,			\
 					 struct btrfs_map_token *token)	\
 {									\
 	BUILD_BUG_ON(sizeof(u##bits) != sizeof(((type *)0))->member);	\
@@ -2214,9 +2223,9 @@ static inline void btrfs_set_token_##name(struct extent_buffer *eb,	\
 }
 
 #define BTRFS_SETGET_HEADER_FUNCS(name, type, member, bits)		\
-static inline u##bits btrfs_##name(struct extent_buffer *eb)		\
+static inline u##bits btrfs_##name(const struct extent_buffer *eb)	\
 {									\
-	type *p = page_address(eb->pages[0]);				\
+	const type *p = page_address(eb->pages[0]);			\
 	u##bits res = le##bits##_to_cpu(p->member);			\
 	return res;							\
 }									\
@@ -2228,7 +2237,7 @@ static inline void btrfs_set_##name(struct extent_buffer *eb,		\
 }
 
 #define BTRFS_SETGET_STACK_FUNCS(name, type, member, bits)		\
-static inline u##bits btrfs_##name(type *s)				\
+static inline u##bits btrfs_##name(const type *s)			\
 {									\
 	return le##bits##_to_cpu(s->member);				\
 }									\
@@ -2554,7 +2563,7 @@ static inline unsigned long btrfs_node_key_ptr_offset(int nr)
 		sizeof(struct btrfs_key_ptr) * nr;
 }
 
-void btrfs_node_key(struct extent_buffer *eb,
+void btrfs_node_key(const struct extent_buffer *eb,
 		    struct btrfs_disk_key *disk_key, int nr);
 
 static inline void btrfs_set_node_key(struct extent_buffer *eb,
@@ -2583,28 +2592,28 @@ static inline struct btrfs_item *btrfs_item_nr(int nr)
 	return (struct btrfs_item *)btrfs_item_nr_offset(nr);
 }
 
-static inline u32 btrfs_item_end(struct extent_buffer *eb,
+static inline u32 btrfs_item_end(const struct extent_buffer *eb,
 				 struct btrfs_item *item)
 {
 	return btrfs_item_offset(eb, item) + btrfs_item_size(eb, item);
 }
 
-static inline u32 btrfs_item_end_nr(struct extent_buffer *eb, int nr)
+static inline u32 btrfs_item_end_nr(const struct extent_buffer *eb, int nr)
 {
 	return btrfs_item_end(eb, btrfs_item_nr(nr));
 }
 
-static inline u32 btrfs_item_offset_nr(struct extent_buffer *eb, int nr)
+static inline u32 btrfs_item_offset_nr(const struct extent_buffer *eb, int nr)
 {
 	return btrfs_item_offset(eb, btrfs_item_nr(nr));
 }
 
-static inline u32 btrfs_item_size_nr(struct extent_buffer *eb, int nr)
+static inline u32 btrfs_item_size_nr(const struct extent_buffer *eb, int nr)
 {
 	return btrfs_item_size(eb, btrfs_item_nr(nr));
 }
 
-static inline void btrfs_item_key(struct extent_buffer *eb,
+static inline void btrfs_item_key(const struct extent_buffer *eb,
 			   struct btrfs_disk_key *disk_key, int nr)
 {
 	struct btrfs_item *item = btrfs_item_nr(nr);
@@ -2640,8 +2649,8 @@ BTRFS_SETGET_STACK_FUNCS(stack_dir_name_len, struct btrfs_dir_item,
 BTRFS_SETGET_STACK_FUNCS(stack_dir_transid, struct btrfs_dir_item,
 			 transid, 64);
 
-static inline void btrfs_dir_item_key(struct extent_buffer *eb,
-				      struct btrfs_dir_item *item,
+static inline void btrfs_dir_item_key(const struct extent_buffer *eb,
+				      const struct btrfs_dir_item *item,
 				      struct btrfs_disk_key *key)
 {
 	read_eb_member(eb, item, struct btrfs_dir_item, location, key);
@@ -2649,7 +2658,7 @@ static inline void btrfs_dir_item_key(struct extent_buffer *eb,
 
 static inline void btrfs_set_dir_item_key(struct extent_buffer *eb,
 					  struct btrfs_dir_item *item,
-					  struct btrfs_disk_key *key)
+					  const struct btrfs_disk_key *key)
 {
 	write_eb_member(eb, item, struct btrfs_dir_item, location, key);
 }
@@ -2661,8 +2670,8 @@ BTRFS_SETGET_FUNCS(free_space_bitmaps, struct btrfs_free_space_header,
 BTRFS_SETGET_FUNCS(free_space_generation, struct btrfs_free_space_header,
 		   generation, 64);
 
-static inline void btrfs_free_space_key(struct extent_buffer *eb,
-					struct btrfs_free_space_header *h,
+static inline void btrfs_free_space_key(const struct extent_buffer *eb,
+					const struct btrfs_free_space_header *h,
 					struct btrfs_disk_key *key)
 {
 	read_eb_member(eb, h, struct btrfs_free_space_header, location, key);
@@ -2670,7 +2679,7 @@ static inline void btrfs_free_space_key(struct extent_buffer *eb,
 
 static inline void btrfs_set_free_space_key(struct extent_buffer *eb,
 					    struct btrfs_free_space_header *h,
-					    struct btrfs_disk_key *key)
+					    const struct btrfs_disk_key *key)
 {
 	write_eb_member(eb, h, struct btrfs_free_space_header, location, key);
 }
@@ -2697,25 +2706,25 @@ static inline void btrfs_cpu_key_to_disk(struct btrfs_disk_key *disk,
 	disk->objectid = cpu_to_le64(cpu->objectid);
 }
 
-static inline void btrfs_node_key_to_cpu(struct extent_buffer *eb,
-				  struct btrfs_key *key, int nr)
+static inline void btrfs_node_key_to_cpu(const struct extent_buffer *eb,
+					 struct btrfs_key *key, int nr)
 {
 	struct btrfs_disk_key disk_key;
 	btrfs_node_key(eb, &disk_key, nr);
 	btrfs_disk_key_to_cpu(key, &disk_key);
 }
 
-static inline void btrfs_item_key_to_cpu(struct extent_buffer *eb,
-				  struct btrfs_key *key, int nr)
+static inline void btrfs_item_key_to_cpu(const struct extent_buffer *eb,
+					 struct btrfs_key *key, int nr)
 {
 	struct btrfs_disk_key disk_key;
 	btrfs_item_key(eb, &disk_key, nr);
 	btrfs_disk_key_to_cpu(key, &disk_key);
 }
 
-static inline void btrfs_dir_item_key_to_cpu(struct extent_buffer *eb,
-				      struct btrfs_dir_item *item,
-				      struct btrfs_key *key)
+static inline void btrfs_dir_item_key_to_cpu(const struct extent_buffer *eb,
+					     const struct btrfs_dir_item *item,
+					     struct btrfs_key *key)
 {
 	struct btrfs_disk_key disk_key;
 	btrfs_dir_item_key(eb, item, &disk_key);
@@ -2748,7 +2757,7 @@ BTRFS_SETGET_STACK_FUNCS(stack_header_nritems, struct btrfs_header,
 			 nritems, 32);
 BTRFS_SETGET_STACK_FUNCS(stack_header_bytenr, struct btrfs_header, bytenr, 64);
 
-static inline int btrfs_header_flag(struct extent_buffer *eb, u64 flag)
+static inline int btrfs_header_flag(const struct extent_buffer *eb, u64 flag)
 {
 	return (btrfs_header_flags(eb) & flag) == flag;
 }
@@ -2767,7 +2776,7 @@ static inline int btrfs_clear_header_flag(struct extent_buffer *eb, u64 flag)
 	return (flags & flag) == flag;
 }
 
-static inline int btrfs_header_backref_rev(struct extent_buffer *eb)
+static inline int btrfs_header_backref_rev(const struct extent_buffer *eb)
 {
 	u64 flags = btrfs_header_flags(eb);
 	return flags >> BTRFS_BACKREF_REV_SHIFT;
@@ -2787,12 +2796,12 @@ static inline unsigned long btrfs_header_fsid(void)
 	return offsetof(struct btrfs_header, fsid);
 }
 
-static inline unsigned long btrfs_header_chunk_tree_uuid(struct extent_buffer *eb)
+static inline unsigned long btrfs_header_chunk_tree_uuid(const struct extent_buffer *eb)
 {
 	return offsetof(struct btrfs_header, chunk_tree_uuid);
 }
 
-static inline int btrfs_is_leaf(struct extent_buffer *eb)
+static inline int btrfs_is_leaf(const struct extent_buffer *eb)
 {
 	return btrfs_header_level(eb) == 0;
 }
@@ -2826,12 +2835,12 @@ BTRFS_SETGET_STACK_FUNCS(root_stransid, struct btrfs_root_item,
 BTRFS_SETGET_STACK_FUNCS(root_rtransid, struct btrfs_root_item,
 			 rtransid, 64);
 
-static inline bool btrfs_root_readonly(struct btrfs_root *root)
+static inline bool btrfs_root_readonly(const struct btrfs_root *root)
 {
 	return (root->root_item.flags & cpu_to_le64(BTRFS_ROOT_SUBVOL_RDONLY)) != 0;
 }
 
-static inline bool btrfs_root_dead(struct btrfs_root *root)
+static inline bool btrfs_root_dead(const struct btrfs_root *root)
 {
 	return (root->root_item.flags & cpu_to_le64(BTRFS_ROOT_SUBVOL_DEAD)) != 0;
 }
@@ -2888,51 +2897,51 @@ BTRFS_SETGET_STACK_FUNCS(backup_num_devices, struct btrfs_root_backup,
 /* struct btrfs_balance_item */
 BTRFS_SETGET_FUNCS(balance_flags, struct btrfs_balance_item, flags, 64);
 
-static inline void btrfs_balance_data(struct extent_buffer *eb,
-				      struct btrfs_balance_item *bi,
+static inline void btrfs_balance_data(const struct extent_buffer *eb,
+				      const struct btrfs_balance_item *bi,
 				      struct btrfs_disk_balance_args *ba)
 {
 	read_eb_member(eb, bi, struct btrfs_balance_item, data, ba);
 }
 
 static inline void btrfs_set_balance_data(struct extent_buffer *eb,
-					  struct btrfs_balance_item *bi,
-					  struct btrfs_disk_balance_args *ba)
+				  struct btrfs_balance_item *bi,
+				  const struct btrfs_disk_balance_args *ba)
 {
 	write_eb_member(eb, bi, struct btrfs_balance_item, data, ba);
 }
 
-static inline void btrfs_balance_meta(struct extent_buffer *eb,
-				      struct btrfs_balance_item *bi,
+static inline void btrfs_balance_meta(const struct extent_buffer *eb,
+				      const struct btrfs_balance_item *bi,
 				      struct btrfs_disk_balance_args *ba)
 {
 	read_eb_member(eb, bi, struct btrfs_balance_item, meta, ba);
 }
 
 static inline void btrfs_set_balance_meta(struct extent_buffer *eb,
-					  struct btrfs_balance_item *bi,
-					  struct btrfs_disk_balance_args *ba)
+				  struct btrfs_balance_item *bi,
+				  const struct btrfs_disk_balance_args *ba)
 {
 	write_eb_member(eb, bi, struct btrfs_balance_item, meta, ba);
 }
 
-static inline void btrfs_balance_sys(struct extent_buffer *eb,
-				     struct btrfs_balance_item *bi,
+static inline void btrfs_balance_sys(const struct extent_buffer *eb,
+				     const struct btrfs_balance_item *bi,
 				     struct btrfs_disk_balance_args *ba)
 {
 	read_eb_member(eb, bi, struct btrfs_balance_item, sys, ba);
 }
 
 static inline void btrfs_set_balance_sys(struct extent_buffer *eb,
-					 struct btrfs_balance_item *bi,
-					 struct btrfs_disk_balance_args *ba)
+				 struct btrfs_balance_item *bi,
+				 const struct btrfs_disk_balance_args *ba)
 {
 	write_eb_member(eb, bi, struct btrfs_balance_item, sys, ba);
 }
 
 static inline void
 btrfs_disk_balance_args_to_cpu(struct btrfs_balance_args *cpu,
-			       struct btrfs_disk_balance_args *disk)
+			       const struct btrfs_disk_balance_args *disk)
 {
 	memset(cpu, 0, sizeof(*cpu));
 
@@ -2950,7 +2959,7 @@ btrfs_disk_balance_args_to_cpu(struct btrfs_balance_args *cpu,
 
 static inline void
 btrfs_cpu_balance_args_to_disk(struct btrfs_disk_balance_args *disk,
-			       struct btrfs_balance_args *cpu)
+			       const struct btrfs_balance_args *cpu)
 {
 	memset(disk, 0, sizeof(*disk));
 
@@ -3018,7 +3027,7 @@ BTRFS_SETGET_STACK_FUNCS(super_magic, struct btrfs_super_block, magic, 64);
 BTRFS_SETGET_STACK_FUNCS(super_uuid_tree_generation, struct btrfs_super_block,
 			 uuid_tree_generation, 64);
 
-static inline int btrfs_super_csum_size(struct btrfs_super_block *s)
+static inline int btrfs_super_csum_size(const struct btrfs_super_block *s)
 {
 	u16 t = btrfs_super_csum_type(s);
 	/*
@@ -3032,6 +3041,21 @@ static inline unsigned long btrfs_leaf_data(struct extent_buffer *l)
 	return offsetof(struct btrfs_leaf, items);
 }
 
+/*
+ * The leaf data grows from end-to-front in the node.
+ * this returns the address of the start of the last item,
+ * which is the stop of the leaf data stack
+ */
+static inline unsigned int leaf_data_end(const struct btrfs_root *root,
+					 const struct extent_buffer *leaf)
+{
+	u32 nr = btrfs_header_nritems(leaf);
+
+	if (nr == 0)
+		return BTRFS_LEAF_DATA_SIZE(root);
+	return btrfs_item_offset_nr(leaf, nr - 1);
+}
+
 /* struct btrfs_file_extent_item */
 BTRFS_SETGET_FUNCS(file_extent_type, struct btrfs_file_extent_item, type, 8);
 BTRFS_SETGET_STACK_FUNCS(stack_file_extent_disk_bytenr,
@@ -3048,16 +3072,14 @@ BTRFS_SETGET_STACK_FUNCS(stack_file_extent_compression,
 			 struct btrfs_file_extent_item, compression, 8);
 
 static inline unsigned long
-btrfs_file_extent_inline_start(struct btrfs_file_extent_item *e)
+btrfs_file_extent_inline_start(const struct btrfs_file_extent_item *e)
 {
-	unsigned long offset = (unsigned long)e;
-	offset += offsetof(struct btrfs_file_extent_item, disk_bytenr);
-	return offset;
+	return (unsigned long)e + BTRFS_FILE_EXTENT_INLINE_DATA_START;
 }
 
 static inline u32 btrfs_file_extent_calc_inline_size(u32 datasize)
 {
-	return offsetof(struct btrfs_file_extent_item, disk_bytenr) + datasize;
+	return BTRFS_FILE_EXTENT_INLINE_DATA_START + datasize;
 }
 
 BTRFS_SETGET_FUNCS(file_extent_disk_bytenr, struct btrfs_file_extent_item,
@@ -3084,20 +3106,19 @@ BTRFS_SETGET_FUNCS(file_extent_other_encoding, struct btrfs_file_extent_item,
  * size of any extent headers.  If a file is compressed on disk, this is
  * the compressed size
  */
-static inline u32 btrfs_file_extent_inline_item_len(struct extent_buffer *eb,
-						    struct btrfs_item *e)
+static inline u32 btrfs_file_extent_inline_item_len(
+						const struct extent_buffer *eb,
+						struct btrfs_item *e)
 {
-	unsigned long offset;
-	offset = offsetof(struct btrfs_file_extent_item, disk_bytenr);
-	return btrfs_item_size(eb, e) - offset;
+	return btrfs_item_size(eb, e) - BTRFS_FILE_EXTENT_INLINE_DATA_START;
 }
 
 /* this returns the number of file bytes represented by the inline item.
  * If an item is compressed, this is the uncompressed size
  */
-static inline u32 btrfs_file_extent_inline_len(struct extent_buffer *eb,
-					       int slot,
-					       struct btrfs_file_extent_item *fi)
+static inline u32 btrfs_file_extent_inline_len(const struct extent_buffer *eb,
+					int slot,
+					const struct btrfs_file_extent_item *fi)
 {
 	struct btrfs_map_token token;
 
@@ -3119,8 +3140,8 @@ static inline u32 btrfs_file_extent_inline_len(struct extent_buffer *eb,
 
 
 /* btrfs_dev_stats_item */
-static inline u64 btrfs_dev_stats_value(struct extent_buffer *eb,
-					struct btrfs_dev_stats_item *ptr,
+static inline u64 btrfs_dev_stats_value(const struct extent_buffer *eb,
+					const struct btrfs_dev_stats_item *ptr,
 					int index)
 {
 	u64 val;
diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c
index 7ee449d0da8a..7542ba457f09 100644
--- a/fs/btrfs/dev-replace.c
+++ b/fs/btrfs/dev-replace.c
@@ -614,7 +614,7 @@ static void btrfs_dev_replace_update_device_in_mapping_tree(
 		em = lookup_extent_mapping(em_tree, start, (u64)-1);
 		if (!em)
 			break;
-		map = (struct map_lookup *)em->bdev;
+		map = em->map_lookup;
 		for (i = 0; i < map->num_stripes; i++)
 			if (srcdev == map->stripes[i].dev)
 				map->stripes[i].dev = tgtdev;
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 64cd85a24ab8..c3669e689db8 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -49,6 +49,7 @@
 #include "raid56.h"
 #include "sysfs.h"
 #include "qgroup.h"
+#include "tree-checker.h"
 
 #ifdef CONFIG_X86
 #include <asm/cpufeature.h>
@@ -507,72 +508,6 @@ static int check_tree_block_fsid(struct btrfs_root *root,
 	return ret;
 }
 
-#define CORRUPT(reason, eb, root, slot)				\
-	btrfs_crit(root->fs_info, "corrupt leaf, %s: block=%llu,"	\
-		   "root=%llu, slot=%d", reason,			\
-	       btrfs_header_bytenr(eb),	root->objectid, slot)
-
-static noinline int check_leaf(struct btrfs_root *root,
-			       struct extent_buffer *leaf)
-{
-	struct btrfs_key key;
-	struct btrfs_key leaf_key;
-	u32 nritems = btrfs_header_nritems(leaf);
-	int slot;
-
-	if (nritems == 0)
-		return 0;
-
-	/* Check the 0 item */
-	if (btrfs_item_offset_nr(leaf, 0) + btrfs_item_size_nr(leaf, 0) !=
-	    BTRFS_LEAF_DATA_SIZE(root)) {
-		CORRUPT("invalid item offset size pair", leaf, root, 0);
-		return -EIO;
-	}
-
-	/*
-	 * Check to make sure each items keys are in the correct order and their
-	 * offsets make sense.  We only have to loop through nritems-1 because
-	 * we check the current slot against the next slot, which verifies the
-	 * next slot's offset+size makes sense and that the current's slot
-	 * offset is correct.
-	 */
-	for (slot = 0; slot < nritems - 1; slot++) {
-		btrfs_item_key_to_cpu(leaf, &leaf_key, slot);
-		btrfs_item_key_to_cpu(leaf, &key, slot + 1);
-
-		/* Make sure the keys are in the right order */
-		if (btrfs_comp_cpu_keys(&leaf_key, &key) >= 0) {
-			CORRUPT("bad key order", leaf, root, slot);
-			return -EIO;
-		}
-
-		/*
-		 * Make sure the offset and ends are right, remember that the
-		 * item data starts at the end of the leaf and grows towards the
-		 * front.
-		 */
-		if (btrfs_item_offset_nr(leaf, slot) !=
-			btrfs_item_end_nr(leaf, slot + 1)) {
-			CORRUPT("slot offset bad", leaf, root, slot);
-			return -EIO;
-		}
-
-		/*
-		 * Check to make sure that we don't point outside of the leaf,
-		 * just incase all the items are consistent to eachother, but
-		 * all point outside of the leaf.
-		 */
-		if (btrfs_item_end_nr(leaf, slot) >
-		    BTRFS_LEAF_DATA_SIZE(root)) {
-			CORRUPT("slot end outside of leaf", leaf, root, slot);
-			return -EIO;
-		}
-	}
-
-	return 0;
-}
-
 static int btree_readpage_end_io_hook(struct btrfs_io_bio *io_bio,
 				      u64 phy_offset, struct page *page,
 				      u64 start, u64 end, int mirror)
@@ -640,11 +575,14 @@ static int btree_readpage_end_io_hook(struct btrfs_io_bio *io_bio,
 	 * that we don't try and read the other copies of this block, just
 	 * return -EIO.
 	 */
-	if (found_level == 0 && check_leaf(root, eb)) {
+	if (found_level == 0 && btrfs_check_leaf_full(root, eb)) {
 		set_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags);
 		ret = -EIO;
 	}
 
+	if (found_level > 0 && btrfs_check_node(root, eb))
+		ret = -EIO;
+
 	if (!ret)
 		set_extent_buffer_uptodate(eb);
 err:
@@ -3764,7 +3702,13 @@ void btrfs_mark_buffer_dirty(struct extent_buffer *buf)
 				     buf->len,
 				     root->fs_info->dirty_metadata_batch);
 #ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY
-	if (btrfs_header_level(buf) == 0 && check_leaf(root, buf)) {
+	/*
+	 * Since btrfs_mark_buffer_dirty() can be called with item pointer set
+	 * but item data not updated.
+	 * So here we should only check item pointers, not item data.
+	 */
+	if (btrfs_header_level(buf) == 0 &&
+	    btrfs_check_leaf_relaxed(root, buf)) {
 		btrfs_print_leaf(root, buf);
 		ASSERT(0);
 	}
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 62a92d7ed0aa..1c1cb07f51f8 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -2258,7 +2258,13 @@ static int run_delayed_tree_ref(struct btrfs_trans_handle *trans,
 		ins.type = BTRFS_EXTENT_ITEM_KEY;
 	}
 
-	BUG_ON(node->ref_mod != 1);
+	if (node->ref_mod != 1) {
+		btrfs_err(root->fs_info,
+	"btree block(%llu) has %d references rather than 1: action %d ref_root %llu parent %llu",
+			  node->bytenr, node->ref_mod, node->action, ref_root,
+			  parent);
+		return -EIO;
+	}
 	if (node->action == BTRFS_ADD_DELAYED_REF && insert_reserved) {
 		BUG_ON(!extent_op || !extent_op->update_flags);
 		ret = alloc_reserved_tree_block(trans, root,
@@ -8550,6 +8556,8 @@ static int find_first_block_group(struct btrfs_root *root,
 	int ret = 0;
 	struct btrfs_key found_key;
 	struct extent_buffer *leaf;
+	struct btrfs_block_group_item bg;
+	u64 flags;
 	int slot;
 
 	ret = btrfs_search_slot(NULL, root, key, path, 0, 0);
@@ -8571,7 +8579,47 @@ static int find_first_block_group(struct btrfs_root *root,
 
 		if (found_key.objectid >= key->objectid &&
 		    found_key.type == BTRFS_BLOCK_GROUP_ITEM_KEY) {
-			ret = 0;
+			struct extent_map_tree *em_tree;
+			struct extent_map *em;
+
+			em_tree = &root->fs_info->mapping_tree.map_tree;
+			read_lock(&em_tree->lock);
+			em = lookup_extent_mapping(em_tree, found_key.objectid,
+						   found_key.offset);
+			read_unlock(&em_tree->lock);
+			if (!em) {
+				btrfs_err(root->fs_info,
+			"logical %llu len %llu found bg but no related chunk",
+					  found_key.objectid, found_key.offset);
+				ret = -ENOENT;
+			} else if (em->start != found_key.objectid ||
+				   em->len != found_key.offset) {
+				btrfs_err(root->fs_info,
+		"block group %llu len %llu mismatch with chunk %llu len %llu",
+					  found_key.objectid, found_key.offset,
+					  em->start, em->len);
+				ret = -EUCLEAN;
+			} else {
+				read_extent_buffer(leaf, &bg,
+					btrfs_item_ptr_offset(leaf, slot),
+					sizeof(bg));
+				flags = btrfs_block_group_flags(&bg) &
+					BTRFS_BLOCK_GROUP_TYPE_MASK;
+
+				if (flags != (em->map_lookup->type &
+					      BTRFS_BLOCK_GROUP_TYPE_MASK)) {
+					btrfs_err(root->fs_info,
+"block group %llu len %llu type flags 0x%llx mismatch with chunk type flags 0x%llx",
+						found_key.objectid,
+						found_key.offset, flags,
+						(BTRFS_BLOCK_GROUP_TYPE_MASK &
+						 em->map_lookup->type));
+					ret = -EUCLEAN;
+				} else {
+					ret = 0;
+				}
+			}
+			free_extent_map(em);
 			goto out;
 		}
 		path->slots[0]++;
@@ -8771,6 +8819,62 @@ btrfs_create_block_group_cache(struct btrfs_root *root, u64 start, u64 size)
 	return cache;
 }
 
+
+/*
+ * Iterate all chunks and verify that each of them has the corresponding block
+ * group
+ */
+static int check_chunk_block_group_mappings(struct btrfs_fs_info *fs_info)
+{
+	struct btrfs_mapping_tree *map_tree = &fs_info->mapping_tree;
+	struct extent_map *em;
+	struct btrfs_block_group_cache *bg;
+	u64 start = 0;
+	int ret = 0;
+
+	while (1) {
+		read_lock(&map_tree->map_tree.lock);
+		/*
+		 * lookup_extent_mapping will return the first extent map
+		 * intersecting the range, so setting @len to 1 is enough to
+		 * get the first chunk.
+		 */
+		em = lookup_extent_mapping(&map_tree->map_tree, start, 1);
+		read_unlock(&map_tree->map_tree.lock);
+		if (!em)
+			break;
+
+		bg = btrfs_lookup_block_group(fs_info, em->start);
+		if (!bg) {
+			btrfs_err(fs_info,
+	"chunk start=%llu len=%llu doesn't have corresponding block group",
+				     em->start, em->len);
+			ret = -EUCLEAN;
+			free_extent_map(em);
+			break;
+		}
+		if (bg->key.objectid != em->start ||
+		    bg->key.offset != em->len ||
+		    (bg->flags & BTRFS_BLOCK_GROUP_TYPE_MASK) !=
+		    (em->map_lookup->type & BTRFS_BLOCK_GROUP_TYPE_MASK)) {
+			btrfs_err(fs_info,
+"chunk start=%llu len=%llu flags=0x%llx doesn't match block group start=%llu len=%llu flags=0x%llx",
+				em->start, em->len,
+				em->map_lookup->type & BTRFS_BLOCK_GROUP_TYPE_MASK,
+				bg->key.objectid, bg->key.offset,
+				bg->flags & BTRFS_BLOCK_GROUP_TYPE_MASK);
+			ret = -EUCLEAN;
+			free_extent_map(em);
+			btrfs_put_block_group(bg);
+			break;
+		}
+		start = em->start + em->len;
+		free_extent_map(em);
+		btrfs_put_block_group(bg);
+	}
+	return ret;
+}
+
 int btrfs_read_block_groups(struct btrfs_root *root)
 {
 	struct btrfs_path *path;
@@ -8933,7 +9037,7 @@ int btrfs_read_block_groups(struct btrfs_root *root)
 	}
 
 	init_global_block_rsv(info);
-	ret = 0;
+	ret = check_chunk_block_group_mappings(info);
 error:
 	btrfs_free_path(path);
 	return ret;
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 604d31e85c82..417a4cf6035c 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -2082,7 +2082,7 @@ int repair_eb_io_failure(struct btrfs_root *root, struct extent_buffer *eb,
 		return -EROFS;
 
 	for (i = 0; i < num_pages; i++) {
-		struct page *p = extent_buffer_page(eb, i);
+		struct page *p = eb->pages[i];
 		ret = repair_io_failure(root->fs_info, start, PAGE_CACHE_SIZE,
 					start, p, mirror_num);
 		if (ret)
@@ -3558,7 +3558,7 @@ lock_extent_buffer_for_io(struct extent_buffer *eb,
 
 	num_pages = num_extent_pages(eb->start, eb->len);
 	for (i = 0; i < num_pages; i++) {
-		struct page *p = extent_buffer_page(eb, i);
+		struct page *p = eb->pages[i];
 
 		if (!trylock_page(p)) {
 			if (!flush) {
@@ -3617,8 +3617,10 @@ static noinline_for_stack int write_one_eb(struct extent_buffer *eb,
 	struct block_device *bdev = fs_info->fs_devices->latest_bdev;
 	struct extent_io_tree *tree = &BTRFS_I(fs_info->btree_inode)->io_tree;
 	u64 offset = eb->start;
+	u32 nritems;
 	unsigned long i, num_pages;
 	unsigned long bio_flags = 0;
+	unsigned long start, end;
 	int rw = (epd->sync_io ? WRITE_SYNC : WRITE) | REQ_META;
 	int ret = 0;
 
@@ -3628,8 +3630,25 @@ static noinline_for_stack int write_one_eb(struct extent_buffer *eb,
 	if (btrfs_header_owner(eb) == BTRFS_TREE_LOG_OBJECTID)
 		bio_flags = EXTENT_BIO_TREE_LOG;
 
+	/* set btree blocks beyond nritems with 0 to avoid stale content. */
+	nritems = btrfs_header_nritems(eb);
+	if (btrfs_header_level(eb) > 0) {
+		end = btrfs_node_key_ptr_offset(nritems);
+
+		memset_extent_buffer(eb, 0, end, eb->len - end);
+	} else {
+		/*
+		 * leaf:
+		 * header 0 1 2 .. N ... data_N .. data_2 data_1 data_0
+		 */
+		start = btrfs_item_nr_offset(nritems);
+		end = btrfs_leaf_data(eb) +
+		      leaf_data_end(fs_info->tree_root, eb);
+		memset_extent_buffer(eb, 0, start, end - start);
+	}
+
 	for (i = 0; i < num_pages; i++) {
-		struct page *p = extent_buffer_page(eb, i);
+		struct page *p = eb->pages[i];
 
 		clear_page_dirty_for_io(p);
 		set_page_writeback(p);
@@ -3652,10 +3671,8 @@ static noinline_for_stack int write_one_eb(struct extent_buffer *eb,
 	}
 
 	if (unlikely(ret)) {
-		for (; i < num_pages; i++) {
-			struct page *p = extent_buffer_page(eb, i);
-			unlock_page(p);
-		}
+		for (; i < num_pages; i++)
+			unlock_page(eb->pages[i]);
 	}
 
 	return ret;
@@ -4459,7 +4476,7 @@ static void btrfs_release_extent_buffer_page(struct extent_buffer *eb,
 
 	do {
 		index--;
-		page = extent_buffer_page(eb, index);
+		page = eb->pages[index];
 		if (page && mapped) {
 			spin_lock(&page->mapping->private_lock);
 			/*
@@ -4641,7 +4658,8 @@ static void mark_extent_buffer_accessed(struct extent_buffer *eb,
 
 	num_pages = num_extent_pages(eb->start, eb->len);
 	for (i = 0; i < num_pages; i++) {
-		struct page *p = extent_buffer_page(eb, i);
+		struct page *p = eb->pages[i];
+
 		if (p != accessed)
 			mark_page_accessed(p);
 	}
@@ -4810,7 +4828,7 @@ struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info,
 	 */
 	SetPageChecked(eb->pages[0]);
 	for (i = 1; i < num_pages; i++) {
-		p = extent_buffer_page(eb, i);
+		p = eb->pages[i];
 		ClearPageChecked(p);
 		unlock_page(p);
 	}
@@ -4921,7 +4939,7 @@ void clear_extent_buffer_dirty(struct extent_buffer *eb)
 	num_pages = num_extent_pages(eb->start, eb->len);
 
 	for (i = 0; i < num_pages; i++) {
-		page = extent_buffer_page(eb, i);
+		page = eb->pages[i];
 		if (!PageDirty(page))
 			continue;
 
@@ -4957,7 +4975,7 @@ int set_extent_buffer_dirty(struct extent_buffer *eb)
 	WARN_ON(!test_bit(EXTENT_BUFFER_TREE_REF, &eb->bflags));
 
 	for (i = 0; i < num_pages; i++)
-		set_page_dirty(extent_buffer_page(eb, i));
+		set_page_dirty(eb->pages[i]);
 	return was_dirty;
 }
 
@@ -4970,7 +4988,7 @@ int clear_extent_buffer_uptodate(struct extent_buffer *eb)
 	clear_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags);
 	num_pages = num_extent_pages(eb->start, eb->len);
 	for (i = 0; i < num_pages; i++) {
-		page = extent_buffer_page(eb, i);
+		page = eb->pages[i];
 		if (page)
 			ClearPageUptodate(page);
 	}
@@ -4986,7 +5004,7 @@ int set_extent_buffer_uptodate(struct extent_buffer *eb)
 	set_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags);
 	num_pages = num_extent_pages(eb->start, eb->len);
 	for (i = 0; i < num_pages; i++) {
-		page = extent_buffer_page(eb, i);
+		page = eb->pages[i];
 		SetPageUptodate(page);
 	}
 	return 0;
@@ -5026,7 +5044,7 @@ int read_extent_buffer_pages(struct extent_io_tree *tree,
 
 	num_pages = num_extent_pages(eb->start, eb->len);
 	for (i = start_i; i < num_pages; i++) {
-		page = extent_buffer_page(eb, i);
+		page = eb->pages[i];
 		if (wait == WAIT_NONE) {
 			if (!trylock_page(page))
 				goto unlock_exit;
@@ -5049,7 +5067,7 @@ int read_extent_buffer_pages(struct extent_io_tree *tree,
 	eb->read_mirror = 0;
 	atomic_set(&eb->io_pages, num_reads);
 	for (i = start_i; i < num_pages; i++) {
-		page = extent_buffer_page(eb, i);
+		page = eb->pages[i];
 		if (!PageUptodate(page)) {
 			ClearPageError(page);
 			err = __extent_read_full_page(tree, page,
@@ -5074,7 +5092,7 @@ int read_extent_buffer_pages(struct extent_io_tree *tree,
 		return ret;
 
 	for (i = start_i; i < num_pages; i++) {
-		page = extent_buffer_page(eb, i);
+		page = eb->pages[i];
 		wait_on_page_locked(page);
 		if (!PageUptodate(page))
 			ret = -EIO;
@@ -5085,7 +5103,7 @@ int read_extent_buffer_pages(struct extent_io_tree *tree,
 unlock_exit:
 	i = start_i;
 	while (locked_pages > 0) {
-		page = extent_buffer_page(eb, i);
+		page = eb->pages[i];
 		i++;
 		unlock_page(page);
 		locked_pages--;
@@ -5093,9 +5111,8 @@ int read_extent_buffer_pages(struct extent_io_tree *tree,
 	return ret;
 }
 
-void read_extent_buffer(struct extent_buffer *eb, void *dstv,
-			unsigned long start,
-			unsigned long len)
+void read_extent_buffer(const struct extent_buffer *eb, void *dstv,
+			unsigned long start, unsigned long len)
 {
 	size_t cur;
 	size_t offset;
@@ -5111,7 +5128,7 @@ void read_extent_buffer(struct extent_buffer *eb, void *dstv,
 	offset = (start_offset + start) & (PAGE_CACHE_SIZE - 1);
 
 	while (len > 0) {
-		page = extent_buffer_page(eb, i);
+		page = eb->pages[i];
 
 		cur = min(len, (PAGE_CACHE_SIZE - offset));
 		kaddr = page_address(page);
@@ -5124,9 +5141,9 @@ void read_extent_buffer(struct extent_buffer *eb, void *dstv,
 	}
 }
 
-int read_extent_buffer_to_user(struct extent_buffer *eb, void __user *dstv,
-			unsigned long start,
-			unsigned long len)
+int read_extent_buffer_to_user(const struct extent_buffer *eb,
+			       void __user *dstv,
+			       unsigned long start, unsigned long len)
 {
 	size_t cur;
 	size_t offset;
@@ -5143,7 +5160,7 @@ int read_extent_buffer_to_user(struct extent_buffer *eb, void __user *dstv,
 	offset = (start_offset + start) & (PAGE_CACHE_SIZE - 1);
 
 	while (len > 0) {
-		page = extent_buffer_page(eb, i);
+		page = eb->pages[i];
 
 		cur = min(len, (PAGE_CACHE_SIZE - offset));
 		kaddr = page_address(page);
@@ -5161,10 +5178,10 @@ int read_extent_buffer_to_user(struct extent_buffer *eb, void __user *dstv,
 	return ret;
 }
 
-int map_private_extent_buffer(struct extent_buffer *eb, unsigned long start,
-			       unsigned long min_len, char **map,
-			       unsigned long *map_start,
-			       unsigned long *map_len)
+int map_private_extent_buffer(const struct extent_buffer *eb,
+			      unsigned long start, unsigned long min_len,
+			      char **map, unsigned long *map_start,
+			      unsigned long *map_len)
 {
 	size_t offset = start & (PAGE_CACHE_SIZE - 1);
 	char *kaddr;
@@ -5192,16 +5209,15 @@ int map_private_extent_buffer(struct extent_buffer *eb, unsigned long start,
 		return -EINVAL;
 	}
 
-	p = extent_buffer_page(eb, i);
+	p = eb->pages[i];
 	kaddr = page_address(p);
 	*map = kaddr + offset;
 	*map_len = PAGE_CACHE_SIZE - offset;
 	return 0;
 }
 
-int memcmp_extent_buffer(struct extent_buffer *eb, const void *ptrv,
-			  unsigned long start,
-			  unsigned long len)
+int memcmp_extent_buffer(const struct extent_buffer *eb, const void *ptrv,
+			 unsigned long start, unsigned long len)
 {
 	size_t cur;
 	size_t offset;
@@ -5218,7 +5234,7 @@ int memcmp_extent_buffer(struct extent_buffer *eb, const void *ptrv,
 	offset = (start_offset + start) & (PAGE_CACHE_SIZE - 1);
 
 	while (len > 0) {
-		page = extent_buffer_page(eb, i);
+		page = eb->pages[i];
 
 		cur = min(len, (PAGE_CACHE_SIZE - offset));
 
@@ -5252,7 +5268,7 @@ void write_extent_buffer(struct extent_buffer *eb, const void *srcv,
 	offset = (start_offset + start) & (PAGE_CACHE_SIZE - 1);
 
 	while (len > 0) {
-		page = extent_buffer_page(eb, i);
+		page = eb->pages[i];
 		WARN_ON(!PageUptodate(page));
 
 		cur = min(len, PAGE_CACHE_SIZE - offset);
@@ -5282,7 +5298,7 @@ void memset_extent_buffer(struct extent_buffer *eb, char c,
 	offset = (start_offset + start) & (PAGE_CACHE_SIZE - 1);
 
 	while (len > 0) {
-		page = extent_buffer_page(eb, i);
+		page = eb->pages[i];
 		WARN_ON(!PageUptodate(page));
 
 		cur = min(len, PAGE_CACHE_SIZE - offset);
@@ -5313,7 +5329,7 @@ void copy_extent_buffer(struct extent_buffer *dst, struct extent_buffer *src,
 		(PAGE_CACHE_SIZE - 1);
 
 	while (len > 0) {
-		page = extent_buffer_page(dst, i);
+		page = dst->pages[i];
 		WARN_ON(!PageUptodate(page));
 
 		cur = min(len, (unsigned long)(PAGE_CACHE_SIZE - offset));
@@ -5391,8 +5407,7 @@ void memcpy_extent_buffer(struct extent_buffer *dst, unsigned long dst_offset,
 		cur = min_t(unsigned long, cur,
 			(unsigned long)(PAGE_CACHE_SIZE - dst_off_in_page));
 
-		copy_pages(extent_buffer_page(dst, dst_i),
-			   extent_buffer_page(dst, src_i),
+		copy_pages(dst->pages[dst_i], dst->pages[src_i],
 			   dst_off_in_page, src_off_in_page, cur);
 
 		src_offset += cur;
@@ -5438,8 +5453,7 @@ void memmove_extent_buffer(struct extent_buffer *dst, unsigned long dst_offset,
 
 		cur = min_t(unsigned long, len, src_off_in_page + 1);
 		cur = min(cur, dst_off_in_page + 1);
-		copy_pages(extent_buffer_page(dst, dst_i),
-			   extent_buffer_page(dst, src_i),
+		copy_pages(dst->pages[dst_i], dst->pages[src_i],
 			   dst_off_in_page - cur + 1,
 			   src_off_in_page - cur + 1, cur);
 
diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h
index ccc264e7bde1..5095cb199128 100644
--- a/fs/btrfs/extent_io.h
+++ b/fs/btrfs/extent_io.h
@@ -286,25 +286,18 @@ static inline unsigned long num_extent_pages(u64 start, u64 len)
 		(start >> PAGE_CACHE_SHIFT);
 }
 
-static inline struct page *extent_buffer_page(struct extent_buffer *eb,
-					      unsigned long i)
-{
-	return eb->pages[i];
-}
-
 static inline void extent_buffer_get(struct extent_buffer *eb)
 {
 	atomic_inc(&eb->refs);
 }
 
-int memcmp_extent_buffer(struct extent_buffer *eb, const void *ptrv,
-			  unsigned long start,
-			  unsigned long len);
-void read_extent_buffer(struct extent_buffer *eb, void *dst,
+int memcmp_extent_buffer(const struct extent_buffer *eb, const void *ptrv,
+			 unsigned long start, unsigned long len);
+void read_extent_buffer(const struct extent_buffer *eb, void *dst,
 			unsigned long start,
 			unsigned long len);
-int read_extent_buffer_to_user(struct extent_buffer *eb, void __user *dst,
-			       unsigned long start,
+int read_extent_buffer_to_user(const struct extent_buffer *eb,
+			       void __user *dst, unsigned long start,
 			       unsigned long len);
 void write_extent_buffer(struct extent_buffer *eb, const void *src,
 			 unsigned long start, unsigned long len);
@@ -323,10 +316,10 @@ int set_extent_buffer_uptodate(struct extent_buffer *eb);
 int clear_extent_buffer_uptodate(struct extent_buffer *eb);
 int extent_buffer_uptodate(struct extent_buffer *eb);
 int extent_buffer_under_io(struct extent_buffer *eb);
-int map_private_extent_buffer(struct extent_buffer *eb, unsigned long offset,
-		      unsigned long min_len, char **map,
-		      unsigned long *map_start,
-		      unsigned long *map_len);
+int map_private_extent_buffer(const struct extent_buffer *eb,
+			      unsigned long offset, unsigned long min_len,
+			      char **map, unsigned long *map_start,
+			      unsigned long *map_len);
 int extent_range_clear_dirty_for_io(struct inode *inode, u64 start, u64 end);
 int extent_range_redirty_for_io(struct inode *inode, u64 start, u64 end);
 int extent_clear_unlock_delalloc(struct inode *inode, u64 start, u64 end,
diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c
index 6a98bddd8f33..84fb56d5c018 100644
--- a/fs/btrfs/extent_map.c
+++ b/fs/btrfs/extent_map.c
@@ -76,7 +76,7 @@ void free_extent_map(struct extent_map *em)
 		WARN_ON(extent_map_in_tree(em));
 		WARN_ON(!list_empty(&em->list));
 		if (test_bit(EXTENT_FLAG_FS_MAPPING, &em->flags))
-			kfree(em->bdev);
+			kfree(em->map_lookup);
 		kmem_cache_free(extent_map_cache, em);
 	}
 }
diff --git a/fs/btrfs/extent_map.h b/fs/btrfs/extent_map.h
index b2991fd8583e..eb8b8fae036b 100644
--- a/fs/btrfs/extent_map.h
+++ b/fs/btrfs/extent_map.h
@@ -32,7 +32,15 @@ struct extent_map {
 	u64 block_len;
 	u64 generation;
 	unsigned long flags;
-	struct block_device *bdev;
+	union {
+		struct block_device *bdev;
+
+		/*
+		 * used for chunk mappings
+		 * flags & EXTENT_FLAG_FS_MAPPING must be set
+		 */
+		struct map_lookup *map_lookup;
+	};
 	atomic_t refs;
 	unsigned int compress_type;
 	struct list_head list;
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index e597cc1c5d5b..8ac270f3fa92 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -1283,7 +1283,11 @@ static noinline int run_delalloc_nocow(struct inode *inode,
 				btrfs_file_extent_num_bytes(leaf, fi);
 			disk_num_bytes =
 				btrfs_file_extent_disk_num_bytes(leaf, fi);
-			if (extent_end <= start) {
+			/*
+			 * If the extent we got ends before our current offset,
+			 * skip to the next extent.
+			 */
+			if (extent_end <= cur_offset) {
 				path->slots[0]++;
 				goto next_slot;
 			}
@@ -4027,7 +4031,6 @@ int btrfs_unlink_subvol(struct btrfs_trans_handle *trans,
 
 		leaf = path->nodes[0];
 		btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
-		btrfs_release_path(path);
 		index = key.offset;
 	}
 	btrfs_release_path(path);
@@ -5140,7 +5143,6 @@ static void inode_tree_del(struct inode *inode)
 	spin_unlock(&root->inode_lock);
 
 	if (empty && btrfs_root_refs(&root->root_item) == 0) {
-		synchronize_srcu(&root->fs_info->subvol_srcu);
 		spin_lock(&root->inode_lock);
 		empty = RB_EMPTY_ROOT(&root->inode_tree);
 		spin_unlock(&root->inode_lock);
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 379c88b17c07..c4c26586318d 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -580,12 +580,18 @@ static noinline int create_subvol(struct inode *dir,
 
 	btrfs_i_size_write(dir, dir->i_size + namelen * 2);
 	ret = btrfs_update_inode(trans, root, dir);
-	BUG_ON(ret);
+	if (ret) {
+		btrfs_abort_transaction(trans, root, ret);
+		goto fail;
+	}
 
 	ret = btrfs_add_root_ref(trans, root->fs_info->tree_root,
 				 objectid, root->root_key.objectid,
 				 btrfs_ino(dir), index, name, namelen);
-	BUG_ON(ret);
+	if (ret) {
+		btrfs_abort_transaction(trans, root, ret);
+		goto fail;
+	}
 
 	ret = btrfs_uuid_tree_add(trans, root->fs_info->uuid_root,
 				  root_item.uuid, BTRFS_UUID_KEY_SUBVOL,
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index 9cba36820c72..54d79d8af015 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -4449,6 +4449,7 @@ int btrfs_recover_relocation(struct btrfs_root *root)
 				       reloc_root->root_key.offset);
 		if (IS_ERR(fs_root)) {
 			err = PTR_ERR(fs_root);
+			list_add_tail(&reloc_root->root_list, &reloc_roots);
 			goto out_free;
 		}
 
diff --git a/fs/btrfs/root-tree.c b/fs/btrfs/root-tree.c
index 360a728a639f..9bdcae8336ff 100644
--- a/fs/btrfs/root-tree.c
+++ b/fs/btrfs/root-tree.c
@@ -373,11 +373,13 @@ int btrfs_del_root_ref(struct btrfs_trans_handle *trans,
 		leaf = path->nodes[0];
 		ref = btrfs_item_ptr(leaf, path->slots[0],
 				     struct btrfs_root_ref);
-
-		WARN_ON(btrfs_root_ref_dirid(leaf, ref) != dirid);
-		WARN_ON(btrfs_root_ref_name_len(leaf, ref) != name_len);
 		ptr = (unsigned long)(ref + 1);
-		WARN_ON(memcmp_extent_buffer(leaf, name, ptr, name_len));
+		if ((btrfs_root_ref_dirid(leaf, ref) != dirid) ||
+		    (btrfs_root_ref_name_len(leaf, ref) != name_len) ||
+		    memcmp_extent_buffer(leaf, name, ptr, name_len)) {
+			err = -ENOENT;
+			goto out;
+		}
 		*sequence = btrfs_root_ref_sequence(leaf, ref);
 
 		ret = btrfs_del_item(trans, tree_root, path);
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c
index 70edd60db654..e3a687c472ec 100644
--- a/fs/btrfs/scrub.c
+++ b/fs/btrfs/scrub.c
@@ -2637,7 +2637,7 @@ static noinline_for_stack int scrub_chunk(struct scrub_ctx *sctx,
 	if (!em)
 		return -EINVAL;
 
-	map = (struct map_lookup *)em->bdev;
+	map = em->map_lookup;
 	if (em->start != chunk_offset)
 		goto out;
 
diff --git a/fs/btrfs/struct-funcs.c b/fs/btrfs/struct-funcs.c
index b976597b0721..63ffd213b0b7 100644
--- a/fs/btrfs/struct-funcs.c
+++ b/fs/btrfs/struct-funcs.c
@@ -50,8 +50,8 @@ static inline void put_unaligned_le8(u8 val, void *p)
  */
 
 #define DEFINE_BTRFS_SETGET_BITS(bits)					\
-u##bits btrfs_get_token_##bits(struct extent_buffer *eb, void *ptr,	\
-			       unsigned long off,			\
+u##bits btrfs_get_token_##bits(const struct extent_buffer *eb,		\
+			       const void *ptr, unsigned long off,	\
 			       struct btrfs_map_token *token)		\
 {									\
 	unsigned long part_offset = (unsigned long)ptr;			\
@@ -90,7 +90,8 @@ u##bits btrfs_get_token_##bits(struct extent_buffer *eb, void *ptr,	\
 	return res;							\
 }									\
 void btrfs_set_token_##bits(struct extent_buffer *eb,			\
-			    void *ptr, unsigned long off, u##bits val,	\
+			    const void *ptr, unsigned long off,		\
+			    u##bits val,				\
 			    struct btrfs_map_token *token)		\
 {									\
 	unsigned long part_offset = (unsigned long)ptr;			\
@@ -133,7 +134,7 @@ DEFINE_BTRFS_SETGET_BITS(16)
 DEFINE_BTRFS_SETGET_BITS(32)
 DEFINE_BTRFS_SETGET_BITS(64)
 
-void btrfs_node_key(struct extent_buffer *eb,
+void btrfs_node_key(const struct extent_buffer *eb,
 		    struct btrfs_disk_key *disk_key, int nr)
 {
 	unsigned long ptr = btrfs_node_key_ptr_offset(nr);
diff --git a/fs/btrfs/tree-checker.c b/fs/btrfs/tree-checker.c
new file mode 100644
index 000000000000..5b98f3c76ce4
--- /dev/null
+++ b/fs/btrfs/tree-checker.c
@@ -0,0 +1,649 @@
+/*
+ * Copyright (C) Qu Wenruo 2017.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License v2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program.
+ */
+
+/*
+ * The module is used to catch unexpected/corrupted tree block data.
+ * Such behavior can be caused either by a fuzzed image or bugs.
+ *
+ * The objective is to do leaf/node validation checks when tree block is read
+ * from disk, and check *every* possible member, so other code won't
+ * need to checking them again.
+ *
+ * Due to the potential and unwanted damage, every checker needs to be
+ * carefully reviewed otherwise so it does not prevent mount of valid images.
+ */
+
+#include "ctree.h"
+#include "tree-checker.h"
+#include "disk-io.h"
+#include "compression.h"
+#include "hash.h"
+#include "volumes.h"
+
+#define CORRUPT(reason, eb, root, slot)					\
+	btrfs_crit(root->fs_info,					\
+		   "corrupt %s, %s: block=%llu, root=%llu, slot=%d",	\
+		   btrfs_header_level(eb) == 0 ? "leaf" : "node",	\
+		   reason, btrfs_header_bytenr(eb), root->objectid, slot)
+
+/*
+ * Error message should follow the following format:
+ * corrupt <type>: <identifier>, <reason>[, <bad_value>]
+ *
+ * @type:	leaf or node
+ * @identifier:	the necessary info to locate the leaf/node.
+ * 		It's recommened to decode key.objecitd/offset if it's
+ * 		meaningful.
+ * @reason:	describe the error
+ * @bad_value:	optional, it's recommened to output bad value and its
+ *		expected value (range).
+ *
+ * Since comma is used to separate the components, only space is allowed
+ * inside each component.
+ */
+
+/*
+ * Append generic "corrupt leaf/node root=%llu block=%llu slot=%d: " to @fmt.
+ * Allows callers to customize the output.
+ */
+__printf(4, 5)
+static void generic_err(const struct btrfs_root *root,
+			const struct extent_buffer *eb, int slot,
+			const char *fmt, ...)
+{
+	struct va_format vaf;
+	va_list args;
+
+	va_start(args, fmt);
+
+	vaf.fmt = fmt;
+	vaf.va = &args;
+
+	btrfs_crit(root->fs_info,
+		"corrupt %s: root=%llu block=%llu slot=%d, %pV",
+		btrfs_header_level(eb) == 0 ? "leaf" : "node",
+		root->objectid, btrfs_header_bytenr(eb), slot, &vaf);
+	va_end(args);
+}
+
+static int check_extent_data_item(struct btrfs_root *root,
+				  struct extent_buffer *leaf,
+				  struct btrfs_key *key, int slot)
+{
+	struct btrfs_file_extent_item *fi;
+	u32 sectorsize = root->sectorsize;
+	u32 item_size = btrfs_item_size_nr(leaf, slot);
+
+	if (!IS_ALIGNED(key->offset, sectorsize)) {
+		CORRUPT("unaligned key offset for file extent",
+			leaf, root, slot);
+		return -EUCLEAN;
+	}
+
+	fi = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item);
+
+	if (btrfs_file_extent_type(leaf, fi) > BTRFS_FILE_EXTENT_TYPES) {
+		CORRUPT("invalid file extent type", leaf, root, slot);
+		return -EUCLEAN;
+	}
+
+	/*
+	 * Support for new compression/encrption must introduce incompat flag,
+	 * and must be caught in open_ctree().
+	 */
+	if (btrfs_file_extent_compression(leaf, fi) > BTRFS_COMPRESS_TYPES) {
+		CORRUPT("invalid file extent compression", leaf, root, slot);
+		return -EUCLEAN;
+	}
+	if (btrfs_file_extent_encryption(leaf, fi)) {
+		CORRUPT("invalid file extent encryption", leaf, root, slot);
+		return -EUCLEAN;
+	}
+	if (btrfs_file_extent_type(leaf, fi) == BTRFS_FILE_EXTENT_INLINE) {
+		/* Inline extent must have 0 as key offset */
+		if (key->offset) {
+			CORRUPT("inline extent has non-zero key offset",
+				leaf, root, slot);
+			return -EUCLEAN;
+		}
+
+		/* Compressed inline extent has no on-disk size, skip it */
+		if (btrfs_file_extent_compression(leaf, fi) !=
+		    BTRFS_COMPRESS_NONE)
+			return 0;
+
+		/* Uncompressed inline extent size must match item size */
+		if (item_size != BTRFS_FILE_EXTENT_INLINE_DATA_START +
+		    btrfs_file_extent_ram_bytes(leaf, fi)) {
+			CORRUPT("plaintext inline extent has invalid size",
+				leaf, root, slot);
+			return -EUCLEAN;
+		}
+		return 0;
+	}
+
+	/* Regular or preallocated extent has fixed item size */
+	if (item_size != sizeof(*fi)) {
+		CORRUPT(
+		"regluar or preallocated extent data item size is invalid",
+			leaf, root, slot);
+		return -EUCLEAN;
+	}
+	if (!IS_ALIGNED(btrfs_file_extent_ram_bytes(leaf, fi), sectorsize) ||
+	    !IS_ALIGNED(btrfs_file_extent_disk_bytenr(leaf, fi), sectorsize) ||
+	    !IS_ALIGNED(btrfs_file_extent_disk_num_bytes(leaf, fi), sectorsize) ||
+	    !IS_ALIGNED(btrfs_file_extent_offset(leaf, fi), sectorsize) ||
+	    !IS_ALIGNED(btrfs_file_extent_num_bytes(leaf, fi), sectorsize)) {
+		CORRUPT(
+		"regular or preallocated extent data item has unaligned value",
+			leaf, root, slot);
+		return -EUCLEAN;
+	}
+
+	return 0;
+}
+
+static int check_csum_item(struct btrfs_root *root, struct extent_buffer *leaf,
+			   struct btrfs_key *key, int slot)
+{
+	u32 sectorsize = root->sectorsize;
+	u32 csumsize = btrfs_super_csum_size(root->fs_info->super_copy);
+
+	if (key->objectid != BTRFS_EXTENT_CSUM_OBJECTID) {
+		CORRUPT("invalid objectid for csum item", leaf, root, slot);
+		return -EUCLEAN;
+	}
+	if (!IS_ALIGNED(key->offset, sectorsize)) {
+		CORRUPT("unaligned key offset for csum item", leaf, root, slot);
+		return -EUCLEAN;
+	}
+	if (!IS_ALIGNED(btrfs_item_size_nr(leaf, slot), csumsize)) {
+		CORRUPT("unaligned csum item size", leaf, root, slot);
+		return -EUCLEAN;
+	}
+	return 0;
+}
+
+/*
+ * Customized reported for dir_item, only important new info is key->objectid,
+ * which represents inode number
+ */
+__printf(4, 5)
+static void dir_item_err(const struct btrfs_root *root,
+			 const struct extent_buffer *eb, int slot,
+			 const char *fmt, ...)
+{
+	struct btrfs_key key;
+	struct va_format vaf;
+	va_list args;
+
+	btrfs_item_key_to_cpu(eb, &key, slot);
+	va_start(args, fmt);
+
+	vaf.fmt = fmt;
+	vaf.va = &args;
+
+	btrfs_crit(root->fs_info,
+	"corrupt %s: root=%llu block=%llu slot=%d ino=%llu, %pV",
+		btrfs_header_level(eb) == 0 ? "leaf" : "node", root->objectid,
+		btrfs_header_bytenr(eb), slot, key.objectid, &vaf);
+	va_end(args);
+}
+
+static int check_dir_item(struct btrfs_root *root,
+			  struct extent_buffer *leaf,
+			  struct btrfs_key *key, int slot)
+{
+	struct btrfs_dir_item *di;
+	u32 item_size = btrfs_item_size_nr(leaf, slot);
+	u32 cur = 0;
+
+	di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item);
+	while (cur < item_size) {
+		u32 name_len;
+		u32 data_len;
+		u32 max_name_len;
+		u32 total_size;
+		u32 name_hash;
+		u8 dir_type;
+
+		/* header itself should not cross item boundary */
+		if (cur + sizeof(*di) > item_size) {
+			dir_item_err(root, leaf, slot,
+		"dir item header crosses item boundary, have %zu boundary %u",
+				cur + sizeof(*di), item_size);
+			return -EUCLEAN;
+		}
+
+		/* dir type check */
+		dir_type = btrfs_dir_type(leaf, di);
+		if (dir_type >= BTRFS_FT_MAX) {
+			dir_item_err(root, leaf, slot,
+			"invalid dir item type, have %u expect [0, %u)",
+				dir_type, BTRFS_FT_MAX);
+			return -EUCLEAN;
+		}
+
+		if (key->type == BTRFS_XATTR_ITEM_KEY &&
+		    dir_type != BTRFS_FT_XATTR) {
+			dir_item_err(root, leaf, slot,
+		"invalid dir item type for XATTR key, have %u expect %u",
+				dir_type, BTRFS_FT_XATTR);
+			return -EUCLEAN;
+		}
+		if (dir_type == BTRFS_FT_XATTR &&
+		    key->type != BTRFS_XATTR_ITEM_KEY) {
+			dir_item_err(root, leaf, slot,
+			"xattr dir type found for non-XATTR key");
+			return -EUCLEAN;
+		}
+		if (dir_type == BTRFS_FT_XATTR)
+			max_name_len = XATTR_NAME_MAX;
+		else
+			max_name_len = BTRFS_NAME_LEN;
+
+		/* Name/data length check */
+		name_len = btrfs_dir_name_len(leaf, di);
+		data_len = btrfs_dir_data_len(leaf, di);
+		if (name_len > max_name_len) {
+			dir_item_err(root, leaf, slot,
+			"dir item name len too long, have %u max %u",
+				name_len, max_name_len);
+			return -EUCLEAN;
+		}
+		if (name_len + data_len > BTRFS_MAX_XATTR_SIZE(root)) {
+			dir_item_err(root, leaf, slot,
+			"dir item name and data len too long, have %u max %zu",
+				name_len + data_len,
+				BTRFS_MAX_XATTR_SIZE(root));
+			return -EUCLEAN;
+		}
+
+		if (data_len && dir_type != BTRFS_FT_XATTR) {
+			dir_item_err(root, leaf, slot,
+			"dir item with invalid data len, have %u expect 0",
+				data_len);
+			return -EUCLEAN;
+		}
+
+		total_size = sizeof(*di) + name_len + data_len;
+
+		/* header and name/data should not cross item boundary */
+		if (cur + total_size > item_size) {
+			dir_item_err(root, leaf, slot,
+		"dir item data crosses item boundary, have %u boundary %u",
+				cur + total_size, item_size);
+			return -EUCLEAN;
+		}
+
+		/*
+		 * Special check for XATTR/DIR_ITEM, as key->offset is name
+		 * hash, should match its name
+		 */
+		if (key->type == BTRFS_DIR_ITEM_KEY ||
+		    key->type == BTRFS_XATTR_ITEM_KEY) {
+			char namebuf[max(BTRFS_NAME_LEN, XATTR_NAME_MAX)];
+
+			read_extent_buffer(leaf, namebuf,
+					(unsigned long)(di + 1), name_len);
+			name_hash = btrfs_name_hash(namebuf, name_len);
+			if (key->offset != name_hash) {
+				dir_item_err(root, leaf, slot,
+		"name hash mismatch with key, have 0x%016x expect 0x%016llx",
+					name_hash, key->offset);
+				return -EUCLEAN;
+			}
+		}
+		cur += total_size;
+		di = (struct btrfs_dir_item *)((void *)di + total_size);
+	}
+	return 0;
+}
+
+__printf(4, 5)
+__cold
+static void block_group_err(const struct btrfs_fs_info *fs_info,
+			    const struct extent_buffer *eb, int slot,
+			    const char *fmt, ...)
+{
+	struct btrfs_key key;
+	struct va_format vaf;
+	va_list args;
+
+	btrfs_item_key_to_cpu(eb, &key, slot);
+	va_start(args, fmt);
+
+	vaf.fmt = fmt;
+	vaf.va = &args;
+
+	btrfs_crit(fs_info,
+	"corrupt %s: root=%llu block=%llu slot=%d bg_start=%llu bg_len=%llu, %pV",
+		btrfs_header_level(eb) == 0 ? "leaf" : "node",
+		btrfs_header_owner(eb), btrfs_header_bytenr(eb), slot,
+		key.objectid, key.offset, &vaf);
+	va_end(args);
+}
+
+static int check_block_group_item(struct btrfs_fs_info *fs_info,
+				  struct extent_buffer *leaf,
+				  struct btrfs_key *key, int slot)
+{
+	struct btrfs_block_group_item bgi;
+	u32 item_size = btrfs_item_size_nr(leaf, slot);
+	u64 flags;
+	u64 type;
+
+	/*
+	 * Here we don't really care about alignment since extent allocator can
+	 * handle it.  We care more about the size, as if one block group is
+	 * larger than maximum size, it's must be some obvious corruption.
+	 */
+	if (key->offset > BTRFS_MAX_DATA_CHUNK_SIZE || key->offset == 0) {
+		block_group_err(fs_info, leaf, slot,
+			"invalid block group size, have %llu expect (0, %llu]",
+				key->offset, BTRFS_MAX_DATA_CHUNK_SIZE);
+		return -EUCLEAN;
+	}
+
+	if (item_size != sizeof(bgi)) {
+		block_group_err(fs_info, leaf, slot,
+			"invalid item size, have %u expect %zu",
+				item_size, sizeof(bgi));
+		return -EUCLEAN;
+	}
+
+	read_extent_buffer(leaf, &bgi, btrfs_item_ptr_offset(leaf, slot),
+			   sizeof(bgi));
+	if (btrfs_block_group_chunk_objectid(&bgi) !=
+	    BTRFS_FIRST_CHUNK_TREE_OBJECTID) {
+		block_group_err(fs_info, leaf, slot,
+		"invalid block group chunk objectid, have %llu expect %llu",
+				btrfs_block_group_chunk_objectid(&bgi),
+				BTRFS_FIRST_CHUNK_TREE_OBJECTID);
+		return -EUCLEAN;
+	}
+
+	if (btrfs_block_group_used(&bgi) > key->offset) {
+		block_group_err(fs_info, leaf, slot,
+			"invalid block group used, have %llu expect [0, %llu)",
+				btrfs_block_group_used(&bgi), key->offset);
+		return -EUCLEAN;
+	}
+
+	flags = btrfs_block_group_flags(&bgi);
+	if (hweight64(flags & BTRFS_BLOCK_GROUP_PROFILE_MASK) > 1) {
+		block_group_err(fs_info, leaf, slot,
+"invalid profile flags, have 0x%llx (%lu bits set) expect no more than 1 bit set",
+			flags & BTRFS_BLOCK_GROUP_PROFILE_MASK,
+			hweight64(flags & BTRFS_BLOCK_GROUP_PROFILE_MASK));
+		return -EUCLEAN;
+	}
+
+	type = flags & BTRFS_BLOCK_GROUP_TYPE_MASK;
+	if (type != BTRFS_BLOCK_GROUP_DATA &&
+	    type != BTRFS_BLOCK_GROUP_METADATA &&
+	    type != BTRFS_BLOCK_GROUP_SYSTEM &&
+	    type != (BTRFS_BLOCK_GROUP_METADATA |
+			   BTRFS_BLOCK_GROUP_DATA)) {
+		block_group_err(fs_info, leaf, slot,
+"invalid type, have 0x%llx (%lu bits set) expect either 0x%llx, 0x%llx, 0x%llx or 0x%llx",
+			type, hweight64(type),
+			BTRFS_BLOCK_GROUP_DATA, BTRFS_BLOCK_GROUP_METADATA,
+			BTRFS_BLOCK_GROUP_SYSTEM,
+			BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_DATA);
+		return -EUCLEAN;
+	}
+	return 0;
+}
+
+/*
+ * Common point to switch the item-specific validation.
+ */
+static int check_leaf_item(struct btrfs_root *root,
+			   struct extent_buffer *leaf,
+			   struct btrfs_key *key, int slot)
+{
+	int ret = 0;
+
+	switch (key->type) {
+	case BTRFS_EXTENT_DATA_KEY:
+		ret = check_extent_data_item(root, leaf, key, slot);
+		break;
+	case BTRFS_EXTENT_CSUM_KEY:
+		ret = check_csum_item(root, leaf, key, slot);
+		break;
+	case BTRFS_DIR_ITEM_KEY:
+	case BTRFS_DIR_INDEX_KEY:
+	case BTRFS_XATTR_ITEM_KEY:
+		ret = check_dir_item(root, leaf, key, slot);
+		break;
+	case BTRFS_BLOCK_GROUP_ITEM_KEY:
+		ret = check_block_group_item(root->fs_info, leaf, key, slot);
+		break;
+	}
+	return ret;
+}
+
+static int check_leaf(struct btrfs_root *root, struct extent_buffer *leaf,
+		      bool check_item_data)
+{
+	struct btrfs_fs_info *fs_info = root->fs_info;
+	/* No valid key type is 0, so all key should be larger than this key */
+	struct btrfs_key prev_key = {0, 0, 0};
+	struct btrfs_key key;
+	u32 nritems = btrfs_header_nritems(leaf);
+	int slot;
+
+	if (btrfs_header_level(leaf) != 0) {
+		generic_err(root, leaf, 0,
+			"invalid level for leaf, have %d expect 0",
+			btrfs_header_level(leaf));
+		return -EUCLEAN;
+	}
+
+	/*
+	 * Extent buffers from a relocation tree have a owner field that
+	 * corresponds to the subvolume tree they are based on. So just from an
+	 * extent buffer alone we can not find out what is the id of the
+	 * corresponding subvolume tree, so we can not figure out if the extent
+	 * buffer corresponds to the root of the relocation tree or not. So
+	 * skip this check for relocation trees.
+	 */
+	if (nritems == 0 && !btrfs_header_flag(leaf, BTRFS_HEADER_FLAG_RELOC)) {
+		u64 owner = btrfs_header_owner(leaf);
+		struct btrfs_root *check_root;
+
+		/* These trees must never be empty */
+		if (owner == BTRFS_ROOT_TREE_OBJECTID ||
+		    owner == BTRFS_CHUNK_TREE_OBJECTID ||
+		    owner == BTRFS_EXTENT_TREE_OBJECTID ||
+		    owner == BTRFS_DEV_TREE_OBJECTID ||
+		    owner == BTRFS_FS_TREE_OBJECTID ||
+		    owner == BTRFS_DATA_RELOC_TREE_OBJECTID) {
+			generic_err(root, leaf, 0,
+			"invalid root, root %llu must never be empty",
+				    owner);
+			return -EUCLEAN;
+		}
+		key.objectid = owner;
+		key.type = BTRFS_ROOT_ITEM_KEY;
+		key.offset = (u64)-1;
+
+		check_root = btrfs_get_fs_root(fs_info, &key, false);
+		/*
+		 * The only reason we also check NULL here is that during
+		 * open_ctree() some roots has not yet been set up.
+		 */
+		if (!IS_ERR_OR_NULL(check_root)) {
+			struct extent_buffer *eb;
+
+			eb = btrfs_root_node(check_root);
+			/* if leaf is the root, then it's fine */
+			if (leaf != eb) {
+				CORRUPT("non-root leaf's nritems is 0",
+					leaf, check_root, 0);
+				free_extent_buffer(eb);
+				return -EUCLEAN;
+			}
+			free_extent_buffer(eb);
+		}
+		return 0;
+	}
+
+	if (nritems == 0)
+		return 0;
+
+	/*
+	 * Check the following things to make sure this is a good leaf, and
+	 * leaf users won't need to bother with similar sanity checks:
+	 *
+	 * 1) key ordering
+	 * 2) item offset and size
+	 *    No overlap, no hole, all inside the leaf.
+	 * 3) item content
+	 *    If possible, do comprehensive sanity check.
+	 *    NOTE: All checks must only rely on the item data itself.
+	 */
+	for (slot = 0; slot < nritems; slot++) {
+		u32 item_end_expected;
+		int ret;
+
+		btrfs_item_key_to_cpu(leaf, &key, slot);
+
+		/* Make sure the keys are in the right order */
+		if (btrfs_comp_cpu_keys(&prev_key, &key) >= 0) {
+			CORRUPT("bad key order", leaf, root, slot);
+			return -EUCLEAN;
+		}
+
+		/*
+		 * Make sure the offset and ends are right, remember that the
+		 * item data starts at the end of the leaf and grows towards the
+		 * front.
+		 */
+		if (slot == 0)
+			item_end_expected = BTRFS_LEAF_DATA_SIZE(root);
+		else
+			item_end_expected = btrfs_item_offset_nr(leaf,
+								 slot - 1);
+		if (btrfs_item_end_nr(leaf, slot) != item_end_expected) {
+			CORRUPT("slot offset bad", leaf, root, slot);
+			return -EUCLEAN;
+		}
+
+		/*
+		 * Check to make sure that we don't point outside of the leaf,
+		 * just in case all the items are consistent to each other, but
+		 * all point outside of the leaf.
+		 */
+		if (btrfs_item_end_nr(leaf, slot) >
+		    BTRFS_LEAF_DATA_SIZE(root)) {
+			CORRUPT("slot end outside of leaf", leaf, root, slot);
+			return -EUCLEAN;
+		}
+
+		/* Also check if the item pointer overlaps with btrfs item. */
+		if (btrfs_item_nr_offset(slot) + sizeof(struct btrfs_item) >
+		    btrfs_item_ptr_offset(leaf, slot)) {
+			CORRUPT("slot overlap with its data", leaf, root, slot);
+			return -EUCLEAN;
+		}
+
+		if (check_item_data) {
+			/*
+			 * Check if the item size and content meet other
+			 * criteria
+			 */
+			ret = check_leaf_item(root, leaf, &key, slot);
+			if (ret < 0)
+				return ret;
+		}
+
+		prev_key.objectid = key.objectid;
+		prev_key.type = key.type;
+		prev_key.offset = key.offset;
+	}
+
+	return 0;
+}
+
+int btrfs_check_leaf_full(struct btrfs_root *root, struct extent_buffer *leaf)
+{
+	return check_leaf(root, leaf, true);
+}
+
+int btrfs_check_leaf_relaxed(struct btrfs_root *root,
+			     struct extent_buffer *leaf)
+{
+	return check_leaf(root, leaf, false);
+}
+
+int btrfs_check_node(struct btrfs_root *root, struct extent_buffer *node)
+{
+	unsigned long nr = btrfs_header_nritems(node);
+	struct btrfs_key key, next_key;
+	int slot;
+	int level = btrfs_header_level(node);
+	u64 bytenr;
+	int ret = 0;
+
+	if (level <= 0 || level >= BTRFS_MAX_LEVEL) {
+		generic_err(root, node, 0,
+			"invalid level for node, have %d expect [1, %d]",
+			level, BTRFS_MAX_LEVEL - 1);
+		return -EUCLEAN;
+	}
+	if (nr == 0 || nr > BTRFS_NODEPTRS_PER_BLOCK(root)) {
+		btrfs_crit(root->fs_info,
+"corrupt node: root=%llu block=%llu, nritems too %s, have %lu expect range [1,%zu]",
+			   root->objectid, node->start,
+			   nr == 0 ? "small" : "large", nr,
+			   BTRFS_NODEPTRS_PER_BLOCK(root));
+		return -EUCLEAN;
+	}
+
+	for (slot = 0; slot < nr - 1; slot++) {
+		bytenr = btrfs_node_blockptr(node, slot);
+		btrfs_node_key_to_cpu(node, &key, slot);
+		btrfs_node_key_to_cpu(node, &next_key, slot + 1);
+
+		if (!bytenr) {
+			generic_err(root, node, slot,
+				"invalid NULL node pointer");
+			ret = -EUCLEAN;
+			goto out;
+		}
+		if (!IS_ALIGNED(bytenr, root->sectorsize)) {
+			generic_err(root, node, slot,
+			"unaligned pointer, have %llu should be aligned to %u",
+				bytenr, root->sectorsize);
+			ret = -EUCLEAN;
+			goto out;
+		}
+
+		if (btrfs_comp_cpu_keys(&key, &next_key) >= 0) {
+			generic_err(root, node, slot,
+	"bad key order, current (%llu %u %llu) next (%llu %u %llu)",
+				key.objectid, key.type, key.offset,
+				next_key.objectid, next_key.type,
+				next_key.offset);
+			ret = -EUCLEAN;
+			goto out;
+		}
+	}
+out:
+	return ret;
+}
diff --git a/fs/btrfs/tree-checker.h b/fs/btrfs/tree-checker.h
new file mode 100644
index 000000000000..3d53e8d6fda0
--- /dev/null
+++ b/fs/btrfs/tree-checker.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) Qu Wenruo 2017.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License v2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program.
+ */
+
+#ifndef __BTRFS_TREE_CHECKER__
+#define __BTRFS_TREE_CHECKER__
+
+#include "ctree.h"
+#include "extent_io.h"
+
+/*
+ * Comprehensive leaf checker.
+ * Will check not only the item pointers, but also every possible member
+ * in item data.
+ */
+int btrfs_check_leaf_full(struct btrfs_root *root, struct extent_buffer *leaf);
+
+/*
+ * Less strict leaf checker.
+ * Will only check item pointers, not reading item data.
+ */
+int btrfs_check_leaf_relaxed(struct btrfs_root *root,
+			     struct extent_buffer *leaf);
+int btrfs_check_node(struct btrfs_root *root, struct extent_buffer *node);
+
+#endif
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index f4e90842eb08..323a8f924896 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -4583,9 +4583,29 @@ int btrfs_recover_log_trees(struct btrfs_root *log_root_tree)
 		wc.replay_dest = btrfs_read_fs_root_no_name(fs_info, &tmp_key);
 		if (IS_ERR(wc.replay_dest)) {
 			ret = PTR_ERR(wc.replay_dest);
+
+			/*
+			 * We didn't find the subvol, likely because it was
+			 * deleted.  This is ok, simply skip this log and go to
+			 * the next one.
+			 *
+			 * We need to exclude the root because we can't have
+			 * other log replays overwriting this log as we'll read
+			 * it back in a few more times.  This will keep our
+			 * block from being modified, and we'll just bail for
+			 * each subsequent pass.
+			 */
+			if (ret == -ENOENT)
+				ret = btrfs_pin_extent_for_log_replay(
+							fs_info->extent_root,
+							log->node->start,
+							log->node->len);
 			free_extent_buffer(log->node);
 			free_extent_buffer(log->commit_root);
 			kfree(log);
+
+			if (!ret)
+				goto next;
 			btrfs_error(fs_info, ret, "Couldn't read target root "
 				    "for tree log recovery.");
 			goto error;
@@ -4600,7 +4620,6 @@ int btrfs_recover_log_trees(struct btrfs_root *log_root_tree)
 						      path);
 		}
 
-		key.offset = found_key.offset - 1;
 		wc.replay_dest->log_root = NULL;
 		free_extent_buffer(log->node);
 		free_extent_buffer(log->commit_root);
@@ -4608,9 +4627,10 @@ int btrfs_recover_log_trees(struct btrfs_root *log_root_tree)
 
 		if (ret)
 			goto error;
-
+next:
 		if (found_key.offset == 0)
 			break;
+		key.offset = found_key.offset - 1;
 	}
 	btrfs_release_path(path);
 
diff --git a/fs/btrfs/uuid-tree.c b/fs/btrfs/uuid-tree.c
index f6a4c03ee7d8..dc29f56cc1b3 100644
--- a/fs/btrfs/uuid-tree.c
+++ b/fs/btrfs/uuid-tree.c
@@ -333,6 +333,8 @@ int btrfs_uuid_tree_iterate(struct btrfs_fs_info *fs_info,
 				}
 				if (ret < 0 && ret != -ENOENT)
 					goto out;
+				key.offset++;
+				goto again_search_slot;
 			}
 			item_size -= sizeof(subid_le);
 			offset += sizeof(subid_le);
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 0ff553ed19b0..812b5e1f5697 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -1047,7 +1047,7 @@ static int contains_pending_extent(struct btrfs_trans_handle *trans,
 		struct map_lookup *map;
 		int i;
 
-		map = (struct map_lookup *)em->bdev;
+		map = em->map_lookup;
 		for (i = 0; i < map->num_stripes; i++) {
 			if (map->stripes[i].dev != device)
 				continue;
@@ -2533,7 +2533,7 @@ static int btrfs_relocate_chunk(struct btrfs_root *root,
 
 	BUG_ON(!em || em->start > chunk_offset ||
 	       em->start + em->len < chunk_offset);
-	map = (struct map_lookup *)em->bdev;
+	map = em->map_lookup;
 
 	for (i = 0; i < map->num_stripes; i++) {
 		ret = btrfs_free_dev_extent(trans, map->stripes[i].dev,
@@ -3248,7 +3248,11 @@ int btrfs_balance(struct btrfs_balance_control *bctl,
 		}
 	}
 
-	num_devices = fs_info->fs_devices->num_devices;
+	/*
+	 * rw_devices will not change at the moment, device add/delete/replace
+	 * are excluded by EXCL_OP
+	 */
+	num_devices = fs_info->fs_devices->rw_devices;
 	btrfs_dev_replace_lock(&fs_info->dev_replace);
 	if (btrfs_dev_replace_is_ongoing(&fs_info->dev_replace)) {
 		BUG_ON(num_devices < 1);
@@ -4134,7 +4138,7 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
 
 	if (type & BTRFS_BLOCK_GROUP_DATA) {
 		max_stripe_size = 1024 * 1024 * 1024;
-		max_chunk_size = 10 * max_stripe_size;
+		max_chunk_size = BTRFS_MAX_DATA_CHUNK_SIZE;
 		if (!devs_max)
 			devs_max = BTRFS_MAX_DEVS(info->chunk_root);
 	} else if (type & BTRFS_BLOCK_GROUP_METADATA) {
@@ -4322,7 +4326,7 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
 		goto error;
 	}
 	set_bit(EXTENT_FLAG_FS_MAPPING, &em->flags);
-	em->bdev = (struct block_device *)map;
+	em->map_lookup = map;
 	em->start = start;
 	em->len = num_bytes;
 	em->block_start = 0;
@@ -4405,7 +4409,7 @@ int btrfs_finish_chunk_alloc(struct btrfs_trans_handle *trans,
 		return -EINVAL;
 	}
 
-	map = (struct map_lookup *)em->bdev;
+	map = em->map_lookup;
 	item_size = btrfs_chunk_item_size(map->num_stripes);
 	stripe_size = em->orig_block_len;
 
@@ -4547,7 +4551,7 @@ int btrfs_chunk_readonly(struct btrfs_root *root, u64 chunk_offset)
 		return 0;
 	}
 
-	map = (struct map_lookup *)em->bdev;
+	map = em->map_lookup;
 	for (i = 0; i < map->num_stripes; i++) {
 		if (!map->stripes[i].dev->writeable) {
 			readonly = 1;
@@ -4613,7 +4617,7 @@ int btrfs_num_copies(struct btrfs_fs_info *fs_info, u64 logical, u64 len)
 		return 1;
 	}
 
-	map = (struct map_lookup *)em->bdev;
+	map = em->map_lookup;
 	if (map->type & (BTRFS_BLOCK_GROUP_DUP | BTRFS_BLOCK_GROUP_RAID1))
 		ret = map->num_stripes;
 	else if (map->type & BTRFS_BLOCK_GROUP_RAID10)
@@ -4649,7 +4653,7 @@ unsigned long btrfs_full_stripe_len(struct btrfs_root *root,
 	BUG_ON(!em);
 
 	BUG_ON(em->start > logical || em->start + em->len < logical);
-	map = (struct map_lookup *)em->bdev;
+	map = em->map_lookup;
 	if (map->type & (BTRFS_BLOCK_GROUP_RAID5 |
 			 BTRFS_BLOCK_GROUP_RAID6)) {
 		len = map->stripe_len * nr_data_stripes(map);
@@ -4672,7 +4676,7 @@ int btrfs_is_parity_mirror(struct btrfs_mapping_tree *map_tree,
 	BUG_ON(!em);
 
 	BUG_ON(em->start > logical || em->start + em->len < logical);
-	map = (struct map_lookup *)em->bdev;
+	map = em->map_lookup;
 	if (map->type & (BTRFS_BLOCK_GROUP_RAID5 |
 			 BTRFS_BLOCK_GROUP_RAID6))
 		ret = 1;
@@ -4794,7 +4798,7 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw,
 		return -EINVAL;
 	}
 
-	map = (struct map_lookup *)em->bdev;
+	map = em->map_lookup;
 	offset = logical - em->start;
 
 	stripe_len = map->stripe_len;
@@ -5321,7 +5325,7 @@ int btrfs_rmap_block(struct btrfs_mapping_tree *map_tree,
 		free_extent_map(em);
 		return -EIO;
 	}
-	map = (struct map_lookup *)em->bdev;
+	map = em->map_lookup;
 
 	length = em->len;
 	rmap_len = map->stripe_len;
@@ -5805,6 +5809,101 @@ struct btrfs_device *btrfs_alloc_device(struct btrfs_fs_info *fs_info,
 	return dev;
 }
 
+/* Return -EIO if any error, otherwise return 0. */
+static int btrfs_check_chunk_valid(struct btrfs_root *root,
+				   struct extent_buffer *leaf,
+				   struct btrfs_chunk *chunk, u64 logical)
+{
+	u64 length;
+	u64 stripe_len;
+	u16 num_stripes;
+	u16 sub_stripes;
+	u64 type;
+	u64 features;
+	bool mixed = false;
+
+	length = btrfs_chunk_length(leaf, chunk);
+	stripe_len = btrfs_chunk_stripe_len(leaf, chunk);
+	num_stripes = btrfs_chunk_num_stripes(leaf, chunk);
+	sub_stripes = btrfs_chunk_sub_stripes(leaf, chunk);
+	type = btrfs_chunk_type(leaf, chunk);
+
+	if (!num_stripes) {
+		btrfs_err(root->fs_info, "invalid chunk num_stripes: %u",
+			  num_stripes);
+		return -EIO;
+	}
+	if (!IS_ALIGNED(logical, root->sectorsize)) {
+		btrfs_err(root->fs_info,
+			  "invalid chunk logical %llu", logical);
+		return -EIO;
+	}
+	if (btrfs_chunk_sector_size(leaf, chunk) != root->sectorsize) {
+		btrfs_err(root->fs_info, "invalid chunk sectorsize %u",
+			  btrfs_chunk_sector_size(leaf, chunk));
+		return -EIO;
+	}
+	if (!length || !IS_ALIGNED(length, root->sectorsize)) {
+		btrfs_err(root->fs_info,
+			"invalid chunk length %llu", length);
+		return -EIO;
+	}
+	if (!is_power_of_2(stripe_len)) {
+		btrfs_err(root->fs_info, "invalid chunk stripe length: %llu",
+			  stripe_len);
+		return -EIO;
+	}
+	if (~(BTRFS_BLOCK_GROUP_TYPE_MASK | BTRFS_BLOCK_GROUP_PROFILE_MASK) &
+	    type) {
+		btrfs_err(root->fs_info, "unrecognized chunk type: %llu",
+			  ~(BTRFS_BLOCK_GROUP_TYPE_MASK |
+			    BTRFS_BLOCK_GROUP_PROFILE_MASK) &
+			  btrfs_chunk_type(leaf, chunk));
+		return -EIO;
+	}
+
+	if ((type & BTRFS_BLOCK_GROUP_TYPE_MASK) == 0) {
+		btrfs_err(root->fs_info, "missing chunk type flag: 0x%llx", type);
+		return -EIO;
+	}
+
+	if ((type & BTRFS_BLOCK_GROUP_SYSTEM) &&
+	    (type & (BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_DATA))) {
+		btrfs_err(root->fs_info,
+			"system chunk with data or metadata type: 0x%llx", type);
+		return -EIO;
+	}
+
+	features = btrfs_super_incompat_flags(root->fs_info->super_copy);
+	if (features & BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS)
+		mixed = true;
+
+	if (!mixed) {
+		if ((type & BTRFS_BLOCK_GROUP_METADATA) &&
+		    (type & BTRFS_BLOCK_GROUP_DATA)) {
+			btrfs_err(root->fs_info,
+			"mixed chunk type in non-mixed mode: 0x%llx", type);
+			return -EIO;
+		}
+	}
+
+	if ((type & BTRFS_BLOCK_GROUP_RAID10 && sub_stripes != 2) ||
+	    (type & BTRFS_BLOCK_GROUP_RAID1 && num_stripes != 2) ||
+	    (type & BTRFS_BLOCK_GROUP_RAID5 && num_stripes < 2) ||
+	    (type & BTRFS_BLOCK_GROUP_RAID6 && num_stripes < 3) ||
+	    (type & BTRFS_BLOCK_GROUP_DUP && num_stripes != 2) ||
+	    ((type & BTRFS_BLOCK_GROUP_PROFILE_MASK) == 0 &&
+	     num_stripes != 1)) {
+		btrfs_err(root->fs_info,
+			"invalid num_stripes:sub_stripes %u:%u for profile %llu",
+			num_stripes, sub_stripes,
+			type & BTRFS_BLOCK_GROUP_PROFILE_MASK);
+		return -EIO;
+	}
+
+	return 0;
+}
+
 static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key,
 			  struct extent_buffer *leaf,
 			  struct btrfs_chunk *chunk)
@@ -5814,6 +5913,7 @@ static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key,
 	struct extent_map *em;
 	u64 logical;
 	u64 length;
+	u64 stripe_len;
 	u64 devid;
 	u8 uuid[BTRFS_UUID_SIZE];
 	int num_stripes;
@@ -5822,6 +5922,12 @@ static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key,
 
 	logical = key->offset;
 	length = btrfs_chunk_length(leaf, chunk);
+	stripe_len = btrfs_chunk_stripe_len(leaf, chunk);
+	num_stripes = btrfs_chunk_num_stripes(leaf, chunk);
+
+	ret = btrfs_check_chunk_valid(root, leaf, chunk, logical);
+	if (ret)
+		return ret;
 
 	read_lock(&map_tree->map_tree.lock);
 	em = lookup_extent_mapping(&map_tree->map_tree, logical, 1);
@@ -5838,7 +5944,6 @@ static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key,
 	em = alloc_extent_map();
 	if (!em)
 		return -ENOMEM;
-	num_stripes = btrfs_chunk_num_stripes(leaf, chunk);
 	map = kmalloc(map_lookup_size(num_stripes), GFP_NOFS);
 	if (!map) {
 		free_extent_map(em);
@@ -5846,7 +5951,7 @@ static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key,
 	}
 
 	set_bit(EXTENT_FLAG_FS_MAPPING, &em->flags);
-	em->bdev = (struct block_device *)map;
+	em->map_lookup = map;
 	em->start = logical;
 	em->len = length;
 	em->orig_start = 0;
@@ -6032,13 +6137,14 @@ int btrfs_read_sys_array(struct btrfs_root *root)
 	struct extent_buffer *sb;
 	struct btrfs_disk_key *disk_key;
 	struct btrfs_chunk *chunk;
-	u8 *ptr;
-	unsigned long sb_ptr;
+	u8 *array_ptr;
+	unsigned long sb_array_offset;
 	int ret = 0;
 	u32 num_stripes;
 	u32 array_size;
 	u32 len = 0;
-	u32 cur;
+	u32 cur_offset;
+	u64 type;
 	struct btrfs_key key;
 
 	sb = btrfs_find_create_tree_block(root, BTRFS_SUPER_INFO_OFFSET,
@@ -6065,35 +6171,73 @@ int btrfs_read_sys_array(struct btrfs_root *root)
 	write_extent_buffer(sb, super_copy, 0, BTRFS_SUPER_INFO_SIZE);
 	array_size = btrfs_super_sys_array_size(super_copy);
 
-	ptr = super_copy->sys_chunk_array;
-	sb_ptr = offsetof(struct btrfs_super_block, sys_chunk_array);
-	cur = 0;
+	array_ptr = super_copy->sys_chunk_array;
+	sb_array_offset = offsetof(struct btrfs_super_block, sys_chunk_array);
+	cur_offset = 0;
+
+	while (cur_offset < array_size) {
+		disk_key = (struct btrfs_disk_key *)array_ptr;
+		len = sizeof(*disk_key);
+		if (cur_offset + len > array_size)
+			goto out_short_read;
 
-	while (cur < array_size) {
-		disk_key = (struct btrfs_disk_key *)ptr;
 		btrfs_disk_key_to_cpu(&key, disk_key);
 
-		len = sizeof(*disk_key); ptr += len;
-		sb_ptr += len;
-		cur += len;
+		array_ptr += len;
+		sb_array_offset += len;
+		cur_offset += len;
 
 		if (key.type == BTRFS_CHUNK_ITEM_KEY) {
-			chunk = (struct btrfs_chunk *)sb_ptr;
+			chunk = (struct btrfs_chunk *)sb_array_offset;
+			/*
+			 * At least one btrfs_chunk with one stripe must be
+			 * present, exact stripe count check comes afterwards
+			 */
+			len = btrfs_chunk_item_size(1);
+			if (cur_offset + len > array_size)
+				goto out_short_read;
+
+			num_stripes = btrfs_chunk_num_stripes(sb, chunk);
+			if (!num_stripes) {
+				printk(KERN_ERR
+	    "BTRFS: invalid number of stripes %u in sys_array at offset %u\n",
+					num_stripes, cur_offset);
+				ret = -EIO;
+				break;
+			}
+
+			type = btrfs_chunk_type(sb, chunk);
+			if ((type & BTRFS_BLOCK_GROUP_SYSTEM) == 0) {
+				btrfs_err(root->fs_info,
+			    "invalid chunk type %llu in sys_array at offset %u",
+					type, cur_offset);
+				ret = -EIO;
+				break;
+			}
+
+			len = btrfs_chunk_item_size(num_stripes);
+			if (cur_offset + len > array_size)
+				goto out_short_read;
+
 			ret = read_one_chunk(root, &key, sb, chunk);
 			if (ret)
 				break;
-			num_stripes = btrfs_chunk_num_stripes(sb, chunk);
-			len = btrfs_chunk_item_size(num_stripes);
 		} else {
 			ret = -EIO;
 			break;
 		}
-		ptr += len;
-		sb_ptr += len;
-		cur += len;
+		array_ptr += len;
+		sb_array_offset += len;
+		cur_offset += len;
 	}
 	free_extent_buffer(sb);
 	return ret;
+
+out_short_read:
+	printk(KERN_ERR "BTRFS: sys_array too short to read %u bytes at offset %u\n",
+			len, cur_offset);
+	free_extent_buffer(sb);
+	return -EIO;
 }
 
 int btrfs_read_chunk_tree(struct btrfs_root *root)
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
index 4292c68196ff..9c6a1cfa122d 100644
--- a/fs/btrfs/volumes.h
+++ b/fs/btrfs/volumes.h
@@ -24,6 +24,8 @@
 #include <linux/btrfs.h>
 #include "async-thread.h"
 
+#define BTRFS_MAX_DATA_CHUNK_SIZE	(10ULL * SZ_1G)
+
 #define BTRFS_STRIPE_LEN	(64 * 1024)
 
 struct buffer_head;
diff --git a/fs/char_dev.c b/fs/char_dev.c
index f77f7702fabe..abed99abcf5a 100644
--- a/fs/char_dev.c
+++ b/fs/char_dev.c
@@ -348,7 +348,7 @@ static struct kobject *cdev_get(struct cdev *p)
 
 	if (owner && !try_module_get(owner))
 		return NULL;
-	kobj = kobject_get(&p->kobj);
+	kobj = kobject_get_unless_zero(&p->kobj);
 	if (!kobj)
 		module_put(owner);
 	return kobj;
@@ -488,6 +488,85 @@ int cdev_add(struct cdev *p, dev_t dev, unsigned count)
 	return 0;
 }
 
+/**
+ * cdev_set_parent() - set the parent kobject for a char device
+ * @p: the cdev structure
+ * @kobj: the kobject to take a reference to
+ *
+ * cdev_set_parent() sets a parent kobject which will be referenced
+ * appropriately so the parent is not freed before the cdev. This
+ * should be called before cdev_add.
+ */
+void cdev_set_parent(struct cdev *p, struct kobject *kobj)
+{
+	WARN_ON(!kobj->state_initialized);
+	p->kobj.parent = kobj;
+}
+
+/**
+ * cdev_device_add() - add a char device and it's corresponding
+ *	struct device, linkink
+ * @dev: the device structure
+ * @cdev: the cdev structure
+ *
+ * cdev_device_add() adds the char device represented by @cdev to the system,
+ * just as cdev_add does. It then adds @dev to the system using device_add
+ * The dev_t for the char device will be taken from the struct device which
+ * needs to be initialized first. This helper function correctly takes a
+ * reference to the parent device so the parent will not get released until
+ * all references to the cdev are released.
+ *
+ * This helper uses dev->devt for the device number. If it is not set
+ * it will not add the cdev and it will be equivalent to device_add.
+ *
+ * This function should be used whenever the struct cdev and the
+ * struct device are members of the same structure whose lifetime is
+ * managed by the struct device.
+ *
+ * NOTE: Callers must assume that userspace was able to open the cdev and
+ * can call cdev fops callbacks at any time, even if this function fails.
+ */
+int cdev_device_add(struct cdev *cdev, struct device *dev)
+{
+	int rc = 0;
+
+	if (dev->devt) {
+		cdev_set_parent(cdev, &dev->kobj);
+
+		rc = cdev_add(cdev, dev->devt, 1);
+		if (rc)
+			return rc;
+	}
+
+	rc = device_add(dev);
+	if (rc)
+		cdev_del(cdev);
+
+	return rc;
+}
+
+/**
+ * cdev_device_del() - inverse of cdev_device_add
+ * @dev: the device structure
+ * @cdev: the cdev structure
+ *
+ * cdev_device_del() is a helper function to call cdev_del and device_del.
+ * It should be used whenever cdev_device_add is used.
+ *
+ * If dev->devt is not set it will not remove the cdev and will be equivalent
+ * to device_del.
+ *
+ * NOTE: This guarantees that associated sysfs callbacks are not running
+ * or runnable, however any cdevs already open will remain and their fops
+ * will still be callable even after this function returns.
+ */
+void cdev_device_del(struct cdev *cdev, struct device *dev)
+{
+	device_del(dev);
+	if (dev->devt)
+		cdev_del(cdev);
+}
+
 static void cdev_unmap(dev_t dev, unsigned count)
 {
 	kobj_unmap(cdev_map, dev, count);
@@ -499,6 +578,10 @@ static void cdev_unmap(dev_t dev, unsigned count)
  *
  * cdev_del() removes @p from the system, possibly freeing the structure
  * itself.
+ *
+ * NOTE: This guarantees that cdev device will no longer be able to be
+ * opened, however any cdevs already open will remain and their fops will
+ * still be callable even after cdev_del returns.
  */
 void cdev_del(struct cdev *p)
 {
@@ -589,6 +672,9 @@ EXPORT_SYMBOL(cdev_init);
 EXPORT_SYMBOL(cdev_alloc);
 EXPORT_SYMBOL(cdev_del);
 EXPORT_SYMBOL(cdev_add);
+EXPORT_SYMBOL(cdev_set_parent);
+EXPORT_SYMBOL(cdev_device_add);
+EXPORT_SYMBOL(cdev_device_del);
 EXPORT_SYMBOL(__register_chrdev);
 EXPORT_SYMBOL(__unregister_chrdev);
 EXPORT_SYMBOL(directly_mappable_cdev_bdi);
diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
index 20e6a870d114..4d17006a1b8e 100644
--- a/fs/ext4/dir.c
+++ b/fs/ext4/dir.c
@@ -78,6 +78,11 @@ int __ext4_check_dir_entry(const char *function, unsigned int line,
 		error_msg = "rec_len is too small for name_len";
 	else if (unlikely(((char *) de - buf) + rlen > size))
 		error_msg = "directory entry overrun";
+	else if (unlikely(((char *) de - buf) + rlen >
+			  size - EXT4_DIR_REC_LEN(1) &&
+			  ((char *) de - buf) + rlen != size)) {
+		error_msg = "directory entry too close to block end";
+	}
 	else if (unlikely(le32_to_cpu(de->inode) >
 			le32_to_cpu(EXT4_SB(dir->i_sb)->s_es->s_inodes_count)))
 		error_msg = "inode out of bounds";
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 550a1bfe98d1..09e978818474 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -937,6 +937,15 @@ struct ext4_inode_info {
 	 * by other means, so we have i_data_sem.
 	 */
 	struct rw_semaphore i_data_sem;
+	/*
+	 * i_mmap_sem is for serializing page faults with truncate / punch hole
+	 * operations. We have to make sure that new page cannot be faulted in
+	 * a section of the inode that is being punched. We cannot easily use
+	 * i_data_sem for this since we need protection for the whole punch
+	 * operation and i_data_sem ranks below transaction start so we have
+	 * to occasionally drop it.
+	 */
+	struct rw_semaphore i_mmap_sem;
 	struct inode vfs_inode;
 	struct jbd2_inode *jinode;
 
@@ -2205,6 +2214,7 @@ extern int ext4_chunk_trans_blocks(struct inode *, int nrblocks);
 extern int ext4_zero_partial_blocks(handle_t *handle, struct inode *inode,
 			     loff_t lstart, loff_t lend);
 extern int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf);
+extern int ext4_filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
 extern qsize_t *ext4_get_reserved_space(struct inode *inode);
 extern void ext4_da_update_reserve_space(struct inode *inode,
 					int used, int quota_claim);
@@ -2550,6 +2560,9 @@ static inline int ext4_update_inode_size(struct inode *inode, loff_t newsize)
 	return changed;
 }
 
+int ext4_update_disksize_before_punch(struct inode *inode, loff_t offset,
+				      loff_t len);
+
 struct ext4_group_info {
 	unsigned long   bb_state;
 	struct rb_root  bb_free_root;
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 25620fc51bf3..02dca6c43316 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -4772,7 +4772,6 @@ static long ext4_zero_range(struct file *file, loff_t offset,
 	int partial_begin, partial_end;
 	loff_t start, end;
 	ext4_lblk_t lblk;
-	struct address_space *mapping = inode->i_mapping;
 	unsigned int blkbits = inode->i_blkbits;
 
 	trace_ext4_zero_range(inode, offset, len, mode);
@@ -4787,17 +4786,6 @@ static long ext4_zero_range(struct file *file, loff_t offset,
 			return ret;
 	}
 
-	/*
-	 * Write out all dirty pages to avoid race conditions
-	 * Then release them.
-	 */
-	if (mapping->nrpages && mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) {
-		ret = filemap_write_and_wait_range(mapping, offset,
-						   offset + len - 1);
-		if (ret)
-			return ret;
-	}
-
 	/*
 	 * Round up offset. This is not fallocate, we neet to zero out
 	 * blocks, so convert interior block aligned part of the range to
@@ -4842,6 +4830,10 @@ static long ext4_zero_range(struct file *file, loff_t offset,
 	if (mode & FALLOC_FL_KEEP_SIZE)
 		flags |= EXT4_GET_BLOCKS_KEEP_SIZE;
 
+	/* Wait all existing dio workers, newcomers will block on i_mutex */
+	ext4_inode_block_unlocked_dio(inode);
+	inode_dio_wait(inode);
+
 	/* Preallocate the range including the unaligned edges */
 	if (partial_begin || partial_end) {
 		ret = ext4_alloc_file_blocks(file,
@@ -4850,7 +4842,7 @@ static long ext4_zero_range(struct file *file, loff_t offset,
 				 round_down(offset, 1 << blkbits)) >> blkbits,
 				new_size, flags, mode);
 		if (ret)
-			goto out_mutex;
+			goto out_dio;
 
 	}
 
@@ -4859,16 +4851,23 @@ static long ext4_zero_range(struct file *file, loff_t offset,
 		flags |= (EXT4_GET_BLOCKS_CONVERT_UNWRITTEN |
 			  EXT4_EX_NOCACHE);
 
-		/* Now release the pages and zero block aligned part of pages*/
+		/*
+		 * Prevent page faults from reinstantiating pages we have
+		 * released from page cache.
+		 */
+		down_write(&EXT4_I(inode)->i_mmap_sem);
+		ret = ext4_update_disksize_before_punch(inode, offset, len);
+		if (ret) {
+			up_write(&EXT4_I(inode)->i_mmap_sem);
+			goto out_dio;
+		}
+		/* Now release the pages and zero block aligned part of pages */
 		truncate_pagecache_range(inode, start, end - 1);
 		inode->i_mtime = inode->i_ctime = ext4_current_time(inode);
 
-		/* Wait all existing dio workers, newcomers will block on i_mutex */
-		ext4_inode_block_unlocked_dio(inode);
-		inode_dio_wait(inode);
-
 		ret = ext4_alloc_file_blocks(file, lblk, max_blocks, new_size,
 					     flags, mode);
+		up_write(&EXT4_I(inode)->i_mmap_sem);
 		if (ret)
 			goto out_dio;
 	}
@@ -4985,8 +4984,13 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
 			goto out;
 	}
 
+	/* Wait all existing dio workers, newcomers will block on i_mutex */
+	ext4_inode_block_unlocked_dio(inode);
+	inode_dio_wait(inode);
+
 	ret = ext4_alloc_file_blocks(file, lblk, max_blocks, new_size,
 				     flags, mode);
+	ext4_inode_resume_unlocked_dio(inode);
 	if (ret)
 		goto out;
 
@@ -5454,21 +5458,7 @@ int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len)
 			return ret;
 	}
 
-	/*
-	 * Need to round down offset to be aligned with page size boundary
-	 * for page size > block size.
-	 */
-	ioffset = round_down(offset, PAGE_SIZE);
-
-	/* Write out all dirty pages */
-	ret = filemap_write_and_wait_range(inode->i_mapping, ioffset,
-					   LLONG_MAX);
-	if (ret)
-		return ret;
-
-	/* Take mutex lock */
 	mutex_lock(&inode->i_mutex);
-
 	/*
 	 * There is no need to overlap collapse range with EOF, in which case
 	 * it is effectively a truncate operation
@@ -5484,17 +5474,43 @@ int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len)
 		goto out_mutex;
 	}
 
-	truncate_pagecache(inode, ioffset);
-
 	/* Wait for existing dio to complete */
 	ext4_inode_block_unlocked_dio(inode);
 	inode_dio_wait(inode);
 
+	/*
+	 * Prevent page faults from reinstantiating pages we have released from
+	 * page cache.
+	 */
+	down_write(&EXT4_I(inode)->i_mmap_sem);
+	/*
+	 * Need to round down offset to be aligned with page size boundary
+	 * for page size > block size.
+	 */
+	ioffset = round_down(offset, PAGE_SIZE);
+	/*
+	 * Write tail of the last page before removed range since it will get
+	 * removed from the page cache below.
+	 */
+	ret = filemap_write_and_wait_range(inode->i_mapping, ioffset, offset);
+	if (ret)
+		goto out_mmap;
+	/*
+	 * Write data that will be shifted to preserve them when discarding
+	 * page cache below. We are also protected from pages becoming dirty
+	 * by i_mmap_sem.
+	 */
+	ret = filemap_write_and_wait_range(inode->i_mapping, offset + len,
+					   LLONG_MAX);
+	if (ret)
+		goto out_mmap;
+	truncate_pagecache(inode, ioffset);
+
 	credits = ext4_writepage_trans_blocks(inode);
 	handle = ext4_journal_start(inode, EXT4_HT_TRUNCATE, credits);
 	if (IS_ERR(handle)) {
 		ret = PTR_ERR(handle);
-		goto out_dio;
+		goto out_mmap;
 	}
 
 	down_write(&EXT4_I(inode)->i_data_sem);
@@ -5534,7 +5550,8 @@ int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len)
 
 out_stop:
 	ext4_journal_stop(handle);
-out_dio:
+out_mmap:
+	up_write(&EXT4_I(inode)->i_mmap_sem);
 	ext4_inode_resume_unlocked_dio(inode);
 out_mutex:
 	mutex_unlock(&inode->i_mutex);
diff --git a/fs/ext4/file.c b/fs/ext4/file.c
index 773b653bae51..20c76e3250d9 100644
--- a/fs/ext4/file.c
+++ b/fs/ext4/file.c
@@ -199,7 +199,7 @@ ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
 }
 
 static const struct vm_operations_struct ext4_file_vm_ops = {
-	.fault		= filemap_fault,
+	.fault		= ext4_filemap_fault,
 	.map_pages	= filemap_map_pages,
 	.page_mkwrite   = ext4_page_mkwrite,
 };
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 5e07fcdef52f..66aed5f01784 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -3651,6 +3651,35 @@ int ext4_can_truncate(struct inode *inode)
 	return 0;
 }
 
+/*
+ * We have to make sure i_disksize gets properly updated before we truncate
+ * page cache due to hole punching or zero range. Otherwise i_disksize update
+ * can get lost as it may have been postponed to submission of writeback but
+ * that will never happen after we truncate page cache.
+ */
+int ext4_update_disksize_before_punch(struct inode *inode, loff_t offset,
+				      loff_t len)
+{
+	handle_t *handle;
+	loff_t size = i_size_read(inode);
+
+	WARN_ON(!mutex_is_locked(&inode->i_mutex));
+	if (offset > size || offset + len < size)
+		return 0;
+
+	if (EXT4_I(inode)->i_disksize >= size)
+		return 0;
+
+	handle = ext4_journal_start(inode, EXT4_HT_MISC, 1);
+	if (IS_ERR(handle))
+		return PTR_ERR(handle);
+	ext4_update_i_disksize(inode, size);
+	ext4_mark_inode_dirty(handle, inode);
+	ext4_journal_stop(handle);
+
+	return 0;
+}
+
 /*
  * ext4_punch_hole: punches a hole in a file by releaseing the blocks
  * associated with the given offset and length
@@ -3716,17 +3745,26 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
 
 	}
 
+	/* Wait all existing dio workers, newcomers will block on i_mutex */
+	ext4_inode_block_unlocked_dio(inode);
+	inode_dio_wait(inode);
+
+	/*
+	 * Prevent page faults from reinstantiating pages we have released from
+	 * page cache.
+	 */
+	down_write(&EXT4_I(inode)->i_mmap_sem);
 	first_block_offset = round_up(offset, sb->s_blocksize);
 	last_block_offset = round_down((offset + length), sb->s_blocksize) - 1;
 
 	/* Now release the pages and zero block aligned part of pages*/
-	if (last_block_offset > first_block_offset)
+	if (last_block_offset > first_block_offset) {
+		ret = ext4_update_disksize_before_punch(inode, offset, length);
+		if (ret)
+			goto out_dio;
 		truncate_pagecache_range(inode, first_block_offset,
 					 last_block_offset);
-
-	/* Wait all existing dio workers, newcomers will block on i_mutex */
-	ext4_inode_block_unlocked_dio(inode);
-	inode_dio_wait(inode);
+	}
 
 	if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
 		credits = ext4_writepage_trans_blocks(inode);
@@ -3773,11 +3811,6 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
 	if (IS_SYNC(inode))
 		ext4_handle_sync(handle);
 
-	/* Now release the pages again to reduce race window */
-	if (last_block_offset > first_block_offset)
-		truncate_pagecache_range(inode, first_block_offset,
-					 last_block_offset);
-
 	inode->i_mtime = inode->i_ctime = ext4_current_time(inode);
 	ext4_mark_inode_dirty(handle, inode);
 	if (ret >= 0)
@@ -3785,6 +3818,7 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
 out_stop:
 	ext4_journal_stop(handle);
 out_dio:
+	up_write(&EXT4_I(inode)->i_mmap_sem);
 	ext4_inode_resume_unlocked_dio(inode);
 out_mutex:
 	mutex_unlock(&inode->i_mutex);
@@ -4809,8 +4843,10 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr)
 		ext4_journal_stop(handle);
 	}
 
-	if (attr->ia_valid & ATTR_SIZE && attr->ia_size != inode->i_size) {
+	if (attr->ia_valid & ATTR_SIZE) {
 		handle_t *handle;
+		loff_t oldsize = inode->i_size;
+		int shrink = (attr->ia_size <= inode->i_size);
 
 		if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) {
 			struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
@@ -4818,27 +4854,37 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr)
 			if (attr->ia_size > sbi->s_bitmap_maxbytes)
 				return -EFBIG;
 		}
+		if (!S_ISREG(inode->i_mode))
+			return -EINVAL;
 
 		if (IS_I_VERSION(inode) && attr->ia_size != inode->i_size)
 			inode_inc_iversion(inode);
 
-		if (S_ISREG(inode->i_mode) &&
+		if (ext4_should_order_data(inode) &&
 		    (attr->ia_size < inode->i_size)) {
-			if (ext4_should_order_data(inode)) {
-				error = ext4_begin_ordered_truncate(inode,
+			error = ext4_begin_ordered_truncate(inode,
 							    attr->ia_size);
-				if (error)
-					goto err_out;
-			}
+			if (error)
+				goto err_out;
+		}
+		if (attr->ia_size != inode->i_size) {
 			handle = ext4_journal_start(inode, EXT4_HT_INODE, 3);
 			if (IS_ERR(handle)) {
 				error = PTR_ERR(handle);
 				goto err_out;
 			}
-			if (ext4_handle_valid(handle)) {
+			if (ext4_handle_valid(handle) && shrink) {
 				error = ext4_orphan_add(handle, inode);
 				orphan = 1;
 			}
+			/*
+			 * Update c/mtime on truncate up, ext4_truncate() will
+			 * update c/mtime in shrink case below
+			 */
+			if (!shrink) {
+				inode->i_mtime = ext4_current_time(inode);
+				inode->i_ctime = inode->i_mtime;
+			}
 			down_write(&EXT4_I(inode)->i_data_sem);
 			EXT4_I(inode)->i_disksize = attr->ia_size;
 			rc = ext4_mark_inode_dirty(handle, inode);
@@ -4854,15 +4900,13 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr)
 			up_write(&EXT4_I(inode)->i_data_sem);
 			ext4_journal_stop(handle);
 			if (error) {
-				ext4_orphan_del(NULL, inode);
+				if (orphan)
+					ext4_orphan_del(NULL, inode);
 				goto err_out;
 			}
-		} else {
-			loff_t oldsize = inode->i_size;
-
-			i_size_write(inode, attr->ia_size);
-			pagecache_isize_extended(inode, oldsize, inode->i_size);
 		}
+		if (!shrink)
+			pagecache_isize_extended(inode, oldsize, inode->i_size);
 
 		/*
 		 * Blocks are going to be removed from the inode. Wait
@@ -4877,18 +4921,16 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr)
 			} else
 				ext4_wait_for_tail_page_commit(inode);
 		}
+		down_write(&EXT4_I(inode)->i_mmap_sem);
 		/*
 		 * Truncate pagecache after we've waited for commit
 		 * in data=journal mode to make pages freeable.
 		 */
 			truncate_pagecache(inode, inode->i_size);
+		if (shrink)
+			ext4_truncate(inode);
+		up_write(&EXT4_I(inode)->i_mmap_sem);
 	}
-	/*
-	 * We want to call ext4_truncate() even if attr->ia_size ==
-	 * inode->i_size for cases like truncation of fallocated space
-	 */
-	if (attr->ia_valid & ATTR_SIZE)
-		ext4_truncate(inode);
 
 	if (!rc) {
 		setattr_copy(inode, attr);
@@ -5340,6 +5382,8 @@ int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
 	sb_start_pagefault(inode->i_sb);
 	file_update_time(vma->vm_file);
 
+	down_read(&EXT4_I(inode)->i_mmap_sem);
+
 	ret = ext4_convert_inline_data(inode);
 	if (ret)
 		goto out_ret;
@@ -5413,6 +5457,19 @@ int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
 out_ret:
 	ret = block_page_mkwrite_return(ret);
 out:
+	up_read(&EXT4_I(inode)->i_mmap_sem);
 	sb_end_pagefault(inode->i_sb);
 	return ret;
 }
+
+int ext4_filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+	struct inode *inode = file_inode(vma->vm_file);
+	int err;
+
+	down_read(&EXT4_I(inode)->i_mmap_sem);
+	err = filemap_fault(vma, vmf);
+	up_read(&EXT4_I(inode)->i_mmap_sem);
+
+	return err;
+}
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 7410cca5bf39..a0864cc67b03 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -967,6 +967,7 @@ static void init_once(void *foo)
 	INIT_LIST_HEAD(&ei->i_orphan);
 	init_rwsem(&ei->xattr_sem);
 	init_rwsem(&ei->i_data_sem);
+	init_rwsem(&ei->i_mmap_sem);
 	inode_init_once(&ei->vfs_inode);
 }
 
diff --git a/fs/ext4/truncate.h b/fs/ext4/truncate.h
index 011ba6670d99..c70d06a383e2 100644
--- a/fs/ext4/truncate.h
+++ b/fs/ext4/truncate.h
@@ -10,8 +10,10 @@
  */
 static inline void ext4_truncate_failed_write(struct inode *inode)
 {
+	down_write(&EXT4_I(inode)->i_mmap_sem);
 	truncate_inode_pages(inode->i_mapping, inode->i_size);
 	ext4_truncate(inode);
+	up_write(&EXT4_I(inode)->i_mmap_sem);
 }
 
 /*
diff --git a/fs/inode.c b/fs/inode.c
index 49df50c900ca..dd757025ecbe 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -131,6 +131,7 @@ int inode_init_always(struct super_block *sb, struct inode *inode)
 	inode->i_sb = sb;
 	inode->i_blkbits = sb->s_blocksize_bits;
 	inode->i_flags = 0;
+	atomic64_set(&inode->i_sequence, 0);
 	atomic_set(&inode->i_count, 1);
 	inode->i_op = &empty_iops;
 	inode->i_fop = &empty_fops;
diff --git a/fs/locks.c b/fs/locks.c
index 10bd454eaf98..c5303e2ac167 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -2488,7 +2488,7 @@ static void lock_get_status(struct seq_file *f, struct file_lock *fl,
 				inode->i_sb->s_id, inode->i_ino);
 #else
 		/* userspace relies on this representation of dev_t ;-( */
-		seq_printf(f, "%d %02x:%02x:%ld ", fl_pid,
+		seq_printf(f, "%d %02x:%02x:%lu ", fl_pid,
 				MAJOR(inode->i_sb->s_dev),
 				MINOR(inode->i_sb->s_dev), inode->i_ino);
 #endif
diff --git a/fs/namei.c b/fs/namei.c
index 2ec89079ddbd..aa4e00cb4dd7 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -723,6 +723,8 @@ static inline void put_link(struct nameidata *nd, struct path *link, void *cooki
 
 int sysctl_protected_symlinks __read_mostly = 0;
 int sysctl_protected_hardlinks __read_mostly = 0;
+int sysctl_protected_fifos __read_mostly;
+int sysctl_protected_regular __read_mostly;
 
 /**
  * may_follow_link - Check symlink following for unsafe situations
@@ -837,6 +839,46 @@ static int may_linkat(struct path *link)
 	return -EPERM;
 }
 
+/**
+ * may_create_in_sticky - Check whether an O_CREAT open in a sticky directory
+ *			  should be allowed, or not, on files that already
+ *			  exist.
+ * @dir_mode: mode bits of directory
+ * @dir_uid: owner of directory
+ * @inode: the inode of the file to open
+ *
+ * Block an O_CREAT open of a FIFO (or a regular file) when:
+ *   - sysctl_protected_fifos (or sysctl_protected_regular) is enabled
+ *   - the file already exists
+ *   - we are in a sticky directory
+ *   - we don't own the file
+ *   - the owner of the directory doesn't own the file
+ *   - the directory is world writable
+ * If the sysctl_protected_fifos (or sysctl_protected_regular) is set to 2
+ * the directory doesn't have to be world writable: being group writable will
+ * be enough.
+ *
+ * Returns 0 if the open is allowed, -ve on error.
+ */
+static int may_create_in_sticky(umode_t dir_mode, kuid_t dir_uid,
+				struct inode * const inode)
+{
+	if ((!sysctl_protected_fifos && S_ISFIFO(inode->i_mode)) ||
+	    (!sysctl_protected_regular && S_ISREG(inode->i_mode)) ||
+	    likely(!(dir_mode & S_ISVTX)) ||
+	    uid_eq(inode->i_uid, dir_uid) ||
+	    uid_eq(current_fsuid(), inode->i_uid))
+		return 0;
+
+	if (likely(dir_mode & 0002) ||
+	    (dir_mode & 0020 &&
+	     ((sysctl_protected_fifos >= 2 && S_ISFIFO(inode->i_mode)) ||
+	      (sysctl_protected_regular >= 2 && S_ISREG(inode->i_mode))))) {
+		return -EACCES;
+	}
+	return 0;
+}
+
 static __always_inline int
 follow_link(struct path *link, struct nameidata *nd, void **p)
 {
@@ -2903,6 +2945,8 @@ static int do_last(struct nameidata *nd, struct path *path,
 		   int *opened, struct filename *name)
 {
 	struct dentry *dir = nd->path.dentry;
+	kuid_t dir_uid = nd->inode->i_uid;
+	umode_t dir_mode = nd->inode->i_mode;
 	int open_flag = op->open_flag;
 	bool will_truncate = (open_flag & O_TRUNC) != 0;
 	bool got_write = false;
@@ -3057,9 +3101,15 @@ static int do_last(struct nameidata *nd, struct path *path,
 		return error;
 	}
 	audit_inode(name, nd->path.dentry, 0);
-	error = -EISDIR;
-	if ((open_flag & O_CREAT) && d_is_dir(nd->path.dentry))
-		goto out;
+	if (open_flag & O_CREAT) {
+		error = -EISDIR;
+		if (d_is_dir(nd->path.dentry))
+			goto out;
+		error = may_create_in_sticky(dir_mode, dir_uid,
+					     d_backing_inode(nd->path.dentry));
+		if (unlikely(error))
+			goto out;
+	}
 	error = -ENOTDIR;
 	if ((nd->flags & LOOKUP_DIRECTORY) && !d_can_lookup(nd->path.dentry))
 		goto out;
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index b992a89abde2..5ed3e773c2e0 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -284,6 +284,7 @@ struct queue_limits {
 	unsigned int		max_sectors;
 	unsigned int		max_segment_size;
 	unsigned int		physical_block_size;
+	unsigned int		logical_block_size;
 	unsigned int		alignment_offset;
 	unsigned int		io_min;
 	unsigned int		io_opt;
@@ -292,7 +293,6 @@ struct queue_limits {
 	unsigned int		discard_granularity;
 	unsigned int		discard_alignment;
 
-	unsigned short		logical_block_size;
 	unsigned short		max_segments;
 	unsigned short		max_integrity_segments;
 
@@ -447,7 +447,7 @@ struct request_queue {
 	unsigned int		sg_reserved_size;
 	int			node;
 #ifdef CONFIG_BLK_DEV_IO_TRACE
-	struct blk_trace	*blk_trace;
+	struct blk_trace __rcu	*blk_trace;
 	struct mutex		blk_trace_mutex;
 #endif
 	/*
@@ -1017,7 +1017,7 @@ extern void blk_queue_max_discard_sectors(struct request_queue *q,
 		unsigned int max_discard_sectors);
 extern void blk_queue_max_write_same_sectors(struct request_queue *q,
 		unsigned int max_write_same_sectors);
-extern void blk_queue_logical_block_size(struct request_queue *, unsigned short);
+extern void blk_queue_logical_block_size(struct request_queue *, unsigned int);
 extern void blk_queue_physical_block_size(struct request_queue *, unsigned int);
 extern void blk_queue_alignment_offset(struct request_queue *q,
 				       unsigned int alignment);
@@ -1232,7 +1232,7 @@ static inline unsigned int queue_max_segment_size(struct request_queue *q)
 	return q->limits.max_segment_size;
 }
 
-static inline unsigned short queue_logical_block_size(struct request_queue *q)
+static inline unsigned queue_logical_block_size(struct request_queue *q)
 {
 	int retval = 512;
 
@@ -1242,7 +1242,7 @@ static inline unsigned short queue_logical_block_size(struct request_queue *q)
 	return retval;
 }
 
-static inline unsigned short bdev_logical_block_size(struct block_device *bdev)
+static inline unsigned int bdev_logical_block_size(struct block_device *bdev)
 {
 	return queue_logical_block_size(bdev_get_queue(bdev));
 }
diff --git a/include/linux/blktrace_api.h b/include/linux/blktrace_api.h
index afc1343df3c7..e644bfe50019 100644
--- a/include/linux/blktrace_api.h
+++ b/include/linux/blktrace_api.h
@@ -51,9 +51,13 @@ void __trace_note_message(struct blk_trace *, const char *fmt, ...);
  **/
 #define blk_add_trace_msg(q, fmt, ...)					\
 	do {								\
-		struct blk_trace *bt = (q)->blk_trace;			\
+		struct blk_trace *bt;					\
+									\
+		rcu_read_lock();					\
+		bt = rcu_dereference((q)->blk_trace);			\
 		if (unlikely(bt))					\
 			__trace_note_message(bt, fmt, ##__VA_ARGS__);	\
+		rcu_read_unlock();					\
 	} while (0)
 #define BLK_TN_MAX_MSG		128
 
diff --git a/include/linux/cdev.h b/include/linux/cdev.h
index fb4591977b03..71d087f7eb39 100644
--- a/include/linux/cdev.h
+++ b/include/linux/cdev.h
@@ -4,6 +4,7 @@
 #include <linux/kobject.h>
 #include <linux/kdev_t.h>
 #include <linux/list.h>
+#include <linux/device.h>
 
 struct file_operations;
 struct inode;
@@ -26,6 +27,10 @@ void cdev_put(struct cdev *p);
 
 int cdev_add(struct cdev *, dev_t, unsigned);
 
+void cdev_set_parent(struct cdev *p, struct kobject *kobj);
+int cdev_device_add(struct cdev *cdev, struct device *dev);
+void cdev_device_del(struct cdev *cdev, struct device *dev);
+
 void cdev_del(struct cdev *);
 
 void cd_forget(struct inode *);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 49ca7649e5b5..b4335a6e9c6b 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -61,6 +61,8 @@ extern struct inodes_stat_t inodes_stat;
 extern int leases_enable, lease_break_time;
 extern int sysctl_protected_symlinks;
 extern int sysctl_protected_hardlinks;
+extern int sysctl_protected_fifos;
+extern int sysctl_protected_regular;
 
 struct buffer_head;
 typedef int (get_block_t)(struct inode *inode, sector_t iblock,
@@ -568,6 +570,7 @@ struct inode {
 		struct rcu_head		i_rcu;
 	};
 	u64			i_version;
+	atomic64_t		i_sequence; /* see futex */
 	atomic_t		i_count;
 	atomic_t		i_dio_count;
 	atomic_t		i_writecount;
diff --git a/include/linux/futex.h b/include/linux/futex.h
index 83fe0d85f8db..41563bfa54a1 100644
--- a/include/linux/futex.h
+++ b/include/linux/futex.h
@@ -39,23 +39,26 @@ handle_futex_death(u32 __user *uaddr, struct task_struct *curr,
 
 union futex_key {
 	struct {
+		u64 i_seq;
 		unsigned long pgoff;
-		struct inode *inode;
-		int offset;
+		unsigned int offset;
 	} shared;
 	struct {
+		union {
+			struct mm_struct *mm;
+			u64 __tmp;
+		};
 		unsigned long address;
-		struct mm_struct *mm;
-		int offset;
+		unsigned int offset;
 	} private;
 	struct {
+		u64 ptr;
 		unsigned long word;
-		void *ptr;
-		int offset;
+		unsigned int offset;
 	} both;
 };
 
-#define FUTEX_KEY_INIT (union futex_key) { .both = { .ptr = NULL } }
+#define FUTEX_KEY_INIT (union futex_key) { .both = { .ptr = 0ULL } }
 
 #ifdef CONFIG_FUTEX
 extern void exit_robust_list(struct task_struct *curr);
diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h
index d5569734f672..676cf8d0acca 100644
--- a/include/linux/if_ether.h
+++ b/include/linux/if_ether.h
@@ -28,6 +28,14 @@ static inline struct ethhdr *eth_hdr(const struct sk_buff *skb)
 	return (struct ethhdr *)skb_mac_header(skb);
 }
 
+/* Prefer this version in TX path, instead of
+ * skb_reset_mac_header() + eth_hdr()
+ */
+static inline struct ethhdr *skb_eth_hdr(const struct sk_buff *skb)
+{
+	return (struct ethhdr *)skb->data;
+}
+
 int eth_header_parse(const struct sk_buff *skb, unsigned char *haddr);
 
 extern ssize_t sysfs_format_mac(char *buf, const unsigned char *addr, int len);
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index 2d61b909f414..d947e541cac8 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -107,6 +107,8 @@ extern int __must_check kobject_rename(struct kobject *, const char *new_name);
 extern int __must_check kobject_move(struct kobject *, struct kobject *);
 
 extern struct kobject *kobject_get(struct kobject *kobj);
+extern struct kobject * __must_check kobject_get_unless_zero(
+						struct kobject *kobj);
 extern void kobject_put(struct kobject *kobj);
 
 extern const void *kobject_namespace(struct kobject *kobj);
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
index 44eeef0da186..4c546028b035 100644
--- a/include/linux/mod_devicetable.h
+++ b/include/linux/mod_devicetable.h
@@ -497,9 +497,9 @@ struct platform_device_id {
 
 #define MDIO_MODULE_PREFIX	"mdio:"
 
-#define MDIO_ID_FMT "%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d"
+#define MDIO_ID_FMT "%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u"
 #define MDIO_ID_ARGS(_id) \
-	(_id)>>31, ((_id)>>30) & 1, ((_id)>>29) & 1, ((_id)>>28) & 1,	\
+	((_id)>>31) & 1, ((_id)>>30) & 1, ((_id)>>29) & 1, ((_id)>>28) & 1, \
 	((_id)>>27) & 1, ((_id)>>26) & 1, ((_id)>>25) & 1, ((_id)>>24) & 1, \
 	((_id)>>23) & 1, ((_id)>>22) & 1, ((_id)>>21) & 1, ((_id)>>20) & 1, \
 	((_id)>>19) & 1, ((_id)>>18) & 1, ((_id)>>17) & 1, ((_id)>>16) & 1, \
diff --git a/include/linux/netfilter_arp/arp_tables.h b/include/linux/netfilter_arp/arp_tables.h
index cfb7191e6efa..f817d1866428 100644
--- a/include/linux/netfilter_arp/arp_tables.h
+++ b/include/linux/netfilter_arp/arp_tables.h
@@ -51,7 +51,7 @@ extern void *arpt_alloc_initial_table(const struct xt_table *);
 extern struct xt_table *arpt_register_table(struct net *net,
 					    const struct xt_table *table,
 					    const struct arpt_replace *repl);
-extern void arpt_unregister_table(struct xt_table *table);
+extern void arpt_unregister_table(struct net *, struct xt_table *table);
 extern unsigned int arpt_do_table(struct sk_buff *skb,
 				  unsigned int hook,
 				  const struct net_device *in,
diff --git a/include/linux/posix-clock.h b/include/linux/posix-clock.h
index 34c4498b800f..6b192187c7ba 100644
--- a/include/linux/posix-clock.h
+++ b/include/linux/posix-clock.h
@@ -104,29 +104,32 @@ struct posix_clock_operations {
  *
  * @ops:     Functional interface to the clock
  * @cdev:    Character device instance for this clock
- * @kref:    Reference count.
+ * @dev:     Pointer to the clock's device.
  * @rwsem:   Protects the 'zombie' field from concurrent access.
  * @zombie:  If 'zombie' is true, then the hardware has disappeared.
- * @release: A function to free the structure when the reference count reaches
- *           zero. May be NULL if structure is statically allocated.
  *
  * Drivers should embed their struct posix_clock within a private
  * structure, obtaining a reference to it during callbacks using
  * container_of().
+ *
+ * Drivers should supply an initialized but not exposed struct device
+ * to posix_clock_register(). It is used to manage lifetime of the
+ * driver's private structure. It's 'release' field should be set to
+ * a release function for this private structure.
  */
 struct posix_clock {
 	struct posix_clock_operations ops;
 	struct cdev cdev;
-	struct kref kref;
+	struct device *dev;
 	struct rw_semaphore rwsem;
 	bool zombie;
-	void (*release)(struct posix_clock *clk);
 };
 
 /**
  * posix_clock_register() - register a new clock
- * @clk:   Pointer to the clock. Caller must provide 'ops' and 'release'
- * @devid: Allocated device id
+ * @clk:   Pointer to the clock. Caller must provide 'ops' field
+ * @dev:   Pointer to the initialized device. Caller must provide
+ *         'release' field
  *
  * A clock driver calls this function to register itself with the
  * clock device subsystem. If 'clk' points to dynamically allocated
@@ -135,7 +138,7 @@ struct posix_clock {
  *
  * Returns zero on success, non-zero otherwise.
  */
-int posix_clock_register(struct posix_clock *clk, dev_t devid);
+int posix_clock_register(struct posix_clock *clk, struct device *dev);
 
 /**
  * posix_clock_unregister() - unregister a clock
diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h
index c2c41f6a65e2..660f59f3dcd1 100644
--- a/include/linux/quotaops.h
+++ b/include/linux/quotaops.h
@@ -21,7 +21,7 @@ static inline struct quota_info *sb_dqopt(struct super_block *sb)
 /* i_mutex must being held */
 static inline bool is_quota_modification(struct inode *inode, struct iattr *ia)
 {
-	return (ia->ia_valid & ATTR_SIZE && ia->ia_size != inode->i_size) ||
+	return (ia->ia_valid & ATTR_SIZE) ||
 		(ia->ia_valid & ATTR_UID && !uid_eq(ia->ia_uid, inode->i_uid)) ||
 		(ia->ia_valid & ATTR_GID && !gid_eq(ia->ia_gid, inode->i_gid));
 }
diff --git a/include/linux/usb/quirks.h b/include/linux/usb/quirks.h
index efc4e51c425a..b0a25fdfb1be 100644
--- a/include/linux/usb/quirks.h
+++ b/include/linux/usb/quirks.h
@@ -62,4 +62,7 @@
 /* Hub needs extra delay after resetting its port. */
 #define USB_QUIRK_HUB_SLOW_RESET		BIT(14)
 
+/* device has blacklisted endpoints */
+#define USB_QUIRK_ENDPOINT_BLACKLIST		BIT(15)
+
 #endif /* __LINUX_USB_QUIRKS_H */
diff --git a/include/media/media-device.h b/include/media/media-device.h
index 6e6db78f1ee2..00bbd679864a 100644
--- a/include/media/media-device.h
+++ b/include/media/media-device.h
@@ -60,7 +60,7 @@ struct device;
 struct media_device {
 	/* dev->driver_data points to this struct. */
 	struct device *dev;
-	struct media_devnode devnode;
+	struct media_devnode *devnode;
 
 	char model[32];
 	char serial[40];
@@ -84,9 +84,6 @@ struct media_device {
 #define MEDIA_DEV_NOTIFY_PRE_LINK_CH	0
 #define MEDIA_DEV_NOTIFY_POST_LINK_CH	1
 
-/* media_devnode to media_device */
-#define to_media_device(node) container_of(node, struct media_device, devnode)
-
 int __must_check __media_device_register(struct media_device *mdev,
 					 struct module *owner);
 #define media_device_register(mdev) __media_device_register(mdev, THIS_MODULE)
diff --git a/include/media/media-devnode.h b/include/media/media-devnode.h
index 0dc7060f9625..6b370e97efae 100644
--- a/include/media/media-devnode.h
+++ b/include/media/media-devnode.h
@@ -33,6 +33,8 @@
 #include <linux/device.h>
 #include <linux/cdev.h>
 
+struct media_device;
+
 /*
  * Flag to mark the media_devnode struct as registered. Drivers must not touch
  * this flag directly, it will be set and cleared by media_devnode_register and
@@ -63,6 +65,8 @@ struct media_file_operations {
  * before registering the node.
  */
 struct media_devnode {
+	struct media_device *media_dev;
+
 	/* device ops */
 	const struct media_file_operations *fops;
 
@@ -76,24 +80,42 @@ struct media_devnode {
 	unsigned long flags;		/* Use bitops to access flags */
 
 	/* callbacks */
-	void (*release)(struct media_devnode *mdev);
+	void (*release)(struct media_devnode *devnode);
 };
 
 /* dev to media_devnode */
 #define to_media_devnode(cd) container_of(cd, struct media_devnode, dev)
 
-int __must_check media_devnode_register(struct media_devnode *mdev,
+int __must_check media_devnode_register(struct media_device *mdev,
+					struct media_devnode *devnode,
 					struct module *owner);
-void media_devnode_unregister(struct media_devnode *mdev);
+
+/**
+ * media_devnode_unregister_prepare - clear the media device node register bit
+ * @devnode: the device node to prepare for unregister
+ *
+ * This clears the passed device register bit. Future open calls will be met
+ * with errors. Should be called before media_devnode_unregister() to avoid
+ * races with unregister and device file open calls.
+ *
+ * This function can safely be called if the device node has never been
+ * registered or has already been unregistered.
+ */
+void media_devnode_unregister_prepare(struct media_devnode *devnode);
+
+void media_devnode_unregister(struct media_devnode *devnode);
 
 static inline struct media_devnode *media_devnode_data(struct file *filp)
 {
 	return filp->private_data;
 }
 
-static inline int media_devnode_is_registered(struct media_devnode *mdev)
+static inline int media_devnode_is_registered(struct media_devnode *devnode)
 {
-	return test_bit(MEDIA_FLAG_REGISTERED, &mdev->flags);
+	if (!devnode)
+		return false;
+
+	return test_bit(MEDIA_FLAG_REGISTERED, &devnode->flags);
 }
 
 #endif /* _MEDIA_DEVNODE_H */
diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index c9766ab9c87c..19d0e56375f7 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -156,8 +156,9 @@ struct ipv6_stub {
 				 const struct in6_addr *addr);
 	int (*ipv6_sock_mc_drop)(struct sock *sk, int ifindex,
 				 const struct in6_addr *addr);
-	int (*ipv6_dst_lookup)(struct sock *sk, struct dst_entry **dst,
-				struct flowi6 *fl6);
+	struct dst_entry *(*ipv6_dst_lookup_flow)(struct sock *sk,
+						  struct flowi6 *fl6,
+						  const struct in6_addr *final_dst);
 	void (*udpv6_encap_enable)(void);
 	void (*ndisc_send_na)(struct net_device *dev, struct neighbour *neigh,
 			      const struct in6_addr *daddr,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 5d636bbd81a9..e1e51d674c2a 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -3626,6 +3626,17 @@ const u8 *cfg80211_find_ie(u8 eid, const u8 *ies, int len);
 const u8 *cfg80211_find_vendor_ie(unsigned int oui, u8 oui_type,
 				  const u8 *ies, int len);
 
+/**
+ * cfg80211_send_layer2_update - send layer 2 update frame
+ *
+ * @dev: network device
+ * @addr: STA MAC address
+ *
+ * Wireless drivers can use this function to update forwarding tables in bridge
+ * devices upon STA association.
+ */
+void cfg80211_send_layer2_update(struct net_device *dev, const u8 *addr);
+
 /**
  * DOC: Regulatory enforcement infrastructure
  *
diff --git a/include/net/neighbour.h b/include/net/neighbour.h
index 47f425464f84..c24981a8d1a8 100644
--- a/include/net/neighbour.h
+++ b/include/net/neighbour.h
@@ -71,7 +71,6 @@ struct neigh_parms {
 	struct net_device *dev;
 	struct neigh_parms *next;
 	int	(*neigh_setup)(struct neighbour *);
-	void	(*neigh_cleanup)(struct neighbour *);
 	struct neigh_table *tbl;
 
 	void	*sysctl_table;
diff --git a/kernel/futex.c b/kernel/futex.c
index 7976a19877e4..4efd512b062d 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -309,9 +309,9 @@ static inline int hb_waiters_pending(struct futex_hash_bucket *hb)
  */
 static struct futex_hash_bucket *hash_futex(union futex_key *key)
 {
-	u32 hash = jhash2((u32*)&key->both.word,
-			  (sizeof(key->both.word)+sizeof(key->both.ptr))/4,
+	u32 hash = jhash2((u32 *)key, offsetof(typeof(*key), both.offset) / 4,
 			  key->both.offset);
+
 	return &futex_queues[hash & (futex_hashsize - 1)];
 }
 
@@ -338,7 +338,7 @@ static void get_futex_key_refs(union futex_key *key)
 
 	switch (key->both.offset & (FUT_OFF_INODE|FUT_OFF_MMSHARED)) {
 	case FUT_OFF_INODE:
-		ihold(key->shared.inode); /* implies MB (B) */
+		smp_mb();		/* explicit smp_mb(); (B) */
 		break;
 	case FUT_OFF_MMSHARED:
 		futex_get_mm(key); /* implies MB (B) */
@@ -362,7 +362,6 @@ static void drop_futex_key_refs(union futex_key *key)
 
 	switch (key->both.offset & (FUT_OFF_INODE|FUT_OFF_MMSHARED)) {
 	case FUT_OFF_INODE:
-		iput(key->shared.inode);
 		break;
 	case FUT_OFF_MMSHARED:
 		mmdrop(key->private.mm);
@@ -370,6 +369,46 @@ static void drop_futex_key_refs(union futex_key *key)
 	}
 }
 
+/*
+ * Generate a machine wide unique identifier for this inode.
+ *
+ * This relies on u64 not wrapping in the life-time of the machine; which with
+ * 1ns resolution means almost 585 years.
+ *
+ * This further relies on the fact that a well formed program will not unmap
+ * the file while it has a (shared) futex waiting on it. This mapping will have
+ * a file reference which pins the mount and inode.
+ *
+ * If for some reason an inode gets evicted and read back in again, it will get
+ * a new sequence number and will _NOT_ match, even though it is the exact same
+ * file.
+ *
+ * It is important that match_futex() will never have a false-positive, esp.
+ * for PI futexes that can mess up the state. The above argues that false-negatives
+ * are only possible for malformed programs.
+ */
+static u64 get_inode_sequence_number(struct inode *inode)
+{
+	static atomic64_t i_seq;
+	u64 old;
+
+	/* Does the inode already have a sequence number? */
+	old = atomic64_read(&inode->i_sequence);
+	if (likely(old))
+		return old;
+
+	for (;;) {
+		u64 new = atomic64_add_return(1, &i_seq);
+		if (WARN_ON_ONCE(!new))
+			continue;
+
+		old = atomic64_cmpxchg(&inode->i_sequence, 0, new);
+		if (old)
+			return old;
+		return new;
+	}
+}
+
 /**
  * get_futex_key() - Get parameters which are the keys for a futex
  * @uaddr:	virtual address of the futex
@@ -382,9 +421,15 @@ static void drop_futex_key_refs(union futex_key *key)
  *
  * The key words are stored in *key on success.
  *
- * For shared mappings, it's (page->index, file_inode(vma->vm_file),
- * offset_within_page).  For private mappings, it's (uaddr, current->mm).
- * We can usually work out the index without swapping in the page.
+ * For shared mappings (when @fshared), the key is:
+ *   ( inode->i_sequence, page->index, offset_within_page )
+ * [ also see get_inode_sequence_number() ]
+ *
+ * For private mappings (or when !@fshared), the key is:
+ *   ( current->mm, address, 0 )
+ *
+ * This allows (cross process, where applicable) identification of the futex
+ * without keeping the page pinned for the duration of the FUTEX_WAIT.
  *
  * lock_page() might sleep, the caller should not hold a spinlock.
  */
@@ -545,8 +590,6 @@ get_futex_key(u32 __user *uaddr, int fshared, union futex_key *key, int rw)
 		key->private.mm = mm;
 		key->private.address = address;
 
-		get_futex_key_refs(key); /* implies smp_mb(); (B) */
-
 	} else {
 		struct inode *inode;
 
@@ -578,40 +621,14 @@ get_futex_key(u32 __user *uaddr, int fshared, union futex_key *key, int rw)
 			goto again;
 		}
 
-		/*
-		 * Take a reference unless it is about to be freed. Previously
-		 * this reference was taken by ihold under the page lock
-		 * pinning the inode in place so i_lock was unnecessary. The
-		 * only way for this check to fail is if the inode was
-		 * truncated in parallel which is almost certainly an
-		 * application bug. In such a case, just retry.
-		 *
-		 * We are not calling into get_futex_key_refs() in file-backed
-		 * cases, therefore a successful atomic_inc return below will
-		 * guarantee that get_futex_key() will still imply smp_mb(); (B).
-		 */
-		if (!atomic_inc_not_zero(&inode->i_count)) {
-			rcu_read_unlock();
-			put_page(page_head);
-
-			goto again;
-		}
-
-		/* Should be impossible but lets be paranoid for now */
-		if (WARN_ON_ONCE(inode->i_mapping != mapping)) {
-			err = -EFAULT;
-			rcu_read_unlock();
-			iput(inode);
-
-			goto out;
-		}
-
 		key->both.offset |= FUT_OFF_INODE; /* inode-based key */
-		key->shared.inode = inode;
+		key->shared.i_seq = get_inode_sequence_number(inode);
 		key->shared.pgoff = basepage_index(page);
 		rcu_read_unlock();
 	}
 
+	get_futex_key_refs(key); /* implies smp_mb(); (B) */
+
 out:
 	put_page(page_head);
 	return err;
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 6f4e876162f5..c5da3c8a67e8 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -1652,6 +1652,24 @@ static struct ctl_table fs_table[] = {
 		.extra1		= &zero,
 		.extra2		= &one,
 	},
+	{
+		.procname	= "protected_fifos",
+		.data		= &sysctl_protected_fifos,
+		.maxlen		= sizeof(int),
+		.mode		= 0600,
+		.proc_handler	= proc_dointvec_minmax,
+		.extra1		= &zero,
+		.extra2		= &two,
+	},
+	{
+		.procname	= "protected_regular",
+		.data		= &sysctl_protected_regular,
+		.maxlen		= sizeof(int),
+		.mode		= 0600,
+		.proc_handler	= proc_dointvec_minmax,
+		.extra1		= &zero,
+		.extra2		= &two,
+	},
 	{
 		.procname	= "suid_dumpable",
 		.data		= &suid_dumpable,
diff --git a/kernel/taskstats.c b/kernel/taskstats.c
index 13d2f7cd65db..158c877e5327 100644
--- a/kernel/taskstats.c
+++ b/kernel/taskstats.c
@@ -591,25 +591,33 @@ static int taskstats_user_cmd(struct sk_buff *skb, struct genl_info *info)
 static struct taskstats *taskstats_tgid_alloc(struct task_struct *tsk)
 {
 	struct signal_struct *sig = tsk->signal;
-	struct taskstats *stats;
+	struct taskstats *stats_new, *stats;
 
-	if (sig->stats || thread_group_empty(tsk))
-		goto ret;
+	/* Pairs with smp_store_release() below. */
+	stats = smp_load_acquire(&sig->stats);
+	if (stats || thread_group_empty(tsk))
+		return stats;
 
 	/* No problem if kmem_cache_zalloc() fails */
-	stats = kmem_cache_zalloc(taskstats_cache, GFP_KERNEL);
+	stats_new = kmem_cache_zalloc(taskstats_cache, GFP_KERNEL);
 
 	spin_lock_irq(&tsk->sighand->siglock);
-	if (!sig->stats) {
-		sig->stats = stats;
-		stats = NULL;
+	stats = sig->stats;
+	if (!stats) {
+		/*
+		 * Pairs with smp_store_release() above and order the
+		 * kmem_cache_zalloc().
+		 */
+		smp_store_release(&sig->stats, stats_new);
+		stats = stats_new;
+		stats_new = NULL;
 	}
 	spin_unlock_irq(&tsk->sighand->siglock);
 
-	if (stats)
-		kmem_cache_free(taskstats_cache, stats);
-ret:
-	return sig->stats;
+	if (stats_new)
+		kmem_cache_free(taskstats_cache, stats_new);
+
+	return stats;
 }
 
 /* Send pid data out on exit */
diff --git a/kernel/time/posix-clock.c b/kernel/time/posix-clock.c
index 9cff0ab82b63..dfb386931512 100644
--- a/kernel/time/posix-clock.c
+++ b/kernel/time/posix-clock.c
@@ -25,8 +25,6 @@
 #include <linux/syscalls.h>
 #include <linux/uaccess.h>
 
-static void delete_clock(struct kref *kref);
-
 /*
  * Returns NULL if the posix_clock instance attached to 'fp' is old and stale.
  */
@@ -168,7 +166,7 @@ static int posix_clock_open(struct inode *inode, struct file *fp)
 		err = 0;
 
 	if (!err) {
-		kref_get(&clk->kref);
+		get_device(clk->dev);
 		fp->private_data = clk;
 	}
 out:
@@ -184,7 +182,7 @@ static int posix_clock_release(struct inode *inode, struct file *fp)
 	if (clk->ops.release)
 		err = clk->ops.release(clk);
 
-	kref_put(&clk->kref, delete_clock);
+	put_device(clk->dev);
 
 	fp->private_data = NULL;
 
@@ -206,38 +204,35 @@ static const struct file_operations posix_clock_file_operations = {
 #endif
 };
 
-int posix_clock_register(struct posix_clock *clk, dev_t devid)
+int posix_clock_register(struct posix_clock *clk, struct device *dev)
 {
 	int err;
 
-	kref_init(&clk->kref);
 	init_rwsem(&clk->rwsem);
 
 	cdev_init(&clk->cdev, &posix_clock_file_operations);
+	err = cdev_device_add(&clk->cdev, dev);
+	if (err) {
+		pr_err("%s unable to add device %d:%d\n",
+			dev_name(dev), MAJOR(dev->devt), MINOR(dev->devt));
+		return err;
+	}
 	clk->cdev.owner = clk->ops.owner;
-	err = cdev_add(&clk->cdev, devid, 1);
+	clk->dev = dev;
 
-	return err;
+	return 0;
 }
 EXPORT_SYMBOL_GPL(posix_clock_register);
 
-static void delete_clock(struct kref *kref)
-{
-	struct posix_clock *clk = container_of(kref, struct posix_clock, kref);
-
-	if (clk->release)
-		clk->release(clk);
-}
-
 void posix_clock_unregister(struct posix_clock *clk)
 {
-	cdev_del(&clk->cdev);
+	cdev_device_del(&clk->cdev, clk->dev);
 
 	down_write(&clk->rwsem);
 	clk->zombie = true;
 	up_write(&clk->rwsem);
 
-	kref_put(&clk->kref, delete_clock);
+	put_device(clk->dev);
 }
 EXPORT_SYMBOL_GPL(posix_clock_unregister);
 
diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c
index 9a9d0288576b..db28c5fabfac 100644
--- a/kernel/trace/blktrace.c
+++ b/kernel/trace/blktrace.c
@@ -302,6 +302,7 @@ static void blk_trace_free(struct blk_trace *bt)
 
 static void blk_trace_cleanup(struct blk_trace *bt)
 {
+	synchronize_rcu();
 	blk_trace_free(bt);
 	if (atomic_dec_and_test(&blk_probes_ref))
 		blk_unregister_tracepoints();
@@ -448,7 +449,7 @@ int do_blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
 		       struct block_device *bdev,
 		       struct blk_user_trace_setup *buts)
 {
-	struct blk_trace *old_bt, *bt = NULL;
+	struct blk_trace *bt = NULL;
 	struct dentry *dir = NULL;
 	int ret, i;
 
@@ -532,11 +533,8 @@ int do_blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
 	bt->trace_state = Blktrace_setup;
 
 	ret = -EBUSY;
-	old_bt = xchg(&q->blk_trace, bt);
-	if (old_bt) {
-		(void) xchg(&q->blk_trace, old_bt);
+	if (cmpxchg(&q->blk_trace, NULL, bt))
 		goto err;
-	}
 
 	if (atomic_inc_return(&blk_probes_ref) == 1)
 		blk_register_tracepoints();
@@ -619,8 +617,10 @@ static int compat_blk_trace_setup(struct request_queue *q, char *name,
 static int __blk_trace_startstop(struct request_queue *q, int start)
 {
 	int ret;
-	struct blk_trace *bt = q->blk_trace;
+	struct blk_trace *bt;
 
+	bt = rcu_dereference_protected(q->blk_trace,
+				       lockdep_is_held(&q->blk_trace_mutex));
 	if (bt == NULL)
 		return -EINVAL;
 
@@ -729,8 +729,8 @@ int blk_trace_ioctl(struct block_device *bdev, unsigned cmd, char __user *arg)
 void blk_trace_shutdown(struct request_queue *q)
 {
 	mutex_lock(&q->blk_trace_mutex);
-
-	if (q->blk_trace) {
+	if (rcu_dereference_protected(q->blk_trace,
+				      lockdep_is_held(&q->blk_trace_mutex))) {
 		__blk_trace_startstop(q, 0);
 		__blk_trace_remove(q);
 	}
@@ -756,10 +756,14 @@ void blk_trace_shutdown(struct request_queue *q)
 static void blk_add_trace_rq(struct request_queue *q, struct request *rq,
 			     unsigned int nr_bytes, u32 what)
 {
-	struct blk_trace *bt = q->blk_trace;
+	struct blk_trace *bt;
 
-	if (likely(!bt))
+	rcu_read_lock();
+	bt = rcu_dereference(q->blk_trace);
+	if (likely(!bt)) {
+		rcu_read_unlock();
 		return;
+	}
 
 	if (rq->cmd_type == REQ_TYPE_BLOCK_PC) {
 		what |= BLK_TC_ACT(BLK_TC_PC);
@@ -770,6 +774,7 @@ static void blk_add_trace_rq(struct request_queue *q, struct request *rq,
 		__blk_add_trace(bt, blk_rq_pos(rq), nr_bytes,
 				rq->cmd_flags, what, rq->errors, 0, NULL);
 	}
+	rcu_read_unlock();
 }
 
 static void blk_add_trace_rq_abort(void *ignore,
@@ -819,16 +824,21 @@ static void blk_add_trace_rq_complete(void *ignore,
 static void blk_add_trace_bio(struct request_queue *q, struct bio *bio,
 			      u32 what, int error)
 {
-	struct blk_trace *bt = q->blk_trace;
+	struct blk_trace *bt;
 
-	if (likely(!bt))
+	rcu_read_lock();
+	bt = rcu_dereference(q->blk_trace);
+	if (likely(!bt)) {
+		rcu_read_unlock();
 		return;
+	}
 
 	if (!error && !bio_flagged(bio, BIO_UPTODATE))
 		error = EIO;
 
 	__blk_add_trace(bt, bio->bi_iter.bi_sector, bio->bi_iter.bi_size,
 			bio->bi_rw, what, error, 0, NULL);
+	rcu_read_unlock();
 }
 
 static void blk_add_trace_bio_bounce(void *ignore,
@@ -873,10 +883,13 @@ static void blk_add_trace_getrq(void *ignore,
 	if (bio)
 		blk_add_trace_bio(q, bio, BLK_TA_GETRQ, 0);
 	else {
-		struct blk_trace *bt = q->blk_trace;
+		struct blk_trace *bt;
 
+		rcu_read_lock();
+		bt = rcu_dereference(q->blk_trace);
 		if (bt)
 			__blk_add_trace(bt, 0, 0, rw, BLK_TA_GETRQ, 0, 0, NULL);
+		rcu_read_unlock();
 	}
 }
 
@@ -888,27 +901,35 @@ static void blk_add_trace_sleeprq(void *ignore,
 	if (bio)
 		blk_add_trace_bio(q, bio, BLK_TA_SLEEPRQ, 0);
 	else {
-		struct blk_trace *bt = q->blk_trace;
+		struct blk_trace *bt;
 
+		rcu_read_lock();
+		bt = rcu_dereference(q->blk_trace);
 		if (bt)
 			__blk_add_trace(bt, 0, 0, rw, BLK_TA_SLEEPRQ,
 					0, 0, NULL);
+		rcu_read_unlock();
 	}
 }
 
 static void blk_add_trace_plug(void *ignore, struct request_queue *q)
 {
-	struct blk_trace *bt = q->blk_trace;
+	struct blk_trace *bt;
 
+	rcu_read_lock();
+	bt = rcu_dereference(q->blk_trace);
 	if (bt)
 		__blk_add_trace(bt, 0, 0, 0, BLK_TA_PLUG, 0, 0, NULL);
+	rcu_read_unlock();
 }
 
 static void blk_add_trace_unplug(void *ignore, struct request_queue *q,
 				    unsigned int depth, bool explicit)
 {
-	struct blk_trace *bt = q->blk_trace;
+	struct blk_trace *bt;
 
+	rcu_read_lock();
+	bt = rcu_dereference(q->blk_trace);
 	if (bt) {
 		__be64 rpdu = cpu_to_be64(depth);
 		u32 what;
@@ -920,14 +941,17 @@ static void blk_add_trace_unplug(void *ignore, struct request_queue *q,
 
 		__blk_add_trace(bt, 0, 0, 0, what, 0, sizeof(rpdu), &rpdu);
 	}
+	rcu_read_unlock();
 }
 
 static void blk_add_trace_split(void *ignore,
 				struct request_queue *q, struct bio *bio,
 				unsigned int pdu)
 {
-	struct blk_trace *bt = q->blk_trace;
+	struct blk_trace *bt;
 
+	rcu_read_lock();
+	bt = rcu_dereference(q->blk_trace);
 	if (bt) {
 		__be64 rpdu = cpu_to_be64(pdu);
 
@@ -936,6 +960,7 @@ static void blk_add_trace_split(void *ignore,
 				!bio_flagged(bio, BIO_UPTODATE),
 				sizeof(rpdu), &rpdu);
 	}
+	rcu_read_unlock();
 }
 
 /**
@@ -955,11 +980,15 @@ static void blk_add_trace_bio_remap(void *ignore,
 				    struct request_queue *q, struct bio *bio,
 				    dev_t dev, sector_t from)
 {
-	struct blk_trace *bt = q->blk_trace;
+	struct blk_trace *bt;
 	struct blk_io_trace_remap r;
 
-	if (likely(!bt))
+	rcu_read_lock();
+	bt = rcu_dereference(q->blk_trace);
+	if (likely(!bt)) {
+		rcu_read_unlock();
 		return;
+	}
 
 	r.device_from = cpu_to_be32(dev);
 	r.device_to   = cpu_to_be32(bio->bi_bdev->bd_dev);
@@ -968,6 +997,7 @@ static void blk_add_trace_bio_remap(void *ignore,
 	__blk_add_trace(bt, bio->bi_iter.bi_sector, bio->bi_iter.bi_size,
 			bio->bi_rw, BLK_TA_REMAP,
 			!bio_flagged(bio, BIO_UPTODATE), sizeof(r), &r);
+	rcu_read_unlock();
 }
 
 /**
@@ -988,11 +1018,15 @@ static void blk_add_trace_rq_remap(void *ignore,
 				   struct request *rq, dev_t dev,
 				   sector_t from)
 {
-	struct blk_trace *bt = q->blk_trace;
+	struct blk_trace *bt;
 	struct blk_io_trace_remap r;
 
-	if (likely(!bt))
+	rcu_read_lock();
+	bt = rcu_dereference(q->blk_trace);
+	if (likely(!bt)) {
+		rcu_read_unlock();
 		return;
+	}
 
 	r.device_from = cpu_to_be32(dev);
 	r.device_to   = cpu_to_be32(disk_devt(rq->rq_disk));
@@ -1001,6 +1035,7 @@ static void blk_add_trace_rq_remap(void *ignore,
 	__blk_add_trace(bt, blk_rq_pos(rq), blk_rq_bytes(rq),
 			rq_data_dir(rq), BLK_TA_REMAP, !!rq->errors,
 			sizeof(r), &r);
+	rcu_read_unlock();
 }
 
 /**
@@ -1018,10 +1053,14 @@ void blk_add_driver_data(struct request_queue *q,
 			 struct request *rq,
 			 void *data, size_t len)
 {
-	struct blk_trace *bt = q->blk_trace;
+	struct blk_trace *bt;
 
-	if (likely(!bt))
+	rcu_read_lock();
+	bt = rcu_dereference(q->blk_trace);
+	if (likely(!bt)) {
+		rcu_read_unlock();
 		return;
+	}
 
 	if (rq->cmd_type == REQ_TYPE_BLOCK_PC)
 		__blk_add_trace(bt, 0, blk_rq_bytes(rq), 0,
@@ -1029,6 +1068,7 @@ void blk_add_driver_data(struct request_queue *q,
 	else
 		__blk_add_trace(bt, blk_rq_pos(rq), blk_rq_bytes(rq), 0,
 				BLK_TA_DRV_DATA, rq->errors, len, data);
+	rcu_read_unlock();
 }
 EXPORT_SYMBOL_GPL(blk_add_driver_data);
 
@@ -1540,6 +1580,7 @@ static int blk_trace_remove_queue(struct request_queue *q)
 	spin_lock_irq(&running_trace_lock);
 	list_del(&bt->running_list);
 	spin_unlock_irq(&running_trace_lock);
+	synchronize_rcu();
 	blk_trace_free(bt);
 	return 0;
 }
@@ -1550,7 +1591,7 @@ static int blk_trace_remove_queue(struct request_queue *q)
 static int blk_trace_setup_queue(struct request_queue *q,
 				 struct block_device *bdev)
 {
-	struct blk_trace *old_bt, *bt = NULL;
+	struct blk_trace *bt = NULL;
 	int ret = -ENOMEM;
 
 	bt = kzalloc(sizeof(*bt), GFP_KERNEL);
@@ -1566,12 +1607,9 @@ static int blk_trace_setup_queue(struct request_queue *q,
 
 	blk_trace_setup_lba(bt, bdev);
 
-	old_bt = xchg(&q->blk_trace, bt);
-	if (old_bt != NULL) {
-		(void)xchg(&q->blk_trace, old_bt);
-		ret = -EBUSY;
+	ret = -EBUSY;
+	if (cmpxchg(&q->blk_trace, NULL, bt))
 		goto free_bt;
-	}
 
 	if (atomic_inc_return(&blk_probes_ref) == 1)
 		blk_register_tracepoints();
@@ -1704,6 +1742,7 @@ static ssize_t sysfs_blk_trace_attr_show(struct device *dev,
 	struct hd_struct *p = dev_to_part(dev);
 	struct request_queue *q;
 	struct block_device *bdev;
+	struct blk_trace *bt;
 	ssize_t ret = -ENXIO;
 
 	bdev = bdget(part_devt(p));
@@ -1716,21 +1755,23 @@ static ssize_t sysfs_blk_trace_attr_show(struct device *dev,
 
 	mutex_lock(&q->blk_trace_mutex);
 
+	bt = rcu_dereference_protected(q->blk_trace,
+				       lockdep_is_held(&q->blk_trace_mutex));
 	if (attr == &dev_attr_enable) {
-		ret = sprintf(buf, "%u\n", !!q->blk_trace);
+		ret = sprintf(buf, "%u\n", !!bt);
 		goto out_unlock_bdev;
 	}
 
-	if (q->blk_trace == NULL)
+	if (bt == NULL)
 		ret = sprintf(buf, "disabled\n");
 	else if (attr == &dev_attr_act_mask)
-		ret = blk_trace_mask2str(buf, q->blk_trace->act_mask);
+		ret = blk_trace_mask2str(buf, bt->act_mask);
 	else if (attr == &dev_attr_pid)
-		ret = sprintf(buf, "%u\n", q->blk_trace->pid);
+		ret = sprintf(buf, "%u\n", bt->pid);
 	else if (attr == &dev_attr_start_lba)
-		ret = sprintf(buf, "%llu\n", q->blk_trace->start_lba);
+		ret = sprintf(buf, "%llu\n", bt->start_lba);
 	else if (attr == &dev_attr_end_lba)
-		ret = sprintf(buf, "%llu\n", q->blk_trace->end_lba);
+		ret = sprintf(buf, "%llu\n", bt->end_lba);
 
 out_unlock_bdev:
 	mutex_unlock(&q->blk_trace_mutex);
@@ -1747,6 +1788,7 @@ static ssize_t sysfs_blk_trace_attr_store(struct device *dev,
 	struct block_device *bdev;
 	struct request_queue *q;
 	struct hd_struct *p;
+	struct blk_trace *bt;
 	u64 value;
 	ssize_t ret = -EINVAL;
 
@@ -1777,8 +1819,10 @@ static ssize_t sysfs_blk_trace_attr_store(struct device *dev,
 
 	mutex_lock(&q->blk_trace_mutex);
 
+	bt = rcu_dereference_protected(q->blk_trace,
+				       lockdep_is_held(&q->blk_trace_mutex));
 	if (attr == &dev_attr_enable) {
-		if (!!value == !!q->blk_trace) {
+		if (!!value == !!bt) {
 			ret = 0;
 			goto out_unlock_bdev;
 		}
@@ -1790,18 +1834,21 @@ static ssize_t sysfs_blk_trace_attr_store(struct device *dev,
 	}
 
 	ret = 0;
-	if (q->blk_trace == NULL)
+	if (bt == NULL) {
 		ret = blk_trace_setup_queue(q, bdev);
+		bt = rcu_dereference_protected(q->blk_trace,
+				lockdep_is_held(&q->blk_trace_mutex));
+	}
 
 	if (ret == 0) {
 		if (attr == &dev_attr_act_mask)
-			q->blk_trace->act_mask = value;
+			bt->act_mask = value;
 		else if (attr == &dev_attr_pid)
-			q->blk_trace->pid = value;
+			bt->pid = value;
 		else if (attr == &dev_attr_start_lba)
-			q->blk_trace->start_lba = value;
+			bt->start_lba = value;
 		else if (attr == &dev_attr_end_lba)
-			q->blk_trace->end_lba = value;
+			bt->end_lba = value;
 	}
 
 out_unlock_bdev:
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index c59d43d54d32..ff5281a9c5d7 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -595,8 +595,7 @@ static int function_stat_show(struct seq_file *m, void *v)
 
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 	seq_printf(m, "    ");
-	avg = rec->time;
-	do_div(avg, rec->counter);
+	avg = div64_ul(rec->time, rec->counter);
 
 	/* Sample standard deviation (s^2) */
 	if (rec->counter <= 1)
@@ -613,7 +612,8 @@ static int function_stat_show(struct seq_file *m, void *v)
 		 * Divide only 1000 for ns^2 -> us^2 conversion.
 		 * trace_print_graph_duration will divide 1000 again.
 		 */
-		do_div(stddev, rec->counter * (rec->counter - 1) * 1000);
+		stddev = div64_ul(stddev,
+				  rec->counter * (rec->counter - 1) * 1000);
 	}
 
 	trace_seq_init(&s);
diff --git a/kernel/trace/trace_sched_wakeup.c b/kernel/trace/trace_sched_wakeup.c
index 19bd8928ce94..0928ea8c5567 100644
--- a/kernel/trace/trace_sched_wakeup.c
+++ b/kernel/trace/trace_sched_wakeup.c
@@ -567,7 +567,7 @@ static void start_wakeup_tracer(struct trace_array *tr)
 	if (ret) {
 		pr_info("wakeup trace: Couldn't activate tracepoint"
 			" probe to kernel_sched_migrate_task\n");
-		return;
+		goto fail_deprobe_sched_switch;
 	}
 
 	wakeup_reset(tr);
@@ -585,6 +585,8 @@ static void start_wakeup_tracer(struct trace_array *tr)
 		printk(KERN_ERR "failed to start wakeup tracer\n");
 
 	return;
+fail_deprobe_sched_switch:
+	unregister_trace_sched_switch(probe_wakeup_sched_switch, NULL);
 fail_deprobe_wake_new:
 	unregister_trace_sched_wakeup_new(probe_wakeup, NULL);
 fail_deprobe:
diff --git a/kernel/trace/trace_stack.c b/kernel/trace/trace_stack.c
index 8a4e5cb66a4c..27eb7e96dabe 100644
--- a/kernel/trace/trace_stack.c
+++ b/kernel/trace/trace_stack.c
@@ -182,6 +182,11 @@ check_stack(unsigned long ip, unsigned long *stack)
 	local_irq_restore(flags);
 }
 
+/* Some archs may not define MCOUNT_INSN_SIZE */
+#ifndef MCOUNT_INSN_SIZE
+# define MCOUNT_INSN_SIZE 0
+#endif
+
 static void
 stack_trace_call(unsigned long ip, unsigned long parent_ip,
 		 struct ftrace_ops *op, struct pt_regs *pt_regs)
diff --git a/lib/kobject.c b/lib/kobject.c
index 58751bb80a7c..370f169ab88f 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -581,12 +581,15 @@ struct kobject *kobject_get(struct kobject *kobj)
 	return kobj;
 }
 
-static struct kobject * __must_check kobject_get_unless_zero(struct kobject *kobj)
+struct kobject * __must_check kobject_get_unless_zero(struct kobject *kobj)
 {
+	if (!kobj)
+		return NULL;
 	if (!kref_get_unless_zero(&kobj->kref))
 		kobj = NULL;
 	return kobj;
 }
+EXPORT_SYMBOL(kobject_get_unless_zero);
 
 /*
  * kobject_cleanup - free kobject resources.
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index aaf4c2e002e2..ad5f8f16270c 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -2711,7 +2711,9 @@ int mpol_parse_str(char *str, struct mempolicy **mpol)
 	switch (mode) {
 	case MPOL_PREFERRED:
 		/*
-		 * Insist on a nodelist of one node only
+		 * Insist on a nodelist of one node only, although later
+		 * we use first_node(nodes) to grab a single node, so here
+		 * nodelist (or nodes) cannot be empty.
 		 */
 		if (nodelist) {
 			char *rest = nodelist;
@@ -2719,6 +2721,8 @@ int mpol_parse_str(char *str, struct mempolicy **mpol)
 				rest++;
 			if (*rest)
 				goto out;
+			if (nodes_empty(nodes))
+				goto out;
 		}
 		break;
 	case MPOL_INTERLEAVE:
diff --git a/net/8021q/vlan_netlink.c b/net/8021q/vlan_netlink.c
index 8ac8a5cc2143..cfcc4cd12944 100644
--- a/net/8021q/vlan_netlink.c
+++ b/net/8021q/vlan_netlink.c
@@ -92,11 +92,13 @@ static int vlan_changelink(struct net_device *dev,
 	struct ifla_vlan_flags *flags;
 	struct ifla_vlan_qos_mapping *m;
 	struct nlattr *attr;
-	int rem;
+	int rem, err;
 
 	if (data[IFLA_VLAN_FLAGS]) {
 		flags = nla_data(data[IFLA_VLAN_FLAGS]);
-		vlan_dev_change_flags(dev, flags->flags, flags->mask);
+		err = vlan_dev_change_flags(dev, flags->flags, flags->mask);
+		if (err)
+			return err;
 	}
 	if (data[IFLA_VLAN_INGRESS_QOS]) {
 		nla_for_each_nested(attr, data[IFLA_VLAN_INGRESS_QOS], rem) {
@@ -107,7 +109,9 @@ static int vlan_changelink(struct net_device *dev,
 	if (data[IFLA_VLAN_EGRESS_QOS]) {
 		nla_for_each_nested(attr, data[IFLA_VLAN_EGRESS_QOS], rem) {
 			m = nla_data(attr);
-			vlan_dev_set_egress_priority(dev, m->from, m->to);
+			err = vlan_dev_set_egress_priority(dev, m->from, m->to);
+			if (err)
+				return err;
 		}
 	}
 	return 0;
diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c
index ab83d8b16c45..a326c4fe1087 100644
--- a/net/batman-adv/distributed-arp-table.c
+++ b/net/batman-adv/distributed-arp-table.c
@@ -207,9 +207,11 @@ static uint32_t batadv_hash_dat(const void *data, uint32_t size)
 {
 	uint32_t hash = 0;
 	const struct batadv_dat_entry *dat = data;
+	__be16 vid;
 
 	hash = batadv_hash_bytes(hash, &dat->ip, sizeof(dat->ip));
-	hash = batadv_hash_bytes(hash, &dat->vid, sizeof(dat->vid));
+	vid = htons(dat->vid);
+	hash = batadv_hash_bytes(hash, &vid, sizeof(vid));
 
 	hash += (hash << 3);
 	hash ^= (hash >> 11);
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index 7ddb8b322556..3829136c245a 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -850,6 +850,9 @@ static unsigned int br_nf_forward_arp(const struct nf_hook_ops *ops,
 		nf_bridge_pull_encap_header(skb);
 	}
 
+	if (unlikely(!pskb_may_pull(skb, sizeof(struct arphdr))))
+		return NF_DROP;
+
 	if (arp_hdr(skb)->ar_pln != 4) {
 		if (IS_VLAN_ARP(skb))
 			nf_bridge_push_encap_header(skb);
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 1596736ff268..df1b8c147062 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -1603,7 +1603,8 @@ static int compat_match_to_user(struct ebt_entry_match *m, void __user **dstptr,
 	int off = ebt_compat_match_offset(match, m->match_size);
 	compat_uint_t msize = m->match_size - off;
 
-	BUG_ON(off >= m->match_size);
+	if (WARN_ON(off >= m->match_size))
+		return -EINVAL;
 
 	if (copy_to_user(cm->u.name, match->name,
 	    strlen(match->name) + 1) || put_user(msize, &cm->match_size))
@@ -1630,7 +1631,8 @@ static int compat_target_to_user(struct ebt_entry_target *t,
 	int off = xt_compat_target_offset(target);
 	compat_uint_t tsize = t->target_size - off;
 
-	BUG_ON(off >= t->target_size);
+	if (WARN_ON(off >= t->target_size))
+		return -EINVAL;
 
 	if (copy_to_user(cm->u.name, target->name,
 	    strlen(target->name) + 1) || put_user(tsize, &cm->match_size))
@@ -1853,12 +1855,13 @@ static int ebt_buf_count(struct ebt_entries_buf_state *state, unsigned int sz)
 }
 
 static int ebt_buf_add(struct ebt_entries_buf_state *state,
-		       void *data, unsigned int sz)
+		       const void *data, unsigned int sz)
 {
 	if (state->buf_kern_start == NULL)
 		goto count_only;
 
-	BUG_ON(state->buf_kern_offset + sz > state->buf_kern_len);
+	if (WARN_ON(state->buf_kern_offset + sz > state->buf_kern_len))
+		return -EINVAL;
 
 	memcpy(state->buf_kern_start + state->buf_kern_offset, data, sz);
 
@@ -1871,7 +1874,8 @@ static int ebt_buf_add_pad(struct ebt_entries_buf_state *state, unsigned int sz)
 {
 	char *b = state->buf_kern_start;
 
-	BUG_ON(b && state->buf_kern_offset > state->buf_kern_len);
+	if (WARN_ON(b && state->buf_kern_offset > state->buf_kern_len))
+		return -EINVAL;
 
 	if (b != NULL && sz > 0)
 		memset(b + state->buf_kern_offset, 0, sz);
@@ -1885,7 +1889,7 @@ enum compat_mwt {
 	EBT_COMPAT_TARGET,
 };
 
-static int compat_mtw_from_user(struct compat_ebt_entry_mwt *mwt,
+static int compat_mtw_from_user(const struct compat_ebt_entry_mwt *mwt,
 				enum compat_mwt compat_mwt,
 				struct ebt_entries_buf_state *state,
 				const unsigned char *base)
@@ -1949,8 +1953,10 @@ static int compat_mtw_from_user(struct compat_ebt_entry_mwt *mwt,
 	pad = XT_ALIGN(size_kern) - size_kern;
 
 	if (pad > 0 && dst) {
-		BUG_ON(state->buf_kern_len <= pad);
-		BUG_ON(state->buf_kern_offset - (match_size + off) + size_kern > state->buf_kern_len - pad);
+		if (WARN_ON(state->buf_kern_len <= pad))
+			return -EINVAL;
+		if (WARN_ON(state->buf_kern_offset - (match_size + off) + size_kern > state->buf_kern_len - pad))
+			return -EINVAL;
 		memset(dst + size_kern, 0, pad);
 	}
 	return off + match_size;
@@ -1960,22 +1966,23 @@ static int compat_mtw_from_user(struct compat_ebt_entry_mwt *mwt,
  * return size of all matches, watchers or target, including necessary
  * alignment and padding.
  */
-static int ebt_size_mwt(struct compat_ebt_entry_mwt *match32,
+static int ebt_size_mwt(const struct compat_ebt_entry_mwt *match32,
 			unsigned int size_left, enum compat_mwt type,
 			struct ebt_entries_buf_state *state, const void *base)
 {
+	const char *buf = (const char *)match32;
 	int growth = 0;
-	char *buf;
 
 	if (size_left == 0)
 		return 0;
 
-	buf = (char *) match32;
-
-	while (size_left >= sizeof(*match32)) {
+	do {
 		struct ebt_entry_match *match_kern;
 		int ret;
 
+		if (size_left < sizeof(*match32))
+			return -EINVAL;
+
 		match_kern = (struct ebt_entry_match *) state->buf_kern_start;
 		if (match_kern) {
 			char *tmp;
@@ -2001,7 +2008,8 @@ static int ebt_size_mwt(struct compat_ebt_entry_mwt *match32,
 		if (ret < 0)
 			return ret;
 
-		BUG_ON(ret < match32->match_size);
+		if (WARN_ON(ret < match32->match_size))
+			return -EINVAL;
 		growth += ret - match32->match_size;
 		growth += ebt_compat_entry_padsize();
 
@@ -2011,22 +2019,18 @@ static int ebt_size_mwt(struct compat_ebt_entry_mwt *match32,
 		if (match_kern)
 			match_kern->match_size = ret;
 
-		/* rule should have no remaining data after target */
-		if (type == EBT_COMPAT_TARGET && size_left)
-			return -EINVAL;
-
 		match32 = (struct compat_ebt_entry_mwt *) buf;
-	}
+	} while (size_left);
 
 	return growth;
 }
 
 /* called for all ebt_entry structures. */
-static int size_entry_mwt(struct ebt_entry *entry, const unsigned char *base,
+static int size_entry_mwt(const struct ebt_entry *entry, const unsigned char *base,
 			  unsigned int *total,
 			  struct ebt_entries_buf_state *state)
 {
-	unsigned int i, j, startoff, new_offset = 0;
+	unsigned int i, j, startoff, next_expected_off, new_offset = 0;
 	/* stores match/watchers/targets & offset of next struct ebt_entry: */
 	unsigned int offsets[4];
 	unsigned int *offsets_update = NULL;
@@ -2114,10 +2118,13 @@ static int size_entry_mwt(struct ebt_entry *entry, const unsigned char *base,
 			return ret;
 	}
 
-	startoff = state->buf_user_offset - startoff;
+	next_expected_off = state->buf_user_offset - startoff;
+	if (next_expected_off != entry->next_offset)
+		return -EINVAL;
 
-	BUG_ON(*total < startoff);
-	*total -= startoff;
+	if (*total < entry->next_offset)
+		return -EINVAL;
+	*total -= entry->next_offset;
 	return 0;
 }
 
@@ -2246,7 +2253,8 @@ static int compat_do_replace(struct net *net, void __user *user,
 	state.buf_kern_len = size64;
 
 	ret = compat_copy_entries(entries_tmp, tmp.entries_size, &state);
-	BUG_ON(ret < 0);	/* parses same data again */
+	if (WARN_ON(ret < 0))
+		goto out_unlock;
 
 	vfree(entries_tmp);
 	tmp.entries_size = size64;
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 9137f30c78b8..e48e552be9fe 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -103,9 +103,6 @@ static int neigh_blackhole(struct neighbour *neigh, struct sk_buff *skb)
 
 static void neigh_cleanup_and_release(struct neighbour *neigh)
 {
-	if (neigh->parms->neigh_cleanup)
-		neigh->parms->neigh_cleanup(neigh);
-
 	__neigh_notify(neigh, RTM_DELNEIGH, 0);
 	neigh_release(neigh);
 }
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index 15019c2408c2..d491af8a11be 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -480,11 +480,12 @@ static int mark_source_chains(const struct xt_table_info *newinfo,
 	return 1;
 }
 
-static inline int check_target(struct arpt_entry *e, const char *name)
+static int check_target(struct arpt_entry *e, struct net *net, const char *name)
 {
 	struct xt_entry_target *t = arpt_get_target(e);
 	int ret;
 	struct xt_tgchk_param par = {
+		.net       = net,
 		.table     = name,
 		.entryinfo = e,
 		.target    = t->u.kernel.target,
@@ -502,8 +503,9 @@ static inline int check_target(struct arpt_entry *e, const char *name)
 	return 0;
 }
 
-static inline int
-find_check_entry(struct arpt_entry *e, const char *name, unsigned int size)
+static int
+find_check_entry(struct arpt_entry *e, struct net *net, const char *name,
+		 unsigned int size)
 {
 	struct xt_entry_target *t;
 	struct xt_target *target;
@@ -519,7 +521,7 @@ find_check_entry(struct arpt_entry *e, const char *name, unsigned int size)
 	}
 	t->u.kernel.target = target;
 
-	ret = check_target(e, name);
+	ret = check_target(e, net, name);
 	if (ret)
 		goto err;
 	return 0;
@@ -600,12 +602,13 @@ static inline int check_entry_size_and_hooks(struct arpt_entry *e,
 	return 0;
 }
 
-static inline void cleanup_entry(struct arpt_entry *e)
+static void cleanup_entry(struct arpt_entry *e, struct net *net)
 {
 	struct xt_tgdtor_param par;
 	struct xt_entry_target *t;
 
 	t = arpt_get_target(e);
+	par.net      = net;
 	par.target   = t->u.kernel.target;
 	par.targinfo = t->data;
 	par.family   = NFPROTO_ARP;
@@ -617,7 +620,9 @@ static inline void cleanup_entry(struct arpt_entry *e)
 /* Checks and translates the user-supplied table segment (held in
  * newinfo).
  */
-static int translate_table(struct xt_table_info *newinfo, void *entry0,
+static int translate_table(struct net *net,
+			   struct xt_table_info *newinfo,
+			   void *entry0,
                            const struct arpt_replace *repl)
 {
 	struct arpt_entry *iter;
@@ -692,7 +697,7 @@ static int translate_table(struct xt_table_info *newinfo, void *entry0,
 	/* Finally, each sanity check must pass */
 	i = 0;
 	xt_entry_foreach(iter, entry0, newinfo->size) {
-		ret = find_check_entry(iter, repl->name, repl->size);
+		ret = find_check_entry(iter, net, repl->name, repl->size);
 		if (ret != 0)
 			break;
 		++i;
@@ -702,7 +707,7 @@ static int translate_table(struct xt_table_info *newinfo, void *entry0,
 		xt_entry_foreach(iter, entry0, newinfo->size) {
 			if (i-- == 0)
 				break;
-			cleanup_entry(iter);
+			cleanup_entry(iter, net);
 		}
 		return ret;
 	}
@@ -1047,7 +1052,7 @@ static int __do_replace(struct net *net, const char *name,
 	/* Decrease module usage counts and free resource */
 	loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
 	xt_entry_foreach(iter, loc_cpu_old_entry, oldinfo->size)
-		cleanup_entry(iter);
+		cleanup_entry(iter, net);
 
 	xt_free_table_info(oldinfo);
 	if (copy_to_user(counters_ptr, counters,
@@ -1100,7 +1105,7 @@ static int do_replace(struct net *net, const void __user *user,
 		goto free_newinfo;
 	}
 
-	ret = translate_table(newinfo, loc_cpu_entry, &tmp);
+	ret = translate_table(net, newinfo, loc_cpu_entry, &tmp);
 	if (ret != 0)
 		goto free_newinfo;
 
@@ -1114,7 +1119,7 @@ static int do_replace(struct net *net, const void __user *user,
 
  free_newinfo_untrans:
 	xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)
-		cleanup_entry(iter);
+		cleanup_entry(iter, net);
  free_newinfo:
 	xt_free_table_info(newinfo);
 	return ret;
@@ -1287,7 +1292,8 @@ compat_copy_entry_from_user(struct compat_arpt_entry *e, void **dstptr,
 	}
 }
 
-static int translate_compat_table(struct xt_table_info **pinfo,
+static int translate_compat_table(struct net *net,
+				  struct xt_table_info **pinfo,
 				  void **pentry0,
 				  const struct compat_arpt_replace *compatr)
 {
@@ -1356,7 +1362,7 @@ static int translate_compat_table(struct xt_table_info **pinfo,
 	repl.num_counters = 0;
 	repl.counters = NULL;
 	repl.size = newinfo->size;
-	ret = translate_table(newinfo, entry1, &repl);
+	ret = translate_table(net, newinfo, entry1, &repl);
 	if (ret)
 		goto free_newinfo;
 
@@ -1412,7 +1418,7 @@ static int compat_do_replace(struct net *net, void __user *user,
 		goto free_newinfo;
 	}
 
-	ret = translate_compat_table(&newinfo, &loc_cpu_entry, &tmp);
+	ret = translate_compat_table(net, &newinfo, &loc_cpu_entry, &tmp);
 	if (ret != 0)
 		goto free_newinfo;
 
@@ -1426,7 +1432,7 @@ static int compat_do_replace(struct net *net, void __user *user,
 
  free_newinfo_untrans:
 	xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)
-		cleanup_entry(iter);
+		cleanup_entry(iter, net);
  free_newinfo:
 	xt_free_table_info(newinfo);
 	return ret;
@@ -1685,7 +1691,7 @@ struct xt_table *arpt_register_table(struct net *net,
 	loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
 	memcpy(loc_cpu_entry, repl->entries, repl->size);
 
-	ret = translate_table(newinfo, loc_cpu_entry, repl);
+	ret = translate_table(net, newinfo, loc_cpu_entry, repl);
 	duprintf("arpt_register_table: translate table gives %d\n", ret);
 	if (ret != 0)
 		goto out_free;
@@ -1703,7 +1709,7 @@ struct xt_table *arpt_register_table(struct net *net,
 	return ERR_PTR(ret);
 }
 
-void arpt_unregister_table(struct xt_table *table)
+void arpt_unregister_table(struct net *net, struct xt_table *table)
 {
 	struct xt_table_info *private;
 	void *loc_cpu_entry;
@@ -1715,7 +1721,7 @@ void arpt_unregister_table(struct xt_table *table)
 	/* Decrease module usage counts and free resources */
 	loc_cpu_entry = private->entries[raw_smp_processor_id()];
 	xt_entry_foreach(iter, loc_cpu_entry, private->size)
-		cleanup_entry(iter);
+		cleanup_entry(iter, net);
 	if (private->number > private->initial_entries)
 		module_put(table_owner);
 	xt_free_table_info(private);
diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c
index 802ddecb30b8..5375fb03d26b 100644
--- a/net/ipv4/netfilter/arptable_filter.c
+++ b/net/ipv4/netfilter/arptable_filter.c
@@ -54,7 +54,7 @@ static int __net_init arptable_filter_net_init(struct net *net)
 
 static void __net_exit arptable_filter_net_exit(struct net *net)
 {
-	arpt_unregister_table(net->ipv4.arptable_filter);
+	arpt_unregister_table(net, net->ipv4.arptable_filter);
 }
 
 static struct pernet_operations arptable_filter_net_ops = {
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index a42b6671d542..fc0425cff370 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -1713,8 +1713,11 @@ tcp_sacktag_write_queue(struct sock *sk, const struct sk_buff *ack_skb,
 		}
 
 		/* Ignore very old stuff early */
-		if (!after(sp[used_sacks].end_seq, prior_snd_una))
+		if (!after(sp[used_sacks].end_seq, prior_snd_una)) {
+			if (i == 0)
+				first_sack_index = -1;
 			continue;
+		}
 
 		used_sacks++;
 	}
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index e292792e9964..51f560d5bc03 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -1992,6 +1992,14 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle,
 		    unlikely(tso_fragment(sk, skb, limit, mss_now, gfp)))
 			break;
 
+		/* Argh, we hit an empty skb(), presumably a thread
+		 * is sleeping in sendmsg()/sk_stream_wait_memory().
+		 * We do not want to send a pure-ack packet and have
+		 * a strange looking rtx queue with empty packet(s).
+		 */
+		if (TCP_SKB_CB(skb)->end_seq == TCP_SKB_CB(skb)->seq)
+			break;
+
 		TCP_SKB_CB(skb)->when = tcp_time_stamp;
 
 		if (unlikely(tcp_transmit_skb(sk, skb, 1, gfp)))
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index d5db3ce7b463..afe276635163 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -820,7 +820,7 @@ static struct pernet_operations inet6_net_ops = {
 static const struct ipv6_stub ipv6_stub_impl = {
 	.ipv6_sock_mc_join = ipv6_sock_mc_join,
 	.ipv6_sock_mc_drop = ipv6_sock_mc_drop,
-	.ipv6_dst_lookup = ip6_dst_lookup,
+	.ipv6_dst_lookup_flow = ip6_dst_lookup_flow,
 	.udpv6_encap_enable = udpv6_encap_enable,
 	.ndisc_send_na = ndisc_send_na,
 	.nd_tbl	= &nd_tbl,
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 46d0ecf362bf..a377edbd90e5 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1196,50 +1196,6 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
 	return 0;
 }
 
-/* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */
-struct iapp_layer2_update {
-	u8 da[ETH_ALEN];	/* broadcast */
-	u8 sa[ETH_ALEN];	/* STA addr */
-	__be16 len;		/* 6 */
-	u8 dsap;		/* 0 */
-	u8 ssap;		/* 0 */
-	u8 control;
-	u8 xid_info[3];
-} __packed;
-
-static void ieee80211_send_layer2_update(struct sta_info *sta)
-{
-	struct iapp_layer2_update *msg;
-	struct sk_buff *skb;
-
-	/* Send Level 2 Update Frame to update forwarding tables in layer 2
-	 * bridge devices */
-
-	skb = dev_alloc_skb(sizeof(*msg));
-	if (!skb)
-		return;
-	msg = (struct iapp_layer2_update *)skb_put(skb, sizeof(*msg));
-
-	/* 802.2 Type 1 Logical Link Control (LLC) Exchange Identifier (XID)
-	 * Update response frame; IEEE Std 802.2-1998, 5.4.1.2.1 */
-
-	eth_broadcast_addr(msg->da);
-	memcpy(msg->sa, sta->sta.addr, ETH_ALEN);
-	msg->len = htons(6);
-	msg->dsap = 0;
-	msg->ssap = 0x01;	/* NULL LSAP, CR Bit: Response */
-	msg->control = 0xaf;	/* XID response lsb.1111F101.
-				 * F=0 (no poll command; unsolicited frame) */
-	msg->xid_info[0] = 0x81;	/* XID format identifier */
-	msg->xid_info[1] = 1;	/* LLC types/classes: Type 1 LLC */
-	msg->xid_info[2] = 0;	/* XID sender's receive window size (RW) */
-
-	skb->dev = sta->sdata->dev;
-	skb->protocol = eth_type_trans(skb, sta->sdata->dev);
-	memset(skb->cb, 0, sizeof(skb->cb));
-	netif_rx_ni(skb);
-}
-
 static int sta_apply_auth_flags(struct ieee80211_local *local,
 				struct sta_info *sta,
 				u32 mask, u32 set)
@@ -1480,7 +1436,6 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
 	struct sta_info *sta;
 	struct ieee80211_sub_if_data *sdata;
 	int err;
-	int layer2_update;
 
 	if (params->vlan) {
 		sdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
@@ -1525,18 +1480,12 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
 	if (!test_sta_flag(sta, WLAN_STA_TDLS_PEER))
 		rate_control_rate_init(sta);
 
-	layer2_update = sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
-		sdata->vif.type == NL80211_IFTYPE_AP;
-
 	err = sta_info_insert_rcu(sta);
 	if (err) {
 		rcu_read_unlock();
 		return err;
 	}
 
-	if (layer2_update)
-		ieee80211_send_layer2_update(sta);
-
 	rcu_read_unlock();
 
 	return 0;
@@ -1640,7 +1589,9 @@ static int ieee80211_change_station(struct wiphy *wiphy,
 				atomic_inc(&sta->sdata->bss->num_mcast_sta);
 		}
 
-		ieee80211_send_layer2_update(sta);
+		if (sta->sta_state == IEEE80211_STA_AUTHORIZED)
+			cfg80211_send_layer2_update(sta->sdata->dev,
+						    sta->sta.addr);
 	}
 
 	err = sta_apply_parameters(local, sta, params);
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index c006801f3d83..f89e76effb42 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -1666,6 +1666,10 @@ int sta_info_move_state(struct sta_info *sta,
 				atomic_inc(&sta->sdata->bss->num_mcast_sta);
 			set_bit(WLAN_STA_AUTHORIZED, &sta->_flags);
 		}
+		if (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
+		    sta->sdata->vif.type == NL80211_IFTYPE_AP)
+			cfg80211_send_layer2_update(sta->sdata->dev,
+						    sta->sta.addr);
 		break;
 	default:
 		break;
diff --git a/net/netfilter/ipset/ip_set_bitmap_gen.h b/net/netfilter/ipset/ip_set_bitmap_gen.h
index f2c7d83dc23f..6338b96d8f17 100644
--- a/net/netfilter/ipset/ip_set_bitmap_gen.h
+++ b/net/netfilter/ipset/ip_set_bitmap_gen.h
@@ -66,12 +66,12 @@ mtype_destroy(struct ip_set *set)
 	if (SET_WITH_TIMEOUT(set))
 		del_timer_sync(&map->gc);
 
-	ip_set_free(map->members);
 	if (set->dsize) {
 		if (set->extensions & IPSET_EXT_DESTROY)
 			mtype_ext_cleanup(set);
 		ip_set_free(map->extensions);
 	}
+	ip_set_free(map->members);
 	kfree(map);
 
 	set->data = NULL;
diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c
index efed6315c695..87c469098350 100644
--- a/net/netfilter/ipset/ip_set_core.c
+++ b/net/netfilter/ipset/ip_set_core.c
@@ -1549,6 +1549,7 @@ ip_set_utest(struct sock *ctnl, struct sk_buff *skb,
 	struct ip_set *set;
 	struct nlattr *tb[IPSET_ATTR_ADT_MAX+1] = {};
 	int ret = 0;
+	u32 lineno;
 
 	if (unlikely(protocol_failed(attr) ||
 		     attr[IPSET_ATTR_SETNAME] == NULL ||
@@ -1565,7 +1566,7 @@ ip_set_utest(struct sock *ctnl, struct sk_buff *skb,
 		return -IPSET_ERR_PROTOCOL;
 
 	read_lock_bh(&set->lock);
-	ret = set->variant->uadt(set, tb, IPSET_TEST, NULL, 0, 0);
+	ret = set->variant->uadt(set, tb, IPSET_TEST, &lineno, 0, 0);
 	read_unlock_bh(&set->lock);
 	/* Userspace can't trigger element to be re-added */
 	if (ret == -EAGAIN)
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index b9bf8b0f4ec1..63c984e01ff8 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -3225,6 +3225,9 @@ static void __net_exit ctnetlink_net_exit_batch(struct list_head *net_exit_list)
 
 	list_for_each_entry(net, net_exit_list, exit_list)
 		ctnetlink_net_exit(net);
+
+	/* wait for other cpus until they are done with ctnl_notifiers */
+	synchronize_rcu();
 }
 
 static struct pernet_operations ctnetlink_net_ops = {
diff --git a/net/netfilter/nft_bitwise.c b/net/netfilter/nft_bitwise.c
index c9e847ff6451..4ee55017cd58 100644
--- a/net/netfilter/nft_bitwise.c
+++ b/net/netfilter/nft_bitwise.c
@@ -86,16 +86,25 @@ static int nft_bitwise_init(const struct nft_ctx *ctx,
 	err = nft_data_init(NULL, &priv->mask, &d1, tb[NFTA_BITWISE_MASK]);
 	if (err < 0)
 		return err;
-	if (d1.len != priv->len)
-		return -EINVAL;
+	if (d1.type != NFT_DATA_VALUE || d1.len != priv->len) {
+		err = -EINVAL;
+		goto err1;
+	}
 
 	err = nft_data_init(NULL, &priv->xor, &d2, tb[NFTA_BITWISE_XOR]);
 	if (err < 0)
-		return err;
-	if (d2.len != priv->len)
-		return -EINVAL;
+		goto err1;
+	if (d2.type != NFT_DATA_VALUE || d2.len != priv->len) {
+		err = -EINVAL;
+		goto err2;
+	}
 
 	return 0;
+err2:
+	nft_data_uninit(&priv->xor, d2.type);
+err1:
+	nft_data_uninit(&priv->mask, d1.type);
+	return err;
 }
 
 static int nft_bitwise_dump(struct sk_buff *skb, const struct nft_expr *expr)
diff --git a/net/netfilter/nft_cmp.c b/net/netfilter/nft_cmp.c
index 109b91deb69a..109793a93ec9 100644
--- a/net/netfilter/nft_cmp.c
+++ b/net/netfilter/nft_cmp.c
@@ -84,6 +84,12 @@ static int nft_cmp_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
 	if (desc.len > U8_MAX)
 		return -ERANGE;
 
+	if (desc.type != NFT_DATA_VALUE) {
+		err = -EINVAL;
+		nft_data_uninit(&priv->data, desc.type);
+		return err;
+	}
+
 	priv->len = desc.len;
 	return 0;
 }
@@ -201,10 +207,18 @@ nft_cmp_select_ops(const struct nft_ctx *ctx, const struct nlattr * const tb[])
 	if (err < 0)
 		return ERR_PTR(err);
 
+	if (desc.type != NFT_DATA_VALUE) {
+		err = -EINVAL;
+		goto err1;
+	}
+
 	if (desc.len <= sizeof(u32) && op == NFT_CMP_EQ)
 		return &nft_cmp_fast_ops;
-	else
-		return &nft_cmp_ops;
+
+	return &nft_cmp_ops;
+err1:
+	nft_data_uninit(&data, desc.type);
+	return ERR_PTR(-EINVAL);
 }
 
 static struct nft_expr_type nft_cmp_type __read_mostly = {
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 2ba9b1a03229..fe436431bd2d 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -608,7 +608,8 @@ static int prb_calc_retire_blk_tmo(struct packet_sock *po,
 			msec = 1;
 			div = speed / 1000;
 		}
-	}
+	} else
+		return DEFAULT_PRB_RETIRE_TOV;
 
 	mbits = (blk_size_in_bytes * 8) / (1024 * 1024);
 
diff --git a/net/sched/ematch.c b/net/sched/ematch.c
index a2abc449ce8f..eaf8e3e727dc 100644
--- a/net/sched/ematch.c
+++ b/net/sched/ematch.c
@@ -266,12 +266,12 @@ static int tcf_em_validate(struct tcf_proto *tp,
 				}
 				em->data = (unsigned long) v;
 			}
+			em->datalen = data_len;
 		}
 	}
 
 	em->matchid = em_hdr->matchid;
 	em->flags = em_hdr->flags;
-	em->datalen = data_len;
 
 	err = 0;
 errout:
diff --git a/net/sched/sch_fq.c b/net/sched/sch_fq.c
index da3621feae74..1a0f943a3423 100644
--- a/net/sched/sch_fq.c
+++ b/net/sched/sch_fq.c
@@ -687,8 +687,14 @@ static int fq_change(struct Qdisc *sch, struct nlattr *opt)
 	if (tb[TCA_FQ_FLOW_PLIMIT])
 		q->flow_plimit = nla_get_u32(tb[TCA_FQ_FLOW_PLIMIT]);
 
-	if (tb[TCA_FQ_QUANTUM])
-		q->quantum = nla_get_u32(tb[TCA_FQ_QUANTUM]);
+	if (tb[TCA_FQ_QUANTUM]) {
+		u32 quantum = nla_get_u32(tb[TCA_FQ_QUANTUM]);
+
+		if (quantum > 0 && quantum <= (1 << 20))
+			q->quantum = quantum;
+		else
+			err = -EINVAL;
+	}
 
 	if (tb[TCA_FQ_INITIAL_QUANTUM])
 		q->initial_quantum = nla_get_u32(tb[TCA_FQ_INITIAL_QUANTUM]);
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index 5e30bdce1d21..ec0eeb35b334 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -1327,8 +1327,10 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
 			/* Generate an INIT ACK chunk.  */
 			new_obj = sctp_make_init_ack(asoc, chunk, GFP_ATOMIC,
 						     0);
-			if (!new_obj)
-				goto nomem;
+			if (!new_obj) {
+				error = -ENOMEM;
+				break;
+			}
 
 			sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
 					SCTP_CHUNK(new_obj));
@@ -1350,7 +1352,8 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
 			if (!new_obj) {
 				if (cmd->obj.chunk)
 					sctp_chunk_free(cmd->obj.chunk);
-				goto nomem;
+				error = -ENOMEM;
+				break;
 			}
 			sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
 					SCTP_CHUNK(new_obj));
@@ -1397,8 +1400,10 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
 
 			/* Generate a SHUTDOWN chunk.  */
 			new_obj = sctp_make_shutdown(asoc, chunk);
-			if (!new_obj)
-				goto nomem;
+			if (!new_obj) {
+				error = -ENOMEM;
+				break;
+			}
 			sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
 					SCTP_CHUNK(new_obj));
 			break;
@@ -1727,11 +1732,17 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
 			break;
 		}
 
-		if (error)
+		if (error) {
+			cmd = sctp_next_cmd(commands);
+			while (cmd) {
+				if (cmd->verb == SCTP_CMD_REPLY)
+					sctp_chunk_free(cmd->obj.chunk);
+				cmd = sctp_next_cmd(commands);
+			}
 			break;
+		}
 	}
 
-out:
 	/* If this is in response to a received chunk, wait until
 	 * we are done with the packet to open the queue so that we don't
 	 * send multiple packets in response to a single request.
@@ -1742,8 +1753,5 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
 	} else if (local_cork)
 		error = sctp_outq_uncork(&asoc->outqueue);
 	return error;
-nomem:
-	error = -ENOMEM;
-	goto out;
 }
 
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 2d8e3d82ad74..731da31aa246 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -1583,3 +1583,48 @@ EXPORT_SYMBOL(rfc1042_header);
 const unsigned char bridge_tunnel_header[] __aligned(2) =
 	{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
 EXPORT_SYMBOL(bridge_tunnel_header);
+
+/* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */
+struct iapp_layer2_update {
+	u8 da[ETH_ALEN];	/* broadcast */
+	u8 sa[ETH_ALEN];	/* STA addr */
+	__be16 len;		/* 6 */
+	u8 dsap;		/* 0 */
+	u8 ssap;		/* 0 */
+	u8 control;
+	u8 xid_info[3];
+} __packed;
+
+void cfg80211_send_layer2_update(struct net_device *dev, const u8 *addr)
+{
+	struct iapp_layer2_update *msg;
+	struct sk_buff *skb;
+
+	/* Send Level 2 Update Frame to update forwarding tables in layer 2
+	 * bridge devices */
+
+	skb = dev_alloc_skb(sizeof(*msg));
+	if (!skb)
+		return;
+	msg = (struct iapp_layer2_update *)skb_put(skb, sizeof(*msg));
+
+	/* 802.2 Type 1 Logical Link Control (LLC) Exchange Identifier (XID)
+	 * Update response frame; IEEE Std 802.2-1998, 5.4.1.2.1 */
+
+	eth_broadcast_addr(msg->da);
+	ether_addr_copy(msg->sa, addr);
+	msg->len = htons(6);
+	msg->dsap = 0;
+	msg->ssap = 0x01;	/* NULL LSAP, CR Bit: Response */
+	msg->control = 0xaf;	/* XID response lsb.1111F101.
+				 * F=0 (no poll command; unsolicited frame) */
+	msg->xid_info[0] = 0x81;	/* XID format identifier */
+	msg->xid_info[1] = 1;	/* LLC types/classes: Type 1 LLC */
+	msg->xid_info[2] = 0;	/* XID sender's receive window size (RW) */
+
+	skb->dev = dev;
+	skb->protocol = eth_type_trans(skb, dev);
+	memset(skb->cb, 0, sizeof(skb->cb));
+	netif_rx_ni(skb);
+}
+EXPORT_SYMBOL(cfg80211_send_layer2_update);
diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
index a97ae04f5d2a..1d03915bf822 100644
--- a/scripts/recordmcount.c
+++ b/scripts/recordmcount.c
@@ -52,6 +52,10 @@
 #define R_AARCH64_ABS64	257
 #endif
 
+#define R_ARM_PC24		1
+#define R_ARM_THM_CALL		10
+#define R_ARM_CALL		28
+
 static int fd_map;	/* File descriptor for file being modified. */
 static int mmap_failed; /* Boolean flag. */
 static char gpfx;	/* prefix for global symbol name (sometimes '_') */
@@ -355,6 +359,18 @@ is_mcounted_section_name(char const *const txtname)
 #define RECORD_MCOUNT_64
 #include "recordmcount.h"
 
+static int arm_is_fake_mcount(Elf32_Rel const *rp)
+{
+	switch (ELF32_R_TYPE(w(rp->r_info))) {
+	case R_ARM_THM_CALL:
+	case R_ARM_CALL:
+	case R_ARM_PC24:
+		return 0;
+	}
+
+	return 1;
+}
+
 /* 64-bit EM_MIPS has weird ELF64_Rela.r_info.
  * http://techpubs.sgi.com/library/manuals/4000/007-4658-001/pdf/007-4658-001.pdf
  * We interpret Table 29 Relocation Operation (Elf64_Rel, Elf64_Rela) [p.40]
@@ -443,6 +459,7 @@ do_file(char const *const fname)
 		break;
 	case EM_ARM:	 reltype = R_ARM_ABS32;
 			 altmcount = "__gnu_mcount_nc";
+			 is_fake_mcount32 = arm_is_fake_mcount;
 			 break;
 	case EM_AARCH64:
 			 reltype = R_AARCH64_ABS64; gpfx = '_'; break;
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index a0ee065a9f8c..4195e3c8b641 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -459,6 +459,10 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
 	while (runtime->boundary * 2 <= LONG_MAX - runtime->buffer_size)
 		runtime->boundary *= 2;
 
+	/* clear the buffer for avoiding possible kernel info leaks */
+	if (runtime->dma_area)
+		memset(runtime->dma_area, 0, runtime->dma_bytes);
+
 	snd_pcm_timer_resolution_change(substream);
 	snd_pcm_set_state(substream, SNDRV_PCM_STATE_SETUP);
 
diff --git a/sound/core/seq/seq_timer.c b/sound/core/seq/seq_timer.c
index 0e6210000fa9..f6fa4b55d33d 100644
--- a/sound/core/seq/seq_timer.c
+++ b/sound/core/seq/seq_timer.c
@@ -484,15 +484,19 @@ void snd_seq_info_timer_read(struct snd_info_entry *entry,
 		q = queueptr(idx);
 		if (q == NULL)
 			continue;
-		if ((tmr = q->timer) == NULL ||
-		    (ti = tmr->timeri) == NULL) {
-			queuefree(q);
-			continue;
-		}
+		mutex_lock(&q->timer_mutex);
+		tmr = q->timer;
+		if (!tmr)
+			goto unlock;
+		ti = tmr->timeri;
+		if (!ti)
+			goto unlock;
 		snd_iprintf(buffer, "Timer for queue %i : %s\n", q->queue, ti->timer->name);
 		resolution = snd_timer_resolution(ti) * tmr->ticks;
 		snd_iprintf(buffer, "  Period time : %lu.%09lu\n", resolution / 1000000000, resolution % 1000000000);
 		snd_iprintf(buffer, "  Skew : %u / %u\n", tmr->skew, tmr->skew_base);
+unlock:
+		mutex_unlock(&q->timer_mutex);
 		queuefree(q);
  	}
 }
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c
index 554a138efdbf..9e2387efa4ec 100644
--- a/sound/pci/hda/patch_ca0132.c
+++ b/sound/pci/hda/patch_ca0132.c
@@ -1271,13 +1271,14 @@ struct scp_msg {
 
 static void dspio_clear_response_queue(struct hda_codec *codec)
 {
+	unsigned long timeout = jiffies + msecs_to_jiffies(1000);
 	unsigned int dummy = 0;
-	int status = -1;
+	int status;
 
 	/* clear all from the response queue */
 	do {
 		status = dspio_read(codec, &dummy);
-	} while (status == 0);
+	} while (status == 0 && time_before(jiffies, timeout));
 }
 
 static int dspio_get_response_data(struct hda_codec *codec)
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
index 5e7948f3efe9..45f5793465b8 100644
--- a/sound/pci/ice1712/ice1724.c
+++ b/sound/pci/ice1712/ice1724.c
@@ -663,6 +663,7 @@ static int snd_vt1724_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate,
 	unsigned long flags;
 	unsigned char mclk_change;
 	unsigned int i, old_rate;
+	bool call_set_rate = false;
 
 	if (rate > ice->hw_rates->list[ice->hw_rates->count - 1])
 		return -EINVAL;
@@ -686,7 +687,7 @@ static int snd_vt1724_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate,
 		 * setting clock rate for internal clock mode */
 		old_rate = ice->get_rate(ice);
 		if (force || (old_rate != rate))
-			ice->set_rate(ice, rate);
+			call_set_rate = true;
 		else if (rate == ice->cur_rate) {
 			spin_unlock_irqrestore(&ice->reg_lock, flags);
 			return 0;
@@ -694,12 +695,14 @@ static int snd_vt1724_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate,
 	}
 
 	ice->cur_rate = rate;
+	spin_unlock_irqrestore(&ice->reg_lock, flags);
+
+	if (call_set_rate)
+		ice->set_rate(ice, rate);
 
 	/* setting master clock */
 	mclk_change = ice->set_mclk(ice, rate);
 
-	spin_unlock_irqrestore(&ice->reg_lock, flags);
-
 	if (mclk_change && ice->gpio.i2s_mclk_changed)
 		ice->gpio.i2s_mclk_changed(ice);
 	if (ice->gpio.set_pro_rate)
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index 0caaa8fa4231..af54f736c01d 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -2795,7 +2795,7 @@ static int fll_factors(struct _fll_div *fll_div, unsigned int Fref,
 
 	if (target % Fref == 0) {
 		fll_div->theta = 0;
-		fll_div->lambda = 0;
+		fll_div->lambda = 1;
 	} else {
 		gcd_fll = gcd(target, fratio * Fref);
 
@@ -2865,7 +2865,7 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
 		return -EINVAL;
 	}
 
-	if (fll_div.theta || fll_div.lambda)
+	if (fll_div.theta)
 		fll1 |= WM8962_FLL_FRAC;
 
 	/* Stop the FLL while we reconfigure */
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 63d5303cc868..cb47c924c92a 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -324,6 +324,7 @@ static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs,
 	struct usb_host_interface *alts;
 	struct usb_interface *iface;
 	unsigned int ep;
+	unsigned int ifnum;
 
 	/* Implicit feedback sync EPs consumers are always playback EPs */
 	if (subs->direction != SNDRV_PCM_STREAM_PLAYBACK)
@@ -333,34 +334,23 @@ static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs,
 	case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */
 	case USB_ID(0x0763, 0x2031): /* M-Audio Fast Track C600 */
 		ep = 0x81;
-		iface = usb_ifnum_to_if(dev, 3);
-
-		if (!iface || iface->num_altsetting == 0)
-			return -EINVAL;
-
-		alts = &iface->altsetting[1];
-		goto add_sync_ep;
-		break;
+		ifnum = 3;
+		goto add_sync_ep_from_ifnum;
 	case USB_ID(0x0763, 0x2080): /* M-Audio FastTrack Ultra */
 	case USB_ID(0x0763, 0x2081):
 		ep = 0x81;
-		iface = usb_ifnum_to_if(dev, 2);
-
-		if (!iface || iface->num_altsetting == 0)
-			return -EINVAL;
-
-		alts = &iface->altsetting[1];
-		goto add_sync_ep;
-	case USB_ID(0x1397, 0x0002):
+		ifnum = 2;
+		goto add_sync_ep_from_ifnum;
+	case USB_ID(0x2466, 0x8003): /* Fractal Audio Axe-Fx II */
+		ep = 0x86;
+		ifnum = 2;
+		goto add_sync_ep_from_ifnum;
+	case USB_ID(0x1397, 0x0002): /* Behringer UFX1204 */
 		ep = 0x81;
-		iface = usb_ifnum_to_if(dev, 1);
-
-		if (!iface || iface->num_altsetting == 0)
-			return -EINVAL;
-
-		alts = &iface->altsetting[1];
-		goto add_sync_ep;
+		ifnum = 1;
+		goto add_sync_ep_from_ifnum;
 	}
+
 	if (attr == USB_ENDPOINT_SYNC_ASYNC &&
 	    altsd->bInterfaceClass == USB_CLASS_VENDOR_SPEC &&
 	    altsd->bInterfaceProtocol == 2 &&
@@ -375,6 +365,14 @@ static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs,
 	/* No quirk */
 	return 0;
 
+add_sync_ep_from_ifnum:
+	iface = usb_ifnum_to_if(dev, ifnum);
+
+	if (!iface || iface->num_altsetting < 2)
+		return -EINVAL;
+
+	alts = &iface->altsetting[1];
+
 add_sync_ep:
 	subs->sync_endpoint = snd_usb_add_endpoint(subs->stream->chip,
 						   alts, ep, !subs->direction,

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply related	[relevance 1%]

* Re: [PATCH 3.16 000/247] 3.16.83-rc2 review
  2020-04-24 17:48  6% ` Guenter Roeck
@ 2020-04-24 17:54  9%   ` Ben Hutchings
  0 siblings, 0 replies; 200+ results
From: Ben Hutchings @ 2020-04-24 17:54 UTC (permalink / raw)
  To: Guenter Roeck, linux-kernel, stable; +Cc: torvalds, akpm, Denis Kirjanov

[-- Attachment #1: Type: text/plain, Size: 739 bytes --]

On Fri, 2020-04-24 at 10:48 -0700, Guenter Roeck wrote:
> On 4/24/20 8:47 AM, Ben Hutchings wrote:
> > This is the start of the stable review cycle for the 3.16.83 release.
> > There are 247 patches in this series, which will be posted as responses
> > to this one.  If anyone has any issues with these being applied, please
> > let me know.
> > 
> > Responses should be made by Tue Apr 28 18:00:00 UTC 2020.
> > Anything received after that time might be too late.
> > 
> 
> For v3.16.82-247-gffbdbb4fe113:
> 
> Build results:
> 	total: 135 pass: 135 fail: 0
> Qemu test results:
> 	total: 233 pass: 233 fail: 0

Great, thanks for testing again.

Ben.

-- 
Ben Hutchings
Knowledge is power.  France is bacon.



[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[relevance 9%]

* Re: [PATCH 3.16 000/247] 3.16.83-rc2 review
  @ 2020-04-24 17:48  6% ` Guenter Roeck
  2020-04-24 17:54  9%   ` Ben Hutchings
  0 siblings, 1 reply; 200+ results
From: Guenter Roeck @ 2020-04-24 17:48 UTC (permalink / raw)
  To: Ben Hutchings, linux-kernel, stable; +Cc: torvalds, akpm, Denis Kirjanov

On 4/24/20 8:47 AM, Ben Hutchings wrote:
> This is the start of the stable review cycle for the 3.16.83 release.
> There are 247 patches in this series, which will be posted as responses
> to this one.  If anyone has any issues with these being applied, please
> let me know.
> 
> Responses should be made by Tue Apr 28 18:00:00 UTC 2020.
> Anything received after that time might be too late.
> 

For v3.16.82-247-gffbdbb4fe113:

Build results:
	total: 135 pass: 135 fail: 0
Qemu test results:
	total: 233 pass: 233 fail: 0

Guenter

^ permalink raw reply	[relevance 6%]

* Re: [PATCH 3.16 208/245] namei: allow restricted O_CREAT of FIFOs and regular files
  @ 2020-04-24 17:38  6%       ` Solar Designer
  0 siblings, 0 replies; 200+ results
From: Solar Designer @ 2020-04-24 17:38 UTC (permalink / raw)
  To: Ben Hutchings
  Cc: linux-kernel, stable, akpm, Denis Kirjanov, Dan Carpenter,
	Al Viro, Kees Cook, Salvatore Mesoraca, Linus Torvalds

On Fri, Apr 24, 2020 at 04:13:22PM +0100, Ben Hutchings wrote:
> On Fri, 2020-04-24 at 15:52 +0200, Solar Designer wrote:
> > On Fri, Apr 24, 2020 at 12:07:15AM +0100, Ben Hutchings wrote:
> > > 3.16.83-rc1 review patch.  If anyone has any objections, please let me know.
> > 
> > I do.  This patch is currently known-buggy, see this thread:
> > 
> > https://www.openwall.com/lists/oss-security/2020/01/28/2
> > 
> > It is (partially) fixed with these newer commits in 5.5 and 5.5.2:
> > 
> > commit d0cb50185ae942b03c4327be322055d622dc79f6
> > Author: Al Viro <viro@zeniv.linux.org.uk>
> > Date:   Sun Jan 26 09:29:34 2020 -0500
> > 
> >     do_last(): fetch directory ->i_mode and ->i_uid before it's too late
> >     
> >     may_create_in_sticky() call is done when we already have dropped the
> >     reference to dir.
> >     
> >     Fixes: 30aba6656f61e (namei: allow restricted O_CREAT of FIFOs and regular files)
> >     Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
> > 
> > commit d76341d93dedbcf6ed5a08dfc8bce82d3e9a772b
> > Author: Al Viro <viro@zeniv.linux.org.uk>
> > Date:   Sat Feb 1 16:26:45 2020 +0000
> > 
> >     vfs: fix do_last() regression
> >     
> >     commit 6404674acd596de41fd3ad5f267b4525494a891a upstream.
> [...]
> > At least inclusion of the above fixes is mandatory for any backports.
> 
> I know, and those are the next 2 patches in the series.

Ah, then no objections from me.

> > Also, I think no one has fixed the logic of may_create_in_sticky() so
> > that it wouldn't unintentionally apply the "protection" when the file
> > is neither a FIFO nor a regular file (something I found and mentioned in
> > the oss-security posting above).
> [...]
> > I think the implementation of may_create_in_sticky() should be rewritten
> > such that it'd directly correspond to the textual description in the
> > comment above.  As we've seen, trying to write the code "more optimally"
> > resulted in its logic actually being different from the description.
> > 
> > Meanwhile, I think backporting known-so-buggy code is a bad idea.
> 
> I can see that it's not quite right, but does it matter in practice? 
> Directories and symlinks are handled separately; sockets can't be
> opened anyway; block and character devices wonn't normally appear in a
> sticky directory.

Clearly, it doesn't matter all that much in practice - I'm not aware of
anyone having complained about it causing issues on their system.

I think it primarily mattered as an attack vector on the issue fixed
with Al's commits above.

I think we should nevertheless fix the code to match its intent and the
comment, but meanwhile this isn't a blocker for the backport.

Alexander

^ permalink raw reply	[relevance 6%]

Results 1-200 of ~9000   | reverse | options above
-- pct% links below jump to the message on this page, permalinks otherwise --
2020-04-23 23:03     [PATCH 3.16 000/245] 3.16.83-rc1 review Ben Hutchings
2020-04-23 23:07     ` [PATCH 3.16 208/245] namei: allow restricted O_CREAT of FIFOs and regular files Ben Hutchings
2020-04-24 13:52       ` Solar Designer
2020-04-24 15:13         ` Ben Hutchings
2020-04-24 17:38  6%       ` Solar Designer
2020-04-24 15:47     [PATCH 3.16 000/247] 3.16.83-rc2 review Ben Hutchings
2020-04-24 17:48  6% ` Guenter Roeck
2020-04-24 17:54  9%   ` Ben Hutchings
2020-04-28 19:17  1% Linux 3.16.83 Ben Hutchings
2020-04-30 22:20  4% [PATCH] doc:it_IT: align Italian translation Federico Vaga
2020-05-20 14:13  6% [PATCH 3.16 00/99] 3.16.84-rc1 review Ben Hutchings
2020-05-20 14:13  9% ` [PATCH 3.16 01/99] fs/namespace.c: fix mountpoint reference counter race Ben Hutchings
2020-05-20 14:13 12% ` [PATCH 3.16 02/99] propagate_one(): mnt_set_mountpoint() needs mount_lock Ben Hutchings
2020-05-20 14:13 10% ` [PATCH 3.16 03/99] spi: spi-dw: Add lock protect dw_spi rx/tx to prevent concurrent calls Ben Hutchings
2020-05-20 14:13  9% ` [PATCH 3.16 04/99] padata: Remove unused but set variables Ben Hutchings
2020-05-20 14:13  8% ` [PATCH 3.16 05/99] padata: avoid race in reordering Ben Hutchings
2020-05-20 14:13  8% ` [PATCH 3.16 06/99] padata: get_next is never NULL Ben Hutchings
2020-05-20 14:13  8% ` [PATCH 3.16 07/99] padata: ensure the reorder timer callback runs on the correct CPU Ben Hutchings
2020-05-20 14:13  8% ` [PATCH 3.16 08/99] padata: ensure padata_do_serial() " Ben Hutchings
2020-05-20 14:13  8% ` [PATCH 3.16 09/99] padata: Replace delayed timer with immediate workqueue in padata_reorder Ben Hutchings
2020-05-20 14:13  8% ` [PATCH 3.16 10/99] padata: initialize pd->cpu with effective cpumask Ben Hutchings
2020-05-20 14:13  8% ` [PATCH 3.16 11/99] padata: Remove broken queue flushing Ben Hutchings
2020-05-20 14:13  9% ` [PATCH 3.16 12/99] padata: purge get_cpu and reorder_via_wq from padata_do_serial Ben Hutchings
2020-05-20 14:13 13% ` [PATCH 3.16 13/99] crypto: pcrypt - Fix user-after-free on module unload Ben Hutchings
2020-05-20 14:13  9% ` [PATCH 3.16 14/99] crypto: pcrypt - Do not clear MAY_SLEEP flag in original request Ben Hutchings
2020-05-20 14:13  8% ` [PATCH 3.16 15/99] padata: always acquire cpu_hotplug_lock before pinst->lock Ben Hutchings
2020-05-20 14:13  9% ` [PATCH 3.16 16/99] crypto: af_alg - Use bh_lock_sock in sk_destruct Ben Hutchings
2020-05-20 14:13  9% ` [PATCH 3.16 17/99] crypto: api - Check spawn->alg under lock in crypto_drop_spawn Ben Hutchings
2020-05-20 14:13  9% ` [PATCH 3.16 18/99] crypto: api - Fix race condition in crypto_spawn_alg Ben Hutchings
2020-05-20 14:13  8% ` [PATCH 3.16 19/99] mmc: spi: Toggle SPI polarity, do not hardcode it Ben Hutchings
2020-05-20 14:13  9% ` [PATCH 3.16 20/99] reiserfs: Fix memory leak of journal device string Ben Hutchings
2020-05-20 14:13  9% ` [PATCH 3.16 21/99] reiserfs: Fix spurious unlock in reiserfs_fill_super() error handling Ben Hutchings
2020-05-20 14:13  9% ` [PATCH 3.16 22/99] ath9k: fix storage endpoint lookup Ben Hutchings
2020-05-20 14:13 12% ` [PATCH 3.16 23/99] rsi: fix use-after-free on failed probe and unbind Ben Hutchings
2020-05-20 14:13 13% ` [PATCH 3.16 24/99] brcmfmac: Fix use after free in brcmf_sdio_readframes() Ben Hutchings
2020-05-20 14:13 12% ` [PATCH 3.16 25/99] brcmfmac: abort and release host after error Ben Hutchings
2020-05-20 14:13 12% ` [PATCH 3.16 26/99] brcmfmac: fix interface sanity check Ben Hutchings
2020-05-20 14:13 13% ` [PATCH 3.16 27/99] orinoco_usb: " Ben Hutchings
2020-05-20 14:13  9% ` [PATCH 3.16 28/99] rsi_91x_usb: " Ben Hutchings
2020-05-20 14:13 13% ` [PATCH 3.16 29/99] zd1211rw: fix storage endpoint lookup Ben Hutchings
2020-05-20 14:13  9% ` [PATCH 3.16 30/99] brcmfmac: Fix memory leak in brcmf_usbdev_qinit Ben Hutchings
2020-05-20 14:13  9% ` [PATCH 3.16 31/99] crypto: picoxcell - adjust the position of tasklet_init and fix missed tasklet_kill Ben Hutchings
2020-05-20 14:14  9% ` [PATCH 3.16 32/99] scsi: qla2xxx: Fix mtcp dump collection failure Ben Hutchings
2020-05-20 14:14  9% ` [PATCH 3.16 33/99] rtc: hym8563: Return -EINVAL if the time is known to be invalid Ben Hutchings
2020-05-20 14:14 11% ` [PATCH 3.16 34/99] gianfar: Fix TX timestamping with a stacked DSA driver Ben Hutchings
2020-05-20 14:14 12% ` [PATCH 3.16 35/99] pxa168fb: Fix the function used to release some memory in an error handling path Ben Hutchings
2020-05-21 14:09  9%   ` Marion & Christophe JAILLET
2020-05-21 14:31  3%     ` Marion & Christophe JAILLET
2020-05-21 20:28  9%       ` Ben Hutchings
2020-05-20 14:14  9% ` [PATCH 3.16 36/99] ALSA: sh: Fix compile warning wrt const Ben Hutchings
2020-05-20 14:14  9% ` [PATCH 3.16 37/99] clk: tegra: Mark fuse clock as critical Ben Hutchings
2020-05-20 15:51 13%   ` Ben Hutchings
2020-05-20 14:14  8% ` [PATCH 3.16 38/99] ARM: tegra: Enable PLLP bypass during Tegra124 LP1 Ben Hutchings
2020-05-20 14:14  9% ` [PATCH 3.16 39/99] media: iguanair: add sanity checks Ben Hutchings
2020-05-20 14:14  9% ` [PATCH 3.16 40/99] media: iguanair: fix endpoint sanity check Ben Hutchings
2020-05-20 14:14 11% ` [PATCH 3.16 41/99] ARM: dts: at91: sama5d3: fix maximum peripheral clock rates Ben Hutchings
2020-05-20 14:14  9% ` [PATCH 3.16 42/99] ARM: dts: at91: sama5d3: define clock rate range for tcb1 Ben Hutchings
2020-05-20 14:14  7% ` [PATCH 3.16 43/99] efi: Use early_mem*() instead of early_io*() Ben Hutchings
2020-05-20 15:53 10%   ` Ben Hutchings
2020-05-20 14:14 11% ` [PATCH 3.16 44/99] efi/x86: Map the entire EFI vendor string before copying it Ben Hutchings
2020-05-20 14:14  7% ` [PATCH 3.16 45/99] PCI: Don't disable bridge BARs when assigning bus resources Ben Hutchings
2020-05-20 14:14 13% ` [PATCH 3.16 46/99] power: supply: sbs-battery: Fix a signedness bug in sbs_get_battery_capacity() Ben Hutchings
2020-05-20 14:14  7% ` [PATCH 3.16 47/99] dm space map common: fix to ensure new block isn't already in use Ben Hutchings
2020-05-20 14:14  9% ` [PATCH 3.16 48/99] usb: dwc3: turn off VBUS when leaving host mode Ben Hutchings
2020-05-20 14:14 11% ` [PATCH 3.16 49/99] usb: gadget: f_ncm: Use atomic_t to track in-flight request Ben Hutchings
2020-05-20 14:14 11% ` [PATCH 3.16 50/99] usb: gadget: f_ecm: " Ben Hutchings
2020-05-20 14:14  9% ` [PATCH 3.16 51/99] staging: wlan-ng: ensure error return is actually returned Ben Hutchings
2020-05-20 14:14  9% ` [PATCH 3.16 52/99] nfs: NFS_SWAP should depend on SWAP Ben Hutchings
2020-05-20 14:14 12% ` [PATCH 3.16 53/99] ubifs: Fix deadlock in concurrent bulk-read and writepage Ben Hutchings
2020-05-20 14:14  8% ` [PATCH 3.16 54/99] x86/cpu: Update cached HLE state on write to TSX_CTRL_CPUID_CLEAR Ben Hutchings
2020-05-20 14:14  9% ` [PATCH 3.16 55/99] jbd2: clear JBD2_ABORT flag before journal_reset to update log tail info when load journal Ben Hutchings
2020-05-20 14:14 10% ` [PATCH 3.16 56/99] KVM: arm64: Only sign-extend MMIO up to register width Ben Hutchings
2020-05-20 14:14  8% ` [PATCH 3.16 57/99] sparc32: fix struct ipc64_perm type definition Ben Hutchings
2020-05-20 14:14 10% ` [PATCH 3.16 58/99] KVM: x86: Don't let userspace set host-reserved cr4 bits Ben Hutchings
2020-05-20 14:14 13% ` [PATCH 3.16 59/99] KVM: nVMX: vmread should not set rflags to specify success in case of #PF Ben Hutchings
2020-05-20 14:14  9% ` [PATCH 3.16 60/99] x86: kvm: avoid unused variable warning Ben Hutchings
2020-05-20 14:14 12% ` [PATCH 3.16 61/99] KVM: x86/mmu: Apply max PA check for MMIO sptes to 32-bit KVM Ben Hutchings
2020-05-20 14:14  9% ` [PATCH 3.16 62/99] USB: serial: ir-usb: add missing endpoint sanity check Ben Hutchings
2020-05-20 14:14  8% ` [PATCH 3.16 63/99] USB: serial: ir-usb: fix link-speed handling Ben Hutchings
2020-05-20 14:14  7% ` [PATCH 3.16 64/99] USB: serial: ir-usb: fix IrLAP framing Ben Hutchings
2020-05-20 14:14  7% ` [PATCH 3.16 65/99] media: uvcvideo: Avoid cyclic entity chains due to malformed USB descriptors Ben Hutchings
2020-05-20 14:14  9% ` [PATCH 3.16 66/99] KVM: PPC: Book3S HV: Uninit vCPU if vcore creation fails Ben Hutchings
2020-05-20 14:14  9% ` [PATCH 3.16 67/99] KVM: PPC: Book3S PR: Free shared page if mmu initialization fails Ben Hutchings
2020-05-20 14:14 13% ` [PATCH 3.16 68/99] KVM: x86: Free wbinvd_dirty_mask if vCPU creation fails Ben Hutchings
2020-05-20 14:14  8% ` [PATCH 3.16 69/99] tracing: Fix very unlikely race of registering two stat tracers Ben Hutchings
2020-05-20 14:14 12% ` [PATCH 3.16 70/99] tracing: Fix tracing_stat return values in error handling paths Ben Hutchings
2020-05-20 14:14  9% ` [PATCH 3.16 71/99] jbd2: switch to use jbd2_journal_abort() when failed to submit the commit record Ben Hutchings
2020-05-20 14:14  8% ` [PATCH 3.16 72/99] ext4, jbd2: ensure panic when aborting with zero errno Ben Hutchings
2020-05-20 14:14 12% ` [PATCH 3.16 73/99] iwlegacy: ensure loop counter addr does not wrap and cause an infinite loop Ben Hutchings
2020-05-20 14:14  9% ` [PATCH 3.16 74/99] CIFS: Fix task struct use-after-free on reconnect Ben Hutchings
2020-05-20 14:14 11% ` [PATCH 3.16 75/99] net_sched: ematch: reject invalid TCF_EM_SIMPLE Ben Hutchings
2020-05-20 14:14 12% ` [PATCH 3.16 76/99] KVM: x86: Protect x86_decode_insn from Spectre-v1/L1TF attacks Ben Hutchings
2020-05-20 14:14 12% ` [PATCH 3.16 77/99] KVM: x86: Refactor picdev_write() to prevent " Ben Hutchings
2020-05-20 14:14 12% ` [PATCH 3.16 78/99] KVM: x86: Protect ioapic_read_indirect() from " Ben Hutchings
2020-05-20 14:14 12% ` [PATCH 3.16 79/99] KVM: x86: Protect ioapic_write_indirect() " Ben Hutchings
2020-05-20 14:14 12% ` [PATCH 3.16 80/99] KVM: x86: Protect kvm_lapic_reg_write() " Ben Hutchings
2020-05-20 14:14 12% ` [PATCH 3.16 81/99] kvm: x86: use macros to compute bank MSRs Ben Hutchings
2020-05-20 14:14 12% ` [PATCH 3.16 82/99] KVM: x86: Protect MSR-based index computations from Spectre-v1/L1TF attacks in x86.c Ben Hutchings
2020-05-20 14:14  9% ` [PATCH 3.16 83/99] KVM: x86: Protect DR-based index computations from Spectre-v1/L1TF attacks Ben Hutchings
2020-05-20 14:14 11% ` [PATCH 3.16 84/99] KVM: Check for a bad hva before dropping into the ghc slow path Ben Hutchings
2020-05-20 14:14 11% ` [PATCH 3.16 85/99] of: Add OF_DMA_DEFAULT_COHERENT & select it on powerpc Ben Hutchings
2020-05-20 14:14  8% ` [PATCH 3.16 86/99] Btrfs: fix race between adding and putting tree mod seq elements and nodes Ben Hutchings
2020-05-20 14:14  8% ` [PATCH 3.16 87/99] mm/mempolicy.c: fix out of bounds write in mpol_parse_str() Ben Hutchings
2020-05-20 14:14 11% ` [PATCH 3.16 88/99] media/v4l2-core: set pages dirty upon releasing DMA buffers Ben Hutchings
2020-05-20 14:14  9% ` [PATCH 3.16 89/99] tcp: clear tp->total_retrans in tcp_disconnect() Ben Hutchings
2020-05-20 14:14  9% ` [PATCH 3.16 90/99] ALSA: dummy: Fix PCM format loop in proc output Ben Hutchings
2020-05-20 14:14  8% ` [PATCH 3.16 91/99] clocksource: Prevent double add_timer_on() for watchdog_timer Ben Hutchings
2020-05-20 14:15  7% ` [PATCH 3.16 92/99] cls_rsvp: fix rsvp_policy Ben Hutchings
2020-05-20 14:15  9% ` [PATCH 3.16 93/99] kconfig: fix broken dependency in randconfig-generated .config Ben Hutchings
2020-05-20 14:15  8% ` [PATCH 3.16 94/99] nfs: use kmap/kunmap directly Ben Hutchings
2020-05-20 14:15  9% ` [PATCH 3.16 95/99] NFS: Fix memory leaks and corruption in readdir Ben Hutchings
2020-05-20 14:15 11% ` [PATCH 3.16 96/99] NFS: Directory page cache pages need to be locked when read Ben Hutchings
2020-05-20 14:15  9% ` [PATCH 3.16 97/99] cifs: fail i/o on soft mounts if sessionsetup errors out Ben Hutchings
2020-05-20 14:15  9% ` [PATCH 3.16 98/99] bonding/alb: properly access headers in bond_alb_xmit() Ben Hutchings
2020-05-20 14:15 12% ` [PATCH 3.16 99/99] sunrpc: expiry_time should be seconds not timeval Ben Hutchings
2020-05-20 21:23  6% ` [PATCH 3.16 00/99] 3.16.84-rc1 review Guenter Roeck
2020-05-21  2:47  3%   ` Chen-Yu Tsai
2020-05-21  7:40  3%     ` Guenter Roeck
2020-05-21 20:22 13%       ` Ben Hutchings
2020-05-21 20:20  9%   ` Ben Hutchings
2020-05-21 22:37  6%     ` Guenter Roeck
2020-05-22  0:00  9%       ` Ben Hutchings
2020-05-23 12:15  1% Linux 3.16.84 Ben Hutchings
2020-06-09 18:03  9% [PATCH 3.16 00/61] 3.16.85-rc1 review Ben Hutchings
2020-06-09 18:03  9% ` [PATCH 3.16 01/61] slcan: Fix memory leak in error path Ben Hutchings
2020-06-09 18:03 11% ` [PATCH 3.16 02/61] can: slcan: Fix use-after-free Read in slcan_open Ben Hutchings
2020-06-09 18:03 13% ` [PATCH 3.16 03/61] slcan: not call free_netdev before rtnl_unlock " Ben Hutchings
2020-06-09 18:03  9% ` [PATCH 3.16 04/61] slip: Fix memory leak in slip_open error path Ben Hutchings
2020-06-09 18:03 11% ` [PATCH 3.16 05/61] slip: Fix use-after-free Read in slip_open Ben Hutchings
2020-06-09 18:03 13% ` [PATCH 3.16 06/61] slip: not call free_netdev before rtnl_unlock " Ben Hutchings
2020-06-09 18:03 12% ` [PATCH 3.16 07/61] net-sysfs: Fix reference count leak in rx|netdev_queue_add_kobject Ben Hutchings
2020-06-09 18:03  9% ` [PATCH 3.16 08/61] net-sysfs: fix netdev_queue_add_kobject() breakage Ben Hutchings
2020-06-09 18:04 12% ` [PATCH 3.16 09/61] net-sysfs: Call dev_hold always in netdev_queue_add_kobject Ben Hutchings
2020-06-09 18:04 12% ` [PATCH 3.16 10/61] net-sysfs: Call dev_hold always in rx_queue_add_kobject Ben Hutchings
2020-06-09 18:04  9% ` [PATCH 3.16 11/61] selinux: cleanup error reporting in selinux_nlmsg_perm() Ben Hutchings
2020-06-09 18:04  9% ` [PATCH 3.16 12/61] selinux: convert WARN_ONCE() to printk() " Ben Hutchings
2020-06-09 18:04  9% ` [PATCH 3.16 13/61] selinux: Print 'sclass' as string when unrecognized netlink message occurs Ben Hutchings
2020-06-09 18:04  9% ` [PATCH 3.16 14/61] selinux: rate-limit netlink message warnings in selinux_nlmsg_perm() Ben Hutchings
2020-06-09 18:04 11% ` [PATCH 3.16 15/61] selinux: properly handle multiple messages in selinux_netlink_send() Ben Hutchings
2020-06-09 18:04  8% ` [PATCH 3.16 16/61] drivers: usb: core: Don't disable irqs in usb_sg_wait() during URB submit Ben Hutchings
2020-06-09 18:04  9% ` [PATCH 3.16 17/61] drivers: usb: core: Minimize irq disabling in usb_sg_cancel() Ben Hutchings
2020-06-09 18:04  7% ` [PATCH 3.16 18/61] USB: core: Fix free-while-in-use bug in the USB S-Glibrary Ben Hutchings
2020-06-09 18:04  9% ` [PATCH 3.16 19/61] scsi: mptfusion: Add bounds check in mptctl_hp_targetinfo() Ben Hutchings
2020-06-09 18:04  4% ` [PATCH 3.16 20/61] scsi: mptfusion: Fix double fetch bug in ioctl Ben Hutchings
2020-06-09 18:04 13% ` [PATCH 3.16 21/61] mwifiex: Fix possible buffer overflows in mwifiex_cmd_append_vsie_tlv() Ben Hutchings
2020-06-09 18:04 13% ` [PATCH 3.16 22/61] mwifiex: Fix possible buffer overflows in mwifiex_ret_wmm_get_status() Ben Hutchings
2020-06-09 18:04  3% ` [PATCH 3.16 23/61] sg: O_EXCL and other lock handling Ben Hutchings
2020-06-09 18:04  8% ` [PATCH 3.16 24/61] sg: prevent integer overflow when converting from sectors to bytes Ben Hutchings
2020-06-09 18:04 10% ` [PATCH 3.16 25/61] scsi: sg: Change next_cmd_len handling to mirror upstream Ben Hutchings
2020-06-09 18:04  7% ` [PATCH 3.16 26/61] scsi: sg: protect accesses to 'reserved' page array Ben Hutchings
2020-06-09 18:04  9% ` [PATCH 3.16 27/61] scsi: sg: reset 'res_in_use' after unlinking reserved array Ben Hutchings
2020-06-09 18:04  9% ` [PATCH 3.16 28/61] scsi: sg: protect against races between mmap() and SG_SET_RESERVED_SIZE Ben Hutchings
2020-06-09 18:04  9% ` [PATCH 3.16 29/61] scsi: sg: recheck MMAP_IO request length with lock held Ben Hutchings
2020-06-09 18:04  9% ` [PATCH 3.16 30/61] scsi: sg: remove 'save_scat_len' Ben Hutchings
2020-06-09 18:04  6% ` [PATCH 3.16 31/61] scsi: sg: use standard lists for sg_requests Ben Hutchings
2020-06-09 18:04  9% ` [PATCH 3.16 32/61] scsi: sg: off by one in sg_ioctl() Ben Hutchings
2020-06-09 18:04  8% ` [PATCH 3.16 33/61] scsi: sg: factor out sg_fill_request_table() Ben Hutchings
2020-06-09 18:04  9% ` [PATCH 3.16 34/61] scsi: sg: fixup infoleak when using SG_GET_REQUEST_TABLE Ben Hutchings
2020-06-09 18:04 11% ` [PATCH 3.16 35/61] scsi: sg: Re-fix off by one in sg_fill_request_table() Ben Hutchings
2020-06-09 18:04 10% ` [PATCH 3.16 36/61] scsi: sg: disable SET_FORCE_LOW_DMA Ben Hutchings
2020-06-09 18:04  8% ` [PATCH 3.16 37/61] scsi: sg: check for valid direction before starting the request Ben Hutchings
2020-06-09 18:04  8% ` [PATCH 3.16 38/61] scsi: sg: close race condition in sg_remove_sfp_usercontext() Ben Hutchings
2020-06-09 18:04  9% ` [PATCH 3.16 39/61] scsi: sg: fix SG_DXFER_FROM_DEV transfers Ben Hutchings
2020-06-09 18:04  9% ` [PATCH 3.16 40/61] scsi: sg: fix static checker warning in sg_is_valid_dxfer Ben Hutchings
2020-06-09 18:04 11% ` [PATCH 3.16 41/61] scsi: sg: only check for dxfer_len greater than 256M Ben Hutchings
2020-06-09 18:04  9% ` [PATCH 3.16 42/61] scsi: sg: don't return bogus Sg_requests Ben Hutchings
2020-06-09 18:28  6%   ` Tony Battersby
2020-06-09 19:03 13%     ` Ben Hutchings
2020-06-09 18:04  9% ` [PATCH 3.16 43/61] scsi: sg: fix minor memory leak in error path Ben Hutchings
2020-06-09 18:04  9% ` [PATCH 3.16 44/61] scsi: sg: add sg_remove_request in sg_common_write Ben Hutchings
2020-06-09 18:04  9% ` [PATCH 3.16 45/61] scsi: sg: add sg_remove_request in sg_write Ben Hutchings
2020-06-09 18:04 11% ` [PATCH 3.16 46/61] signal: Extend exec_id to 64bits Ben Hutchings
2020-06-09 18:04  8% ` [PATCH 3.16 47/61] USB: gadget: fix illegal array access in binding with UDC Ben Hutchings
2020-06-09 18:04 13% ` [PATCH 3.16 48/61] ext4: Make checks for metadata_csum feature safer Ben Hutchings
2020-06-09 18:04 11% ` [PATCH 3.16 49/61] ext4: protect journal inode's blocks using block_validity Ben Hutchings
2020-06-09 18:04  9% ` [PATCH 3.16 50/61] ext4: unsigned int compared against zero Ben Hutchings
2020-06-09 18:04 12% ` [PATCH 3.16 51/61] ext4: fix block validity checks for journal inodes using indirect blocks Ben Hutchings
2020-06-09 18:04 12% ` [PATCH 3.16 52/61] ext4: don't perform block validity checks on the journal inode Ben Hutchings
2020-06-09 18:04  9% ` [PATCH 3.16 53/61] ext4: add cond_resched() to ext4_protect_reserved_inode Ben Hutchings
2020-06-09 18:04  5% ` [PATCH 3.16 54/61] x86/cpu: Rename cpu_data.x86_mask to cpu_data.x86_stepping Ben Hutchings
2020-06-09 18:04  7% ` [PATCH 3.16 55/61] x86/cpu: Add a steppings field to struct x86_cpu_id Ben Hutchings
2020-06-09 18:04  8% ` [PATCH 3.16 56/61] x86/cpu: Add 'table' argument to cpu_matches() Ben Hutchings
2020-06-09 18:04  7% ` [PATCH 3.16 57/61] x86/speculation: Add Special Register Buffer Data Sampling (SRBDS) mitigation Ben Hutchings
2020-06-09 18:04  6% ` [PATCH 3.16 58/61] x86/speculation: Add SRBDS vulnerability and mitigation documentation Ben Hutchings
2020-06-09 18:04  9% ` [PATCH 3.16 59/61] x86/speculation: Add Ivy Bridge to affected list Ben Hutchings
2020-06-09 18:04 11% ` [PATCH 3.16 60/61] random: always use batched entropy for get_random_u{32,64} Ben Hutchings
2020-06-09 18:04 12% ` [PATCH 3.16 61/61] fs/binfmt_elf.c: allocate initialized memory in fill_thread_core_info() Ben Hutchings
2020-06-10 19:08  6% ` [PATCH 3.16 00/61] 3.16.85-rc1 review Guenter Roeck
2020-06-10 21:25  9%   ` Ben Hutchings
2020-06-11 18:35  1% Linux 3.16.85 Ben Hutchings
2021-07-03 14:31     [PATCH v3 1/4] docs: add traditional Chinese translation for kernel Documentation Hu Haowen
2021-07-03 14:31  1% ` [PATCH v3 2/4] docs/zh_TW: add translations for zh_TW/process Hu Haowen
2021-07-21 14:25     [PATCH v4 1/2] docs: add traditional Chinese translation for kernel Documentation Hu Haowen
2021-07-21 14:25  1% ` [PATCH v4 2/2] docs/zh_TW: add translations for zh_TW/process Hu Haowen
2021-07-25 14:14     ` [PATCH v5 1/2] docs: add traditional Chinese translation for kernel Documentation Hu Haowen
2021-07-25 14:14  1%   ` [PATCH v5 2/2] docs/zh_TW: add translations for zh_TW/process Hu Haowen
2021-07-27 16:14     [PATCH v6 1/3] docs: add traditional Chinese translation for kernel Documentation Hu Haowen
2021-07-27 16:15  1% ` [PATCH v6 2/3] docs/zh_TW: add translations for zh_TW/process Hu Haowen
2021-07-29 15:56     [PATCH v7 1/3] docs: add traditional Chinese translation for kernel Documentation Hu Haowen
2021-07-29 15:56  1% ` [PATCH v7 2/3] docs/zh_TW: add translations for zh_TW/process Hu Haowen
2022-10-13 18:34 15% [PATCH] Documentation: process: update the list of current LTS Nick Desaulniers
2022-10-14  7:08  0% ` Greg Kroah-Hartman
2022-10-14 16:46     Greg Kroah-Hartman
2022-10-14 17:10 13% ` [PATCH v2] Documentation: process: replace outdated LTS table w/ link Nick Desaulniers
2022-10-14 17:13  0%   ` Tyler Hicks
2022-10-15  2:06  0%   ` Bagas Sanjaya
2022-10-18  0:04  0%     ` Nick Desaulniers
2022-12-30 17:25  4% [PATCH] doc:it_IT: align Italian documentation Federico Vaga
2022-12-30 17:31  4% [PATCH V2] " Federico Vaga
2022-12-31 13:01  4% [PATCH V3] " Federico Vaga
2022-12-31 13:08  4% [PATCH V4] " Federico Vaga

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).